+protected:
+ ChatItem(const qreal &width, const qreal &height, const QPointF &pos, QGraphicsItem *parent);
+ virtual ~ChatItem();
+
+public:
+ inline const QAbstractItemModel *model() const;
+ inline int row() const;
+ virtual ChatLineModel::ColumnType column() const = 0;
+ inline ChatScene *chatScene() const { return qobject_cast<ChatScene *>(scene()); }
+
+ inline QRectF boundingRect() const { return _boundingRect; }
+ inline qreal width() const { return _boundingRect.width(); }
+ inline qreal height() const { return _boundingRect.height(); }
+
+ QTextLayout *createLayout(QTextOption::WrapMode, Qt::Alignment = Qt::AlignLeft) const;
+ virtual void doLayout();
+ void clearLayout();
+
+ virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
+
+ QVariant data(int role) const;
+
+ // selection stuff, to be called by the scene
+ void clearSelection();
+ void setFullSelection();
+ void continueSelecting(const QPointF &pos);
+
+ QList<QRectF> findWords(const QString &searchWord, Qt::CaseSensitivity caseSensitive);
+
+protected:
+ virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
+ virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+ inline QTextLayout *layout() const;
+
+ virtual inline QVector<QTextLayout::FormatRange> additionalFormats() const { return QVector<QTextLayout::FormatRange>(); }
+ qint16 posToCursor(const QPointF &pos);
+
+ inline bool hasPrivateData() const { return (bool)_data; }
+ ChatItemPrivate *privateData() const;
+ virtual inline ChatItemPrivate *newPrivateData();
+
+ // WARNING: setGeometry and setHeight should not be used without either:
+ // a) calling prepareGeometryChange() immediately before setColumns()
+ // b) calling Chatline::setPos() immediately afterwards
+ inline void setGeometry(qreal width, qreal height) {
+ prepareGeometryChange();
+ _boundingRect.setWidth(width);
+ _boundingRect.setHeight(height);
+ }
+ inline void setHeight(const qreal &height) {
+ prepareGeometryChange();
+ _boundingRect.setHeight(height);
+ }
+ inline void setWidth(const qreal &width) {
+ prepareGeometryChange();
+ _boundingRect.setWidth(width);
+ }
+
+private:
+ // internal selection stuff
+ void setSelection(int start, int length);
+
+ ChatItemPrivate *_data;
+ QRectF _boundingRect;
+
+ enum SelectionMode { NoSelection, PartialSelection, FullSelection };
+ SelectionMode _selectionMode;
+ qint16 _selectionStart, _selectionEnd;
+
+ friend class ChatLine;
+};
+
+struct ChatItemPrivate {
+ QTextLayout *layout;
+ ChatItemPrivate(QTextLayout *l) : layout(l) {}
+ ~ChatItemPrivate() {
+ delete layout;
+ }
+};
+
+// inlines of ChatItem
+QTextLayout *ChatItem::layout() const { return privateData()->layout; }
+ChatItemPrivate *ChatItem::newPrivateData() { return new ChatItemPrivate(createLayout(QTextOption::WrapAnywhere)); }
+
+// ************************************************************
+// TimestampChatItem
+// ************************************************************
+
+//! A ChatItem for the timestamp column
+class TimestampChatItem : public ChatItem {
+public:
+ TimestampChatItem(const qreal &width, const qreal &height, QGraphicsItem *parent) : ChatItem(width, height, QPointF(0, 0), parent) {}
+ virtual inline ChatLineModel::ColumnType column() const { return ChatLineModel::TimestampColumn; }
+};