File indexing completed on 2024-05-12 16:25:04

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 {
0018     if (_emojis.isEmpty()) {
0019 #include "emojis.h"
0020     }
0021 }
0022 
0023 int EmojiModel::rowCount(const QModelIndex &parent) const
0024 {
0025     Q_UNUSED(parent);
0026     int total = 0;
0027     for (const auto &category : _emojis) {
0028         total += category.count();
0029     }
0030     return total;
0031 }
0032 
0033 QVariant EmojiModel::data(const QModelIndex &index, int role) const
0034 {
0035     auto row = index.row();
0036     for (const auto &category : _emojis) {
0037         if (row >= category.count()) {
0038             row -= category.count();
0039             continue;
0040         }
0041         auto emoji = category[row].value<Emoji>();
0042         switch (role) {
0043         case ShortNameRole:
0044             return QStringLiteral(":%1:").arg(emoji.shortName);
0045         case UnicodeRole:
0046         case ReplacedTextRole:
0047             return emoji.unicode;
0048         case InvalidRole:
0049             return QStringLiteral("invalid");
0050         case DisplayRole:
0051             return QStringLiteral("%2   :%1:").arg(emoji.shortName, emoji.unicode);
0052         case DescriptionRole:
0053             return emoji.description;
0054         }
0055     }
0056     return {};
0057 }
0058 
0059 QHash<int, QByteArray> EmojiModel::roleNames() const
0060 {
0061     return {{ShortNameRole, "shortName"}, {UnicodeRole, "unicode"}};
0062 }
0063 
0064 QVariantList EmojiModel::history() const
0065 {
0066     return m_settings.value("Editor/emojis", QVariantList()).toList();
0067 }
0068 
0069 QVariantList EmojiModel::filterModel(const QString &filter, bool limit)
0070 {
0071     auto emojis = CustomEmojiModel::instance().filterModel(filter);
0072     emojis += filterModelNoCustom(filter, limit);
0073     return emojis;
0074 }
0075 
0076 QVariantList EmojiModel::filterModelNoCustom(const QString &filter, bool limit)
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                 if (result.length() > 10 && limit) {
0086                     return result;
0087                 }
0088             }
0089         }
0090     }
0091     return result;
0092 }
0093 
0094 void EmojiModel::emojiUsed(const QVariant &modelData)
0095 {
0096     QVariantList list = history();
0097 
0098     auto it = list.begin();
0099     while (it != list.end()) {
0100         if ((*it).value<Emoji>().unicode == modelData.value<Emoji>().unicode) {
0101             it = list.erase(it);
0102         } else {
0103             it++;
0104         }
0105     }
0106 
0107     list.push_front(modelData);
0108     m_settings.setValue("Editor/emojis", list);
0109 
0110     Q_EMIT historyChanged();
0111 }
0112 
0113 QVariantList EmojiModel::emojis(Category category) const
0114 {
0115     if (category == History) {
0116         return history();
0117     }
0118     if (category == HistoryNoCustom) {
0119         QVariantList list;
0120         for (const auto &e : history()) {
0121             auto emoji = qvariant_cast<Emoji>(e);
0122             if (!emoji.isCustom) {
0123                 list.append(e);
0124             }
0125         }
0126         return list;
0127     }
0128     if (category == Custom) {
0129         return CustomEmojiModel::instance().filterModel({});
0130     }
0131     return _emojis[category];
0132 }
0133 
0134 QVariantList EmojiModel::tones(const QString &baseEmoji) const
0135 {
0136     if (baseEmoji.endsWith("tone")) {
0137         return EmojiTones::_tones.values(baseEmoji.split(":")[0]);
0138     }
0139     return EmojiTones::_tones.values(baseEmoji);
0140 }
0141 
0142 QHash<EmojiModel::Category, QVariantList> EmojiModel::_emojis;
0143 
0144 QVariantList EmojiModel::categories() const
0145 {
0146     return QVariantList{
0147         {QVariantMap{
0148             {"category", EmojiModel::HistoryNoCustom},
0149             {"name", i18nc("Previously used emojis", "History")},
0150             {"emoji", QStringLiteral("⌛️")},
0151         }},
0152         {QVariantMap{
0153             {"category", EmojiModel::Smileys},
0154             {"name", i18nc("'Smileys' is a category of emoji", "Smileys")},
0155             {"emoji", QStringLiteral("😏")},
0156         }},
0157         {QVariantMap{
0158             {"category", EmojiModel::People},
0159             {"name", i18nc("'People' is a category of emoji", "People")},
0160             {"emoji", QStringLiteral("🙋‍♂️")},
0161         }},
0162         {QVariantMap{
0163             {"category", EmojiModel::Nature},
0164             {"name", i18nc("'Nature' is a category of emoji", "Nature")},
0165             {"emoji", QStringLiteral("🌲")},
0166         }},
0167         {QVariantMap{
0168             {"category", EmojiModel::Food},
0169             {"name", i18nc("'Food' is a category of emoji", "Food")},
0170             {"emoji", QStringLiteral("🍛")},
0171         }},
0172         {QVariantMap{
0173             {"category", EmojiModel::Activities},
0174             {"name", i18nc("'Activities' is a category of emoji", "Activities")},
0175             {"emoji", QStringLiteral("🚁")},
0176         }},
0177         {QVariantMap{
0178             {"category", EmojiModel::Travel},
0179             {"name", i18nc("'Travel' is  a category of emoji", "Travel")},
0180             {"emoji", QStringLiteral("🚅")},
0181         }},
0182         {QVariantMap{
0183             {"category", EmojiModel::Objects},
0184             {"name", i18nc("'Objects' is a category of emoji", "Objects")},
0185             {"emoji", QStringLiteral("💡")},
0186         }},
0187         {QVariantMap{
0188             {"category", EmojiModel::Symbols},
0189             {"name", i18nc("'Symbols' is a category of emoji", "Symbols")},
0190             {"emoji", QStringLiteral("🔣")},
0191         }},
0192         {QVariantMap{
0193             {"category", EmojiModel::Flags},
0194             {"name", i18nc("'Flags' is a category of emoji", "Flags")},
0195             {"emoji", QStringLiteral("🏁")},
0196         }},
0197     };
0198 }
0199 
0200 QVariantList EmojiModel::categoriesWithCustom() const
0201 {
0202     auto cats = categories();
0203     cats.removeAt(0);
0204     cats.insert(0,
0205                 QVariantMap{
0206                     {"category", EmojiModel::History},
0207                     {"name", i18nc("Previously used emojis", "History")},
0208                     {"emoji", QStringLiteral("⌛️")},
0209                 });
0210     cats.insert(1,
0211                 QVariantMap{
0212                     {"category", EmojiModel::Custom},
0213                     {"name", i18nc("'Custom' is a category of emoji", "Custom")},
0214                     {"emoji", QStringLiteral("🖼️")},
0215                 });
0216     ;
0217     return cats;
0218 }
0219 
0220 #include "moc_emojimodel.cpp"