[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [konversation] src: Add support for server-time and message tags
From:       Peter Simonsson <peter.simonsson () gmail ! com>
Date:       2016-09-10 13:54:33
Message-ID: E1biijp-0008JG-0m () code ! kde ! org
[Download RAW message or body]

Git commit b994b59f41e817dfa0a46274bf3529b6a7bc3813 by Peter Simonsson.
Committed on 10/09/2016 at 13:49.
Pushed by psn into branch 'master'.

Add support for server-time and message tags

Also added support for znc.in/server-time-iso which is the same as
server-time. This makes buffer playback from znc look much nicer.

BUG: 356917

M  +1    -1    src/dcc/transferrecv.cpp
M  +1    -1    src/dcc/transfersend.cpp
M  +35   -35   src/irc/channel.cpp
M  +9    -9    src/irc/channel.h
M  +175  -142  src/irc/inputfilter.cpp
M  +6    -4    src/irc/inputfilter.h
M  +3    -3    src/irc/query.cpp
M  +1    -1    src/irc/query.h
M  +47   -35   src/irc/server.cpp
M  +17   -14   src/irc/server.h
M  +12   -12   src/viewer/chatwindow.cpp
M  +5    -5    src/viewer/chatwindow.h
M  +25   -23   src/viewer/ircview.cpp
M  +8    -8    src/viewer/ircview.h
M  +3    -3    src/viewer/viewcontainer.cpp
M  +1    -1    src/viewer/viewcontainer.h

http://commits.kde.org/konversation/b994b59f41e817dfa0a46274bf3529b6a7bc3813

diff --git a/src/dcc/transferrecv.cpp b/src/dcc/transferrecv.cpp
index bbab8e1..4244dd3 100644
--- a/src/dcc/transferrecv.cpp
+++ b/src/dcc/transferrecv.cpp
@@ -584,7 +584,7 @@ namespace Konversation
 
                 if (error)
                 {
-                    server->appendMessageToFrontmost(i18nc("Universal Plug and Play", "UPnP"), \
i18n("Failed to forward port %1. Sending DCC request to remote user regardless.", \
QString::number(m_ownPort)), false); +                    \
server->appendMessageToFrontmost(i18nc("Universal Plug and Play", "UPnP"), i18n("Failed to \
forward port %1. Sending DCC request to remote user regardless.", QString::number(m_ownPort)), \
QHash<QString, QString>(), false);  }
             }
 
diff --git a/src/dcc/transfersend.cpp b/src/dcc/transfersend.cpp
index 2121684..cc3629a 100644
--- a/src/dcc/transfersend.cpp
+++ b/src/dcc/transfersend.cpp
@@ -391,7 +391,7 @@ namespace Konversation
 
                 if (error)
                 {
-                    server->appendMessageToFrontmost(i18nc("Universal Plug and Play", "UPnP"), \
i18n("Failed to forward port %1. Sending DCC request to remote user regardless.", \
QString::number(m_ownPort)), false); +                    \
server->appendMessageToFrontmost(i18nc("Universal Plug and Play", "UPnP"), i18n("Failed to \
forward port %1. Sending DCC request to remote user regardless.", QString::number(m_ownPort)), \
QHash<QString, QString>(), false);  }
             }
 
diff --git a/src/irc/channel.cpp b/src/irc/channel.cpp
index 4304d57..acd40b6 100644
--- a/src/irc/channel.cpp
+++ b/src/irc/channel.cpp
@@ -1045,7 +1045,7 @@ bool Channel::shouldShowEvent(ChannelNickPtr channelNick)
         return true; // if hideUnimportantEvents is off we don't care and just show the event
 }
 
-void Channel::nickRenamed(const QString &oldNick, const NickInfo& nickInfo)
+void Channel::nickRenamed(const QString &oldNick, const NickInfo& nickInfo, const \
QHash<QString, QString> &messageTags)  {
     QString newNick = nickInfo.getNickname();
     Nick *nick = getNickByName(oldNick);
@@ -1063,12 +1063,12 @@ void Channel::nickRenamed(const QString &oldNick, const NickInfo& \
nickInfo)  {
         setNickname(newNick);
         if (displayCommandMessage)
-            appendCommandMessage(i18n("Nick"),i18n("You are now known as %1.", newNick), true, \
true); +            appendCommandMessage(i18n("Nick"),i18n("You are now known as %1.", \
newNick), messageTags, true, true);  }
     else if (displayCommandMessage)
     {
         /* No, must've been someone else */
-        appendCommandMessage(i18n("Nick"),i18n("%1 is now known as %2.", oldNick, newNick));
+        appendCommandMessage(i18n("Nick"),i18n("%1 is now known as %2.", oldNick, newNick), \
messageTags);  }
 
     if (nick)
@@ -1080,7 +1080,7 @@ void Channel::nickRenamed(const QString &oldNick, const NickInfo& \
nickInfo)  }
 }
 
-void Channel::joinNickname(ChannelNickPtr channelNick)
+void Channel::joinNickname(ChannelNickPtr channelNick, const QHash<QString, QString> \
&messageTags)  {
     bool displayCommandMessage = shouldShowEvent(channelNick);
 
@@ -1090,7 +1090,7 @@ void Channel::joinNickname(ChannelNickPtr channelNick)
         emit joined(this);
         if (displayCommandMessage)
             appendCommandMessage(i18nc("Message type", "Join"), i18nc("%1 = our hostmask, %2 = \
                channel",
-                                 "You (%1) have joined the channel %2.", \
channelNick->getHostmask(), getName()), false, true); +                                 "You \
(%1) have joined the channel %2.", channelNick->getHostmask(), getName()), messageTags, false, \
true);  
         // Prepare for impending NAMES.
         purgeNicks();
@@ -1118,12 +1118,12 @@ void Channel::joinNickname(ChannelNickPtr channelNick)
         QString hostname = channelNick->getHostmask();
         if (displayCommandMessage)
             appendCommandMessage(i18nc("Message type", "Join"), i18nc("%1 is the nick joining \
                and %2 the hostmask of that nick",
-                                 "%1 (%2) has joined this channel.", nick, hostname), false);
+                                 "%1 (%2) has joined this channel.", nick, hostname), \
messageTags, false);  addNickname(channelNick);
     }
 }
 
-void Channel::removeNick(ChannelNickPtr channelNick, const QString &reason, bool quit)
+void Channel::removeNick(ChannelNickPtr channelNick, const QString &reason, bool quit, const \
QHash<QString, QString> &messageTags)  {
     bool displayCommandMessage = shouldShowEvent(channelNick);
 
@@ -1144,18 +1144,18 @@ void Channel::removeNick(ChannelNickPtr channelNick, const QString \
&reason, bool  if (quit)
             {
                 if (displayReason.isEmpty())
-                    appendCommandMessage(i18nc("Message type", "Quit"), i18n("You (%1) have \
left this server.", channelNick->getHostmask())); +                    \
appendCommandMessage(i18nc("Message type", "Quit"), i18n("You (%1) have left this server.", \
channelNick->getHostmask()), messageTags);  else
                     appendCommandMessage(i18nc("Message type", "Quit"), i18nc("%1 = our \
                hostmask, %2 = reason", "You (%1) have left this server (%2).",
-                        channelNick->getHostmask(), displayReason), false);
+                        channelNick->getHostmask(), displayReason), messageTags, false);
             }
             else
             {
                 if (displayReason.isEmpty())
-                    appendCommandMessage(i18nc("Message type", "Part"), i18n("You have left \
channel %1.", getName())); +                    appendCommandMessage(i18nc("Message type", \
"Part"), i18n("You have left channel %1.", getName()), messageTags);  else
                     appendCommandMessage(i18nc("Message type", "Part"), i18nc("%1 = our \
                hostmask, %2 = channel, %3 = reason",
-                        "You (%1) have left channel %2 (%3).", channelNick->getHostmask(), \
getName(), displayReason), false); +                        "You (%1) have left channel %2 \
(%3).", channelNick->getHostmask(), getName(), displayReason), messageTags, false);  }
         }
 
@@ -1169,19 +1169,19 @@ void Channel::removeNick(ChannelNickPtr channelNick, const QString \
&reason, bool  {
                 if (displayReason.isEmpty())
                     appendCommandMessage(i18nc("Message type", "Quit"), i18n("%1 (%2) has left \
                this server.", channelNick->getNickname(),
-                        channelNick->getHostmask()), false);
+                        channelNick->getHostmask()), messageTags, false);
                 else
                     appendCommandMessage(i18nc("Message type", "Quit"), i18nc("%1 = nick, %2 = \
                hostname, %3 = reason",
-                        "%1 (%2) has left this server (%3).", channelNick->getNickname(), \
channelNick->getHostmask(), displayReason), false); +                        "%1 (%2) has left \
this server (%3).", channelNick->getNickname(), channelNick->getHostmask(), displayReason), \
messageTags, false);  }
             else
             {
                 if (displayReason.isEmpty())
                     appendCommandMessage(i18nc("Message type", "Part"), i18n("%1 (%2) has left \
                this channel.", channelNick->getNickname(),
-                        channelNick->getHostmask()), false);
+                        channelNick->getHostmask()), messageTags, false);
                 else
                     appendCommandMessage(i18nc("Message type", "Part"), i18nc("%1 = nick, %2 = \
                hostmask, %3 = reason",
-                        "%1 (%2) has left this channel (%3).", channelNick->getNickname(), \
channelNick->getHostmask(), displayReason), false); +                        "%1 (%2) has left \
this channel (%3).", channelNick->getNickname(), channelNick->getHostmask(), displayReason), \
messageTags, false);  }
         }
 
@@ -1213,7 +1213,7 @@ void Channel::flushNickQueue()
     processQueuedNicks(true);
 }
 
-void Channel::kickNick(ChannelNickPtr channelNick, const QString &kicker, const QString \
&reason) +void Channel::kickNick(ChannelNickPtr channelNick, const QString &kicker, const \
QString &reason, const QHash<QString, QString> &messageTags)  {
     QString displayReason = reason;
 
@@ -1229,22 +1229,22 @@ void Channel::kickNick(ChannelNickPtr channelNick, const QString \
&kicker, const  if(kicker == m_server->getNickname())
         {
             if (displayReason.isEmpty())
-                appendCommandMessage(i18n("Kick"), i18n("You have kicked yourself from channel \
%1.", getName())); +                appendCommandMessage(i18n("Kick"), i18n("You have kicked \
yourself from channel %1.", getName()), messageTags);  else
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the channel and %2 the \
                reason",
-                                              "You have kicked yourself from channel %1 \
(%2).", getName(), displayReason)); +                                              "You have \
kicked yourself from channel %1 (%2).", getName(), displayReason), messageTags);  }
         else
         {
             if (displayReason.isEmpty())
             {
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the channel, %2 adds the \
                kicker",
-                                              "You have been kicked from channel %1 by %2.", \
getName(), kicker)); +                                              "You have been kicked from \
channel %1 by %2.", getName(), kicker), messageTags);  }
             else
             {
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the channel, %2 the kicker \
                and %3 the reason",
-                                              "You have been kicked from channel %1 by %2 \
(%3).", getName(), kicker, displayReason)); +                                              "You \
have been kicked from channel %1 by %2 (%3).", getName(), kicker, displayReason), messageTags); \
}  
             Application::instance()->notificationHandler()->kick(this,getName(), kicker);
@@ -1264,22 +1264,22 @@ void Channel::kickNick(ChannelNickPtr channelNick, const QString \
&kicker, const  if(kicker == m_server->getNickname())
         {
             if (displayReason.isEmpty())
-                appendCommandMessage(i18n("Kick"), i18n("You have kicked %1 from the \
channel.", channelNick->getNickname())); +                appendCommandMessage(i18n("Kick"), \
i18n("You have kicked %1 from the channel.", channelNick->getNickname()), messageTags);  else
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the kicked nick and %2 the \
                reason",
-                                     "You have kicked %1 from the channel (%2).", \
channelNick->getNickname(), displayReason)); +                                     "You have \
kicked %1 from the channel (%2).", channelNick->getNickname(), displayReason), messageTags);  }
         else
         {
             if (displayReason.isEmpty())
             {
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the kicked nick, %2 adds the \
                kicker",
-                                     "%1 has been kicked from the channel by %2.", \
channelNick->getNickname(), kicker)); +                                     "%1 has been kicked \
from the channel by %2.", channelNick->getNickname(), kicker), messageTags);  }
             else
             {
                 appendCommandMessage(i18n("Kick"), i18nc("%1 adds the kicked nick, %2 the \
                kicker and %3 the reason",
-                                     "%1 has been kicked from the channel by %2 (%3).", \
channelNick->getNickname(), kicker, displayReason)); +                                     "%1 \
has been kicked from the channel by %2 (%3).", channelNick->getNickname(), kicker, \
displayReason), messageTags);  }
         }
 
@@ -1357,7 +1357,7 @@ QString Channel::getTopic()
     return m_topicHistory->currentTopic();
 }
 
-void Channel::setTopic(const QString& text)
+void Channel::setTopic(const QString& text, const QHash<QString, QString> &messageTags)
 {
     QString cleanTopic = text;
 
@@ -1365,12 +1365,12 @@ void Channel::setTopic(const QString& text)
     if (!cleanTopic.isEmpty() && hasIRCMarkups(cleanTopic))
         cleanTopic += QStringLiteral("\017");
 
-    appendCommandMessage(i18n("Topic"), i18n("The channel topic is \"%1\".", cleanTopic));
+    appendCommandMessage(i18n("Topic"), i18n("The channel topic is \"%1\".", cleanTopic), \
messageTags);  
     m_topicHistory->appendTopic(replaceIRCMarkups(Konversation::removeIrcMarkup(text)));
 }
 
