File indexing completed on 2024-05-12 16:02:27

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_icon_utils.h"
0008 
0009 #include <QApplication>
0010 #include <QAction>
0011 #include <QAbstractButton>
0012 #include <QComboBox>
0013 #include <QTabBar>
0014 #include <QTabWidget>
0015 #include <QIcon>
0016 #include <QFile>
0017 #include <QPair>
0018 #include <QDebug>
0019 
0020 #include <KoIcon.h>
0021 #include "kis_debug.h"
0022 
0023 namespace KisIconUtils
0024 {
0025 
0026 static QMap<QString, QIcon> s_cache;
0027 static QMap<qint64, QString> s_icons;
0028 
0029 QIcon loadIcon(const QString &name)
0030 {
0031     QMap<QString, QIcon>::const_iterator cached = s_cache.constFind(name);
0032     if (cached != s_cache.constEnd()) {
0033         return cached.value();
0034     }
0035 
0036     // try load themed icon
0037     const char * const prefix = useDarkIcons() ? "dark_" : "light_";
0038 
0039     QString  realName = QLatin1String(prefix) + name;
0040 
0041     // Dark and light, no size specified
0042     const QStringList names = { ":/pics/" + realName + ".png",
0043                                 ":/pics/" + realName + ".svg",
0044                                 ":/pics/" + realName + ".svgz",
0045                                 ":/pics/" + name + ".png",
0046                                 ":/pics/" + name + ".svg",
0047                                 ":/pics/" + name + ".svgz",
0048                                 ":/" + realName + ".png",
0049                                 ":/" + realName + ".svg",
0050                                 ":/" + realName + ".svgz",
0051                                 ":/" + name,
0052                                 ":/" + name + ".png",
0053                                 ":/" + name + ".svg",
0054                                 ":/" + name + ".svgz"};
0055 
0056     for (const QString &resname : names) {
0057         if (QFile(resname).exists()) {
0058             QIcon icon(resname);
0059             s_icons.insert(icon.cacheKey(), name);
0060             s_cache.insert(name, icon);
0061             return icon;
0062         }
0063     }
0064 
0065     // Now check for icons with sizes
0066     QStringList sizes = QStringList() << "16_" << "22_" << "32_" << "48_" << "64_" << "128_" << "256_" << "512_" << "1024_";
0067     QVector<QPair<QString, QString> > icons;
0068     Q_FOREACH (const QString &size, sizes) {
0069         const QStringList names = { ":/pics/" + size + realName + ".png",
0070                                     ":/pics/" + size + realName + ".svg",
0071                                     ":/pics/" + size + realName + ".svgz",
0072                                     ":/pics/" + size + name + ".png",
0073                                     ":/pics/" + size + name + ".svg",
0074                                     ":/pics/" + size + name + ".svgz",
0075                                     ":/" + size + realName + ".png",
0076                                     ":/" + size + realName + ".svg",
0077                                     ":/" + size + realName + ".svgz",
0078                                     ":/" + size + name,
0079                                     ":/" + size + name + ".png",
0080                                     ":/" + size + name + ".svg",
0081                                     ":/" + size + name + ".svgz"};
0082 
0083         for (const QString &resname : names) {
0084             if (QFile(resname).exists()) {
0085                 icons << qMakePair(size, resname);
0086             }
0087         }
0088     }
0089 
0090     if (!icons.isEmpty()) {
0091         QIcon icon;
0092         Q_FOREACH (auto p, icons) {
0093             QString sz = p.first;
0094             sz.chop(1);
0095             int size = sz.toInt();
0096             icon.addFile(p.second, QSize(size, size));
0097         }
0098         s_icons.insert(icon.cacheKey(), name);
0099         s_cache.insert(name, icon);
0100         return icon;
0101     }
0102 
0103     QIcon icon = QIcon::fromTheme(name);
0104     //qDebug() << "falling back on QIcon::FromTheme:" << name;
0105     s_icons.insert(icon.cacheKey(), name);
0106     s_cache.insert(name, icon);
0107     return icon;
0108 }
0109 
0110 
0111 
0112 
0113 bool useDarkIcons() {
0114     QColor background = qApp->palette().window().color();
0115     return  background.value() > 100;
0116 }
0117 
0118 bool adjustIcon(QIcon *icon)
0119 {
0120     bool result = false;
0121 
0122     QString iconName = icon->name();
0123     if (iconName.isNull()) {
0124         if (s_icons.contains(icon->cacheKey())) {
0125             iconName = s_icons[icon->cacheKey()];
0126         } else {
0127             return false;
0128         }
0129     }
0130 
0131     QString realIconName = iconName;
0132 
0133     if (iconName.startsWith("dark_")) {
0134         realIconName = iconName.mid(5);
0135     }
0136 
0137     if (iconName.startsWith("light_")) {
0138         realIconName = iconName.mid(6);
0139     }
0140 
0141     if (!realIconName.isNull()) {
0142         *icon = loadIcon(realIconName);
0143         result = !icon->isNull();
0144         s_icons.insert(icon->cacheKey(), iconName);
0145     }
0146 
0147     return result;
0148 }
0149 
0150 void updateIconCommon(QObject *object)
0151 {
0152     QAbstractButton* button = qobject_cast<QAbstractButton*>(object);
0153     if (button) {
0154         updateIcon(button);
0155         return;
0156     }
0157 
0158     QComboBox* comboBox = qobject_cast<QComboBox*>(object);
0159     if (comboBox) {
0160         updateIcon(comboBox);
0161         return;
0162     }
0163 
0164     QAction* action = qobject_cast<QAction*>(object);
0165     if (action) {
0166         updateIcon(action);
0167         return;
0168     }
0169 
0170     QTabBar* tabBar = qobject_cast<QTabBar*>(object);
0171     if (tabBar) {
0172         updateIcon(tabBar);
0173         return;
0174     }
0175 }
0176 
0177 void clearIconCache() {
0178     s_cache.clear();
0179 }
0180 
0181 void updateIcon(QAbstractButton *button)
0182 {
0183     KIS_SAFE_ASSERT_RECOVER_RETURN(button);
0184 
0185     QIcon icon = button->icon();
0186 
0187     if (adjustIcon(&icon)) {
0188         button->setIcon(icon);
0189     }
0190 }
0191 
0192 void updateIcon(QComboBox *comboBox)
0193 {
0194     for (int i = 0; i < comboBox->count(); i++) {
0195         QIcon icon = comboBox->itemIcon(i);
0196         if (adjustIcon(&icon)) {
0197             comboBox->setItemIcon(i, icon);
0198         }
0199     }
0200 }
0201 
0202 void updateIcon(QAction *action)
0203 {
0204     QIcon icon = action->icon();
0205 
0206     if (adjustIcon(&icon)) {
0207         action->setIcon(icon);
0208     }
0209 }
0210 
0211 void updateIcon(QTabBar *tabBar)
0212 {
0213     for (int i = 0; i < tabBar->count(); i++) {
0214         QIcon icon = tabBar->tabIcon(i);
0215         if (adjustIcon(&icon)) {
0216             tabBar->setTabIcon(i, icon);
0217         }
0218     }
0219 }
0220 
0221 }