chat:
authorsheepluva
Mon, 24 Oct 2011 10:30:47 +0200
changeset 6197 4ce7c29799b9
parent 6196 c16e84558f71
child 6198 9aa9ed77d63c
chat: + added timestamps (can also be css styled and disabled) + allow exchanging stylesheet by just dragging a *.css file into the chat widget! + /saveStyleSheet command for keeping the applied stylesheet for future runs + /discardStyleSheet to reset to the saved/default stylesheet Note: I noticed command auto-completion is broken, don't know since when. annoying.
QTfrontend/main.cpp
QTfrontend/res/css/chat.css
QTfrontend/ui/widget/SmartLineEdit.cpp
QTfrontend/ui/widget/chatwidget.cpp
QTfrontend/ui/widget/chatwidget.h
--- a/QTfrontend/main.cpp	Mon Oct 24 06:54:46 2011 +0200
+++ b/QTfrontend/main.cpp	Mon Oct 24 10:30:47 2011 +0200
@@ -165,27 +165,6 @@
         return 1;
     }
 
-    // copy data/default css files to cfgdir as templates
-    QString userCssDir = cfgdir->absolutePath() + "/Data/css";
-    if (checkForDir(userCssDir))
-    {
-        QString defaultCssDir = ":res/css";
-        QStringList cssFiles = QDir(defaultCssDir).entryList(QDir::Files);
-        foreach (const QString & cssFile, cssFiles)
-        {
-            QString srcName = datadir->absolutePath()+"/css/"+cssFile;
-
-            if (!QFile::exists(srcName))
-                srcName = defaultCssDir+"/"+cssFile;
-
-            QString tmpName = userCssDir + "/template_" + cssFile;
-            if (QFile::exists(tmpName))
-                QFile::remove(tmpName);
-
-            QFile(srcName).copy(tmpName);
-        }
-    }
-
     HWDataManager & dataMgr = HWDataManager::instance();
 
     {
--- a/QTfrontend/res/css/chat.css	Mon Oct 24 06:54:46 2011 +0200
+++ b/QTfrontend/res/css/chat.css	Mon Oct 24 10:30:47 2011 +0200
@@ -7,8 +7,8 @@
  * see http://doc.qt.nokia.com/4.5/richtext-html-subset.html#css-properties
  *
  * In the QTfrontend of hedgewars also display:none; will work for class names
- * that start with msg_   -   as long as they are referenced directly and not
- * within any hierachy.
+ * that start with msg_ and .TimeStamp -  as long as they are referenced
+ * directly and not within any hierachy.
  *
  ******************************************************************************
  *
@@ -24,6 +24,11 @@
 /* links */
 a { color:#c8c8ff; }
 
+/* appearance of the whole chat */
+/* body { color: white; background-color: #000000; } */
+
+/* appearance of all elements in chat */
+/* * { color: white; background-color: #000000; } */
 
 /* nick names (they are also sometimes linked) */
 .nick { text-decoration: none; }
@@ -42,6 +47,19 @@
 .msg_FriendAction { color: #ff00ff; }
 .msg_FriendAction .nick { color: #ff30ff; }
 
+/* timestamps */
+.timestamp {
+    color: #e0d8e0;
+    font-family: courier;
+    font-size: 11px;
+    vertical-align: center;
+    /* uncomment next line to hide timestamps */
+    /* display: none; */
+}
+
+/* you can also set timestamp style for different msg types */
+.msg_FriendChat .timestamp { color: #ffffff; }
+
 /* messages that contain your nickname */
 .highlight {  }
 .highlight .nick { color: red; } /* nicknames in highlighted messages */
--- a/QTfrontend/ui/widget/SmartLineEdit.cpp	Mon Oct 24 06:54:46 2011 +0200
+++ b/QTfrontend/ui/widget/SmartLineEdit.cpp	Mon Oct 24 10:30:47 2011 +0200
@@ -222,7 +222,7 @@
             {
                 match = cmd;
 
-                // move match to end so next time new matches will be prefered
+                // move match to end so next time new matches will be preferred
                 if (m_cmds->removeAll(cmd) > 0);
                     m_cmds->append(cmd);
 
--- a/QTfrontend/ui/widget/chatwidget.cpp	Mon Oct 24 06:54:46 2011 +0200
+++ b/QTfrontend/ui/widget/chatwidget.cpp	Mon Oct 24 10:30:47 2011 +0200
@@ -30,6 +30,8 @@
 #include <QScrollBar>
 #include <QItemSelectionModel>
 #include <QStringList>
+#include <QDateTime>
+#include <QTime>
 
 
 #include "HWDataManager.h"
@@ -99,36 +101,54 @@
 
 QString * HWChatWidget::s_styleSheet = NULL;
 QStringList * HWChatWidget::s_displayNone = NULL;
+bool HWChatWidget::s_isTimeStamped = true;
+QMutex HWChatWidget::s_styleSheetMutex;
 
 QString & HWChatWidget::styleSheet()
 {
-    if (s_styleSheet != NULL)
-        return *s_styleSheet;
+    s_styleSheetMutex.lock();
 
-    // initialize
-    s_styleSheet = new QString();
+    if (s_styleSheet != NULL)
+    {
+        s_styleSheetMutex.unlock();
+        return *s_styleSheet;
+    }
 
-    // getting a reference
-    QString & style = *s_styleSheet;
+    setStyleSheet();
+
+    s_styleSheetMutex.unlock();
 
-    // load external stylesheet if there is any
-    QFile extFile(HWDataManager::instance().findFileForRead("css/chat.css"));
+    return *s_styleSheet;
+}
+
+void HWChatWidget::setStyleSheet(const QString & styleSheet)
+{
+    QString style = styleSheet;
 
-    QFile resFile(":/res/css/chat.css");
-
-    QFile & file = (extFile.exists()?extFile:resFile);
-
-    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
+    // no stylesheet supplied, search for one or use default
+    if (style.isEmpty())
     {
-        QTextStream in(&file);
-        while (!in.atEnd())
+        // load external stylesheet if there is any
+        QFile extFile(HWDataManager::instance().findFileForRead("css/chat.css"));
+
+        QFile resFile(":/res/css/chat.css");
+
+        QFile & file = (extFile.exists()?extFile:resFile);
+
+        if (file.open(QIODevice::ReadOnly | QIODevice::Text))
         {
-            QString line = in.readLine();
-            if(!line.isEmpty())
-                style.append(line);
+            QTextStream in(&file);
+            while (!in.atEnd())
+            {
+                QString line = in.readLine();
+                if(!line.isEmpty())
+                    style.append(line);
+            }
         }
     }
 
+    // let's parse display:none; ...
+
     // prepare for MAGIC :D
 
     // matches (multi-)whitespaces (for replacement with simple space)
@@ -162,12 +182,27 @@
                                 filter(nohierarchy). // only direct class names
                                 replaceInStrings(QRegExp("^."),""); // crop .
 
+
+    if (victims.contains("timestamp"))
+    {
+        s_isTimeStamped = false;
+        victims.removeAll("timestamp");
+    }
+
     victims.removeDuplicates();
 
+    QStringList * oldDisplayNone = s_displayNone;
+    QString * oldStyleSheet = s_styleSheet;
+
     s_displayNone = new QStringList(victims);
-
+    s_styleSheet = new QString(style);
 
-    return style;
+    if (oldDisplayNone != NULL)
+        delete oldDisplayNone;
+
+    if (oldStyleSheet != NULL)
+        delete oldStyleSheet;
+
 }
 
 void HWChatWidget::displayError(const QString & message)
@@ -216,7 +251,9 @@
     mainLayout.setColumnStretch(1, 24);
 
     chatEditLine = new SmartLineEdit(this);
-    chatEditLine->addCommands(QStringList("/me"));
+    QStringList cmds;
+    cmds << "/me" << "/discardStyleSheet" << "/saveStyleSheet";
+    chatEditLine->addCommands(cmds);
     chatEditLine->setMaxLength(300);
     connect(chatEditLine, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
 
@@ -273,6 +310,7 @@
     showReady = false;
     setShowFollow(true);
 
+    setAcceptDrops(true);
     clear();
 }
 
@@ -415,9 +453,12 @@
 {
     QStringList lines = chatEditLine->text().split('\n');
     chatEditLine->rememberCurrentText();
+    foreach (const QString &line, lines)
+    {
+        if (!parseCommand(line))
+            emit chatLine(line);
+    }
     chatEditLine->clear();
-    foreach (const QString &line, lines)
-        emit chatLine(line);
 }
 
 
@@ -480,6 +521,13 @@
     if (chatStrings.size() > 250)
         chatStrings.removeFirst();
 
+    if (s_isTimeStamped)
+    {
+        QString tsMarkUp = "<span class=\"timestamp\">[%1]</span> ";
+        QTime now = QDateTime::currentDateTime().time();
+        line = tsMarkUp.arg(now.toString(":mm:ss")) + line;
+    }
+
     line = QString("<span class=\"%1\">%2</span>").arg(cssClass).arg(line);
 
     if (isHighlight)
@@ -490,7 +538,7 @@
 
     chatStrings.append(line);
 
-    chatText->setHtml(chatStrings.join("<br>"));
+    chatText->setHtml("<html><body>"+chatStrings.join("<br>")+"</body></html>");
 
     chatText->moveCursor(QTextCursor::End);
 }
@@ -502,7 +550,7 @@
 
     chatStrings.append("<hr>" + str + "<hr>");
 
-    chatText->setHtml(chatStrings.join("<br>"));
+    chatText->setHtml("<html><body>"+chatStrings.join("<br>")+"</body></html>");
 
     chatText->moveCursor(QTextCursor::End);
 }
@@ -705,3 +753,91 @@
 //      chatNicks->insertAction(0, acBan);
     }
 }
+
+void HWChatWidget::dragEnterEvent(QDragEnterEvent * event)
+{
+    if (event->mimeData()->hasUrls())
+    {
+        QList<QUrl> urls = event->mimeData()->urls();
+        QString url = urls[0].toString();
+        if (urls.count() == 1)
+            if (url.contains(QRegExp("^file://.*\\.css$")))
+                event->acceptProposedAction();
+    }
+}
+
+void HWChatWidget::dropEvent(QDropEvent * event)
+{
+    QFile file(
+        event->mimeData()->urls()[0].toString().remove(QRegExp("^file://")));
+
+    if (file.exists() && (file.open(QIODevice::ReadOnly | QIODevice::Text)))
+    {
+        QString style;
+        QTextStream in(&file);
+        while (!in.atEnd())
+        {
+            QString line = in.readLine();
+            if(!line.isEmpty())
+                style.append(line);
+        }
+
+        setStyleSheet(style);
+        chatText->document()->setDefaultStyleSheet(*s_styleSheet);
+        displayNotice(tr("Stylesheet replaced! Enter %1 if you want to use it in future, enter %2 to reset!").arg("/saveStyleSheet").arg("/discaredStyleSheet"));
+
+        event->acceptProposedAction();
+    }
+}
+
+
+void HWChatWidget::discardStyleSheet()
+{
+    setStyleSheet();
+    chatText->document()->setDefaultStyleSheet(*s_styleSheet);
+    displayNotice(tr("StyleSheet discarded"));
+}
+
+
+void HWChatWidget::saveStyleSheet()
+{
+    QString dest =
+        HWDataManager::instance().findFileForWrite("css/chat.css");
+
+    QFile file(dest);
+    if (file.open(QIODevice::WriteOnly | QIODevice::Text))
+    {
+        QTextStream out(&file);
+        out << *s_styleSheet;
+        file.close();
+        displayNotice(tr("StyleSheet saved to %1").arg(dest));
+    }
+    else
+        displayError(tr("StyleSheet could NOT be saved to %1 !").arg(dest));
+}
+
+
+bool HWChatWidget::parseCommand(const QString & line)
+{
+    if (line[0] == '/')
+    {
+        QString tline = line.trimmed();
+        if (tline.startsWith("/me"))
+            return false; // not a real command
+
+        else if (tline == "/discardStyleSheet")
+            discardStyleSheet();
+        else if (tline == "/saveStyleSheet")
+            saveStyleSheet();
+        else
+        {
+            static QRegExp post("\\s.*$");
+            tline.remove(post);
+            displayWarning(tr("%1 is not a valid command!").arg(tline));
+        }
+
+        return true;
+    }
+
+    return false;
+}
--- a/QTfrontend/ui/widget/chatwidget.h	Mon Oct 24 06:54:46 2011 +0200
+++ b/QTfrontend/ui/widget/chatwidget.h	Mon Oct 24 10:30:47 2011 +0200
@@ -24,6 +24,7 @@
 #include <QListWidget>
 #include <QString>
 #include <QGridLayout>
+#include <QMutex>
 #include <QRegExp>
 
 #include "SDLInteraction.h"
@@ -78,16 +79,27 @@
   void displayNotice(const QString & message);
   void displayWarning(const QString & message);
 
+protected:
+    virtual void dragEnterEvent(QDragEnterEvent * event);
+    virtual void dropEvent(QDropEvent * event);
+
 private:
   static QString * s_styleSheet;
   static QStringList * s_displayNone;
+  static bool s_isTimeStamped;
+  static QMutex s_styleSheetMutex;
+  static const QRegExp URLREGEXP;
+
+  static void setStyleSheet(const QString & styleSheet = "");
 
   void loadList(QStringList & list, const QString & file);
   void saveList(QStringList & list, const QString & file);
   void updateNickItem(QListWidgetItem *item);
   void updateNickItems();
   void addLine(const QString & cssClass, QString line, bool isHighlight = false);
-  static const QRegExp URLREGEXP;
+  bool parseCommand(const QString & line);
+  void discardStyleSheet();
+  void saveStyleSheet();
 
  public slots:
   void onChatString(const QString& str);