From ac7a58dd970833da2336f6ce035ec55515bac0f1 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Tue, 6 Mar 2018 21:07:42 +0100 Subject: [PATCH] uistyle: Add more type-safety to UiStyle, and clean up a bit Migrate all UiStyle enums to be enum classes. Enforce explicit types instead of quint32 in most places using them, and handle MessageLabel in a more obvious fashion. A bunch of bit-wise operators had to be added to avoid lots of boilerplate when dealing with the enums. FormatList now holds the formats in a struct rather than as plain enum (or quint32) values. This will be needed for extended color support; as the format type cannot hold the hard-coded extended color values, the colors will be stored explicitly in the list and applied as appropriate. Also, in the quest to modernize the codebase, FormatList is now a std::vector rather than a QList. --- src/qtui/chatitem.cpp | 30 +-- src/qtui/chatitem.h | 2 +- src/qtui/chatline.cpp | 4 +- src/qtui/chatlinemodelitem.cpp | 33 +-- src/qtui/chatlinemodelitem.h | 8 +- src/qtui/markerlineitem.cpp | 4 +- src/qtui/topicwidget.cpp | 2 +- src/uisupport/qssparser.cpp | 245 +++++++++++----------- src/uisupport/qssparser.h | 16 +- src/uisupport/styledlabel.cpp | 4 +- src/uisupport/uisettings.cpp | 6 +- src/uisupport/uistyle.cpp | 358 ++++++++++++++++++++++----------- src/uisupport/uistyle.h | 80 ++++++-- 13 files changed, 479 insertions(+), 313 deletions(-) diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index 47106398..e9922d24 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -153,7 +153,7 @@ void ChatItem::initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode wrapM layout->setTextOption(option); QList formatRanges - = QtUi::style()->toTextLayoutList(formatList(), layout->text().length(), data(ChatLineModel::MsgLabelRole).toUInt()); + = QtUi::style()->toTextLayoutList(formatList(), layout->text().length(), data(ChatLineModel::MsgLabelRole).value()); layout->setAdditionalFormats(formatRanges); } @@ -257,11 +257,11 @@ void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, } -void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const +void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, quint16 start, quint16 end, UiStyle::FormatType overlayFmt) const { - for (int i = 0; i < fmtList.count(); i++) { + for (size_t i = 0; i < fmtList.size(); i++) { int fmtStart = fmtList.at(i).first; - int fmtEnd = (i < fmtList.count()-1 ? fmtList.at(i+1).first : data(MessageModel::DisplayRole).toString().length()); + int fmtEnd = (i < fmtList.size()-1 ? fmtList.at(i+1).first : data(MessageModel::DisplayRole).toString().length()); if (fmtEnd <= start) continue; @@ -270,15 +270,15 @@ void ChatItem::overlayFormat(UiStyle::FormatList &fmtList, int start, int end, q // split the format if necessary if (fmtStart < start) { - fmtList.insert(i, fmtList.at(i)); + fmtList.insert(fmtList.begin() + i, fmtList.at(i)); fmtList[++i].first = start; } if (end < fmtEnd) { - fmtList.insert(i, fmtList.at(i)); + fmtList.insert(fmtList.begin() + i, fmtList.at(i)); fmtList[i+1].first = end; } - fmtList[i].second |= overlayFmt; + fmtList[i].second.type |= overlayFmt; } } @@ -306,15 +306,15 @@ QVector ChatItem::selectionFormats() const UiStyle::FormatList fmtList = formatList(); - while (fmtList.count() > 1 && fmtList.at(1).first <= start) - fmtList.removeFirst(); + while (fmtList.size() > 1 && fmtList.at(1).first <= start) + fmtList.erase(fmtList.begin()); - fmtList.first().first = start; + fmtList.front().first = start; - while (fmtList.count() > 1 && fmtList.last().first >= end) - fmtList.removeLast(); + while (fmtList.size() > 1 && fmtList.back().first >= end) + fmtList.pop_back(); - return QtUi::style()->toTextLayoutList(fmtList, end, UiStyle::Selected|data(ChatLineModel::MsgLabelRole).toUInt()).toVector(); + return QtUi::style()->toTextLayoutList(fmtList, end, data(ChatLineModel::MsgLabelRole).value()|UiStyle::MessageLabel::Selected).toVector(); } @@ -567,7 +567,7 @@ ContentsChatItem::ContentsChatItem(const QPointF &pos, const qreal &width, ChatL QFontMetricsF *ContentsChatItem::fontMetrics() const { - return QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value().at(0).second, 0); + return QtUi::style()->fontMetrics(data(ChatLineModel::FormatRole).value().at(0).second.type, UiStyle::MessageLabel::None); } @@ -674,7 +674,7 @@ UiStyle::FormatList ContentsChatItem::formatList() const for (int i = 0; i < privateData()->clickables.count(); i++) { Clickable click = privateData()->clickables.at(i); if (click.type() == Clickable::Url) { - overlayFormat(fmtList, click.start(), click.start() + click.length(), UiStyle::Url); + overlayFormat(fmtList, click.start(), click.start() + click.length(), UiStyle::FormatType::Url); } } return fmtList; diff --git a/src/qtui/chatitem.h b/src/qtui/chatitem.h index 7a2b562d..2051fab6 100644 --- a/src/qtui/chatitem.h +++ b/src/qtui/chatitem.h @@ -114,7 +114,7 @@ protected: void paintBackground(QPainter *); QVector selectionFormats() const; virtual QVector additionalFormats() const; - void overlayFormat(UiStyle::FormatList &fmtList, int start, int end, quint32 overlayFmt) const; + void overlayFormat(UiStyle::FormatList &fmtList, quint16 start, quint16 end, UiStyle::FormatType overlayFmt) const; inline qint16 selectionStart() const { return _selectionStart; } inline void setSelectionStart(qint16 start) { _selectionStart = start; } diff --git a/src/qtui/chatline.cpp b/src/qtui/chatline.cpp index db23428c..0c666220 100644 --- a/src/qtui/chatline.cpp +++ b/src/qtui/chatline.cpp @@ -215,7 +215,7 @@ void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, const QAbstractItemModel *model_ = model(); QModelIndex myIdx = model_->index(row(), 0); Message::Type type = (Message::Type)myIdx.data(MessageModel::TypeRole).toInt(); - UiStyle::MessageLabel label = (UiStyle::MessageLabel)myIdx.data(ChatLineModel::MsgLabelRole).toInt(); + UiStyle::MessageLabel label = myIdx.data(ChatLineModel::MsgLabelRole).value(); QTextCharFormat msgFmt = QtUi::style()->format(UiStyle::formatType(type), label); if (msgFmt.hasProperty(QTextFormat::BackgroundBrush)) { @@ -223,7 +223,7 @@ void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, } if (_selection & Selected) { - QTextCharFormat selFmt = QtUi::style()->format(UiStyle::formatType(type), label | UiStyle::Selected); + QTextCharFormat selFmt = QtUi::style()->format(UiStyle::formatType(type), label | UiStyle::MessageLabel::Selected); if (selFmt.hasProperty(QTextFormat::BackgroundBrush)) { qreal left = item((ChatLineModel::ColumnType)(_selection & ItemMask))->pos().x(); QRectF selectRect(left, 0, width() - left, height()); diff --git a/src/qtui/chatlinemodelitem.cpp b/src/qtui/chatlinemodelitem.cpp index 50002215..5582fe87 100644 --- a/src/qtui/chatlinemodelitem.cpp +++ b/src/qtui/chatlinemodelitem.cpp @@ -76,7 +76,7 @@ bool ChatLineModelItem::setData(int column, const QVariant &value, int role) QVariant ChatLineModelItem::data(int column, int role) const { if (role == ChatLineModel::MsgLabelRole) - return messageLabel(); + return QVariant::fromValue(messageLabel()); QVariant variant; MessageModel::ColumnType col = (MessageModel::ColumnType)column; @@ -107,12 +107,11 @@ QVariant ChatLineModelItem::timestampData(int role) const case ChatLineModel::EditRole: return _styledMsg.timestamp(); case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Timestamp); + return backgroundBrush(UiStyle::FormatType::Timestamp); case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Timestamp, true); + return backgroundBrush(UiStyle::FormatType::Timestamp, true); case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() - << qMakePair((quint16)0, (quint32) UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp)); + return QVariant::fromValue({std::make_pair(quint16{0}, UiStyle::Format{UiStyle::formatType(_styledMsg.type()) | UiStyle::FormatType::Timestamp})}); } return QVariant(); } @@ -126,12 +125,11 @@ QVariant ChatLineModelItem::senderData(int role) const case ChatLineModel::EditRole: return _styledMsg.plainSender(); case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Sender); + return backgroundBrush(UiStyle::FormatType::Sender); case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Sender, true); + return backgroundBrush(UiStyle::FormatType::Sender, true); case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() - << qMakePair((quint16)0, (quint32) UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender)); + return QVariant::fromValue({std::make_pair(quint16{0}, UiStyle::Format{UiStyle::formatType(_styledMsg.type()) | UiStyle::FormatType::Sender})}); } return QVariant(); } @@ -144,9 +142,9 @@ QVariant ChatLineModelItem::contentsData(int role) const case ChatLineModel::EditRole: return _styledMsg.plainContents(); case ChatLineModel::BackgroundRole: - return backgroundBrush(UiStyle::Contents); + return backgroundBrush(UiStyle::FormatType::Contents); case ChatLineModel::SelectedBackgroundRole: - return backgroundBrush(UiStyle::Contents, true); + return backgroundBrush(UiStyle::FormatType::Contents, true); case ChatLineModel::FormatRole: return QVariant::fromValue(_styledMsg.contentsFormatList()); case ChatLineModel::WrapListRole: @@ -158,20 +156,23 @@ QVariant ChatLineModelItem::contentsData(int role) const } -quint32 ChatLineModelItem::messageLabel() const +UiStyle::MessageLabel ChatLineModelItem::messageLabel() const { - quint32 label = _styledMsg.senderHash() << 16; + using MessageLabel = UiStyle::MessageLabel; + + MessageLabel label = static_cast(_styledMsg.senderHash() << 16); if (_styledMsg.flags() & Message::Self) - label |= UiStyle::OwnMsg; + label |= MessageLabel::OwnMsg; if (_styledMsg.flags() & Message::Highlight) - label |= UiStyle::Highlight; + label |= MessageLabel::Highlight; return label; } QVariant ChatLineModelItem::backgroundBrush(UiStyle::FormatType subelement, bool selected) const { - QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel() | (selected ? UiStyle::Selected : 0)); + QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, + messageLabel() | (selected ? UiStyle::MessageLabel::Selected : UiStyle::MessageLabel::None)); if (fmt.hasProperty(QTextFormat::BackgroundBrush)) return QVariant::fromValue(fmt.background()); return QVariant(); diff --git a/src/qtui/chatlinemodelitem.h b/src/qtui/chatlinemodelitem.h index 5e03e0c8..e48b1cd1 100644 --- a/src/qtui/chatlinemodelitem.h +++ b/src/qtui/chatlinemodelitem.h @@ -18,8 +18,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef CHATLINEMODELITEM_H_ -#define CHATLINEMODELITEM_H_ +#pragma once #include "messagemodel.h" @@ -58,7 +57,7 @@ private: QVariant contentsData(int role) const; QVariant backgroundBrush(UiStyle::FormatType subelement, bool selected = false) const; - quint32 messageLabel() const; + UiStyle::MessageLabel messageLabel() const; void computeWrapList() const; @@ -68,6 +67,3 @@ private: static unsigned char *TextBoundaryFinderBuffer; static int TextBoundaryFinderBufferSize; }; - - -#endif diff --git a/src/qtui/markerlineitem.cpp b/src/qtui/markerlineitem.cpp index 33363418..68d681ac 100644 --- a/src/qtui/markerlineitem.cpp +++ b/src/qtui/markerlineitem.cpp @@ -45,13 +45,13 @@ void MarkerLineItem::setChatLine(ChatLine *line) void MarkerLineItem::styleChanged() { - _brush = QtUi::style()->brush(UiStyle::MarkerLine); + _brush = QtUi::style()->brush(UiStyle::ColorRole::MarkerLine); // if this is a solid color, we assume 1px because wesurely don't surely don't want to fill the entire chatline. // else, use the height of a single line of text to play around with gradients etc. qreal height = 1.; if (_brush.style() != Qt::SolidPattern) - height = QtUi::style()->fontMetrics(QtUiStyle::PlainMsg, 0)->lineSpacing(); + height = QtUi::style()->fontMetrics(QtUiStyle::FormatType::PlainMsg, UiStyle::MessageLabel::None)->lineSpacing(); prepareGeometryChange(); _boundingRect = QRectF(0, 0, scene() ? scene()->width() : 100, height); diff --git a/src/qtui/topicwidget.cpp b/src/qtui/topicwidget.cpp index b449f12a..712e74ca 100644 --- a/src/qtui/topicwidget.cpp +++ b/src/qtui/topicwidget.cpp @@ -202,7 +202,7 @@ void TopicWidget::updateResizeMode() void TopicWidget::clickableActivated(const Clickable &click) { NetworkId networkId = selectionModel()->currentIndex().data(NetworkModel::NetworkIdRole).value(); - UiStyle::StyledString sstr = GraphicalUi::uiStyle()->styleString(GraphicalUi::uiStyle()->mircToInternal(_topic), UiStyle::PlainMsg); + UiStyle::StyledString sstr = GraphicalUi::uiStyle()->styleString(GraphicalUi::uiStyle()->mircToInternal(_topic), UiStyle::FormatType::PlainMsg); click.activate(networkId, sstr.plainText); } diff --git a/src/uisupport/qssparser.cpp b/src/uisupport/qssparser.cpp index 50c8c321..24032fbf 100644 --- a/src/uisupport/qssparser.cpp +++ b/src/uisupport/qssparser.cpp @@ -18,6 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ +#include +#include + #include #include "qssparser.h" @@ -49,27 +52,27 @@ QssParser::QssParser() _paletteColorRoles["window"] = QPalette::Window; _paletteColorRoles["window-text"] = QPalette::WindowText; - _uiStylePalette = QVector(UiStyle::NumRoles, QBrush()); + _uiStylePalette = QVector(static_cast(UiStyle::ColorRole::NumRoles), QBrush()); - _uiStyleColorRoles["marker-line"] = UiStyle::MarkerLine; + _uiStyleColorRoles["marker-line"] = UiStyle::ColorRole::MarkerLine; // Sender colors - _uiStyleColorRoles["sender-color-self"] = UiStyle::SenderColorSelf; - _uiStyleColorRoles["sender-color-00"] = UiStyle::SenderColor00; - _uiStyleColorRoles["sender-color-01"] = UiStyle::SenderColor01; - _uiStyleColorRoles["sender-color-02"] = UiStyle::SenderColor02; - _uiStyleColorRoles["sender-color-03"] = UiStyle::SenderColor03; - _uiStyleColorRoles["sender-color-04"] = UiStyle::SenderColor04; - _uiStyleColorRoles["sender-color-05"] = UiStyle::SenderColor05; - _uiStyleColorRoles["sender-color-06"] = UiStyle::SenderColor06; - _uiStyleColorRoles["sender-color-07"] = UiStyle::SenderColor07; - _uiStyleColorRoles["sender-color-08"] = UiStyle::SenderColor08; - _uiStyleColorRoles["sender-color-09"] = UiStyle::SenderColor09; - _uiStyleColorRoles["sender-color-0a"] = UiStyle::SenderColor0a; - _uiStyleColorRoles["sender-color-0b"] = UiStyle::SenderColor0b; - _uiStyleColorRoles["sender-color-0c"] = UiStyle::SenderColor0c; - _uiStyleColorRoles["sender-color-0d"] = UiStyle::SenderColor0d; - _uiStyleColorRoles["sender-color-0e"] = UiStyle::SenderColor0e; - _uiStyleColorRoles["sender-color-0f"] = UiStyle::SenderColor0f; + _uiStyleColorRoles["sender-color-self"] = UiStyle::ColorRole::SenderColorSelf; + _uiStyleColorRoles["sender-color-00"] = UiStyle::ColorRole::SenderColor00; + _uiStyleColorRoles["sender-color-01"] = UiStyle::ColorRole::SenderColor01; + _uiStyleColorRoles["sender-color-02"] = UiStyle::ColorRole::SenderColor02; + _uiStyleColorRoles["sender-color-03"] = UiStyle::ColorRole::SenderColor03; + _uiStyleColorRoles["sender-color-04"] = UiStyle::ColorRole::SenderColor04; + _uiStyleColorRoles["sender-color-05"] = UiStyle::ColorRole::SenderColor05; + _uiStyleColorRoles["sender-color-06"] = UiStyle::ColorRole::SenderColor06; + _uiStyleColorRoles["sender-color-07"] = UiStyle::ColorRole::SenderColor07; + _uiStyleColorRoles["sender-color-08"] = UiStyle::ColorRole::SenderColor08; + _uiStyleColorRoles["sender-color-09"] = UiStyle::ColorRole::SenderColor09; + _uiStyleColorRoles["sender-color-0a"] = UiStyle::ColorRole::SenderColor0a; + _uiStyleColorRoles["sender-color-0b"] = UiStyle::ColorRole::SenderColor0b; + _uiStyleColorRoles["sender-color-0c"] = UiStyle::ColorRole::SenderColor0c; + _uiStyleColorRoles["sender-color-0d"] = UiStyle::ColorRole::SenderColor0d; + _uiStyleColorRoles["sender-color-0e"] = UiStyle::ColorRole::SenderColor0e; + _uiStyleColorRoles["sender-color-0f"] = UiStyle::ColorRole::SenderColor0f; } @@ -79,12 +82,12 @@ void QssParser::processStyleSheet(QString &ss) return; // Remove C-style comments /* */ or // - QRegExp commentRx("(//.*(\\n|$)|/\\*.*\\*/)"); + static QRegExp commentRx("(//.*(\\n|$)|/\\*.*\\*/)"); commentRx.setMinimal(true); ss.remove(commentRx); // Palette definitions first, so we can apply roles later on - QRegExp paletterx("(Palette[^{]*)\\{([^}]+)\\}"); + static const QRegExp paletterx("(Palette[^{]*)\\{([^}]+)\\}"); int pos = 0; while ((pos = paletterx.indexIn(ss, pos)) >= 0) { parsePaletteBlock(paletterx.cap(1).trimmed(), paletterx.cap(2).trimmed()); @@ -92,7 +95,7 @@ void QssParser::processStyleSheet(QString &ss) } // Now we can parse the rest of our custom blocks - QRegExp blockrx("((?:ChatLine|ChatListItem|NickListItem)[^{]*)\\{([^}]+)\\}"); + static const QRegExp blockrx("((?:ChatLine|ChatListItem|NickListItem)[^{]*)\\{([^}]+)\\}"); pos = 0; while ((pos = blockrx.indexIn(ss, pos)) >= 0) { //qDebug() << blockrx.cap(1) << blockrx.cap(2); @@ -115,18 +118,20 @@ void QssParser::processStyleSheet(QString &ss) void QssParser::parseChatLineBlock(const QString &decl, const QString &contents) { - quint64 fmtType = parseFormatType(decl); - if (fmtType == UiStyle::Invalid) + UiStyle::FormatType fmtType; + UiStyle::MessageLabel label; + std::tie(fmtType, label) = parseFormatType(decl); + if (fmtType == UiStyle::FormatType::Invalid) return; - _formats[fmtType].merge(parseFormat(contents)); + _formats[fmtType|label].merge(parseFormat(contents)); } void QssParser::parseListItemBlock(const QString &decl, const QString &contents) { - quint32 fmtType = parseItemFormatType(decl); - if (fmtType == UiStyle::Invalid) + UiStyle::ItemFormatType fmtType = parseItemFormatType(decl); + if (fmtType == UiStyle::ItemFormatType::Invalid) return; _listItemFormats[fmtType].merge(parseFormat(contents)); @@ -141,7 +146,7 @@ void QssParser::parsePaletteBlock(const QString &decl, const QString &contents) QList colorGroups; // Check if we want to apply this palette definition for particular ColorGroups - QRegExp rx("Palette((:(normal|active|inactive|disabled))*)"); + static const QRegExp rx("Palette((:(normal|active|inactive|disabled))*)"); if (!rx.exactMatch(decl)) { qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); return; @@ -178,7 +183,7 @@ void QssParser::parsePaletteBlock(const QString &decl, const QString &contents) _palette.setBrush(_paletteColorRoles.value(rolestr), brush); } else if (_uiStyleColorRoles.contains(rolestr)) { - _uiStylePalette[_uiStyleColorRoles.value(rolestr)] = parseBrush(brushstr); + _uiStylePalette[static_cast(_uiStyleColorRoles.value(rolestr))] = parseBrush(brushstr); } else qWarning() << Q_FUNC_INFO << tr("Unknown palette role name: %1").arg(rolestr); @@ -188,184 +193,190 @@ void QssParser::parsePaletteBlock(const QString &decl, const QString &contents) /******** Determine format types from a block declaration ********/ -quint64 QssParser::parseFormatType(const QString &decl) +std::pair QssParser::parseFormatType(const QString &decl) { - QRegExp rx("ChatLine(?:::(\\w+))?(?:#([\\w\\-]+))?(?:\\[([=-,\\\"\\w\\s]+)\\])?"); + using FormatType = UiStyle::FormatType; + using MessageLabel = UiStyle::MessageLabel; + + const std::pair invalid{FormatType::Invalid, MessageLabel::None}; + + static const QRegExp rx("ChatLine(?:::(\\w+))?(?:#([\\w\\-]+))?(?:\\[([=-,\\\"\\w\\s]+)\\])?"); // $1: subelement; $2: msgtype; $3: conditionals if (!rx.exactMatch(decl)) { qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); - return UiStyle::Invalid; + return invalid; } QString subElement = rx.cap(1); QString msgType = rx.cap(2); QString conditions = rx.cap(3); - quint64 fmtType = 0; + FormatType fmtType{FormatType::Base}; + MessageLabel label{MessageLabel::None}; // First determine the subelement if (!subElement.isEmpty()) { if (subElement == "timestamp") - fmtType |= UiStyle::Timestamp; + fmtType |= FormatType::Timestamp; else if (subElement == "sender") - fmtType |= UiStyle::Sender; + fmtType |= FormatType::Sender; else if (subElement == "nick") - fmtType |= UiStyle::Nick; + fmtType |= FormatType::Nick; else if (subElement == "contents") - fmtType |= UiStyle::Contents; + fmtType |= FormatType::Contents; else if (subElement == "hostmask") - fmtType |= UiStyle::Hostmask; + fmtType |= FormatType::Hostmask; else if (subElement == "modeflags") - fmtType |= UiStyle::ModeFlags; + fmtType |= FormatType::ModeFlags; else if (subElement == "url") - fmtType |= UiStyle::Url; + fmtType |= FormatType::Url; else { qWarning() << Q_FUNC_INFO << tr("Invalid subelement name in %1").arg(decl); - return UiStyle::Invalid; + return invalid; } } // Now, figure out the message type if (!msgType.isEmpty()) { if (msgType == "plain") - fmtType |= UiStyle::PlainMsg; + fmtType |= FormatType::PlainMsg; else if (msgType == "notice") - fmtType |= UiStyle::NoticeMsg; + fmtType |= FormatType::NoticeMsg; else if (msgType == "action") - fmtType |= UiStyle::ActionMsg; + fmtType |= FormatType::ActionMsg; else if (msgType == "nick") - fmtType |= UiStyle::NickMsg; + fmtType |= FormatType::NickMsg; else if (msgType == "mode") - fmtType |= UiStyle::ModeMsg; + fmtType |= FormatType::ModeMsg; else if (msgType == "join") - fmtType |= UiStyle::JoinMsg; + fmtType |= FormatType::JoinMsg; else if (msgType == "part") - fmtType |= UiStyle::PartMsg; + fmtType |= FormatType::PartMsg; else if (msgType == "quit") - fmtType |= UiStyle::QuitMsg; + fmtType |= FormatType::QuitMsg; else if (msgType == "kick") - fmtType |= UiStyle::KickMsg; + fmtType |= FormatType::KickMsg; else if (msgType == "kill") - fmtType |= UiStyle::KillMsg; + fmtType |= FormatType::KillMsg; else if (msgType == "server") - fmtType |= UiStyle::ServerMsg; + fmtType |= FormatType::ServerMsg; else if (msgType == "info") - fmtType |= UiStyle::InfoMsg; + fmtType |= FormatType::InfoMsg; else if (msgType == "error") - fmtType |= UiStyle::ErrorMsg; + fmtType |= FormatType::ErrorMsg; else if (msgType == "daychange") - fmtType |= UiStyle::DayChangeMsg; + fmtType |= FormatType::DayChangeMsg; else if (msgType == "topic") - fmtType |= UiStyle::TopicMsg; + fmtType |= FormatType::TopicMsg; else if (msgType == "netsplit-join") - fmtType |= UiStyle::NetsplitJoinMsg; + fmtType |= FormatType::NetsplitJoinMsg; else if (msgType == "netsplit-quit") - fmtType |= UiStyle::NetsplitQuitMsg; + fmtType |= FormatType::NetsplitQuitMsg; else if (msgType == "invite") - fmtType |= UiStyle::InviteMsg; + fmtType |= FormatType::InviteMsg; else { qWarning() << Q_FUNC_INFO << tr("Invalid message type in %1").arg(decl); } } // Next up: conditional (formats, labels, nickhash) - QRegExp condRx("\\s*([\\w\\-]+)\\s*=\\s*\"(\\w+)\"\\s*"); + static const QRegExp condRx("\\s*([\\w\\-]+)\\s*=\\s*\"(\\w+)\"\\s*"); if (!conditions.isEmpty()) { foreach(const QString &cond, conditions.split(',', QString::SkipEmptyParts)) { if (!condRx.exactMatch(cond)) { qWarning() << Q_FUNC_INFO << tr("Invalid condition %1").arg(cond); - return UiStyle::Invalid; + return invalid; } QString condName = condRx.cap(1); QString condValue = condRx.cap(2); if (condName == "label") { - quint64 labeltype = 0; if (condValue == "highlight") - labeltype = UiStyle::Highlight; + label |= MessageLabel::Highlight; else if (condValue == "selected") - labeltype = UiStyle::Selected; + label |= MessageLabel::Selected; else { qWarning() << Q_FUNC_INFO << tr("Invalid message label: %1").arg(condValue); - return UiStyle::Invalid; + return invalid; } - fmtType |= (labeltype << 32); } else if (condName == "sender") { if (condValue == "self") - fmtType |= (quint64) UiStyle::OwnMsg << 32; // sender="self" is actually treated as a label + label |= MessageLabel::OwnMsg; // sender="self" is actually treated as a label else { bool ok = true; - quint64 val = condValue.toUInt(&ok, 16); + quint32 val = condValue.toUInt(&ok, 16); if (!ok) { qWarning() << Q_FUNC_INFO << tr("Invalid senderhash specification: %1").arg(condValue); - return UiStyle::Invalid; + return invalid; } if (val >= 16) { qWarning() << Q_FUNC_INFO << tr("Senderhash can be at most \"0x0f\"!"); - return UiStyle::Invalid; + return invalid; } - fmtType |= ++val << 48; + label |= static_cast(++val << 16); } } else if (condName == "format") { if (condValue == "bold") - fmtType |= UiStyle::Bold; + fmtType |= FormatType::Bold; else if (condValue == "italic") - fmtType |= UiStyle::Italic; + fmtType |= FormatType::Italic; else if (condValue == "underline") - fmtType |= UiStyle::Underline; + fmtType |= FormatType::Underline; else if (condValue == "reverse") - fmtType |= UiStyle::Reverse; + fmtType |= FormatType::Reverse; else { qWarning() << Q_FUNC_INFO << tr("Invalid format name: %1").arg(condValue); - return UiStyle::Invalid; + return invalid; } } else if (condName == "fg-color" || condName == "bg-color") { bool ok; - quint8 col = condValue.toUInt(&ok, 16); + quint32 col = condValue.toUInt(&ok, 16); if (!ok || col > 0x0f) { qWarning() << Q_FUNC_INFO << tr("Illegal IRC color specification (must be between 00 and 0f): %1").arg(condValue); - return UiStyle::Invalid; + return invalid; } if (condName == "fg-color") - fmtType |= 0x00400000 | (quint32)(col << 24); + fmtType |= 0x00400000 | (col << 24); else - fmtType |= 0x00800000 | (quint32)(col << 28); + fmtType |= 0x00800000 | (col << 28); } else { qWarning() << Q_FUNC_INFO << tr("Unhandled condition: %1").arg(condName); - return UiStyle::Invalid; + return invalid; } } } - return fmtType; + return std::make_pair(fmtType, label); } // FIXME: Code duplication -quint32 QssParser::parseItemFormatType(const QString &decl) +UiStyle::ItemFormatType QssParser::parseItemFormatType(const QString &decl) { - QRegExp rx("(Chat|Nick)ListItem(?:\\[([=-,\\\"\\w\\s]+)\\])?"); + using ItemFormatType = UiStyle::ItemFormatType; + + static const QRegExp rx("(Chat|Nick)ListItem(?:\\[([=-,\\\"\\w\\s]+)\\])?"); // $1: item type; $2: properties if (!rx.exactMatch(decl)) { qWarning() << Q_FUNC_INFO << tr("Invalid block declaration: %1").arg(decl); - return UiStyle::Invalid; + return ItemFormatType::Invalid; } QString mainItemType = rx.cap(1); QString properties = rx.cap(2); - quint32 fmtType = 0; + ItemFormatType fmtType{ItemFormatType::None}; // Next up: properties QString type, state; if (!properties.isEmpty()) { QHash props; - QRegExp propRx("\\s*([\\w\\-]+)\\s*=\\s*\"([\\w\\-]+)\"\\s*"); + static const QRegExp propRx("\\s*([\\w\\-]+)\\s*=\\s*\"([\\w\\-]+)\"\\s*"); foreach(const QString &prop, properties.split(',', QString::SkipEmptyParts)) { if (!propRx.exactMatch(prop)) { qWarning() << Q_FUNC_INFO << tr("Invalid proplist %1").arg(prop); - return UiStyle::Invalid; + return ItemFormatType::Invalid; } props[propRx.cap(1)] = propRx.cap(2); } @@ -374,46 +385,46 @@ quint32 QssParser::parseItemFormatType(const QString &decl) } if (mainItemType == "Chat") { - fmtType |= UiStyle::BufferViewItem; + fmtType |= ItemFormatType::BufferViewItem; if (!type.isEmpty()) { if (type == "network") - fmtType |= UiStyle::NetworkItem; + fmtType |= ItemFormatType::NetworkItem; else if (type == "channel") - fmtType |= UiStyle::ChannelBufferItem; + fmtType |= ItemFormatType::ChannelBufferItem; else if (type == "query") - fmtType |= UiStyle::QueryBufferItem; + fmtType |= ItemFormatType::QueryBufferItem; else { qWarning() << Q_FUNC_INFO << tr("Invalid chatlist item type %1").arg(type); - return UiStyle::Invalid; + return ItemFormatType::Invalid; } } if (!state.isEmpty()) { if (state == "inactive") - fmtType |= UiStyle::InactiveBuffer; + fmtType |= ItemFormatType::InactiveBuffer; else if (state == "channel-event") - fmtType |= UiStyle::ActiveBuffer; + fmtType |= ItemFormatType::ActiveBuffer; else if (state == "unread-message") - fmtType |= UiStyle::UnreadBuffer; + fmtType |= ItemFormatType::UnreadBuffer; else if (state == "highlighted") - fmtType |= UiStyle::HighlightedBuffer; + fmtType |= ItemFormatType::HighlightedBuffer; else if (state == "away") - fmtType |= UiStyle::UserAway; + fmtType |= ItemFormatType::UserAway; else { qWarning() << Q_FUNC_INFO << tr("Invalid chatlist state %1").arg(state); - return UiStyle::Invalid; + return ItemFormatType::Invalid; } } } else { // NickList - fmtType |= UiStyle::NickViewItem; + fmtType |= ItemFormatType::NickViewItem; if (!type.isEmpty()) { if (type == "user") { - fmtType |= UiStyle::IrcUserItem; + fmtType |= ItemFormatType::IrcUserItem; if (state == "away") - fmtType |= UiStyle::UserAway; + fmtType |= ItemFormatType::UserAway; } else if (type == "category") - fmtType |= UiStyle::UserCategoryItem; + fmtType |= ItemFormatType::UserCategoryItem; } } return fmtType; @@ -495,7 +506,7 @@ QBrush QssParser::parseBrush(const QString &str, bool *ok) // [0-9] Match any digit from 0-9 // Note that '\' must be escaped as '\\' // Helpful interactive website for debugging and explaining: https://regex101.com/ - QRegExp rx("palette\\s*\\(\\s*([a-z-0-9]+)\\s*\\)"); + static const QRegExp rx("palette\\s*\\(\\s*([a-z-0-9]+)\\s*\\)"); if (!rx.exactMatch(str)) { qWarning() << Q_FUNC_INFO << tr("Invalid palette color role specification: %1").arg(str); return QBrush(); @@ -503,13 +514,13 @@ QBrush QssParser::parseBrush(const QString &str, bool *ok) if (_paletteColorRoles.contains(rx.cap(1))) return QBrush(_palette.brush(_paletteColorRoles.value(rx.cap(1)))); if (_uiStyleColorRoles.contains(rx.cap(1))) - return QBrush(_uiStylePalette.at(_uiStyleColorRoles.value(rx.cap(1)))); + return QBrush(_uiStylePalette.at(static_cast(_uiStyleColorRoles.value(rx.cap(1))))); qWarning() << Q_FUNC_INFO << tr("Unknown palette color role: %1").arg(rx.cap(1)); return QBrush(); } else if (str.startsWith("qlineargradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qlineargradient\\s*\\(\\s*x1:%1,\\s*y1:%1,\\s*x2:%1,\\s*y2:%1,(.+)\\)").arg(rxFloat)); + static const QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + static const QRegExp rx(QString("qlineargradient\\s*\\(\\s*x1:%1,\\s*y1:%1,\\s*x2:%1,\\s*y2:%1,(.+)\\)").arg(rxFloat)); if (!rx.exactMatch(str)) { qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); return QBrush(); @@ -531,8 +542,8 @@ QBrush QssParser::parseBrush(const QString &str, bool *ok) return QBrush(gradient); } else if (str.startsWith("qconicalgradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qconicalgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*angle:%1,(.+)\\)").arg(rxFloat)); + static const QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + static const QRegExp rx(QString("qconicalgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*angle:%1,(.+)\\)").arg(rxFloat)); if (!rx.exactMatch(str)) { qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); return QBrush(); @@ -553,8 +564,8 @@ QBrush QssParser::parseBrush(const QString &str, bool *ok) return QBrush(gradient); } else if (str.startsWith("qradialgradient")) { - static QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); - QRegExp rx(QString("qradialgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*radius:%1,\\s*fx:%1,\\s*fy:%1,(.+)\\)").arg(rxFloat)); + static const QString rxFloat("\\s*(-?\\s*[0-9]*\\.?[0-9]+)\\s*"); + static const QRegExp rx(QString("qradialgradient\\s*\\(\\s*cx:%1,\\s*cy:%1,\\s*radius:%1,\\s*fx:%1,\\s*fy:%1,(.+)\\)").arg(rxFloat)); if (!rx.exactMatch(str)) { qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str); return QBrush(); @@ -610,7 +621,7 @@ QColor QssParser::parseColor(const QString &str) } } else { - QRegExp rx("#?[0-9A-Fa-z]+"); + static const QRegExp rx("#?[0-9A-Fa-z]+"); if (rx.exactMatch(str)) return QColor(str); } @@ -622,7 +633,7 @@ QColor QssParser::parseColor(const QString &str) QssParser::ColorTuple QssParser::parseColorTuple(const QString &str) { ColorTuple result; - QRegExp rx("\\(((\\s*[0-9]{1,3}%?\\s*)(,\\s*[0-9]{1,3}%?\\s*)*)\\)"); + static const QRegExp rx("\\(((\\s*[0-9]{1,3}%?\\s*)(,\\s*[0-9]{1,3}%?\\s*)*)\\)"); if (!rx.exactMatch(str.trimmed())) { return ColorTuple(); } @@ -651,8 +662,8 @@ QGradientStops QssParser::parseGradientStops(const QString &str_) { QString str = str_; QGradientStops result; - static QString rxFloat("(0?\\.[0-9]+|[01])"); // values between 0 and 1 - QRegExp rx(QString("\\s*,?\\s*stop:\\s*(%1)\\s+([^:]+)(,\\s*stop:|$)").arg(rxFloat)); + static const QString rxFloat("(0?\\.[0-9]+|[01])"); // values between 0 and 1 + static const QRegExp rx(QString("\\s*,?\\s*stop:\\s*(%1)\\s+([^:]+)(,\\s*stop:|$)").arg(rxFloat)); int idx; while ((idx = rx.indexIn(str)) == 0) { qreal x = rx.cap(1).toDouble(); @@ -673,7 +684,7 @@ QGradientStops QssParser::parseGradientStops(const QString &str_) void QssParser::parseFont(const QString &value, QTextCharFormat *format) { - QRegExp rx("((?:(?:normal|italic|oblique|underline|bold|100|200|300|400|500|600|700|800|900) ){0,2}) ?(\\d+)(pt|px)? \"(.*)\""); + static const QRegExp rx("((?:(?:normal|italic|oblique|underline|bold|100|200|300|400|500|600|700|800|900) ){0,2}) ?(\\d+)(pt|px)? \"(.*)\""); if (!rx.exactMatch(value)) { qWarning() << Q_FUNC_INFO << tr("Invalid font specification: %1").arg(value); return; @@ -741,7 +752,7 @@ void QssParser::parseFontWeight(const QString &value, QTextCharFormat *format) void QssParser::parseFontSize(const QString &value, QTextCharFormat *format) { - QRegExp rx("(\\d+)(pt|px)"); + static const QRegExp rx("(\\d+)(pt|px)"); if (!rx.exactMatch(value)) { qWarning() << Q_FUNC_INFO << tr("Invalid font size specification: %1").arg(value); return; diff --git a/src/uisupport/qssparser.h b/src/uisupport/qssparser.h index 228b024f..1370c105 100644 --- a/src/uisupport/qssparser.h +++ b/src/uisupport/qssparser.h @@ -18,8 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef QSSPARSER_H_ -#define QSSPARSER_H_ +#pragma once + +#include #include "uistyle.h" @@ -35,7 +36,7 @@ public: inline QPalette palette() const { return _palette; } inline QVector uiStylePalette() const { return _uiStylePalette; } inline const QHash &formats() const { return _formats; } - inline const QHash &listItemFormats() const { return _listItemFormats; } + inline const QHash &listItemFormats() const { return _listItemFormats; } protected: typedef QList ColorTuple; @@ -44,8 +45,8 @@ protected: void parsePaletteBlock(const QString &decl, const QString &contents); void parseListItemBlock(const QString &decl, const QString &contents); - quint64 parseFormatType(const QString &decl); - quint32 parseItemFormatType(const QString &decl); + std::pair parseFormatType(const QString &decl); + UiStyle::ItemFormatType parseItemFormatType(const QString &decl); QTextCharFormat parseFormat(const QString &qss); @@ -69,8 +70,5 @@ private: QPalette _palette; QVector _uiStylePalette; QHash _formats; - QHash _listItemFormats; + QHash _listItemFormats; }; - - -#endif diff --git a/src/uisupport/styledlabel.cpp b/src/uisupport/styledlabel.cpp index dc13660e..059ab698 100644 --- a/src/uisupport/styledlabel.cpp +++ b/src/uisupport/styledlabel.cpp @@ -122,8 +122,8 @@ void StyledLabel::setText(const QString &text) { UiStyle *style = GraphicalUi::uiStyle(); - UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::PlainMsg); - QList layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), 0); + UiStyle::StyledString sstr = style->styleString(style->mircToInternal(text), UiStyle::FormatType::PlainMsg); + QList layoutList = style->toTextLayoutList(sstr.formatList, sstr.plainText.length(), UiStyle::MessageLabel::None); // Use default font rather than the style's QTextLayout::FormatRange fmtRange; diff --git a/src/uisupport/uisettings.cpp b/src/uisupport/uisettings.cpp index 49d3fcb3..9da5987a 100644 --- a/src/uisupport/uisettings.cpp +++ b/src/uisupport/uisettings.cpp @@ -39,19 +39,19 @@ UiStyleSettings::UiStyleSettings(const QString &subGroup) : UiSettings(QString(" void UiStyleSettings::setCustomFormat(UiStyle::FormatType ftype, QTextCharFormat format) { - setLocalValue(QString("Format/%1").arg(ftype), format); + setLocalValue(QString("Format/%1").arg(static_cast(ftype)), format); } QTextCharFormat UiStyleSettings::customFormat(UiStyle::FormatType ftype) { - return localValue(QString("Format/%1").arg(ftype), QTextFormat()).value().toCharFormat(); + return localValue(QString("Format/%1").arg(static_cast(ftype)), QTextFormat()).value().toCharFormat(); } void UiStyleSettings::removeCustomFormat(UiStyle::FormatType ftype) { - removeLocalKey(QString("Format/%1").arg(ftype)); + removeLocalKey(QString("Format/%1").arg(static_cast(ftype))); } diff --git a/src/uisupport/uistyle.cpp b/src/uisupport/uistyle.cpp index 3b9e079b..fc9ccb13 100644 --- a/src/uisupport/uistyle.cpp +++ b/src/uisupport/uistyle.cpp @@ -18,6 +18,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ +#include + #include #include @@ -55,20 +57,20 @@ UiStyle::UiStyle(QObject *parent) Q_ASSERT(QVariant::nameToType("UiStyle::FormatList") != QVariant::Invalid); } - _uiStylePalette = QVector(NumRoles, QBrush()); + _uiStylePalette = QVector(static_cast(ColorRole::NumRoles), QBrush()); // Now initialize the mapping between FormatCodes and FormatTypes... - _formatCodes["%O"] = Base; - _formatCodes["%B"] = Bold; - _formatCodes["%S"] = Italic; - _formatCodes["%U"] = Underline; - _formatCodes["%R"] = Reverse; - - _formatCodes["%DN"] = Nick; - _formatCodes["%DH"] = Hostmask; - _formatCodes["%DC"] = ChannelName; - _formatCodes["%DM"] = ModeFlags; - _formatCodes["%DU"] = Url; + _formatCodes["%O"] = FormatType::Base; + _formatCodes["%B"] = FormatType::Bold; + _formatCodes["%S"] = FormatType::Italic; + _formatCodes["%U"] = FormatType::Underline; + _formatCodes["%R"] = FormatType::Reverse; + + _formatCodes["%DN"] = FormatType::Nick; + _formatCodes["%DH"] = FormatType::Hostmask; + _formatCodes["%DC"] = FormatType::ChannelName; + _formatCodes["%DM"] = FormatType::ModeFlags; + _formatCodes["%DU"] = FormatType::Url; // Initialize fallback defaults // NOTE: If you change this, update qtui/chatviewsettings.h, too. More explanations available @@ -283,44 +285,44 @@ QVariant UiStyle::bufferViewItemData(const QModelIndex &index, int role) const } } - quint32 fmtType = BufferViewItem; + ItemFormatType fmtType = ItemFormatType::BufferViewItem; switch (type) { case BufferInfo::StatusBuffer: - fmtType |= NetworkItem; + fmtType |= ItemFormatType::NetworkItem; break; case BufferInfo::ChannelBuffer: - fmtType |= ChannelBufferItem; + fmtType |= ItemFormatType::ChannelBufferItem; break; case BufferInfo::QueryBuffer: - fmtType |= QueryBufferItem; + fmtType |= ItemFormatType::QueryBufferItem; break; default: return QVariant(); } - QTextCharFormat fmt = _listItemFormats.value(BufferViewItem); + QTextCharFormat fmt = _listItemFormats.value(ItemFormatType::BufferViewItem); fmt.merge(_listItemFormats.value(fmtType)); BufferInfo::ActivityLevel activity = (BufferInfo::ActivityLevel)index.data(NetworkModel::BufferActivityRole).toInt(); if (activity & BufferInfo::Highlight) { - fmt.merge(_listItemFormats.value(BufferViewItem | HighlightedBuffer)); - fmt.merge(_listItemFormats.value(fmtType | HighlightedBuffer)); + fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::HighlightedBuffer)); + fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::HighlightedBuffer)); } else if (activity & BufferInfo::NewMessage) { - fmt.merge(_listItemFormats.value(BufferViewItem | UnreadBuffer)); - fmt.merge(_listItemFormats.value(fmtType | UnreadBuffer)); + fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::UnreadBuffer)); + fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::UnreadBuffer)); } else if (activity & BufferInfo::OtherActivity) { - fmt.merge(_listItemFormats.value(BufferViewItem | ActiveBuffer)); - fmt.merge(_listItemFormats.value(fmtType | ActiveBuffer)); + fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::ActiveBuffer)); + fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::ActiveBuffer)); } else if (!isActive) { - fmt.merge(_listItemFormats.value(BufferViewItem | InactiveBuffer)); - fmt.merge(_listItemFormats.value(fmtType | InactiveBuffer)); + fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::InactiveBuffer)); + fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::InactiveBuffer)); } else if (index.data(NetworkModel::UserAwayRole).toBool()) { - fmt.merge(_listItemFormats.value(BufferViewItem | UserAway)); - fmt.merge(_listItemFormats.value(fmtType | UserAway)); + fmt.merge(_listItemFormats.value(ItemFormatType::BufferViewItem | ItemFormatType::UserAway)); + fmt.merge(_listItemFormats.value(fmtType | ItemFormatType::UserAway)); } return itemData(role, fmt); @@ -355,18 +357,18 @@ QVariant UiStyle::nickViewItemData(const QModelIndex &index, int role) const } } - QTextCharFormat fmt = _listItemFormats.value(NickViewItem); + QTextCharFormat fmt = _listItemFormats.value(ItemFormatType::NickViewItem); switch (type) { case NetworkModel::IrcUserItemType: - fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem)); + fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::IrcUserItem)); if (!index.data(NetworkModel::ItemActiveRole).toBool()) { - fmt.merge(_listItemFormats.value(NickViewItem | UserAway)); - fmt.merge(_listItemFormats.value(NickViewItem | IrcUserItem | UserAway)); + fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::UserAway)); + fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::IrcUserItem | ItemFormatType::UserAway)); } break; case NetworkModel::UserCategoryItemType: - fmt.merge(_listItemFormats.value(NickViewItem | UserCategoryItem)); + fmt.merge(_listItemFormats.value(ItemFormatType::NickViewItem | ItemFormatType::UserCategoryItem)); break; default: return QVariant(); @@ -399,22 +401,22 @@ QTextCharFormat UiStyle::format(quint64 key) const } -QTextCharFormat UiStyle::cachedFormat(quint32 formatType, quint32 messageLabel) const +QTextCharFormat UiStyle::cachedFormat(FormatType formatType, MessageLabel messageLabel) const { - return _formatCache.value(formatType | ((quint64)messageLabel << 32), QTextCharFormat()); + return _formatCache.value(formatType | messageLabel, QTextCharFormat()); } -void UiStyle::setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const +void UiStyle::setCachedFormat(const QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const { - _formatCache[formatType | ((quint64)messageLabel << 32)] = format; + _formatCache[formatType | messageLabel] = format; } -QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) const +QFontMetricsF *UiStyle::fontMetrics(FormatType ftype, MessageLabel label) const { // QFontMetricsF is not assignable, so we need to store pointers :/ - quint64 key = ftype | ((quint64)label << 32); + quint64 key = ftype | label; if (_metricsCache.contains(key)) return _metricsCache.value(key); @@ -427,39 +429,37 @@ QFontMetricsF *UiStyle::fontMetrics(quint32 ftype, quint32 label) const // NOTE: This and the following functions are intimately tied to the values in FormatType. Don't change this // until you _really_ know what you do! -QTextCharFormat UiStyle::format(quint32 ftype, quint32 label_) const +QTextCharFormat UiStyle::format(FormatType ftype, MessageLabel label) const { - if (ftype == Invalid) - return QTextCharFormat(); - - quint64 label = (quint64)label_ << 32; + if (ftype == FormatType::Invalid) + return {}; // check if we have exactly this format readily cached already - QTextCharFormat fmt = cachedFormat(ftype, label_); + QTextCharFormat fmt = cachedFormat(ftype, label); if (fmt.properties().count()) return fmt; - mergeFormat(fmt, ftype, label & Q_UINT64_C(0xffff000000000000)); + mergeFormat(fmt, ftype, label & 0xffff0000); // keep nickhash in label - for (quint64 mask = Q_UINT64_C(0x0000000100000000); mask <= (quint64)Selected << 32; mask <<= 1) { - if (label & mask) - mergeFormat(fmt, ftype, mask | Q_UINT64_C(0xffff000000000000)); + for (quint32 mask = 0x00000001; mask <= static_cast(MessageLabel::Selected); mask <<= 1) { + if (static_cast(label) & mask) + mergeFormat(fmt, ftype, label & (mask | 0xffff0000)); } - setCachedFormat(fmt, ftype, label_); + setCachedFormat(fmt, ftype, label); return fmt; } -void UiStyle::mergeFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) const +void UiStyle::mergeFormat(QTextCharFormat &fmt, FormatType ftype, MessageLabel label) const { mergeSubElementFormat(fmt, ftype & 0x00ff, label); // 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 & 0xfff00)) { // element format + if ((ftype & 0xfff00) != FormatType::Base) { // element format for (quint32 mask = 0x00100; mask <= 0x40000; mask <<= 1) { - if (ftype & mask) { + if ((ftype & mask) != FormatType::Base) { mergeSubElementFormat(fmt, ftype & (mask | 0xff), label); } } @@ -468,28 +468,28 @@ void UiStyle::mergeFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) co // Now we handle color codes // We assume that those can't be combined with subelement and message types. if (_allowMircColors) { - if (ftype & 0x00400000) + if ((ftype & 0x00400000) != FormatType::Base) mergeSubElementFormat(fmt, ftype & 0x0f400000, label); // foreground - if (ftype & 0x00800000) + if ((ftype & 0x00800000) != FormatType::Base) mergeSubElementFormat(fmt, ftype & 0xf0800000, label); // background - if ((ftype & 0x00c00000) == 0x00c00000) + if ((ftype & 0x00c00000) == static_cast(0x00c00000)) mergeSubElementFormat(fmt, ftype & 0xffc00000, label); // combination } // URL - if (ftype & Url) - mergeSubElementFormat(fmt, ftype & (Url | 0x000000ff), label); + if ((ftype & FormatType::Url) != FormatType::Base) + mergeSubElementFormat(fmt, ftype & (FormatType::Url | static_cast(0x000000ff)), label); } // Merge a subelement format into an existing message format -void UiStyle::mergeSubElementFormat(QTextCharFormat &fmt, quint32 ftype, quint64 label) const +void UiStyle::mergeSubElementFormat(QTextCharFormat &fmt, FormatType ftype, MessageLabel label) const { quint64 key = ftype | label; - fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffff00))); // label + subelement - fmt.merge(format(key & Q_UINT64_C(0x0000ffffffffffff))); // label + subelement + msgtype - fmt.merge(format(key & Q_UINT64_C(0xffffffffffffff00))); // label + subelement + nickhash - fmt.merge(format(key & Q_UINT64_C(0xffffffffffffffff))); // label + subelement + nickhash + msgtype + fmt.merge(format(key & 0x0000ffffffffff00ull)); // label + subelement + fmt.merge(format(key & 0x0000ffffffffffffull)); // label + subelement + msgtype + fmt.merge(format(key & 0xffffffffffffff00ull)); // label + subelement + nickhash + fmt.merge(format(key & 0xffffffffffffffffull)); // label + subelement + nickhash + msgtype } @@ -497,52 +497,53 @@ UiStyle::FormatType UiStyle::formatType(Message::Type msgType) { switch (msgType) { case Message::Plain: - return PlainMsg; + return FormatType::PlainMsg; case Message::Notice: - return NoticeMsg; + return FormatType::NoticeMsg; case Message::Action: - return ActionMsg; + return FormatType::ActionMsg; case Message::Nick: - return NickMsg; + return FormatType::NickMsg; case Message::Mode: - return ModeMsg; + return FormatType::ModeMsg; case Message::Join: - return JoinMsg; + return FormatType::JoinMsg; case Message::Part: - return PartMsg; + return FormatType::PartMsg; case Message::Quit: - return QuitMsg; + return FormatType::QuitMsg; case Message::Kick: - return KickMsg; + return FormatType::KickMsg; case Message::Kill: - return KillMsg; + return FormatType::KillMsg; case Message::Server: - return ServerMsg; + return FormatType::ServerMsg; case Message::Info: - return InfoMsg; + return FormatType::InfoMsg; case Message::Error: - return ErrorMsg; + return FormatType::ErrorMsg; case Message::DayChange: - return DayChangeMsg; + return FormatType::DayChangeMsg; case Message::Topic: - return TopicMsg; + return FormatType::TopicMsg; case Message::NetsplitJoin: - return NetsplitJoinMsg; + return FormatType::NetsplitJoinMsg; case Message::NetsplitQuit: - return NetsplitQuitMsg; + return FormatType::NetsplitQuitMsg; case Message::Invite: - return InviteMsg; + return FormatType::InviteMsg; } //Q_ASSERT(false); // we need to handle all message types qWarning() << Q_FUNC_INFO << "Unknown message type:" << msgType; - return ErrorMsg; + return FormatType::ErrorMsg; } UiStyle::FormatType UiStyle::formatType(const QString &code) { - if (_formatCodes.contains(code)) return _formatCodes.value(code); - return Invalid; + if (_formatCodes.contains(code)) + return _formatCodes.value(code); + return FormatType::Invalid; } @@ -552,29 +553,31 @@ QString UiStyle::formatCode(FormatType ftype) } -QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, quint32 messageLabel) const +QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, MessageLabel messageLabel) const { QList formatRanges; QTextLayout::FormatRange range; - int i = 0; - for (i = 0; i < formatList.count(); i++) { - range.format = format(formatList.at(i).second, messageLabel); + size_t i = 0; + for (i = 0; i < formatList.size(); i++) { + range.format = format(formatList.at(i).second.type, messageLabel); range.start = formatList.at(i).first; - if (i > 0) formatRanges.last().length = range.start - formatRanges.last().start; + if (i > 0) + formatRanges.last().length = range.start - formatRanges.last().start; formatRanges.append(range); } - if (i > 0) formatRanges.last().length = textLength - formatRanges.last().start; + if (i > 0) + formatRanges.last().length = textLength - formatRanges.last().start; return formatRanges; } // This method expects a well-formatted string, there is no error checking! // Since we create those ourselves, we should be pretty safe that nobody does something crappy here. -UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat) +UiStyle::StyledString UiStyle::styleString(const QString &s_, FormatType baseFormat) { QString s = s_; StyledString result; - result.formatList.append(qMakePair((quint16)0, baseFormat)); + result.formatList.emplace_back(std::make_pair(quint16{0}, Format{baseFormat})); if (s.length() > 65535) { // We use quint16 for indexes @@ -583,7 +586,8 @@ UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat return result; } - quint32 curfmt = baseFormat; + FormatType curfmt = baseFormat; + int pos = 0; quint16 length = 0; for (;;) { pos = s.indexOf('%', pos); @@ -626,7 +630,7 @@ UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat QString code = QString("%") + s[pos+1]; if (s[pos+1] == 'D') code += s[pos+2]; FormatType ftype = formatType(code); - if (ftype == Invalid) { + if (ftype == FormatType::Invalid) { pos++; qWarning() << (QString("Invalid format code in string: %1").arg(s)); continue; @@ -635,10 +639,10 @@ UiStyle::StyledString UiStyle::styleString(const QString &s_, quint32 baseFormat length = code.length(); } s.remove(pos, length); - if (pos == result.formatList.last().first) - result.formatList.last().second = curfmt; + if (pos == result.formatList.back().first) + result.formatList.back().second.type = curfmt; else - result.formatList.append(qMakePair((quint16)pos, curfmt)); + result.formatList.emplace_back(std::make_pair(pos, Format{curfmt})); } result.plainText = s; return result; @@ -928,44 +932,43 @@ QString UiStyle::StyledMessage::decoratedSender() const return QString("<%1%2>").arg(_senderPrefixes, plainSender()); else return QString("%1%2").arg(_senderPrefixes, plainSender()); - break; case Message::Notice: - return QString("[%1%2]").arg(_senderPrefixes, plainSender()); break; + return QString("[%1%2]").arg(_senderPrefixes, plainSender()); case Message::Action: - return "-*-"; break; + return "-*-"; case Message::Nick: - return "<->"; break; + return "<->"; case Message::Mode: - return "***"; break; + return "***"; case Message::Join: - return "-->"; break; + return "-->"; case Message::Part: - return "<--"; break; + return "<--"; case Message::Quit: - return "<--"; break; + return "<--"; case Message::Kick: - return "<-*"; break; + return "<-*"; case Message::Kill: - return "<-x"; break; + return "<-x"; case Message::Server: - return "*"; break; + return "*"; case Message::Info: - return "*"; break; + return "*"; case Message::Error: - return "*"; break; + return "*"; case Message::DayChange: - return "-"; break; + return "-"; case Message::Topic: - return "*"; break; + return "*"; case Message::NetsplitJoin: - return "=>"; break; + return "=>"; case Message::NetsplitQuit: - return "<="; break; + return "<="; case Message::Invite: - return "->"; break; - default: - return QString("%1%2").arg(_senderPrefixes, plainSender()); + return "->"; } + + return QString("%1%2").arg(_senderPrefixes, plainSender()); } @@ -999,15 +1002,132 @@ quint8 UiStyle::StyledMessage::senderHash() const return (_senderHash = (hash & 0xf) + 1); } +/***********************************************************************************/ + +#if QT_VERSION < 0x050000 +uint qHash(UiStyle::ItemFormatType key) +{ + return qHash(static_cast(key)); +} + +#else + +uint qHash(UiStyle::ItemFormatType key, uint seed) +{ + return qHash(static_cast(key), seed); +} +#endif + +UiStyle::FormatType operator|(UiStyle::FormatType lhs, UiStyle::FormatType rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +UiStyle::FormatType& operator|=(UiStyle::FormatType& lhs, UiStyle::FormatType rhs) +{ + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + return lhs; +} + + +UiStyle::FormatType operator|(UiStyle::FormatType lhs, quint32 rhs) +{ + return static_cast(static_cast(lhs) | rhs); +} + + +UiStyle::FormatType& operator|=(UiStyle::FormatType &lhs, quint32 rhs) +{ + lhs = static_cast(static_cast(lhs) | rhs); + return lhs; +} + + +UiStyle::FormatType operator&(UiStyle::FormatType lhs, UiStyle::FormatType rhs) +{ + return static_cast(static_cast(lhs) & static_cast(rhs)); +} + + +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs) +{ + lhs = static_cast(static_cast(lhs) & static_cast(rhs)); + return lhs; +} + + +UiStyle::FormatType operator&(UiStyle::FormatType lhs, quint32 rhs) +{ + return static_cast(static_cast(lhs) & rhs); +} + + +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, quint32 rhs) +{ + lhs = static_cast(static_cast(lhs) & rhs); + return lhs; +} + + +UiStyle::FormatType& operator^=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs) +{ + lhs = static_cast(static_cast(lhs) ^ static_cast(rhs)); + return lhs; +} + + +UiStyle::MessageLabel operator|(UiStyle::MessageLabel lhs, UiStyle::MessageLabel rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + + +UiStyle::MessageLabel& operator|=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs) +{ + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + return lhs; +} + + +UiStyle::MessageLabel operator&(UiStyle::MessageLabel lhs, quint32 rhs) +{ + return static_cast(static_cast(lhs) & rhs); +} + + +UiStyle::MessageLabel& operator&=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs) +{ + lhs = static_cast(static_cast(lhs) & static_cast(rhs)); + return lhs; +} + + +quint64 operator|(UiStyle::FormatType lhs, UiStyle::MessageLabel rhs) +{ + return static_cast(lhs) | (static_cast(rhs) << 32ull); +} + + +UiStyle::ItemFormatType operator|(UiStyle::ItemFormatType lhs, UiStyle::ItemFormatType rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + + +UiStyle::ItemFormatType& operator|=(UiStyle::ItemFormatType &lhs, UiStyle::ItemFormatType rhs) +{ + lhs = static_cast(static_cast(lhs) | static_cast(rhs)); + return lhs; +} /***********************************************************************************/ QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList) { - out << formatList.count(); + out << static_cast(formatList.size()); UiStyle::FormatList::const_iterator it = formatList.begin(); while (it != formatList.end()) { - out << (*it).first << (*it).second; + out << it->first << static_cast(it->second.type); ++it; } return out; @@ -1021,7 +1141,7 @@ QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList) for (quint16 i = 0; i < cnt; i++) { quint16 pos; quint32 ftype; in >> pos >> ftype; - formatList.append(qMakePair((quint16)pos, ftype)); + formatList.emplace_back(std::make_pair(quint16{pos}, UiStyle::Format{static_cast(ftype)})); } return in; } diff --git a/src/uisupport/uistyle.h b/src/uisupport/uistyle.h index d565e5b8..7d1a8bcd 100644 --- a/src/uisupport/uistyle.h +++ b/src/uisupport/uistyle.h @@ -18,8 +18,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#ifndef UISTYLE_H_ -#define UISTYLE_H_ +#pragma once + +#include +#include #include #include @@ -43,8 +45,6 @@ public: UiStyle(QObject *parent = 0); virtual ~UiStyle(); - typedef QList > FormatList; - //! This enumerates the possible formats a text element may have. */ /** These formats are ordered on increasing importance, in cases where a given property is specified * by multiple active formats. @@ -52,7 +52,7 @@ public: * methods in this class (in particular mergedFormat())! * Also, we _do_ rely on certain properties of these values in styleString() and friends! */ - enum FormatType { + enum class FormatType : quint32 { Base = 0x00000000, Invalid = 0xffffffff, @@ -99,13 +99,16 @@ public: // background: 0x.0800000 }; - enum MessageLabel { + enum class MessageLabel : quint32 { + None = 0x00000000, OwnMsg = 0x00000001, Highlight = 0x00000002, Selected = 0x00000004 // must be last! }; - enum ItemFormatType { + enum class ItemFormatType : quint32 { + None = 0x00000000, + BufferViewItem = 0x00000001, NickViewItem = 0x00000002, @@ -119,10 +122,12 @@ public: ActiveBuffer = 0x00002000, UnreadBuffer = 0x00004000, HighlightedBuffer = 0x00008000, - UserAway = 0x00010000 + UserAway = 0x00010000, + + Invalid = 0xffffffff }; - enum ColorRole { + enum class ColorRole { MarkerLine, // Sender colors (16 + self) // These aren't used directly to avoid having storing all of the sender color options in the @@ -151,6 +156,12 @@ public: NumRoles // must be last! }; + struct Format { + FormatType type; + }; + + using FormatList = std::vector>; + struct StyledString { QString plainText; FormatList formatList; // starting pos, ftypes @@ -201,7 +212,7 @@ public: const QColor defaultSenderColorSelf = QColor(0, 0, 0); static FormatType formatType(Message::Type msgType); - static StyledString styleString(const QString &string, quint32 baseFormat = Base); + static StyledString styleString(const QString &string, FormatType baseFormat = FormatType::Base); static QString mircToInternal(const QString &); /** @@ -231,10 +242,10 @@ public: */ static QString timestampFormatString(); - QTextCharFormat format(quint32 formatType, quint32 messageLabel) const; - QFontMetricsF *fontMetrics(quint32 formatType, quint32 messageLabel) const; + QTextCharFormat format(FormatType formatType, MessageLabel messageLabel) const; + QFontMetricsF *fontMetrics(FormatType formatType, MessageLabel messageLabel) const; - QList toTextLayoutList(const FormatList &, int textLength, quint32 messageLabel) const; + QList toTextLayoutList(const FormatList &, int textLength, MessageLabel messageLabel) const; inline const QBrush &brush(ColorRole role) const { return _uiStylePalette.at((int)role); } inline void setBrush(ColorRole role, const QBrush &brush) { _uiStylePalette[(int)role] = brush; } @@ -253,10 +264,10 @@ protected: QString loadStyleSheet(const QString &name, bool shouldExist = false); QTextCharFormat format(quint64 key) const; - QTextCharFormat cachedFormat(quint32 formatType, quint32 messageLabel) const; - void setCachedFormat(const QTextCharFormat &format, quint32 formatType, quint32 messageLabel) const; - void mergeFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; - void mergeSubElementFormat(QTextCharFormat &format, quint32 formatType, quint64 messageLabel) const; + QTextCharFormat cachedFormat(FormatType formatType, MessageLabel messageLabel) const; + void setCachedFormat(const QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; + void mergeFormat(QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; + void mergeSubElementFormat(QTextCharFormat &format, FormatType formatType, MessageLabel messageLabel) const; static FormatType formatType(const QString &code); static QString formatCode(FormatType); @@ -310,7 +321,7 @@ private: QHash _formats; mutable QHash _formatCache; mutable QHash _metricsCache; - QHash _listItemFormats; + QHash _listItemFormats; static QHash _formatCodes; static bool _useCustomTimestampFormat; /// If true, use the custom timestamp format static QString _systemTimestampFormatString; /// Cached copy of system locale timestamp format @@ -357,10 +368,39 @@ private: mutable quint8 _senderHash; }; +#if QT_VERSION < 0x050000 +uint qHash(UiStyle::ItemFormatType key); +#else +uint qHash(UiStyle::ItemFormatType key, uint seed); +#endif + +// ---- Operators for dealing with enums ---------------------------------------------------------- + +UiStyle::FormatType operator|(UiStyle::FormatType lhs, UiStyle::FormatType rhs); +UiStyle::FormatType& operator|=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); +UiStyle::FormatType operator|(UiStyle::FormatType lhs, quint32 rhs); +UiStyle::FormatType& operator|=(UiStyle::FormatType &lhs, quint32 rhs); +UiStyle::FormatType operator&(UiStyle::FormatType lhs, UiStyle::FormatType rhs); +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); +UiStyle::FormatType operator&(UiStyle::FormatType lhs, quint32 rhs); +UiStyle::FormatType& operator&=(UiStyle::FormatType &lhs, quint32 rhs); +UiStyle::FormatType& operator^=(UiStyle::FormatType &lhs, UiStyle::FormatType rhs); + +UiStyle::MessageLabel operator|(UiStyle::MessageLabel lhs, UiStyle::MessageLabel rhs); +UiStyle::MessageLabel& operator|=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs); +UiStyle::MessageLabel operator&(UiStyle::MessageLabel lhs, quint32 rhs); +UiStyle::MessageLabel& operator&=(UiStyle::MessageLabel &lhs, UiStyle::MessageLabel rhs); + +// Shifts the label into the upper half of the return value +quint64 operator|(UiStyle::FormatType lhs, UiStyle::MessageLabel rhs); + +UiStyle::ItemFormatType operator|(UiStyle::ItemFormatType lhs, UiStyle::ItemFormatType rhs); +UiStyle::ItemFormatType& operator|=(UiStyle::ItemFormatType &lhs, UiStyle::ItemFormatType rhs); + +// ---- Allow for FormatList in QVariant ---------------------------------------------------------- QDataStream &operator<<(QDataStream &out, const UiStyle::FormatList &formatList); QDataStream &operator>>(QDataStream &in, UiStyle::FormatList &formatList); Q_DECLARE_METATYPE(UiStyle::FormatList) - -#endif +Q_DECLARE_METATYPE(UiStyle::MessageLabel) -- 2.20.1