File indexing completed on 2024-05-12 05:04:18

0001 // SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
0002 // SPDX-FileCopyrightText: 2023 Joshua Goins <josh@redstrate.com>
0003 // SPDX-License-Identifier: GPL-3.0-or-later
0004 
0005 #include "emojimodel.h"
0006 
0007 #include <KLocalizedString>
0008 
0009 #include "abstractaccount.h"
0010 #include "emojitones.h"
0011 
0012 using namespace Qt::Literals::StringLiterals;
0013 
0014 QHash<EmojiModel::Category, QVariantList> EmojiModel::_emojis;
0015 
0016 EmojiModel::EmojiModel(QObject *parent)
0017     : QObject(parent)
0018 {
0019     if (_emojis.isEmpty()) {
0020 #include "emojis.h"
0021     }
0022 }
0023 
0024 QVariantList EmojiModel::filterModel(AbstractAccount *account, const QString &filter)
0025 {
0026     return filterCustomModel(account, filter) + filterModelNoCustom(filter);
0027 }
0028 
0029 QVariantList EmojiModel::emojis(AbstractAccount *account, Category category) const
0030 {
0031     if (category == History) {
0032         QVariantList list;
0033         for (const auto &historicEmoji : history(account)) {
0034             for (const auto &emojiCategory : _emojis) {
0035                 for (const auto &emoji : emojiCategory) {
0036                     if (qvariant_cast<Emoji>(emoji).shortName == historicEmoji) {
0037                         list.append(emoji);
0038                     }
0039                 }
0040             }
0041 
0042             for (const auto &customEmoji : filterCustomModel(account, {})) {
0043                 if (qvariant_cast<CustomEmoji>(customEmoji).shortcode == historicEmoji) {
0044                     list.append(customEmoji);
0045                 }
0046             }
0047         }
0048 
0049         return list;
0050     } else if (category == Custom) {
0051         return filterCustomModel(account, {});
0052     }
0053 
0054     return _emojis[category];
0055 }
0056 
0057 QVariantList EmojiModel::tones(const QString &baseEmoji) const
0058 {
0059     if (baseEmoji.endsWith("tone"_L1)) {
0060         return EmojiTones::_tones.values(baseEmoji.split(":"_L1)[0]);
0061     }
0062 
0063     return EmojiTones::_tones.values(baseEmoji);
0064 }
0065 
0066 QStringList EmojiModel::history(AbstractAccount *account) const
0067 {
0068     if (account == nullptr) {
0069         return {};
0070     }
0071 
0072     AccountConfig config(account->settingsGroupName());
0073     return config.lastUsedEmojis();
0074 }
0075 
0076 QVariantList EmojiModel::filterModelNoCustom(const QString &filter)
0077 {
0078     QVariantList result;
0079 
0080     for (const auto &e : _emojis.values()) {
0081         for (const auto &variant : e) {
0082             const auto &emoji = qvariant_cast<Emoji>(variant);
0083             if (emoji.shortName.contains(filter, Qt::CaseInsensitive)) {
0084                 result.append(variant);
0085             }
0086         }
0087     }
0088 
0089     return result;
0090 }
0091 
0092 void EmojiModel::emojiUsed(AbstractAccount *account, const QString &shortcode)
0093 {
0094     if (account == nullptr) {
0095         return;
0096     }
0097 
0098     auto list = history(account).toVector();
0099 
0100     // Remove previous instances of this emoji
0101     auto it = list.begin();
0102     while (it != list.end()) {
0103         if ((*it) == shortcode) {
0104             it = list.erase(it);
0105         } else {
0106             it++;
0107         }
0108     }
0109 
0110     list.push_front(shortcode);
0111 
0112     // sigh, QList didn't have resize until 6.0.
0113     if (list.size() > 100) {
0114         list.resize(100);
0115     }
0116 
0117     AccountConfig config(account->settingsGroupName());
0118     config.setLastUsedEmojis(list.toList());
0119     config.save();
0120 
0121     Q_EMIT historyChanged();
0122 }
0123 
0124 QVariantList EmojiModel::categories() const
0125 {
0126     return QVariantList{
0127         {QVariantMap{
0128             {QStringLiteral("category"), EmojiModel::History},
0129             {QStringLiteral("name"), i18nc("Previously used emojis", "History")},
0130             {QStringLiteral("emoji"), QStringLiteral("⌛️")},
0131         }},
0132         {QVariantMap{
0133             {QStringLiteral("category"), EmojiModel::Custom},
0134             {QStringLiteral("name"), i18nc("'Custom' is a category of emoji", "Custom")},
0135             {QStringLiteral("emoji"), QStringLiteral("🖼️")},
0136         }},
0137         {QVariantMap{
0138             {QStringLiteral("category"), EmojiModel::Smileys},
0139             {QStringLiteral("name"), i18nc("'Smileys' is a category of emoji", "Smileys")},
0140             {QStringLiteral("emoji"), QStringLiteral("😏")},
0141         }},
0142         {QVariantMap{
0143             {QStringLiteral("category"), EmojiModel::People},
0144             {QStringLiteral("name"), i18nc("'People' is a category of emoji", "People")},
0145             {QStringLiteral("emoji"), QStringLiteral("🙋‍♂️")},
0146         }},
0147         {QVariantMap{
0148             {QStringLiteral("category"), EmojiModel::Nature},
0149             {QStringLiteral("name"), i18nc("'Nature' is a category of emoji", "Nature")},
0150             {QStringLiteral("emoji"), QStringLiteral("🌲")},
0151         }},
0152         {QVariantMap{
0153             {QStringLiteral("category"), EmojiModel::Food},
0154             {QStringLiteral("name"), i18nc("'Food' is a category of emoji", "Food")},
0155             {QStringLiteral("emoji"), QStringLiteral("🍛")},
0156         }},
0157         {QVariantMap{
0158             {QStringLiteral("category"), EmojiModel::Activities},
0159             {QStringLiteral("name"), i18nc("'Activities' is a category of emoji", "Activities")},
0160             {QStringLiteral("emoji"), QStringLiteral("🚁")},
0161         }},
0162         {QVariantMap{
0163             {QStringLiteral("category"), EmojiModel::Travel},
0164             {QStringLiteral("name"), i18nc("'Travel' is  a category of emoji", "Travel")},
0165             {QStringLiteral("emoji"), QStringLiteral("🚅")},
0166         }},
0167         {QVariantMap{
0168             {QStringLiteral("category"), EmojiModel::Objects},
0169             {QStringLiteral("name"), i18nc("'Objects' is a category of emoji", "Objects")},
0170             {QStringLiteral("emoji"), QStringLiteral("💡")},
0171         }},
0172         {QVariantMap{
0173             {QStringLiteral("category"), EmojiModel::Symbols},
0174             {QStringLiteral("name"), i18nc("'Symbols' is a category of emoji", "Symbols")},
0175             {QStringLiteral("emoji"), QStringLiteral("🔣")},
0176         }},
0177         {QVariantMap{
0178             {QStringLiteral("category"), EmojiModel::Flags},
0179             {QStringLiteral("name"), i18nc("'Flags' is a category of emoji", "Flags")},
0180             {QStringLiteral("emoji"), QStringLiteral("🏁")},
0181         }},
0182     };
0183 }
0184 
0185 QVariantList EmojiModel::filterCustomModel(AbstractAccount *account, const QString &filter)
0186 {
0187     if (account == nullptr) {
0188         return {};
0189     }
0190 
0191     QVariantList result;
0192     for (const auto &emoji : account->customEmojis()) {
0193         if (emoji.shortcode.contains(filter, Qt::CaseInsensitive)) {
0194             result.append(QVariant::fromValue(emoji));
0195         }
0196     }
0197 
0198     return result;
0199 }
0200 
0201 #include "moc_emojimodel.cpp"