File indexing completed on 2024-05-19 05:06:54

0001 /*
0002     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0003     SPDX-FileCopyrightText: 2020 Dawid Wróbel <me@dawidwrobel.com>
0004     SPDX-FileCopyrightText: 2023 Thomas Baumgart <tbaumgart@kde.org>
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "icons.h"
0009 
0010 // Qt includes
0011 
0012 #include <QHash>
0013 #include <QString>
0014 #include <QIcon>
0015 #include <QPainter>
0016 #include <QRegularExpression>
0017 #include <QDir>
0018 #include <QStandardPaths>
0019 
0020 // Project includes
0021 
0022 #include "qhashseedtype.h"
0023 
0024 inline void initIconResources()
0025 {
0026     Q_INIT_RESOURCE(kmm_icons);
0027 }
0028 
0029 namespace Icons {
0030 qHashSeedType qHash(const Icon key, qHashSeedType seed)
0031 {
0032     return ::qHash(static_cast<uint>(key), seed);
0033 }
0034 
0035 KMM_ICONS_EXPORT QIcon get(Icon icon)
0036 {
0037     static const QHash<Icon, QString> iconMappings{
0038         {Icon::AccountNew, QStringLiteral("view-financial-account-add")},
0039         {Icon::AccountEdit, QStringLiteral("view-financial-account-edit")},
0040         {Icon::AccountRemove, QStringLiteral("view-financial-account-delete")},
0041         {Icon::AccountClose, QStringLiteral("view-financial-account-close")},
0042         {Icon::AccountReopen, QStringLiteral("view-financial-account-reopen")},
0043         {Icon::AccountUpdate, QStringLiteral("edit-download")},
0044         {Icon::AccountUpdateAll, QStringLiteral("edit-download")},
0045         {Icon::ArrowDown, QStringLiteral("arrow-down")},
0046         {Icon::ArrowLeft, QStringLiteral("arrow-left")},
0047         {Icon::ArrowRight, QStringLiteral("arrow-right")},
0048         {Icon::ArrowUp, QStringLiteral("arrow-up")},
0049         {Icon::Budget, QStringLiteral("view-financial-budget")},
0050         {Icon::Budgets, QStringLiteral("financial-budget")},
0051         {Icon::Calculator, QStringLiteral("accessories-calculator")},
0052         {Icon::Configure, QStringLiteral("configure")},
0053         {Icon::DialogCancel, QStringLiteral("dialog-cancel")},
0054         {Icon::DialogClose, QStringLiteral("dialog-close")},
0055         {Icon::DialogError, QStringLiteral("dialog-error")},
0056         {Icon::DialogInformation, QStringLiteral("dialog-information")},
0057         {Icon::DialogOK, QStringLiteral("dialog-ok")},
0058         {Icon::DialogOKApply, QStringLiteral("dialog-ok-apply")},
0059         {Icon::DialogWarning, QStringLiteral("dialog-warning")},
0060         {Icon::DocumentClose, QStringLiteral("document-close")},
0061         {Icon::DocumentEdit, QStringLiteral("document-edit")},
0062         {Icon::DocumentExport, QStringLiteral("document-export")},
0063         {Icon::DocumentImport, QStringLiteral("document-import")},
0064         {Icon::DocumentNew, QStringLiteral("document-new")},
0065         {Icon::DocumentOpen, QStringLiteral("document-open")},
0066         {Icon::DocumentProperties, QStringLiteral("document-properties")},
0067         {Icon::DocumentSave, QStringLiteral("document-save")},
0068         {Icon::Download, QStringLiteral("edit-download")},
0069         {Icon::EditClear, QStringLiteral("edit-clear")},
0070         {Icon::EditCopy, QStringLiteral("edit-copy")},
0071         {Icon::EditRemove, QStringLiteral("edit-delete")},
0072         {Icon::EditShred, QStringLiteral("edit-delete-shred")},
0073         {Icon::Find, QStringLiteral("edit-find")},
0074         {Icon::EditRename, QStringLiteral("edit-rename")},
0075         {Icon::EditUndo, QStringLiteral("edit-undo")},
0076         {Icon::Folder, QStringLiteral("folder")},
0077         {Icon::GoTo, QStringLiteral("go-jump")},
0078         {Icon::Help, QStringLiteral("help-contents")},
0079         {Icon::HideCategories, QStringLiteral("hide-categories")},
0080         {Icon::HideReconciled, QStringLiteral("view-financial-transfer-unreconciled")},
0081         {Icon::ItemExchange, QStringLiteral("object-flip-vertical-symbolic")},
0082         {Icon::KMyMoney, QStringLiteral("kmymoney")},
0083         {Icon::KeyEnter, QStringLiteral("key-enter")},
0084         {Icon::Link, QStringLiteral("link")},
0085         {Icon::ListAdd, QStringLiteral("list-add")},
0086         {Icon::ListCollapse, QStringLiteral("zoom-out")},
0087         {Icon::ListExpand, QStringLiteral("zoom-in")},
0088         {Icon::TagRemove, QStringLiteral("tag-delete")},
0089         {Icon::TagRename, QStringLiteral("tag-edit")},
0090         {Icon::MailMessage, QStringLiteral("mail-message")},
0091         {Icon::MailReceive, QStringLiteral("mail-receive")},
0092         {Icon::MailSend, QStringLiteral("mail-send")},
0093         {Icon::MapOnlineAccount, QStringLiteral("network-connect")},
0094         {Icon::OnlineTransfer, QStringLiteral("document-send")},
0095         {Icon::NewSchedule, QStringLiteral("appointment-new")},
0096         {Icon::OfficeCharBar, QStringLiteral("office-chart-bar")},
0097         {Icon::OfficeChartLineForecast, QStringLiteral("office-chart-line-forecast")},
0098         {Icon::OpenDatabase, QStringLiteral("server-database")},
0099         {Icon::Pause, QStringLiteral("media-playback-pause")},
0100         {Icon::Payee, QStringLiteral("system-users")},
0101         {Icon::Community, QStringLiteral("system-users")},
0102         {Icon::PayeeNew, QStringLiteral("list-add-user")},
0103         {Icon::PayeeRemove, QStringLiteral("list-remove-user")},
0104         {Icon::PayeeMerge, QStringLiteral("merge")},
0105         {Icon::PayeeRename, QStringLiteral("user-properties")},
0106         {Icon::PerformanceTest, QStringLiteral("speedometer")},
0107         {Icon::PreferencesColors, QStringLiteral("preferences-desktop-color")},
0108         {Icon::PreferencesFonts, QStringLiteral("preferences-desktop-font")},
0109         {Icon::PreferencesGeneral, QStringLiteral("preferences-other")},
0110         {Icon::PreferencesIcons, QStringLiteral("preferences-desktop-icons")},
0111         {Icon::PreferencesNetwork, QStringLiteral("preferences-system-network")},
0112         {Icon::PreferencesPlugins, QStringLiteral("preferences-plugin")},
0113         {Icon::Reconcile, QStringLiteral("view-financial-transfer-reconcile")},
0114         {Icon::Reconciled, QStringLiteral("view-financial-transfer-reconciled")},
0115         {Icon::Refresh, QStringLiteral("view-refresh-symbolic")},
0116         {Icon::Report, QStringLiteral("office-report")},
0117         {Icon::Reverse, QStringLiteral("reverse")},
0118         {Icon::SeekForward, QStringLiteral("media-seek-forward")},
0119         {Icon::SkipForward, QStringLiteral("media-skip-forward")},
0120         {Icon::SeekBackward, QStringLiteral("media-seek-backward")},
0121         {Icon::SkipBackward, QStringLiteral("media-skip-backward")},
0122         {Icon::SortAscending, QStringLiteral("view-sort-ascending-symbolic")},
0123         {Icon::SortDescending, QStringLiteral("view-sort-descending-symbolic")},
0124         {Icon::Split, QStringLiteral("split")},
0125         {Icon::TagNew, QStringLiteral("tag-new")},
0126         {Icon::TaskAccepted, QStringLiteral("state-download")},
0127         {Icon::TaskComplete, QStringLiteral("state-ok")},
0128         {Icon::TaskOngoing, QStringLiteral("state-sync")},
0129         {Icon::TaskReject, QStringLiteral("state-error")},
0130         {Icon::TaskPending, QStringLiteral("state-information")},
0131         {Icon::Unknown, QStringLiteral("unknown")},
0132         {Icon::UnmapOnlineAccount, QStringLiteral("network-disconnect")},
0133         {Icon::UserProperties, QStringLiteral("user-properties")},
0134         {Icon::Accounts, QStringLiteral("financial-account")},
0135         {Icon::Asset, QStringLiteral("view-financial-account-asset")},
0136         {Icon::AssetClosed, QStringLiteral("view-financial-account-asset-closed")},
0137         {Icon::BankAccount, QStringLiteral("view-financial-account")},
0138         {Icon::BankAccountClosed, QStringLiteral("view-financial-account-closed")},
0139         {Icon::Calendar, QStringLiteral("view-calendar")},
0140         {Icon::CalendarDay, QStringLiteral("view-calendar-day")},
0141         {Icon::Cash, QStringLiteral("view-financial-account-cash")},
0142         {Icon::CashClosed, QStringLiteral("view-financial-account-cash-closed")},
0143         {Icon::Checking, QStringLiteral("view-financial-account-checking")},
0144         {Icon::CheckingClosed, QStringLiteral("view-financial-account-checking-closed")},
0145         {Icon::Close, QStringLiteral("view-close")},
0146         {Icon::CreditCard, QStringLiteral("view-financial-account-credit-card")},
0147         {Icon::CreditCardClosed, QStringLiteral("view-financial-account-credit-card-closed")},
0148         {Icon::Currencies, QStringLiteral("view-currency-list")},
0149         {Icon::Equity, QStringLiteral("view-financial-account")},
0150         {Icon::Expense, QStringLiteral("view-financial-category-expense")},
0151         {Icon::Filter, QStringLiteral("view-filter")},
0152         {Icon::FinancialCategories, QStringLiteral("financial-categories")},
0153         {Icon::FinancialCategoryNew, QStringLiteral("view-financial-category-add")},
0154         {Icon::FinancialCategoryEdit, QStringLiteral("view-financial-category-edit")},
0155         {Icon::FinancialCategoryRemove, QStringLiteral("view-financial-category-delete")},
0156         {Icon::Ledger, QStringLiteral("view-financial-list")},
0157         {Icon::Ledgers, QStringLiteral("financial-list")},
0158         {Icon::Transaction, QStringLiteral("view-financial-transfer")},
0159         {Icon::Forecast, QStringLiteral("financial-forecast")},
0160         {Icon::Home, QStringLiteral("home")},
0161         {Icon::Income, QStringLiteral("view-financial-category-income")},
0162         {Icon::Institution, QStringLiteral("view-institution")},
0163         {Icon::InstitutionNew, QStringLiteral("view-institution-add")},
0164         {Icon::InstitutionEdit, QStringLiteral("view-institution-edit")},
0165         {Icon::InstitutionRemove, QStringLiteral("view-institution-delete")},
0166         {Icon::Institutions, QStringLiteral("institution")},
0167         {Icon::Investment, QStringLiteral("view-financial-account-investment")},
0168         {Icon::InvestmentClosed, QStringLiteral("view-financial-account-investment-closed")},
0169         {Icon::InvestmentNew, QString()},
0170         {Icon::InvestmentEdit, QString()},
0171         {Icon::InvestmentRemove, QString()},
0172         {Icon::Investments, QStringLiteral("financial-investments")},
0173         {Icon::Liability, QStringLiteral("view-financial-account-liability")},
0174         {Icon::LiabilityClosed, QStringLiteral("view-financial-account-liability-closed")},
0175         {Icon::Loan, QStringLiteral("view-financial-account-loan")},
0176         {Icon::LoanClosed, QStringLiteral("view-financial-account-loan-closed")},
0177         {Icon::AssetLoan, QStringLiteral("view-financial-account-loan")},
0178         {Icon::AssetLoanClosed, QStringLiteral("view-financial-account-loan-closed")},
0179         {Icon::OnlineJobOutbox, QStringLiteral("internet-mail")},
0180         {Icon::OnlinePriceUpdate, QStringLiteral("view-refresh-symbolic")},
0181         {Icon::Globe, QStringLiteral("globe")},
0182         {Icon::Payees, QStringLiteral("financial-payees")},
0183         {Icon::Reports, QStringLiteral("financial-report")},
0184         {Icon::Savings, QStringLiteral("view-financial-account-savings")},
0185         {Icon::SavingsClosed, QStringLiteral("view-financial-account-savings-closed")},
0186         {Icon::Schedule, QStringLiteral("financial-schedule")},
0187         {Icon::Security, QStringLiteral("view-financial-account-investment-security")},
0188         {Icon::SecurityClosed, QStringLiteral("view-financial-account-investment-security-closed")},
0189         {Icon::Tags, QStringLiteral("tag")},
0190         {Icon::TransactionDetails, QStringLiteral("zoom-in")},
0191         {Icon::ScheduleOverdue, QStringLiteral("view-calendar-upcoming-events")},
0192         {Icon::ScheduleOnTime, QStringLiteral("view-calendar-upcoming-events")},
0193         {Icon::ZoomIn, QStringLiteral("zoom-in")},
0194         {Icon::ZoomOut, QStringLiteral("zoom-out")},
0195         {Icon::Visibility, QStringLiteral("visibility")},
0196         {Icon::NoVisibility, QStringLiteral("hint")},
0197         {Icon::Backup, QStringLiteral("backup")},
0198         {Icon::TransactionStateAny, QStringLiteral("unknown")},
0199         {Icon::TransactionStateImported, QStringLiteral("document-import")},
0200         {Icon::TransactionStateMatched, QStringLiteral("link")},
0201         {Icon::TransactionStateErroneous, QStringLiteral("dialog-warning-symbolic")},
0202         {Icon::TransactionStateScheduled, QStringLiteral("view-calendar-upcoming-days")},
0203         {Icon::TransactionStateReconciled, QStringLiteral("view-financial-transfer-reconciled")},
0204         {Icon::TransactionStateNotReconciled, QStringLiteral("view-financial-transfer-unreconciled")},
0205         {Icon::TransactionStateNotMarked, QStringLiteral("view-financial-transfer-notmarked")},
0206         {Icon::TransactionStateCleared, QStringLiteral("view-financial-transfer-cleared")},
0207         {Icon::Unlink, QStringLiteral("remove-link")},
0208         {Icon::Vault, QStringLiteral("plasmavault")},
0209     };
0210 
0211     initIconResources();
0212 
0213     return QIcon::fromTheme(iconMappings[icon]);
0214 }
0215 
0216 QString iconCacheDir()
0217 {
0218     const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0219     if (QDir::root().mkpath(cachePath)) {
0220         return cachePath;
0221     }
0222     return QString();
0223 }
0224 
0225 KMM_ICONS_EXPORT bool storeIconInApplicationCache(const QString& name, const QIcon& icon)
0226 {
0227     // split the icon name from the type
0228     QRegularExpression iconPath(QStringLiteral("^(?<type>[a-zA-Z]+):(?<name>.+)"), QRegularExpression::CaseInsensitiveOption);
0229     QRegularExpressionMatch matcher = iconPath.match(name);
0230     if (matcher.hasMatch()) {
0231         if (matcher.captured(QStringLiteral("type")).compare(QLatin1String("enum")) == 0) {
0232             return true;
0233         } else {
0234             const QString cacheDir = iconCacheDir();
0235             if (!cacheDir.isEmpty()) {
0236                 return icon.pixmap(16).save(QString::fromLatin1("%1/%2-%3").arg(cacheDir, matcher.captured(QStringLiteral("type")), matcher.captured(QStringLiteral("name"))), "PNG");
0237             }
0238         }
0239     }
0240     return false;
0241 }
0242 
0243 KMM_ICONS_EXPORT QIcon loadIconFromApplicationCache(const QString& name)
0244 {
0245     const QHash<QString, Icon> sEnumIcons {
0246         { QStringLiteral("Bank"), Icon::Institution },
0247     };
0248 
0249     // split the icon name from the type
0250     QRegularExpression iconPath(QStringLiteral("^(?<type>[a-zA-Z]+):(?<name>.+)"), QRegularExpression::CaseInsensitiveOption);
0251     QRegularExpressionMatch matcher = iconPath.match(name);
0252     if (matcher.hasMatch()) {
0253         if (matcher.captured(QStringLiteral("type")).compare(QLatin1String("enum")) == 0) {
0254             // type is enum, so we use our own set of icons
0255             const QString iconName = matcher.captured(QStringLiteral("name"));
0256             if (sEnumIcons.contains(iconName)) {
0257                 return get(sEnumIcons[iconName]);
0258             }
0259 
0260         } else {
0261             // otherwise, we use the type as part of the filename
0262             const QString cacheDir = iconCacheDir();
0263             if (!cacheDir.isEmpty()) {
0264                 const QString filename = QString::fromLatin1("%1/%2-%3").arg(cacheDir, matcher.captured(QStringLiteral("type")), matcher.captured(QStringLiteral("name")));
0265                 if (QFile::exists(filename)) {
0266                     return QIcon(filename);
0267                 }
0268             }
0269         }
0270     }
0271     return QIcon();
0272 }
0273 }