make names in chats clickable. still color adjustments needed; and testing
authorsheepluva
Tue, 01 Feb 2011 06:06:38 +0100
changeset 4897 11598e7aa7e6
parent 4896 972d418057a7
child 4898 7a94005874c9
make names in chats clickable. still color adjustments needed; and testing
QTfrontend/chatwidget.cpp
QTfrontend/chatwidget.h
QTfrontend/hwform.cpp
QTfrontend/newnetclient.cpp
QTfrontend/newnetclient.h
QTfrontend/pages.cpp
QTfrontend/proto.cpp
QTfrontend/proto.h
--- a/QTfrontend/chatwidget.cpp	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/chatwidget.cpp	Tue Feb 01 06:06:38 2011 +0100
@@ -17,6 +17,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  */
 
+#include <QDesktopServices>
 #include <QTextBrowser>
 #include <QLineEdit>
 #include <QAction>
@@ -26,7 +27,10 @@
 #include <QSettings>
 #include <QFile>
 #include <QTextStream>
+#include <QMenu>
+#include <QCursor>
 #include <QScrollBar>
+#include <QItemSelectionModel>
 
 #include "hwconsts.h"
 #include "SDLs.h"
@@ -92,6 +96,8 @@
     return firstIsShorter;
 }
 
+const char* HWChatWidget::STYLE = "a {color:white;} a.nick {text-decoration: none;}";
+
 HWChatWidget::HWChatWidget(QWidget* parent, QSettings * gameSettings, SDLInteraction * sdli, bool notify) :
   QWidget(parent),
   mainLayout(this)
@@ -124,10 +130,13 @@
     mainLayout.addWidget(chatEditLine, 1, 0);
 
     chatText = new QTextBrowser(this);
+    chatText->document()->setDefaultStyleSheet(STYLE);
     chatText->setMinimumHeight(20);
     chatText->setMinimumWidth(10);
     chatText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-    chatText->setOpenExternalLinks(true);
+    chatText->setOpenLinks(false);
+    connect(chatText, SIGNAL(anchorClicked(const QUrl&)),
+        this, SLOT(linkClicked(const QUrl&)));
     mainLayout.addWidget(chatText, 0, 0);
 
     chatNicks = new QListWidget(this);
@@ -170,6 +179,32 @@
     setShowFollow(true);
 }
 
