***************************************************************************/
#include <QApplication>
+#include "qssparser.h"
#include "quassel.h"
#include "uistyle.h"
#include "uisettings.h"
_customFormats[type] = s.customFormat(type);
}
+ // Check for the sender auto coloring option
+ _senderAutoColor = s.value("Colors/SenderAutoColor", false).toBool();
+
// Now initialize the mapping between FormatCodes and FormatTypes...
_formatCodes["%O"] = None;
_formatCodes["%B"] = Bold;
QTextCharFormat underline; underline.setFontUnderline(true);
setFormat(Underline, underline, Settings::Default);
-
- // All other formats should be defined in derived classes.
+*/
+ loadStyleSheet();
}
UiStyle::~ UiStyle() {
- qDeleteAll(_cachedFontMetrics);
+ qDeleteAll(_metricsCache);
}
void UiStyle::setFormat(FormatType ftype, QTextCharFormat fmt, Settings::Mode mode) {
}
}
// TODO: invalidate only affected cached formats... if that's possible with less overhead than just rebuilding them
- _cachedFormats.clear();
- _cachedFontMetrics.clear();
+ qDeleteAll(_metricsCache);
+ _metricsCache.clear();
+ _formatCache.clear();
+}
+
+void UiStyle::setSenderAutoColor( bool state ) {
+ _senderAutoColor = state;
+ UiStyleSettings s(_settingsKey);
+ s.setValue("Colors/SenderAutoColor", QVariant(state));
}
QTextCharFormat UiStyle::format(FormatType ftype, Settings::Mode mode) const {
- // TODO: implement setting for nick autocoloring and make a check for it here
- if ( (ftype & 0x00000fff) == Sender )
- {
- // If it is not enabled just set ftype to Sender and go on
+ // Check for enabled sender auto coloring
+ if ( (ftype & 0x00000fff) == Sender && !_senderAutoColor ) {
+ // Just use the default sender style if auto coloring is disabled FIXME
+ ftype = Sender;
}
if(mode == Settings::Custom && _customFormats.contains(ftype)) return _customFormats.value(ftype);
else return _defaultFormats.value(ftype, QTextCharFormat());
}
+QTextCharFormat UiStyle::cachedFormat(quint64 key) const {
+ return _formatCache.value(key, QTextCharFormat());
+}
+
+QTextCharFormat UiStyle::cachedFormat(quint32 formatType, quint32 messageLabel) const {
+ return cachedFormat(formatType | ((quint64)messageLabel << 32));
+}
+
+void UiStyle::setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) {
+ _formatCache[formatType | ((quint64)messageLabel << 32)] = format;
+}
+
+// Merge a subelement format into an existing message format
+void UiStyle::mergeSubElementFormat(QTextCharFormat& fmt, quint32 ftype, quint32 label) {
+ quint64 key = ftype | ((quint64)label << 32);
+
+ // start with the most general format and then specialize
+ fmt.merge(cachedFormat(key & 0x00000000fffffff0)); // basic subelement format
+ fmt.merge(cachedFormat(key & 0x00000000ffffffff)); // subelement + msgtype
+ fmt.merge(cachedFormat(key & 0xffff0000fffffff0)); // subelement + nickhash
+ fmt.merge(cachedFormat(key & 0xffff0000ffffffff)); // subelement + nickhash + msgtype
+ fmt.merge(cachedFormat(key & 0x0000fffffffffff0)); // label + subelement
+ fmt.merge(cachedFormat(key & 0x0000ffffffffffff)); // label + subelement + msgtype
+ fmt.merge(cachedFormat(key & 0xfffffffffffffff0)); // label + subelement + nickhash
+ fmt.merge(cachedFormat(key & 0xffffffffffffffff)); // label + subelement + nickhash + msgtype
+}
+
// NOTE: This function is intimately tied to the values in FormatType. Don't change this
// until you _really_ know what you do!
-QTextCharFormat UiStyle::mergedFormat(quint32 ftype) {
- if(_cachedFormats.contains(ftype)) return _cachedFormats.value(ftype);
- if(ftype == Invalid) return QTextCharFormat();
- // Now we construct the merged format, starting with the default
- QTextCharFormat fmt = format(None);
- // First: general message format
- fmt.merge(format((FormatType)(ftype & 0x0f)));
- // now more specific ones
- for(quint32 mask = 0x0010; mask <= 0x2000; mask <<= 1) {
- if(ftype & mask) fmt.merge(format((FormatType)mask));
+QTextCharFormat UiStyle::mergedFormat(quint32 ftype, quint32 label) {
+ if(ftype == Invalid)
+ return QTextCharFormat();
+
+ quint64 key = ftype | ((quint64)label << 32);
+
+ // check if we have exactly this format readily cached already
+ QTextCharFormat fmt = cachedFormat(key);
+ if(fmt.isValid())
+ return fmt;
+
+ fmt.merge(cachedFormat(key & 0x0000000000000000)); // basic
+ fmt.merge(cachedFormat(key & 0x000000000000000f)); // msgtype
+ fmt.merge(cachedFormat(key & 0x0000ffff00000000)); // label
+ fmt.merge(cachedFormat(key & 0x0000ffff0000000f)); // label + msgtype
+
+ // TODO: allow combinations for mirc formats and colors (each), e.g. setting a special format for "bold and italic"
+ // or "foreground 01 and background 03"
+ if((ftype & 0xfff0)) { // element format
+ for(quint32 mask = 0x10; mask <= 0x2000; mask <<= 1) {
+ if(ftype & mask) {
+ mergeSubElementFormat(fmt, ftype & 0xffff, label);
+ }
+ }
}
- // color codes!
- if(ftype & 0x00400000) fmt.merge(format((FormatType)(ftype & 0x0f400000))); // foreground
- if(ftype & 0x00800000) fmt.merge(format((FormatType)(ftype & 0xf0800000))); // background
- // Sender auto colors
- if((ftype & 0xfff) == 0x200 && (ftype & 0xff000200) != 0x200) fmt.merge(format((FormatType)(ftype & 0xff000200)));
+
+ // Now we handle color codes
+ if(ftype & 0x00400000)
+ mergeSubElementFormat(fmt, ftype & 0x0f400000, label); // foreground
+ if(ftype & 0x00800000)
+ mergeSubElementFormat(fmt, ftype & 0xf0800000, label); // background
+ if((ftype & 0x00c00000) == 0x00c00000)
+ mergeSubElementFormat(fmt, ftype & 0xffc00000, label); // combination
+
// URL
- if(ftype & Url) fmt.merge(format(Url));
- return _cachedFormats[ftype] = fmt;
+ if(ftype & Url)
+ mergeSubElementFormat(fmt, ftype & Url, label);
+
+ setCachedFormat(fmt, ftype, label);
+ return fmt;
}
-QFontMetricsF *UiStyle::fontMetrics(quint32 ftype) {
+QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) {
// QFontMetricsF is not assignable, so we need to store pointers :/
- if(_cachedFontMetrics.contains(ftype)) return _cachedFontMetrics.value(ftype);
- return (_cachedFontMetrics[ftype] = new QFontMetricsF(mergedFormat(ftype).font()));
+ quint64 key = ftype | ((quint64)label << 32);
+
+ if(_metricsCache.contains(key))
+ return _metricsCache.value(key);
+
+ return (_metricsCache[key] = new QFontMetricsF(mergedFormat(ftype, label).font()));
}
UiStyle::FormatType UiStyle::formatType(const QString & code) const {
t = tr("%D0%1").arg(txt); break;
case Message::Notice:
t = tr("%Dn%1").arg(txt); break;
+ case Message::Topic:
case Message::Server:
t = tr("%Ds%1").arg(txt); break;
case Message::Error:
return tr("<%1>").arg(plainSender()); break;
case Message::Notice:
return tr("[%1]").arg(plainSender()); break;
+ case Message::Topic:
case Message::Server:
return tr("*"); break;
case Message::Error:
}
UiStyle::FormatType UiStyle::StyledMessage::senderFormat() const {
- quint16 hash;
switch(type()) {
case Message::Plain:
- // To produce random like but stable nick colorings some sort of hashing should work best.
- // In this case we just use the qt function qChecksum which produces a
- // CRC16 hash. This should be fast and 16 bits are more than enough.
- hash = qChecksum(_sender.toAscii().data(), _sender.toAscii().size());
- return (UiStyle::FormatType)((((hash % 21) + 1) << 24) + 0x200);
+ // To produce random like but stable nick colorings some sort of hashing should work best.
+ // In this case we just use the qt function qChecksum which produces a
+ // CRC16 hash. This should be fast and 16 bits are more than enough.
+ {
+ QString nick = nickFromMask(sender()).toLower();
+ if(!nick.isEmpty()) {
+ int chopCount = 0;
+ while(nick[nick.count() - 1 - chopCount] == '_') {
+ chopCount++;
+ }
+ nick.chop(chopCount);
+ }
+ quint16 hash = qChecksum(nick.toAscii().data(), nick.toAscii().size());
+ return (UiStyle::FormatType)((((hash % 12) + 1) << 24) + 0x200); // FIXME: amount of sender colors hardwired
+ }
case Message::Notice:
return UiStyle::NoticeMsg; break;
+ case Message::Topic:
case Message::Server:
return UiStyle::ServerMsg; break;
case Message::Error:
}
return in;
}
+
+/***********************************************************************************/
+// Stylesheet handling
+/***********************************************************************************/
+
+void UiStyle::loadStyleSheet() {
+ QssParser parser;
+ parser.loadStyleSheet(qApp->styleSheet());
+
+ // TODO handle results
+ QApplication::setPalette(parser.palette());
+ //QApplication::setStyleSheet(qApp->styleSheet()); // reload with custom palette settings
+}