Make backgrounds of ChatLines and ChatItems styleable
authorManuel Nickschas <sputnick@quassel-irc.org>
Sun, 21 Jun 2009 19:23:40 +0000 (21:23 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Thu, 6 Aug 2009 18:25:05 +0000 (20:25 +0200)
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
src/qtui/chatitem.cpp
src/qtui/chatline.cpp
src/qtui/chatlinemodel.h
src/qtui/chatlinemodelitem.cpp
src/qtui/chatlinemodelitem.h
src/uisupport/uistyle.cpp
src/uisupport/uistyle.h

index b6b783f..2e30dd2 100644 (file)
@@ -37,6 +37,7 @@ public:
   enum MessageRole {
     DisplayRole = Qt::DisplayRole,
     EditRole = Qt::EditRole,
+    BackgroundRole = Qt::BackgroundRole,
     MsgIdRole = Qt::UserRole,
     BufferIdRole,
     TypeRole,
index d58ab0b..5c44815 100644 (file)
@@ -69,7 +69,7 @@ void ChatItem::initLayoutHelper(QTextLayout *layout, QTextOption::WrapMode wrapM
   layout->setTextOption(option);
 
   QList<QTextLayout::FormatRange> formatRanges
-         = QtUi::style()->toTextLayoutList(data(MessageModel::FormatRole).value<UiStyle::FormatList>(), layout->text().length());
+         = QtUi::style()->toTextLayoutList(data(MessageModel::FormatRole).value<UiStyle::FormatList>(), 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<QBrush>());
+
   QVector<QTextLayout::FormatRange> 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<QBrush>());
+
   QTextLayout layout;
   initLayout(&layout);
   qreal layoutWidth = layout.minimumWidth();
index 278c1de..1c7db84 100644 (file)
@@ -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<MsgId>();
-    QModelIndex myIdx = model_->index(row(), 0);
-    MsgId myMsgId = model_->data(myIdx, MessageModel::MsgIdRole).value<MsgId>();
-    Message::Flags flags = (Message::Flags)model_->data(myIdx, MessageModel::FlagsRole).toInt();
+    MsgId prevMsgId = prevRowIdx.data(MessageModel::MsgIdRole).value<MsgId>();
+    MsgId myMsgId = myIdx.data(MessageModel::MsgIdRole).value<MsgId>();
+    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<QColor>());
-       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<QColor>());
+        gradient.setColorAt(0.1, Qt::transparent);
+        painter->fillRect(boundingRect(), gradient);
       }
     }
   }
index 12770d2..dffb706 100644 (file)
@@ -31,7 +31,8 @@ class ChatLineModel : public MessageModel {
 
 public:
   enum ChatLineRole {
-    WrapListRole = MessageModel::UserRole
+    WrapListRole = MessageModel::UserRole,
+    MsgLabelRole
   };
 
   ChatLineModel(QObject *parent = 0);
index 2264fa5..0bcc7a7 100644 (file)
@@ -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>(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.timestampFormat()));
+    return QVariant::fromValue<UiStyle::FormatList>(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>(UiStyle::FormatList() << qMakePair((quint16)0, (quint32)_styledMsg.senderFormat()));
+    return QVariant::fromValue<UiStyle::FormatList>(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<UiStyle::FormatList>(_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<QBrush>(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);
index 5382a7b..a553cca 100644 (file)
@@ -49,9 +49,12 @@ public:
   typedef QVector<Word> 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;
 
index a29d0c5..80a29b2 100644 (file)
@@ -181,12 +181,12 @@ QString UiStyle::formatCode(FormatType ftype) {
   return _formatCodes.key(ftype);
 }
 
-QList<QTextLayout::FormatRange> UiStyle::toTextLayoutList(const FormatList &formatList, int textLength) {
+QList<QTextLayout::FormatRange> UiStyle::toTextLayoutList(const FormatList &formatList, int textLength, quint32 messageLabel) {
   QList<QTextLayout::FormatRange> 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);
index 5941515..22ade27 100644 (file)
@@ -112,7 +112,7 @@ public:
 
   inline QFont defaultFont() const { return _defaultFont; }
 
-  QList<QTextLayout::FormatRange> toTextLayoutList(const FormatList &, int textLength);
+  QList<QTextLayout::FormatRange> toTextLayoutList(const FormatList &, int textLength, quint32 messageLabel = 0);
 
 protected:
   void loadStyleSheet();