-void Channel::setTopic(const QString& nickname, const QString& text)
+void Channel::setTopic(const QString& nickname, const QString& text, const QHash<QString, \
QString> &messageTags)  {
     QString cleanTopic = text;
 
@@ -1379,9 +1379,9 @@ void Channel::setTopic(const QString& nickname, const QString& text)
         cleanTopic += QStringLiteral("\017");
 
     if (nickname == m_server->getNickname())
-        appendCommandMessage(i18n("Topic"), i18n("You set the channel topic to \"%1\".", \
cleanTopic)); +        appendCommandMessage(i18n("Topic"), i18n("You set the channel topic to \
\"%1\".", cleanTopic), messageTags);  else
-        appendCommandMessage(i18n("Topic"), i18n("%1 sets the channel topic to \"%2\".", \
nickname, cleanTopic)); +        appendCommandMessage(i18n("Topic"), i18n("%1 sets the channel \
topic to \"%2\".", nickname, cleanTopic), messageTags);  
     m_topicHistory->appendTopic(replaceIRCMarkups(Konversation::removeIrcMarkup(text)), \
nickname);  }
@@ -1394,7 +1394,7 @@ void Channel::setTopicAuthor(const QString& author, QDateTime time)
     m_topicHistory->setCurrentTopicMetadata(author, time);
 }
 
-void Channel::updateMode(const QString& sourceNick, char mode, bool plus, const QString \
&parameter) +void Channel::updateMode(const QString& sourceNick, char mode, bool plus, const \
QString &parameter, const QHash<QString, QString> &messageTags)  {
     // Note for future expansion:
     //     m_server->getChannelNick(getName(), sourceNick);
@@ -1826,7 +1826,7 @@ void Channel::updateMode(const QString& sourceNick, char mode, bool plus, \
const  
     if (!message.isEmpty() && !Preferences::self()->useLiteralModes())
     {
-        appendCommandMessage(i18n("Mode"), message);
+        appendCommandMessage(i18n("Mode"), message, messageTags);
     }
 
     updateModeWidgets(mode, plus, parameter);
@@ -2683,7 +2683,7 @@ void Channel::clearBanList()
   emit banListCleared();
 }
 
-void Channel::append(const QString& nickname, const QString& message, const QString& label)
+void Channel::append(const QString& nickname, const QString& message, const QHash<QString, \
QString> &messageTags, const QString& label)  {
     if(nickname != getServer()->getNickname()) {
         Nick* nick = getNickByName(nickname);
@@ -2693,11 +2693,11 @@ void Channel::append(const QString& nickname, const QString& message, \
const QStr  }
     }
 
-    ChatWindow::append(nickname, message, label);
+    ChatWindow::append(nickname, message, messageTags, label);
     nickActive(nickname);
 }
 
-void Channel::appendAction(const QString& nickname, const QString& message)
+void Channel::appendAction(const QString& nickname, const QString& message, const \
QHash<QString, QString> &messageTags)  {
     if(nickname != getServer()->getNickname()) {
         Nick* nick = getNickByName(nickname);
@@ -2707,7 +2707,7 @@ void Channel::appendAction(const QString& nickname, const QString& \
message)  }
     }
 
-    ChatWindow::appendAction(nickname, message);
+    ChatWindow::appendAction(nickname, message, messageTags);
     nickActive(nickname);
 }
 
diff --git a/src/irc/channel.h b/src/irc/channel.h
index 23042b0..f542053 100644
--- a/src/irc/channel.h
+++ b/src/irc/channel.h
@@ -78,8 +78,8 @@ class Channel : public ChatWindow
         virtual bool canBeFrontView();
         virtual bool searchView();
 
-        virtual void append(const QString& nickname,const QString& message, const QString& \
                label = QString());
-        virtual void appendAction(const QString& nickname,const QString& message);
+        virtual void append(const QString& nickname, const QString& message, const \
QHash<QString, QString> &messageTags = QHash<QString, QString>(), const QString& label = \
QString()); +        virtual void appendAction(const QString& nickname, const QString& message, \
const QHash<QString, QString> &messageTags = QHash<QString, QString>());  void nickActive(const \
QString& nickname);  #ifdef HAVE_QCA2
         Konversation::Cipher* getCipher();
@@ -137,11 +137,11 @@ class Channel : public ChatWindow
         ChannelNickPtr getOwnChannelNick() const;
         ChannelNickPtr getChannelNick(const QString &ircnick) const;
 
-        void joinNickname(ChannelNickPtr channelNick);
-        void removeNick(ChannelNickPtr channelNick, const QString &reason, bool quit);
-        void kickNick(ChannelNickPtr channelNick, const QString &kicker, const QString \
&reason); +        void joinNickname(ChannelNickPtr channelNick, const QHash<QString, QString> \
&messageTags); +        void removeNick(ChannelNickPtr channelNick, const QString &reason, bool \
quit, const QHash<QString, QString> &messageTags); +        void kickNick(ChannelNickPtr \
channelNick, const QString &kicker, const QString &reason, const QHash<QString, QString> \
&messageTags);  void addNickname(ChannelNickPtr channelNick);
-        void nickRenamed(const QString &oldNick, const NickInfo& channelnick);
+        void nickRenamed(const QString &oldNick, const NickInfo& channelnick, const \
QHash<QString, QString> &messageTags);  void queueNicks(const QStringList& nicknameList);
         void endOfNames();
         Nick *getNickByName(const QString& lookname) const;
@@ -164,8 +164,8 @@ class Channel : public ChatWindow
         QString getTopic();
         TopicHistoryModel* getTopicHistory() { return m_topicHistory; }
 
-        void setTopic(const QString& text);
-        void setTopic(const QString& nickname, const QString& text);
+        void setTopic(const QString& text, const QHash<QString, QString> &messageTags);
+        void setTopic(const QString& nickname, const QString& text, const QHash<QString, \
QString> &messageTags);  void setTopicAuthor(const QString& author, QDateTime timestamp);
 
     Q_SIGNALS:
@@ -188,7 +188,7 @@ class Channel : public ChatWindow
          *  @param plus True if the mode is being granted, false if it's being taken away.
          *  @param parameter This depends on what the mode change is.  In most cases it is the \
                nickname of the person that is being given voice/op/admin etc.  See the code.
          */
-        void updateMode(const QString& sourceNick, char mode, bool plus, const QString \
&parameter); +        void updateMode(const QString& sourceNick, char mode, bool plus, const \
QString &parameter, const QHash<QString, QString> &messageTags);  
     Q_SIGNALS:
         void modesChanged();
diff --git a/src/irc/inputfilter.cpp b/src/irc/inputfilter.cpp
index c1857df..e5adfec 100644
--- a/src/irc/inputfilter.cpp
+++ b/src/irc/inputfilter.cpp
@@ -60,15 +60,22 @@ int posOrLen(T chr, const QString& str, int from=0)
 /// "[21:49] >> :niven.freenode.net 352 argonel #kde-forum i=beezle \
konversation/developer/argonel irc.freenode.net argonel H :0 Konversation User "  void \
InputFilter::parseLine(const QString& line)  {
-    QString prefix;
     int start=0;
-    int end(posOrLen(' ', line));
+    QHash<QString, QString> messageTags;
 
-    if (line[0]==QLatin1Char(':'))
+    if (line[0] == QLatin1Char('@'))
     {
-        start=end+1;
-        prefix=line.mid(1, end-1); //skips the colon and does not include the trailing space
-        end=posOrLen(' ', line, start);
+        messageTags = parseMessageTags(line, &start);
+    }
+
+    QString prefix;
+    int end(posOrLen(' ', line, start));
+
+    if (line[start]==QLatin1Char(':'))
+    {
+        prefix = line.mid(start + 1, end - 1); //skips the colon and does not include the \
trailing space +        start = end + 1;
+        end = posOrLen(' ', line, start);
     }
 
     //even though the standard is UPPER CASE, someone when through a great deal of trouble to \
make this lower case... @@ -114,11 +121,11 @@ void InputFilter::parseLine(const QString& line)
     // Server command, if no "!" was found in prefix
     if ((!prefix.contains(QLatin1Char('!'))) && (prefix != m_server->getNickname()))
     {
-        parseServerCommand(prefix, command, parameterList);
+        parseServerCommand(prefix, command, parameterList, messageTags);
     }
     else
     {
-        parseClientCommand(prefix, command, parameterList);
+        parseClientCommand(prefix, command, parameterList, messageTags);
     }
 }
 
@@ -137,7 +144,7 @@ bool _plHas(int count, int x)
     return _plHad;
 }
 
-void InputFilter::parseClientCommand(const QString &prefix, const QString &command, \
QStringList &parameterList) +void InputFilter::parseClientCommand(const QString &prefix, const \
QString &command, QStringList &parameterList, QHash<QString, QString> messageTags)  {
     Application* konv_app = Application::instance();
     Q_ASSERT(konv_app);
@@ -187,7 +194,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  return;
                     }
 
-                    channel->appendAction(sourceNick, ctcpArgument);
+                    channel->appendAction(sourceNick, ctcpArgument, messageTags);
 
                     if (sourceNick != m_server->getNickname())
                     {
@@ -217,7 +224,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
                &comma
                     Query* query = m_server->addQuery(nickinfo, false /* we didn't initiate \
this*/ );  
                     // send action to query
-                    query->appendAction(sourceNick, ctcpArgument);
+                    query->appendAction(sourceNick, ctcpArgument, messageTags);
 
                     if (sourceNick != m_server->getNickname() && query)
                         konv_app->notificationHandler()->queryMessage(query, sourceNick, \
ctcpArgument); @@ -233,14 +240,16 @@ void InputFilter::parseClientCommand(const QString \
&prefix, const QString &comma  {
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received CTCP-PING request from %1 to channel %2, sending \
                answer.",
-                                 sourceNick, parameterList.value(0))
+                                 sourceNick, parameterList.value(0)),
+                            messageTags
                             );
                     }
                     else
                     {
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received CTCP-%1 request from %2, sending answer.",
-                                 QStringLiteral("PING"), sourceNick)
+                                 QStringLiteral("PING"), sourceNick),
+                            messageTags
                             );
                     }
                     m_server->ctcpReply(sourceNick, QString(QStringLiteral("PING \
%1")).arg(ctcpArgument)); @@ -256,14 +265,16 @@ void InputFilter::parseClientCommand(const \
QString &prefix, const QString &comma  {
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received Version request from %1 to channel %2.",
-                                 sourceNick, parameterList.value(0))
+                                 sourceNick, parameterList.value(0)),
+                            messageTags
                             );
                     }
                     else
                     {
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received Version request from %1.",
-                                 sourceNick)
+                                 sourceNick),
+                            messageTags
                             );
                     }
 
@@ -336,7 +347,8 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                             m_server->appendMessageToFrontmost(i18n("DCC"),
                                 i18n("Received invalid DCC SEND request from %1.",
-                                     sourceNick)
+                                     sourceNick),
+                                messageTags
                                 );
                         }
                     }
@@ -351,7 +363,8 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                             m_server->appendMessageToFrontmost(i18n("DCC"),
                                 i18n("Received invalid DCC ACCEPT request from %1.",
-                                     sourceNick)
+                                     sourceNick),
+                                messageTags
                                 );
                         }
                     }
@@ -366,7 +379,8 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                             m_server->appendMessageToFrontmost(i18n("DCC"),
                                 i18n("Received invalid DCC RESUME request from %1.",
-                                     sourceNick)
+                                     sourceNick),
+                                messageTags
                                 );
                         }
                     }
@@ -394,7 +408,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                             m_server->appendMessageToFrontmost(i18n("DCC"),
                                                              i18n("Received invalid DCC CHAT \
                request from %1.",
-                                                             sourceNick)
+                                                             sourceNick), messageTags
                                 );
                         }
                     }
@@ -402,7 +416,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                         m_server->appendMessageToFrontmost(i18n("DCC"),
                             i18n("Unknown DCC command %1 received from %2.",
-                                 ctcpArgument, sourceNick)
+                                 ctcpArgument, sourceNick), messageTags
                             );
                     }
                 }
@@ -413,7 +427,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                     m_server->appendMessageToFrontmost(i18n("CTCP"),
                         i18n("Received CTCP-%1 request from %2, sending answer.",
-                            QString::fromLatin1("CLIENTINFO"), sourceNick)
+                            QString::fromLatin1("CLIENTINFO"), sourceNick), messageTags
                         );
                     m_server->ctcpReply(sourceNick, QStringLiteral("CLIENTINFO ACTION \
CLIENTINFO DCC PING TIME VERSION"));  }
@@ -424,7 +438,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                     m_server->appendMessageToFrontmost(i18n("CTCP"),
                         i18n("Received CTCP-%1 request from %2, sending answer.",
-                            QString::fromLatin1("TIME"), sourceNick)
+                            QString::fromLatin1("TIME"), sourceNick), messageTags
                         );
                     m_server->ctcpReply(sourceNick, QStringLiteral("TIME \
")+QDateTime::currentDateTime().toString());  }
@@ -440,12 +454,14 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  parameterList.value(0),
                             QStringLiteral("CTCP"),
                             i18n("Received unknown CTCP-%1 request from %2 to Channel %3.",
-                                 ctcp, sourceNick, parameterList.value(0))
+                                 ctcp, sourceNick, parameterList.value(0)),
+                            messageTags
                             );
                     else
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received unknown CTCP-%1 request from %2.",
-                                 ctcp, sourceNick)
+                                 ctcp, sourceNick),
+                            messageTags
                             );
                 }
             }
