mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-08-01 02:36:23 -04:00
Redesigned history browser of group chat.
New chat style for history browser. There's more to come. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3443 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
b067ab5560
commit
1f8017d06a
9 changed files with 337 additions and 102 deletions
|
@ -207,6 +207,8 @@ HEADERS += rshare.h \
|
||||||
gui/im_history/IMHistoryKeeper.h \
|
gui/im_history/IMHistoryKeeper.h \
|
||||||
gui/im_history/IMHistoryReader.h \
|
gui/im_history/IMHistoryReader.h \
|
||||||
gui/im_history/IMHistoryItem.h \
|
gui/im_history/IMHistoryItem.h \
|
||||||
|
gui/im_history/IMHistoryItemDelegate.h \
|
||||||
|
gui/im_history/IMHistoryItemPainter.h \
|
||||||
gui/im_history/IMHistoryWriter.h \
|
gui/im_history/IMHistoryWriter.h \
|
||||||
lang/languagesupport.h \
|
lang/languagesupport.h \
|
||||||
util/stringutil.h \
|
util/stringutil.h \
|
||||||
|
@ -421,6 +423,8 @@ SOURCES += main.cpp \
|
||||||
gui/im_history/IMHistoryKeeper.cpp \
|
gui/im_history/IMHistoryKeeper.cpp \
|
||||||
gui/im_history/IMHistoryReader.cpp \
|
gui/im_history/IMHistoryReader.cpp \
|
||||||
gui/im_history/IMHistoryItem.cpp \
|
gui/im_history/IMHistoryItem.cpp \
|
||||||
|
gui/im_history/IMHistoryItemDelegate.cpp \
|
||||||
|
gui/im_history/IMHistoryItemPainter.cpp \
|
||||||
gui/im_history/IMHistoryWriter.cpp \
|
gui/im_history/IMHistoryWriter.cpp \
|
||||||
gui/help/browser/helpbrowser.cpp \
|
gui/help/browser/helpbrowser.cpp \
|
||||||
gui/help/browser/helptextbrowser.cpp \
|
gui/help/browser/helptextbrowser.cpp \
|
||||||
|
|
|
@ -1756,6 +1756,6 @@ void PeersDialog::statusColumn()
|
||||||
|
|
||||||
void PeersDialog::on_actionMessageHistory_triggered()
|
void PeersDialog::on_actionMessageHistory_triggered()
|
||||||
{
|
{
|
||||||
ImHistoryBrowser imBrowser(historyKeeper, this);
|
ImHistoryBrowser imBrowser(false, historyKeeper, this);
|
||||||
imBrowser.exec();
|
imBrowser.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,28 +18,51 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
#include "ImHistoryBrowser.h"
|
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
//#include <QDomDocument>
|
#include <QTextDocument>
|
||||||
|
|
||||||
|
#include "ImHistoryBrowser.h"
|
||||||
|
#include "IMHistoryItemDelegate.h"
|
||||||
|
#include "IMHistoryItemPainter.h"
|
||||||
|
|
||||||
#include "rshare.h"
|
#include "rshare.h"
|
||||||
|
#include "gui/settings/rsharesettings.h"
|
||||||
|
|
||||||
//#include "gui/chat/HandleRichText.h"
|
#define ROLE_PLAINTEXT Qt::UserRole
|
||||||
|
|
||||||
/** Default constructor */
|
/** Default constructor */
|
||||||
ImHistoryBrowser::ImHistoryBrowser(IMHistoryKeeper &histKeeper, QWidget *parent, Qt::WFlags flags)
|
ImHistoryBrowser::ImHistoryBrowser(bool isPrivateChatIn, IMHistoryKeeper &histKeeper, QWidget *parent, Qt::WFlags flags)
|
||||||
: QDialog(parent, flags), historyKeeper(histKeeper)
|
: QDialog(parent, flags), historyKeeper(histKeeper)
|
||||||
{
|
{
|
||||||
/* Invoke Qt Designer generated QObject setup routine */
|
/* Invoke Qt Designer generated QObject setup routine */
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
|
|
||||||
|
isPrivateChat = isPrivateChatIn;
|
||||||
|
|
||||||
connect(&historyKeeper, SIGNAL(historyAdd(IMHistoryItem)), this, SLOT(historyAdd(IMHistoryItem)));
|
connect(&historyKeeper, SIGNAL(historyAdd(IMHistoryItem)), this, SLOT(historyAdd(IMHistoryItem)));
|
||||||
connect(&historyKeeper, SIGNAL(historyClear()), this, SLOT(historyClear()));
|
connect(&historyKeeper, SIGNAL(historyClear()), this, SLOT(historyClear()));
|
||||||
|
|
||||||
|
connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
|
||||||
|
connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged()));
|
||||||
|
|
||||||
|
ui.clearButton->hide();
|
||||||
|
|
||||||
|
// embed smileys ?
|
||||||
|
if (isPrivateChat) {
|
||||||
|
embedSmileys = Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_PrivatChat"), true).toBool();
|
||||||
|
} else {
|
||||||
|
embedSmileys = Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_GroupChat"), true).toBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
style.setStylePath(":/qss/chat/history");
|
||||||
|
style.loadEmoticons();
|
||||||
|
|
||||||
|
ui.listWidget->setItemDelegate(new IMHistoryItemDelegate);
|
||||||
|
|
||||||
QList<IMHistoryItem> historyItems;
|
QList<IMHistoryItem> historyItems;
|
||||||
historyKeeper.getMessages(historyItems, 0);
|
historyKeeper.getMessages(historyItems, 0);
|
||||||
foreach(IMHistoryItem item, historyItems) {
|
foreach(IMHistoryItem item, historyItems) {
|
||||||
|
@ -49,38 +72,93 @@ ImHistoryBrowser::ImHistoryBrowser(IMHistoryKeeper &histKeeper, QWidget *parent,
|
||||||
|
|
||||||
void ImHistoryBrowser::historyAdd(IMHistoryItem item)
|
void ImHistoryBrowser::historyAdd(IMHistoryItem item)
|
||||||
{
|
{
|
||||||
addItem(item);
|
QListWidgetItem *itemWidget = addItem(item);
|
||||||
|
if (itemWidget) {
|
||||||
|
filterItems(itemWidget);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImHistoryBrowser::historyClear()
|
void ImHistoryBrowser::historyClear()
|
||||||
{
|
{
|
||||||
ui.textBrowser->clear();
|
ui.listWidget->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImHistoryBrowser::addItem(IMHistoryItem &item)
|
QListWidgetItem *ImHistoryBrowser::addItem(IMHistoryItem &item)
|
||||||
{
|
{
|
||||||
QString timestamp = item.sendTime.toString("hh:mm:ss");
|
unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS;
|
||||||
QString text = "<span style=\"color:#C00000\">" + timestamp + "</span>" +
|
|
||||||
"<span style=\"color:#2D84C9\"><strong>" + " " + item.name + "</strong></span>";
|
|
||||||
|
|
||||||
// create a DOM tree object from the message and embed contents with HTML tags
|
if (embedSmileys) {
|
||||||
// QDomDocument doc;
|
formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS;
|
||||||
// doc.setContent(item.messageText);
|
}
|
||||||
//
|
|
||||||
// // embed links
|
ChatStyle::enumFormatMessage type;
|
||||||
// QDomElement body = doc.documentElement();
|
if (item.incoming) {
|
||||||
// RsChat::embedHtml(doc, body, defEmbedAhref);
|
type = ChatStyle::FORMATMSG_INCOMING;
|
||||||
//
|
} else {
|
||||||
// // embed smileys
|
type = ChatStyle::FORMATMSG_OUTGOING;
|
||||||
// Settings->beginGroup("Chat");
|
}
|
||||||
// if (Settings->value(QString::fromUtf8("Emoteicons_GroupChat"), true).toBool()) {
|
|
||||||
// RsChat::embedHtml(doc, body, defEmbedImg);
|
QString formatMsg = style.formatMessage(type, item.name, item.sendTime, item.messageText, formatFlag);
|
||||||
// }
|
|
||||||
// Settings->endGroup();
|
QListWidgetItem *itemWidget = new QListWidgetItem;
|
||||||
//
|
itemWidget->setData(Qt::DisplayRole, qVariantFromValue(IMHistoryItemPainter(formatMsg)));
|
||||||
// text += doc.toString(-1); // -1 removes any annoying carriage return misinterpreted by QTextEdit
|
|
||||||
|
/* calculate plain text */
|
||||||
text += item.messageText;
|
QTextDocument doc;
|
||||||
|
doc.setHtml(item.messageText);
|
||||||
ui.textBrowser->append(text);
|
itemWidget->setData(ROLE_PLAINTEXT, doc.toPlainText());
|
||||||
|
ui.listWidget->addItem(itemWidget);
|
||||||
|
|
||||||
|
return itemWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImHistoryBrowser::filterRegExpChanged()
|
||||||
|
{
|
||||||
|
QString text = ui.filterPatternLineEdit->text();
|
||||||
|
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
ui.clearButton->hide();
|
||||||
|
} else {
|
||||||
|
ui.clearButton->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
filterItems();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImHistoryBrowser::clearFilter()
|
||||||
|
{
|
||||||
|
ui.filterPatternLineEdit->clear();
|
||||||
|
ui.filterPatternLineEdit->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImHistoryBrowser::filterItems(QListWidgetItem *item)
|
||||||
|
{
|
||||||
|
QString text = ui.filterPatternLineEdit->text();
|
||||||
|
|
||||||
|
QRegExp regExp(text);
|
||||||
|
if (item == NULL) {
|
||||||
|
int count = ui.listWidget->count();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
item = ui.listWidget->item(i);
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
item->setHidden(false);
|
||||||
|
} else {
|
||||||
|
if (item->data(ROLE_PLAINTEXT).toString().contains(regExp)) {
|
||||||
|
item->setHidden(false);
|
||||||
|
} else {
|
||||||
|
item->setHidden(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
item->setHidden(false);
|
||||||
|
} else {
|
||||||
|
if (item->data(ROLE_PLAINTEXT).toString().contains(regExp)) {
|
||||||
|
item->setHidden(false);
|
||||||
|
} else {
|
||||||
|
item->setHidden(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
|
|
||||||
#include "IMHistoryKeeper.h"
|
#include "IMHistoryKeeper.h"
|
||||||
|
#include "gui/chat/ChatStyle.h"
|
||||||
|
|
||||||
#include "ui_ImHistoryBrowser.h"
|
#include "ui_ImHistoryBrowser.h"
|
||||||
|
|
||||||
|
@ -35,17 +36,24 @@ class ImHistoryBrowser : public QDialog
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Default constructor */
|
/** Default constructor */
|
||||||
ImHistoryBrowser(IMHistoryKeeper &histKeeper, QWidget *parent = 0, Qt::WFlags flags = 0);
|
ImHistoryBrowser(bool isPrivateChat, IMHistoryKeeper &histKeeper, QWidget *parent = 0, Qt::WFlags flags = 0);
|
||||||
/** Default destructor */
|
/** Default destructor */
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void historyAdd(IMHistoryItem item);
|
void historyAdd(IMHistoryItem item);
|
||||||
void historyClear();
|
void historyClear();
|
||||||
|
|
||||||
private:
|
void filterRegExpChanged();
|
||||||
void addItem(IMHistoryItem &item);
|
void clearFilter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QListWidgetItem *addItem(IMHistoryItem &item);
|
||||||
|
void filterItems(QListWidgetItem *item = NULL);
|
||||||
|
|
||||||
|
bool isPrivateChat;
|
||||||
|
bool embedSmileys;
|
||||||
IMHistoryKeeper &historyKeeper;
|
IMHistoryKeeper &historyKeeper;
|
||||||
|
ChatStyle style;
|
||||||
|
|
||||||
/** Qt Designer generated object */
|
/** Qt Designer generated object */
|
||||||
Ui::ImHistoryBrowser ui;
|
Ui::ImHistoryBrowser ui;
|
||||||
|
|
|
@ -19,15 +19,86 @@
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QTextBrowser" name="textBrowser"/>
|
<layout class="QGridLayout" name="mainLayout">
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<layout class="QHBoxLayout" name="bottomLine">
|
||||||
<property name="standardButtons">
|
<item>
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<layout class="QHBoxLayout" name="filterLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../images.qrc">:/images/find-16.png</pixmap>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="filterPatternLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="clearButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reset</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QPushButton
|
||||||
|
{
|
||||||
|
border-image: url(:/images/closenormal.png)
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:hover
|
||||||
|
{
|
||||||
|
border-image: url(:/images/closehover.png)
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton:pressed {
|
||||||
|
border-image: url(:/images/closepressed.png)
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QListWidget" name="listWidget"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -38,27 +109,11 @@
|
||||||
<sender>buttonBox</sender>
|
<sender>buttonBox</sender>
|
||||||
<signal>accepted()</signal>
|
<signal>accepted()</signal>
|
||||||
<receiver>ImHistoryBrowser</receiver>
|
<receiver>ImHistoryBrowser</receiver>
|
||||||
<slot>close()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>237</x>
|
<x>427</x>
|
||||||
<y>312</y>
|
<y>310</y>
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>237</x>
|
|
||||||
<y>166</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>ImHistoryBrowser</receiver>
|
|
||||||
<slot>close()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>237</x>
|
|
||||||
<y>312</y>
|
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>237</x>
|
<x>237</x>
|
||||||
|
|
|
@ -459,6 +459,9 @@
|
||||||
<file>qss/chat/public/hincoming.htm</file>
|
<file>qss/chat/public/hincoming.htm</file>
|
||||||
<file>qss/chat/public/houtgoing.htm</file>
|
<file>qss/chat/public/houtgoing.htm</file>
|
||||||
<file>qss/chat/public/main.css</file>
|
<file>qss/chat/public/main.css</file>
|
||||||
|
<file>qss/chat/history/incoming.htm</file>
|
||||||
|
<file>qss/chat/history/outgoing.htm</file>
|
||||||
|
<file>qss/chat/history/main.css</file>
|
||||||
<file>smileys/angry.png</file>
|
<file>smileys/angry.png</file>
|
||||||
<file>smileys/beer.png</file>
|
<file>smileys/beer.png</file>
|
||||||
<file>smileys/cake.png</file>
|
<file>smileys/cake.png</file>
|
||||||
|
|
16
retroshare-gui/src/gui/qss/chat/history/incoming.htm
Normal file
16
retroshare-gui/src/gui/qss/chat/history/incoming.htm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<style type="text/css">
|
||||||
|
%css-style%
|
||||||
|
</style>
|
||||||
|
<table class='incomingTable' width='100%'>
|
||||||
|
<tr>
|
||||||
|
<td class='header incomingHeader'>%name%</td>
|
||||||
|
<td width='10%' align='left' class='time incomingTime'>[%timestamp%] </td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class='incomingTable' width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>%message%</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
55
retroshare-gui/src/gui/qss/chat/history/main.css
Normal file
55
retroshare-gui/src/gui/qss/chat/history/main.css
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
.header {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
}
|
||||||
|
|
||||||
|
.incomingTable{
|
||||||
|
background-color:#dfedff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incomingHeader {
|
||||||
|
border-color:#fafafa #d1dfef #d1dfef #fafafa;
|
||||||
|
color: #295b07;
|
||||||
|
}
|
||||||
|
|
||||||
|
.incomingTime {
|
||||||
|
color: #295b07;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outgoingTable{
|
||||||
|
background-color:#f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outgoingHeader {
|
||||||
|
border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa;
|
||||||
|
color: #244578;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outgoingTime {
|
||||||
|
color: #244578;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hincomingHeader {
|
||||||
|
background-color:#dfedff;
|
||||||
|
border-color:#fafafa #d1dfef #d1dfef #fafafa;
|
||||||
|
color: #295b07;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hincomingTime {
|
||||||
|
background-color:#dfedff;
|
||||||
|
color: #295b07;
|
||||||
|
}
|
||||||
|
|
||||||
|
.houtgoingHeader {
|
||||||
|
background-color:#f5f5f5;
|
||||||
|
border-color:#fafafa #e3e3e3 #e3e3e3 #fafafa;
|
||||||
|
color: #244578;
|
||||||
|
}
|
||||||
|
|
||||||
|
.houtgoingTime {
|
||||||
|
background-color:#f5f5f5;
|
||||||
|
color: #244578;
|
||||||
|
}
|
||||||
|
|
16
retroshare-gui/src/gui/qss/chat/history/outgoing.htm
Normal file
16
retroshare-gui/src/gui/qss/chat/history/outgoing.htm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<style type="text/css">
|
||||||
|
%css-style%
|
||||||
|
</style>
|
||||||
|
<table class='outgoingTable' width='100%'>
|
||||||
|
<tr>
|
||||||
|
<td class='header outgoingHeader'>%name%</td>
|
||||||
|
<td width='10%' align='left' class='time outgoingTime'>[%timestamp%] </td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class='outgoingTable' width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>%message%</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue