File indexing completed on 2024-12-08 07:33:43
0001 // SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com> 0002 // SPDX-License-Identifier: GPL-2.0-or-later 0003 0004 #pragma once 0005 0006 #include <QAbstractListModel> 0007 #include <QQmlEngine> 0008 #include <QRegularExpression> 0009 0010 #include "neochatconnection.h" 0011 0012 struct CustomEmoji { 0013 QString name; // with :semicolons: 0014 QString url; // mxc:// 0015 QRegularExpression regexp; 0016 0017 Q_GADGET 0018 Q_PROPERTY(QString unicode MEMBER url) 0019 Q_PROPERTY(QString name MEMBER name) 0020 }; 0021 0022 /** 0023 * @class CustomEmojiModel 0024 * 0025 * This class defines the model for custom user emojis. 0026 * 0027 * This is based upon the im.ponies.user_emotes spec (MSC2545). 0028 */ 0029 class CustomEmojiModel : public QAbstractListModel 0030 { 0031 Q_OBJECT 0032 QML_ELEMENT 0033 QML_SINGLETON 0034 0035 Q_PROPERTY(NeoChatConnection *connection READ connection WRITE setConnection NOTIFY connectionChanged) 0036 0037 public: 0038 /** 0039 * @brief Defines the model roles. 0040 */ 0041 enum Roles { 0042 Name = Qt::DisplayRole, /**< The name of the emoji. */ 0043 ImageURL, /**< The URL for the custom emoji. */ 0044 ModelData, /**< for emulating the regular emoji model's usage, otherwise the UI code would get too complicated. */ 0045 MxcUrl = 50, /**< The mxc source URL for the custom emoji. */ 0046 DisplayRole = 51, /**< The name of the emoji. For compatibility with EmojiModel. */ 0047 ReplacedTextRole = 52, /**< The name of the emoji. For compatibility with EmojiModel. */ 0048 DescriptionRole = 53, /**< Invalid, reserved. For compatibility with EmojiModel. */ 0049 }; 0050 Q_ENUM(Roles) 0051 0052 static CustomEmojiModel &instance() 0053 { 0054 static CustomEmojiModel _instance; 0055 return _instance; 0056 } 0057 static CustomEmojiModel *create(QQmlEngine *engine, QJSEngine *) 0058 { 0059 engine->setObjectOwnership(&instance(), QQmlEngine::CppOwnership); 0060 return &instance(); 0061 } 0062 0063 /** 0064 * @brief Get the given role value at the given index. 0065 * 0066 * @sa QAbstractItemModel::data 0067 */ 0068 QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override; 0069 0070 /** 0071 * @brief Number of rows in the model. 0072 * 0073 * @sa QAbstractItemModel::rowCount 0074 */ 0075 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0076 0077 /** 0078 * @brief Returns a mapping from Role enum values to role names. 0079 * 0080 * @sa Roles, QAbstractItemModel::roleNames() 0081 */ 0082 QHash<int, QByteArray> roleNames() const override; 0083 0084 /** 0085 * @brief Substitute any custom emojis for an image in the input text. 0086 */ 0087 Q_INVOKABLE QString preprocessText(QString text); 0088 0089 /** 0090 * @brief Return a list of custom emojis where the name contains the filter text. 0091 */ 0092 Q_INVOKABLE QVariantList filterModel(const QString &filter); 0093 0094 /** 0095 * @brief Add a new emoji to the model. 0096 */ 0097 Q_INVOKABLE void addEmoji(const QString &name, const QUrl &location); 0098 0099 /** 0100 * @brief Remove an emoji from the model. 0101 */ 0102 Q_INVOKABLE void removeEmoji(const QString &name); 0103 0104 void setConnection(NeoChatConnection *connection); 0105 NeoChatConnection *connection() const; 0106 0107 Q_SIGNALS: 0108 void connectionChanged(); 0109 0110 private: 0111 explicit CustomEmojiModel(QObject *parent = nullptr); 0112 QList<CustomEmoji> m_emojis; 0113 NeoChatConnection *m_connection = nullptr; 0114 0115 void fetchEmojis(); 0116 };