#pragma once #include enum MessageDataRole { MsgAuthorRole = Qt::UserRole + 1, MsgTextRole = Qt::UserRole + 2, MsgTimeRole = Qt::UserRole + 3, MsgEditedRole = Qt::UserRole + 4, MsgAvatarRole = Qt::UserRole + 5, MsgHasQuoteRole = Qt::UserRole + 6, MsgQuoteAuthorRole = Qt::UserRole + 7, MsgQuoteTextRole = Qt::UserRole + 8, MsgReactionsRole = Qt::UserRole + 9, MsgIdRole = Qt::UserRole + 10, MsgIsOutgoingRole = Qt::UserRole + 11, MsgContentTypeRole = Qt::UserRole + 12, MsgVoiceDurationRole = Qt::UserRole + 13, MsgVoiceFileRole = Qt::UserRole + 14, MsgVoicePlayStateRole = Qt::UserRole + 15, MsgVoicePlayPosRole = Qt::UserRole + 16, MsgVoiceWaveformRole = Qt::UserRole + 17, MsgVoiceFileSizeRole = Qt::UserRole + 18, MsgVoiceBlockSizeRole = Qt::UserRole + 19, MsgAuthorNodeIdRole = Qt::UserRole + 20, MsgVoiceNumBlocksRole = Qt::UserRole + 21, MsgVoiceSigsRole = Qt::UserRole + 22, MsgFileDisplayNameRole = Qt::UserRole + 23, MsgFileSizeRole = Qt::UserRole + 24, MsgFileDownloadStateRole = Qt::UserRole + 25, MsgChannelIdRole = Qt::UserRole + 26, MsgFileDownloadProgressRole = Qt::UserRole + 27, MsgMediaBlocksDoneRole = Qt::UserRole + 28, MsgMediaNumBlocksRole = Qt::UserRole + 29, MsgVoiceDownloadPendingRole = Qt::UserRole + 30, }; class MessageDelegate : public QStyledItemDelegate { Q_OBJECT public: explicit MessageDelegate(QObject *parent = nullptr); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) override; private: struct Layout { int viewWidth; int bubbleWidth; QRect authorRect; QRect avatarRect; QRect bubbleRect; QRect quoteRect; QRect quoteBarRect; QRect quoteAuthorRect; QRect quoteTextRect; QRect textRect; QRect statusRect; int totalHeight; bool narrow = false; bool emojiOnly = false; int emojiCount = 0; QRect emojiArea; bool isOutgoing = false; bool isVoice = false; bool isFile = false; QRect voicePlayBtnRect; QRect voiceWaveformRect; QRect voiceDurationRect; QRect voiceTimeRect; QString voiceDuration; int mediaBarColor = 0; /* 0=gray, 1=yellow, 2=green */ QRect mediaBarRect; QRect progressBarRect; float progressFrac = 0.0f; }; Layout calcLayout(const QStyleOptionViewItem &option, const QModelIndex &index) const; void drawQuote(QPainter *p, const Layout &L, const QModelIndex &index, const QStyleOptionViewItem &opt) const; void drawBubble(QPainter *p, const Layout &L, const QStyleOptionViewItem &opt) const; void drawStatusBar(QPainter *p, const Layout &L, const QModelIndex &index, const QStyleOptionViewItem &opt) const; void drawAvatar(QPainter *p, const Layout &L, const QModelIndex &index) const; static constexpr int kAvatar = 36; static constexpr int kGap = 8; static constexpr int kRadius = 10; static constexpr int kPadH = 12; static constexpr int kPadTop = 8; static constexpr int kPadBot = 6; static constexpr int kTail = 6; static constexpr int kMarginH = 8; static constexpr int kItemGap = 3; static constexpr int kQuoteGap = 4; static constexpr int kQuotePadH = 6; static constexpr int kQuotePadV = 6; static constexpr int kQuoteBarW = 2; static constexpr int kQuoteAv = 16; static constexpr int kStatusH = 18; };