+void HWChatWidget::linkClicked(const QUrl & link)
+{
+    if (link.scheme() == "http")
+        QDesktopServices::openUrl(link);
+    if (link.scheme() == "hwnick")
+    {
+        // decode nick
+        const QString& nick = QString::fromUtf8(QByteArray::fromBase64(link.encodedQuery()));
+        QList<QListWidgetItem *> items = chatNicks->findItems(nick, Qt::MatchExactly);
+        if (items.size() < 1)
+            return;
+        QMenu * popup = new QMenu();
+        // selecting an item will automatically scroll there, so let's save old position
+        QScrollBar * scrollBar = chatNicks->verticalScrollBar();
+        int oldScrollPos = scrollBar->sliderPosition();
+        // select the nick which we want to see the actions for
+        chatNicks->setCurrentItem(items[0], QItemSelectionModel::Clear);
+        // selecting an item will automatically scroll there, so let's save old position
+        scrollBar->setSliderPosition(oldScrollPos);
+        // load actions
+        popup->addActions(chatNicks->actions());
+        // display menu popup at mouse cursor position
+        popup->popup(QCursor::pos());
+    }
+}
+
 void HWChatWidget::setShowFollow(bool enabled)
 {
     if (enabled) {
@@ -269,33 +304,50 @@
     chatEditLine->clear();
 }
 
+
 void HWChatWidget::onChatString(const QString& str)
 {
+    onChatString("", str);
+}
+
+void HWChatWidget::onChatString(const QString& nick, const QString& str)
+{
+    bool isFriend = false;
+
+    if (!nick.isEmpty()) {
+        // don't show chat lines that are from ignored nicks
+        if (ignoreList.contains(nick, Qt::CaseInsensitive))
+            return;
+        // friends will get special treatment, of course
+        isFriend = friendsList.contains(nick, Qt::CaseInsensitive);
+    }
+
     if (chatStrings.size() > 250)
         chatStrings.removeFirst();
 
     QString formattedStr = Qt::escape(str.mid(1));
-    QStringList parts = formattedStr.split(QRegExp("\\W+"), QString::SkipEmptyParts);
 
-    if (!formattedStr.startsWith(" ***")) // don't ignore status messages
-    {
-        if (formattedStr.startsWith(" *")) // emote
-            parts[0] = parts[1];
-        if(parts.size() > 0 && ignoreList.contains(parts[0], Qt::CaseInsensitive))
-            return;
-    }
+    // "link" nick, but before that encode it in base64 to make sure it can't intefere with html/url syntax
+    // the nick is put as querystring as putting it as host would convert it to it's lower case variant
+    if(!nick.isEmpty())
+        formattedStr.replace("|nick|",QString("<a href=\"hwnick://?%1\" class=\"nick\">%2</a>").arg(QString(nick.toUtf8().toBase64())).arg(nick));
 
     QString color("");
-    bool isFriend = friendsList.contains(parts[0], Qt::CaseInsensitive);
 
-    if (str.startsWith("\x03"))
-        color = QString("#c0c0c0");
-    else if (str.startsWith("\x02"))
-        color = QString(isFriend ? "#00ff00" : "#ff00ff");
-    else if (isFriend)
-        color = QString("#00c000");
+    // check first character for color code and set color properly
+    switch (str[0].toAscii()) {
+        case 3:
+            color = QString("#c0c0c0");
+            break;
+        case 2:
+            color = QString(isFriend ? "#00ff00" : "#ff00ff");
+            break;
+        default:
+            if (isFriend)
+                color = QString("#00c000");
+    }
 
-    if(color.compare("") != 0)
+    if (!color.isEmpty())
         formattedStr = QString("<font color=\"%2\">%1</font>").arg(formattedStr).arg(color);
 
     chatStrings.append(formattedStr);
@@ -391,7 +443,7 @@
 
         // scroll down on first ignore added so that people see where that nick went to
         if (ignoreList.isEmpty())
-            emit chatNicks->verticalScrollBar()->setValue(chatNicks->verticalScrollBar()->maximum());
+            chatNicks->scrollToBottom();
 
         ignoreList << curritem->text().toLower();
         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your ignore list").arg('\x03').arg(curritem->text()));
@@ -420,7 +472,7 @@
 
         // scroll up on first friend added so that people see where that nick went to
         if (friendsList.isEmpty())
-            emit chatNicks->verticalScrollBar()->setValue(chatNicks->verticalScrollBar()->minimum());
+            chatNicks->scrollToTop();
 
         friendsList << curritem->text().toLower();
         onChatString(HWChatWidget::tr("%1 *** %2 has been added to your friends list").arg('\x03').arg(curritem->text()));
--- a/QTfrontend/chatwidget.h	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/chatwidget.h	Tue Feb 01 06:06:38 2011 +0100
@@ -59,6 +59,7 @@
   void saveLists(const QString & nick);
   void setShowReady(bool s);
   void setShowFollow(bool enabled);
+  static const char* STYLE;
 
 private:
   void loadList(QStringList & list, const QString & file);
@@ -68,6 +69,7 @@
 
  public slots:
   void onChatString(const QString& str);
+  void onChatString(const QString& nick, const QString& str);
   void onServerMessage(const QString& str);
   void nickAdded(const QString& nick, bool notifyNick);
   void nickRemoved(const QString& nick);
@@ -111,6 +113,7 @@
   void onFriend();
   void chatNickDoubleClicked(QListWidgetItem * item);
   void chatNickSelected(int index);
+  void linkClicked(const QUrl & link);
 };
 
 #endif // _CHAT_WIDGET_INCLUDED
--- a/QTfrontend/hwform.cpp	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/hwform.cpp	Tue Feb 01 06:06:38 2011 +0100
@@ -797,6 +797,8 @@
         hwnet, SLOT(chatLineToLobby(const QString&)));
     connect(hwnet, SIGNAL(chatStringLobby(const QString&)),
         ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)));