@@ -453,7 +469,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  // No CTCP, so it's an ordinary channel or query message
         else
         {
-            parsePrivMsg(prefix, parameterList);
+            parsePrivMsg(prefix, parameterList, messageTags);
         }
     }
     else if (command==QStringLiteral("notice") && plHas(2))
@@ -469,7 +485,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  }
 
                 m_server->appendServerMessageToChannel(parameterList.value(0), i18n("Notice"),
-                        i18n("-%1 to %2- %3", sourceNick, parameterList.value(0), trailing)
+                        i18n("-%1 to %2- %3", sourceNick, parameterList.value(0), trailing), \
messageTags  );
             }
             // Private notice
@@ -493,7 +509,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received CTCP-PING reply from %1: %2 %3.",
-                                 sourceNick, time, unit)
+                                 sourceNick, time, unit), messageTags
                             );
                     }
                     else if (replyReason.toLower() == QStringLiteral("dcc"))
@@ -521,7 +537,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
                         m_server->appendMessageToFrontmost(i18n("CTCP"),
                             i18n("Received CTCP-%1 reply from %2: %3.",
-                                 replyReason, sourceNick, reply)
+                                 replyReason, sourceNick, reply), messageTags
                             );
                     }
                 }
@@ -533,19 +549,19 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  //Key exchange
                     if (trailing.startsWith(QLatin1String("DH1080_INIT ")))
                     {
-                        m_server->appendMessageToFrontmost(i18n("Notice"), i18n("Received \
DH1080_INIT from %1", sourceNick)); +                        \
m_server->appendMessageToFrontmost(i18n("Notice"), i18n("Received DH1080_INIT from %1", \
                sourceNick), messageTags);
                         m_server->parseInitKeyX(sourceNick, trailing.mid(12));
                     }
                     else if (trailing.startsWith(QLatin1String("DH1080_FINISH ")))
                     {
-                        m_server->appendMessageToFrontmost(i18n("Notice"), i18n("Received \
DH1080_FINISH from %1", sourceNick)); +                        \
m_server->appendMessageToFrontmost(i18n("Notice"), i18n("Received DH1080_FINISH from %1", \
                sourceNick), messageTags);
                         m_server->parseFinishKeyX(sourceNick, trailing.mid(14));
                     }
                     else
                     {
                     #endif
                         m_server->appendMessageToFrontmost(i18n("Notice"), i18n("-%1- %2", \
                sourceNick,
-                            m_server->identifyMsg() ? trailing.mid(1) : trailing));
+                            m_server->identifyMsg() ? trailing.mid(1) : trailing), \
messageTags);  #ifdef HAVE_QCA2
                     }
                     #endif
@@ -592,7 +608,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
                &comma
             */
 
             // Join the channel
-            Channel* channel = m_server->joinChannel(channelName, sourceHostmask);
+            Channel* channel = m_server->joinChannel(channelName, sourceHostmask, \
messageTags);  
             // Upon JOIN we're going to receive some NAMES input from the server which
             // we need to be able to tell apart from manual invocations of /names
@@ -610,13 +626,13 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  }
         else
         {
-            Channel* channel = m_server->nickJoinsChannel(channelName, sourceNick, \
sourceHostmask, account, realName); +            Channel* channel = \
m_server->nickJoinsChannel(channelName, sourceNick, sourceHostmask, account, realName, \
messageTags);  konv_app->notificationHandler()->join(channel, sourceNick);
         }
     }
     else if (command==QStringLiteral("kick") && plHas(2))
     {
-        m_server->nickWasKickedFromChannel(parameterList.value(0), parameterList.value(1), \
sourceNick, trailing); +        m_server->nickWasKickedFromChannel(parameterList.value(0), \
parameterList.value(1), sourceNick, trailing, messageTags);  }
     else if (command==QStringLiteral("part") && plHas(1))
     {
@@ -625,7 +641,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  QString channel(parameterList.value(0));
         QString reason(parameterList.value(1));
 
-        Channel* channelPtr = m_server->removeNickFromChannel(channel, sourceNick, reason);
+        Channel* channelPtr = m_server->removeNickFromChannel(channel, sourceNick, reason, \
messageTags);  
         if (sourceNick != m_server->getNickname())
         {
@@ -634,7 +650,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  }
     else if (command==QStringLiteral("quit") && plHas(1))
     {
-        m_server->removeNickFromServer(sourceNick, trailing);
+        m_server->removeNickFromServer(sourceNick, trailing, messageTags);
         if (sourceNick != m_server->getNickname())
         {
             konv_app->notificationHandler()->quit(m_server->getStatusView(), sourceNick);
@@ -644,7 +660,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  {
         QString newNick(parameterList.value(0)); // Message may not include ":" in front of \
the new nickname  
-        m_server->renameNick(sourceNick, newNick);
+        m_server->renameNick(sourceNick, newNick, messageTags);
 
         if (sourceNick != m_server->getNickname())
         {
@@ -653,11 +669,11 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  }
     else if (command==QStringLiteral("topic") && plHas(2))
     {
-        m_server->setChannelTopic(sourceNick, parameterList.value(0), trailing);
+        m_server->setChannelTopic(sourceNick, parameterList.value(0), trailing, messageTags);
     }
     else if (command==QStringLiteral("mode") && plHas(2)) // mode #channel -/+ mmm params
     {
-        parseModes(sourceNick, parameterList);
+        parseModes(sourceNick, parameterList, messageTags);
         Channel* channel = m_server->getChannelByName(parameterList.value(0));
         konv_app->notificationHandler()->mode(channel, sourceNick, parameterList.value(0),
             QStringList(parameterList.mid(1)).join (QStringLiteral(" ")));
@@ -669,7 +685,7 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  QString channel(trailing);
 
             m_server->appendMessageToFrontmost(i18n("Invite"),
-                i18n("%1 invited you to channel %2.", sourceNick, channel)
+                i18n("%1 invited you to channel %2.", sourceNick, channel), messageTags
                 );
             emit invitation(sourceNick, channel);
         }
@@ -713,11 +729,11 @@ void InputFilter::parseClientCommand(const QString &prefix, const QString \
&comma  else
     {
         qDebug() << "unknown client command" << parameterList.count() << _plHad << _plWanted \
                << command << parameterList.join(QStringLiteral(" "));
-        m_server->appendMessageToFrontmost(command, parameterList.join(QStringLiteral(" ")));
+        m_server->appendMessageToFrontmost(command, parameterList.join(QStringLiteral(" ")), \
messageTags);  }
 }
 
-void InputFilter::parseServerCommand(const QString &prefix, const QString &command, \
QStringList &parameterList) +void InputFilter::parseServerCommand(const QString &prefix, const \
QString &command, QStringList &parameterList, QHash<QString, QString> messageTags)  {
     bool isNumeric;
     int numeric = command.toInt(&isNumeric);
@@ -762,19 +778,19 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
         else if (command == QStringLiteral("mode"))
         {
-            parseModes(prefix, parameterList);
+            parseModes(prefix, parameterList, messageTags);
         }
         else if (command == QStringLiteral("notice"))
         {
-            m_server->appendStatusMessage(i18n("Notice"), i18n("-%1- %2", prefix, trailing));
+            m_server->appendStatusMessage(i18n("Notice"), i18n("-%1- %2", prefix, trailing), \
messageTags);  }
         else if (command == QStringLiteral("kick") && plHas(3))
         {
-            m_server->nickWasKickedFromChannel(parameterList.value(1), parameterList.value(2), \
prefix, trailing); +            m_server->nickWasKickedFromChannel(parameterList.value(1), \
parameterList.value(2), prefix, trailing, messageTags);  }
         else if (command == QStringLiteral("privmsg"))
         {
-            parsePrivMsg(prefix, parameterList);
+            parsePrivMsg(prefix, parameterList, messageTags);
         }
         else if (command==QStringLiteral("cap") && plHas(3))
         {
@@ -825,7 +841,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
             else if (command == "ls" || command == "list")
             {
-                m_server->appendStatusMessage(i18n("Capabilities"), \
parameterList.mid(2).join(QStringLiteral(" "))); +                \
m_server->appendStatusMessage(i18n("Capabilities"), parameterList.mid(2).join(QStringLiteral(" \
")), messageTags);  }
         }
         else if (command == QStringLiteral("authenticate") && plHas(1))
@@ -837,7 +853,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  else
         {
             qDebug() << "unknown server command" << command;
-            m_server->appendMessageToFrontmost(command, parameterList.join(QStringLiteral(" \
"))); +            m_server->appendMessageToFrontmost(command, \
parameterList.join(QStringLiteral(" ")), messageTags);  }
     }
     else if (plHas(2)) //[0]==ourNick, [1] needs to be *something*
@@ -864,14 +880,14 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                         // re-set nickname, since the server may have truncated it
                         if (m_serverAssignedNick != m_server->getNickname())
                         {
-                            m_server->renameNick(m_server->getNickname(), \
m_serverAssignedNick); +                            \
m_server->renameNick(m_server->getNickname(), m_serverAssignedNick, messageTags);  }
 
                         // Send the welcome signal, so the server class knows we are connected \
properly  emit welcome(host);
                         m_connecting = true;
                     }
-                    m_server->appendStatusMessage(i18n("Welcome"), trailing);
+                    m_server->appendStatusMessage(i18n("Welcome"), trailing, messageTags);
                 }
                 break;
             }
@@ -884,7 +900,8 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  parameterList.value(1),
                          parameterList.value(2),
                          parameterList.value(3),
-                         parameterList.value(4))
+                         parameterList.value(4)),
+                        messageTags
                         );
 
                     QString allowed = m_server->allowedChannelModes();
@@ -906,7 +923,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(0)) //make the script happy
                 {
-                    m_server->appendStatusMessage(i18n("Support"), \
parameterList.join(QStringLiteral(" "))); +                    \
m_server->appendStatusMessage(i18n("Support"), parameterList.join(QStringLiteral(" ")), \
messageTags);  
                 // The following behaviour is neither documented in RFC 1459 nor in 2810-2813
                     // Nowadays, most ircds send server capabilities out via 005 (BOUNCE).
@@ -937,7 +954,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  m_server->setPrefixes(QString(), value);
                                 // XXX if ) isn't in the string, NOTHING should be there. \
anyone got a server  if (value.length() || property.length())
-                                    m_server->appendStatusMessage(QString(), \
QStringLiteral("XXX Server sent bad PREFIX in RPL_ISUPPORT, please report.")); +                \
m_server->appendStatusMessage(QString(), QStringLiteral("XXX Server sent bad PREFIX in \
RPL_ISUPPORT, please report."), messageTags);  }
                             else
                             {
@@ -1010,7 +1027,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     // TODO check this one... I amputated  + ' '+trailing
                     QString message=QString(QStringLiteral("%1 %2")).arg(i18n("Your personal \
                modes are:")).arg(parameterList.join(QLatin1Char(' ')).section(QLatin1Char(' \
                '),1));
-                    m_server->appendMessageToFrontmost(QStringLiteral("Info"), message);
+                    m_server->appendMessageToFrontmost(QStringLiteral("Info"), message, \
messageTags);  }
                 break;
             }
@@ -1058,12 +1075,12 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
QString &comma  } // endfor
                     if (!modesAre.isEmpty() && Preferences::self()->useLiteralModes())
                     {
-                        m_server->appendCommandMessageToChannel(parameterList.value(1), \
i18n("Mode"), message); +                        \
m_server->appendCommandMessageToChannel(parameterList.value(1), i18n("Mode"), message, \
messageTags);  }
                     else
                     {
                         m_server->appendCommandMessageToChannel(parameterList.value(1), \
                i18n("Mode"),
-                            i18n("Channel modes: ") + modesAre);
+                            i18n("Channel modes: ") + modesAre, messageTags);
                     }
                 }
                 break;
@@ -1073,7 +1090,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(3))
                 {
                     m_server->appendCommandMessageToChannel(parameterList.value(1), \
                i18n("URL"),
-                        i18n("Channel URL: %1", trailing));
+                        i18n("Channel URL: %1", trailing), messageTags);
                 }
                 break;
             }
@@ -1085,7 +1102,8 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  when.setTime_t(parameterList.value(2).toUInt());
                     m_server->appendCommandMessageToChannel(parameterList.value(1), \
i18n("Created"),  i18n("This channel was created on %1.",
-                            QLocale().toString(when, QLocale::ShortFormat))
+                            QLocale().toString(when, QLocale::ShortFormat)),
+                        messageTags
                         );
                 }
                 break;
@@ -1102,7 +1120,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // Display message only if this was not an automatic request.
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
== 0)  {
-                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is logged \
in as %2.", parameterList.value(1), parameterList.value(2)) ); +                        \
m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is logged in as %2.", \
parameterList.value(1), parameterList.value(2)), messageTags);  }
                 }
                 break;
@@ -1135,7 +1153,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // Display message only if this was not an automatic request.
                     if (getAutomaticRequest(QStringLiteral("NAMES"), parameterList.value(2)) \
== 0)  {
-                        m_server->appendMessageToFrontmost(i18n("Names"), trailing);
+                        m_server->appendMessageToFrontmost(i18n("Names"), trailing, \
messageTags);  }
                 }
                 break;
@@ -1152,7 +1170,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
                     else
                     {
-                        m_server->appendMessageToFrontmost(i18n("Names"), i18n("End of NAMES \
list.")); +                        m_server->appendMessageToFrontmost(i18n("Names"), i18n("End \
of NAMES list."), messageTags);  }
 
                     emit endOfNames(parameterList.value(1));
