Warning, file /frameworks/kiconthemes/src/kiconengine.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "kiconengine.h" 0009 0010 #include "kiconloader_p.h" 0011 #include <kiconloader.h> 0012 0013 #include "kiconcolors.h" 0014 #include <KIconTheme> 0015 #include <QFileInfo> 0016 #include <QPainter> 0017 #include <qscopeguard.h> 0018 0019 class KIconEnginePrivate 0020 { 0021 public: 0022 QPointer<KIconLoader> mIconLoader; 0023 bool mCustomColors = false; 0024 KIconColors mColors; 0025 QString mActualIconName; 0026 }; 0027 0028 KIconEngine::KIconEngine(const QString &iconName, KIconLoader *iconLoader, const QStringList &overlays) 0029 : mIconName(iconName) 0030 , mOverlays(overlays) 0031 , d(new KIconEnginePrivate{iconLoader, false, {}, {}}) 0032 { 0033 } 0034 0035 KIconEngine::KIconEngine(const QString &iconName, KIconLoader *iconLoader) 0036 : mIconName(iconName) 0037 , d(new KIconEnginePrivate{iconLoader, false, {}, {}}) 0038 { 0039 } 0040 0041 KIconEngine::KIconEngine(const QString &iconName, const KIconColors &colors, KIconLoader *iconLoader) 0042 : mIconName(iconName) 0043 , d(new KIconEnginePrivate{iconLoader, true, colors, {}}) 0044 { 0045 } 0046 0047 KIconEngine::~KIconEngine() 0048 { 0049 delete d; 0050 } 0051 0052 static inline int qIconModeToKIconState(QIcon::Mode mode) 0053 { 0054 switch (mode) { 0055 case QIcon::Normal: 0056 return KIconLoader::DefaultState; 0057 case QIcon::Active: 0058 return KIconLoader::ActiveState; 0059 case QIcon::Disabled: 0060 return KIconLoader::DisabledState; 0061 case QIcon::Selected: 0062 return KIconLoader::SelectedState; 0063 default: 0064 return KIconLoader::DefaultState; 0065 } 0066 } 0067 0068 QSize KIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) 0069 { 0070 return QIconEngine::actualSize(size, mode, state); 0071 } 0072 0073 void KIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) 0074 { 0075 if (!d->mIconLoader) { 0076 return; 0077 } 0078 0079 const qreal dpr = painter->device()->devicePixelRatioF(); 0080 const QPixmap pix = createPixmap(rect.size() * dpr, dpr, mode, state); 0081 painter->drawPixmap(rect, pix); 0082 } 0083 0084 QPixmap KIconEngine::createPixmap(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state) 0085 { 0086 Q_UNUSED(state) 0087 0088 if (scale < 1) { 0089 scale = 1; 0090 } 0091 0092 if (size.isEmpty()) { 0093 return QPixmap(); 0094 } 0095 0096 if (!d->mIconLoader) { 0097 QPixmap pm(size); 0098 pm.setDevicePixelRatio(scale); 0099 pm.fill(Qt::transparent); 0100 return pm; 0101 } 0102 0103 const QSize scaledSize = size / scale; 0104 0105 QString iconPath; 0106 0107 const int kstate = qIconModeToKIconState(mode); 0108 QPixmap pix = d->mIconLoader->loadScaledIcon(mIconName, 0109 KIconLoader::Desktop, 0110 scale, 0111 scaledSize, 0112 kstate, 0113 mOverlays, 0114 &iconPath, 0115 false, 0116 d->mCustomColors ? std::make_optional(d->mColors) : std::nullopt); 0117 0118 if (!iconPath.isEmpty() && !d->mActualIconName.isEmpty()) { 0119 d->mActualIconName = QFileInfo(iconPath).completeBaseName(); 0120 } 0121 0122 if (pix.size() == size) { 0123 return pix; 0124 } 0125 0126 QPixmap pix2(size); 0127 pix2.setDevicePixelRatio(scale); 0128 pix2.fill(QColor(0, 0, 0, 0)); 0129 0130 QPainter painter(&pix2); 0131 painter.setRenderHint(QPainter::SmoothPixmapTransform); 0132 const QSizeF targetSize = pix.size().scaled(scaledSize, Qt::KeepAspectRatio); 0133 QRectF targetRect({0, 0}, targetSize); 0134 targetRect.moveCenter(QRectF(pix2.rect()).center() / scale); 0135 painter.drawPixmap(targetRect, pix, pix.rect()); 0136 0137 return pix2; 0138 } 0139 0140 QPixmap KIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) 0141 { 0142 return createPixmap(size, 1 /*scale*/, mode, state); 0143 } 0144 0145 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0146 QString KIconEngine::iconName() 0147 #else 0148 QString KIconEngine::iconName() const 0149 #endif 0150 { 0151 if (!d->mActualIconName.isEmpty()) { 0152 return d->mActualIconName; 0153 } 0154 0155 if (!d->mIconLoader) { 0156 return QString(); 0157 } 0158 0159 const QString iconPath = KIconLoaderPrivate::get(d->mIconLoader)->preferredIconPath(mIconName); 0160 if (iconPath.isEmpty()) { 0161 return QString(); 0162 } 0163 0164 d->mActualIconName = QFileInfo(iconPath).completeBaseName(); 0165 return d->mActualIconName; 0166 } 0167 0168 Q_GLOBAL_STATIC_WITH_ARGS(QList<QSize>, 0169 sSizes, 0170 (QList<QSize>() << QSize(16, 16) << QSize(22, 22) << QSize(32, 32) << QSize(48, 48) << QSize(64, 64) << QSize(128, 128) 0171 << QSize(256, 256))) 0172 0173 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0174 QList<QSize> KIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state) 0175 #else 0176 QList<QSize> KIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state) const 0177 #endif 0178 { 0179 Q_UNUSED(mode); 0180 Q_UNUSED(state); 0181 0182 if (!d->mIconLoader) { 0183 return QList<QSize>(); 0184 } 0185 0186 const bool found = d->mIconLoader->hasIcon(mIconName); 0187 return found ? *sSizes : QList<QSize>(); 0188 } 0189 0190 QString KIconEngine::key() const 0191 { 0192 return QStringLiteral("KIconEngine"); 0193 } 0194 0195 QIconEngine *KIconEngine::clone() const 0196 { 0197 return new KIconEngine(mIconName, d->mIconLoader, mOverlays); 0198 } 0199 0200 bool KIconEngine::read(QDataStream &in) 0201 { 0202 in >> mIconName >> mOverlays; 0203 return true; 0204 } 0205 0206 bool KIconEngine::write(QDataStream &out) const 0207 { 0208 out << mIconName << mOverlays; 0209 return true; 0210 } 0211 0212 void KIconEngine::virtual_hook(int id, void *data) 0213 { 0214 if (id == QIconEngine::IsNullHook) { 0215 *reinterpret_cast<bool *>(data) = !d->mIconLoader || !d->mIconLoader->hasIcon(mIconName); 0216 } 0217 if (id == QIconEngine::ScaledPixmapHook) { 0218 auto *info = reinterpret_cast<ScaledPixmapArgument *>(data); 0219 info->pixmap = createPixmap(info->size, info->scale, info->mode, info->state); 0220 return; 0221 } 0222 QIconEngine::virtual_hook(id, data); 0223 }