File indexing completed on 2024-12-01 07:40:33

0001 // SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
0002 // SPDX-License-Identifier: GPL-3.0-or-later
0003 
0004 #include <QVariant>
0005 
0006 #include "emojimodel.h"
0007 #include "emojitones.h"
0008 #include <QDebug>
0009 
0010 #include <algorithm>
0011 
0012 #include "customemojimodel.h"
0013 #include <KLocalizedString>
0014 
0015 EmojiModel::EmojiModel(QObject *parent)
0016     : QAbstractListModel(parent)
0017     , m_config(KSharedConfig::openStateConfig())
0018     , m_configGroup(KConfigGroup(m_config, QStringLiteral("Editor")))
0019 {
0020     if (_emojis.isEmpty()) {
0021 #include "emojis.h"
0022     }
0023 }
0024 
0025 int EmojiModel::rowCount(const QModelIndex &parent) const
0026 {
0027     Q_UNUSED(parent);
0028     int total = 0;
0029     for (const auto &category : _emojis) {
0030         total += category.count();
0031     }
0032     return total;
0033 }
0034 
0035 QVariant EmojiModel::data(const QModelIndex &index, int role) const
0036 {
0037     auto row = index.row();
0038     for (const auto &category : _emojis) {
0039         if (row >= category.count()) {
0040             row -= category.count();
0041             continue;
0042         }
0043         auto emoji = category[row].value<Emoji>();
0044         switch (role) {
0045         case ShortNameRole:
0046             return QStringLiteral(":%1:").arg(emoji.shortName);
0047         case UnicodeRole:
0048         case ReplacedTextRole:
0049             return emoji.unicode;
0050         case InvalidRole:
0051             return QStringLiteral("invalid");
0052         case DisplayRole:
0053             return QStringLiteral("%2   :%1:").arg(emoji.shortName, emoji.unicode);
0054         case DescriptionRole:
0055             return emoji.description;
0056         }
0057     }
0058     return {};
0059 }
0060 
0061 QHash<int, QByteArray> EmojiModel::roleNames() const
0062 {
0063     return {{ShortNameRole, "shortName"}, {UnicodeRole, "unicode"}};
0064 }
0065 
0066 QStringList EmojiModel::lastUsedEmojis() const
0067 {
0068     return m_configGroup.readEntry(QStringLiteral("lastUsedEmojis"), QStringList());
0069 }
0070 
0071 QVariantList EmojiModel::filterModel(const QString &filter, bool limit)
0072 {
0073     auto emojis = CustomEmojiModel::instance().filterModel(filter);
0074     emojis += filterModelNoCustom(filter, limit);
0075     return emojis;
0076 }
0077 
0078 QVariantList EmojiModel::filterModelNoCustom(const QString &filter, bool limit)
0079 {
0080     QVariantList result;
0081 
0082     for (const auto &e : _emojis.values()) {
0083         for (const auto &variant : e) {
0084             const auto &emoji = qvariant_cast<Emoji>(variant);
0085             if (emoji.shortName.contains(filter, Qt::CaseInsensitive)) {
0086                 result.append(variant);
0087                 if (result.length() > 10 && limit) {
0088                     return result;
0089                 }
0090             }
0091         }
0092     }
0093     return result;
0094 }
0095 
0096 void EmojiModel::emojiUsed(const QVariant &modelData)
0097 {
0098     auto list = lastUsedEmojis();
0099     const auto emoji = modelData.value<Emoji>();
0100 
0101     auto it = list.begin();
0102     while (it != list.end()) {
0103         if (*it == emoji.shortName) {
0104             it = list.erase(it);
0105         } else {
0106             it++;
0107         }
0108     }
0109 
0110     list.push_front(emoji.shortName);
0111 
0112     m_configGroup.writeEntry(QStringLiteral("lastUsedEmojis"), list);
0113 
0114     Q_EMIT historyChanged();
0115 }
0116 
0117 QVariantList EmojiModel::emojis(Category category) const
0118 {
0119     if (category == History) {
0120         return emojiHistory();
0121     }
0122     if (category == HistoryNoCustom) {
0123         QVariantList list;
0124         for (const auto &e : emojiHistory()) {
0125             auto emoji = qvariant_cast<Emoji>(e);
0126             if (!emoji.isCustom) {
0127                 list.append(e);
0128             }
0129         }
0130         return list;
0131     }
0132     if (category == Custom) {
0133         return CustomEmojiModel::instance().filterModel({});
0134     }
0135     return _emojis[category];
0136 }
0137 
0138 QVariantList EmojiModel::tones(const QString &baseEmoji) const
0139 {
0140     if (baseEmoji.endsWith(QStringLiteral("tone"))) {
0141         return EmojiTones::_tones.values(baseEmoji.split(QStringLiteral(":"))[0]);
0142     }
0143     return EmojiTones::_tones.values(baseEmoji);
0144 }
0145 
0146 QHash<EmojiModel::Category, QVariantList> EmojiModel::_emojis;
0147 
0148 QVariantList EmojiModel::categories() const
0149 {
0150     return QVariantList{
0151         {QVariantMap{
0152             {QStringLiteral("category"), EmojiModel::HistoryNoCustom},
0153             {QStringLiteral("name"), i18nc("Previously used emojis", "History")},
0154             {QStringLiteral("emoji"), QStringLiteral("⌛️")},
0155         }},
0156         {QVariantMap{
0157             {QStringLiteral("category"), EmojiModel::Smileys},
0158             {QStringLiteral("name"), i18nc("'Smileys' is a category of emoji", "Smileys")},
0159             {QStringLiteral("emoji"), QStringLiteral("😏")},
0160         }},
0161         {QVariantMap{
0162             {QStringLiteral("category"), EmojiModel::People},
0163             {QStringLiteral("name"), i18nc("'People' is a category of emoji", "People")},
0164             {QStringLiteral("emoji"), QStringLiteral("🙋‍♂️")},
0165         }},
0166         {QVariantMap{
0167             {QStringLiteral("category"), EmojiModel::Nature},
0168             {QStringLiteral("name"), i18nc("'Nature' is a category of emoji", "Nature")},
0169             {QStringLiteral("emoji"), QStringLiteral("🌲")},
0170         }},
0171         {QVariantMap{
0172             {QStringLiteral("category"), EmojiModel::Food},
0173             {QStringLiteral("name"), i18nc("'Food' is a category of emoji", "Food")},
0174             {QStringLiteral("emoji"), QStringLiteral("🍛")},
0175         }},
0176         {QVariantMap{
0177             {QStringLiteral("category"), EmojiModel::Activities},
0178             {QStringLiteral("name"), i18nc("'Activities' is a category of emoji", "Activities")},
0179             {QStringLiteral("emoji"), QStringLiteral("🚁")},
0180         }},
0181         {QVariantMap{
0182             {QStringLiteral("category"), EmojiModel::Travel},
0183             {QStringLiteral("name"), i18nc("'Travel' is  a category of emoji", "Travel")},
0184             {QStringLiteral("emoji"), QStringLiteral("🚅")},
0185         }},
0186         {QVariantMap{
0187             {QStringLiteral("category"), EmojiModel::Objects},
0188             {QStringLiteral("name"), i18nc("'Objects' is a category of emoji", "Objects")},
0189             {QStringLiteral("emoji"), QStringLiteral("💡")},
0190         }},
0191         {QVariantMap{
0192             {QStringLiteral("category"), EmojiModel::Symbols},
0193             {QStringLiteral("name"), i18nc("'Symbols' is a category of emoji", "Symbols")},
0194             {QStringLiteral("emoji"), QStringLiteral("🔣")},
0195         }},
0196         {QVariantMap{
0197             {QStringLiteral("category"), EmojiModel::Flags},
0198             {QStringLiteral("name"), i18nc("'Flags' is a category of emoji", "Flags")},
0199             {QStringLiteral("emoji"), QStringLiteral("🏁")},
0200         }},
0201     };
0202 }
0203 
0204 QVariantList EmojiModel::categoriesWithCustom() const
0205 {
0206     auto cats = categories();
0207     cats.removeAt(0);
0208     cats.insert(0,
0209                 QVariantMap{
0210                     {QStringLiteral("category"), EmojiModel::History},
0211                     {QStringLiteral("name"), i18nc("Previously used emojis", "History")},
0212                     {QStringLiteral("emoji"), QStringLiteral("⌛️")},
0213                 });
0214     cats.insert(1,
0215                 QVariantMap{
0216                     {QStringLiteral("category"), EmojiModel::Custom},
0217                     {QStringLiteral("name"), i18nc("'Custom' is a category of emoji", "Custom")},
0218                     {QStringLiteral("emoji"), QStringLiteral("🖼️")},
0219                 });
0220     ;
0221     return cats;
0222 }
0223 
0224 QVariantList EmojiModel::emojiHistory() const
0225 {
0226     QVariantList list;
0227     for (const auto &historicEmoji : lastUsedEmojis()) {
0228         for (const auto &emojiCategory : _emojis) {
0229             for (const auto &emoji : emojiCategory) {
0230                 if (qvariant_cast<Emoji>(emoji).shortName == historicEmoji) {
0231                     list.append(emoji);
0232                 }
0233             }
0234         }
0235     }
0236     return list;
0237 }
0238 
0239 #include "moc_emojimodel.cpp"