@@ -1165,7 +1183,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(2))
                 {
                     //this really has 3, but [2] is "No topic has been set"
-                    m_server->appendMessageToFrontmost(i18n("TOPIC"), i18n("The channel %1 has \
no topic set.", parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("TOPIC"), i18n("The channel %1 has no topic set.", \
parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -1182,11 +1200,11 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                     if (getAutomaticRequest(QStringLiteral("TOPIC"), parameterList.value(1)) \
== 0)  {
                         // Update channel window
-                        m_server->setChannelTopic(parameterList.value(1), topic);
+                        m_server->setChannelTopic(parameterList.value(1), topic, messageTags);
                     }
                     else
                     {
-                        m_server->appendMessageToFrontmost(i18n("Topic"), i18n("The channel \
topic for %1 is: \"%2\"", parameterList.value(1), topic)); +                        \
m_server->appendMessageToFrontmost(i18n("Topic"), i18n("The channel topic for %1 is: \"%2\"", \
parameterList.value(1), topic), messageTags);  }
                 }
                 break;
@@ -1205,6 +1223,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                         m_server->appendCommandMessageToChannel(parameterList.value(1), \
i18n("Topic"),  i18n("The topic was set by %1 on %2.",
                             parameterList.value(2), QLocale().toString(when, \
QLocale::ShortFormat)), +                            messageTags,
                             false,
                             false);
                     }
@@ -1213,7 +1232,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                         m_server->appendMessageToFrontmost(i18n("Topic"), i18n("The topic for \
%1 was set by %2 on %3.",  parameterList.value(1),
                             parameterList.value(2),
-                            QLocale().toString(when, QLocale::ShortFormat)),
+                            QLocale().toString(when, QLocale::ShortFormat)), messageTags,
                             false);
                         setAutomaticRequest(QStringLiteral("TOPIC"),parameterList.value(1), \
false);  }
@@ -1228,7 +1247,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // Display message only if this was not an automatic request.
                     if (getAutomaticRequest(QStringLiteral("WHOIS"),parameterList.value(1)) == \
0)  {
-                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is actually \
using the host %2.", parameterList.value(1), parameterList.value(2))); +                        \
m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is actually using the host %2.", \
parameterList.value(1), parameterList.value(2)), messageTags);  }
                 }
                 break;
@@ -1241,11 +1260,11 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                     // IP resolve purposes, and clear it from the automaticRequest list
                     if (getAutomaticRequest(QStringLiteral("DNS"), parameterList.value(1)) == \
0)  {
-                        m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: No such \
nick/channel.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: No such nick/channel.", \
parameterList.value(1)), messageTags);  }
                     else if(getAutomaticRequest(QStringLiteral("WHOIS"), \
parameterList.value(1)) == 0) //Display message only if this was not an automatic request.  {
-                        m_server->appendMessageToFrontmost(i18n("Error"), i18n("No such nick: \
%1.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("No such nick: %1.", \
                parameterList.value(1)), messageTags);
                         setAutomaticRequest(QStringLiteral("DNS"), parameterList.value(1), \
false);  }
                 }
@@ -1258,7 +1277,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // Display message only if this was not an automatic request.
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
== 0)  {
-                        m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: No such \
channel.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: No such channel.", \
parameterList.value(1)), messageTags);  }
                 }
                 break;
@@ -1271,7 +1290,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // if we are already connected, don't try tro find another nick ourselves
                     if (m_server->isConnected()) // Show message
                     {
-                        m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname \
already in use, try a different one.")); +                        \
m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname already in use, try a different \
one."), messageTags);  }
                     else // not connected yet, so try to find a nick that's not in use
                     {
@@ -1284,15 +1303,15 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                             if (m_server->isConnecting()) // ... or did they?
                                 m_server->disconnectServer();
                              else // No they didn't!
-                                 m_server->appendMessageToFrontmost(i18n("Info"), i18n("The \
nickname %1 was already in use, but the connection failed before you responded.", \
m_server->getNickname())); +                                 \
m_server->appendMessageToFrontmost(i18n("Info"), i18n("The nickname %1 was already in use, but \
the connection failed before you responded.", m_server->getNickname()), messageTags);  }
                         else
                         {
                             // Update Server window
                             m_server->obtainNickInfo(m_server->getNickname()) ;
-                            m_server->renameNick(m_server->getNickname(), newNick);
+                            m_server->renameNick(m_server->getNickname(), newNick, \
messageTags);  // Show message
-                            m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname \
already in use. Trying %1.", newNick)); +                            \
m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Nickname already in use. Trying %1.", \
newNick), messageTags);  // Send nickchange request to the server
                             m_server->queue(QStringLiteral("NICK ")+newNick);
                         }
@@ -1306,7 +1325,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     if (m_server->isConnected())
                     {                                 // We are already connected. Just print \
                the error message
-                        m_server->appendMessageToFrontmost(i18n("Nick"), trailing);
+                        m_server->appendMessageToFrontmost(i18n("Nick"), trailing, \
messageTags);  }
                     else                              // Find a new nick as in \
ERR_NICKNAMEINUSE  {
@@ -1320,8 +1339,8 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  else
                         {
                             m_server->obtainNickInfo(m_server->getNickname()) ;
-                            m_server->renameNick(m_server->getNickname(), newNick);
-                            m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Erroneous \
nickname. Changing nick to %1.", newNick)); +                            \
m_server->renameNick(m_server->getNickname(), newNick, messageTags); +                          \
m_server->appendMessageToFrontmost(i18n("Nick"), i18n("Erroneous nickname. Changing nick to \
                %1.", newNick), messageTags);
                             m_server->queue(QStringLiteral("NICK ")+newNick);
                         }
                     }
@@ -1332,7 +1351,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("You are not on \
%1.", parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("You are not on %1.", \
                parameterList.value(1)), messageTags);
                     setAutomaticRequest(QStringLiteral("TOPIC"),parameterList.value(1), \
false);  
                 }
@@ -1343,7 +1362,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(1))
                 {
                     if (!m_connecting || !Preferences::self()->skipMOTD())
-                    m_server->appendStatusMessage(i18n("MOTD"), i18n("Message of the day:"));
+                    m_server->appendStatusMessage(i18n("MOTD"), i18n("Message of the day:"), \
messageTags);  }
                 break;
             }
@@ -1352,7 +1371,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(2))
                 {
                     if (!m_connecting || !Preferences::self()->skipMOTD())
-                        m_server->appendStatusMessage(i18n("MOTD"), trailing);
+                        m_server->appendStatusMessage(i18n("MOTD"), trailing, messageTags);
                 }
                 break;
             }
@@ -1361,7 +1380,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(1))
                 {
                     if (!m_connecting || !Preferences::self()->skipMOTD())
-                        m_server->appendStatusMessage(i18n("MOTD"), i18n("End of message of \
the day")); +                        m_server->appendStatusMessage(i18n("MOTD"), i18n("End of \
message of the day"), messageTags);  
                     if (m_connecting)
                         m_server->autoCommandsAndChannels();
@@ -1385,7 +1404,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("You need to be a \
channel operator in %1 to do that.", parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("You need to be a channel operator in %1 \
to do that.", parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -1393,7 +1412,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(1))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Notice"), i18n("You are now an \
IRC operator on this server.")); +                    \
m_server->appendMessageToFrontmost(i18n("Notice"), i18n("You are now an IRC operator on this \
server."), messageTags);  }
                 break;
             }
@@ -1401,7 +1420,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendStatusMessage(i18n("Info"), i18n("'%1' is now your hidden \
host (set by services).", parameterList.value(1))); +                    \
m_server->appendStatusMessage(i18n("Info"), i18n("'%1' is now your hidden host (set by \
services).", parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -1411,7 +1430,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     QString current(trailing.section(QLatin1Char(' '),3));
                     //QString max(trailing.section(' ',5,5));
-                    m_server->appendStatusMessage(i18n("Users"), i18n("Current users on the \
network: %1", current)); +                    m_server->appendStatusMessage(i18n("Users"), \
i18n("Current users on the network: %1", current), messageTags);  }
                 break;
             }
@@ -1421,7 +1440,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     QString current(trailing.section(QLatin1Char(' '), 3));
                     //QString max(trailing.section(' ',5,5));
-                    m_server->appendStatusMessage(i18n("Users"), i18n("Current users on %1: \
%2.", prefix, current)); +                    m_server->appendStatusMessage(i18n("Users"), \
i18n("Current users on %1: %2.", prefix, current), messageTags);  }
                 break;
             }
@@ -1452,7 +1471,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
== 0)  {
                         m_server->appendMessageToFrontmost(i18n("Away"),
-                            i18n("%1 is away: %2", parameterList.value(1), trailing)
+                            i18n("%1 is away: %2", parameterList.value(1), trailing), \
messageTags  );
                     }
                 }
@@ -1464,7 +1483,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     m_server->appendMessageToFrontmost(i18n("Invite"),
                             i18n("You invited %1 to channel %2.",
-                            parameterList.value(1), parameterList.value(2))
+                            parameterList.value(1), parameterList.value(2)), messageTags
                         );
                 }
                 break;
@@ -1499,7 +1518,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  parameterList.value(1),
                                 parameterList.value(2),
                                 parameterList.value(3),
-                                escapedRealName), false);   // Don't parse any urls
+                                escapedRealName), messageTags, false);   // Don't parse any \
urls  }
                     else
                     {
@@ -1514,7 +1533,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                                     i18n("Resolved %1 (%2) to address: %3",
                                         parameterList.value(1),
                                         parameterList.value(3),
-                                        ip)
+                                        ip), messageTags
                                     );
                             }
                             else
@@ -1522,7 +1541,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                                 m_server->appendMessageToFrontmost(i18n("Error"),
                                     i18n("Unable to resolve address for %1 (%2)",
                                         parameterList.value(1),
-                                        parameterList.value(3))
+                                        parameterList.value(3)), messageTags
                                     );
                             }
 
@@ -1550,7 +1569,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  // Prints "psn is an identified user"
                         //server->appendStatusMessage(i18n("Whois"),parameterList.join(" \
                ").section(' ',1)+' '+trailing);
                         // The above line works fine, but can't be i18n'ised. So use the below \
                instead.. I hope this is okay.
-                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an \
identified user.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an identified user.", \
parameterList.value(1)), messageTags);  }
                 }
                 break;
@@ -1560,7 +1579,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(2))
                 {
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
                == 0)
-                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is using a \
secure connection.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is using a secure connection.", \
parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -1602,7 +1621,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  parameterList.value(2),
                                     parameterList.value(3),
                                     trailing.section(QLatin1Char(' '), 1),
-                                    bAway?i18n(" (Away)"):QString()),
+                                    bAway?i18n(" (Away)"):QString()), messageTags,
                                 false); // Don't parse as url
                         }
                     }
@@ -1624,7 +1643,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                                 m_server->appendMessageToFrontmost(i18n("Who"),
                                     i18n("End of /WHO list for %1",
-                                        parameterList.value(1)));
+                                        parameterList.value(1)), messageTags);
                             }
                             else
                             {
@@ -1711,42 +1730,42 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 is a user on channels: %2",
                                     parameterList.value(1),
-                                    userChannels.join(QStringLiteral(" ")))
+                                    userChannels.join(QStringLiteral(" "))), messageTags
                                 );
                         }
                         if (voiceChannels.count())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 has voice on channels: %2",
-                                    parameterList.value(1), \
voiceChannels.join(QStringLiteral(" "))) +                                    \
parameterList.value(1), voiceChannels.join(QStringLiteral(" "))), messageTags  );
                         }
                         if (halfopChannels.count())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 is a halfop on channels: %2",
-                                    parameterList.value(1), \
halfopChannels.join(QStringLiteral(" "))) +                                    \
parameterList.value(1), halfopChannels.join(QStringLiteral(" "))), messageTags  );
                         }
                         if (opChannels.count())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 is an operator on channels: %2",
-                                    parameterList.value(1), opChannels.join(QStringLiteral(" \
"))) +                                    parameterList.value(1), \
opChannels.join(QStringLiteral(" "))), messageTags  );
                         }
                         if (ownerChannels.count())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 is owner of channels: %2",
-                                    parameterList.value(1), \
ownerChannels.join(QStringLiteral(" "))) +                                    \
parameterList.value(1), ownerChannels.join(QStringLiteral(" "))), messageTags  );
                         }
                         if (adminChannels.count())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 is admin on channels: %2",
-                                    parameterList.value(1), \
adminChannels.join(QStringLiteral(" "))) +                                    \
parameterList.value(1), adminChannels.join(QStringLiteral(" "))), messageTags  );
                         }
                     }
@@ -1772,7 +1791,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                         m_server->appendMessageToFrontmost(i18n("Whois"),
                             i18n("%1 is online via %2 (%3).", parameterList.value(1),
-                                parameterList.value(2), trailing)
+                                parameterList.value(2), trailing), messageTags
                             );
                     }
                 }
@@ -1787,7 +1806,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                         m_server->appendMessageToFrontmost(i18n("Whois"),
                             i18n("%1 is available for help.",
-                                parameterList.value(1))
+                                parameterList.value(1)), messageTags
                             );
                     }
                 }
@@ -1801,9 +1820,9 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
== 0)  {
                         if (trailing.toLower().simplified().startsWith(QLatin1String("is an \
                irc operator")))
-                            m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an \
IRC Operator.", parameterList.value(1))); +                            \
m_server->appendMessageToFrontmost(i18n("Whois"), i18n("%1 is an IRC Operator.", \
parameterList.value(1)), messageTags);  else
-                            m_server->appendMessageToFrontmost(i18n("Whois"), \
QString(QStringLiteral("%1 %2")).arg(parameterList.value(1)).arg(trailing)); +                  \
m_server->appendMessageToFrontmost(i18n("Whois"), QString(QStringLiteral("%1 \
%2")).arg(parameterList.value(1)).arg(trailing), messageTags);  }
                 }
                 break;
