diff options
Diffstat (limited to 'src/gui/image/qicon.cpp')
-rw-r--r-- | src/gui/image/qicon.cpp | 774 |
1 files changed, 602 insertions, 172 deletions
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index af28c8a0ec..086ac37a07 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qicon.h" #include "qicon_p.h" @@ -61,11 +25,14 @@ #include "private/qhexstring_p.h" #include "private/qguiapplication_p.h" +#include "private/qoffsetstringarray_p.h" #include "qpa/qplatformtheme.h" #ifndef QT_NO_ICON QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + /*! \enum QIcon::Mode @@ -101,7 +68,7 @@ QT_BEGIN_NAMESPACE static int nextSerialNumCounter() { - static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0); + Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0); return 1 + serial.fetchAndAddRelaxed(1); } @@ -132,6 +99,11 @@ QIconPrivate::QIconPrivate(QIconEngine *e) { } +void QIconPrivate::clearIconCache() +{ + qt_cleanup_icon_cache(); +} + /*! \internal Computes the displayDevicePixelRatio for a pixmap. @@ -192,12 +164,15 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale // scale: we can only differentiate on scale if the scale differs if (pa->scale != pb->scale) { - // Score the pixmaps: 0 is an exact scale match, postive + // Score the pixmaps: 0 is an exact scale match, positive // scores have more detail than requested, negative scores - // have less detail than rquested. + // have less detail than requested. qreal ascore = pa->scale - scale; qreal bscore = pb->scale - scale; + // always prefer positive scores to prevent upscaling + if ((ascore < 0) != (bscore < 0)) + return bscore < 0 ? pa : pb; // Take the one closest to 0 return (qAbs(ascore) < qAbs(bscore)) ? pa : pb; } @@ -226,7 +201,7 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state) { QPixmapIconEngineEntry *pe = nullptr; - for (int i = 0; i < pixmaps.count(); ++i) + for (int i = 0; i < pixmaps.size(); ++i) if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) { if (pe) pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe); @@ -303,7 +278,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc pm = pe->pixmap; if (pm.isNull()) { - int idx = pixmaps.count(); + int idx = pixmaps.size(); while (--idx >= 0) { if (pe == &pixmaps.at(idx)) { pixmaps.remove(idx); @@ -320,7 +295,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height())) actualSize.scale(size, Qt::KeepAspectRatio); - QString key = QLatin1String("qt_") + QString key = "qt_"_L1 % HexString<quint64>(pm.cacheKey()) % HexString<uint>(pe ? pe->mode : QIcon::Normal) % HexString<quint64>(QGuiApplication::palette().cacheKey()) @@ -358,7 +333,7 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon:: { QSize actualSize; - // The returned actiual size is the size in device independent pixels, + // The returned actual size is the size in device independent pixels, // so we limit the search to scale 1 and assume that e.g. @2x versions // does not proviode extra actual sizes not also provided by the 1x versions. qreal scale = 1; @@ -377,15 +352,16 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon:: QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state) { QList<QSize> sizes; - for (int i = 0; i < pixmaps.size(); ++i) { - QPixmapIconEngineEntry &pe = pixmaps[i]; - if (pe.size == QSize() && pe.pixmap.isNull()) { + for (QPixmapIconEngineEntry &pe : pixmaps) { + if (pe.mode != mode || pe.state != state) + continue; + if (pe.size.isEmpty() && pe.pixmap.isNull()) { pe.pixmap = QPixmap(pe.fileName); pe.size = pe.pixmap.size(); } - if (pe.mode == mode && pe.state == state && !pe.size.isEmpty()) + if (!pe.size.isEmpty() && !sizes.contains(pe.size)) sizes.push_back(pe.size); - } + } return sizes; } @@ -450,7 +426,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco { if (fileName.isEmpty()) return; - const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath(); + const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath(); const bool ignoreSize = !size.isValid(); ImageReader imageReader(abs); const QByteArray format = imageReader.format(); @@ -485,15 +461,20 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco } } } - for (const QImage &i : qAsConst(icoImages)) + for (const QImage &i : std::as_const(icoImages)) pixmaps += QPixmapIconEngineEntry(abs, i, mode, state); if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size. pixmaps += QPixmapIconEngineEntry(abs, size, mode, state); } +bool QPixmapIconEngine::isNull() +{ + return pixmaps.isEmpty(); +} + QString QPixmapIconEngine::key() const { - return QLatin1String("QPixmapIconEngine"); + return "QPixmapIconEngine"_L1; } QIconEngine *QPixmapIconEngine::clone() const @@ -549,12 +530,12 @@ bool QPixmapIconEngine::write(QDataStream &out) const return true; } -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QIconEngineFactoryInterface_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, iceLoader, + (QIconEngineFactoryInterface_iid, "/iconengines"_L1, Qt::CaseInsensitive)) QFactoryLoader *qt_iconEngineFactoryLoader() { - return loader(); + return iceLoader(); } @@ -570,15 +551,26 @@ QFactoryLoader *qt_iconEngineFactoryLoader() A QIcon can generate smaller, larger, active, and disabled pixmaps from the set of pixmaps it is given. Such pixmaps are used by Qt - widgets to show an icon representing a particular action. + UI components to show an icon representing a particular action. - The simplest use of QIcon is to create one from a QPixmap file or - resource, and then use it, allowing Qt to work out all the required - icon styles and sizes. For example: + \section1 Creating an icon from image files + + The simplest way to construct a QIcon is to create one from one or + several image files or resources. For example: \snippet code/src_gui_image_qicon.cpp 0 - To undo a QIcon, simply set a null icon in its place: + QIcon can store several images for different states, and Qt will + select the image that is the closest match for the action's current + state. + + \snippet code/src_gui_image_qicon.cpp addFile + + Qt will generate the required icon styles and sizes when needed, + e.g. the pixmap for the QIcon::Disabled state might be generated by + graying out one of the provided pixmaps. + + To clear the icon, simply set a null icon in its place: \snippet code/src_gui_image_qicon.cpp 1 @@ -586,31 +578,54 @@ QFactoryLoader *qt_iconEngineFactoryLoader() QImageWriter::supportedImageFormats() functions to retrieve a complete list of the supported file formats. - When you retrieve a pixmap using pixmap(QSize, Mode, State), and no - pixmap for this given size, mode and state has been added with - addFile() or addPixmap(), then QIcon will generate one on the - fly. This pixmap generation happens in a QIconEngine. The default - engine scales pixmaps down if required, but never up, and it uses - the current style to calculate a disabled appearance. By using - custom icon engines, you can customize every aspect of generated - icons. With QIconEnginePlugin it is possible to register different - icon engines for different file suffixes, making it possible for - third parties to provide additional icon engines to those included + \section1 Creating an icon from a theme or icon library + + The most convenient way to construct an icon is by using the + \l{QIcon::}{fromTheme()} factory function. Qt implements access to + the native icon library on platforms that support the + \l {Freedesktop Icon Theme Specification}. Since Qt 6.7, Qt also + provides access to the native icon library on macOS, iOS, and + Windows 10 and 11. On Android, Qt can access icons from the Material + design system as long as the + \l{https://github.com/google/material-design-icons/tree/master/font} + {MaterialIcons-Regular} font is available on the system, or bundled + as a resource at \c{:/qt-project.org/icons/MaterialIcons-Regular.ttf} + with the application. + + \snippet code/src_gui_image_qicon.cpp fromTheme + + Applications can use the same theming specification to provide + their own icon library. See below for an example theme description + and the corresponding directory structure for the image files. + Icons from an application-provided theme take precedence over the + native icon library. + + In addition, it is possible to provide custom \l {QIconEngine} + {icon engines}. This allows applications to customize every aspect + of generated icons. With QIconEnginePlugin it is possible to register + different icon engines for different file suffixes, making it possible + for third parties to provide additional icon engines to those included with Qt. - \note Since Qt 4.2, an icon engine that supports SVG is included. - \section1 Making Classes that Use QIcon If you write your own widgets that have an option to set a small pixmap, consider allowing a QIcon to be set for that pixmap. The Qt class QToolButton is an example of such a widget. - Provide a method to set a QIcon, and when you draw the icon, choose - whichever pixmap is appropriate for the current state of your widget. - For example: + Provide a method to set a QIcon, and paint the QIcon with + \l{QIcon::}{paint}, choosing the appropriate parameters based + on the current state of your widget. For example: + \snippet code/src_gui_image_qicon.cpp 2 + When you retrieve a pixmap using pixmap(QSize, Mode, State), and no + pixmap for this given size, mode and state has been added with + addFile() or addPixmap(), then QIcon will generate one on the + fly. This pixmap generation happens in a QIconEngine. The default + engine scales pixmaps down if required, but never up, and it uses + the current style to calculate a disabled appearance. + You might also make use of the \c Active mode, perhaps making your widget \c Active when the mouse is over the widget (see \l QWidget::enterEvent()), while the mouse is pressed pending the @@ -624,17 +639,19 @@ QFactoryLoader *qt_iconEngineFactoryLoader() \section1 High DPI Icons - There are two ways that QIcon supports \l {High DPI}{high DPI} - icons: via \l addFile() and \l fromTheme(). + Icons that are provided by the native icon library are usually based + on vector graphics, and will automatically be rendered in the appropriate + resolution. - \l addFile() is useful if you have your own custom directory structure and do - not need to use the \l {Icon Theme Specification}{freedesktop.org Icon Theme - Specification}. Icons created via this approach use Qt's \l {High Resolution - Versions of Images}{"@nx" high DPI syntax}. + When providing your own image files via \l addFile(), then QIcon will + use Qt's \l {High Resolution Versions of Images}{"@nx" high DPI syntax}. + This is useful if you have your own custom directory structure and do not + use follow \l {Freedesktop Icon Theme Specification}. - Using \l fromTheme() is necessary if you plan on following the Icon Theme - Specification. To make QIcon use the high DPI version of an image, add an - additional entry to the appropriate \c index.theme file: + When providing an application theme, then you need to follow the Icon Theme + Specification to specify which files to use for different resolutions. + To make QIcon use the high DPI version of an image, add an additional entry + to the appropriate \c index.theme file: \badcode [Icon Theme] @@ -666,8 +683,6 @@ QFactoryLoader *qt_iconEngineFactoryLoader() │ └── appointment-new.png └── index.theme \endcode - - \sa {fowler}{GUI Design Handbook: Iconic Label}, {Icons Example} */ @@ -876,7 +891,7 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat #if QT_DEPRECATED_SINCE(6, 0) /*! \since 5.1 - \deprecated + \deprecated [6.0] Use pixmap(size, devicePixelRatio) instead. Returns a pixmap with the requested \a window \a size, \a mode, and \a state, generating one if necessary. @@ -885,8 +900,6 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat a high-dpi display the pixmap can be larger. In that case it will have a devicePixelRatio larger than 1. - \deprecated Use the overload which takes qreal devicePixelRatio instead. - \sa actualSize(), paint() */ @@ -926,6 +939,7 @@ QSize QIcon::actualSize(const QSize &size, Mode mode, State state) const #if QT_DEPRECATED_SINCE(6, 0) /*! \since 5.1 + \deprecated [6.0] Use actualSize(size) instead. Returns the actual size of the icon for the requested \a window \a size, \a mode, and \a state. @@ -1054,9 +1068,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) static QIconEngine *iconEngineFromSuffix(const QString &fileName, const QString &suffix) { if (!suffix.isEmpty()) { - const int index = loader()->indexOf(suffix); + const int index = iceLoader()->indexOf(suffix); if (index != -1) { - if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) { + if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) { return factory->create(fileName); } } @@ -1138,10 +1152,9 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const Returns the name used to create the icon, if available. Depending on the way the icon was created, it may have an associated - name. This is the case for icons created with fromTheme() or icons - using a QIconEngine which supports the QIconEngine::IconNameHook. + name. This is the case for icons created with fromTheme(). - \sa fromTheme(), QIconEngine + \sa fromTheme(), QIconEngine::iconName() */ QString QIcon::name() const { @@ -1154,6 +1167,10 @@ QString QIcon::name() const \since 4.6 Sets the search paths for icon themes to \a paths. + + The content of \a paths should follow the theme format + documented by setThemeName(). + \sa themeSearchPaths(), fromTheme(), setThemeName() */ void QIcon::setThemeSearchPaths(const QStringList &paths) @@ -1162,20 +1179,14 @@ void QIcon::setThemeSearchPaths(const QStringList &paths) } /*! - \since 4.6 - - Returns the search paths for icon themes. - - The default value will depend on the platform: + \since 4.6 - On X11, the search path will use the XDG_DATA_DIRS environment - variable if available. + Returns the search paths for icon themes. - By default all platforms will have the resource directory - \c{:\icons} as a fallback. You can use "rcc -project" to generate a - resource file from your icon theme. + The default search paths will be defined by the platform. + All platforms will also have the resource directory \c{:\icons} as a fallback. - \sa setThemeSearchPaths(), fromTheme(), setThemeName() + \sa setThemeSearchPaths(), fromTheme(), setThemeName() */ QStringList QIcon::themeSearchPaths() { @@ -1187,7 +1198,13 @@ QStringList QIcon::themeSearchPaths() Returns the fallback search paths for icons. - The default value will depend on the platform. + The fallback search paths are consulted for standalone + icon files if the \l{themeName()}{current icon theme} + or \l{fallbackThemeName()}{fallback icon theme} do + not provide results for an icon lookup. + + If not set, the fallback search paths will be defined + by the platform. \sa setFallbackSearchPaths(), themeSearchPaths() */ @@ -1201,7 +1218,12 @@ QStringList QIcon::fallbackSearchPaths() Sets the fallback search paths for icons to \a paths. - \note To add some path without replacing existing ones: + The fallback search paths are consulted for standalone + icon files if the \l{themeName()}{current icon theme} + or \l{fallbackThemeName()}{fallback icon theme} do + not provide results for an icon lookup. + + For example: \snippet code/src_gui_image_qicon.cpp 5 @@ -1217,11 +1239,15 @@ void QIcon::setFallbackSearchPaths(const QStringList &paths) Sets the current icon theme to \a name. - The \a name should correspond to a directory name in the - themeSearchPath() containing an index.theme - file describing its contents. + The theme will be will be looked up in themeSearchPaths(). + + At the moment the only supported icon theme format is the + \l{Freedesktop Icon Theme Specification}. The \a name should + correspond to a directory name in the themeSearchPath() + containing an \c index.theme file describing its contents. - \sa themeSearchPaths(), themeName() + \sa themeSearchPaths(), themeName(), + {Freedesktop Icon Theme Specification} */ void QIcon::setThemeName(const QString &name) { @@ -1233,8 +1259,12 @@ void QIcon::setThemeName(const QString &name) Returns the name of the current icon theme. - On X11, the current icon theme depends on your desktop - settings. On other platforms it is not set by default. + If not set, the current icon theme will be defined by the + platform. + + \note Platform icon themes are only implemented on + \l{Freedesktop} based systems at the moment, and the + icon theme depends on your desktop settings. \sa setThemeName(), themeSearchPaths(), fromTheme(), hasThemeIcon() @@ -1249,8 +1279,12 @@ QString QIcon::themeName() Returns the name of the fallback icon theme. - On X11, if not set, the fallback icon theme depends on your desktop - settings. On other platforms it is not set by default. + If not set, the fallback icon theme will be defined by the + platform. + + \note Platform fallback icon themes are only implemented on + \l{Freedesktop} based systems at the moment, and the + icon theme depends on your desktop settings. \sa setFallbackThemeName(), themeName() */ @@ -1264,12 +1298,16 @@ QString QIcon::fallbackThemeName() Sets the fallback icon theme to \a name. - The \a name should correspond to a directory name in the - themeSearchPath() containing an index.theme - file describing its contents. + The fallback icon theme is consulted for icons not provided by + the \l{themeName()}{current icon theme}, or if the \l{themeName()} + {current icon theme} does not exist. - \note This should be done before creating \l QGuiApplication, to ensure - correct initialization. + The \a name should correspond to theme in the same format + as documented by setThemeName(), and will be looked up + in themeSearchPaths(). + + \note Fallback icon themes should be set before creating + QGuiApplication, to ensure correct initialization. \sa fallbackThemeName(), themeSearchPaths(), themeName() */ @@ -1281,67 +1319,63 @@ void QIcon::setFallbackThemeName(const QString &name) /*! \since 4.6 - Returns the QIcon corresponding to \a name in the current - icon theme. - - The latest version of the freedesktop icon specification and naming - specification can be obtained here: + Returns the QIcon corresponding to \a name in the + \l{themeName()}{current icon theme}. - \list - \li \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html} - \li \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html} - \endlist + If the current theme does not provide an icon for \a name, + the \l{fallbackThemeName()}{fallback icon theme} is consulted, + before falling back to looking up standalone icon files in the + \l{QIcon::fallbackSearchPaths()}{fallback icon search path}. + Finally, the platform's native icon library is consulted. To fetch an icon from the current icon theme: - \snippet code/src_gui_image_qicon.cpp 3 - - \note By default, only X11 will support themed icons. In order to - use themed icons on Mac and Windows, you will have to bundle a - compliant theme in one of your themeSearchPaths() and set the - appropriate themeName(). + \snippet code/src_gui_image_qicon.cpp fromTheme - \note Qt will make use of GTK's icon-theme.cache if present to speed up - the lookup. These caches can be generated using gtk-update-icon-cache: - \l{https://developer.gnome.org/gtk3/stable/gtk-update-icon-cache.html}. + If an \l{themeName()}{icon theme} has not been explicitly + set via setThemeName() a platform defined icon theme will + be used. - \note If an icon can't be found in the current theme, then it will be - searched in fallbackSearchPaths() as an unthemed icon. - - \sa themeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths() + \sa themeName(), fallbackThemeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths(), + {Freedesktop Icon Naming Specification} */ QIcon QIcon::fromTheme(const QString &name) { - QIcon icon; - if (qtIconCache()->contains(name)) { - icon = *qtIconCache()->object(name); - } else if (QDir::isAbsolutePath(name)) { + if (QIcon *cachedIcon = qtIconCache()->object(name)) + return *cachedIcon; + + if (QDir::isAbsolutePath(name)) return QIcon(name); - } else { - QPlatformTheme * const platformTheme = QGuiApplicationPrivate::platformTheme(); - bool hasUserTheme = QIconLoader::instance()->hasUserTheme(); - QIconEngine * const engine = (platformTheme && !hasUserTheme) ? platformTheme->createIconEngine(name) - : new QIconLoaderEngine(name); - icon = QIcon(engine); - if (!icon.isNull()) - qtIconCache()->insert(name, new QIcon(icon)); - } + QIcon icon(new QThemeIconEngine(name)); + qtIconCache()->insert(name, new QIcon(icon)); return icon; } /*! \overload - Returns the QIcon corresponding to \a name in the current - icon theme. If no such icon is found in the current theme - \a fallback is returned instead. + Returns the QIcon corresponding to \a name in the + \l{themeName()}{current icon theme}. + + If the current theme does not provide an icon for \a name, + the \l{fallbackThemeName()}{fallback icon theme} is consulted, + before falling back to looking up standalone icon files in the + \l{QIcon::fallbackSearchPaths()}{fallback icon search path}. + Finally, the platform's native icon library is consulted. + + If no icon is found \a fallback is returned. + + This is useful to provide a guaranteed fallback, regardless of + whether the current set of icon themes and fallbacks paths + support the requested icon. - If you want to provide a guaranteed fallback for platforms that - do not support theme icons, you can use the second argument: + For example: \snippet code/src_gui_image_qicon.cpp 4 + + \sa fallbackThemeName(), fallbackSearchPaths() */ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) { @@ -1357,7 +1391,8 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) \since 4.6 Returns \c true if there is an icon available for \a name in the - current icon theme, otherwise returns \c false. + current icon theme or any of the fallbacks, as described by + fromTheme(), otherwise returns \c false. \sa themeSearchPaths(), fromTheme(), setThemeName() */ @@ -1368,6 +1403,401 @@ bool QIcon::hasThemeIcon(const QString &name) return icon.name() == name; } +static constexpr auto themeIconMapping = qOffsetStringArray( + "address-book-new", + "application-exit", + "appointment-new", + "call-start", + "call-stop", + "contact-new", + "document-new", + "document-open", + "document-open-recent", + "document-page-setup", + "document-print", + "document-print-preview", + "document-properties", + "document-revert", + "document-save", + "document-save-as", + "document-send", + "edit-clear", + "edit-copy", + "edit-cut", + "edit-delete", + "edit-find", + "edit-paste", + "edit-redo", + "edit-select-all", + "edit-undo", + "folder-new", + "format-indent-less", + "format-indent-more", + "format-justify-center", + "format-justify-fill", + "format-justify-left", + "format-justify-right", + "format-text-direction-ltr", + "format-text-direction-rtl", + "format-text-bold", + "format-text-italic", + "format-text-underline", + "format-text-strikethrough", + "go-down", + "go-home", + "go-next", + "go-previous", + "go-up", + "help-about", + "help-faq", + "insert-image", + "insert-link", + "insert-text", + "list-add", + "list-remove", + "mail-forward", + "mail-mark-important", + "mail-mark-read", + "mail-mark-unread", + "mail-message-new", + "mail-reply-all", + "mail-reply-sender", + "mail-send", + "media-eject", + "media-playback-pause", + "media-playback-start", + "media-playback-stop", + "media-record", + "media-seek-backward", + "media-seek-forward", + "media-skip-backward", + "media-skip-forward", + "object-rotate-left", + "object-rotate-right", + "process-stop", + "system-lock-screen", + "system-log-out", + "system-search", + "system-reboot", + "system-shutdown", + "tools-check-spelling", + "view-fullscreen", + "view-refresh", + "view-restore", + "window-close", + "window-new", + "zoom-fit-best", + "zoom-in", + "zoom-out", + + "audio-card", + "audio-input-microphone", + "battery", + "camera-photo", + "camera-video", + "camera-web", + "computer", + "drive-harddisk", + "drive-optical", + "input-gaming", + "input-keyboard", + "input-mouse", + "input-tablet", + "media-flash", + "media-optical", + "media-tape", + "multimedia-player", + "network-wired", + "network-wireless", + "phone", + "printer", + "scanner", + "video-display", + + "appointment-missed", + "appointment-soon", + "audio-volume-high", + "audio-volume-low", + "audio-volume-medium", + "audio-volume-muted", + "battery-caution", + "battery-low", + "dialog-error", + "dialog-information", + "dialog-password", + "dialog-question", + "dialog-warning", + "folder-drag-accept", + "folder-open", + "folder-visiting", + "image-loading", + "image-missing", + "mail-attachment", + "mail-unread", + "mail-read", + "mail-replied", + "media-playlist-repeat", + "media-playlist-shuffle", + "network-offline", + "printer-printing", + "security-high", + "security-low", + "software-update-available", + "software-update-urgent", + "sync-error", + "sync-synchronizing", + "user-available", + "user-offline", + "weather-clear", + "weather-clear-night", + "weather-few-clouds", + "weather-few-clouds-night", + "weather-fog", + "weather-showers", + "weather-snow", + "weather-storm" +); +static_assert(QIcon::ThemeIcon::NThemeIcons == QIcon::ThemeIcon(themeIconMapping.count())); + +static constexpr QLatin1StringView themeIconName(QIcon::ThemeIcon icon) +{ + using ThemeIconIndex = std::underlying_type_t<QIcon::ThemeIcon>; + const auto index = static_cast<ThemeIconIndex>(icon); + Q_ASSERT(index < themeIconMapping.count()); + return QLatin1StringView(themeIconMapping.viewAt(index)); +} + +/*! + \enum QIcon::ThemeIcon + \since 6.7 + + This enum provides access to icons that are provided by most + icon theme implementations. + + \value AddressBookNew The icon for the action to create a new address book. + \value ApplicationExit The icon for exiting an application. + \value AppointmentNew The icon for the action to create a new appointment. + \value CallStart The icon for initiating or accepting a call. + \value CallStop The icon for stopping a current call. + \value ContactNew The icon for the action to create a new contact. + \value DocumentNew The icon for the action to create a new document. + \value DocumentOpen The icon for the action to open a document. + \value DocumentOpenRecent The icon for the action to open a document that was recently opened. + \value DocumentPageSetup The icon for the \e{page setup} action. + \value DocumentPrint The icon for the \e{print} action. + \value DocumentPrintPreview The icon for the \e{print preview} action. + \value DocumentProperties The icon for the action to view the properties of a document. + \value DocumentRevert The icon for the action of reverting to a previous version of a document. + \value DocumentSave The icon for the \e{save} action. + \value DocumentSaveAs The icon for the \e{save as} action. + \value DocumentSend The icon for the \e{send} action. + \value EditClear The icon for the \e{clear} action. + \value EditCopy The icon for the \e{copy} action. + \value EditCut The icon for the \e{cut} action. + \value EditDelete The icon for the \e{delete} action. + \value EditFind The icon for the \e{find} action. + \value EditPaste The icon for the \e{paste} action. + \value EditRedo The icon for the \e{redo} action. + \value EditSelectAll The icon for the \e{select all} action. + \value EditUndo The icon for the \e{undo} action. + \value FolderNew The icon for creating a new folder. + \value FormatIndentLess The icon for the \e{decrease indent formatting} action. + \value FormatIndentMore The icon for the \e{increase indent formatting} action. + \value FormatJustifyCenter The icon for the \e{center justification formatting} action. + \value FormatJustifyFill The icon for the \e{fill justification formatting} action. + \value FormatJustifyLeft The icon for the \e{left justification formatting} action. + \value FormatJustifyRight The icon for the \e{right justification} action. + \value FormatTextDirectionLtr The icon for the \e{left-to-right text formatting} action. + \value FormatTextDirectionRtl The icon for the \e{right-to-left formatting} action. + \value FormatTextBold The icon for the \e{bold text formatting} action. + \value FormatTextItalic The icon for the \e{italic text formatting} action. + \value FormatTextUnderline The icon for the \e{underlined text formatting} action. + \value FormatTextStrikethrough The icon for the \e{strikethrough text formatting} action. + \value GoDown The icon for the \e{go down in a list} action. + \value GoHome The icon for the \e{go to home location} action. + \value GoNext The icon for the \e{go to the next item in a list} action. + \value GoPrevious The icon for the \e{go to the previous item in a list} action. + \value GoUp The icon for the \e{go up in a list} action. + \value HelpAbout The icon for the \e{About} item in the Help menu. + \value HelpFaq The icon for the \e{FAQ} item in the Help menu. + \value InsertImage The icon for the \e{insert image} action of an application. + \value InsertLink The icon for the \e{insert link} action of an application. + \value InsertText The icon for the \e{insert text} action of an application. + \value ListAdd The icon for the \e{add to list} action. + \value ListRemove The icon for the \e{remove from list} action. + \value MailForward The icon for the \e{forward} action. + \value MailMarkImportant The icon for the \e{mark as important} action. + \value MailMarkRead The icon for the \e{mark as read} action. + \value MailMarkUnread The icon for the \e{mark as unread} action. + \value MailMessageNew The icon for the \e{compose new mail} action. + \value MailReplyAll The icon for the \e{reply to all} action. + \value MailReplySender The icon for the \e{reply to sender} action. + \value MailSend The icon for the \e{send} action. + \value MediaEject The icon for the \e{eject} action of a media player or file manager. + \value MediaPlaybackPause The icon for the \e{pause} action of a media player. + \value MediaPlaybackStart The icon for the \e{start playback} action of a media player. + \value MediaPlaybackStop The icon for the \e{stop} action of a media player. + \value MediaRecord The icon for the \e{record} action of a media application. + \value MediaSeekBackward The icon for the \e{seek backward} action of a media player. + \value MediaSeekForward The icon for the \e{seek forward} action of a media player. + \value MediaSkipBackward The icon for the \e{skip backward} action of a media player. + \value MediaSkipForward The icon for the \e{skip forward} action of a media player. + \value ObjectRotateLeft The icon for the \e{rotate left} action performed on an object. + \value ObjectRotateRight The icon for the \e{rotate right} action performed on an object. + \value ProcessStop The icon for the \e{stop action in applications with} actions that + may take a while to process, such as web page loading in a browser. + \value SystemLockScreen The icon for the \e{lock screen} action. + \value SystemLogOut The icon for the \e{log out} action. + \value SystemSearch The icon for the \e{search} action. + \value SystemReboot The icon for the \e{reboot} action. + \value SystemShutdown The icon for the \e{shutdown} action. + \value ToolsCheckSpelling The icon for the \e{check spelling} action. + \value ViewFullscreen The icon for the \e{fullscreen} action. + \value ViewRefresh The icon for the \e{refresh} action. + \value ViewRestore The icon for leaving the fullscreen view. + \value WindowClose The icon for the \e{close window} action. + \value WindowNew The icon for the \e{new window} action. + \value ZoomFitBest The icon for the \e{best fit} action. + \value ZoomIn The icon for the \e{zoom in} action. + \value ZoomOut The icon for the \e{zoom out} action. + + \value AudioCard The icon for the audio rendering device. + \value AudioInputMicrophone The icon for the microphone audio input device. + \value Battery The icon for the system battery device. + \value CameraPhoto The icon for a digital still camera devices. + \value CameraVideo The icon for a video camera device. + \value CameraWeb The icon for a web camera device. + \value Computer The icon for the computing device as a whole. + \value DriveHarddisk The icon for hard disk drives. + \value DriveOptical The icon for optical media drives such as CD and DVD. + \value InputGaming The icon for the gaming input device. + \value InputKeyboard The icon for the keyboard input device. + \value InputMouse The icon for the mousing input device. + \value InputTablet The icon for graphics tablet input devices. + \value MediaFlash The icon for flash media, such as a memory stick. + \value MediaOptical The icon for physical optical media such as CD and DVD. + \value MediaTape The icon for generic physical tape media. + \value MultimediaPlayer The icon for generic multimedia playing devices. + \value NetworkWired The icon for wired network connections. + \value NetworkWireless The icon for wireless network connections. + \value Phone The icon for phone devices. + \value Printer The icon for a printer device. + \value Scanner The icon for a scanner device. + \value VideoDisplay The icon for the monitor that video gets displayed on. + + \value AppointmentMissed The icon for when an appointment was missed. + \value AppointmentSoon The icon for when an appointment will occur soon. + \value AudioVolumeHigh The icon used to indicate high audio volume. + \value AudioVolumeLow The icon used to indicate low audio volume. + \value AudioVolumeMedium The icon used to indicate medium audio volume. + \value AudioVolumeMuted The icon used to indicate the muted state for audio playback. + \value BatteryCaution The icon used when the battery is below 40%. + \value BatteryLow The icon used when the battery is below 20%. + \value DialogError The icon used when a dialog is opened to explain an error + condition to the user. + \value DialogInformation The icon used when a dialog is opened to give information to the + user that may be pertinent to the requested action. + \value DialogPassword The icon used when a dialog requesting the authentication + credentials for a user is opened. + \value DialogQuestion The icon used when a dialog is opened to ask a simple question + to the user. + \value DialogWarning The icon used when a dialog is opened to warn the user of + impending issues with the requested action. + \value FolderDragAccept The icon used for a folder while an acceptable object is being + dragged onto it. + \value FolderOpen The icon used for folders, while their contents are being displayed + within the same window. + \value FolderVisiting The icon used for folders, while their contents are being displayed + in another window. + \value ImageLoading The icon used while another image is being loaded. + \value ImageMissing The icon used when another image could not be loaded. + \value MailAttachment The icon for a message that contains attachments. + \value MailUnread The icon for an unread message. + \value MailRead The icon for a read message. + \value MailReplied The icon for a message that has been replied to. + \value MediaPlaylistRepeat The icon for the repeat mode of a media player. + \value MediaPlaylistShuffle The icon for the shuffle mode of a media player. + \value NetworkOffline The icon used to indicate that the device is not connected to the + network. + \value PrinterPrinting The icon used while a print job is successfully being spooled to a + printing device. + \value SecurityHigh The icon used to indicate that the security level of an item is + known to be high. + \value SecurityLow The icon used to indicate that the security level of an item is + known to be low. + \value SoftwareUpdateAvailable The icon used to indicate that an update is available. + \value SoftwareUpdateUrgent The icon used to indicate that an urgent update is available. + \value SyncError The icon used when an error occurs while attempting to synchronize + data across devices. + \value SyncSynchronizing The icon used while data is successfully synchronizing across + devices. + \value UserAvailable The icon used to indicate that a user is available. + \value UserOffline The icon used to indicate that a user is not available. + \value WeatherClear The icon used to indicate that the sky is clear. + \value WeatherClearNight The icon used to indicate that the sky is clear + during the night. + \value WeatherFewClouds The icon used to indicate that the sky is partly cloudy. + \value WeatherFewCloudsNight The icon used to indicate that the sky is partly cloudy + during the night. + \value WeatherFog The icon used to indicate that the weather is foggy. + \value WeatherShowers The icon used to indicate that rain showers are occurring. + \value WeatherSnow The icon used to indicate that snow is falling. + \value WeatherStorm The icon used to indicate that the weather is stormy. + + \omitvalue NThemeIcons + + \sa {QIcon#Creating an icon from a theme or icon library}, + fromTheme() +*/ + +/*! + \since 6.7 + \overload + + Returns \c true if there is an icon available for \a icon in the + current icon theme or any of the fallbacks, as described by + fromTheme(), otherwise returns \c false. + + \sa fromTheme() +*/ +bool QIcon::hasThemeIcon(QIcon::ThemeIcon icon) +{ + return hasThemeIcon(themeIconName(icon)); +} + +/*! + \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon) + \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback) + \since 6.7 + \overload + + Returns the QIcon corresponding to \a icon in the + \l{themeName()}{current icon theme}. + + If the current theme does not provide an icon for \a icon, + the \l{fallbackThemeName()}{fallback icon theme} is consulted, + before falling back to looking up standalone icon files in the + \l{QIcon::fallbackSearchPaths()}{fallback icon search path}. + Finally, the platform's native icon library is consulted. + + If no icon is found and a \a fallback is provided, \a fallback is + returned. This is useful to provide a guaranteed fallback, regardless + of whether the current set of icon themes and fallbacks paths + support the requested icon. + + If no icon is found and no \a fallback is provided, a default + constructed, empty QIcon is returned. +*/ +QIcon QIcon::fromTheme(QIcon::ThemeIcon icon) +{ + return fromTheme(themeIconName(icon)); +} + +QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback) +{ + return fromTheme(themeIconName(icon), fallback); +} + /*! \since 5.6 @@ -1459,16 +1889,16 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon) icon = QIcon(); QString key; s >> key; - if (key == QLatin1String("QPixmapIconEngine")) { + if (key == "QPixmapIconEngine"_L1) { icon.d = new QIconPrivate(new QPixmapIconEngine); icon.d->engine->read(s); - } else if (key == QLatin1String("QIconLoaderEngine")) { - icon.d = new QIconPrivate(new QIconLoaderEngine()); + } else if (key == "QIconLoaderEngine"_L1 || key == "QThemeIconEngine"_L1) { + icon.d = new QIconPrivate(new QThemeIconEngine); icon.d->engine->read(s); } else { - const int index = loader()->indexOf(key); + const int index = iceLoader()->indexOf(key); if (index != -1) { - if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) { + if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) { if (QIconEngine *engine= factory->create()) { icon.d = new QIconPrivate(engine); engine->read(s); @@ -1559,17 +1989,17 @@ QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRati if (disableNxImageLoading) return baseFileName; - int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.')); + int dotIndex = baseFileName.lastIndexOf(u'.'); if (dotIndex == -1) { /* no dot */ dotIndex = baseFileName.size(); /* append */ - } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == QLatin1Char('9') - && baseFileName[dotIndex - 2] == QLatin1Char('.')) { + } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9' + && baseFileName[dotIndex - 2] == u'.') { // If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it. dotIndex -= 2; } QString atNxfileName = baseFileName; - atNxfileName.insert(dotIndex, QLatin1String("@2x")); + atNxfileName.insert(dotIndex, "@2x"_L1); // Check for @Nx, ..., @3x, @2x file versions, for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) { atNxfileName[dotIndex + 1] = QLatin1Char('0' + n); |