+ // 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, 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);
+ }
+ }
+ }
+
+ // 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)
+ mergeSubElementFormat(fmt, ftype & Url, label);
+
+ setCachedFormat(fmt, ftype, label);
+ return fmt;
+}
+
+QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) {
+ // QFontMetricsF is not assignable, so we need to store pointers :/
+ quint64 key = ftype | ((quint64)label << 32);
+
+ if(_metricsCache.contains(key))
+ return _metricsCache.value(key);
+
+ return (_metricsCache[key] = new QFontMetricsF(mergedFormat(ftype, label).font()));