@@ -1850,7 +1869,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                                 i18nc("%1 = name of person, %2 = (x days), %3 = (x hours), %4 \
                = (x minutes), %5 = (x seconds)",
                                     "%1 has been idle for %2, %3, %4, and %5.",
                                     parameterList.value(1),
-                                    daysString, hoursString, minutesString, secondsString));
+                                    daysString, hoursString, minutesString, secondsString), \
messageTags);  // or longer than an hour
                         }
                         else if (hours)
@@ -1861,7 +1880,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18nc("%1 = name of person, %2 = (x hours), %3 = (x minutes), \
                %4 = (x seconds)",
                                     "%1 has been idle for %2, %3, and %4.", \
                parameterList.value(1), hoursString,
-                                    minutesString, secondsString));
+                                    minutesString, secondsString), messageTags);
                             // or longer than a minute
                         }
                         else if (minutes)
@@ -1870,20 +1889,20 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                             const QString secondsString = i18np("1 second", "%1 seconds", \
                (seconds % 60));
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18nc("%1 = name of person, %2 = (x minutes), %3 = (x \
                seconds)",
-                                    "%1 has been idle for %2 and %3.", parameterList.value(1), \
minutesString, secondsString)); +                                    "%1 has been idle for %2 \
and %3.", parameterList.value(1), minutesString, secondsString), messageTags);  // or just some \
seconds  }
                         else
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
-                            i18np("%2 has been idle for 1 second.", "%2 has been idle for %1 \
seconds.", seconds, parameterList.value(1))); +                            i18np("%2 has been \
idle for 1 second.", "%2 has been idle for %1 seconds.", seconds, parameterList.value(1)), \
messageTags);  }
 
                         if (!signonTime.isNull())
                         {
                             m_server->appendMessageToFrontmost(i18n("Whois"),
                                 i18n("%1 has been online since %2.",
-                                parameterList.value(1), QLocale().toString(signonTime, \
QLocale::ShortFormat))); +                                parameterList.value(1), \
QLocale().toString(signonTime, QLocale::ShortFormat)), messageTags);  }
                     }
                 }
@@ -1899,7 +1918,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                     // Display message only if this was not an automatic request.
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
== 0)  {
-                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("End of WHOIS \
list.")); +                        m_server->appendMessageToFrontmost(i18n("Whois"), i18n("End \
of WHOIS list."), messageTags);  }
                     // was this an automatic request?
                     if (getAutomaticRequest(QStringLiteral("WHOIS"), parameterList.value(1)) \
!= 0) @@ -1944,7 +1963,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
QString &comma  nick,
                                 (ircOp) ? i18n(" (IRC Operator)") : QString()
                                 ,mask,
-                                (away) ? i18n(" (away)") : QString()));
+                                (away) ? i18n(" (away)") : QString()), messageTags);
                         }
 
                         // was this an automatic request?
@@ -1962,7 +1981,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                     if (getAutomaticRequest(QStringLiteral("LIST"),QString())==0)
                     {
-                        m_server->appendMessageToFrontmost(i18n("List"), i18n("List of \
channels:")); +                        m_server->appendMessageToFrontmost(i18n("List"), \
i18n("List of channels:"), messageTags);  }
                 }
                 break;
@@ -1975,7 +1994,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                         QString message;
                         message=i18np("%2 (%1 user): %3", "%2 (%1 users): %3", \
                parameterList.value(2).toInt(), parameterList.value(1), trailing);
-                        m_server->appendMessageToFrontmost(i18n("List"), message);
+                        m_server->appendMessageToFrontmost(i18n("List"), message, \
messageTags);  }
                     else                              // send them to /LIST window
                     {
@@ -1991,7 +2010,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  // was this an automatic request?
                     if (getAutomaticRequest(QStringLiteral("LIST"),QString())==0)
                     {
-                        m_server->appendMessageToFrontmost(i18n("List"), i18n("End of channel \
list.")); +                        m_server->appendMessageToFrontmost(i18n("List"), i18n("End \
of channel list."), messageTags);  }
                     else
                     {
@@ -2011,7 +2030,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  nickInfo->setAway(true);
                     }
 
-                    m_server->setAway(true);
+                    m_server->setAway(true, messageTags);
                 }
                 break;
             }
@@ -2027,7 +2046,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  nickInfo->setAwayMessage(QString());
                     }
 
-                    m_server->setAway(false);
+                    m_server->setAway(false, messageTags);
                 }
                 break;
             }
@@ -2052,7 +2071,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  
                         m_server->appendMessageToFrontmost(i18n("BanList:%1", \
                parameterList.value(1)),
                                     i18nc("BanList message: e.g. *!*@aol.com set by MrGrim on \
                <date>", "%1 set by %2 on %3",
-                                        parameterList.value(2), setter, \
QLocale().toString(when, QLocale::ShortFormat)) +                                        \
parameterList.value(2), setter, QLocale().toString(when, QLocale::ShortFormat)), messageTags  \
);  }
                 }
@@ -2068,7 +2087,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
                     else
                     {
-                        m_server->appendMessageToFrontmost(i18n("BanList:%1", \
parameterList.value(1)), i18n("End of Ban List.")); +                        \
m_server->appendMessageToFrontmost(i18n("BanList:%1", parameterList.value(1)), i18n("End of Ban \
List."), messageTags);  }
                 }
                 break;
@@ -2080,11 +2099,11 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
                QString &comma
                     ChatWindow *chatwindow = \
m_server->getChannelByName(parameterList.value(1));  if (chatwindow)
                     {
-                        chatwindow->appendServerMessage(i18n("Channel"), trailing);
+                        chatwindow->appendServerMessage(i18n("Channel"), trailing, \
messageTags);  }
                     else // We couldn't join the channel , so print the error. with [#channel] \
: <Error Message>  {
-                        m_server->appendMessageToFrontmost(i18n("Channel"), trailing);
+                        m_server->appendMessageToFrontmost(i18n("Channel"), trailing, \
messageTags);  }
                 }
                 break;
@@ -2104,7 +2123,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
                     else
                     {
-                        m_server->appendMessageToFrontmost(i18n("Error"), i18n("No such \
server: %1.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("No such server: %1.", \
parameterList.value(1)), messageTags);  }
                 }
                 break;
@@ -2114,7 +2133,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  if (plHas(2))
                 {
                     if (m_server->isConnected())
-                        m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1 is \
currently unavailable.", parameterList.value(1))); +                        \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1 is currently unavailable.", \
parameterList.value(1)), messageTags);  else
                     {
                         QString newNick = m_server->getNextNickname();
@@ -2125,9 +2144,9 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  else
                         {
                             m_server->obtainNickInfo(m_server->getNickname()) ;
-                            m_server->renameNick(m_server->getNickname(), newNick);
+                            m_server->renameNick(m_server->getNickname(), newNick, \
                messageTags);
                             m_server->appendMessageToFrontmost(i18n("Nick"),
-                                i18n("Nickname %1 is unavailable. Trying %2.", \
parameterList.value(1), newNick)); +                                i18n("Nickname %1 is \
                unavailable. Trying %2.", parameterList.value(1), newNick), messageTags);
                             m_server->queue(QStringLiteral("NICK ")+newNick);
                         }
                     }
@@ -2143,7 +2162,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
             { // TODO make sure this works, i amputated the "+ ' '+trailing"
                 if (plHas(0))
                 {
-                    m_server->appendStatusMessage(i18n("Users"), \
parameterList.join(QStringLiteral(" ")).section(QLatin1Char(' '),1)); +                    \
m_server->appendStatusMessage(i18n("Users"), parameterList.join(QStringLiteral(" \
")).section(QLatin1Char(' '),1), messageTags);  }
                 break;
             }
@@ -2151,7 +2170,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: Unknown \
command.", parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: Unknown command.", \
parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -2159,7 +2178,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(0))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("Not \
registered.")); +                    m_server->appendMessageToFrontmost(i18n("Error"), \
i18n("Not registered."), messageTags);  }
                 break;
             }
@@ -2167,7 +2186,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: This command \
requires more parameters.", parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("%1: This command requires more \
parameters.", parameterList.value(1)), messageTags);  }
                 break;
             }
@@ -2182,7 +2201,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
                     else // TEST is this right? split the logic up in prep for slotization
                     {
-                        m_server->appendMessageToFrontmost(command, \
parameterList.join(QStringLiteral(" ")).section(QLatin1Char(' '),1) + QLatin1Char(' \
')+trailing); +                        m_server->appendMessageToFrontmost(command, \
parameterList.join(QStringLiteral(" ")).section(QLatin1Char(' '),1) + QLatin1Char(' \
')+trailing, messageTags);  }
                 }
                 break;
@@ -2191,14 +2210,14 @@ void InputFilter::parseServerCommand(const QString &prefix, const \
QString &comma  {
                 if (plHas(2))
                 {
-                    m_server->appendMessageToFrontmost(i18n("Error"), i18n("Cannot join %1: \
The channel is password-protected and either a wrong or no password was given.", \
parameterList.value(1))); +                    \
m_server->appendMessageToFrontmost(i18n("Error"), i18n("Cannot join %1: The channel is \
password-protected and either a wrong or no password was given.", parameterList.value(1)), \
messageTags);  }
                 break;
             }
             case RPL_LOGGEDIN:
             {
                 if (plHas(3))
-                    m_server->appendStatusMessage(i18n("Info"), i18n("You are now logged in as \
%1.", parameterList.value(2))); +                    \
m_server->appendStatusMessage(i18n("Info"), i18n("You are now logged in as %1.", \
parameterList.value(2)), messageTags);  
                 break;
             }
@@ -2206,7 +2225,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendStatusMessage(i18n("Info"), i18n("SASL authentication \
successful.")); +                    m_server->appendStatusMessage(i18n("Info"), i18n("SASL \
authentication successful."), messageTags);  m_server->capEndNegotiation();
 
                     NickInfoPtr nickInfo = m_server->getNickInfo(m_server->getNickname());
@@ -2219,7 +2238,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  {
                 if (plHas(2))
                 {
-                    m_server->appendStatusMessage(i18n("Error"), i18n("SASL authentication \
attempt failed.")); +                    m_server->appendStatusMessage(i18n("Error"), \
i18n("SASL authentication attempt failed."), messageTags);  m_server->capEndNegotiation();
                 }
 
@@ -2228,7 +2247,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  case ERR_SASLABORTED:
             {
                 if (plHas(2))
-                    m_server->appendStatusMessage(i18n("Info"), i18n("SASL authentication \
aborted.")); +                    m_server->appendStatusMessage(i18n("Info"), i18n("SASL \
authentication aborted."), messageTags);  
                 break;
             }
@@ -2237,7 +2256,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
                &comma
                 // All yet unknown messages go into the frontmost window without the
                 // preceding nickname
                 qDebug() << "unknown numeric" << parameterList.count() << _plHad << _plWanted \
                << command << parameterList.join(QStringLiteral(" "));
-                m_server->appendMessageToFrontmost(command, \
parameterList.join(QStringLiteral(" "))); +                \
m_server->appendMessageToFrontmost(command, parameterList.join(QStringLiteral(" ")), \
messageTags);  }
         } // end of numeric switch
         if (!_plHad)
@@ -2249,7 +2268,7 @@ void InputFilter::parseServerCommand(const QString &prefix, const QString \
&comma  }
 } // end of server
 
-void InputFilter::parseModes(const QString &sourceNick, const QStringList &parameterList)
+void InputFilter::parseModes(const QString &sourceNick, const QStringList &parameterList, \
const QHash<QString, QString> &messageTags)  {
     const QString modestring=parameterList.value(1);
 
@@ -2268,7 +2287,7 @@ void InputFilter::parseModes(const QString &sourceNick, const QStringList \
&param  }
         }
         if (!message.isEmpty())
-            m_server->appendStatusMessage(i18n("Mode"), message);
+            m_server->appendStatusMessage(i18n("Mode"), message, messageTags);
         return;
     }
 
@@ -2316,13 +2335,13 @@ void InputFilter::parseModes(const QString &sourceNick, const \
                QStringList &param
                 qDebug()   << "in updateChannelMode.  sourceNick: '" << sourceNick << "'  \
parameterlist: '"  << parameterList.join(QStringLiteral(", ")) << "'";
             }
-            m_server->updateChannelMode(sourceNick, parameterList.value(0), mode, plus, \
parameter); +            m_server->updateChannelMode(sourceNick, parameterList.value(0), mode, \
plus, parameter, messageTags);  }
     } // endfor
 
     if (Preferences::self()->useLiteralModes())
     {
-        m_server->appendCommandMessageToChannel(parameterList.value(0), i18n("Mode"), \
message); +        m_server->appendCommandMessageToChannel(parameterList.value(0), \
i18n("Mode"), message, messageTags);  }
 }
 
@@ -2384,7 +2403,7 @@ void InputFilter::setLagMeasuring(bool state) { m_lagMeasuring=state; }
 
 bool InputFilter::getLagMeasuring()           { return m_lagMeasuring; }
 
