File indexing completed on 2024-12-08 07:33:45
0001 // SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org> 0002 // SPDX-License-Identifier: GPL-3.0-only 0003 0004 #pragma once 0005 0006 #include <KFormat> 0007 #include <QAbstractListModel> 0008 #include <QQmlEngine> 0009 0010 #include "linkpreviewer.h" 0011 #include "neochatroom.h" 0012 #include "pollhandler.h" 0013 0014 class ReactionModel; 0015 0016 /** 0017 * @class MessageEventModel 0018 * 0019 * This class defines the model for visualising the room timeline. 0020 * 0021 * This model covers all event types in the timeline with many of the roles being 0022 * specific to a subset of events. This means the user needs to understand which 0023 * roles will return useful information for a given event type. 0024 * 0025 * @sa NeoChatRoom 0026 */ 0027 class MessageEventModel : public QAbstractListModel 0028 { 0029 Q_OBJECT 0030 QML_ELEMENT 0031 0032 /** 0033 * @brief The current room that the model is getting its messages from. 0034 */ 0035 Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged) 0036 0037 public: 0038 /** 0039 * @brief Defines the model roles. 0040 */ 0041 enum EventRoles { 0042 DelegateTypeRole = Qt::UserRole + 1, /**< The delegate type of the message. */ 0043 PlainText, /**< Plain text representation of the message. */ 0044 EventIdRole, /**< The matrix event ID of the event. */ 0045 TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */ 0046 TimeStringRole, /**< The timestamp for when the event was sent as a string (in QLocale::ShortFormat). */ 0047 SectionRole, /**< The date of the event as a string. */ 0048 AuthorRole, /**< The author of the event. */ 0049 HighlightRole, /**< Whether the event should be highlighted. */ 0050 SpecialMarksRole, /**< Whether the event is hidden or not. */ 0051 ProgressInfoRole, /**< Progress info when downloading files. */ 0052 GenericDisplayRole, /**< A generic string based upon the message type. */ 0053 0054 ShowLinkPreviewRole, /**< Whether a link preview should be shown. */ 0055 LinkPreviewRole, /**< The link preview details. */ 0056 0057 MediaInfoRole, /**< The media info for the event. */ 0058 0059 IsReplyRole, /**< Is the message a reply to another event. */ 0060 ReplyAuthor, /**< The author of the event that was replied to. */ 0061 ReplyIdRole, /**< The matrix ID of the message that was replied to. */ 0062 ReplyDelegateTypeRole, /**< The delegate type of the message that was replied to. */ 0063 ReplyDisplayRole, /**< The body of the message that was replied to. */ 0064 ReplyMediaInfoRole, /**< The media info of the message that was replied to. */ 0065 0066 IsThreadedRole, 0067 ThreadRootRole, 0068 0069 ShowAuthorRole, /**< Whether the author's name should be shown. */ 0070 ShowSectionRole, /**< Whether the section header should be shown. */ 0071 0072 ReadMarkersRole, /**< The first 5 other users at the event for read marker tracking. */ 0073 ExcessReadMarkersRole, /**< The number of other users at the event after the first 5. */ 0074 ReadMarkersStringRole, /**< String with the display name and mxID of the users at the event. */ 0075 ShowReadMarkersRole, /**< Whether there are any other user read markers to be shown. */ 0076 ReactionRole, /**< List model for this event. */ 0077 ShowReactionsRole, /**< Whether there are any reactions to be shown. */ 0078 0079 VerifiedRole, /**< Whether an encrypted message is sent in a verified session. */ 0080 AuthorDisplayNameRole, /**< The displayname for the event's sender; for name change events, the old displayname. */ 0081 IsRedactedRole, /**< Whether an event has been deleted. */ 0082 IsPendingRole, /**< Whether an event is waiting to be accepted by the server. */ 0083 LatitudeRole, /**< Latitude for a location event. */ 0084 LongitudeRole, /**< Longitude for a location event. */ 0085 AssetRole, /**< Type of location event, e.g. self pin of the user location. */ 0086 PollHandlerRole, /**< The PollHandler for the event, if any. */ 0087 LastRole, // Keep this last 0088 }; 0089 Q_ENUM(EventRoles) 0090 0091 explicit MessageEventModel(QObject *parent = nullptr); 0092 0093 [[nodiscard]] NeoChatRoom *room() const; 0094 void setRoom(NeoChatRoom *room); 0095 0096 /** 0097 * @brief Get the given role value at the given index. 0098 * 0099 * @sa QAbstractItemModel::data 0100 */ 0101 [[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override; 0102 0103 /** 0104 * @brief Number of rows in the model. 0105 * 0106 * @sa QAbstractItemModel::rowCount 0107 */ 0108 [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0109 0110 /** 0111 * @brief Returns a mapping from Role enum values to role names. 0112 * 0113 * @sa EventRoles, QAbstractItemModel::roleNames() 0114 */ 0115 [[nodiscard]] QHash<int, QByteArray> roleNames() const override; 0116 0117 /** 0118 * @brief Get the row number of the given event ID in the model. 0119 */ 0120 Q_INVOKABLE [[nodiscard]] int eventIdToRow(const QString &eventID) const; 0121 0122 protected: 0123 bool event(QEvent *event) override; 0124 0125 private Q_SLOTS: 0126 int refreshEvent(const QString &eventId); 0127 void refreshRow(int row); 0128 0129 private: 0130 NeoChatRoom *m_currentRoom = nullptr; 0131 QString lastReadEventId; 0132 QPersistentModelIndex m_lastReadEventIndex; 0133 int rowBelowInserted = -1; 0134 bool resetting = false; 0135 bool movingEvent = false; 0136 KFormat m_format; 0137 0138 QMap<QString, QSharedPointer<LinkPreviewer>> m_linkPreviewers; 0139 QMap<QString, QSharedPointer<ReactionModel>> m_reactionModels; 0140 0141 [[nodiscard]] int timelineBaseIndex() const; 0142 [[nodiscard]] QDateTime makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const; 0143 0144 bool canFetchMore(const QModelIndex &parent) const override; 0145 void fetchMore(const QModelIndex &parent) override; 0146 0147 void refreshLastUserEvents(int baseTimelineRow); 0148 void refreshEventRoles(int row, const QList<int> &roles = {}); 0149 int refreshEventRoles(const QString &eventId, const QList<int> &roles = {}); 0150 void moveReadMarker(const QString &toEventId); 0151 0152 void createEventObjects(const Quotient::RoomMessageEvent *event); 0153 // Hack to ensure that we don't call endInsertRows when we haven't called beginInsertRows 0154 bool m_initialized = false; 0155 0156 Q_SIGNALS: 0157 void roomChanged(); 0158 void fancyEffectsReasonFound(const QString &fancyEffect); 0159 };