Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 "private/qoffsetstringarray_p.h"
29#include "qpa/qplatformtheme.h"
30
31#ifndef QT_NO_ICON
33
34using namespace Qt::StringLiterals;
35
70{
71 Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
72 return 1 + serial.fetchAndAddRelaxed(1);
73}
74
75static void qt_cleanup_icon_cache();
76namespace {
77 struct IconCache : public QCache<QString, QIcon>
78 {
79 IconCache()
80 {
81 // ### note: won't readd if QApplication is re-created!
83 }
84 };
85}
86
87Q_GLOBAL_STATIC(IconCache, qtIconCache)
88
90{
91 qtIconCache()->clear();
92}
93
95 : engine(e), ref(1),
96 serialNum(nextSerialNumCounter()),
97 detach_no(0),
98 is_mask(false)
99{
100}
101
106
118qreal QIconPrivate::pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize)
119{
120 QSize targetSize = requestedSize * displayDevicePixelRatio;
121 if ((actualSize.width() == targetSize.width() && actualSize.height() <= targetSize.height()) ||
122 (actualSize.width() <= targetSize.width() && actualSize.height() == targetSize.height())) {
123 // Correctly scaled for dpr, just having different aspect ratio
124 return displayDevicePixelRatio;
125 }
126 qreal scale = 0.5 * (qreal(actualSize.width()) / qreal(targetSize.width()) +
127 qreal(actualSize.height() / qreal(targetSize.height())));
128 return qMax(qreal(1.0), displayDevicePixelRatio *scale);
129}
130
134
139
143
145{
146 auto paintDevice = painter->device();
147 qreal dpr = paintDevice ? paintDevice->devicePixelRatio() : qApp->devicePixelRatio();
148 const QSize pixmapSize = rect.size() * dpr;
149 QPixmap px = scaledPixmap(pixmapSize, mode, state, dpr);
150 painter->drawPixmap(rect, px);
151}
152
153static inline int area(const QSize &s) { return s.width() * s.height(); }
154
155// Returns the smallest of the two that is still larger than or equal to size.
156// Pixmaps at the correct scale are preferred, pixmaps at lower scale are
157// used as fallbacks. We assume that the pixmap set is complete, in the sense
158// that no 2x pixmap is going to be a better match than a 3x pixmap for the the
159// target scale of 3 (It's OK if 3x pixmaps are missing - we'll fall back to
160// the 2x pixmaps then.)
162{
163 const auto scaleA = pa->pixmap.devicePixelRatio();
164 const auto scaleB = pb->pixmap.devicePixelRatio();
165 // scale: we can only differentiate on scale if the scale differs
166 if (scaleA != scaleB) {
167
168 // Score the pixmaps: 0 is an exact scale match, positive
169 // scores have more detail than requested, negative scores
170 // have less detail than requested.
171 qreal ascore = scaleA - scale;
172 qreal bscore = scaleB - scale;
173
174 // always prefer positive scores to prevent upscaling
175 if ((ascore < 0) != (bscore < 0))
176 return bscore < 0 ? pa : pb;
177 // Take the one closest to 0
178 return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
179 }
180
181 int s = area(size);
182 if (pa->size == QSize() && pa->pixmap.isNull()) {
183 pa->pixmap = QPixmap(pa->fileName);
184 pa->size = pa->pixmap.size();
185 }
186 int a = area(pa->size);
187 if (pb->size == QSize() && pb->pixmap.isNull()) {
188 pb->pixmap = QPixmap(pb->fileName);
189 pb->size = pb->pixmap.size();
190 }
191 int b = area(pb->size);
192 int res = a;
193 if (qMin(a,b) >= s)
194 res = qMin(a,b);
195 else
196 res = qMax(a,b);
197 if (res == a)
198 return pa;
199 return pb;
200}
201
202QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
203{
204 QPixmapIconEngineEntry *pe = nullptr;
205 for (auto &entry : pixmaps) {
206 if (entry.mode == mode && entry.state == state) {
207 if (pe)
208 pe = bestSizeScaleMatch(size, scale, &entry, pe);
209 else
210 pe = &entry;
211 }
212 }
213 return pe;
214}
215
216
218{
219 QPixmapIconEngineEntry *pe = tryMatch(size, scale, mode, state);
220 while (!pe){
221 QIcon::State oppositeState = (state == QIcon::On) ? QIcon::Off : QIcon::On;
224 if ((pe = tryMatch(size, scale, QIcon::Normal, state)))
225 break;
226 if ((pe = tryMatch(size, scale, QIcon::Active, state)))
227 break;
228 if ((pe = tryMatch(size, scale, mode, oppositeState)))
229 break;
230 if ((pe = tryMatch(size, scale, QIcon::Normal, oppositeState)))
231 break;
232 if ((pe = tryMatch(size, scale, QIcon::Active, oppositeState)))
233 break;
234 if ((pe = tryMatch(size, scale, oppositeMode, state)))
235 break;
236 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
237 break;
238 } else {
240 if ((pe = tryMatch(size, scale, oppositeMode, state)))
241 break;
242 if ((pe = tryMatch(size, scale, mode, oppositeState)))
243 break;
244 if ((pe = tryMatch(size, scale, oppositeMode, oppositeState)))
245 break;
246 if ((pe = tryMatch(size, scale, QIcon::Disabled, state)))
247 break;
248 if ((pe = tryMatch(size, scale, QIcon::Selected, state)))
249 break;
250 if ((pe = tryMatch(size, scale, QIcon::Disabled, oppositeState)))
251 break;
252 if ((pe = tryMatch(size, scale, QIcon::Selected, oppositeState)))
253 break;
254 }
255
256 if (!pe)
257 return pe;
258 }
259
260 if (sizeOnly ? (pe->size.isNull() || !pe->size.isValid()) : pe->pixmap.isNull()) {
261 pe->pixmap = QPixmap(pe->fileName);
262 if (!pe->pixmap.isNull())
263 pe->size = pe->pixmap.size();
264 }
265
266 return pe;
267}
268
273
275{
276
277 QPixmap pm;
279 if (pe)
280 pm = pe->pixmap;
281
282 if (pm.isNull()) {
283 auto idx = pixmaps.size();
284 while (--idx >= 0) {
285 if (pe == &pixmaps.at(idx)) {
286 pixmaps.remove(idx);
287 break;
288 }
289 }
290 if (pixmaps.isEmpty())
291 return pm;
292 else
293 return pixmap(size, mode, state);
294 }
295
296 QSize actualSize = pm.size();
297 if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
299
300 QString key = "qt_"_L1
301 % HexString<quint64>(pm.cacheKey())
302 % HexString<uint>(pe ? pe->mode : QIcon::Normal)
303 % HexString<quint64>(QGuiApplication::palette().cacheKey())
304 % HexString<uint>(actualSize.width())
305 % HexString<uint>(actualSize.height());
306
307 if (mode == QIcon::Active) {
308 if (QPixmapCache::find(key % HexString<uint>(mode), &pm))
309 return pm; // horray
310 if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), &pm)) {
311 QPixmap active = pm;
312 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
313 active = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(QIcon::Active, pm);
314 if (pm.cacheKey() == active.cacheKey())
315 return pm;
316 }
317 }
318
319 if (!QPixmapCache::find(key % HexString<uint>(mode), &pm)) {
320 if (pm.size() != actualSize)
322 if (pe->mode != mode && mode != QIcon::Normal) {
323 QPixmap generated = pm;
324 if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
325 generated = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(mode, pm);
326 if (!generated.isNull())
327 pm = generated;
328 }
329 QPixmapCache::insert(key % HexString<uint>(mode), pm);
330 }
331 return pm;
332}
333
335{
337
338 // The returned actual size is the size in device independent pixels,
339 // so we limit the search to scale 1 and assume that e.g. @2x versions
340 // does not proviode extra actual sizes not also provided by the 1x versions.
341 qreal scale = 1;
342
344 actualSize = pe->size;
345
346 if (actualSize.isNull())
347 return actualSize;
348
349 if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
351 return actualSize;
352}
353
355{
356 QList<QSize> sizes;
357 for (QPixmapIconEngineEntry &pe : pixmaps) {
358 if (pe.mode != mode || pe.state != state)
359 continue;
360 if (pe.size.isEmpty() && pe.pixmap.isNull()) {
361 pe.pixmap = QPixmap(pe.fileName);
362 pe.size = pe.pixmap.size();
363 }
364 if (!pe.size.isEmpty() && !sizes.contains(pe.size))
365 sizes.push_back(pe.size);
366 }
367 return sizes;
368}
369
371{
372 if (!pixmap.isNull()) {
373 QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), pixmap.devicePixelRatio(), mode, state);
374 if (pe && pe->size == pixmap.size() && pe->pixmap.devicePixelRatio() == pixmap.devicePixelRatio()) {
375 pe->pixmap = pixmap;
376 pe->fileName.clear();
377 } else {
379 }
380 }
381}
382
383// Read out original image depth as set by ICOReader
384static inline int origIcoDepth(const QImage &image)
385{
386 const QString s = image.text(QStringLiteral("_q_icoOrigDepth"));
387 return s.isEmpty() ? 32 : s.toInt();
388}
389
390static inline int findBySize(const QList<QImage> &images, const QSize &size)
391{
392 for (qsizetype i = 0; i < images.size(); ++i) {
393 if (images.at(i).size() == size)
394 return i;
395 }
396 return -1;
397}
398
399// Convenience class providing a bool read() function.
400namespace {
401class ImageReader
402{
403public:
404 ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
405
406 QByteArray format() const { return m_reader.format(); }
407
408 bool read(QImage *image)
409 {
410 if (m_atEnd)
411 return false;
412 *image = m_reader.read();
413 if (!image->size().isValid()) {
414 m_atEnd = true;
415 return false;
416 }
417 m_atEnd = !m_reader.jumpToNextImage();
418 return true;
419 }
420
421private:
422 QImageReader m_reader;
423 bool m_atEnd;
424};
425} // namespace
426
428{
429 if (fileName.isEmpty())
430 return;
432 const bool ignoreSize = !size.isValid();
433 ImageReader imageReader(abs);
434 const QByteArray format = imageReader.format();
435 if (format.isEmpty()) // Device failed to open or unsupported format.
436 return;
438 if (format != "ico") {
439 if (ignoreSize) { // No size specified: Add all images.
440 while (imageReader.read(&image))
441 pixmaps += QPixmapIconEngineEntry(abs, image, mode, state);
442 } else {
443 // Try to match size. If that fails, add a placeholder with the filename and empty pixmap for the size.
444 while (imageReader.read(&image) && image.size() != size) {}
445 pixmaps += image.size() == size ?
447 }
448 return;
449 }
450 // Special case for reading Windows ".ico" files. Historically (QTBUG-39287),
451 // these files may contain low-resolution images. As this information is lost,
452 // ICOReader sets the original format as an image text key value. Read all matching
453 // images into a list trying to find the highest quality per size.
454 QList<QImage> icoImages;
455 while (imageReader.read(&image)) {
456 if (ignoreSize || image.size() == size) {
457 const int position = findBySize(icoImages, image.size());
458 if (position >= 0) { // Higher quality available? -> replace.
459 if (origIcoDepth(image) > origIcoDepth(icoImages.at(position)))
460 icoImages[position] = image;
461 } else {
462 icoImages.append(image);
463 }
464 }
465 }
466 for (const QImage &i : std::as_const(icoImages))
467 pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
468 if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
469 pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
470}
471
473{
474 return pixmaps.isEmpty();
475}
476
478{
479 return "QPixmapIconEngine"_L1;
480}
481
483{
484 return new QPixmapIconEngine(*this);
485}
486
488{
489 int num_entries;
490 QPixmap pm;
492 QSize sz;
493 uint mode;
494 uint state;
495
496 in >> num_entries;
497 for (int i=0; i < num_entries; ++i) {
498 if (in.atEnd()) {
499 pixmaps.clear();
500 return false;
501 }
502 in >> pm;
503 in >> fileName;
504 in >> sz;
505 in >> mode;
506 in >> state;
507 if (pm.isNull()) {
509 } else {
511 pe.pixmap = pm;
512 pixmaps += pe;
513 }
514 }
515 return true;
516}
517
519{
520 int num_entries = pixmaps.size();
521 out << num_entries;
522 for (int i=0; i < num_entries; ++i) {
523 if (pixmaps.at(i).pixmap.isNull())
524 out << QPixmap(pixmaps.at(i).fileName);
525 else
526 out << pixmaps.at(i).pixmap;
527 out << pixmaps.at(i).fileName;
528 out << pixmaps.at(i).size;
529 out << (uint) pixmaps.at(i).mode;
530 out << (uint) pixmaps.at(i).state;
531 }
532 return true;
533}
534
537
539{
540 return iceLoader();
541}
542
543
694QIcon::QIcon() noexcept
695 : d(nullptr)
696{
697}
698
703 :d(nullptr)
704{
706}
707
712 :d(other.d)
713{
714 if (d)
715 d->ref.ref();
716}
717
744 : d(nullptr)
745{
747}
748
749
758
763{
764 if (d && !d->ref.deref())
765 delete d;
766}
767
773{
774 if (other.d)
775 other.d->ref.ref();
776 if (d && !d->ref.deref())
777 delete d;
778 d = other.d;
779 return *this;
780}
781
801QIcon::operator QVariant() const
802{
803 return QVariant::fromValue(*this);
804}
805
820{
821 if (!d)
822 return 0;
823 return (((qint64) d->serialNum) << 32) | ((qint64) (d->detach_no));
824}
825
835{
836 if (!d)
837 return QPixmap();
838 const qreal dpr = -1; // don't know target dpr
839 return pixmap(size, dpr, mode, state);
840}
841
871QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, State state) const
872{
873 if (!d)
874 return QPixmap();
875
876 // Use the global devicePixelRatio if the caller does not know the target dpr
877 if (devicePixelRatio == -1)
878 devicePixelRatio = qApp->devicePixelRatio();
879
880 // Handle the simple normal-dpi case
881 if (!(devicePixelRatio > 1.0)) {
883 pixmap.setDevicePixelRatio(1.0);
884 return pixmap;
885 }
886
887 // Try get a pixmap that is big enough to be displayed at device pixel resolution.
888 QPixmap pixmap = d->engine->scaledPixmap(size * devicePixelRatio, mode, state, devicePixelRatio);
889 pixmap.setDevicePixelRatio(d->pixmapDevicePixelRatio(devicePixelRatio, size, pixmap.size()));
890 return pixmap;
891}
892
893#if QT_DEPRECATED_SINCE(6, 0)
909{
910 if (!d)
911 return QPixmap();
912
913 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
914 return pixmap(size, devicePixelRatio, mode, state);
915}
916#endif
917
918
927{
928 if (!d)
929 return QSize();
930
931 const qreal devicePixelRatio = qApp->devicePixelRatio();
932
933 // Handle the simple normal-dpi case:
934 if (!(devicePixelRatio > 1.0))
935 return d->engine->actualSize(size, mode, state);
936
937 const QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
938 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
939}
940
941#if QT_DEPRECATED_SINCE(6, 0)
956{
957 if (!d)
958 return QSize();
959
960 qreal devicePixelRatio = window ? window->devicePixelRatio() : qApp->devicePixelRatio();
961
962 // Handle the simple normal-dpi case:
963 if (!(devicePixelRatio > 1.0))
964 return d->engine->actualSize(size, mode, state);
965
966 QSize actualSize = d->engine->actualSize(size * devicePixelRatio, mode, state);
967 return actualSize / d->pixmapDevicePixelRatio(devicePixelRatio, size, actualSize);
968}
969#endif
970
977void QIcon::paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, Mode mode, State state) const
978{
979 if (!d || !painter)
980 return;
981
982 // Copy of QStyle::alignedRect
983 const QSize size = d->engine->actualSize(rect.size(), mode, state);
985 int x = rect.x();
986 int y = rect.y();
987 int w = size.width();
988 int h = size.height();
990 y += rect.size().height()/2 - h/2;
992 y += rect.size().height() - h;
994 x += rect.size().width() - w;
996 x += rect.size().width()/2 - w/2;
997 QRect alignedRect(x, y, w, h);
998
1000}
1001
1019bool QIcon::isNull() const
1020{
1021 return !d || d->engine->isNull();
1022}
1023
1027{
1028 return !d || d->ref.loadRelaxed() == 1;
1029}
1030
1034{
1035 if (d) {
1036 if (d->engine->isNull()) {
1037 if (!d->ref.deref())
1038 delete d;
1039 d = nullptr;
1040 return;
1041 } else if (d->ref.loadRelaxed() != 1) {
1042 QIconPrivate *x = new QIconPrivate(d->engine->clone());
1043 if (!d->ref.deref())
1044 delete d;
1045 d = x;
1046 }
1047 ++d->detach_no;
1048 }
1049}
1050
1061{
1062 if (pixmap.isNull())
1063 return;
1064 detach();
1065 if (!d)
1066 d = new QIconPrivate(new QPixmapIconEngine);
1068}
1069
1071{
1072 if (!suffix.isEmpty()) {
1073 const int index = iceLoader()->indexOf(suffix);
1074 if (index != -1) {
1075 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1076 return factory->create(fileName);
1077 }
1078 }
1079 }
1080 return nullptr;
1081}
1082
1114{
1115 if (fileName.isEmpty())
1116 return;
1117 detach();
1118 if (!d) {
1119
1121 QString suffix = info.suffix();
1122#if QT_CONFIG(mimetype)
1123 if (suffix.isEmpty())
1124 suffix = QMimeDatabase().mimeTypeForFile(info).preferredSuffix(); // determination from contents
1125#endif // mimetype
1128 }
1129
1131
1132 // Check if a "@Nx" file exists and add it.
1133 QString atNxFileName = qt_findAtNxFile(fileName, qApp->devicePixelRatio());
1134 if (atNxFileName != fileName)
1135 d->engine->addFile(atNxFileName, size, mode, state);
1136}
1137
1145{
1146 if (!d || !d->engine)
1147 return QList<QSize>();
1148 return d->engine->availableSizes(mode, state);
1149}
1150
1162{
1163 if (!d || !d->engine)
1164 return QString();
1165 return d->engine->iconName();
1166}
1167
1179{
1180 QIconLoader::instance()->setThemeSearchPath(paths);
1181}
1182
1194{
1195 return QIconLoader::instance()->themeSearchPaths();
1196}
1197
1214{
1215 return QIconLoader::instance()->fallbackSearchPaths();
1216}
1217
1235{
1236 QIconLoader::instance()->setFallbackSearchPaths(paths);
1237}
1238
1255{
1256 QIconLoader::instance()->setThemeName(name);
1257}
1258
1275{
1276 return QIconLoader::instance()->themeName();
1277}
1278
1294{
1295 return QIconLoader::instance()->fallbackThemeName();
1296}
1297
1317{
1318 QIconLoader::instance()->setFallbackThemeName(name);
1319}
1320
1345{
1346
1347 if (QIcon *cachedIcon = qtIconCache()->object(name))
1348 return *cachedIcon;
1349
1351 return QIcon(name);
1352
1354 qtIconCache()->insert(name, new QIcon(icon));
1355 return icon;
1356}
1357
1382QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
1383{
1385
1386 if (icon.isNull() || icon.availableSizes().isEmpty())
1387 return fallback;
1388
1389 return icon;
1390}
1391
1402{
1404
1405 return icon.name() == name;
1406}
1407
1408static constexpr auto themeIconMapping = qOffsetStringArray(
1409 "address-book-new",
1410 "application-exit",
1411 "appointment-new",
1412 "call-start",
1413 "call-stop",
1414 "contact-new",
1415 "document-new",
1416 "document-open",
1417 "document-open-recent",
1418 "document-page-setup",
1419 "document-print",
1420 "document-print-preview",
1421 "document-properties",
1422 "document-revert",
1423 "document-save",
1424 "document-save-as",
1425 "document-send",
1426 "edit-clear",
1427 "edit-copy",
1428 "edit-cut",
1429 "edit-delete",
1430 "edit-find",
1431 "edit-paste",
1432 "edit-redo",
1433 "edit-select-all",
1434 "edit-undo",
1435 "folder-new",
1436 "format-indent-less",
1437 "format-indent-more",
1438 "format-justify-center",
1439 "format-justify-fill",
1440 "format-justify-left",
1441 "format-justify-right",
1442 "format-text-direction-ltr",
1443 "format-text-direction-rtl",
1444 "format-text-bold",
1445 "format-text-italic",
1446 "format-text-underline",
1447 "format-text-strikethrough",
1448 "go-down",
1449 "go-home",
1450 "go-next",
1451 "go-previous",
1452 "go-up",
1453 "help-about",
1454 "help-faq",
1455 "insert-image",
1456 "insert-link",
1457 "insert-text",
1458 "list-add",
1459 "list-remove",
1460 "mail-forward",
1461 "mail-mark-important",
1462 "mail-mark-read",
1463 "mail-mark-unread",
1464 "mail-message-new",
1465 "mail-reply-all",
1466 "mail-reply-sender",
1467 "mail-send",
1468 "media-eject",
1469 "media-playback-pause",
1470 "media-playback-start",
1471 "media-playback-stop",
1472 "media-record",
1473 "media-seek-backward",
1474 "media-seek-forward",
1475 "media-skip-backward",
1476 "media-skip-forward",
1477 "object-rotate-left",
1478 "object-rotate-right",
1479 "process-stop",
1480 "system-lock-screen",
1481 "system-log-out",
1482 "system-search",
1483 "system-reboot",
1484 "system-shutdown",
1485 "tools-check-spelling",
1486 "view-fullscreen",
1487 "view-refresh",
1488 "view-restore",
1489 "window-close",
1490 "window-new",
1491 "zoom-fit-best",
1492 "zoom-in",
1493 "zoom-out",
1494
1495 "audio-card",
1496 "audio-input-microphone",
1497 "battery",
1498 "camera-photo",
1499 "camera-video",
1500 "camera-web",
1501 "computer",
1502 "drive-harddisk",
1503 "drive-optical",
1504 "input-gaming",
1505 "input-keyboard",
1506 "input-mouse",
1507 "input-tablet",
1508 "media-flash",
1509 "media-optical",
1510 "media-tape",
1511 "multimedia-player",
1512 "network-wired",
1513 "network-wireless",
1514 "phone",
1515 "printer",
1516 "scanner",
1517 "video-display",
1518
1519 "appointment-missed",
1520 "appointment-soon",
1521 "audio-volume-high",
1522 "audio-volume-low",
1523 "audio-volume-medium",
1524 "audio-volume-muted",
1525 "battery-caution",
1526 "battery-low",
1527 "dialog-error",
1528 "dialog-information",
1529 "dialog-password",
1530 "dialog-question",
1531 "dialog-warning",
1532 "folder-drag-accept",
1533 "folder-open",
1534 "folder-visiting",
1535 "image-loading",
1536 "image-missing",
1537 "mail-attachment",
1538 "mail-unread",
1539 "mail-read",
1540 "mail-replied",
1541 "media-playlist-repeat",
1542 "media-playlist-shuffle",
1543 "network-offline",
1544 "printer-printing",
1545 "security-high",
1546 "security-low",
1547 "software-update-available",
1548 "software-update-urgent",
1549 "sync-error",
1550 "sync-synchronizing",
1551 "user-available",
1552 "user-offline",
1553 "weather-clear",
1554 "weather-clear-night",
1555 "weather-few-clouds",
1556 "weather-few-clouds-night",
1557 "weather-fog",
1558 "weather-showers",
1559 "weather-snow",
1560 "weather-storm"
1561);
1563
1565{
1566 using ThemeIconIndex = std::underlying_type_t<QIcon::ThemeIcon>;
1567 const auto index = static_cast<ThemeIconIndex>(icon);
1568 Q_ASSERT(index < themeIconMapping.count());
1570}
1571
1769
1797
1799{
1800 return fromTheme(themeIconName(icon), fallback);
1801}
1802
1810void QIcon::setIsMask(bool isMask)
1811{
1812 detach();
1813 if (!d)
1814 d = new QIconPrivate(new QPixmapIconEngine);
1815 d->is_mask = isMask;
1816}
1817
1827bool QIcon::isMask() const
1828{
1829 if (!d)
1830 return false;
1831 return d->is_mask;
1832}
1833
1834/*****************************************************************************
1835 QIcon stream functions
1836 *****************************************************************************/
1837#if !defined(QT_NO_DATASTREAM)
1850{
1851 if (s.version() >= QDataStream::Qt_4_3) {
1852 if (icon.isNull()) {
1853 s << QString();
1854 } else {
1855 s << icon.d->engine->key();
1856 icon.d->engine->write(s);
1857 }
1858 } else if (s.version() == QDataStream::Qt_4_2) {
1859 if (icon.isNull()) {
1860 s << 0;
1861 } else {
1863 int num_entries = engine->pixmaps.size();
1864 s << num_entries;
1865 for (int i=0; i < num_entries; ++i) {
1866 s << engine->pixmaps.at(i).pixmap;
1867 s << engine->pixmaps.at(i).fileName;
1868 s << engine->pixmaps.at(i).size;
1869 s << (uint) engine->pixmaps.at(i).mode;
1870 s << (uint) engine->pixmaps.at(i).state;
1871 }
1872 }
1873 } else {
1874 s << QPixmap(icon.pixmap(22,22));
1875 }
1876 return s;
1877}
1878
1889{
1890 if (s.version() >= QDataStream::Qt_4_3) {
1891 icon = QIcon();
1892 QString key;
1893 s >> key;
1894 if (key == "QPixmapIconEngine"_L1) {
1895 icon.d = new QIconPrivate(new QPixmapIconEngine);
1896 icon.d->engine->read(s);
1897 } else if (key == "QIconLoaderEngine"_L1 || key == "QThemeIconEngine"_L1) {
1898 icon.d = new QIconPrivate(new QThemeIconEngine);
1899 icon.d->engine->read(s);
1900 } else {
1901 const int index = iceLoader()->indexOf(key);
1902 if (index != -1) {
1903 if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
1904 if (QIconEngine *engine= factory->create()) {
1905 icon.d = new QIconPrivate(engine);
1906 engine->read(s);
1907 } // factory
1908 } // instance
1909 } // index
1910 }
1911 } else if (s.version() == QDataStream::Qt_4_2) {
1912 icon = QIcon();
1913 int num_entries;
1914 QPixmap pm;
1916 QSize sz;
1917 uint mode;
1918 uint state;
1919
1920 s >> num_entries;
1921 for (int i=0; i < num_entries; ++i) {
1922 s >> pm;
1923 s >> fileName;
1924 s >> sz;
1925 s >> mode;
1926 s >> state;
1927 if (pm.isNull())
1929 else
1931 }
1932 } else {
1933 QPixmap pm;
1934 s >> pm;
1935 icon.addPixmap(pm);
1936 }
1937 return s;
1938}
1939
1940#endif //QT_NO_DATASTREAM
1941
1942#ifndef QT_NO_DEBUG_STREAM
1944{
1945 QDebugStateSaver saver(dbg);
1946 dbg.resetFormat();
1947 dbg.nospace();
1948 dbg << "QIcon(";
1949 if (i.isNull()) {
1950 dbg << "null";
1951 } else {
1952 if (!i.name().isEmpty())
1953 dbg << i.name() << ',';
1954 dbg << "availableSizes[normal,Off]=" << i.availableSizes()
1955 << ",cacheKey=" << Qt::showbase << Qt::hex << i.cacheKey() << Qt::dec << Qt::noshowbase;
1956 }
1957 dbg << ')';
1958 return dbg;
1959}
1960#endif
1961
1984QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
1985 qreal *sourceDevicePixelRatio)
1986{
1987 if (targetDevicePixelRatio <= 1.0)
1988 return baseFileName;
1989
1990 static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
1991 if (disableNxImageLoading)
1992 return baseFileName;
1993
1994 int dotIndex = baseFileName.lastIndexOf(u'.');
1995 if (dotIndex == -1) { /* no dot */
1996 dotIndex = baseFileName.size(); /* append */
1997 } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9'
1998 && baseFileName[dotIndex - 2] == u'.') {
1999 // If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it.
2000 dotIndex -= 2;
2001 }
2002
2003 QString atNxfileName = baseFileName;
2004 atNxfileName.insert(dotIndex, "@2x"_L1);
2005 // Check for @Nx, ..., @3x, @2x file versions,
2006 for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) {
2007 atNxfileName[dotIndex + 1] = QLatin1Char('0' + n);
2008 if (QFile::exists(atNxfileName)) {
2009 if (sourceDevicePixelRatio)
2010 *sourceDevicePixelRatio = n;
2011 return atNxfileName;
2012 }
2013 }
2014
2015 return baseFileName;
2016}
2017
2019#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:46
\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:184
QString absoluteFilePath() const
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.
static QIconLoader * instance()
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:94
int detach_no
Definition qicon_p.h:43
static void clearIconCache()
Definition qicon.cpp:102
qreal pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize)
Definition qicon.cpp:118
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
static bool hasThemeIcon(const QString &name)
Definition qicon.cpp:1401
void setIsMask(bool isMask)
Definition qicon.cpp:1810
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:977
~QIcon()
Destroys the icon.
Definition qicon.cpp:762
static QString themeName()
Definition qicon.cpp:1274
static void setFallbackSearchPaths(const QStringList &paths)
Definition qicon.cpp:1234
static void setThemeName(const QString &path)
Definition qicon.cpp:1254
static QStringList fallbackSearchPaths()
Definition qicon.cpp:1213
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:1060
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:1019
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:1144
static void setThemeSearchPaths(const QStringList &searchpath)
Definition qicon.cpp:1178
qint64 cacheKey() const
Returns a number that identifies the contents of this QIcon object.
Definition qicon.cpp:819
bool isMask() const
Definition qicon.cpp:1827
static void setFallbackThemeName(const QString &name)
Definition qicon.cpp:1316
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:1113
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:1193
QString name() const
Definition qicon.cpp:1161
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:926
ThemeIcon
Definition qicon.h:25
void detach()
Definition qicon.cpp:1033
bool isDetached() const
Definition qicon.cpp:1026
QIcon & operator=(const QIcon &other)
Assigns the other icon to this icon and returns a reference to this icon.
Definition qicon.cpp:772
static QString fallbackThemeName()
Definition qicon.cpp:1293
QIcon() noexcept
Constructs a null icon.
Definition qicon.cpp:694
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:834
static QIcon fromTheme(const QString &name)
Definition qicon.cpp:1344
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.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void remove(qsizetype i, qsizetype n=1)
Definition qlist.h:794
void clear()
Definition qlist.h:434
\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:150
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.
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:487
QList< QSize > availableSizes(QIcon::Mode mode, QIcon::State state) override
Definition qicon.cpp:354
QString key() const override
\variable QIconEngine::ScaledPixmapArgument::size
Definition qicon.cpp:477
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override
Called by QIcon::addPixmap().
Definition qicon.cpp:370
QIconEngine * clone() const override
Reimplement this method to return a clone of this icon engine.
Definition qicon.cpp:482
bool write(QDataStream &out) const override
Writes the contents of this engine to the QDataStream out.
Definition qicon.cpp:518
bool isNull() override
Definition qicon.cpp:472
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override
Definition qicon.cpp:274
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:144
QPixmapIconEngineEntry * bestMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state, bool sizeOnly)
Definition qicon.cpp:217
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:334
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:269
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override
Called by QIcon::addFile().
Definition qicon.cpp:427
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:493
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition qpixmap.cpp:456
qreal devicePixelRatio() const
Returns the device pixel ratio for the pixmap.
Definition qpixmap.cpp:576
qint64 cacheKey() const
Returns a number that identifies this QPixmap.
Definition qpixmap.cpp:884
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
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:145
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
Definition qsize.h:121
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5455
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QString & insert(qsizetype i, QChar c)
Definition qstring.cpp:3132
A named-based icon engine for providing theme icons.
\inmodule QtCore
Definition qvariant.h:65
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:536
\inmodule QtGui
Definition qwindow.h:63
rect
[4]
uint alignment
else opt state
[0]
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignBottom
Definition qnamespace.h:154
@ AlignVCenter
Definition qnamespace.h:155
@ AlignHCenter
Definition qnamespace.h:148
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:89
static constexpr auto themeIconMapping
Definition qicon.cpp:1408
static int origIcoDepth(const QImage &image)
Definition qicon.cpp:384
static int area(const QSize &s)
Definition qicon.cpp:153
static int nextSerialNumCounter()
Definition qicon.cpp:69
QDataStream & operator>>(QDataStream &s, QIcon &icon)
Definition qicon.cpp:1888
static QIconEngine * iconEngineFromSuffix(const QString &fileName, const QString &suffix)
Definition qicon.cpp:1070
QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, qreal *sourceDevicePixelRatio)
Definition qicon.cpp:1984
static int findBySize(const QList< QImage > &images, const QSize &size)
Definition qicon.cpp:390
static QPixmapIconEngineEntry * bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
Definition qicon.cpp:161
static constexpr QLatin1StringView themeIconName(QIcon::ThemeIcon icon)
Definition qicon.cpp:1564
QDataStream & operator<<(QDataStream &s, const QIcon &icon)
Definition qicon.cpp:1849
Q_GUI_EXPORT QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, qreal *sourceDevicePixelRatio=nullptr)
Definition qicon.cpp:1984
#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
constexpr auto qOffsetStringArray(const char(&...strings)[Nx]) noexcept
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
GLdouble s
[6]
Definition qopenglext.h:235
GLuint res
GLuint entry
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLuint in
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 Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
double qreal
Definition qtypes.h:187
ReturnedValue read(const char *data)
QList< QImage > images
[6]
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]
QHostInfo info
[0]
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:18
QIcon::State state
Definition qicon_p.h:62
QIcon::Mode mode
Definition qicon_p.h:61