-void InputFilter::parsePrivMsg(const QString& prefix, QStringList& parameterList)
+void InputFilter::parsePrivMsg(const QString& prefix, QStringList& parameterList, const \
QHash<QString, QString> &messageTags)  {
     int pos = prefix.indexOf(QLatin1Char('!'));
     QString source;
@@ -2418,7 +2437,7 @@ void InputFilter::parsePrivMsg(const QString& prefix, QStringList& \
parameterList  label = parameterList.value(0);
                 }
 
-                channel->append(source, message, label);
+                channel->append(source, message, messageTags, label);
 
                 if(source != m_server->getNickname())
                 {
@@ -2451,7 +2470,7 @@ void InputFilter::parsePrivMsg(const QString& prefix, QStringList& \
                parameterList
             Query* query = m_server->addQuery(nickinfo, false /*we didn't initiate this*/ );
 
             // send action to query
-            query->appendQuery(source, message);
+            query->appendQuery(source, message, messageTags);
 
             if(source != m_server->getNickname() && query)
             {
@@ -2474,7 +2493,21 @@ void InputFilter::parsePrivMsg(const QString& prefix, QStringList& \
parameterList  }
 }
 
+QHash<QString, QString> InputFilter::parseMessageTags(const QString &line, int \
*startOfMessage) +{
+    int index = line.indexOf(QLatin1Char(' '));
+    *startOfMessage = index + 1;
+    QStringList tags = line.mid(1, index - 1).split(QLatin1Char(';'));
+    QHash<QString, QString> tagHash;
+
+    foreach(const QString &tag, tags)
+    {
+        QStringList tagList = tag.split(QLatin1Char('='));
+        tagHash.insert(tagList.first(), tagList.last());
+    }
 
+    return tagHash;
+}
 
 // kate: space-indent on; tab-width 4; indent-width 4; mixed-indent off; replace-tabs on;
 // vim: set et sw=4 ts=4 cino=l1,cs,U1:
diff --git a/src/irc/inputfilter.h b/src/irc/inputfilter.h
index 6452452..d02af1b 100644
--- a/src/irc/inputfilter.h
+++ b/src/irc/inputfilter.h
@@ -77,10 +77,12 @@ class InputFilter : public QObject
         void addDccChat(const QString& nick,const QStringList& arguments);
 
     protected:
-        void parseClientCommand(const QString &prefix, const QString &command, QStringList \
                &parameterList);
-        void parseServerCommand(const QString &prefix, const QString &command, QStringList \
                &parameterList);
-        void parseModes(const QString &sourceNick, const QStringList &parameterList);
-        void parsePrivMsg(const QString& prefix, QStringList& parameterList);
+        void parseClientCommand(const QString &prefix, const QString &command, QStringList \
&parameterList, QHash<QString, QString> messageTags); +        void parseServerCommand(const \
QString &prefix, const QString &command, QStringList &parameterList, QHash<QString, QString> \
messageTags); +        void parseModes(const QString &sourceNick, const QStringList \
&parameterList, const QHash<QString, QString> &messageTags); +        void parsePrivMsg(const \
QString& prefix, QStringList& parameterList, const QHash<QString, QString> &messageTags); +
+        QHash<QString, QString> parseMessageTags(const QString &line, int *startOfMessage);
 
         bool isAChannel(const QString &check);
         bool isIgnore(const QString &pattern, Ignore::Type type);
diff --git a/src/irc/query.cpp b/src/irc/query.cpp
index 0399f43..8c1845e 100644
--- a/src/irc/query.cpp
+++ b/src/irc/query.cpp
@@ -455,14 +455,14 @@ void Query::emitUpdateInfo()
 }
 
 // show quit message of nick if we see it
-void Query::quitNick(const QString& reason)
+void Query::quitNick(const QString& reason, const QHash<QString, QString> &messageTags)
 {
     QString displayReason = reason;
 
     if (displayReason.isEmpty())
     {
         appendCommandMessage(i18nc("Message type", "Quit"), i18nc("%1 = nick, %2 = hostmask", \
                "%1 (%2) has left this server.",
-            getName(), getNickInfo()->getHostmask()), false);
+            getName(), getNickInfo()->getHostmask()), messageTags, false);
     }
     else
     {
@@ -470,7 +470,7 @@ void Query::quitNick(const QString& reason)
             displayReason+=QStringLiteral("\017");
 
         appendCommandMessage(i18nc("Message type", "Quit"), i18nc("%1 = nick, %2 = hostmask, \
                %3 = reason", "%1 (%2) has left this server (%3).",
-            getName(), getNickInfo()->getHostmask(), displayReason), false);
+            getName(), getNickInfo()->getHostmask(), displayReason), messageTags, false);
     }
 }
 
diff --git a/src/irc/query.h b/src/irc/query.h
index eb2251d..09537c0 100644
--- a/src/irc/query.h
+++ b/src/irc/query.h
@@ -67,7 +67,7 @@ class Query : public ChatWindow
         /** call this when you see a nick quit from the server.
          *  @param reason The quit reason given by that user.
          */
-        void quitNick(const QString& reason);
+        void quitNick(const QString& reason, const QHash<QString, QString> &messageTags);
 
         #ifdef HAVE_QCA2
         Konversation::Cipher* getCipher();
diff --git a/src/irc/server.cpp b/src/irc/server.cpp
index 1cc04b3..905d806 100644
--- a/src/irc/server.cpp
+++ b/src/irc/server.cpp
@@ -90,6 +90,7 @@ Server::Server(QObject* parent, ConnectionSettings& settings) : \
QObject(parent)  m_hasAwayNotify = false;
     m_hasExtendedJoin = false;
     m_hasWHOX = false;
+    m_hasServerTime = false;
 
     m_nickIndices.clear();
     m_nickIndices.append(0);
@@ -720,6 +721,12 @@ void Server::capInitiateNegotiation(bool useSASL)
     queue(QStringLiteral("CAP REQ :extended-join"), HighPriority);
     m_hasExtendedJoin = false;
     m_capRequested++;
+
+    queue(QStringLiteral("CAP REQ :server-time"), HighPriority);
+    m_hasServerTime = false;
+    m_capRequested++;
+    queue(QStringLiteral("CAP REQ :znc.in/server-time-iso"), HighPriority);
+    m_capRequested++;
 }
 
 void Server::capReply()
@@ -759,6 +766,10 @@ void Server::capAcknowledged(const QString& name, Server::CapModifiers \
modifiers  {
         m_hasExtendedJoin = true;
     }
+    else if (name == QStringLiteral("server-time") || name == \
QStringLiteral("znc.in/server-time-iso")) +    {
+        m_hasServerTime = true;
+    }
 }
 
 void Server::capDenied(const QString& name)
@@ -2758,7 +2769,7 @@ void Server::sendJoinCommand(const QString& name, const QString& \
password)  queue(result.toServer);
 }
 
-Channel* Server::joinChannel(const QString& name, const QString& hostmask)
+Channel* Server::joinChannel(const QString& name, const QString& hostmask, const \
QHash<QString, QString> &messageTags)  {
     // (re-)join channel, open a new panel if needed
     Channel* channel = getChannelByName(name);
@@ -2793,7 +2804,7 @@ Channel* Server::joinChannel(const QString& name, const QString& \
hostmask)  nickInfo->setHostmask(hostmask);
     }
 
-    channel->joinNickname(channelNick);
+    channel->joinNickname(channelNick, messageTags);
 
     return channel;
 }
@@ -2817,13 +2828,13 @@ void Server::removeChannel(Channel* channel)
         updateAutoJoin();
 }
 
-void Server::updateChannelMode(const QString &updater, const QString &channelName, char mode, \
bool plus, const QString &parameter) +void Server::updateChannelMode(const QString &updater, \
const QString &channelName, char mode, bool plus, const QString &parameter, const \
QHash<QString, QString> &messageTags)  {
 
     Channel* channel=getChannelByName(channelName);
 
     if(channel)                                   //Let the channel be verbose to the screen \
                about the change, and update channelNick
-        channel->updateMode(updater, mode, plus, parameter);
+        channel->updateMode(updater, mode, plus, parameter, messageTags);
     // TODO: What is mode character for owner?
     // Answer from JOHNFLUX - I think that admin is the same as owner.  Channel.h has owner as \
"a"  // "q" is the likely answer.. UnrealIRCd and euIRCd use it.
@@ -3067,7 +3078,7 @@ NickInfoPtr Server::setWatchedNickOnline(const QString& nickname)
 
     emit watchedNickChanged(this, nickname, true);
 
-    appendMessageToFrontmost(i18nc("Message type", "Notify"), i18n("%1 is online (%2).", \
nickname, getServerName()), getStatusView()); +    appendMessageToFrontmost(i18nc("Message \
type", "Notify"), i18n("%1 is online (%2).", nickname, getServerName()), QHash<QString, \
QString>(), getStatusView());  
     Application::instance()->notificationHandler()->nickOnline(getStatusView(), nickname);
 
@@ -3081,7 +3092,7 @@ void Server::setWatchedNickOffline(const QString& nickname, const \
NickInfoPtr ni  
     emit watchedNickChanged(this, nickname, false);
 
-    appendMessageToFrontmost(i18nc("Message type", "Notify"), i18n("%1 went offline (%2).", \
nickname, getServerName()), getStatusView()); +    appendMessageToFrontmost(i18nc("Message \
type", "Notify"), i18n("%1 went offline (%2).", nickname, getServerName()), QHash<QString, \
QString>(), getStatusView());  
     Application::instance()->notificationHandler()->nickOffline(getStatusView(), nickname);
 
@@ -3331,7 +3342,8 @@ void Server::renameNickInfo(NickInfoPtr nickInfo, const QString& newname)
     }
 }
 
-Channel* Server::nickJoinsChannel(const QString &channelName, const QString &nickname, const \
QString &hostmask, const QString &account, const QString &realName) +Channel* \
Server::nickJoinsChannel(const QString &channelName, const QString &nickname, const QString \
&hostmask, const QString &account, +                                  const QString &realName, \
const QHash<QString, QString> &messageTags)  {
     Channel* outChannel = getChannelByName(channelName);
     if(outChannel)
@@ -3351,7 +3363,7 @@ Channel* Server::nickJoinsChannel(const QString &channelName, const \
QString &nic  {
             nickInfo->setRealName(realName);
         }
-        outChannel->joinNickname(channelNick);
+        outChannel->joinNickname(channelNick, messageTags);
     }
 
     return outChannel;
@@ -3370,7 +3382,7 @@ void Server::addHostmaskToNick(const QString& sourceNick, const QString& \
sourceH  }
 }
 
-Channel* Server::removeNickFromChannel(const QString &channelName, const QString &nickname, \
const QString &reason, bool quit) +Channel* Server::removeNickFromChannel(const QString \
&channelName, const QString &nickname, const QString &reason, const QHash<QString, QString> \
&messageTags, bool quit)  {
     Channel* outChannel = getChannelByName(channelName);
     if(outChannel)
@@ -3379,7 +3391,7 @@ Channel* Server::removeNickFromChannel(const QString &channelName, const \
                QString
         ChannelNickPtr channelNick = getChannelNick(channelName, nickname);
         if(channelNick)
         {
-            outChannel->removeNick(channelNick,reason,quit);
+            outChannel->removeNick(channelNick,reason,quit, messageTags);
         }
     }
 
@@ -3397,7 +3409,7 @@ Channel* Server::removeNickFromChannel(const QString &channelName, const \
QString  return outChannel;
 }
 
-void Server::nickWasKickedFromChannel(const QString &channelName, const QString &nickname, \
const QString &kicker, const QString &reason) +void Server::nickWasKickedFromChannel(const \
QString &channelName, const QString &nickname, const QString &kicker, const QString &reason, \
const QHash<QString, QString> &messageTags)  {
     Channel* outChannel = getChannelByName(channelName);
     if(outChannel)
@@ -3407,32 +3419,32 @@ void Server::nickWasKickedFromChannel(const QString &channelName, const \
QString  
         if(channelNick)
         {
-          outChannel->kickNick(channelNick, kicker, reason);
+          outChannel->kickNick(channelNick, kicker, reason, messageTags);
           // Tell Nickinfo
           removeChannelNick(channelName,nickname);
         }
     }
 }
 
-void Server::removeNickFromServer(const QString &nickname,const QString &reason)
+void Server::removeNickFromServer(const QString &nickname,const QString &reason, const \
QHash<QString, QString> &messageTags)  {
     foreach (Channel* channel, m_channelList)
     {
         channel->flushNickQueue();
         // Check if nick is in this channel or not.
         if(channel->getNickByName(nickname))
-            removeNickFromChannel(channel->getName(),nickname,reason,true);
+            removeNickFromChannel(channel->getName(), nickname, reason, messageTags, true);
     }
 
     Query* query = getQueryByName(nickname);
-    if (query) query->quitNick(reason);
+    if (query) query->quitNick(reason, messageTags);
 
     // Delete the nick from all channels and then delete the nickinfo,
     // emitting signal if on the watch list.
     setNickOffline(nickname);
 }
 
-void Server::renameNick(const QString &nickname, const QString &newNick)
+void Server::renameNick(const QString &nickname, const QString &newNick, const QHash<QString, \
QString> &messageTags)  {
     if(nickname.isEmpty() || newNick.isEmpty())
     {
@@ -3462,7 +3474,7 @@ void Server::renameNick(const QString &nickname, const QString &newNick)
             channel->flushNickQueue();
 
             // All we do is notify that the nick has been renamed.. we haven't actually \
                renamed it yet
-            if (channel->getNickByName(nickname)) channel->nickRenamed(nickname, *nickInfo);
+            if (channel->getNickByName(nickname)) channel->nickRenamed(nickname, *nickInfo, \
messageTags);  }
 
         //Watched nicknames stuff
@@ -3511,33 +3523,33 @@ void Server::gotOwnResolvedHostByUserhost(const QHostInfo& res)
         qDebug() << "Got error: " << res.errorString();
 }
 
-void Server::appendServerMessageToChannel(const QString& channel,const QString& type,const \
QString& message) +void Server::appendServerMessageToChannel(const QString& channel,const \
QString& type,const QString& message, const QHash<QString, QString> &messageTags)  {
     Channel* outChannel = getChannelByName(channel);
-    if (outChannel) outChannel->appendServerMessage(type,message);
+    if (outChannel) outChannel->appendServerMessage(type, message, messageTags);
 }
 
-void Server::appendCommandMessageToChannel(const QString& channel,const QString& command,const \
QString& message, bool highlight, bool parseURL) +void \
Server::appendCommandMessageToChannel(const QString& channel, const QString& command, const \
QString& message, const QHash<QString, QString> &messageTags, bool highlight, bool parseURL)  {
     Channel* outChannel = getChannelByName(channel);
     if (outChannel)
     {
-        outChannel->appendCommandMessage(command,message,parseURL,!highlight);
+        outChannel->appendCommandMessage(command, message, messageTags, parseURL, !highlight);
     }
     else
     {
-        appendStatusMessage(command, QString(QStringLiteral("%1 \
%2")).arg(channel).arg(message)); +        appendStatusMessage(command, \
QString(QStringLiteral("%1 %2")).arg(channel).arg(message), messageTags);  }
 }
 
-void Server::appendStatusMessage(const QString& type,const QString& message)
+void Server::appendStatusMessage(const QString& type, const QString& message, const \
QHash<QString, QString> &messageTags)  {
-    getStatusView()->appendServerMessage(type,message);
+    getStatusView()->appendServerMessage(type, message, messageTags);
 }
 
-void Server::appendMessageToFrontmost(const QString& type,const QString& message, bool \
parseURL) +void Server::appendMessageToFrontmost(const QString& type, const QString& message, \
const QHash<QString, QString> &messageTags, bool parseURL)  {
-    getViewContainer()->appendToFrontmost(type, message, getStatusView(), parseURL);
+    getViewContainer()->appendToFrontmost(type, message, getStatusView(), messageTags, \
parseURL);  }
 
 void Server::setNickname(const QString &newNickname)
@@ -3551,24 +3563,24 @@ void Server::setNickname(const QString &newNickname)
     emit nicknameChanged(newNickname);
 }
 
