10#include "private/qfactoryloader_p.h"
11#include "private/qiconloader_p.h"
14#if QT_CONFIG(mimetype)
15#include <qmimedatabase.h>
26#include "private/qhexstring_p.h"
27#include "private/qguiapplication_p.h"
28#include "private/qoffsetstringarray_p.h"
29#include "qpa/qplatformtheme.h"
34using namespace Qt::StringLiterals;
40 ImageReader(
const QString &fileName, QSize size)
44 if (m_reader.supportsOption(QImageIOHandler::ScaledSize))
45 m_reader.setScaledSize(size);
48 QByteArray format()
const {
return m_reader.format(); }
49 bool supportsReadSize()
const {
return m_reader.supportsOption(QImageIOHandler::Size); }
50 QSize size()
const {
return m_reader.size(); }
51 bool jumpToNextImage() {
return m_reader.jumpToNextImage(); }
52 void jumpToImage(
int index) { m_reader.jumpToImage(index); }
54 bool read(QImage *image)
58 *image = m_reader.read();
59 if (!image->size().isValid()) {
63 m_atEnd = !m_reader.jumpToNextImage();
68 QImageReader m_reader;
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
97
98
99
100
101
102
103
104
108 Q_CONSTINIT
static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
109 return 1 + serial.fetchAndAddRelaxed(1);
114 struct IconCache :
public QCache<QString, QIcon>
124Q_GLOBAL_STATIC(IconCache, qtIconCache)
128 qtIconCache()->clear();
145
146
147
148
149
150
151
152
153
154
155qreal
QIconPrivate::pixmapDevicePixelRatio(qreal displayDevicePixelRatio,
const QSize &requestedSize,
const QSize &actualSize)
157 QSize targetSize = requestedSize * displayDevicePixelRatio;
158 if ((actualSize.width() == targetSize.width() && actualSize.height() <= targetSize.height()) ||
159 (actualSize.width() <= targetSize.width() && actualSize.height() == targetSize.height())) {
161 return displayDevicePixelRatio;
163 qreal scale = 0.5 * (qreal(actualSize.width()) / qreal(targetSize.width()) +
164 qreal(actualSize.height()) / qreal(targetSize.height()));
165 qreal dpr = qMax(qreal(1.0), displayDevicePixelRatio * scale);
166 return qRound(dpr * 100) / 100.0;
169QPixmapIconEngine::QPixmapIconEngine()
173QPixmapIconEngine::QPixmapIconEngine(
const QPixmapIconEngine &other)
174 : QIconEngine(other), pixmaps(other.pixmaps)
178QPixmapIconEngine::~QPixmapIconEngine()
182void QPixmapIconEngine::paint(QPainter *painter,
const QRect &rect, QIcon::Mode mode, QIcon::State state)
184 auto paintDevice = painter->device();
185 qreal dpr = paintDevice ? paintDevice->devicePixelRatio() : qApp->devicePixelRatio();
186 QPixmap px = scaledPixmap(rect.size(), mode, state, dpr);
187 painter->drawPixmap(rect, px);
190static inline qint64 area(
const QSize &s) {
return qint64(s.width()) * s.height(); }
200 const auto scaleA = pa->pixmap.devicePixelRatio();
201 const auto scaleB = pb->pixmap.devicePixelRatio();
203 if (scaleA != scaleB) {
208 qreal ascore = scaleA - scale;
209 qreal bscore = scaleB - scale;
212 if ((ascore < 0) != (bscore < 0))
213 return bscore < 0 ? pa : pb;
215 return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
218 qint64 s = area(size * scale);
219 if (pa->size == QSize() && pa->pixmap.isNull()) {
220 pa->pixmap = QPixmap(pa->fileName);
221 pa->size = pa->pixmap.size();
223 qint64 a = area(pa->size);
224 if (pb->size == QSize() && pb->pixmap.isNull()) {
225 pb->pixmap = QPixmap(pb->fileName);
226 pb->size = pb->pixmap.size();
228 qint64 b = area(pb->size);
239QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(
const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
241 QPixmapIconEngineEntry *pe =
nullptr;
242 for (
auto &entry : pixmaps) {
243 if (entry.mode == mode && entry.state == state) {
245 pe = bestSizeScaleMatch(size, scale, &entry, pe);
254QPixmapIconEngineEntry *QPixmapIconEngine::bestMatch(
const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
256 QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
258 QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On;
259 if (mode == QIcon::Disabled || mode == QIcon::Selected) {
260 QIcon::Mode oppositeMode = (mode == QIcon::Disabled) ? QIcon::Selected : QIcon::Disabled;
261 if ((pe = tryMatch(size, scale, QIcon::Normal, state)))
263 if ((pe = tryMatch(size, scale, QIcon::Active, state)))
265 if ((pe = tryMatch(size, scale, mode, oppositeState)))
267 if ((pe = tryMatch(size, scale, QIcon::Normal, oppositeState)))
269 if ((pe = tryMatch(size, scale, QIcon::Active, oppositeState)))
271 if ((pe = tryMatch(size, scale, oppositeMode, state)))
273 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
276 QIcon::Mode oppositeMode = (mode == QIcon::Normal) ? QIcon::Active : QIcon::Normal;
277 if ((pe = tryMatch(size, scale, oppositeMode, state)))
279 if ((pe = tryMatch(size, scale, mode, oppositeState)))
281 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
283 if ((pe = tryMatch(size, scale, QIcon::Disabled, state)))
285 if ((pe = tryMatch(size, scale, QIcon::Selected, state)))
287 if ((pe = tryMatch(size, scale, QIcon::Disabled, oppositeState)))
289 if ((pe = tryMatch(size, scale, QIcon::Selected, oppositeState)))
297 if (pe->pixmap.isNull()) {
299 QImage image, prevImage;
300 const QSize realSize = size * scale;
301 ImageReader imageReader(pe->fileName, realSize);
302 bool fittingImageFound =
false;
303 if (imageReader.supportsReadSize()) {
306 fittingImageFound = imageReader.size() == realSize;
307 }
while (!fittingImageFound && imageReader.jumpToNextImage());
309 if (!fittingImageFound) {
310 imageReader.jumpToImage(0);
311 while (imageReader.read(&image) && image.size() != realSize)
316 imageReader.read(&image);
318 if (!image.isNull()) {
319 pe->pixmap.convertFromImage(image);
320 if (!pe->pixmap.isNull()) {
321 pe->size = pe->pixmap.size();
322 pe->pixmap.setDevicePixelRatio(scale);
325 if (!pe->size.isValid()) {
326 removePixmapEntry(pe);
334QPixmap QPixmapIconEngine::pixmap(
const QSize &size, QIcon::Mode mode, QIcon::State state)
336 return scaledPixmap(size, mode, state, 1.0);
339QPixmap QPixmapIconEngine::scaledPixmap(
const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
342 QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state);
349 removePixmapEntry(pe);
350 if (pixmaps.isEmpty())
352 return scaledPixmap(size, mode, state, scale);
355 const auto actualSize = adjustSize(size * scale, pm.size());
356 const auto calculatedDpr = QIconPrivate::pixmapDevicePixelRatio(scale, size, actualSize);
357 QString key =
"qt_"_L1
358 % HexString<quint64>(pm.cacheKey())
359 % HexString<quint8>(pe->mode)
360 % HexString<quint64>(QGuiApplication::palette().cacheKey())
361 % HexString<uint>(actualSize.width())
362 % HexString<uint>(actualSize.height())
363 % HexString<quint16>(qRound(calculatedDpr * 1000));
365 if (mode == QIcon::Active) {
366 if (QPixmapCache::find(key % HexString<quint8>(mode), &pm))
368 if (QPixmapCache::find(key % HexString<quint8>(QIcon::Normal), &pm)) {
370 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
371 active =
static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(QIcon::Active, pm);
372 if (pm.cacheKey() == active.cacheKey())
377 if (!QPixmapCache::find(key % HexString<quint8>(mode), &pm)) {
378 if (pm.size() != actualSize)
379 pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
380 if (pe->mode != mode && mode != QIcon::Normal) {
381 QPixmap generated = pm;
382 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
383 generated =
static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, pm);
384 if (!generated.isNull())
387 pm.setDevicePixelRatio(calculatedDpr);
388 QPixmapCache::insert(key % HexString<quint8>(mode), pm);
393QSize QPixmapIconEngine::actualSize(
const QSize &size, QIcon::Mode mode, QIcon::State state)
402 if (QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state))
403 actualSize = pe->size;
405 return adjustSize(size, actualSize);
408QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
411 for (QPixmapIconEngineEntry &pe : pixmaps) {
412 if (pe.mode != mode || pe.state != state)
414 if (pe.size.isEmpty() && pe.pixmap.isNull()) {
415 pe.pixmap = QPixmap(pe.fileName);
416 pe.size = pe.pixmap.size();
418 if (!pe.size.isEmpty() && !sizes.contains(pe.size))
419 sizes.push_back(pe.size);
424void QPixmapIconEngine::addPixmap(
const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
426 if (!pixmap.isNull()) {
427 QPixmapIconEngineEntry *pe = tryMatch(pixmap.size() / pixmap.devicePixelRatio(),
428 pixmap.devicePixelRatio(), mode, state);
429 if (pe && pe->size == pixmap.size() && pe->pixmap.devicePixelRatio() == pixmap.devicePixelRatio()) {
431 pe->fileName.clear();
433 pixmaps += QPixmapIconEngineEntry(pixmap, mode, state);
441 const QString s = image.text(QStringLiteral(
"_q_icoOrigDepth"));
442 return s.isEmpty() ? 32 : s.toInt();
445static inline int findBySize(
const QList<QImage> &images,
const QSize &size)
447 for (qsizetype i = 0; i < images.size(); ++i) {
448 if (images.at(i).size() == size)
454void QPixmapIconEngine::addFile(
const QString &fileName,
const QSize &size, QIcon::Mode mode, QIcon::State state)
456 if (fileName.isEmpty())
458 const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath();
459 const bool ignoreSize = !size.isValid();
460 ImageReader imageReader(abs, size);
461 const QByteArray format = imageReader.format();
462 if (format.isEmpty())
465 if (format !=
"ico") {
467 if (imageReader.supportsReadSize()) {
469 pixmaps += QPixmapIconEngineEntry(abs, imageReader.size(), mode, state);
470 }
while (imageReader.jumpToNextImage());
472 while (imageReader.read(&image))
473 pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
476 pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
484 QList<QImage> icoImages;
485 while (imageReader.read(&image)) {
486 if (ignoreSize || image.size() == size) {
487 const int position = findBySize(icoImages, image.size());
489 if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
490 icoImages[position] = image;
492 icoImages.append(image);
496 for (
const QImage &i : std::as_const(icoImages))
497 pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
498 if (icoImages.isEmpty() && !ignoreSize)
499 pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
502bool QPixmapIconEngine::isNull()
504 return pixmaps.isEmpty();
507QString QPixmapIconEngine::key()
const
509 return "QPixmapIconEngine"_L1;
512QIconEngine *QPixmapIconEngine::clone()
const
514 return new QPixmapIconEngine(*
this);
517bool QPixmapIconEngine::read(QDataStream &in)
527 for (
int i=0; i < num_entries; ++i) {
538 addFile(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
540 QPixmapIconEngineEntry pe(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
548bool QPixmapIconEngine::write(QDataStream &out)
const
550 int num_entries = pixmaps.size();
552 for (
int i=0; i < num_entries; ++i) {
553 if (pixmaps.at(i).pixmap.isNull())
554 out << QPixmap(pixmaps.at(i).fileName);
556 out << pixmaps.at(i).pixmap;
557 out << pixmaps.at(i).fileName;
558 out << pixmaps.at(i).size;
559 out << (uint) pixmaps.at(i).mode;
560 out << (uint) pixmaps.at(i).state;
568QFactoryLoader *qt_iconEngineFactoryLoader()
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
755
756
757QIcon::QIcon()
noexcept
763
764
765QIcon::QIcon(
const QPixmap &pixmap)
772
773
774QIcon::QIcon(
const QIcon &other)
782
783
784
785
786
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806QIcon::QIcon(
const QString &fileName)
814
815
816
817QIcon::QIcon(QIconEngine *engine)
818 :d(
new QIconPrivate(engine))
823
824
827 if (d && !d->ref.deref())
832
833
834
835QIcon &QIcon::operator=(
const QIcon &other)
839 if (d && !d->ref.deref())
846
847
848
849
850
851
854
855
856
859
860
861QIcon::operator QVariant()
const
863 return QVariant::fromValue(*
this);
867
868
869
870
871
872
873
874
875
876
877
878qint64 QIcon::cacheKey()
const
882 return (((qint64) d->serialNum) << 32) | ((qint64) (d->detach_no));
886
887
888
889
890
891
892
893QPixmap QIcon::pixmap(
const QSize &size, Mode mode, State state)
const
897 const qreal dpr = -1;
898 return pixmap(size, dpr, mode, state);
902
903
904
905
906
907
908
909
912
913
914
915
916
917
918
919
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938QPixmap QIcon::pixmap(
const QSize &size, qreal devicePixelRatio, Mode mode, State state)
const
944 if (devicePixelRatio == -1)
945 devicePixelRatio = qApp->devicePixelRatio();
947 QPixmap pixmap = d->engine->scaledPixmap(size, mode, state, devicePixelRatio);
951 pixmap.setDevicePixelRatio(d->pixmapDevicePixelRatio(devicePixelRatio, size, pixmap.size()));
955#if QT_DEPRECATED_SINCE(6
, 0
)
957
958
959
960
961
962
963
964
965
966
967
968
970QPixmap QIcon::pixmap(QWindow *window,
const QSize &size, Mode mode, State state)
const
975 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
976 return pixmap(size, devicePixelRatio, mode, state);
982
983
984
985
986
987
988QSize QIcon::actualSize(
const QSize &size, Mode mode, State state)
const
993 const qreal devicePixelRatio = qApp->devicePixelRatio();
996 if (!(devicePixelRatio > 1.0))
997 return d->engine->actualSize(size, mode, state);
999 const QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
1000 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
1003#if QT_DEPRECATED_SINCE(6
, 0
)
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1017QSize QIcon::actualSize(QWindow *window,
const QSize &size, Mode mode, State state)
const
1022 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
1025 if (!(devicePixelRatio > 1.0))
1026 return d->engine->actualSize(size, mode, state);
1028 QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
1029 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
1034
1035
1036
1037
1038
1039void QIcon::paint(QPainter *painter,
const QRect &rect, Qt::Alignment alignment, Mode mode, State state)
const
1045 const QSize size = d->engine->actualSize(rect.size(), mode, state);
1046 alignment = QGuiApplicationPrivate::visualAlignment(painter->layoutDirection(), alignment);
1049 int w = size.width();
1050 int h = size.height();
1051 if ((alignment & Qt::AlignVCenter) == Qt::AlignVCenter)
1052 y += rect.size().height()/2 - h/2;
1053 else if ((alignment & Qt::AlignBottom) == Qt::AlignBottom)
1054 y += rect.size().height() - h;
1055 if ((alignment & Qt::AlignRight) == Qt::AlignRight)
1056 x += rect.size().width() - w;
1057 else if ((alignment & Qt::AlignHCenter) == Qt::AlignHCenter)
1058 x += rect.size().width()/2 - w/2;
1059 QRect alignedRect(x, y, w, h);
1061 d->engine->paint(painter, alignedRect, mode, state);
1065
1066
1067
1068
1069
1070
1071
1074
1075
1076
1077
1078
1079
1080
1081bool QIcon::isNull()
const
1083 return !d || d->engine->isNull();
1087
1088bool QIcon::isDetached()
const
1090 return !d || d->ref.loadRelaxed() == 1;
1094
1098 if (d->engine->isNull()) {
1099 if (!d->ref.deref())
1103 }
else if (d->ref.loadRelaxed() != 1) {
1104 QIconPrivate *x =
new QIconPrivate(d->engine->clone());
1105 if (!d->ref.deref())
1114
1115
1116
1117
1118
1119
1120
1121
1122void QIcon::addPixmap(
const QPixmap &pixmap, Mode mode, State state)
1124 if (pixmap.isNull())
1128 d =
new QIconPrivate(
new QPixmapIconEngine);
1129 d->engine->addPixmap(pixmap, mode, state);
1134 if (!suffix.isEmpty()) {
1135 const int index = iceLoader()->indexOf(suffix);
1137 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1138 return factory->create(fileName);
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175void QIcon::addFile(
const QString &fileName,
const QSize &size, Mode mode, State state)
1177 if (fileName.isEmpty())
1180 bool alreadyAdded =
false;
1183 QFileInfo info(fileName);
1184 QString suffix = info.suffix();
1185#if QT_CONFIG(mimetype)
1186 if (suffix.isEmpty())
1187 suffix = QMimeDatabase().mimeTypeForFile(info).preferredSuffix();
1189 QIconEngine *engine = iconEngineFromSuffix(fileName, suffix);
1191 alreadyAdded = !engine->isNull();
1192 d =
new QIconPrivate(engine ? engine :
new QPixmapIconEngine);
1195 d->engine->addFile(fileName, size, mode, state);
1197 if (d->engine->key() ==
"svg"_L1)
1201 QVarLengthArray<
int, 4> devicePixelRatios;
1202 const auto screens = qApp->screens();
1203 for (
const auto *screen : screens) {
1204 const auto dpr = qCeil(screen->devicePixelRatio());
1205 if (dpr >= 1 && !devicePixelRatios.contains(dpr))
1206 devicePixelRatios.push_back(dpr);
1208 std::sort(devicePixelRatios.begin(), devicePixelRatios.end(), std::greater<
int>());
1209 qreal sourceDevicePixelRatio = std::numeric_limits<qreal>::max();
1210 for (
const auto dpr : std::as_const(devicePixelRatios)) {
1211 if (dpr >= sourceDevicePixelRatio)
1213 const QString atNxFileName = qt_findAtNxFile(fileName, dpr, &sourceDevicePixelRatio);
1214 if (atNxFileName != fileName)
1215 d->engine->addFile(atNxFileName, size, mode, state);
1220
1221
1222
1223QList<QSize> QIcon::availableSizes(Mode mode, State state)
const
1225 if (!d || !d->engine)
1226 return QList<QSize>();
1227 return d->engine->availableSizes(mode, state);
1231
1232
1233
1234
1235
1236
1237
1238QString QIcon::name()
const
1240 if (!d || !d->engine)
1242 return d->engine->iconName();
1246
1247
1248
1249
1250
1251
1252
1253void QIcon::setThemeSearchPaths(
const QStringList &paths)
1255 QIconLoader::instance()->setThemeSearchPath(paths);
1259
1260
1261
1262
1263
1264
1265
1266QStringList QIcon::themeSearchPaths()
1268 return QIconLoader::instance()->themeSearchPaths();
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286QStringList QIcon::fallbackSearchPaths()
1288 return QIconLoader::instance()->fallbackSearchPaths();
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307void QIcon::setFallbackSearchPaths(
const QStringList &paths)
1309 QIconLoader::instance()->setFallbackSearchPaths(paths);
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328void QIcon::setThemeName(
const QString &name)
1330 QIconLoader::instance()->setThemeName(name);
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346QString QIcon::themeName()
1348 return QIconLoader::instance()->themeName();
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365QString QIcon::fallbackThemeName()
1367 return QIconLoader::instance()->fallbackThemeName();
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388void QIcon::setFallbackThemeName(
const QString &name)
1390 QIconLoader::instance()->setFallbackThemeName(name);
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414QIcon QIcon::fromTheme(
const QString &name)
1417 if (QIcon *cachedIcon = qtIconCache()->object(name))
1420 if (QDir::isAbsolutePath(name))
1423 QIcon icon(
new QThemeIconEngine(name));
1424 qtIconCache()->insert(name,
new QIcon(icon));
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452QIcon QIcon::fromTheme(
const QString &name,
const QIcon &fallback)
1454 QIcon icon = fromTheme(name);
1456 if (icon.isNull() || icon.availableSizes().isEmpty())
1463
1464
1465
1466
1467
1468
1469bool QIcon::hasThemeIcon(
const QString &name)
1471 QIcon icon = fromTheme(name);
1473 return icon.name() == name;
1485 "document-open-recent",
1486 "document-page-setup",
1488 "document-print-preview",
1489 "document-properties",
1504 "format-indent-less",
1505 "format-indent-more",
1506 "format-justify-center",
1507 "format-justify-fill",
1508 "format-justify-left",
1509 "format-justify-right",
1510 "format-text-direction-ltr",
1511 "format-text-direction-rtl",
1513 "format-text-italic",
1514 "format-text-underline",
1515 "format-text-strikethrough",
1529 "mail-mark-important",
1534 "mail-reply-sender",
1537 "media-playback-pause",
1538 "media-playback-start",
1539 "media-playback-stop",
1541 "media-seek-backward",
1542 "media-seek-forward",
1543 "media-skip-backward",
1544 "media-skip-forward",
1545 "object-rotate-left",
1546 "object-rotate-right",
1548 "system-lock-screen",
1553 "tools-check-spelling",
1564 "audio-input-microphone",
1579 "multimedia-player",
1587 "appointment-missed",
1589 "audio-volume-high",
1591 "audio-volume-medium",
1592 "audio-volume-muted",
1596 "dialog-information",
1600 "folder-drag-accept",
1609 "media-playlist-repeat",
1610 "media-playlist-shuffle",
1615 "software-update-available",
1616 "software-update-urgent",
1618 "sync-synchronizing",
1622 "weather-clear-night",
1623 "weather-few-clouds",
1624 "weather-few-clouds-night",
1630static_assert(QIcon::ThemeIcon::NThemeIcons == QIcon::ThemeIcon(themeIconMapping.count()));
1634 using ThemeIconIndex = std::underlying_type_t<QIcon::ThemeIcon>;
1635 const auto index =
static_cast<ThemeIconIndex>(icon);
1636 Q_ASSERT(index < themeIconMapping.count());
1637 return QLatin1StringView(themeIconMapping.viewAt(index));
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833bool QIcon::hasThemeIcon(QIcon::ThemeIcon icon)
1835 return hasThemeIcon(themeIconName(icon));
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861QIcon QIcon::fromTheme(QIcon::ThemeIcon icon)
1863 return fromTheme(themeIconName(icon));
1866QIcon QIcon::fromTheme(QIcon::ThemeIcon icon,
const QIcon &fallback)
1868 return fromTheme(themeIconName(icon), fallback);
1872
1873
1874
1875
1876
1877
1878void QIcon::setIsMask(
bool isMask)
1880 if (isMask == (d && d->is_mask))
1885 d =
new QIconPrivate(
new QPixmapIconEngine);
1886 d->is_mask = isMask;
1890
1891
1892
1893
1894
1895
1896
1897
1898bool QIcon::isMask()
const
1906
1907
1908#if !defined(QT_NO_DATASTREAM)
1910
1911
1912
1913
1914
1915
1916
1917
1919QDataStream &operator<<(QDataStream &s,
const QIcon &icon)
1921 if (s.version() >= QDataStream::Qt_4_3) {
1922 if (icon.isNull()) {
1925 s << icon.d->engine->key();
1926 icon.d->engine->write(s);
1928 }
else if (s.version() == QDataStream::Qt_4_2) {
1929 if (icon.isNull()) {
1932 QPixmapIconEngine *engine =
static_cast<QPixmapIconEngine *>(icon.d->engine);
1933 int num_entries = engine->pixmaps.size();
1935 for (
int i=0; i < num_entries; ++i) {
1936 s << engine->pixmaps.at(i).pixmap;
1937 s << engine->pixmaps.at(i).fileName;
1938 s << engine->pixmaps.at(i).size;
1939 s << (uint) engine->pixmaps.at(i).mode;
1940 s << (uint) engine->pixmaps.at(i).state;
1944 s << QPixmap(icon.pixmap(22,22));
1950
1951
1952
1953
1954
1955
1959 if (s.version() >= QDataStream::Qt_4_3) {
1963 if (key ==
"QPixmapIconEngine"_L1) {
1964 icon.d =
new QIconPrivate(
new QPixmapIconEngine);
1965 icon.d->engine->read(s);
1966 }
else if (key ==
"QIconLoaderEngine"_L1 || key ==
"QThemeIconEngine"_L1) {
1967 icon.d =
new QIconPrivate(
new QThemeIconEngine);
1968 icon.d->engine->read(s);
1970 const int index = iceLoader()->indexOf(key);
1972 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1973 if (QIconEngine *engine= factory->create()) {
1980 }
else if (s.version() == QDataStream::Qt_4_2) {
1990 for (
int i=0; i < num_entries; ++i) {
1997 icon.addFile(fileName, sz, QIcon::Mode(mode), QIcon::State(state));
1999 icon.addPixmap(pm, QIcon::Mode(mode), QIcon::State(state));
2011#ifndef QT_NO_DEBUG_STREAM
2014 QDebugStateSaver saver(dbg);
2021 if (!i.name().isEmpty())
2022 dbg << i.name() <<
',';
2023 dbg <<
"availableSizes[normal,Off]=" << i.availableSizes()
2024 <<
",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase;
2032
2033
2034
2037
2038
2039
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2054 qreal *sourceDevicePixelRatio)
2056 if (sourceDevicePixelRatio)
2057 *sourceDevicePixelRatio = 1;
2058 if (targetDevicePixelRatio <= 1.0)
2059 return baseFileName;
2061 static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty(
"QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
2062 if (disableNxImageLoading)
2063 return baseFileName;
2065 int dotIndex = baseFileName.lastIndexOf(u'.');
2066 if (dotIndex == -1) {
2067 dotIndex = baseFileName.size();
2068 }
else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9'
2069 && baseFileName[dotIndex - 2] == u'.') {
2074 QString atNxfileName = baseFileName;
2075 atNxfileName.insert(dotIndex,
"@2x"_L1);
2077 for (
int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) {
2078 atNxfileName[dotIndex + 1] = QLatin1Char(
'0' + n);
2079 if (QFile::exists(atNxfileName)) {
2080 if (sourceDevicePixelRatio)
2081 *sourceDevicePixelRatio = n;
2082 return atNxfileName;
2086 return baseFileName;
QIconPrivate(QIconEngine *e)
static void clearIconCache()
QString fileName() const
If the currently assigned device is a QFile, or if setFileName() has been called, this function retur...
QDataStream & operator>>(QDataStream &s, QKeyCombination &combination)
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
static void qt_cleanup_icon_cache()
static constexpr auto themeIconMapping
static int origIcoDepth(const QImage &image)
static qint64 area(const QSize &s)
static int nextSerialNumCounter()
static QIconEngine * iconEngineFromSuffix(const QString &fileName, const QString &suffix)
QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, qreal *sourceDevicePixelRatio)
static int findBySize(const QList< QImage > &images, const QSize &size)
static QPixmapIconEngineEntry * bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
static constexpr QLatin1StringView themeIconName(QIcon::ThemeIcon icon)
#define QIconEngineFactoryInterface_iid
Q_GLOBAL_STATIC_WITH_ARGS(PermissionStatusHash, g_permissionStatusHash,({ { qMetaTypeId< QCameraPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QMicrophonePermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QBluetoothPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QContactsPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QCalendarPermission >(), Qt::PermissionStatus::Undetermined }, { qMetaTypeId< QLocationPermission >(), Qt::PermissionStatus::Undetermined } }))