File indexing completed on 2024-11-24 04:53:27

0001 /* Copyright (C) 2006 - 2015 Jan Kundrát <jkt@kde.org>
0002    Copyright (C) 2016 Luís Pereira <luis.artur.pereira@gmail.com>
0003 
0004    This file is part of the Trojita Qt IMAP e-mail client,
0005    http://trojita.flaska.net/
0006 
0007    This program is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU General Public License as
0009    published by the Free Software Foundation; either version 2 of
0010    the License or (at your option) version 3 or any later version
0011    accepted by the membership of KDE e.V. (or its successor approved
0012    by the membership of KDE e.V.), which shall act as a proxy
0013    defined in Section 14 of version 3 of the license.
0014 
0015    This program is distributed in the hope that it will be useful,
0016    but WITHOUT ANY WARRANTY; without even the implied warranty of
0017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0018    GNU General Public License for more details.
0019 
0020    You should have received a copy of the GNU General Public License
0021    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0022 */
0023 
0024 #include "IconLoader.h"
0025 #include <QCoreApplication>
0026 #include <QFileInfo>
0027 #include <QHash>
0028 
0029 namespace UiUtils {
0030 
0031 static void cleanup_icon_cache();
0032 namespace {
0033     struct Cache : public QHash<QString, QIcon>
0034     {
0035         Cache()
0036         {
0037             qAddPostRoutine(cleanup_icon_cache);
0038         }
0039     };
0040 }
0041 
0042 Q_GLOBAL_STATIC(Cache, iconDict)
0043 
0044 static void cleanup_icon_cache()
0045 {
0046     iconDict()->clear();
0047 }
0048 
0049 
0050 /** @short Wrapper around the QIcon::fromTheme with sane fallback
0051  *
0052  * The issue with the QIcon::fromTheme is that it does not really work on non-X11
0053  * platforms, unless you ship your own theme index and specify your theme name.
0054  * In Trojitá, we do not really want to hardcode anything, because the
0055  * preference is to use whatever is available from the current theme, but *also*
0056  * provide an icon as a fallback. And that is exactly why this function is here.
0057  * */
0058 QIcon loadIcon(const QString &name)
0059 {
0060     auto it = iconDict()->constFind(name);
0061     if (it != iconDict()->constEnd())
0062         return *it;
0063 
0064     auto overrideIcon = QStringLiteral(":/icons/%1/%2.svg").arg(QIcon::themeName(), name);
0065     if (QFileInfo(overrideIcon).exists()) {
0066         QIcon icon(overrideIcon);
0067         iconDict()->insert(name, icon);
0068         return icon;
0069     }
0070 
0071     // A QIcon(QString) constructor creates non-null QIcons, even though the resulting icon will
0072     // not ever return a valid and usable pixmap. This means that we have to actually look at the
0073     // icon's pixmap to find out what to return.
0074     // If we do not do that, the GUI shows empty pixmaps instead of a text fallback, which is
0075     // clearly suboptimal.
0076     QIcon res = QIcon::fromTheme(name, QIcon(QStringLiteral(":/icons/%1").arg(name)));
0077     if (res.pixmap(QSize(16, 16)).isNull()) {
0078         res = QIcon();
0079     }
0080     iconDict()->insert(name, res);
0081     return res;
0082 }
0083 
0084 }