/* * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * * Author: Kateryna Kostiuk * Author: Trevor Tabah * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once #include "api/interaction.h" #include namespace lrc { namespace api { namespace interaction { struct Info; } #define MSG_ROLES \ X(Id) \ X(Author) \ X(Body) \ X(ParentId) \ X(Timestamp) \ X(Duration) \ X(Type) \ X(Status) \ X(IsRead) \ X(ContactAction) \ X(ActionUri) \ X(LinkPreviewInfo) \ X(Linkified) \ X(ReplyTo) \ X(ReplyToBody) \ X(ReplyToAuthor) \ X(TransferName) \ X(Readers) namespace MessageList { Q_NAMESPACE enum Role { DummyRole = Qt::UserRole + 1, #define X(role) role, MSG_ROLES #undef X }; Q_ENUM_NS(Role) } // namespace MessageList class MessageListModel : public QAbstractListModel { Q_OBJECT public: using item_t = const QPair; typedef QList>::ConstIterator constIterator; typedef QList>::Iterator iterator; typedef QList>::reverse_iterator reverseIterator; explicit MessageListModel(QObject* parent = nullptr); ~MessageListModel() = default; // map functions QPair emplace(const QString& msgId, interaction::Info message, bool beginning = false); iterator find(const QString& msgId); iterator erase(const iterator& it); constIterator find(const QString& msgId) const; QPair insert(std::pair message, bool beginning = false); Q_INVOKABLE int erase(const QString& msgId); interaction::Info& operator[](const QString& messageId); iterator end(); constIterator end() const; constIterator cend() const; iterator begin(); constIterator begin() const; reverseIterator rbegin(); Q_INVOKABLE int size() const; void clear(); bool empty() const; interaction::Info at(const QString& intId) const; QPair front() const; QPair last() const; QPair atIndex(int index) const; QPair insert(int index, QPair message); int indexOfMessage(const QString& msgId, bool reverse = true) const; void moveMessages(QList msgIds, const QString& parentId); int rowCount(const QModelIndex& parent = QModelIndex()) const override; Q_INVOKABLE virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; Q_INVOKABLE virtual QVariant data(int idx, int role = Qt::DisplayRole) const; QHash roleNames() const override; QVariant dataForItem(item_t item, int indexRow, int role = Qt::DisplayRole) const; bool contains(const QString& msgId); int getIndexOfMessage(const QString& messageId) const; void addHyperlinkInfo(const QString& messageId, const QVariantMap& info); void linkifyMessage(const QString& messageId, const QString& linkified); void setRead(const QString& peer, const QString& messageId); QString getRead(const QString& peer); // use these if the underlying data model is changed from conversationmodel // Note: this is not ideal, and this class should be refactored into a proper // view model and absorb the interaction management logic to avoid exposing // these emission wrappers void emitDataChanged(iterator it, VectorInt roles = {}); void emitDataChanged(const QString& msgId, VectorInt roles = {}); protected: using Role = MessageList::Role; private: QList> interactions_; // Note: because read status are updated even if interaction is not loaded // we need to keep track of these status outside the interaction::Info // lastDisplayedMessageUid_ stores: {"peerId":"messageId"} // messageToReaders_ caches: "messageId":["peer1", "peer2"] // to allow quick access. QMap lastDisplayedMessageUid_; QMap messageToReaders_; QMap replyTo_; void moveMessage(const QString& msgId, const QString& parentId); void insertMessage(int index, item_t& message); iterator insertMessage(iterator it, item_t& message); void removeMessage(int index, iterator it); void moveMessage(int from, int to); }; } // namespace api } // namespace lrc Q_DECLARE_METATYPE(lrc::api::MessageListModel*)