File indexing completed on 2024-05-05 16:58:37

0001 // SPDX-FileCopyrightText: 2018 Black Hat <bhat@encom.eu.org>
0002 // SPDX-License-Identifier: GPL-3.0-only
0003 
0004 #pragma once
0005 
0006 #include <QAbstractListModel>
0007 #include <QObject>
0008 #include <QSettings>
0009 
0010 struct Emoji {
0011     Emoji(QString unicode, QString shortname, bool isCustom = false)
0012         : unicode(std::move(unicode))
0013         , shortName(std::move(shortname))
0014         , isCustom(isCustom)
0015     {
0016     }
0017     Emoji(QString unicode, QString shortname, QString description)
0018         : unicode(std::move(unicode))
0019         , shortName(std::move(shortname))
0020         , description(std::move(description))
0021     {
0022     }
0023     Emoji() = default;
0024 
0025     friend QDataStream &operator<<(QDataStream &arch, const Emoji &object)
0026     {
0027         arch << object.unicode;
0028         arch << object.shortName;
0029         return arch;
0030     }
0031 
0032     friend QDataStream &operator>>(QDataStream &arch, Emoji &object)
0033     {
0034         arch >> object.unicode;
0035         arch >> object.shortName;
0036         object.isCustom = object.unicode.startsWith("image://");
0037         return arch;
0038     }
0039 
0040     QString unicode;
0041     QString shortName;
0042     QString description;
0043     bool isCustom = false;
0044 
0045     Q_GADGET
0046     Q_PROPERTY(QString unicode MEMBER unicode)
0047     Q_PROPERTY(QString shortName MEMBER shortName)
0048     Q_PROPERTY(QString description MEMBER description)
0049     Q_PROPERTY(bool isCustom MEMBER isCustom)
0050 };
0051 
0052 Q_DECLARE_METATYPE(Emoji)
0053 
0054 /**
0055  * @class EmojiModel
0056  *
0057  * This class defines the model for visualising a list of emojis.
0058  */
0059 class EmojiModel : public QAbstractListModel
0060 {
0061     Q_OBJECT
0062 
0063     /**
0064      * @brief Return a list of recently used emojis.
0065      */
0066     Q_PROPERTY(QVariantList history READ history NOTIFY historyChanged)
0067 
0068     /**
0069      * @brief Return a list of emoji categories.
0070      *
0071      * @note No custom emoji categories will be included.
0072      */
0073     Q_PROPERTY(QVariantList categories READ categories CONSTANT)
0074 
0075     /**
0076      * @brief Return a list of emoji categories with custom emojis.
0077      */
0078     Q_PROPERTY(QVariantList categoriesWithCustom READ categoriesWithCustom CONSTANT)
0079 
0080 public:
0081     static EmojiModel &instance()
0082     {
0083         static EmojiModel _instance;
0084         return _instance;
0085     }
0086 
0087     /**
0088      * @brief Defines the model roles.
0089      */
0090     enum RoleNames {
0091         ShortNameRole = Qt::DisplayRole, /**< The name of the emoji. */
0092         UnicodeRole, /**< The unicode character of the emoji. */
0093         InvalidRole = 50, /**< Invalid, reserved. */
0094         DisplayRole = 51, /**< The display text for an emoji. */
0095         ReplacedTextRole = 52, /**< The text to replace the short name with (i.e. the unicode character). */
0096         DescriptionRole = 53, /**< The long description of an emoji. */
0097     };
0098     Q_ENUM(RoleNames)
0099 
0100     /**
0101      * @brief Defines the potential categories an emoji can be placed in.
0102      */
0103     enum Category {
0104         Custom, /**< A custom user emoji. */
0105         Search, /**< The results of a filter. */
0106         SearchNoCustom, /**< The results of a filter with no custom emojis. */
0107         History, /**< Recently used emojis. */
0108         HistoryNoCustom, /**< Recently used emojis with no custom emojis. */
0109         Smileys, /**< Smileys & emotion emojis. */
0110         People, /**< People & Body emojis. */
0111         Nature, /**< Animals & Nature emojis. */
0112         Food, /**< Food & Drink emojis. */
0113         Activities, /**< Activities emojis. */
0114         Travel, /**< Travel & Places emojis. */
0115         Objects, /**< Objects emojis. */
0116         Symbols, /**< Symbols emojis. */
0117         Flags, /**< Flags emojis. */
0118         Component, /**< ??? */
0119     };
0120     Q_ENUM(Category)
0121 
0122     /**
0123      * @brief Get the given role value at the given index.
0124      *
0125      * @sa QAbstractItemModel::data
0126      */
0127     [[nodiscard]] QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
0128 
0129     /**
0130      * @brief Number of rows in the model.
0131      *
0132      * @sa  QAbstractItemModel::rowCount
0133      */
0134     [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
0135 
0136     /**
0137      * @brief Returns a mapping from Role enum values to role names.
0138      *
0139      * @sa RoleNames, QAbstractItemModel::roleNames()
0140      */
0141     [[nodiscard]] QHash<int, QByteArray> roleNames() const override;
0142 
0143     /**
0144      * @brief Return a filtered list of emojis.
0145      *
0146      * @note This includes custom emojis, use filterModelNoCustom to return a result
0147      *       without custom emojis.
0148      *
0149      * @sa filterModelNoCustom
0150      */
0151     Q_INVOKABLE static QVariantList filterModel(const QString &filter, bool limit = true);
0152 
0153     /**
0154      * @brief Return a filtered list of emojis without custom emojis.
0155      *
0156      * @note Use filterModel to return a result with custom emojis.
0157      *
0158      * @sa filterModel
0159      */
0160     Q_INVOKABLE static QVariantList filterModelNoCustom(const QString &filter, bool limit = true);
0161 
0162     /**
0163      * @brief Return a list of emojis for the given category.
0164      */
0165     Q_INVOKABLE QVariantList emojis(Category category) const;
0166 
0167     /**
0168      * @brief Return a list of emoji tones for the given base emoji.
0169      */
0170     Q_INVOKABLE QVariantList tones(const QString &baseEmoji) const;
0171 
0172     Q_INVOKABLE QVariantList history() const;
0173     QVariantList categories() const;
0174     QVariantList categoriesWithCustom() const;
0175 
0176 Q_SIGNALS:
0177     void historyChanged();
0178 
0179 public Q_SLOTS:
0180     void emojiUsed(const QVariant &modelData);
0181 
0182 private:
0183     static QHash<Category, QVariantList> _emojis;
0184 
0185     // TODO: Port away from QSettings
0186     QSettings m_settings;
0187     EmojiModel(QObject *parent = nullptr);
0188 };