3 This file is part of Minitube.
4 Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
6 Minitube is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 Minitube is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Minitube. If not, see <http://www.gnu.org/licenses/>.
21 #include "iconutils.h"
22 #include "mainwindow.h"
27 void addIconFile(QIcon &icon,
28 const QString &filename,
30 QIcon::Mode mode = QIcon::Normal,
31 QIcon::State state = QIcon::Off) {
32 if (QFile::exists(filename)) {
33 icon.addFile(filename, QSize(size, size), mode, state);
38 QIcon IconUtils::fromTheme(const QString &name) {
39 static const QLatin1String symbolic("-symbolic");
40 if (name.endsWith(symbolic)) return QIcon::fromTheme(name);
41 QIcon icon = QIcon::fromTheme(name + symbolic);
42 if (icon.isNull()) return QIcon::fromTheme(name);
46 QIcon IconUtils::fromResources(const char *name) {
47 qDebug() << "Creating icon" << name;
48 static const QLatin1String normal("_normal");
49 static const QLatin1String active("_active");
50 static const QLatin1String selected("_selected");
51 static const QLatin1String disabled("_disabled");
52 static const QLatin1String checked("_checked");
53 static const QLatin1String ext(".png");
55 QString path = QStringLiteral(":/icons/");
57 if (MainWindow::instance()->palette().window().color().value() > 128)
58 path += QLatin1String("light/");
60 path += QLatin1String("dark/");
64 // WARN keep these sizes updated with what we really use
65 for (int size : {16, 24, 32, 88}) {
66 const QString pathAndName =
67 path + QString::number(size) + QLatin1Char('/') + QLatin1String(name);
68 QString iconFilename = pathAndName + normal + ext;
69 if (QFile::exists(iconFilename)) {
70 addIconFile(icon, iconFilename, size);
71 addIconFile(icon, pathAndName + active + ext, size, QIcon::Active);
72 addIconFile(icon, pathAndName + selected + ext, size, QIcon::Selected);
73 addIconFile(icon, pathAndName + disabled + ext, size, QIcon::Disabled);
74 addIconFile(icon, pathAndName + checked + ext, size, QIcon::Normal, QIcon::On);
80 QIcon IconUtils::icon(const char *name) {
81 static QMap<QByteArray, QIcon> cache = [] {
82 qDebug() << "Init icon cache";
83 QMap<QByteArray, QIcon> c;
84 QObject::connect(qApp, &QApplication::paletteChanged, qApp, [&c]() {
85 qDebug() << "Clearing icon cache";
91 auto i = cache.constFind(QByteArray::fromRawData(name, strlen(name)));
92 if (i != cache.constEnd()) return i.value();
96 icon = fromTheme(name);
97 if (icon.isNull()) icon = fromResources(name);
99 icon = fromResources(name);
102 cache.insert(QByteArray(name), icon);
106 QIcon IconUtils::icon(const QVector<const char *> &names) {
108 for (auto name : names) {
109 icon = IconUtils::icon(name);
110 if (!icon.availableSizes().isEmpty()) break;
115 QPixmap IconUtils::iconPixmap(const char *name,
117 const QColor &background,
118 const qreal pixelRatio) {
119 QString path = QStringLiteral(":/icons/");
120 if (background.value() > 128)
121 path += QLatin1String("light/");
123 path += QLatin1String("dark/");
124 path += QString::number(size) + QLatin1Char('/') + QLatin1String(name) +
125 QLatin1String("_normal.png");
126 return IconUtils::pixmap(path, pixelRatio);
129 QIcon IconUtils::tintedIcon(const char *name, const QColor &color, const QVector<QSize> &sizes) {
130 QIcon i = IconUtils::icon(name);
132 // if (sizes.isEmpty()) sizes = i.availableSizes();
133 for (const QSize &size : sizes) {
134 QPixmap pixmap = i.pixmap(size);
141 QIcon IconUtils::tintedIcon(const char *name, const QColor &color, const QSize &size) {
142 return IconUtils::tintedIcon(name, color, QVector<QSize>() << size);
145 QImage IconUtils::grayscaled(const QImage &image) {
147 int pixels = img.width() * img.height();
148 unsigned int *data = (unsigned int *)img.bits();
149 for (int i = 0; i < pixels; ++i) {
150 int val = qGray(data[i]);
151 data[i] = qRgba(val, val, val, qAlpha(data[i]));
156 QImage IconUtils::tinted(const QImage &image, const QColor &color, QPainter::CompositionMode mode) {
157 QImage img(image.size(), QImage::Format_ARGB32_Premultiplied);
158 QPainter painter(&img);
159 painter.drawImage(0, 0, grayscaled(image));
160 painter.setCompositionMode(mode);
161 painter.fillRect(img.rect(), color);
163 img.setAlphaChannel(image.alphaChannel());
167 void IconUtils::tint(QPixmap &pixmap, const QColor &color, QPainter::CompositionMode mode) {
168 QPainter painter(&pixmap);
169 painter.setCompositionMode(mode);
170 painter.fillRect(pixmap.rect(), color);
173 QPixmap IconUtils::pixmap(const char *name, const qreal pixelRatio) {
174 return pixmap(QString::fromLatin1(name), pixelRatio);
177 QPixmap IconUtils::pixmap(const QString &filename, const qreal pixelRatio) {
178 // Check if a "@2x" file exists
179 if (pixelRatio > 1.0) {
180 int dotIndex = filename.lastIndexOf(QLatin1Char('.'));
181 if (dotIndex != -1) {
182 QString at2xfileName = filename;
183 at2xfileName.insert(dotIndex, QLatin1String("@2x"));
184 if (QFile::exists(at2xfileName)) {
185 QPixmap pixmap(at2xfileName);
186 pixmap.setDevicePixelRatio(pixelRatio);
191 return QPixmap(filename);