common: Make frequently called util methods more efficient
[quassel.git] / src / qtui / qtuistyle.cpp
index 11f6c43..d167b2e 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2013 by the Quassel Project                        *
+ *   Copyright (C) 2005-2016 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
 #include "qtuistyle.h"
 
 #include <QFile>
+#include <QFileInfo>
 #include <QTextStream>
 
 QtUiStyle::QtUiStyle(QObject *parent) : UiStyle(parent)
 {
     ChatViewSettings s;
+    s.notify("UseCustomTimestampFormat", this, SLOT(updateUseCustomTimestampFormat()));
+    updateUseCustomTimestampFormat();
     s.notify("TimestampFormat", this, SLOT(updateTimestampFormatString()));
     updateTimestampFormatString();
+    s.notify("ShowSenderBrackets", this, SLOT(updateShowSenderBrackets()));
+    updateShowSenderBrackets();
+
+    // If no style sheet exists, generate it on first run.
+    initializeSettingsQss();
 }
 
 
 QtUiStyle::~QtUiStyle() {}
 
+void QtUiStyle::updateUseCustomTimestampFormat()
+{
+    ChatViewSettings s;
+    setUseCustomTimestampFormat(s.useCustomTimestampFormat());
+}
+
 void QtUiStyle::updateTimestampFormatString()
 {
     ChatViewSettings s;
     setTimestampFormatString(s.timestampFormatString());
 }
 
+void QtUiStyle::updateShowSenderBrackets()
+{
+    ChatViewSettings s;
+    enableSenderBrackets(s.showSenderBrackets());
+}
+
+
+void QtUiStyle::initializeSettingsQss()
+{
+    QFileInfo settingsQss(Quassel::configDirPath() + "settings.qss");
+    // Only initialize if it doesn't already exist
+    if (settingsQss.exists())
+        return;
+
+    // Generate and load the new stylesheet
+    generateSettingsQss();
+    reload();
+}
 
 void QtUiStyle::generateSettingsQss() const
 {
     QFile settingsQss(Quassel::configDirPath() + "settings.qss");
+
     if (!settingsQss.open(QFile::WriteOnly|QFile::Truncate)) {
         qWarning() << "Could not open" << settingsQss.fileName() << "for writing!";
         return;
@@ -94,12 +127,44 @@ void QtUiStyle::generateSettingsQss() const
         << "\n";
     }
 
-    if (s.value("UseSenderColors").toBool()) {
-        out << "\n// Sender Colors\n"
-            << "ChatLine::sender#plain[sender=\"self\"] { foreground: " << color("SenderSelf", s) << "; }\n\n";
+    if (s.value("UseSenderColors", true).toBool()) {
+        out << "\n// Sender Colors\n";
+        // Generate a color palette for easy reuse elsewhere
+        // NOTE: A color palette is not a complete replacement for specifying the colors below, as
+        // specifying the colors one-by-one instead of with QtUi::style()->brush(...) makes it easy
+        // to toggle the specific coloring of sender/nick at the cost of regenerating this file.
+        // See UiStyle::ColorRole
+        out << senderPaletteQss(s);
+
+        out << "ChatLine::sender#plain[sender=\"self\"] { foreground: palette(sender-color-self); }\n\n";
+
+        // Matches qssparser.cpp for UiStyle::PlainMsg
+        for (int i = 0; i < defaultSenderColors.count(); i++)
+            out << senderQss(i, "plain");
+
+        // Only color the nicks in CTCP ACTIONs if sender colors are enabled
+        if (s.value("UseSenderActionColors", true).toBool()) {
+            // For action messages, color the 'sender' column -and- the nick itself
+            out << "\n// Sender Nickname Colors for action messages\n"
+                << "ChatLine::sender#action[sender=\"self\"] { foreground: palette(sender-color-self); }\n"
+                << "ChatLine::nick#action[sender=\"self\"] { foreground: palette(sender-color-self); }\n\n";
+
+            // Matches qssparser.cpp for UiStyle::ActionMsg
+            for (int i = 0; i < defaultSenderColors.count(); i++)
+                out << senderQss(i, "action", true);
+        }
+
+        // Only color the nicks in CTCP ACTIONs if sender colors are enabled
+        if (s.value("UseNickGeneralColors", true).toBool()) {
+            // For action messages, color the 'sender' column -and- the nick itself
+            out << "\n// Nickname colors for all messages\n"
+                << "ChatLine::nick[sender=\"self\"] { foreground: palette(sender-color-self); }\n\n";
+
+            // Matches qssparser.cpp for any style of message (UiStyle::...)
+            for (int i = 0; i < defaultSenderColors.count(); i++)
+                out << nickQss(i);
+        }
 
-        for (int i = 0; i < 16; i++)
-            out << senderQss(i, s);
     }
 
     // ItemViews
@@ -134,9 +199,9 @@ void QtUiStyle::generateSettingsQss() const
 }
 
 
-QString QtUiStyle::color(const QString &key, UiSettings &settings) const
+QString QtUiStyle::color(const QString &key, UiSettings &settings, const QColor &defaultColor) const
 {
-    return settings.value(key).value<QColor>().name();
+    return settings.value(key, defaultColor).value<QColor>().name();
 }
 
 
@@ -160,12 +225,51 @@ QString QtUiStyle::msgTypeQss(const QString &msgType, const QString &key, UiSett
 }
 
 
-QString QtUiStyle::senderQss(int i, UiSettings &settings) const
+QString QtUiStyle::senderPaletteQss(UiSettings &settings) const
+{
+    QString result;
+    result += "Palette {\n";
+
+    // Generate entries for sender-color-self
+    result += QString("    sender-color-self: %1;\n")
+              .arg(color("SenderSelf", settings, defaultSenderColorSelf));
+
+    // Generate entries for sender-color-HASH
+    for (int i = 0; i < defaultSenderColors.count(); i++) {
+        QString dez = QString::number(i);
+        if (dez.length() == 1) dez.prepend('0');
+        result += QString("    sender-color-0%1: %2;\n")
+                .arg(QString::number(i, 16), color("Sender"+dez, settings, defaultSenderColors[i]));
+    }
+    result += "}\n\n";
+    return result;
+}
+
+
+QString QtUiStyle::senderQss(int i, const QString &messageType, bool includeNick) const
+{
+    QString dez = QString::number(i);
+    if (dez.length() == 1) dez.prepend('0');
+
+    if (includeNick) {
+        // Include the nickname in the color rules
+        return QString("ChatLine::sender#%1[sender=\"0%2\"] { foreground: palette(sender-color-0%2); }\n"
+                       "ChatLine::nick#%1[sender=\"0%2\"]   { foreground: palette(sender-color-0%2); }\n")
+                .arg(messageType, QString::number(i, 16));
+    } else {
+        return QString("ChatLine::sender#%1[sender=\"0%2\"] { foreground: palette(sender-color-0%2); }\n")
+                .arg(messageType, QString::number(i, 16));
+    }
+}
+
+
+QString QtUiStyle::nickQss(int i) const
 {
     QString dez = QString::number(i);
     if (dez.length() == 1) dez.prepend('0');
 
-    return QString("ChatLine::sender#plain[sender=\"0%1\"] { foreground: %2; }\n").arg(QString::number(i, 16), color("Sender"+dez, settings));
+    return QString("ChatLine::nick[sender=\"0%1\"]   { foreground: palette(sender-color-0%1); }\n")
+            .arg(QString::number(i, 16));
 }