-void Server::setChannelTopic(const QString &channel, const QString &newTopic)
+void Server::setChannelTopic(const QString &channel, const QString &newTopic, const \
QHash<QString, QString> &messageTags)  {
     Channel* outChannel = getChannelByName(channel);
     if(outChannel)
     {
         // encoding stuff is done in send()
-        outChannel->setTopic(newTopic);
+        outChannel->setTopic(newTopic, messageTags);
     }
 }
 
                                                   // Overloaded
-void Server::setChannelTopic(const QString& nickname, const QString &channel, const QString \
&newTopic) +void Server::setChannelTopic(const QString& nickname, const QString &channel, const \
QString &newTopic, const QHash<QString, QString> &messageTags)  {
     Channel* outChannel = getChannelByName(channel);
     if(outChannel)
     {
         // encoding stuff is done in send()
-        outChannel->setTopic(nickname,newTopic);
+        outChannel->setTopic(nickname, newTopic, messageTags);
     }
 }
 
@@ -3988,7 +4000,7 @@ void Server::requestUnaway()
     queue(QStringLiteral("AWAY"));
 }
 
-void Server::setAway(bool away)
+void Server::setAway(bool away, const QHash<QString, QString> &messageTags)
 {
     IdentityPtr identity = getIdentity();
 
@@ -4007,9 +4019,9 @@ void Server::setAway(bool away)
         }
 
         if (!m_awayReason.isEmpty())
-            appendMessageToFrontmost(i18n("Away"), i18n("You are now marked as being away \
(reason: %1).",m_awayReason)); +            appendMessageToFrontmost(i18n("Away"), i18n("You \
are now marked as being away (reason: %1).",m_awayReason), messageTags);  else
-           appendMessageToFrontmost(i18n("Away"), i18n("You are now marked as being away."));
+           appendMessageToFrontmost(i18n("Away"), i18n("You are now marked as being away."), \
messageTags);  
         if (identity && identity->getRunAwayCommands())
         {
@@ -4034,7 +4046,7 @@ void Server::setAway(bool away)
 
         if (m_away)
         {
-            appendMessageToFrontmost(i18n("Away"), i18n("You are no longer marked as being \
away.")); +            appendMessageToFrontmost(i18n("Away"), i18n("You are no longer marked as \
being away."), messageTags);  
             if (identity && identity->getRunAwayCommands())
             {
@@ -4043,7 +4055,7 @@ void Server::setAway(bool away)
             }
         }
         else
-            appendMessageToFrontmost(i18n("Away"), i18n("You are not marked as being away."));
+            appendMessageToFrontmost(i18n("Away"), i18n("You are not marked as being away."), \
messageTags);  
         m_away = false;
     }
diff --git a/src/irc/server.h b/src/irc/server.h
index 068f4e0..30524ce 100644
--- a/src/irc/server.h
+++ b/src/irc/server.h
@@ -138,11 +138,12 @@ class Server : public QObject
         void resetNickSelection();
         void queueNicks(const QString& channelName, const QStringList& nicknameList);
         void addHostmaskToNick(const QString &sourceNick, const QString &sourceHostmask);
-        Channel* nickJoinsChannel(const QString &channelName, const QString &nickname, const \
                QString &hostmask, const QString &account, const QString &realName);
-        void renameNick(const QString &nickname,const QString &newNick);
-        Channel* removeNickFromChannel(const QString &channelName, const QString &nickname, \
                const QString &reason, bool quit=false);
-        void nickWasKickedFromChannel(const QString &channelName, const QString &nickname, \
                const QString &kicker, const QString &reason);
-        void removeNickFromServer(const QString &nickname, const QString &reason);
+        Channel* nickJoinsChannel(const QString &channelName, const QString &nickname, const \
QString &hostmask, const QString &account, +                                  const QString \
&realName, const QHash<QString, QString> &messageTags); +        void renameNick(const QString \
&nickname, const QString &newNick, const QHash<QString, QString> &messageTags); +        \
Channel* removeNickFromChannel(const QString &channelName, const QString &nickname, const \
QString &reason, const QHash<QString, QString> &messageTags, bool quit=false); +        void \
nickWasKickedFromChannel(const QString &channelName, const QString &nickname, const QString \
&kicker, const QString &reason, const QHash<QString, QString> &messageTags); +        void \
removeNickFromServer(const QString &nickname, const QString &reason, const QHash<QString, \
QString> &messageTags);  
         void setChannelTypes(const QString &types);
         QString getChannelTypes() const;
@@ -171,13 +172,13 @@ class Server : public QObject
         InputFilter* getInputFilter() { return &m_inputFilter; }
         Konversation::OutputFilter* getOutputFilter() { return m_outputFilter; }
 
-        Channel* joinChannel(const QString& name, const QString& hostmask);
+        Channel* joinChannel(const QString& name, const QString& hostmask, const \
QHash<QString, QString> &messageTags);  void removeChannel(Channel* channel);
-        void appendServerMessageToChannel(const QString& channel, const QString& type, const \
                QString& message);
-        void appendCommandMessageToChannel(const QString& channel, const QString& command, \
const QString& message, +        void appendServerMessageToChannel(const QString& channel, \
const QString& type, const QString& message, const QHash<QString, QString> &messageTags); +     \
void appendCommandMessageToChannel(const QString& channel, const QString& command, const \
                QString& message, const QHash<QString, QString> &messageTags,
                                            bool highlight = true, bool parseURL = true);
-        void appendStatusMessage(const QString& type,const QString& message);
-        void appendMessageToFrontmost(const QString& type,const QString& message, bool \
parseURL = true); +        void appendStatusMessage(const QString& type,const QString& message, \
const QHash<QString, QString> &messageTags); +        void appendMessageToFrontmost(const \
QString& type,const QString& message, const QHash<QString, QString> &messageTags = \
QHash<QString, QString>(), bool parseURL = true);  
         int getPreLength(const QString& command, const QString& dest);
 
@@ -186,10 +187,10 @@ class Server : public QObject
         void dbusInfo(const QString& string);
         void ctcpReply(const QString& receiver, const QString& text);
 
-        void setChannelTopic(const QString& channel, const QString& topic);
+        void setChannelTopic(const QString& channel, const QString& topic, const \
QHash<QString, QString> &messageTags);  // Overloaded
-        void setChannelTopic(const QString& nickname, const QString& channel, const QString& \
                topic);
-        void updateChannelMode(const QString& nick, const QString& channel, char mode, bool \
plus, const QString& parameter); +        void setChannelTopic(const QString& nickname, const \
QString& channel, const QString& topic, const QHash<QString, QString> &messageTags); +        \
void updateChannelMode(const QString& nick, const QString& channel, char mode, bool plus, const \
                QString& parameter, const QHash<QString, QString> &messageTags);
         void updateChannelModeWidgets(const QString& channel, char mode, const QString& \
parameter);  
         Channel* getChannelByName(const QString& name);
@@ -213,7 +214,7 @@ class Server : public QObject
         QString getOwnIpByServerMessage();
 
         bool isAway() { return m_away; }
-        void setAway(bool away);
+        void setAway(bool away, const QHash<QString, QString> &messageTags);
         QString awayTime() const;
 
         void setAwayReason(const QString& reason) { m_awayReason = reason; }
@@ -391,6 +392,7 @@ class Server : public QObject
         bool hasExtendedJoin() const { return m_hasExtendedJoin; }
         void setHasWHOX(bool state) { m_hasWHOX = state; }
         bool hasWHOX() const { return m_hasWHOX; }
+        bool hasServerTime() const { return m_hasServerTime; }
 
     // IRCQueueManager
         bool validQueue(QueuePriority priority); ///< is this queue index valid?
@@ -857,6 +859,7 @@ class Server : public QObject
         bool m_hasAwayNotify;
         bool m_hasExtendedJoin;
         bool m_hasWHOX;
+        bool m_hasServerTime;
 };
 
 Q_DECLARE_OPERATORS_FOR_FLAGS(Server::CapModifiers)
diff --git a/src/viewer/chatwindow.cpp b/src/viewer/chatwindow.cpp
index 427dcc0..3e2b877 100644
--- a/src/viewer/chatwindow.cpp
+++ b/src/viewer/chatwindow.cpp
@@ -275,38 +275,38 @@ void ChatWindow::appendLog(const QString& message)
     textView->appendLog(message);
 }
 
-void ChatWindow::append(const QString& nickname,const QString& message, const QString& label)
+void ChatWindow::append(const QString& nickname, const QString& message, const QHash<QString, \
QString> &messageTags, const QString& label)  {
     if(!textView) return;
-    textView->append(nickname, message, label);
+    textView->append(nickname, message, messageTags, label);
 }
 
-void ChatWindow::appendQuery(const QString& nickname,const QString& message, bool inChannel)
+void ChatWindow::appendQuery(const QString& nickname, const QString& message, const \
QHash<QString, QString> &messageTags, bool inChannel)  {
     if(!textView) return ;
-    textView->appendQuery(nickname,message, inChannel);
+    textView->appendQuery(nickname, message, messageTags, inChannel);
 }
 
-void ChatWindow::appendAction(const QString& nickname, const QString& message)
+void ChatWindow::appendAction(const QString& nickname, const QString& message, const \
QHash<QString, QString> &messageTags)  {
     if(!textView) return;
 
     if (getType() == Query || getType() == DccChat)
-        textView->appendQueryAction(nickname, message);
+        textView->appendQueryAction(nickname, message, messageTags);
     else
-        textView->appendChannelAction(nickname, message);
+        textView->appendChannelAction(nickname, message, messageTags);
 }
 
-void ChatWindow::appendServerMessage(const QString& type,const QString& message, bool \
parseURL) +void ChatWindow::appendServerMessage(const QString& type, const QString& message, \
const QHash<QString, QString> &messageTags, bool parseURL)  {
     if(!textView) return ;
-    textView->appendServerMessage(type,message, parseURL);
+    textView->appendServerMessage(type, message, messageTags, parseURL);
 }
 
-void ChatWindow::appendCommandMessage(const QString& command, const QString& message, bool \
parseURL, bool self) +void ChatWindow::appendCommandMessage(const QString& command, const \
QString& message, const QHash<QString, QString> &messageTags, bool parseURL, bool self)  {
     if(!textView) return ;
-    textView->appendCommandMessage(command,message,parseURL,self);
+    textView->appendCommandMessage(command, message, messageTags, parseURL, self);
 }
 
 void ChatWindow::appendBacklogMessage(const QString& firstColumn,const QString& message)
@@ -717,7 +717,7 @@ void ChatWindow::msgHelper(const QString& recipient, const QString& \
message)  else
         visualization = result;
 
-    appendQuery(recipient, visualization, true);
+    appendQuery(recipient, visualization, QHash<QString, QString>(), true);
 
     if (!getServer())
         return;
diff --git a/src/viewer/chatwindow.h b/src/viewer/chatwindow.h
index 499cb55..880477a 100644
--- a/src/viewer/chatwindow.h
+++ b/src/viewer/chatwindow.h
@@ -85,13 +85,13 @@ class ChatWindow : public QWidget
 
         virtual void sendText(const QString& /*text*/) {}
 
-        virtual void append(const QString& nickname,const QString& message, const QString& \
label = QString()); +        virtual void append(const QString& nickname,const QString& \
                message, const QHash<QString, QString> &messageTags, const QString& label = \
                QString());
         virtual void appendRaw(const QString& message, bool self = false);
         virtual void appendLog(const QString& message);
-        virtual void appendQuery(const QString& nickname,const QString& message, bool \
                inChannel = false);
-        virtual void appendAction(const QString& nickname,const QString& message);
-        virtual void appendServerMessage(const QString& type,const QString& message, bool \
                parseURL = true);
