More QML fidgetery
authorManuel Nickschas <sputnick@quassel-irc.org>
Sat, 19 Nov 2011 10:12:08 +0000 (11:12 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sat, 19 Nov 2011 10:12:08 +0000 (11:12 +0100)
While playing around with various approaches to how to implement ChatView in QML, I think slowly
things are shaping up. We now have extended the QmlMessageModel to provide all info needed for rendering
a QmlChatLine in one data stracture, in order to avoid numerous calls to the model whenever a ChatLine
is instantiated.

Currently there's a lot of code duplication with the related non-QML classes, but this will either go away
once we decide to kill the QGV-based ChatView, or be unified into a common set of base classes if we
find out that both implementations are going to stay around.

src/qmlui/qml/ChatView.qml
src/qmlui/qmlchatline.cpp
src/qmlui/qmlchatline.h
src/qmlui/qmlmessagemodel.cpp
src/qmlui/qmlmessagemodel.h
src/qmlui/qmlmessagemodelitem.cpp
src/qmlui/qmlmessagemodelitem.h

index aa72fb4..79a9148 100644 (file)
@@ -1,57 +1,96 @@
 import QtQuick 1.1
 // import Qt.components 1.0
 
-import eu.quassel.qmlui 1.0
+import eu.quassel.qml 1.0
 
 Rectangle {
-  id: container
+    id: container
 
-  ListView {
-    id: chatView
-    anchors.fill: parent
-    model: msgModel
+    ListView {
+        id: chatView
 
-    delegate: Component {
-      ChatLine {
-        chatLineData: chatLineDataRole
-      }
-    }
+        property int timestampWidth: 50
+        property int senderWidth: 80
+        property int contentsWidth: width - timestampWidth - senderWidth - 30;
+        property int columnSpacing: 10
 
-    //interactive: false
-    boundsBehavior: Flickable.StopAtBounds
+        anchors.fill: parent
+        model: msgModel
 
-    property int timestampWidth: 50
-    property int senderWidth: 80
-    property int contentsWidth: width - timestampWidth - senderWidth - 30;
+        delegate: ChatLine {
+            id: chatLineDelegate
+
+            timestampWidth: chatView.timestampWidth
+            senderWidth: chatView.senderWidth
+            contentsWidth: chatView.contentsWidth
+            columnSpacing: chatView.columnSpacing
+            model: chatView.model
+            renderData: renderDataRole
 
-    Connections {
-      target: msgModel
-      onRowsInserted: chatView.positionViewAtEnd();
-    }
 /*
-    MouseArea {
-      id: mouseArea
-      anchors.fill: parent
-      acceptedButtons: Qt.LeftButton
-
-      onClicked: {
-        console.log("clicked")
-        parent.senderWidth = parent.senderWidth + 10
-      }
-      onPositionChanged: {
-        console.log("changed" + mouseX + mouseY)
-      }
+                MouseArea {
+                    id: itemMouseArea
+                    anchors.fill: parent
+                    acceptedButtons: Qt.LeftButton
+                    hoverEnabled: true
 
-    }
+                    //onClicked: {
+                    //    console.log("clicked " + mouseX + " " + mouseY + " " + parent.text)
+                    //    parent.onClicked(mouseX, mouseY)
+                    //}
+
+                    //onPositionChanged: {
+                    //    console.log("changed " + mouseX + " " + mouseY + " " + parent.text)
+                    //}
+
+                }
+*/
+/*
+                Connections {
+                    target: itemMouseArea
+                    onClicked: onClicked(itemMouseArea.mouseX, itemMouseArea.mouseY)
+                    onPressed: onPressed(itemMouseArea.mouseX, itemMouseArea.mouseY)
+                    onPositionChanged: onMousePositionChanged(itemMouseArea.mouseX, itemMouseArea.mouseY)
+                }
 */
+        }
+
+        interactive: true
+        boundsBehavior: Flickable.StopAtBounds
+
+        Connections {
+            target: msgModel
+            onRowsInserted: chatView.positionViewAtEnd();
+        }
+
+        MouseArea {
+            id: mouseArea
+            anchors.fill: parent
+            acceptedButtons: Qt.LeftButton
+            //hoverEnabled: true
+
+            onClicked: {
+                //parent.senderWidth = parent.senderWidth + 10
+                //chatView.currentItem.senderWidth = 40;
+                //var pos = mapToItem(chatView, mouseX, mouseY)
+                //console.log(pos.x + " " + pos.y + " " + chatView.contentY)
+                console.log("clicked " + mouseX + " " + mouseY + " " + chatView.indexAt(mouseX, mouseY + chatView.contentY))
+                console.log("item " + chatView.model.get(17).text)
+            }
+            onPositionChanged: {
+                console.log("changed " + mouseX + " " + mouseY)
+            }
+
+        }
+
 
-    Rectangle {
-      id: scrollbar
-      anchors.right: chatView.right
-      y: chatView.visibleArea.yPosition * chatView.height
-      width: 10
-      height: chatView.visibleArea.heightRatio * chatView.height
-      color: "grey"
+        Rectangle {
+            id: scrollbar
+            anchors.right: chatView.right
+            y: chatView.visibleArea.yPosition * chatView.height
+            width: 10
+            height: chatView.visibleArea.heightRatio * chatView.height
+            color: "grey"
+        }
     }
-  }
 }
index 874437c..3d3c4b4 100644 (file)
 #include "qmlchatline.h"
 
 void QmlChatLine::registerTypes() {
-  qRegisterMetaType<Data>("QmlChatLine::Data");
-  qRegisterMetaTypeStreamOperators<Data>("QmlChatLine::Data");
-  qmlRegisterType<QmlChatLine>("eu.quassel.qmlui", 1, 0, "ChatLine");
+  qRegisterMetaType<RenderData>("QmlChatLine::RenderData");
+  qRegisterMetaTypeStreamOperators<RenderData>("QmlChatLine::RenderData");
+  qmlRegisterType<QmlChatLine>("eu.quassel.qml", 1, 0, "ChatLine");
 }
 
-QDataStream &operator<<(QDataStream &out, const QmlChatLine::Data &data) {
-  out << data.timestamp.text << data.timestamp.formats
-      << data.sender.text << data.sender.formats
-      << data.contents.text << data.contents.formats;
+QDataStream &operator<<(QDataStream &out, const QmlChatLine::RenderData &data) {
+  for(int i = 0; i < (int)QmlChatLine::NumColumns; ++i) {
+    const QmlChatLine::RenderData::Column &col = data[static_cast<QmlChatLine::ColumnType>(i)];
+    out << col.text << col.formats;
+  }
   return out;
 }
 
-QDataStream &operator>>(QDataStream &in, QmlChatLine::Data &data) {
-  in >> data.timestamp.text >> data.timestamp.formats
-     >> data.sender.text >> data.sender.formats
-     >> data.contents.text >> data.contents.formats;
+QDataStream &operator>>(QDataStream &in, QmlChatLine::RenderData &data) {
+  for(int i = 0; i < (int)QmlChatLine::NumColumns; ++i) {
+    QmlChatLine::RenderData::Column &col = data[static_cast<QmlChatLine::ColumnType>(i)];
+    in >> col.text >> col.formats;
+  }
   return in;
 }
 
-QmlChatLine::QmlChatLine(QDeclarativeItem *parent) : QDeclarativeItem(parent) {
+QmlChatLine::QmlChatLine(QDeclarativeItem *parent)
+  : QDeclarativeItem(parent),
+    _timestampWidth(0),
+    _senderWidth(0),
+    _contentsWidth(0),
+    _layout(0)
+{
   setFlag(ItemHasNoContents, false);
   setImplicitHeight(20);
-  setImplicitWidth(100);
+  setImplicitWidth(1000);
+  connect(this, SIGNAL(columnWidthChanged(ColumnType)), SLOT(onColumnWidthChanged(ColumnType)));
 }
 
 QmlChatLine::~QmlChatLine() {
 
 }
 
+void QmlChatLine::setTimestampWidth(qreal w) {
+  if(w != _timestampWidth) {
+    _timestampWidth = w;
+    emit timestampWidthChanged(w);
+    emit columnWidthChanged(TimestampColumn);
+  }
+}
+
+void QmlChatLine::setSenderWidth(qreal w) {
+  if(w != _senderWidth) {
+    _senderWidth = w;
+    emit senderWidthChanged(w);
+    emit columnWidthChanged(SenderColumn);
+  }
+}
+
+void QmlChatLine::setContentsWidth(qreal w) {
+  if(w != _contentsWidth) {
+    _contentsWidth = w;
+    emit contentsWidthChanged(w);
+    emit columnWidthChanged(ContentsColumn);
+  }
+}
+
+void QmlChatLine::setColumnSpacing(qreal s) {
+  if(s != _columnSpacing) {
+    _columnSpacing = s;
+    emit columnSpacingChanged(s);
+  }
+}
+
+QPointF QmlChatLine::columnPos(ColumnType colType) const {
+  switch(colType) {
+  case TimestampColumn:
+    return QPointF(0, 0);
+  case SenderColumn:
+    return QPointF(timestampWidth(), 0);
+  case ContentsColumn:
+    return QPointF(timestampWidth() + senderWidth(), 0);
+  default:
+    return QPointF();
+  }
+}
+
+qreal QmlChatLine::columnWidth(ColumnType colType) const {
+  switch(colType) {
+  case TimestampColumn:
+    return timestampWidth();
+  case SenderColumn:
+    return senderWidth();
+  case ContentsColumn:
+    return contentsWidth();
+  default:
+    return 0;
+  }
+}
+
+QRectF QmlChatLine::columnBoundingRect(ColumnType colType) const {
+  QRectF rect;
+  switch(colType) {
+  case TimestampColumn:
+    return QRectF(columnPos(TimestampColumn), QSizeF(timestampWidth() - columnSpacing(), implicitHeight()));
+  case SenderColumn:
+    return QRectF(columnPos(SenderColumn), QSizeF(senderWidth() - columnSpacing(), implicitHeight()));
+  case ContentsColumn:
+    return QRectF(columnPos(ContentsColumn), QSizeF(contentsWidth(), implicitHeight()));
+  default:
+    return QRectF();
+  }
+}
+
+void QmlChatLine::setRenderData(const RenderData &data) {
+  _data = data;
+  if(_layout) {
+    delete _layout;
+    _layout = 0;
+  }
+
+  //update();
+}
+
+QmlChatLine::ColumnLayout *QmlChatLine::layout() const {
+  if(!_layout) {
+    _layout = new ColumnLayout(this);
+  }
+  return _layout;
+}
+
 void QmlChatLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
-  painter->drawText(0, 0, data().contents.text);
+  Q_UNUSED(option)
+  Q_UNUSED(widget)
+  //painter->drawText(0, 0, renderData()[TimestampColumn].text);
+  //painter->drawText(timestampWidth() + columnSpacing(), 0, renderData()[SenderColumn].text);
+  //painter->drawText(timestampWidth() + senderWidth() + 2*columnSpacing(), 0, renderData()[ContentsColumn].text);
+  layout()->draw(painter);
+}
+
+void QmlChatLine::onColumnWidthChanged(ColumnType colType) {
+
+  //qDebug() << "changed width" << _timestampWidth << _senderWidth << _contentsWidth;
+  //setImplicitHeight(implicitHeight() + 5);
+
+  if(colType == ContentsColumn) {
+    layout()->prepare();
+    setImplicitHeight(layout()->height());
+  }
+
+  update();
+}
 
+/**************************************************************************************/
+
+QmlChatLine::ColumnLayout::ColumnLayout(const QmlChatLine *parent)
+  : _parent(parent)
+{
+
+}
+
+qreal QmlChatLine::ColumnLayout::height() const {
+  return chatLine()->contentsWidth()/20;
 }
 
+void QmlChatLine::ColumnLayout::prepare() {
 
+}
+
+void QmlChatLine::ColumnLayout::draw(QPainter *p) {
+  p->drawText(chatLine()->boundingRect(), chatLine()->renderData()[ContentsColumn].text);
+  //p->drawText(chatLine()->timestampWidth() + chatLine()->columnSpacing(), 0, chatLine()->renderData()[SenderColumn].text);
+  //p->drawText(chatLine()->timestampWidth() + chatLine()->senderWidth() + 2*chatLine()->columnSpacing(), 0, chatLine()->renderData()[ContentsColumn].text);
+
+}
index 12ce82e..db8d5d0 100644 (file)
 
 #include "uistyle.h"
 
+class QAbstractItemModel;
+
+#include <QAbstractItemModel>
+
 class QmlChatLine : public QDeclarativeItem {
   Q_OBJECT
 
-  Q_PROPERTY(QVariant chatLineData READ chatLineData WRITE setChatLineData)
-
-  //Q_PROPERTY(QVariant )
+  Q_PROPERTY(QObject *model READ modelPointer WRITE setModelPointer)
+  Q_PROPERTY(QmlChatLine::RenderData renderData READ renderData WRITE setRenderData)
+  Q_PROPERTY(qreal timestampWidth READ timestampWidth WRITE setTimestampWidth NOTIFY timestampWidthChanged)
+  Q_PROPERTY(qreal senderWidth READ senderWidth WRITE setSenderWidth NOTIFY senderWidthChanged)
+  Q_PROPERTY(qreal contentsWidth READ contentsWidth WRITE setContentsWidth NOTIFY contentsWidthChanged)
+  Q_PROPERTY(qreal columnSpacing READ columnSpacing WRITE setColumnSpacing NOTIFY columnSpacingChanged)
+  Q_PROPERTY(QVariant test READ test WRITE setTest)
 
 public:
-  //! Contains all data needed to render a QmlChatLine
-  struct Data {
-    struct ChatLineColumnData {
+  enum ColumnType {
+    TimestampColumn,
+    SenderColumn,
+    ContentsColumn,
+    NumColumns
+  };
+
+  //! Contains all model data needed to render a QmlChatLine
+  struct RenderData {
+    struct Column {
       QString text;
       UiStyle::FormatList formats;
+      QBrush background;
+      QBrush selectedBackground;
     };
 
-    ChatLineColumnData timestamp;
-    ChatLineColumnData sender;
-    ChatLineColumnData contents;
+    qint32 messageLabel;
+
+    Column &operator[](ColumnType col) {
+      return _data[col];
+    }
+
+    Column const &operator[](ColumnType col) const {
+      return _data[col];
+    }
+
+    RenderData() { messageLabel = 0; }
+
+  private:
+    Column _data[NumColumns];
   };
 
+  class ColumnLayout;
+
   QmlChatLine(QDeclarativeItem *parent = 0);
   virtual ~QmlChatLine();
 
-  inline Data data() const { return _data; }
-  inline QVariant chatLineData() const { return QVariant::fromValue<Data>(_data); }
-  inline void setChatLineData(const QVariant &data) { _data = data.value<Data>(); }
+  inline QAbstractItemModel *model() const { return _model; }
+  inline QObject *modelPointer() const { return _model; }
+  void setModelPointer(QObject *model) { _model = qobject_cast<QAbstractItemModel *>(model); }
+
+  inline RenderData renderData() const { return _data; }
+  void setRenderData(const RenderData &data);
+
+  ColumnLayout *layout() const;
+
+  inline qreal timestampWidth() const { return _timestampWidth; }
+  void setTimestampWidth(qreal w);
+  inline qreal senderWidth() const { return _senderWidth; }
+  void setSenderWidth(qreal w);
+  inline qreal contentsWidth() const { return _contentsWidth; }
+  void setContentsWidth(qreal w);
+  inline qreal columnSpacing() const { return _columnSpacing; }
+  void setColumnSpacing(qreal s);
+
+  inline QString text() const { return renderData()[ContentsColumn].text; }
+
+  void setTest(const QVariant &test) { _test = test; qDebug() << "set test" << test; }
+  QVariant test() const { return _test; }
+
+  QPointF columnPos(ColumnType colType) const;
+  qreal columnWidth(ColumnType colType) const;
+  QRectF columnBoundingRect(ColumnType colType) const;
 
   virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
 
   static void registerTypes();
 
+signals:
+  void timestampWidthChanged(qreal);
+  void senderWidthChanged(qreal);
+  void contentsWidthChanged(qreal);
+  void columnWidthChanged(ColumnType column);
+  void columnSpacingChanged(qreal);
+
+public slots:
+  void onClicked(qreal mouseX, qreal mouseY) { qDebug() << "clicked" << mouseX << mouseY; }
+  void onPressed(qreal mouseX, qreal mouseY) { qDebug() << "pressed" << mouseX << mouseY; }
+  void onMousePositionChanged(qreal mouseX, qreal mouseY) { qDebug() << "moved" << mouseX << mouseY; }
+
+protected:
+
+protected slots:
+  void onColumnWidthChanged(ColumnType column);
+
 private:
-  Data _data;
+  QAbstractItemModel *_model;
+  RenderData _data;
+
+  qreal _timestampWidth, _senderWidth, _contentsWidth;
+  qreal _columnSpacing;
+
+  QVariant _test;
+
+  mutable ColumnLayout *_layout;
 };
 
-QDataStream &operator<<(QDataStream &out, const QmlChatLine::Data &data);
-QDataStream &operator>>(QDataStream &in, QmlChatLine::Data &data);
+QDataStream &operator<<(QDataStream &out, const QmlChatLine::RenderData &data);
+QDataStream &operator>>(QDataStream &in, QmlChatLine::RenderData &data);
 
-Q_DECLARE_METATYPE(QmlChatLine::Data)
+Q_DECLARE_METATYPE(QmlChatLine::RenderData)
+
+class QmlChatLine::ColumnLayout {
+public:
+  explicit ColumnLayout(const QmlChatLine *parent);
+  virtual ~ColumnLayout() {}
+
+  inline const QmlChatLine *chatLine() const { return _parent; }
+
+  qreal height() const;
+  virtual void prepare();
+  virtual void draw(QPainter *p);
+
+private:
+  const QmlChatLine *_parent;
+};
 
 #endif
index fc7ecc3..c58f862 100644 (file)
@@ -29,7 +29,7 @@ QmlMessageModel::QmlMessageModel(QObject *parent)
   QmlChatLine::registerTypes();
 
   QHash<int, QByteArray> roles;
-  roles[ChatLineDataRole] = "chatLineDataRole";
+  roles[RenderDataRole] = "renderDataRole";
   setRoleNames(roles);
 }
 
index 92ce1e7..ce59d8f 100644 (file)
@@ -31,7 +31,9 @@ class QmlMessageModel : public MessageModel {
 
 public:
   enum QmlMessageModelRole {
-    ChatLineDataRole = MessageModel::UserRole,
+    RenderDataRole = MessageModel::UserRole,
+    MsgLabelRole,
+    SelectedBackgroundRole,
     UserRole
   };
 
index 561c9b7..ec11ec4 100644 (file)
@@ -18,6 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
+#include "graphicalui.h"
 #include "qmlchatline.h"
 #include "qmlmessagemodel.h"
 #include "qmlmessagemodelitem.h"
@@ -31,23 +32,127 @@ QmlMessageModelItem::QmlMessageModelItem(const Message &msg)
     _styledMsg.setFlags(msg.flags() |= Message::ServerMsg);
 }
 
+bool QmlMessageModelItem::setData(int column, const QVariant &value, int role) {
+  switch(role) {
+    case MessageModel::FlagsRole:
+      _styledMsg.setFlags((Message::Flags)value.toUInt());
+      return true;
+    default:
+      return MessageModelItem::setData(column, value, role);
+  }
+}
+
 QVariant QmlMessageModelItem::data(int column, int role) const {
   QVariant variant;
   switch(role) {
-  case QmlMessageModel::ChatLineDataRole: {
-    QmlChatLine::Data data;
-    data.timestamp.text = _styledMsg.decoratedTimestamp();
-    data.timestamp.formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp);
-    data.sender.text = _styledMsg.decoratedSender();
-    data.sender.formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender);
-    data.contents.text = _styledMsg.plainContents();
-    data.contents.formats = _styledMsg.contentsFormatList();
-    return QVariant::fromValue<QmlChatLine::Data>(data);
+  case QmlMessageModel::MsgLabelRole:
+    return messageLabel();
+
+  case QmlMessageModel::RenderDataRole: {
+    QmlChatLine::RenderData data;
+    data[QmlChatLine::TimestampColumn].text = _styledMsg.decoratedTimestamp();
+    data[QmlChatLine::TimestampColumn].formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp);
+    data[QmlChatLine::TimestampColumn].background = backgroundBrush(UiStyle::Timestamp).value<QBrush>();
+    data[QmlChatLine::TimestampColumn].selectedBackground = backgroundBrush(UiStyle::Timestamp, true).value<QBrush>();
+
+    data[QmlChatLine::SenderColumn].text = _styledMsg.decoratedSender();
+    data[QmlChatLine::SenderColumn].formats = UiStyle::FormatList() << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender);
+    data[QmlChatLine::SenderColumn].background = backgroundBrush(UiStyle::Sender).value<QBrush>();
+    data[QmlChatLine::SenderColumn].selectedBackground = backgroundBrush(UiStyle::Sender, true).value<QBrush>();
+
+    data[QmlChatLine::ContentsColumn].text = _styledMsg.plainContents();
+    data[QmlChatLine::ContentsColumn].formats = _styledMsg.contentsFormatList();
+    data[QmlChatLine::ContentsColumn].background = backgroundBrush(UiStyle::Contents).value<QBrush>();
+    data[QmlChatLine::ContentsColumn].selectedBackground = backgroundBrush(UiStyle::Contents, true).value<QBrush>();
+
+    return QVariant::fromValue<QmlChatLine::RenderData>(data);
   }
+
   default:
     break;
   }
+
+  MessageModel::ColumnType col = (MessageModel::ColumnType)column;
+  switch(col) {
+  case QmlMessageModel::TimestampColumn:
+    variant = timestampData(role);
+    break;
+  case QmlMessageModel::SenderColumn:
+    variant = senderData(role);
+    break;
+  case QmlMessageModel::ContentsColumn:
+    variant = contentsData(role);
+    break;
+  default:
+    break;
+  }
+
   if(!variant.isValid())
     return MessageModelItem::data(column, role);
   return variant;
 }
+
+QVariant QmlMessageModelItem::timestampData(int role) const {
+  switch(role) {
+  case QmlMessageModel::DisplayRole:
+    return _styledMsg.decoratedTimestamp();
+  case QmlMessageModel::EditRole:
+    return _styledMsg.timestamp();
+  case QmlMessageModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Timestamp);
+  case QmlMessageModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Timestamp, true);
+  case QmlMessageModel::FormatRole:
+    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList()
+                      << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Timestamp));
+  }
+  return QVariant();
+}
+
+QVariant QmlMessageModelItem::senderData(int role) const {
+  switch(role) {
+  case QmlMessageModel::DisplayRole:
+    return _styledMsg.decoratedSender();
+  case QmlMessageModel::EditRole:
+    return _styledMsg.plainSender();
+  case QmlMessageModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Sender);
+  case QmlMessageModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Sender, true);
+  case QmlMessageModel::FormatRole:
+    return QVariant::fromValue<UiStyle::FormatList>(UiStyle::FormatList()
+                      << qMakePair((quint16)0, (quint32)UiStyle::formatType(_styledMsg.type()) | UiStyle::Sender));
+  }
+  return QVariant();
+}
+
+QVariant QmlMessageModelItem::contentsData(int role) const {
+  switch(role) {
+  case QmlMessageModel::DisplayRole:
+  case QmlMessageModel::EditRole:
+    return _styledMsg.plainContents();
+  case QmlMessageModel::BackgroundRole:
+    return backgroundBrush(UiStyle::Contents);
+  case QmlMessageModel::SelectedBackgroundRole:
+    return backgroundBrush(UiStyle::Contents, true);
+  case QmlMessageModel::FormatRole:
+    return QVariant::fromValue<UiStyle::FormatList>(_styledMsg.contentsFormatList());
+  }
+  return QVariant();
+}
+
+quint32 QmlMessageModelItem::messageLabel() const {
+  quint32 label = _styledMsg.senderHash() << 16;
+  if(_styledMsg.flags() & Message::Self)
+    label |= UiStyle::OwnMsg;
+  if(_styledMsg.flags() & Message::Highlight)
+    label |= UiStyle::Highlight;
+  return label;
+}
+
+QVariant QmlMessageModelItem::backgroundBrush(UiStyle::FormatType subelement, bool selected) const {
+  QTextCharFormat fmt = GraphicalUi::uiStyle()->format(UiStyle::formatType(_styledMsg.type()) | subelement, messageLabel() | (selected ? UiStyle::Selected : 0));
+  if(fmt.hasProperty(QTextFormat::BackgroundBrush))
+    return QVariant::fromValue<QBrush>(fmt.background());
+  return QVariant();
+}
index 7138df3..b9a2602 100644 (file)
@@ -29,6 +29,7 @@ public:
   QmlMessageModelItem(const Message &msg);
 
   virtual QVariant data(int column, int role) const;
+  virtual bool setData(int column, const QVariant &value, int role);
 
   virtual inline const Message &message() const { return _styledMsg; }
   virtual inline const QDateTime &timestamp() const { return _styledMsg.timestamp(); }
@@ -39,6 +40,13 @@ public:
   virtual inline Message::Flags msgFlags() const { return _styledMsg.flags(); }
 
 private:
+  QVariant timestampData(int role) const;
+  QVariant senderData(int role) const;
+  QVariant contentsData(int role) const;
+
+  QVariant backgroundBrush(UiStyle::FormatType subelement, bool selected = false) const;
+  quint32 messageLabel() const;
+
   UiStyle::StyledMessage _styledMsg;
 };