From: Manuel Nickschas Date: Sat, 19 Nov 2011 10:12:08 +0000 (+0100) Subject: More QML fidgetery X-Git-Url: https://git.quassel-irc.org/?a=commitdiff_plain;h=8ec1029ae729b443f9df955dabf831397341abe6;p=quassel.git More QML fidgetery 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. --- diff --git a/src/qmlui/qml/ChatView.qml b/src/qmlui/qml/ChatView.qml index aa72fb4c..79a91486 100644 --- a/src/qmlui/qml/ChatView.qml +++ b/src/qmlui/qml/ChatView.qml @@ -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" + } } - } } diff --git a/src/qmlui/qmlchatline.cpp b/src/qmlui/qmlchatline.cpp index 874437cc..3d3c4b40 100644 --- a/src/qmlui/qmlchatline.cpp +++ b/src/qmlui/qmlchatline.cpp @@ -22,38 +22,173 @@ #include "qmlchatline.h" void QmlChatLine::registerTypes() { - qRegisterMetaType("QmlChatLine::Data"); - qRegisterMetaTypeStreamOperators("QmlChatLine::Data"); - qmlRegisterType("eu.quassel.qmlui", 1, 0, "ChatLine"); + qRegisterMetaType("QmlChatLine::RenderData"); + qRegisterMetaTypeStreamOperators("QmlChatLine::RenderData"); + qmlRegisterType("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(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(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); + +} diff --git a/src/qmlui/qmlchatline.h b/src/qmlui/qmlchatline.h index 12ce82e9..db8d5d0f 100644 --- a/src/qmlui/qmlchatline.h +++ b/src/qmlui/qmlchatline.h @@ -25,44 +25,137 @@ #include "uistyle.h" +class QAbstractItemModel; + +#include + 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); } - inline void setChatLineData(const QVariant &data) { _data = data.value(); } + inline QAbstractItemModel *model() const { return _model; } + inline QObject *modelPointer() const { return _model; } + void setModelPointer(QObject *model) { _model = qobject_cast(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 diff --git a/src/qmlui/qmlmessagemodel.cpp b/src/qmlui/qmlmessagemodel.cpp index fc7ecc3b..c58f862f 100644 --- a/src/qmlui/qmlmessagemodel.cpp +++ b/src/qmlui/qmlmessagemodel.cpp @@ -29,7 +29,7 @@ QmlMessageModel::QmlMessageModel(QObject *parent) QmlChatLine::registerTypes(); QHash roles; - roles[ChatLineDataRole] = "chatLineDataRole"; + roles[RenderDataRole] = "renderDataRole"; setRoleNames(roles); } diff --git a/src/qmlui/qmlmessagemodel.h b/src/qmlui/qmlmessagemodel.h index 92ce1e7d..ce59d8f2 100644 --- a/src/qmlui/qmlmessagemodel.h +++ b/src/qmlui/qmlmessagemodel.h @@ -31,7 +31,9 @@ class QmlMessageModel : public MessageModel { public: enum QmlMessageModelRole { - ChatLineDataRole = MessageModel::UserRole, + RenderDataRole = MessageModel::UserRole, + MsgLabelRole, + SelectedBackgroundRole, UserRole }; diff --git a/src/qmlui/qmlmessagemodelitem.cpp b/src/qmlui/qmlmessagemodelitem.cpp index 561c9b7b..ec11ec4e 100644 --- a/src/qmlui/qmlmessagemodelitem.cpp +++ b/src/qmlui/qmlmessagemodelitem.cpp @@ -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(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(); + data[QmlChatLine::TimestampColumn].selectedBackground = backgroundBrush(UiStyle::Timestamp, true).value(); + + 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(); + data[QmlChatLine::SenderColumn].selectedBackground = backgroundBrush(UiStyle::Sender, true).value(); + + data[QmlChatLine::ContentsColumn].text = _styledMsg.plainContents(); + data[QmlChatLine::ContentsColumn].formats = _styledMsg.contentsFormatList(); + data[QmlChatLine::ContentsColumn].background = backgroundBrush(UiStyle::Contents).value(); + data[QmlChatLine::ContentsColumn].selectedBackground = backgroundBrush(UiStyle::Contents, true).value(); + + return QVariant::fromValue(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() + << 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() + << 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(_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(fmt.background()); + return QVariant(); +} diff --git a/src/qmlui/qmlmessagemodelitem.h b/src/qmlui/qmlmessagemodelitem.h index 7138df3c..b9a2602e 100644 --- a/src/qmlui/qmlmessagemodelitem.h +++ b/src/qmlui/qmlmessagemodelitem.h @@ -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 ×tamp() 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; };