Files
neochat/src/models/messageeventmodel.h
James Graham 2c6ab498ac Event Handler
Similar to text handler, pull out the disparate array of functions which format information from an event ready for display in the UI and put in a handler class with a test suite.

requires https://github.com/quotient-im/libQuotient/pull/686
2023-09-07 19:02:50 +00:00

153 lines
6.0 KiB
C++

// SPDX-FileCopyrightText: 2018-2019 Black Hat <bhat@encom.eu.org>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
#include <KFormat>
#include <QAbstractListModel>
#include "linkpreviewer.h"
#include "neochatroom.h"
class ReactionModel;
/**
* @class MessageEventModel
*
* This class defines the model for visualising the room timeline.
*
* This model covers all event types in the timeline with many of the roles being
* specific to a subset of events. This means the user needs to understand which
* roles will return useful information for a given event type.
*
* @sa NeoChatRoom
*/
class MessageEventModel : public QAbstractListModel
{
Q_OBJECT
/**
* @brief The current room that the model is getting its messages from.
*/
Q_PROPERTY(NeoChatRoom *room READ room WRITE setRoom NOTIFY roomChanged)
public:
/**
* @brief Defines the model roles.
*/
enum EventRoles {
DelegateTypeRole = Qt::UserRole + 1, /**< The delegate type of the message. */
PlainText, /**< Plain text representation of the message. */
EventIdRole, /**< The matrix event ID of the event. */
TimeRole, /**< The timestamp for when the event was sent (as a QDateTime). */
TimeStringRole, /**< The timestamp for when the event was sent as a string (in QLocale::ShortFormat). */
SectionRole, /**< The date of the event as a string. */
AuthorRole, /**< The author of the event. */
ContentRole, /**< The full message content. */
HighlightRole, /**< Whether the event should be highlighted. */
SpecialMarksRole, /**< Whether the event is hidden or not. */
ProgressInfoRole, /**< Progress info when downloading files. */
GenericDisplayRole, /**< A generic string based upon the message type. */
ShowLinkPreviewRole, /**< Whether a link preview should be shown. */
LinkPreviewRole, /**< The link preview details. */
MediaInfoRole, /**< The media info for the event. */
IsReplyRole, /**< Is the message a reply to another event. */
ReplyAuthor, /**< The author of the event that was replied to. */
ReplyIdRole, /**< The matrix ID of the message that was replied to. */
ReplyDelegateTypeRole, /**< The delegate type of the message that was replied to. */
ReplyDisplayRole, /**< The body of the message that was replied to. */
ReplyMediaInfoRole, /**< The media info of the message that was replied to. */
ShowAuthorRole, /**< Whether the author's name should be shown. */
ShowSectionRole, /**< Whether the section header should be shown. */
ReadMarkersRole, /**< The first 5 other users at the event for read marker tracking. */
ExcessReadMarkersRole, /**< The number of other users at the event after the first 5. */
ReadMarkersStringRole, /**< String with the display name and mxID of the users at the event. */
ShowReadMarkersRole, /**< Whether there are any other user read markers to be shown. */
ReactionRole, /**< List model for this event. */
ShowReactionsRole, /**< Whether there are any reactions to be shown. */
SourceRole, /**< The full message source JSON. */
AuthorIdRole, /**< Matrix ID of the message author. */
VerifiedRole, /**< Whether an encrypted message is sent in a verified session. */
AuthorDisplayNameRole, /**< The displayname for the event's sender; for name change events, the old displayname. */
IsRedactedRole, /**< Whether an event has been deleted. */
IsPendingRole, /**< Whether an event is waiting to be accepted by the server. */
LatitudeRole, /**< Latitude for a location event. */
LongitudeRole, /**< Longitude for a location event. */
AssetRole, /**< Type of location event, e.g. self pin of the user location. */
LastRole, // Keep this last
};
Q_ENUM(EventRoles)
explicit MessageEventModel(QObject *parent = nullptr);
[[nodiscard]] NeoChatRoom *room() const;
void setRoom(NeoChatRoom *room);
/**
* @brief Get the given role value at the given index.
*
* @sa QAbstractItemModel::data
*/
[[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
/**
* @brief Number of rows in the model.
*
* @sa QAbstractItemModel::rowCount
*/
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
/**
* @brief Returns a mapping from Role enum values to role names.
*
* @sa EventRoles, QAbstractItemModel::roleNames()
*/
[[nodiscard]] QHash<int, QByteArray> roleNames() const override;
/**
* @brief Get the row number of the given event ID in the model.
*/
Q_INVOKABLE [[nodiscard]] int eventIdToRow(const QString &eventID) const;
private Q_SLOTS:
int refreshEvent(const QString &eventId);
void refreshRow(int row);
private:
NeoChatRoom *m_currentRoom = nullptr;
QString lastReadEventId;
QPersistentModelIndex m_lastReadEventIndex;
int rowBelowInserted = -1;
bool movingEvent = false;
KFormat m_format;
QMap<QString, QSharedPointer<LinkPreviewer>> m_linkPreviewers;
QMap<QString, QSharedPointer<ReactionModel>> m_reactionModels;
[[nodiscard]] int timelineBaseIndex() const;
[[nodiscard]] QDateTime makeMessageTimestamp(const Quotient::Room::rev_iter_t &baseIt) const;
bool canFetchMore(const QModelIndex &parent) const override;
void fetchMore(const QModelIndex &parent) override;
void refreshLastUserEvents(int baseTimelineRow);
void refreshEventRoles(int row, const QVector<int> &roles = {});
int refreshEventRoles(const QString &eventId, const QVector<int> &roles = {});
void moveReadMarker(const QString &toEventId);
void createEventObjects(const Quotient::RoomMessageEvent *event);
// Hack to ensure that we don't call endInsertRows when we haven't called beginInsertRows
bool m_initialized = false;
Q_SIGNALS:
void roomChanged();
void fancyEffectsReasonFound(const QString &fancyEffect);
};