-        virtual void appendCommandMessage(const QString& command, const QString& message,
+        virtual void appendQuery(const QString& nickname,const QString& message, const \
QHash<QString, QString> &messageTags = QHash<QString, QString>(), bool inChannel = false); +    \
virtual void appendAction(const QString& nickname,const QString& message, const QHash<QString, \
QString> &messageTags = QHash<QString, QString>()); +        virtual void \
appendServerMessage(const QString& type,const QString& message, const QHash<QString, QString> \
&messageTags = QHash<QString, QString>(), bool parseURL = true); +        virtual void \
appendCommandMessage(const QString& command, const QString& message, const QHash<QString, \
QString> &messageTags = QHash<QString, QString>(),  bool parseURL = true, bool self = false);
         virtual void appendBacklogMessage(const QString& firstColumn,const QString& message);
 
diff --git a/src/viewer/ircview.cpp b/src/viewer/ircview.cpp
index 24f24c9..fe9bcb7 100644
--- a/src/viewer/ircview.cpp
+++ b/src/viewer/ircview.cpp
@@ -520,7 +520,7 @@ void IRCView::updateAppearance()
 
 // Data insertion
 
-void IRCView::append(const QString& nick, const QString& message, const QString& label)
+void IRCView::append(const QString& nick, const QString& message, const QHash<QString, \
QString> &messageTags, const QString& label)  {
     QString channelColor = Preferences::self()->color(Preferences::ChannelMessage).name();
 
@@ -539,14 +539,11 @@ void IRCView::append(const QString& nick, const QString& message, const \
                QString&
         line += "<font color=\"" + channelColor + "\"><b>[</b>%4<b>]</b></font>";
     }
     line += "<font color=\"" + channelColor + "\">%1" + directionOfLine + nickLine + \
directionOfLine + " %3</font>"; +    line = line.arg(timeStamp(messageTags), nick, text);
 
     if (!label.isEmpty())
     {
-        line = line.arg(timeStamp(), nick, text, label);
-    }
-    else
-    {
-        line = line.arg(timeStamp(), nick, text);
+        line = line.arg(label);
     }
 
     emit textToLog(QString("<%1>\t%2").arg(nick, message));
@@ -560,7 +557,7 @@ void IRCView::appendRaw(const QString& message, bool self)
         : Preferences::self()->color(Preferences::ServerMessage);
     m_tabNotification = Konversation::tnfNone;
 
-    QString line = QString(timeStamp() + " <font color=\"" + color.name() + "\">" + message + \
"</font>"); +    QString line = QString(timeStamp(QHash<QString, QString>()) + " <font \
color=\"" + color.name() + "\">" + message + "</font>");  
     doAppend(line, false, self);
 }
@@ -575,7 +572,7 @@ void IRCView::appendLog(const QString & message)
     doRawAppend(line, !QApplication::isLeftToRight());
 }
 
-void IRCView::appendQuery(const QString& nick, const QString& message, bool inChannel)
+void IRCView::appendQuery(const QString& nick, const QString& message, const QHash<QString, \
QString> &messageTags, bool inChannel)  {
     QString queryColor=Preferences::self()->color(Preferences::QueryMessage).name();
 
@@ -590,7 +587,7 @@ void IRCView::appendQuery(const QString& nick, const QString& message, bool \
inCh  
     QChar directionOfLine = rtl ? RLM : LRM;
     line = directionOfLine + "<font color=\"" + queryColor + "\">%1" + directionOfLine + \
                nickLine + directionOfLine + " %3";
-    line = line.arg(timeStamp(), nick, text);
+    line = line.arg(timeStamp(messageTags), nick, text);
 
     if (inChannel) {
         emit textToLog(QString("<-> %1>\t%2").arg(nick, message));
@@ -601,19 +598,19 @@ void IRCView::appendQuery(const QString& nick, const QString& message, \
bool inCh  doAppend(line, rtl);
 }
 
-void IRCView::appendChannelAction(const QString& nick, const QString& message)
+void IRCView::appendChannelAction(const QString& nick, const QString& message, const \
QHash<QString, QString> &messageTags)  {
     m_tabNotification = Konversation::tnfNormal;
-    appendAction(nick, message);
+    appendAction(nick, message, messageTags);
 }
 
-void IRCView::appendQueryAction(const QString& nick, const QString& message)
+void IRCView::appendQueryAction(const QString& nick, const QString& message, const \
QHash<QString, QString> &messageTags)  {
     m_tabNotification = Konversation::tnfPrivate;
-    appendAction(nick, message);
+    appendAction(nick, message, messageTags);
 }
 
-void IRCView::appendAction(const QString& nick, const QString& message)
+void IRCView::appendAction(const QString& nick, const QString& message, const QHash<QString, \
QString> &messageTags)  {
     QString actionColor = Preferences::self()->color(Preferences::ActionMessage).name();
 
@@ -625,7 +622,7 @@ void IRCView::appendAction(const QString& nick, const QString& message)
     {
         line = LRM + "<font color=\"" + actionColor + "\">%1 * " + nickLine + "</font>";
 
-        line = line.arg(timeStamp(), nick);
+        line = line.arg(timeStamp(messageTags), nick);
 
         emit textToLog(QString("\t * %1").arg(nick));
 
@@ -639,7 +636,7 @@ void IRCView::appendAction(const QString& nick, const QString& message)
 
         QChar directionOfLine = rtl ? RLM : LRM;
         line = directionOfLine + "<font color=\"" + actionColor + "\">%1 " + directionOfLine + \
                "* " + nickLine + directionOfLine + " %3</font>";
-        line = line.arg(timeStamp(), nick, text);
+        line = line.arg(timeStamp(messageTags), nick, text);
 
         emit textToLog(QString("\t * %1 %2").arg(nick, message));
 
@@ -647,7 +644,7 @@ void IRCView::appendAction(const QString& nick, const QString& message)
     }
 }
 
-void IRCView::appendServerMessage(const QString& type, const QString& message, bool parseURL)
+void IRCView::appendServerMessage(const QString& type, const QString& message, const \
QHash<QString, QString> &messageTags, bool parseURL)  {
     QString serverColor = Preferences::self()->color(Preferences::ServerMessage).name();
     m_tabNotification = Konversation::tnfControl;
@@ -667,14 +664,14 @@ void IRCView::appendServerMessage(const QString& type, const QString& \
message, b  
     QChar directionOfLine = rtl ? RLM : LRM;
     line = directionOfLine + "<font color=\"" + serverColor + "\"" + fixed + ">%1 " + \
                directionOfLine + "<b>[</b>%2<b>]</b>" + directionOfLine + " %3</font>";
-    line = line.arg(timeStamp(), type, text);
+    line = line.arg(timeStamp(messageTags), type, text);
 
     emit textToLog(QString("%1\t%2").arg(type, message));
 
     doAppend(line, rtl);
 }
 
-void IRCView::appendCommandMessage(const QString& type,const QString& message, bool parseURL, \
bool self) +void IRCView::appendCommandMessage(const QString& type, const QString& message, \
const QHash<QString, QString> &messageTags, bool parseURL, bool self)  {
     QString commandColor = Preferences::self()->color(Preferences::CommandMessage).name();
     QString prefix="***";
@@ -699,7 +696,7 @@ void IRCView::appendCommandMessage(const QString& type,const QString& \
message, b  
     QChar directionOfLine = rtl ? RLM : LRM;
     line = directionOfLine + "<font color=\"" + commandColor + "\">%1 %2 %3</font>";
-    line = line.arg(timeStamp(), prefix, text);
+    line = line.arg(timeStamp(messageTags), prefix, text);
 
     emit textToLog(QString("%1\t%2").arg(type, message));
 
@@ -797,11 +794,16 @@ void IRCView::doRawAppend(const QString& newLine, bool rtl)
     formatCursor.setBlockFormat(format);
 }
 
-QString IRCView::timeStamp()
+QString IRCView::timeStamp(QHash<QString, QString> messageTags)
 {
     if(Preferences::self()->timestamping())
     {
-        QTime time = QTime::currentTime();
+        QDateTime serverTime;
+
+        if (messageTags.contains(QStringLiteral("time"))) // If it exists use the supplied \
server time. +            serverTime = \
QDateTime::fromString(messageTags[QStringLiteral("time")], Qt::ISODate).toLocalTime(); +
+        QTime time = serverTime.isValid() ? serverTime.time() : QTime::currentTime();
         QString timeColor = Preferences::self()->color(Preferences::Time).name();
         QString timeFormat = Preferences::self()->timestampFormat();
         QString timeString;
@@ -815,7 +817,7 @@ QString IRCView::timeStamp()
         }
         else
         {
-            QDate date = QDate::currentDate();
+            QDate date = serverTime.isValid() ? serverTime.date() : QDate::currentDate();
             timeString = QString("<font color=\"" +
                 timeColor + "\">[%1%2 %3%4]</font> ")
                     .arg(rtlLocale ? RLM : LRM,
diff --git a/src/viewer/ircview.h b/src/viewer/ircview.h
index 83979f2..7bc02ae 100644
--- a/src/viewer/ircview.h
+++ b/src/viewer/ircview.h
@@ -174,24 +174,24 @@ class IRCView : public QTextBrowser
     //// Other stuff
     public Q_SLOTS:
         //! FIXME enum { Raw, Query, Query+Action, Channel+Action, Server Message, Command \
                Message, Backlog message } this looks more like a tuple
-        void append(const QString& nick, const QString& message, const QString& label = \
QString()); +        void append(const QString& nick, const QString& message, const \
QHash<QString, QString> &messageTags = QHash<QString, QString>(), const QString& label = \
QString());  void appendRaw(const QString& message, bool self = false);
         void appendLog(const QString& message);
 
-        void appendQuery(const QString& nick, const QString& message, bool inChannel = false);
-        void appendQueryAction(const QString& nick, const QString& message);
+        void appendQuery(const QString& nick, const QString& message, const QHash<QString, \
QString> &messageTags, bool inChannel = false); +        void appendQueryAction(const QString& \
nick, const QString& message, const QHash<QString, QString> &messageTags);  protected:
         //! FIXME why is this protected, and all alone down there?
-        void appendAction(const QString& nick, const QString& message);
+        void appendAction(const QString& nick, const QString& message, const QHash<QString, \
QString> &messageTags);  
         /// Appends a new line without any scrollback or notification checks
         void doRawAppend(const QString& newLine, bool rtl);
 
     public Q_SLOTS:
-        void appendChannelAction(const QString& nick, const QString& message);
+        void appendChannelAction(const QString& nick, const QString& message, const \
QHash<QString, QString> &messageTags);  
-        void appendServerMessage(const QString& type, const QString& message, bool parseURL = \
                true);
-        void appendCommandMessage(const QString& command, const QString& message, bool \
parseURL=true, bool self=false); +        void appendServerMessage(const QString& type, const \
QString& message, const QHash<QString, QString> &messageTags = QHash<QString, QString>(), bool \
parseURL = true); +        void appendCommandMessage(const QString& command, const QString& \
                message, const QHash<QString, QString> &messageTags, bool parseURL=true, bool \
                self=false);
         void appendBacklogMessage(const QString& firstColumn, const QString& message);
 
     protected:
@@ -283,7 +283,7 @@ class IRCView : public QTextBrowser
         QChar::Direction basicDirection(const QString &string);
 
         /// Returns a formated timestamp if timestamps are enabled else it returns \
                QString::null
-        QString timeStamp();
+        QString timeStamp(QHash<QString, QString> messageTags);
 
         /// Returns a formated nick string
         //! FIXME formatted in what way?
diff --git a/src/viewer/viewcontainer.cpp b/src/viewer/viewcontainer.cpp
index 1b1f320..520c42c 100644
--- a/src/viewer/viewcontainer.cpp
+++ b/src/viewer/viewcontainer.cpp
@@ -2378,7 +2378,7 @@ void ViewContainer::findPrevText()
     }
 }
 
-void ViewContainer::appendToFrontmost(const QString& type,const QString& message,ChatWindow* \
serverView, bool parseURL) +void ViewContainer::appendToFrontmost(const QString& type, const \
QString& message, ChatWindow* serverView, const QHash<QString, QString> &messageTags, bool \
parseURL)  {
     if (!m_tabWidget) return;
 
@@ -2404,14 +2404,14 @@ void ViewContainer::appendToFrontmost(const QString& type,const \
QString& message  Preferences::self()->redirectServerAndAppMsgToStatusPane())
     {
         // if not, take server specified fallback view instead
-        serverView->appendServerMessage(type,  message, parseURL);
+        serverView->appendServerMessage(type,  message, messageTags, parseURL);
         // FIXME: this signal should be sent from the status panel instead, so it
         //        can be using the correct highlight color, would be more consistent
         //        anyway!
         // FIXME newText(serverView,QString::null,true);
     }
     else
-        m_frontView->appendServerMessage(type, message, parseURL);
+        m_frontView->appendServerMessage(type, message, messageTags, parseURL);
 }
 
 void ViewContainer::insertCharacter()
diff --git a/src/viewer/viewcontainer.h b/src/viewer/viewcontainer.h
index cf433c0..4c12f41 100644
--- a/src/viewer/viewcontainer.h
+++ b/src/viewer/viewcontainer.h
@@ -120,7 +120,7 @@ class ViewContainer : public QAbstractItemModel
         QString currentViewURL(bool passNetwork = true);
 
         void appendToFrontmost(const QString& type,const QString& message,ChatWindow* \
                serverView,
-                               bool parseURL = true);
+                               const QHash<QString, QString> &messageTags = QHash<QString, \
QString>(), bool parseURL = true);  
         void showQueueTuner(bool);
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic