You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

168 lines
7.1 KiB

/* Роли модели сообщений и отрисовка text/voice/file/image/video, статусов и progress.
* Рассчитывает геометрию для ChatView и обрабатывает действия по media-элементам строки. */
#pragma once
#include <cstdint>
#include <QStyledItemDelegate>
#include <QPersistentModelIndex>
#include <QVector>
#include <functional>
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,
MsgImageWidthRole = Qt::UserRole + 31,
MsgImageHeightRole = Qt::UserRole + 32,
MsgVideoWidthRole = Qt::UserRole + 33,
MsgVideoHeightRole = Qt::UserRole + 34,
MsgVideoDurationMsRole = Qt::UserRole + 35,
MsgDeliveryStateRole = Qt::UserRole + 36,
MsgInviteLinkRole = Qt::UserRole + 37, /* полная ссылка; MsgTextRole содержит локализованный заголовок и ссылку */
MsgMessageKeyRole = Qt::UserRole + 38,
MsgRawTimestampRole = Qt::UserRole + 39,
MsgReplyToRole = Qt::UserRole + 40,
MsgHighlightRole = Qt::UserRole + 41,
};
class MessageDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
static constexpr int kAvatar = 54;
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;
QString linkAt(const QStyleOptionViewItem& option, const QModelIndex& index, const QPoint& point) const;
static void startAutoPlay(const QString& filePath, float actualDurationSec, uint64_t playbackId);
static void stopAllAutoPlay();
void setVideoOpenCallback(std::function<void(const QString&)> cb) { m_videoOpenCb = std::move(cb); }
void setImageOpenCallback(std::function<void(const QString&)> cb) { m_imageOpenCb = std::move(cb); }
void setDownloadCallback(std::function<bool(const QModelIndex&)> cb) { m_downloadCb = std::move(cb); }
signals:
void avatarRequested(const QString& channel, quint64 owner);
void reactionRequested(const QModelIndex& index, int emoji); /* -1 открывает выбор реакции */
void pollRequested(const QString& messageId);
void replyRequested(const QString& messageId);
private:
struct ReactionChip { QRect rect; int id; QString emoji; int count; bool mine; };
struct Layout {
int viewWidth;
int bubbleWidth;
QRect authorRect;
QRect avatarRect;
QRect bubbleRect;
QRect quoteRect;
QRect quoteBarRect;
QRect quoteAuthorRect;
QRect quoteTextRect;
QRect textRect;
QRect statusRect;
QRect deliveryRect;
int totalHeight;
bool narrow = false;
bool emojiOnly = false;
int emojiCount = 0;
QRect emojiArea;
bool isOutgoing = false;
bool isVoice = false;
bool isFile = false;
bool isVideo = false;
bool isImage = 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;
QRect videoThumbRect;
QRect videoPlayBtnRect;
QRect videoDurBadgeRect;
QRect imageThumbRect;
QRect imageBadgeRect;
QRect reactionHeart;
QRect reactionTime;
QString reactionTimeText;
QVector<ReactionChip> reactionChips;
};
std::function<void(const QString&)> m_videoOpenCb;
std::function<void(const QString&)> m_imageOpenCb;
QPersistentModelIndex m_avatarPress;
QPoint m_avatarPressPosition;
QPersistentModelIndex m_reactionPress;
QPoint m_reactionPressPosition;
int m_pressedReaction = -2;
QPersistentModelIndex m_pollPress;
QPoint m_pollPressPosition;
QPersistentModelIndex m_quotePress;
QPoint m_quotePressPosition;
std::function<bool(const QModelIndex&)> m_downloadCb;
Layout calcLayout(const QStyleOptionViewItem &option,
const QModelIndex &index) const;
Layout calcBodyLayout(const QStyleOptionViewItem& option, const QModelIndex& index) const;
void paintBody(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const Layout& layout) const;
void drawReactions(QPainter* painter, const Layout& layout, const QStyleOptionViewItem& option) 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 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;
};