File indexing completed on 2024-05-12 16:42:15

0001 /*
0002     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0003     SPDX-FileCopyrightText: 2020 Dawid Wróbel <me@dawidwrobel.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "icons.h"
0008 
0009 #include <QDir>
0010 #include <QHash>
0011 #include <QIcon>
0012 #include <QPainter>
0013 #include <QPixmapCache>
0014 #include <QRegularExpression>
0015 #include <QStandardPaths>
0016 #include <QString>
0017 
0018 namespace Icons {
0019 QHash<Icon, QString> sStandardIcons;
0020 
0021 uint qHash(const Icon key, uint seed)
0022 {
0023     return ::qHash(static_cast<uint>(key), seed);
0024 }
0025 
0026 uint qHash(const IconSet key, uint seed)
0027 {
0028     return ::qHash(static_cast<uint>(key), seed);
0029 }
0030 
0031 struct iconDescription {
0032     Icon baseIcon;
0033     Icon overlayIcon;
0034     Qt::Corner corner;
0035 };
0036 
0037 const QHash<Icon, QHash<IconSet, QString>> iconMappings{
0038     {Icon::AccountClosed,
0039      {{IconSet::Common, QStringLiteral("account-types-closed")},
0040       {IconSet::Oxygen, QStringLiteral("dialog-close")},
0041       {IconSet::Breeze, QStringLiteral("view-financial-account-closed")}}},
0042     {Icon::ArrowDown, {{IconSet::Common, QStringLiteral("arrow-down")}, {IconSet::Tango, QStringLiteral("go-down")}}},
0043     {Icon::ArrowLeft, {{IconSet::Common, QStringLiteral("arrow-left")}, {IconSet::Tango, QStringLiteral("go-previous")}}},
0044     {Icon::ArrowRight, {{IconSet::Common, QStringLiteral("arrow-right")}, {IconSet::Tango, QStringLiteral("go-next")}}},
0045     {Icon::ArrowUp, {{IconSet::Common, QStringLiteral("arrow-up")}, {IconSet::Tango, QStringLiteral("go-up")}}},
0046     {Icon::Budget,
0047      {{IconSet::Common, QStringLiteral("budget")},
0048       {IconSet::Oxygen, QStringLiteral("view-time-schedule-calculus")},
0049       {IconSet::Breeze, QStringLiteral("financial-budget")}}},
0050     {Icon::Calculator, {{IconSet::Common, QStringLiteral("accessories-calculator")}}},
0051     {Icon::Configure, {{IconSet::Common, QStringLiteral("configure")}, {IconSet::Tango, QStringLiteral("preferences-system")}}},
0052     {Icon::DialogCancel, {{IconSet::Common, QStringLiteral("dialog-cancel")}, {IconSet::Tango, QStringLiteral("stop")}}},
0053     {Icon::DialogClose, {{IconSet::Common, QStringLiteral("dialog-close")}}},
0054     {Icon::DialogError, {{IconSet::Common, QStringLiteral("dialog-error")}}},
0055     {Icon::DialogInformation, {{IconSet::Common, QStringLiteral("dialog-information")}}},
0056     {Icon::DialogOK, {{IconSet::Common, QStringLiteral("dialog-ok")}, {IconSet::Tango, QStringLiteral("finish")}}},
0057     {Icon::DialogOKApply, {{IconSet::Common, QStringLiteral("dialog-ok-apply")}}},
0058     {Icon::DialogWarning, {{IconSet::Common, QStringLiteral("dialog-warning")}}},
0059     {Icon::DocumentClose, {{IconSet::Common, QStringLiteral("document-close")}, {IconSet::Tango, QStringLiteral("stop")}}},
0060     {Icon::DocumentEdit, {{IconSet::Common, QStringLiteral("document-edit")}, {IconSet::Tango, QStringLiteral("text-editor")}}},
0061     {Icon::DocumentExport,
0062      {{IconSet::Common, QStringLiteral("format-indent-more")},
0063       {IconSet::Oxygen, QStringLiteral("document-export")},
0064       {IconSet::Breeze, QStringLiteral("document-export")}}},
0065     {Icon::DocumentImport,
0066      {{IconSet::Common, QStringLiteral("format-indent-less")},
0067       {IconSet::Oxygen, QStringLiteral("document-import")},
0068       {IconSet::Breeze, QStringLiteral("document-import")}}},
0069     {Icon::DocumentNew, {{IconSet::Common, QStringLiteral("document-new")}}},
0070     {Icon::DocumentOpen, {{IconSet::Common, QStringLiteral("document-open")}}},
0071     {Icon::DocumentProperties, {{IconSet::Common, QStringLiteral("document-properties")}}},
0072     {Icon::DocumentSave, {{IconSet::Common, QStringLiteral("document-save")}}},
0073     {Icon::Download,
0074      {{IconSet::Breeze, QStringLiteral("edit-download")}, {IconSet::Common, QStringLiteral("go-down")}, {IconSet::Oxygen, QStringLiteral("download")}}},
0075     {Icon::EditClear, {{IconSet::Common, QStringLiteral("edit-clear")}}},
0076     {Icon::EditCopy, {{IconSet::Common, QStringLiteral("edit-copy")}}},
0077     {Icon::EditDelete, {{IconSet::Common, QStringLiteral("edit-delete")}}},
0078     {Icon::Find, {{IconSet::Common, QStringLiteral("edit-find")}}},
0079     {Icon::EditRename, {{IconSet::Common, QStringLiteral("edit-rename")}, {IconSet::Tango, QStringLiteral("text-editor")}}},
0080     {Icon::EditUndo, {{IconSet::Common, QStringLiteral("edit-undo")}}},
0081     {Icon::Folder, {{IconSet::Common, QStringLiteral("folder")}}},
0082     {Icon::GoTo, {{IconSet::Common, QStringLiteral("go-jump")}}},
0083     {Icon::Help, {{IconSet::Common, QStringLiteral("help-contents")}}},
0084     {Icon::HideCategories, {{IconSet::Common, QStringLiteral("hide-categories")}}},
0085     {Icon::HideReconciled, {{IconSet::Common, QStringLiteral("hide-reconciled")}}},
0086     {Icon::ShowReconciledBalances, {{IconSet::Breeze, QStringLiteral("gnumeric-autosum")}}},
0087     {Icon::KMyMoney, {{IconSet::Common, QStringLiteral("kmymoney")}}},
0088     {Icon::KeyEnter,
0089      {{IconSet::Common, QStringLiteral("input-keyboard")}, {IconSet::Oxygen, QStringLiteral("key-enter")}, {IconSet::Breeze, QStringLiteral("key-enter")}}},
0090     {Icon::ListAdd, {{IconSet::Common, QStringLiteral("list-add")}}},
0091     {Icon::ListAddTag, {{IconSet::Common, QStringLiteral("list-add-tag")}}},
0092     {Icon::ListAddUser, {{IconSet::Common, QStringLiteral("list-add-user")}}},
0093     {Icon::ListCollapse, {{IconSet::Common, QStringLiteral("zoom-out")}, {IconSet::Tango, QStringLiteral("list-remove")}}},
0094     {Icon::ListExpand, {{IconSet::Common, QStringLiteral("zoom-in")}, {IconSet::Tango, QStringLiteral("list-add")}}},
0095     {Icon::ListRemoveTag, {{IconSet::Common, QStringLiteral("list-remove-tag")}}},
0096     {Icon::ListRemoveUser, {{IconSet::Common, QStringLiteral("list-remove-user")}}},
0097     {Icon::MailMessage,
0098      {{IconSet::Common, QStringLiteral("internet-mail")},
0099       {IconSet::Oxygen, QStringLiteral("mail-message")},
0100       {IconSet::Breeze, QStringLiteral("mail-message")}}},
0101     {Icon::MailMessageNew, {{IconSet::Common, QStringLiteral("mail-message-new")}}},
0102     {Icon::MailReceive, {{IconSet::Common, QStringLiteral("mail-receive")}}},
0103     {Icon::MapOnlineAccount, {{IconSet::Common, QStringLiteral("news-subscribe")}}},
0104     {Icon::Merge, {{IconSet::Common, QStringLiteral("reconcile")}, {IconSet::Oxygen, QStringLiteral("merge")}, {IconSet::Breeze, QStringLiteral("merge")}}},
0105     {Icon::NewSchedule, {{IconSet::Common, QStringLiteral("appointment-new")}}},
0106     {Icon::OfficeChartLine,
0107      {{IconSet::Common, QStringLiteral("account-types-investments")},
0108       {IconSet::Oxygen, QStringLiteral("office-chart-line")},
0109       {IconSet::Breeze, QStringLiteral("office-chart-line")},
0110       {IconSet::Tango, QStringLiteral("report-line")}}},
0111     {Icon::OpenDatabase, {{IconSet::Common, QStringLiteral("server-database")}}},
0112     {Icon::Pause, {{IconSet::Common, QStringLiteral("media-playback-pause")}}},
0113     {Icon::PayeeMerge, {{IconSet::Common, QStringLiteral("merge")}}},
0114     {Icon::PayeeRename, {{IconSet::Common, QStringLiteral("user-properties")}, {IconSet::Oxygen, QStringLiteral("payee-rename")}}},
0115     {Icon::PerformanceTest, {{IconSet::Common, QStringLiteral("fork")}, {IconSet::Breeze, QStringLiteral("speedometer")}}},
0116     {Icon::PreferencesColors, {{IconSet::Common, QStringLiteral("preferences-desktop-color")}}},
0117     {Icon::PreferencesFonts, {{IconSet::Common, QStringLiteral("preferences-desktop-font")}}},
0118     {Icon::PreferencesGeneral, {{IconSet::Common, QStringLiteral("system-run")}, {IconSet::Tango, QStringLiteral("media-playback-start")}}},
0119     {Icon::PreferencesIcons, {{IconSet::Common, QStringLiteral("preferences-desktop-icon")}}},
0120     {Icon::PreferencesNetwork, {{IconSet::Common, QStringLiteral("preferences-system-network")}}},
0121     {Icon::PreferencesPlugins, {{IconSet::Common, QStringLiteral("network-disconnect")}}},
0122     {Icon::Reconcile, {{IconSet::Common, QStringLiteral("reconcile")}, {IconSet::Oxygen, QStringLiteral("merge")}, {IconSet::Breeze, QStringLiteral("merge")}}},
0123     {Icon::Reconciled,
0124      {{IconSet::Common, QStringLiteral("reconciled")}, {IconSet::Oxygen, QStringLiteral("flag-green")}, {IconSet::Breeze, QStringLiteral("flag-green")}}},
0125     {Icon::Refresh, {{IconSet::Breeze, QStringLiteral("view-refresh")}, {IconSet::Oxygen, QStringLiteral("refresh")}}},
0126     {Icon::Report, {{IconSet::Common, QStringLiteral("application-vnd.oasis.opendocument.spreadsheet")}}},
0127     {Icon::Reverse, {{IconSet::Common, QStringLiteral("reverse")}}},
0128     {Icon::SeekForward, {{IconSet::Common, QStringLiteral("media-seek-forward")}}},
0129     {Icon::SkipForward, {{IconSet::Common, QStringLiteral("media-skip-forward")}}},
0130     {Icon::SortAscending,
0131      {{IconSet::Common, QStringLiteral("go-up")},
0132       {IconSet::Oxygen, QStringLiteral("view-sort-ascending")},
0133       {IconSet::Breeze, QStringLiteral("view-sort-ascending")}}},
0134     {Icon::SortDescending,
0135      {{IconSet::Common, QStringLiteral("go-down")},
0136       {IconSet::Oxygen, QStringLiteral("view-sort-descending")},
0137       {IconSet::Breeze, QStringLiteral("view-sort-descending")}}},
0138     {Icon::Split,
0139      {{IconSet::Common, QStringLiteral("transaction-split")}, {IconSet::Oxygen, QStringLiteral("split")}, {IconSet::Breeze, QStringLiteral("split")}}},
0140     {Icon::TagRename, {{IconSet::Common, QStringLiteral("tag-rename")}}},
0141     {Icon::TaskAccepted, {{IconSet::Common, QStringLiteral("task-accepted")}}},
0142     {Icon::TaskComplete, {{IconSet::Common, QStringLiteral("task-complete")}}},
0143     {Icon::TaskOngoing, {{IconSet::Common, QStringLiteral("task-ongoing")}}},
0144     {Icon::TaskReject, {{IconSet::Common, QStringLiteral("task-reject")}}},
0145     {Icon::Warning, {{IconSet::Common, QStringLiteral("dialog-warning")}}},
0146     {Icon::Tip, {{IconSet::Common, QStringLiteral("info")}, {IconSet::Oxygen, QStringLiteral("ktip")}}},
0147     {Icon::Unknown, {{IconSet::Common, QStringLiteral("unknown")}}},
0148     {Icon::UnmapOnlineAccount, {{IconSet::Common, QStringLiteral("news-unsubscribe")}}},
0149     {Icon::UserProperties,
0150      {{IconSet::Common, QStringLiteral("system-users")},
0151       {IconSet::Oxygen, QStringLiteral("user-properties")},
0152       {IconSet::Breeze, QStringLiteral("user-properties")}}},
0153     {Icon::Accounts,
0154      {{IconSet::Common, QStringLiteral("account")},
0155       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0156       {IconSet::Breeze, QStringLiteral("financial-account")}}},
0157     {Icon::Asset,
0158      {{IconSet::Common, QStringLiteral("account-types-asset")},
0159       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0160       {IconSet::Breeze, QStringLiteral("view-financial-account-asset")}}},
0161     {Icon::Bank,
0162      {{IconSet::Common, QStringLiteral("bank")}, {IconSet::Oxygen, QStringLiteral("view-bank")}, {IconSet::Breeze, QStringLiteral("view-institution")}}},
0163     {Icon::BankAccount,
0164      {{IconSet::Common, QStringLiteral("account")},
0165       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0166       {IconSet::Breeze, QStringLiteral("view-financial-account")}}},
0167     {Icon::AccountNew,
0168      {{IconSet::Common, QStringLiteral("account")},
0169       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0170       {IconSet::Breeze, QStringLiteral("view-financial-account-add")}}},
0171     {Icon::AccountEdit,
0172      {{IconSet::Common, QStringLiteral("account")},
0173       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0174       {IconSet::Breeze, QStringLiteral("view-financial-account-edit")}}},
0175     {Icon::AccountDelete,
0176      {{IconSet::Common, QStringLiteral("account")},
0177       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0178       {IconSet::Breeze, QStringLiteral("view-financial-account-delete")}}},
0179     {Icon::AccountClose, {{IconSet::Breeze, QStringLiteral("view-financial-account-close")}}},
0180     {Icon::AccountReopen, {{IconSet::Breeze, QStringLiteral("view-financial-account-reopen")}}},
0181     {Icon::AccountUpdate, {{IconSet::Breeze, QStringLiteral("edit-download")}}},
0182     {Icon::AccountUpdateAll, {{IconSet::Breeze, QStringLiteral("edit-download")}}},
0183     {Icon::PriceUpdate, {{IconSet::Common, QStringLiteral("view-refresh-symbolic")}}},
0184     {Icon::Calendar, {{IconSet::Common, QStringLiteral("view-calendar")}}},
0185     {Icon::CalendarDay,
0186      {{IconSet::Common, QStringLiteral("office-calendar")},
0187       {IconSet::Oxygen, QStringLiteral("view-calendar-day")},
0188       {IconSet::Breeze, QStringLiteral("view-calendar-day")}}},
0189     {Icon::Cash, {{IconSet::Common, QStringLiteral("account-types-cash")}, {IconSet::Breeze, QStringLiteral("view-financial-account-cash")}}},
0190     {Icon::Checking,
0191      {{IconSet::Common, QStringLiteral("account-types-checking")},
0192       {IconSet::Oxygen, QStringLiteral("view-bank-account-checking")},
0193       {IconSet::Breeze, QStringLiteral("view-financial-account-checking")}}},
0194     {Icon::Close, {{IconSet::Common, QStringLiteral("view-close")}}},
0195     {Icon::CreditCard,
0196      {{IconSet::Breeze, QStringLiteral("view-financial-account-credit-card")},
0197       {IconSet::Common, QStringLiteral("account-types-credit-card")},
0198       {IconSet::Oxygen, QStringLiteral("view-financial-account-credit-card")}}},
0199     {Icon::Currencies, {{IconSet::Common, QStringLiteral("view-currency-list")}}},
0200     {Icon::Equity,
0201      {{IconSet::Common, QStringLiteral("account")},
0202       {IconSet::Oxygen, QStringLiteral("view-bank-account")},
0203       {IconSet::Breeze, QStringLiteral("view-financial-account")}}},
0204     {Icon::Expense,
0205      {{IconSet::Breeze, QStringLiteral("view-financial-category-expense")},
0206       {IconSet::Common, QStringLiteral("account-types-expense")},
0207       {IconSet::Oxygen, QStringLiteral("view-expenses-categories")}}},
0208     {Icon::Filter, {{IconSet::Common, QStringLiteral("view-filter")}}},
0209     {Icon::FinancialCategories,
0210      {{IconSet::Common, QStringLiteral("categories")},
0211       {IconSet::Oxygen, QStringLiteral("view-categories")},
0212       {IconSet::Breeze, QStringLiteral("financial-categories")}}},
0213     {Icon::CategoryNew,
0214      {{IconSet::Common, QStringLiteral("categories")},
0215       {IconSet::Oxygen, QStringLiteral("view-categories")},
0216       {IconSet::Breeze, QStringLiteral("financial-category-add")}}},
0217     {Icon::CategoryEdit,
0218      {{IconSet::Common, QStringLiteral("categories")},
0219       {IconSet::Oxygen, QStringLiteral("view-categories")},
0220       {IconSet::Breeze, QStringLiteral("financial-category-edit")}}},
0221     {Icon::CategoryDelete,
0222      {{IconSet::Common, QStringLiteral("categories")},
0223       {IconSet::Oxygen, QStringLiteral("view-categories")},
0224       {IconSet::Breeze, QStringLiteral("financial-category-delete")}}},
0225     {Icon::Ledger,
0226      {{IconSet::Common, QStringLiteral("ledger")},
0227       {IconSet::Oxygen, QStringLiteral("view-financial-list")},
0228       {IconSet::Breeze, QStringLiteral("financial-list")}}},
0229     {Icon::Transaction,
0230      {{IconSet::Common, QStringLiteral("ledger")},
0231       {IconSet::Oxygen, QStringLiteral("view-financial-transfer")},
0232       {IconSet::Breeze, QStringLiteral("view-financial-transfer")}}},
0233     {Icon::Forecast,
0234      {{IconSet::Common, QStringLiteral("forecast")},
0235       {IconSet::Oxygen, QStringLiteral("view-financial-forecast")},
0236       {IconSet::Breeze, QStringLiteral("financial-forecast")}}},
0237     {Icon::Home, {{IconSet::Common, QStringLiteral("home")}, {IconSet::Oxygen, QStringLiteral("go-home")}, {IconSet::Breeze, QStringLiteral("home")}}},
0238     {Icon::Income,
0239      {{IconSet::Breeze, QStringLiteral("view-financial-category-income")},
0240       {IconSet::Common, QStringLiteral("account-types-income")},
0241       {IconSet::Oxygen, QStringLiteral("view-income-categories")}}},
0242     {Icon::Institution,
0243      {{IconSet::Common, QStringLiteral("institution")}, {IconSet::Oxygen, QStringLiteral("view-bank")}, {IconSet::Breeze, QStringLiteral("view-institution")}}},
0244     {Icon::InstitutionNew,
0245      {{IconSet::Common, QStringLiteral("institution")},
0246       {IconSet::Oxygen, QStringLiteral("view-bank")},
0247       {IconSet::Breeze, QStringLiteral("view-institution-add")}}},
0248     {Icon::InstitutionEdit,
0249      {{IconSet::Common, QStringLiteral("institution")},
0250       {IconSet::Oxygen, QStringLiteral("view-bank")},
0251       {IconSet::Breeze, QStringLiteral("view-institution-edit")}}},
0252     {Icon::InstitutionDelete,
0253      {{IconSet::Common, QStringLiteral("institution")},
0254       {IconSet::Oxygen, QStringLiteral("view-bank")},
0255       {IconSet::Breeze, QStringLiteral("view-institution-delete")}}},
0256     {Icon::Institutions,
0257      {{IconSet::Common, QStringLiteral("institution")}, {IconSet::Oxygen, QStringLiteral("view-bank")}, {IconSet::Breeze, QStringLiteral("institution")}}},
0258     {Icon::Investment,
0259      {{IconSet::Common, QStringLiteral("investment")},
0260       {IconSet::Oxygen, QStringLiteral("view-investment")},
0261       {IconSet::Breeze, QStringLiteral("view-financial-account-investment")}}},
0262     {Icon::Investments,
0263      {{IconSet::Common, QStringLiteral("investment")},
0264       {IconSet::Oxygen, QStringLiteral("view-investment")},
0265       {IconSet::Breeze, QStringLiteral("financial-investments")}}},
0266     {Icon::Liability,
0267      {{IconSet::Common, QStringLiteral("account-types-liability")},
0268       {IconSet::Oxygen, QStringLiteral("view-loan")},
0269       {IconSet::Breeze, QStringLiteral("view-financial-account-liability")}}},
0270     {Icon::Loan,
0271      {{IconSet::Common, QStringLiteral("account-types-loan")},
0272       {IconSet::Oxygen, QStringLiteral("view-loan")},
0273       {IconSet::Breeze, QStringLiteral("view-financial-account-loan")}}},
0274     {Icon::LoanAsset,
0275      {{IconSet::Common, QStringLiteral("account-types-loan")},
0276       {IconSet::Oxygen, QStringLiteral("view-loan-asset")},
0277       {IconSet::Breeze, QStringLiteral("view-financial-account-loan")}}},
0278     {Icon::OnlineJobOutbox, {{IconSet::Common, QStringLiteral("online-banking")}, {IconSet::Breeze, QStringLiteral("internet-mail")}}},
0279     {Icon::Payees,
0280      {{IconSet::Common, QStringLiteral("payee")}, {IconSet::Oxygen, QStringLiteral("system-users")}, {IconSet::Breeze, QStringLiteral("financial-payees")}}},
0281     {Icon::Reports,
0282      {{IconSet::Common, QStringLiteral("report")},
0283       {IconSet::Oxygen, QStringLiteral("office-chart-bar")},
0284       {IconSet::Breeze, QStringLiteral("financial-report")}}},
0285     {Icon::Savings,
0286      {{IconSet::Common, QStringLiteral("account-types-savings")},
0287       {IconSet::Oxygen, QStringLiteral("view-bank-account-savings")},
0288       {IconSet::Breeze, QStringLiteral("view-financial-account-savings")}}},
0289     {Icon::Schedule,
0290      {{IconSet::Common, QStringLiteral("schedule")},
0291       {IconSet::Oxygen, QStringLiteral("view-pim-calendar")},
0292       {IconSet::Breeze, QStringLiteral("financial-schedule")}}},
0293     {Icon::Stock,
0294      {{IconSet::Common, QStringLiteral("account-types-investments")},
0295       {IconSet::Oxygen, QStringLiteral("view-stock-account")},
0296       {IconSet::Breeze, QStringLiteral("view-financial-account-investment-security")}}},
0297     {Icon::Tags,
0298      {{IconSet::Common, QStringLiteral("bookmark-new")}, {IconSet::Oxygen, QStringLiteral("mail-tagged")}, {IconSet::Breeze, QStringLiteral("tag")}}},
0299     {Icon::TransactionDetails,
0300      {{IconSet::Common, QStringLiteral("edit-find")}, {IconSet::Oxygen, QStringLiteral("zoom-in")}, {IconSet::Breeze, QStringLiteral("zoom-in")}}},
0301     {Icon::UpcomingEvents, {{IconSet::Common, QStringLiteral("view-calendar-upcoming-events")}}},
0302     {Icon::ZoomIn, {{IconSet::Common, QStringLiteral("zoom-in")}}},
0303     {Icon::ZoomOut, {{IconSet::Common, QStringLiteral("zoom-out")}}},
0304     {Icon::Visibility, {{IconSet::Common, QStringLiteral("visibility")}}},
0305     {Icon::NoVisibility, {{IconSet::Common, QStringLiteral("hint")}}},
0306     {Icon::SelectAll, {{IconSet::Common, QStringLiteral("edit-select-all")}}}};
0307 
0308 const QHash<Icon, iconDescription> sComposedIcons{
0309 
0310     {Icon::AccountFinishReconciliation, {Icon::Merge, Icon::DialogOK, Qt::BottomRightCorner}},
0311     {Icon::AccountCreditTransfer, {Icon::BankAccount, Icon::MailMessageNew, Qt::BottomRightCorner}},
0312     {Icon::TransactionMatch, {Icon::Transaction, Icon::DocumentImport, Qt::BottomRightCorner}},
0313     {Icon::TransactionAccept, {Icon::Transaction, Icon::DialogOKApply, Qt::BottomRightCorner}},
0314     {Icon::InvestmentNew, {Icon::Investment, Icon::ListAdd, Qt::TopRightCorner}},
0315     {Icon::InvestmentEdit, {Icon::Investment, Icon::DocumentEdit, Qt::BottomRightCorner}},
0316     {Icon::InvestmentDelete, {Icon::Investment, Icon::EditDelete, Qt::BottomRightCorner}},
0317     {Icon::InvestmentOnlinePrice, {Icon::Investment, Icon::Download, Qt::BottomRightCorner}},
0318     {Icon::InvestmentOnlinePriceAll, {Icon::Investment, Icon::Download, Qt::BottomRightCorner}},
0319     {Icon::BudgetNew, {Icon::Budget, Icon::ListAdd, Qt::TopRightCorner}},
0320     {Icon::BudgetRename, {Icon::Budget, Icon::DocumentEdit, Qt::BottomRightCorner}},
0321     {Icon::BudgetDelete, {Icon::Budget, Icon::EditDelete, Qt::BottomRightCorner}},
0322     {Icon::BudgetCopy, {Icon::Budget, Icon::EditCopy, Qt::BottomRightCorner}}};
0323 
0324 KMM_ICONS_EXPORT void setUpMappings(const QString& themeName)
0325 {
0326     IconSet themeIconSet;
0327 
0328     if (themeName.contains(QStringLiteral("oxygen"), Qt::CaseInsensitive))
0329         themeIconSet = IconSet::Oxygen;
0330     else if (themeName.contains(QStringLiteral("tango"), Qt::CaseInsensitive))
0331         themeIconSet = IconSet::Tango;
0332     // default to breeze mappings
0333     else
0334         themeIconSet = IconSet::Breeze;
0335 
0336     for (auto iconDef = iconMappings.cbegin(); iconDef != iconMappings.cend(); ++iconDef) {
0337         const auto icon = iconDef.key();
0338         auto name = iconDef.value().value(themeIconSet);
0339 
0340         // get common mapping if theme-specific does not exist
0341         if (name.isEmpty())
0342             name = iconDef.value().value(IconSet::Common);
0343 
0344         sStandardIcons.insert(icon, name);
0345     }
0346 }
0347 
0348 /**
0349  * This method overlays an icon over another one, to get a composite one
0350  * eg. an icon to add accounts
0351  */
0352 QIcon overlayIcon(iconDescription description, const int size = 64)
0353 {
0354     const auto iconName = sStandardIcons[description.baseIcon];
0355     const auto overlayName = sStandardIcons[description.overlayIcon];
0356     const auto corner = description.corner;
0357 
0358     QPixmap pxIcon;
0359     QString kyIcon = iconName + overlayName;
0360 
0361     // If found in the cache, return quickly
0362     if (QPixmapCache::find(kyIcon, pxIcon))
0363         return pxIcon;
0364 
0365     // try to retrieve the main icon from cache
0366     if (!QPixmapCache::find(iconName, pxIcon)) {
0367         pxIcon = QIcon::fromTheme(iconName).pixmap(size);
0368         QPixmapCache::insert(iconName, pxIcon);
0369     }
0370 
0371     if (overlayName.isEmpty()) // call from MyMoneyAccount::accountPixmap can have no overlay icon, so handle that appropriately
0372         return pxIcon;
0373 
0374     QPainter pixmapPainter(&pxIcon);
0375     QPixmap pxOverlay = QIcon::fromTheme(overlayName).pixmap(size);
0376 
0377     int x, y;
0378     switch (corner) {
0379     case Qt::TopLeftCorner:
0380         x = 0;
0381         y = 0;
0382         break;
0383     case Qt::TopRightCorner:
0384         x = pxIcon.width() / 2;
0385         y = 0;
0386         break;
0387     case Qt::BottomLeftCorner:
0388         x = 0;
0389         y = pxIcon.height() / 2;
0390         break;
0391     case Qt::BottomRightCorner:
0392     default:
0393         x = pxIcon.width() / 2;
0394         y = pxIcon.height() / 2;
0395         break;
0396     }
0397     pixmapPainter.drawPixmap(x, y, pxIcon.width() / 2, pxIcon.height() / 2, pxOverlay);
0398 
0399     // save for later use
0400     QPixmapCache::insert(kyIcon, pxIcon);
0401 
0402     return pxIcon;
0403 }
0404 
0405 KMM_ICONS_EXPORT QIcon get(Icon icon)
0406 {
0407     if (sComposedIcons.contains(icon))
0408         return overlayIcon(sComposedIcons[icon]);
0409 
0410     auto name = sStandardIcons[icon];
0411     auto iconpix = QIcon::fromTheme(sStandardIcons[icon]);
0412     return iconpix;
0413 }
0414 
0415 QString iconCacheDir()
0416 {
0417     const QString cachePath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
0418     if (QDir::root().mkpath(cachePath)) {
0419         return cachePath;
0420     }
0421     return QString();
0422 }
0423 
0424 KMM_ICONS_EXPORT bool storeIconInApplicationCache(const QString& name, const QIcon& icon)
0425 {
0426     // split the icon name from the type
0427     QRegularExpression iconPath(QStringLiteral("^(?<type>[a-zA-Z]+):(?<name>.+)"), QRegularExpression::CaseInsensitiveOption);
0428     QRegularExpressionMatch matcher = iconPath.match(name);
0429     if (matcher.hasMatch()) {
0430         if (matcher.captured(QStringLiteral("type")).compare(QLatin1String("enum")) == 0) {
0431             return true;
0432         } else {
0433             const QString cacheDir = iconCacheDir();
0434             if (!cacheDir.isEmpty()) {
0435                 return icon.pixmap(16).save(
0436                     QString::fromLatin1("%1/%2-%3").arg(cacheDir, matcher.captured(QStringLiteral("type")), matcher.captured(QStringLiteral("name"))),
0437                     "PNG");
0438             }
0439         }
0440     }
0441     return false;
0442 }
0443 
0444 KMM_ICONS_EXPORT QIcon loadIconFromApplicationCache(const QString& name)
0445 {
0446     const QHash<QString, Icon> sEnumIcons{
0447         {QStringLiteral("Bank"), Icon::Bank},
0448     };
0449 
0450     // split the icon name from the type
0451     QRegularExpression iconPath(QStringLiteral("^(?<type>[a-zA-Z]+):(?<name>.+)"), QRegularExpression::CaseInsensitiveOption);
0452     QRegularExpressionMatch matcher = iconPath.match(name);
0453     if (matcher.hasMatch()) {
0454         if (matcher.captured(QStringLiteral("type")).compare(QLatin1String("enum")) == 0) {
0455             // type is enum, so we use our own set of icons
0456             const QString iconName = matcher.captured(QStringLiteral("name"));
0457             if (sEnumIcons.contains(iconName)) {
0458                 return get(sEnumIcons[iconName]);
0459             }
0460 
0461         } else {
0462             // otherwise, we use the type as part of the filename
0463             const QString cacheDir = iconCacheDir();
0464             if (!cacheDir.isEmpty()) {
0465                 const QString filename =
0466                     QString::fromLatin1("%1/%2-%3").arg(cacheDir, matcher.captured(QStringLiteral("type")), matcher.captured(QStringLiteral("name")));
0467                 if (QFile::exists(filename)) {
0468                     return QIcon(filename);
0469                 }
0470             }
0471         }
0472     }
0473     return QIcon();
0474 }
0475 }