Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qicon.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qicon.h"
6#include "qicon_p.h"
7#include "qiconengine.h"
8#include "qiconengineplugin.h"
9#include "qimagereader.h"
10#include "private/qfactoryloader_p.h"
11#include "private/qiconloader_p.h"
12#include "qpainter.h"
13#include "qfileinfo.h"
14#if QT_CONFIG(mimetype)
15#include <qmimedatabase.h>
16#include <qmimetype.h>
17#endif
18#include "qpixmapcache.h"
19#include "qvariant.h"
20#include "qcache.h"
21#include "qdebug.h"
22#include "qdir.h"
23#include "qpalette.h"
24#include "qmath.h"
25
26#include "private/qhexstring_p.h"
27#include "private/qguiapplication_p.h"
28#include "qpa/qplatformtheme.h"
29
30#ifndef QT_NO_ICON
32
33using namespace Qt::StringLiterals;
34
69{
70 Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
71 return 1 + serial.fetchAndAddRelaxed(1);
72}
73
74static void qt_cleanup_icon_cache();
75namespace {
76 struct IconCache : public QCache<QString, QIcon>
77 {
78 IconCache()
79 {
80 // ### note: won't readd if QApplication is re-created!
82 }
83 };
84}
85
86Q_GLOBAL_STATIC(IconCache, qtIconCache)
87
89{
90 qtIconCache()->clear();
91}
92
94 : engine(e), ref(1),
95 serialNum(nextSerialNumCounter()),
96 detach_no(0),
97 is_mask(false)
98{
102{
104}
105
117qreal QIconPrivate::pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize)
118{
119 QSize targetSize = requestedSize * displayDevicePixelRatio;
120 if ((actualSize.width() == targetSize.width() && actualSize.height() <= targetSize.height()) ||
121 (actualSize.width() <= targetSize.width() && actualSize.height() == targetSize.height())) {
122 // Correctly scaled for dpr, just having different aspect ratio
123 return displayDevicePixelRatio;
124 }
125 qreal scale = 0.5 * (qreal(actualSize.width()) / qreal(targetSize.width()) +
126 qreal(actualSize.height() / qreal(targetSize.height())));
127 return qMax(qreal(1.0), displayDevicePixelRatio *scale);
128}
129
131{
132}
133
135 : QIconEngine(other), pixmaps(other.pixmaps)
136{
137}
138
140{
141}
142
144{
145 auto paintDevice = painter->device();
146 qreal dpr = paintDevice ? paintDevice->devicePixelRatio() : qApp->devicePixelRatio();
147 const QSize pixmapSize = rect.size() * dpr;
148 QPixmap px = scaledPixmap(pixmapSize, mode, state, dpr);
149 painter->drawPixmap(rect, px);
150}
151
152static inline int area(const QSize &s) { return s.width() * s.height(); }
153
154// Returns the smallest of the two that is still larger than or equal to size.
155// Pixmaps at the correct scale are preferred, pixmaps at lower scale are
156// used as fallbacks. We assume that the pixmap set is complete, in the sense
157// that no 2x pixmap is going to be a better match than a 3x pixmap for the the
158// target scale of 3 (It's OK if 3x pixmaps are missing - we'll fall back to
159// the 2x pixmaps then.)
161{
162
163 // scale: we can only differentiate on scale if the scale differs
164 if (pa->scale != pb->scale) {
165
166 // Score the pixmaps: 0 is an exact scale match, positive
167 // scores have more detail than requested, negative scores
168 // have less detail than requested.
169 qreal ascore = pa->scale - scale;
170 qreal bscore = pb->scale - scale;
171
172 // Take the one closest to 0
173 return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
174 }
175
176 int s = area(size);
177 if (pa->size == QSize() && pa->pixmap.isNull()) {
178 pa->pixmap = QPixmap(pa->fileName);
179 pa->size = pa->pixmap.size();
180 }
181 int a = area(pa->size);
182 if (pb->size == QSize() && pb->pixmap.isNull()) {
183 pb->pixmap = QPixmap(pb->fileName);
184 pb->size = pb->pixmap.size();
185 }
186 int b = area(pb->size);
187 int res = a;
188 if (qMin(a,b) >= s)
189 res = qMin(a,b);
190 else
191 res = qMax(a,b);
192 if (res == a)
193 return pa;
194 return pb;
195}
196
197QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
198{
199 QPixmapIconEngineEntry *pe = nullptr;
200 for (int i = 0; i < pixmaps.size(); ++i)
201 if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
202 if (pe)
203 pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
204 else
205 pe = &pixmaps[i];
206 }
207 return pe;
208}
209
210
212{
213 QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
214 while (!pe){
215 QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On;
218 if ((pe = tryMatch(size, scale, QIcon::Normal, state)))
219 break;
220 if ((pe = tryMatch(size, scale, QIcon::Active, state)))
221 break;
222 if ((pe = tryMatch(size, scale, mode, oppositeState)))
223 break;
224 if ((pe = tryMatch(size, scale, QIcon::Normal, oppositeState)))
225 break;
226 if ((pe = tryMatch(size, scale, QIcon::Active, oppositeState)))
227 break;
228 if ((pe = tryMatch(size, scale, oppositeMode, state)))
229 break;
230 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
231 break;
232 } else {
234 if ((pe = tryMatch(size, scale, oppositeMode, state)))
235 break;
236 if ((pe = tryMatch(size, scale, mode, oppositeState)))
237 break;
238 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
239 break;
240 if ((pe = tryMatch(size, scale, QIcon::Disabled, state)))
241 break;
242 if ((pe = tryMatch(size, scale, QIcon::Selected, state)))
243 break;
244 if ((pe = tryMatch(size, scale, QIcon::Disabled, oppositeState)))
245 break;
246 if ((pe = tryMatch(size, scale, QIcon::Selected, oppositeState)))
247 break;
248 }
249
250 if (!pe)
251 return pe;
252 }
253
254 if (sizeOnly ? (pe->size.isNull() || !pe->size.isValid()) : pe->pixmap.isNull()) {
255 pe->pixmap = QPixmap(pe->fileName);
256 if (!pe->pixmap.isNull())
257 pe->size = pe->pixmap.size();
258 }
259
260 return pe;
261}
262
264{
265 return scaledPixmap(size, mode, state, 1.0);
266}
267
269{
270
271 QPixmap pm;
273 if (pe)
274 pm = pe->pixmap;
275
276 if (pm.isNull()) {
277 int idx = pixmaps.size();
278 while (--idx >= 0) {
279 if (pe == &pixmaps.at(idx)) {
280 pixmaps.remove(idx);
281 break;
282 }
283 }
284 if (pixmaps.isEmpty())
285 return pm;
286 else
287 return pixmap(size, mode, state);
288 }
289
290 QSize actualSize = pm.size();
291 if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
293
294 QString key = "qt_"_L1
300
301 if (mode == QIcon::Active) {
303 return pm; // horray
305 QPixmap active = pm;
306 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
307 active = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(QIcon::Active, pm);
308 if (pm.cacheKey() == active.cacheKey())
309 return pm;
310 }
311 }
312
314 if (pm.size() != actualSize)
316 if (pe->mode != mode && mode != QIcon::Normal) {
317 QPixmap generated = pm;
318 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
319 generated = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, pm);
320 if (!generated.isNull())
321 pm = generated;
322 }
324 }
325 return pm;
326}
327
329{
331
332 // The returned actual size is the size in device independent pixels,
333 // so we limit the search to scale 1 and assume that e.g. @2x versions
334 // does not proviode extra actual sizes not also provided by the 1x versions.
335 qreal scale = 1;
336
338 actualSize = pe->size;
339
340 if (actualSize.isNull())
341 return actualSize;
342
343 if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
345 return actualSize;
346}
347
349{
351 for (int i = 0; i < pixmaps.size(); ++i) {
352 QPixmapIconEngineEntry &pe = pixmaps[i];
353 if (pe.size == QSize() && pe.pixmap.isNull()) {
354 pe.pixmap = QPixmap(pe.fileName);
355 pe.size = pe.pixmap.size();
356 }
357 if (pe.mode == mode && pe.state == state && !pe.size.isEmpty())
358 sizes.push_back(pe.size);
359 }
360 return sizes;
361}
362
364{
365 if (!pixmap.isNull()) {
366 QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), pixmap.devicePixelRatio(), mode, state);
367 if (pe && pe->size == pixmap.size() && pe->scale == pixmap.devicePixelRatio()) {
368 pe->pixmap = pixmap;
369 pe->fileName.clear();
370 } else {
372 }
373 }
374}
375
376// Read out original image depth as set by ICOReader
377static inline int origIcoDepth(const QImage &image)
378{
379 const QString s = image.text(QStringLiteral("_q_icoOrigDepth"));
380 return s.isEmpty() ? 32 : s.toInt();
381}
382
383static inline int findBySize(const QList<QImage> &images, const QSize &size)
384{
385 for (int i = 0; i < images.size(); ++i) {
386 if (images.at(i).size() == size)
387 return i;
388 }
389 return -1;
390}
391
392// Convenience class providing a bool read() function.
393namespace {
394class ImageReader
395{
396public:
397 ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
398
399 QByteArray format() const { return m_reader.format(); }
400
401 bool read(QImage *image)
402 {
403 if (m_atEnd)
404 return false;
405 *image = m_reader.read();
406 if (!image->size().isValid()) {
407 m_atEnd = true;
408 return false;
409 }
410 m_atEnd = !m_reader.jumpToNextImage();
411 return true;
412 }
413
414private:
415 QImageReader m_reader;
416 bool m_atEnd;
417};
418} // namespace
419
421{
422 if (fileName.isEmpty())
423 return;
424 const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath();
425 const bool ignoreSize = !size.isValid();
426 ImageReader imageReader(abs);
427 const QByteArray format = imageReader.format();
428 if (format.isEmpty()) // Device failed to open or unsupported format.
429 return;
431 if (format != "ico") {
432 if (ignoreSize) { // No size specified: Add all images.
433 while (imageReader.read(&image))
434 pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
435 } else {
436 // Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
437 while (imageReader.read(&image) && image.size() != size) {}
438 pixmaps += image.size() == size ?
440 }
441 return;
442 }
443 // Special case for reading Windows ".ico" files. Historically (QTBUG-39287),
444 // these files may contain low-resolution images. As this information is lost,
445 // ICOReader sets the original format as an image text key value. Read all matching
446 // images into a list trying to find the highest quality per size.
447 QList<QImage> icoImages;
448 while (imageReader.read(&image)) {
449 if (ignoreSize || image.size() == size) {
450 const int position = findBySize(icoImages, image.size());
451 if (position >= 0) { // Higher quality available? -> replace.
452 if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
453 icoImages[position] = image;
454 } else {
455 icoImages.append(image);
456 }
457 }
458 }
459 for (const QImage &i : std::as_const(icoImages))
460 pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
461 if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
462 pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
463}
464
466{
467 return "QPixmapIconEngine"_L1;
468}
469
471{
472 return new QPixmapIconEngine(*this);
473}
474
476{
477 int num_entries;
478 QPixmap pm;
480 QSize sz;
481 uint mode;
482 uint state;
483
484 in >> num_entries;
485 for (int i=0; i < num_entries; ++i) {
486 if (in.atEnd()) {
487 pixmaps.clear();
488 return false;
489 }
490 in >> pm;
491 in >> fileName;
492 in >> sz;
493 in >> mode;
494 in >> state;
495 if (pm.isNull()) {
497 } else {
499 pe.pixmap = pm;
500 pixmaps += pe;
501 }
502 }
503 return true;
504}
505
507{
508 int num_entries = pixmaps.size();
509 out << num_entries;
510 for (int i=0; i < num_entries; ++i) {
511 if (pixmaps.at(i).pixmap.isNull())
512 out << QPixmap(pixmaps.at(i).fileName);
513 else
514 out << pixmaps.at(i).pixmap;
515 out << pixmaps.at(i).fileName;
516 out << pixmaps.at(i).size;
517 out << (uint) pixmaps.at(i).mode;
518 out << (uint) pixmaps.at(i).state;
519 }
520 return true;
521}
522
525
527{
528 return iceLoader();
529}
530
531
648QIcon::QIcon() noexcept
649 : d(nullptr)
650{
651}
652
657 :d(nullptr)
658{
660}
661
666 :d(other.d)
667{
668 if (d)
669 d->ref.ref();
670}
671
698 : d(nullptr)
699{
701}
702
703
709 :d(new QIconPrivate(engine))
710{
711}
712
717{
718 if (d && !d->ref.deref())
719 delete d;
720}
721
727{
728 if (other.d)
729 other.d->ref.ref();
730 if (d && !d->ref.deref())
731 delete d;
732 d = other.d;
733 return *this;
734}
735
755QIcon::operator QVariant() const
756{
757 return QVariant::fromValue(*this);
758}
759
774{
775 if (!d)
776 return 0;
777 return (((qint64) d->serialNum) << 32) | ((qint64) (d->detach_no));
778}
779
789{
790 if (!d)
791 return QPixmap();
792 const qreal dpr = -1; // don't know target dpr
793 return pixmap(size, dpr, mode, state);
794}
795
825QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, State state) const
826{
827 if (!d)
828 return QPixmap();
829
830 // Use the global devicePixelRatio if the caller does not know the target dpr
831 if (devicePixelRatio == -1)
832 devicePixelRatio = qApp->devicePixelRatio();
833
834 // Handle the simple normal-dpi case
835 if (!(devicePixelRatio > 1.0)) {
837 pixmap.setDevicePixelRatio(1.0);
838 return pixmap;
839 }
840
841 // Try get a pixmap that is big enough to be displayed at device pixel resolution.
842 QPixmap pixmap = d->engine->scaledPixmap(size * devicePixelRatio, mode, state, devicePixelRatio);
843 pixmap.setDevicePixelRatio(d->pixmapDevicePixelRatio(devicePixelRatio, size, pixmap.size()));
844 return pixmap;
845}
846
847#if QT_DEPRECATED_SINCE(6, 0)
863{
864 if (!d)
865 return QPixmap();
866
867 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
868 return pixmap(size, devicePixelRatio, mode, state);
869}
870#endif
871
872
881{
882 if (!d)
883 return QSize();
884
885 const qreal devicePixelRatio = qApp->devicePixelRatio();
886
887 // Handle the simple normal-dpi case:
888 if (!(devicePixelRatio > 1.0))
889 return d->engine->actualSize(size, mode, state);
890
891 const QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
892 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
893}
894
895#if QT_DEPRECATED_SINCE(6, 0)
910{
911 if (!d)
912 return QSize();
913
914 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
915
916 // Handle the simple normal-dpi case:
917 if (!(devicePixelRatio > 1.0))
918 return d->engine->actualSize(size, mode, state);
919
920 QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
921 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
922}
923#endif
924
931void QIcon::paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, Mode mode, State state) const
932{
933 if (!d || !painter)
934 return;
935
936 // Copy of QStyle::alignedRect
937 const QSize size = d->engine->actualSize(rect.size(), mode, state);
939 int x = rect.x();
940 int y = rect.y();
941 int w = size.width();
942 int h = size.height();
944 y += rect.size().height()/2 - h/2;
946 y += rect.size().height() - h;
948 x += rect.size().width() - w;
950 x += rect.size().width()/2 - w/2;
951 QRect alignedRect(x, y, w, h);
952
954}
955
973bool QIcon::isNull() const
974{
975 return !d || d->engine->isNull();
976}
977
981{
982 return !d || d->ref.loadRelaxed() == 1;
983}
984
988{
989 if (d) {
990 if (d->engine->isNull()) {
991 if (!d->ref.deref())
992 delete d;
993 d = nullptr;
994 return;
995 } else if (d->ref.loadRelaxed() != 1) {
996 QIconPrivate *x = new QIconPrivate(d->engine->clone());
997 if (!d->ref.deref())
998 delete d;
999 d = x;
1000 }
1001 ++d->detach_no;
1002 }
1003}
1004
1015{
1016 if (pixmap.isNull())
1017 return;
1018 detach();
1019 if (!d)
1020 d = new QIconPrivate(new QPixmapIconEngine);
1022}
1023
1025{
1026 if (!suffix.isEmpty()) {
1027 const int index = iceLoader()->indexOf(suffix);
1028 if (index != -1) {
1029 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1030 return factory->create(fileName);
1031 }
1032 }
1033 }
1034 return nullptr;
1035}
1036
1068{
1069 if (fileName.isEmpty())
1070 return;
1071 detach();
1072 if (!d) {
1073
1075 QString suffix = info.suffix();
1076#if QT_CONFIG(mimetype)
1077 if (suffix.isEmpty())
1078 suffix = QMimeDatabase().mimeTypeForFile(info).preferredSuffix(); // determination from contents
1079#endif // mimetype
1082 }
1083
1085
1086 // Check if a "@Nx" file exists and add it.
1087 QString atNxFileName = qt_findAtNxFile(fileName, qApp->devicePixelRatio());
1088 if (atNxFileName != fileName)
1089 d->engine->addFile(atNxFileName, size, mode, state);
1090}
1091
1099{
1100 if (!d || !d->engine)
1101 return QList<QSize>();
1102 return d->engine->availableSizes(mode, state);
1103}
1104
1116{
1117 if (!d || !d->engine)
1118 return QString();
1119 return d->engine->iconName();
1120}
1121
1129{
1131}
1132
1150{
1152}
1153
1169{
1171}
1172
1190{
1192}
1193
1206{
1208}
1209
1222{
1223 return QIconLoader::instance()->themeName();
1224}
1225
1237{
1239}
1240
1260{
1262}
1263
1297{
1298
1299 if (QIcon *cachedIcon = qtIconCache()->object(name))
1300 return *cachedIcon;
1301
1303 return QIcon(name);
1304
1306 qtIconCache()->insert(name, new QIcon(icon));
1307 return icon;
1308}
1309
1322QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
1323{
1325
1326 if (icon.isNull() || icon.availableSizes().isEmpty())
1327 return fallback;
1328
1329 return icon;
1330}
1331
1341{
1343
1344 return icon.name() == name;
1345}
1346
1354void QIcon::setIsMask(bool isMask)
1355{
1356 detach();
1357 if (!d)
1358 d = new QIconPrivate(new QPixmapIconEngine);
1359 d->is_mask = isMask;
1360}
1361
1371bool QIcon::isMask() const
1372{
1373 if (!d)
1374 return false;
1375 return d->is_mask;
1376}
1377
1378/*****************************************************************************
1379 QIcon stream functions
1380 *****************************************************************************/
1381#if !defined(QT_NO_DATASTREAM)
1394{
1395 if (s.version() >= QDataStream::Qt_4_3) {
1396 if (icon.isNull()) {
1397 s << QString();
1398 } else {
1399 s << icon.d->engine->key();
1400 icon.d->engine->write(s);
1401 }
1402 } else if (s.version() == QDataStream::Qt_4_2) {
1403 if (icon.isNull()) {
1404 s << 0;
1405 } else {
1407 int num_entries = engine->pixmaps.size();
1408 s << num_entries;
1409 for (int i=0; i < num_entries; ++i) {
1410 s << engine->pixmaps.at(i).pixmap;
1411 s << engine->pixmaps.at(i).fileName;
1412 s << engine->pixmaps.at(i).size;
1413 s << (uint) engine->pixmaps.at(i).mode;
1414 s << (uint) engine->pixmaps.at(i).state;
1415 }
1416 }
1417 } else {
1418 s << QPixmap(icon.pixmap(22,22));
1419 }
1420 return s;
1421}
1422
1433{
1434 if (s.version() >= QDataStream::Qt_4_3) {
1435 icon = QIcon();
1436 QString key;
1437 s >> key;
1438 if (key == "QPixmapIconEngine"_L1) {
1439 icon.d = new QIconPrivate(new QPixmapIconEngine);
1440 icon.d->engine->read(s);
1441 } else if (key == "QIconLoaderEngine"_L1 || key == "QThemeIconEngine"_L1) {
1442 icon.d = new QIconPrivate(new QThemeIconEngine);
1443 icon.d->engine->read(s);
1444 } else {
1445 const int index = iceLoader()->indexOf(key);
1446 if (index != -1) {
1447 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1448 if (QIconEngine *engine= factory->create()) {
1449 icon.d = new QIconPrivate(engine);
1450 engine->read(s);
1451 } // factory
1452 } // instance
1453 } // index
1454 }
1455 } else if (s.version() == QDataStream::Qt_4_2) {
1456 icon = QIcon();
1457 int num_entries;
1458 QPixmap pm;
1460 QSize sz;
1461 uint mode;
1462 uint state;
1463
1464 s >> num_entries;
1465 for (int i=0; i < num_entries; ++i) {
1466 s >> pm;
1467 s >> fileName;
1468 s >> sz;
1469 s >> mode;
1470 s >> state;
1471 if (pm.isNull())
1473 else
1475 }
1476 } else {
1477 QPixmap pm;
1478 s >> pm;
1479 icon.addPixmap(pm);
1480 }
1481 return s;
1482}
1483
1484#endif //QT_NO_DATASTREAM
1485
1486#ifndef QT_NO_DEBUG_STREAM
1488{
1489 QDebugStateSaver saver(dbg);
1490 dbg.resetFormat();
1491 dbg.nospace();
1492 dbg << "QIcon(";
1493 if (i.isNull()) {
1494 dbg << "null";
1495 } else {
1496 if (!i.name().isEmpty())
1497 dbg << i.name() << ',';
1498 dbg << "availableSizes[normal,Off]=" << i.availableSizes()
1499 << ",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase;
1500 }
1501 dbg << ')';
1502 return dbg;
1503}
1504#endif
1505
1528QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
1529 qreal *sourceDevicePixelRatio)
1530{
1531 if (targetDevicePixelRatio <= 1.0)
1532 return baseFileName;
1533
1534 static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
1535 if (disableNxImageLoading)
1536 return baseFileName;
1537
1538 int dotIndex = baseFileName.lastIndexOf(u'.');
1539 if (dotIndex == -1) { /* no dot */
1540 dotIndex = baseFileName.size(); /* append */
1541 } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9'
1542 && baseFileName[dotIndex - 2] == u'.') {
1543 // If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it.
1544 dotIndex -= 2;
1545 }
1546
1547 QString atNxfileName = baseFileName;
1548 atNxfileName.insert(dotIndex, "@2x"_L1);
1549 // Check for @Nx, ..., @3x, @2x file versions,
1550 for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) {
1551 atNxfileName[dotIndex + 1] = QLatin1Char('0' + n);
1552 if (QFile::exists(atNxfileName)) {
1553 if (sourceDevicePixelRatio)
1554 *sourceDevicePixelRatio = n;
1555 return atNxfileName;
1556 }
1557 }
1558
1559 return baseFileName;
1560}
1561
1563#endif //QT_NO_ICON
bool ref() noexcept
bool deref() noexcept
T loadRelaxed() const noexcept
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
static bool isAbsolutePath(const QString &path)
Returns true if path is absolute; returns false if it is relative.
Definition qdir.h:183
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString suffix() const
Returns the suffix (extension) of the file.
QString absoluteFilePath() const
Returns an absolute path including the file name.
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qfile.cpp:351
static Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
\macro qGuiApp
static QPalette palette()
Returns the current application palette.
The QIconEnginePlugin class provides an abstract base for custom QIconEngine plugins.
The QIconEngine class provides an abstract base class for QIcon renderers.
Definition qiconengine.h:15
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)=0
Uses the given painter to paint the icon with the required mode and state into the rectangle rect.
virtual QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
virtual QIconEngine * clone() const =0
Reimplement this method to return a clone of this icon engine.
virtual bool read(QDataStream &in)
Reads icon engine contents from the QDataStream in.
virtual QString iconName()
virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
Returns the icon as a pixmap with the required size, mode, and state.
virtual void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
Called by QIcon::addFile().
virtual bool isNull()
virtual QList< QSize > availableSizes(QIcon::Mode mode=QIcon::Normal, QIcon::State state=QIcon::Off)
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
Returns the actual size of the icon the engine provides for the requested size, mode and state.
virtual void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
Called by QIcon::addPixmap().
virtual QString key() const
\variable QIconEngine::ScaledPixmapArgument::size
virtual bool write(QDataStream &out) const
Writes the contents of this engine to the QDataStream out.
void setFallbackThemeName(const QString &themeName)
QStringList fallbackSearchPaths() const
void setFallbackSearchPaths(const QStringList &searchPaths)
void setThemeSearchPath(const QStringList &searchPaths)
static QIconLoader * instance()
QString fallbackThemeName() const
QStringList themeSearchPaths() const
QString themeName() const
void setThemeName(const QString &themeName)
QAtomicInt ref
Definition qicon_p.h:41
QIconEngine * engine
Definition qicon_p.h:39
int serialNum
Definition qicon_p.h:42
bool is_mask
Definition qicon_p.h:44
QIconPrivate(QIconEngine *e)
Definition qicon.cpp:93
int detach_no
Definition qicon_p.h:43
static void clearIconCache()
Definition qicon.cpp:101
qreal pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize)
Definition qicon.cpp:117
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
static bool hasThemeIcon(const QString &name)
Definition qicon.cpp:1340
void setIsMask(bool isMask)
Definition qicon.cpp:1354
void paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment=Qt::AlignCenter, Mode mode=Normal, State state=Off) const
Uses the painter to paint the icon with specified alignment, required mode, and state into the rectan...
Definition qicon.cpp:931
~QIcon()
Destroys the icon.
Definition qicon.cpp:716
static QString themeName()
Definition qicon.cpp:1221
static void setFallbackSearchPaths(const QStringList &paths)
Definition qicon.cpp:1189
static void setThemeName(const QString &path)
Definition qicon.cpp:1205
static QStringList fallbackSearchPaths()
Definition qicon.cpp:1168
void addPixmap(const QPixmap &pixmap, Mode mode=Normal, State state=Off)
Adds pixmap to the icon, as a specialization for mode and state.
Definition qicon.cpp:1014
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:973
Mode
This enum type describes the mode for which a pixmap is intended to be used.
Definition qicon.h:22
@ Disabled
Definition qicon.h:22
@ Selected
Definition qicon.h:22
@ Normal
Definition qicon.h:22
@ Active
Definition qicon.h:22
QList< QSize > availableSizes(Mode mode=Normal, State state=Off) const
Definition qicon.cpp:1098
static void setThemeSearchPaths(const QStringList &searchpath)
Definition qicon.cpp:1128
qint64 cacheKey() const
Returns a number that identifies the contents of this QIcon object.
Definition qicon.cpp:773
bool isMask() const
Definition qicon.cpp:1371
static void setFallbackThemeName(const QString &name)
Definition qicon.cpp:1259
void addFile(const QString &fileName, const QSize &size=QSize(), Mode mode=Normal, State state=Off)
Adds an image from the file with the given fileName to the icon, as a specialization for size,...
Definition qicon.cpp:1067
State
This enum describes the state for which a pixmap is intended to be used.
Definition qicon.h:23
@ Off
Definition qicon.h:23
@ On
Definition qicon.h:23
static QStringList themeSearchPaths()
Definition qicon.cpp:1149
QString name() const
Definition qicon.cpp:1115
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
Definition qicon.cpp:880
void detach()
Definition qicon.cpp:987
bool isDetached() const
Definition qicon.cpp:980
QIcon & operator=(const QIcon &other)
Assigns the other icon to this icon and returns a reference to this icon.
Definition qicon.cpp:726
static QString fallbackThemeName()
Definition qicon.cpp:1236
QIcon() noexcept
Constructs a null icon.
Definition qicon.cpp:648
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Definition qicon.cpp:788
static QIcon fromTheme(const QString &name)
Definition qicon.cpp:1296
The QImageReader class provides a format independent interface for reading images from files or other...
\inmodule QtGui
Definition qimage.h:37
QSize size() const
Returns the size of the image, i.e.
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:787
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
QMimeType mimeTypeForFile(const QString &fileName, MatchMode mode=MatchDefault) const
Returns a MIME type for the file named fileName using mode.
QString preferredSuffix
the preferred suffix for the MIME type
Definition qmimetype.h:38
static QObjectPrivate * get(QObject *o)
Definition qobject_p.h:153
The QPainter class performs low-level painting on widgets and other paint devices.
Definition qpainter.h:46
Qt::LayoutDirection layoutDirection() const
Returns the layout direction used by the painter when drawing text.
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or \nullptr if the painter is n...
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device.
qint64 cacheKey() const
Returns a number that identifies the contents of this QPalette object.
Definition qpalette.cpp:989
static bool find(const QString &key, QPixmap *pixmap)
Looks for a cached pixmap associated with the given key in the cache.
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
bool read(QDataStream &in) override
Reads icon engine contents from the QDataStream in.
Definition qicon.cpp:475
QList< QSize > availableSizes(QIcon::Mode mode, QIcon::State state) override
Definition qicon.cpp:348
QString key() const override
\variable QIconEngine::ScaledPixmapArgument::size
Definition qicon.cpp:465
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override
Called by QIcon::addPixmap().
Definition qicon.cpp:363
QIconEngine * clone() const override
Reimplement this method to return a clone of this icon engine.
Definition qicon.cpp:470
bool write(QDataStream &out) const override
Writes the contents of this engine to the QDataStream out.
Definition qicon.cpp:506
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override
Definition qicon.cpp:268
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override
Uses the given painter to paint the icon with the required mode and state into the rectangle rect.
Definition qicon.cpp:143
QPixmapIconEngineEntry * bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
Definition qicon.cpp:211
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override
Returns the actual size of the icon the engine provides for the requested size, mode and state.
Definition qicon.cpp:328
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override
Returns the icon as a pixmap with the required size, mode, and state.
Definition qicon.cpp:263
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override
Called by QIcon::addFile().
Definition qicon.cpp:420
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
Definition qpixmap.h:27
QPixmap scaled(int w, int h, Qt::AspectRatioMode aspectMode=Qt::IgnoreAspectRatio, Qt::TransformationMode mode=Qt::FastTransformation) const
Definition qpixmap.h:78
QSize size() const
Returns the size of the pixmap.
Definition qpixmap.cpp:497
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:460
qint64 cacheKey() const
Returns a number that identifies this QPixmap.
Definition qpixmap.cpp:888
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
void scale(int w, int h, Qt::AspectRatioMode mode) noexcept
Scales the size to a rectangle with the given width and height, according to the specified mode:
Definition qsize.h:144
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:120
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:123
constexpr bool isValid() const noexcept
Returns true if both the width and height is equal to or greater than 0; otherwise returns false.
Definition qsize.h:126
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:279
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString & insert(qsizetype i, QChar c)
Definition qstring.cpp:3110
A named-based icon engine for providing theme icons.
\inmodule QtCore
Definition qvariant.h:64
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:531
\inmodule QtGui
Definition qwindow.h:63
double e
rect
[4]
uint alignment
else opt state
[0]
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:145
@ AlignBottom
Definition qnamespace.h:153
@ AlignVCenter
Definition qnamespace.h:154
@ AlignHCenter
Definition qnamespace.h:147
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
@ SmoothTransformation
QTextStream & showbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on stream and r...
@ KeepAspectRatio
@ IgnoreAspectRatio
QTextStream & noshowbase(QTextStream &stream)
Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on stream and ...
QTextStream & dec(QTextStream &stream)
Calls QTextStream::setIntegerBase(10) on stream and returns stream.
@ CaseInsensitive
Definition image.cpp:4
#define Q_BASIC_ATOMIC_INITIALIZER(a)
void qAddPostRoutine(QtCleanUpFunction p)
#define qApp
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static void qt_cleanup_icon_cache()
Definition qicon.cpp:88
static int origIcoDepth(const QImage &image)
Definition qicon.cpp:377
static int area(const QSize &s)
Definition qicon.cpp:152
static int nextSerialNumCounter()
Definition qicon.cpp:68
QDataStream & operator>>(QDataStream &s, QIcon &icon)
Definition qicon.cpp:1432
static QIconEngine * iconEngineFromSuffix(const QString &fileName, const QString &suffix)
Definition qicon.cpp:1024
QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, qreal *sourceDevicePixelRatio)
Definition qicon.cpp:1528
static int findBySize(const QList< QImage > &images, const QSize &size)
Definition qicon.cpp:383
static QPixmapIconEngineEntry * bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
Definition qicon.cpp:160
QDataStream & operator<<(QDataStream &s, const QIcon &icon)
Definition qicon.cpp:1393
Q_GUI_EXPORT QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, qreal *sourceDevicePixelRatio=nullptr)
Definition qicon.cpp:1528
#define QIconEngineFactoryInterface_iid
QFactoryLoader * qt_iconEngineFactoryLoader()
int qCeil(T v)
Definition qmath.h:36
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum mode
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLsizei const GLuint * paths
GLint ref
GLuint name
GLfloat n
GLint GLsizei GLsizei GLenum format
GLint y
GLfloat GLfloat GLfloat GLfloat h
GLuint res
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLuint in
GLdouble s
[6]
Definition qopenglext.h:235
GLenum GLenum GLenum GLenum GLenum scale
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QT_BEGIN_NAMESPACE qreal dpr(const QWindow *w)
static QRectF alignedRect(bool mirrored, Qt::Alignment alignment, const QSizeF &size, const QRectF &rectangle)
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
ReturnedValue read(const char *data)
QList< QImage > images
[6]
QFileInfo info(fileName)
[8]
QTextStream out(stdout)
[7]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QItemEditorFactory * factory
widget render & pixmap
QPainter painter(this)
[7]
aWidget window() -> setWindowTitle("New Window Title")
[2]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
QIcon::State state
Definition qicon_p.h:63
QIcon::Mode mode
Definition qicon_p.h:62