From 2c16b8e356817cb4a4bf7fcd59c0c7429b0100e1 Mon Sep 17 00:00:00 2001 From: Manuel Nickschas Date: Sun, 21 Jun 2009 21:23:40 +0200 Subject: [PATCH] Make backgrounds of ChatLines and ChatItems styleable The background color (set by UiStyle) is now available in the MessageModel via the BackgroundRole. It is used by the items to paint themselves, if it is set by a stylesheet. Message labels (so far, we support "highlight" and "own message") are also respected properly. They can be accessed via the MsgLabelRole and are now used for accessing the style engine. --- src/client/messagemodel.h | 1 + src/qtui/chatitem.cpp | 12 ++++++++++- src/qtui/chatline.cpp | 32 +++++++++++++++++----------- src/qtui/chatlinemodel.h | 3 ++- src/qtui/chatlinemodelitem.cpp | 38 +++++++++++++++++++++++++++------- src/qtui/chatlinemodelitem.h | 9 +++++--- src/uisupport/uistyle.cpp | 4 ++-- src/uisupport/uistyle.h | 2 +- 8 files changed, 74 insertions(+), 27 deletions(-) diff --git a/src/client/messagemodel.h b/src/client/messagemodel.h index b6b783fb..2e30dd21 100644 --- a/src/client/messagemodel.h +++ b/src/client/messagemodel.h @@ -37,6 +37,7 @@ public: enum MessageRole { DisplayRole = Qt::DisplayRole, EditRole = Qt::EditRole, + BackgroundRole = Qt::BackgroundRole, MsgIdRole = Qt::UserRole, BufferIdRole, TypeRole, diff --git a/src/qtui/chatitem.cpp b/src/qtui/chatitem.cpp index d58ab0b3..5c44815a 100644 --- a/src/qtui/chatitem.cpp +++ b/src/qtui/chatitem.cpp @@ -69,7 +69,7 @@ void ChatItem::initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode wrapM layout->setTextOption(option); QList formatRanges - = QtUi::style()->toTextLayoutList(data(MessageModel::FormatRole).value(), layout->text().length()); + = QtUi::style()->toTextLayoutList(data(MessageModel::FormatRole).value(), layout->text().length(), data(ChatLineModel::MsgLabelRole).toUInt()); layout->setAdditionalFormats(formatRanges); } @@ -89,6 +89,11 @@ void ChatItem::doLayout(QTextLayout *layout) const { void ChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work + + QVariant bgBrush = data(ChatLineModel::BackgroundRole); + if(bgBrush.isValid()) + painter->fillRect(boundingRect(), bgBrush.value()); + QVector formats = additionalFormats(); QTextLayout::FormatRange selectFmt = selectionFormat(); if(selectFmt.format.isValid()) formats.append(selectFmt); @@ -300,6 +305,11 @@ void SenderChatItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *op Q_UNUSED(option); Q_UNUSED(widget); painter->setClipRect(boundingRect()); // no idea why QGraphicsItem clipping won't work + + QVariant bgBrush = data(ChatLineModel::BackgroundRole); + if(bgBrush.isValid()) + painter->fillRect(boundingRect(), bgBrush.value()); + QTextLayout layout; initLayout(&layout); qreal layoutWidth = layout.minimumWidth(); diff --git a/src/qtui/chatline.cpp b/src/qtui/chatline.cpp index 278c1de4..1c7db84c 100644 --- a/src/qtui/chatline.cpp +++ b/src/qtui/chatline.cpp @@ -154,9 +154,18 @@ void ChatLine::setHighlighted(bool highlighted) { void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); - if(_selection & Highlighted) { - painter->fillRect(boundingRect(), QBrush(QtUi::style()->highlightColor())); + + 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(); + + QTextCharFormat msgFmt = QtUi::style()->format(UiStyle::formatType(type), label); + if(msgFmt.hasProperty(QTextFormat::BackgroundBrush)) { + painter->fillRect(boundingRect(), msgFmt.background()); } + + // TODO make this dependent on the style engine (highlight-color & friends) if(_selection & Selected) { qreal left = item((ChatLineModel::ColumnType)(_selection & ItemMask)).x(); QRectF selectRect(left, 0, width() - left, height()); @@ -164,23 +173,22 @@ void ChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, } // new line marker - const QAbstractItemModel *model_ = model(); if(model_ && row() > 0 && chatScene()->isSingleBufferScene()) { QModelIndex prevRowIdx = model_->index(row() - 1, 0); - MsgId prevMsgId = model_->data(prevRowIdx, MessageModel::MsgIdRole).value(); - QModelIndex myIdx = model_->index(row(), 0); - MsgId myMsgId = model_->data(myIdx, MessageModel::MsgIdRole).value(); - Message::Flags flags = (Message::Flags)model_->data(myIdx, MessageModel::FlagsRole).toInt(); + MsgId prevMsgId = prevRowIdx.data(MessageModel::MsgIdRole).value(); + MsgId myMsgId = myIdx.data(MessageModel::MsgIdRole).value(); + Message::Flags flags = (Message::Flags)myIdx.data(MessageModel::FlagsRole).toInt(); + // don't show the marker if we wrote that new line if(!(flags & Message::Self)) { BufferId bufferId = BufferId(chatScene()->idString().toInt()); MsgId lastSeenMsgId = Client::networkModel()->lastSeenMarkerMsgId(bufferId); if(lastSeenMsgId < myMsgId && lastSeenMsgId >= prevMsgId) { - QtUiStyleSettings s("Colors"); - QLinearGradient gradient(0, 0, 0, contentsItem().fontMetrics()->lineSpacing()); - gradient.setColorAt(0, s.value("newMsgMarkerFG", QColor(Qt::red)).value()); - gradient.setColorAt(0.1, Qt::transparent); - painter->fillRect(boundingRect(), gradient); + QtUiStyleSettings s("Colors"); + QLinearGradient gradient(0, 0, 0, contentsItem().fontMetrics()->lineSpacing()); + gradient.setColorAt(0, s.value("newMsgMarkerFG", QColor(Qt::red)).value()); + gradient.setColorAt(0.1, Qt::transparent); + painter->fillRect(boundingRect(), gradient); } } } diff --git a/src/qtui/chatlinemodel.h b/src/qtui/chatlinemodel.h index 12770d20..dffb7065 100644 --- a/src/qtui/chatlinemodel.h +++ b/src/qtui/chatlinemodel.h @@ -31,7 +31,8 @@ class ChatLineModel : public MessageModel { public: enum ChatLineRole { - WrapListRole = MessageModel::UserRole + WrapListRole = MessageModel::UserRole, + MsgLabelRole }; ChatLineModel(QObject *parent = 0); diff --git a/src/qtui/chatlinemodelitem.cpp b/src/qtui/chatlinemodelitem.cpp index 2264fa5a..0bcc7a78 100644 --- a/src/qtui/chatlinemodelitem.cpp +++ b/src/qtui/chatlinemodelitem.cpp @@ -53,8 +53,11 @@ ChatLineModelItem::ChatLineModelItem(const Message &msg) } QVariant ChatLineModelItem::data(int column, int role) const { - MessageModel::ColumnType col = (MessageModel::ColumnType)column; + if(role == ChatLineModel::MsgLabelRole) + return messageLabel(); + QVariant variant; + MessageModel::ColumnType col = (MessageModel::ColumnType)column; switch(col) { case ChatLineModel::TimestampColumn: variant = timestampData(role); @@ -79,8 +82,11 @@ QVariant ChatLineModelItem::timestampData(int role) const { return _styledMsg.decoratedTimestamp(); case ChatLineModel::EditRole: return _styledMsg.timestamp(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Timestamp); case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.timestampFormat())); + return QVariant::fromValue(UiStyle::FormatList() + << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp)); } return QVariant(); } @@ -91,20 +97,22 @@ QVariant ChatLineModelItem::senderData(int role) const { return _styledMsg.decoratedSender(); case ChatLineModel::EditRole: return _styledMsg.plainSender(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Sender); case ChatLineModel::FormatRole: - return QVariant::fromValue(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.senderFormat())); + return QVariant::fromValue(UiStyle::FormatList() + << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender)); } return QVariant(); } QVariant ChatLineModelItem::contentsData(int role) const { - if(_styledMsg.needsStyling()) - _styledMsg.style(QtUi::style()); - switch(role) { case ChatLineModel::DisplayRole: case ChatLineModel::EditRole: return _styledMsg.plainContents(); + case ChatLineModel::BackgroundRole: + return backgroundBrush(UiStyle::Contents); case ChatLineModel::FormatRole: return QVariant::fromValue(_styledMsg.contentsFormatList()); case ChatLineModel::WrapListRole: @@ -115,6 +123,22 @@ QVariant ChatLineModelItem::contentsData(int role) const { return QVariant(); } +quint32 ChatLineModelItem::messageLabel() const { + quint32 label = 0; + if(_styledMsg.flags() & Message::Self) + label |= UiStyle::OwnMsg; + if(_styledMsg.flags() & Message::Highlight) + label |= UiStyle::Highlight; + return label; +} + +QVariant ChatLineModelItem::backgroundBrush(UiStyle::FormatType subelement) const { + QTextCharFormat fmt = QtUi::style()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel()); + if(fmt.hasProperty(QTextFormat::BackgroundBrush)) + return QVariant::fromValue(fmt.background()); + return QVariant(); +} + void ChatLineModelItem::computeWrapList() const { int length = _styledMsg.plainContents().length(); if(!length) @@ -140,7 +164,7 @@ void ChatLineModelItem::computeWrapList() const { option.setWrapMode(QTextOption::NoWrap); layout.setTextOption(option); - layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length)); + layout.setAdditionalFormats(QtUi::style()->toTextLayoutList(_styledMsg.contentsFormatList(), length, messageLabel())); layout.beginLayout(); QTextLine line = layout.createLine(); line.setNumColumns(length); diff --git a/src/qtui/chatlinemodelitem.h b/src/qtui/chatlinemodelitem.h index 5382a7b8..a553cca3 100644 --- a/src/qtui/chatlinemodelitem.h +++ b/src/qtui/chatlinemodelitem.h @@ -49,9 +49,12 @@ public: typedef QVector WrapList; private: - virtual QVariant timestampData(int role) const; - virtual QVariant senderData(int role) const; - virtual QVariant contentsData(int role) const; + QVariant timestampData(int role) const; + QVariant senderData(int role) const; + QVariant contentsData(int role) const; + + QVariant backgroundBrush(UiStyle::FormatType subelement) const; + quint32 messageLabel() const; void computeWrapList() const; diff --git a/src/uisupport/uistyle.cpp b/src/uisupport/uistyle.cpp index a29d0c56..80a29b2f 100644 --- a/src/uisupport/uistyle.cpp +++ b/src/uisupport/uistyle.cpp @@ -181,12 +181,12 @@ QString UiStyle::formatCode(FormatType ftype) { return _formatCodes.key(ftype); } -QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength) { +QList UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, quint32 messageLabel) { QList formatRanges; QTextLayout::FormatRange range; int i = 0; for(i = 0; i < formatList.count(); i++) { - range.format = format(formatList.at(i).second); + range.format = format(formatList.at(i).second, messageLabel); range.start = formatList.at(i).first; if(i > 0) formatRanges.last().length = range.start - formatRanges.last().start; formatRanges.append(range); diff --git a/src/uisupport/uistyle.h b/src/uisupport/uistyle.h index 59415159..22ade27a 100644 --- a/src/uisupport/uistyle.h +++ b/src/uisupport/uistyle.h @@ -112,7 +112,7 @@ public: inline QFont defaultFont() const { return _defaultFont; } - QList toTextLayoutList(const FormatList &, int textLength); + QList toTextLayoutList(const FormatList &, int textLength, quint32 messageLabel = 0); protected: void loadStyleSheet(); -- 2.20.1