+    connect(hwnet, SIGNAL(chatStringLobby(const QString&, const QString&)),
+        ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&, const QString&)));
     connect(hwnet, SIGNAL(chatStringFromMeLobby(const QString&)),
         ui.pageRoomsList->chatWidget, SLOT(onChatString(const QString&)));
 
--- a/QTfrontend/newnetclient.cpp	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/newnetclient.cpp	Tue Feb 01 06:06:38 2011 +0100
@@ -276,7 +276,7 @@
             return;
         }
         if (netClientState == 2)
-            emit chatStringLobby(HWProto::formatChatMsg(lst[1], lst[2]));
+            emit chatStringLobby(lst[1], HWProto::formatChatMsgForFrontend(lst[2]));
         else
             emit chatStringFromNet(HWProto::formatChatMsg(lst[1], lst[2]));
         return;
@@ -418,7 +418,7 @@
             }
 
             emit nickAddedLobby(lst[i], false);
-            emit chatStringLobby(tr("%1 *** %2 has joined").arg('\x03').arg(lst[i]));
+            emit chatStringLobby(lst[i], tr("%1 *** %2 has joined").arg('\x03').arg("|nick|"));
         }
         return;
     }
--- a/QTfrontend/newnetclient.h	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/newnetclient.h	Tue Feb 01 06:06:38 2011 +0100
@@ -113,6 +113,7 @@
   void hhnumChanged(const HWTeam&);
   void teamColorChanged(const HWTeam&);
   void chatStringLobby(const QString&);
+  void chatStringLobby(const QString&, const QString&);
   void chatStringFromNet(const QString&);
   void chatStringFromMe(const QString&);
   void chatStringFromMeLobby(const QString&);
--- a/QTfrontend/pages.cpp	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/pages.cpp	Tue Feb 01 06:06:38 2011 +0100
@@ -2025,6 +2025,7 @@
 
     tb = new QTextBrowser(this);
     tb->setOpenExternalLinks(true);
+    tb->document()->setDefaultStyleSheet(HWChatWidget::STYLE);
     pageLayout->addWidget(tb, 4, 1, 1, 2);
     connect(leServerMessageNew, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
     connect(leServerMessageOld, SIGNAL(textEdited(const QString &)), tb, SLOT(setHtml(const QString &)));
--- a/QTfrontend/proto.cpp	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/proto.cpp	Tue Feb 01 06:06:38 2011 +0100
@@ -45,6 +45,11 @@
     return buf;
 }
 
+QString HWProto::formatChatMsgForFrontend(const QString & msg)
+{
+    return formatChatMsg("|nick|", msg);
+}
+
 QString HWProto::formatChatMsg(const QString & nick, const QString & msg)
 {
     if(msg.left(4) == "/me ")
--- a/QTfrontend/proto.h	Tue Feb 01 00:24:28 2011 +0100
+++ b/QTfrontend/proto.h	Tue Feb 01 06:06:38 2011 +0100
@@ -34,6 +34,7 @@
     static QByteArray & addByteArrayToBuffer(QByteArray & buf, const QByteArray & msg);
     static QByteArray & addStringListToBuffer(QByteArray & buf, const QStringList & strList);
     static QString formatChatMsg(const QString & nick, const QString & msg);
+    static QString formatChatMsgForFrontend(const QString & msg);
 };
 
 #endif // _PROTO_H