4#include <private/qiconloader_p.h>
6#include <private/qguiapplication_p.h>
7#include <private/qicon_p.h>
9#include <QtGui/QIconEnginePlugin>
10#include <QtGui/QPixmapCache>
11#include <qpa/qplatformtheme.h>
12#include <QtGui/QIconEngine>
13#include <QtGui/QPalette>
14#include <QtCore/qmath.h>
15#include <QtCore/QList>
17#include <QtCore/qloggingcategory.h>
18#if QT_CONFIG(settings)
19#include <QtCore/QSettings>
21#include <QtGui/QPainter>
23#include <private/qhexstring_p.h>
29using namespace
Qt::StringLiterals;
45 m_themeKey(1), m_supportsSvg(
false), m_initialized(
false)
51 const auto override =
qgetenv(
"QT_QPA_SYSTEM_ICON_THEME");
52 if (!
override.isEmpty())
97 qCDebug(lcIconLoader) <<
"Initialized icon loader with system theme"
98 << m_systemTheme <<
"and SVG support" << m_supportsSvg;
114 iconLoaderInstance()->ensureInitialized();
115 return iconLoaderInstance();
122 const QString currentSystemTheme = m_systemTheme;
126 if (m_systemTheme != currentSystemTheme)
127 qCDebug(lcIconLoader) <<
"Updated system theme to" << m_systemTheme;
144 return m_userTheme.
isEmpty() ? m_systemTheme : m_userTheme;
178 qCDebug(lcIconLoader) <<
"Setting theme search path to" << searchPaths;
179 m_iconDirs = searchPaths;
186 if (m_iconDirs.isEmpty()) {
189 m_iconDirs.append(
":/icons"_L1);
196 qCDebug(lcIconLoader) <<
"Setting fallback search path to" << searchPaths;
197 m_fallbackDirs = searchPaths;
203 if (m_fallbackDirs.isEmpty()) {
206 return m_fallbackDirs;
224 const unsigned char *m_data;
257 m_size = m_file.
size();
268 quint32 dirListOffset = read32(8);
269 quint32 dirListLen = read32(dirListOffset);
270 for (
uint i = 0;
i < dirListLen; ++
i) {
272 if (!m_isValid ||
offset >= m_size || lastModified <
QFileInfo(dirName + u
'/'
282 quint32 h =
static_cast<signed char>(*p);
283 for (
p += 1; *
p !=
'\0';
p++)
284 h = (
h << 5) -
h + *
p;
295 QList<const char *>
ret;
302 quint32 hashOffset = read32(4);
303 quint32 hashBucketCount = read32(hashOffset);
305 if (!
isValid() || hashBucketCount == 0) {
311 quint32 bucketOffset = read32(hashOffset + 4 + bucketIndex * 4);
312 while (bucketOffset > 0 && bucketOffset <= m_size - 12) {
313 quint32 nameOff = read32(bucketOffset + 4);
314 if (nameOff < m_size && strcmp(
reinterpret_cast<const char*
>(
m_data + nameOff), nameUtf8) == 0) {
315 quint32 dirListOffset = read32(8);
316 quint32 dirListLen = read32(dirListOffset);
318 quint32 listOffset = read32(bucketOffset+8);
319 quint32 listLen = read32(listOffset);
321 if (!m_isValid || listOffset + 4 + 8 * listLen > m_size) {
326 ret.reserve(listLen);
327 for (
uint j = 0;
j < listLen && m_isValid; ++
j) {
328 quint32 dirIndex = read16(listOffset + 4 + 8 *
j);
329 quint32 o = read32(dirListOffset + 4 + dirIndex*4);
330 if (!m_isValid || dirIndex >= dirListLen ||
o >= m_size) {
334 ret.append(
reinterpret_cast<const char*
>(
m_data) +
o);
338 bucketOffset = read32(bucketOffset);
349 for (
int i = 0 ;
i < iconDirs.size() ; ++
i) {
350 QDir iconDir(iconDirs[
i]);
354 if (themeDirInfo.isDir()) {
355 m_contentDirs << themeDir;
356 m_gtkCaches << QSharedPointer<QIconCacheGtkReader>::create(themeDir);
360 themeIndex.setFileName(themeDir +
"/index.theme"_L1);
361 m_valid = themeIndex.exists();
362 qCDebug(lcIconLoader) <<
"Probing theme file at" << themeIndex.fileName() << m_valid;
365#if QT_CONFIG(settings)
370 if (
key.endsWith(
"/Size"_L1)) {
373 if (
int size = indexReader.value(
key).toInt()) {
377 QString type = indexReader.value(directoryKey +
"/Type"_L1).toString();
379 if (
type ==
"Fixed"_L1)
381 else if (
type ==
"Scalable"_L1)
386 dirInfo.
threshold = indexReader.value(directoryKey +
390 dirInfo.
minSize = indexReader.value(directoryKey +
"/MinSize"_L1,
size).toInt();
392 dirInfo.
maxSize = indexReader.value(directoryKey +
"/MaxSize"_L1,
size).toInt();
394 dirInfo.
scale = indexReader.value(directoryKey +
"/Scale"_L1, 1).toInt();
396 const QString context = indexReader.value(directoryKey +
"/Context"_L1).toString();
398 if (
context ==
"Applications"_L1)
400 else if (
context ==
"MimeTypes"_L1)
406 m_keyList.
append(dirInfo);
412 m_parents = indexReader.value(
"Icon Theme/Inherits"_L1).toStringList();
413 m_parents.removeAll(
QString());
425 if (!fallback.isEmpty())
429 result.removeAll(
"hicolor"_L1);
430 result.append(
"hicolor"_L1);
447 qCDebug(lcIconLoader) <<
"Finding icon" << iconName <<
"in theme" <<
themeName
448 <<
"skipping" << visited;
468 bool searchingGenericFallback = m_iconName.
length() > iconName.
length();
471 if (
info.entries.empty()) {
472 const QString svgIconName = iconNameFallback +
".svg"_L1;
473 const QString pngIconName = iconNameFallback +
".png"_L1;
476 for (
int i = 0;
i < contentDirs.size(); ++
i) {
482 if (
cache->isValid()) {
483 const auto result =
cache->lookup(iconNameFallback);
484 if (
cache->isValid()) {
485 const QList<QIconDirInfo> subDirsCopy = subDirs;
487 subDirs.reserve(
result.size());
490 auto it = std::find_if(subDirsCopy.cbegin(), subDirsCopy.cend(),
492 return info.path == path; } );
493 if (
it != subDirsCopy.
cend()) {
500 QString contentDir = contentDirs.at(
i) + u
'/';
501 for (
int j = 0;
j < subDirs.size() ; ++
j) {
503 if (searchingGenericFallback &&
509 const QString pngPath = subDir + pngIconName;
511 auto iconEntry = std::make_unique<PixmapEntry>();
513 iconEntry->filename = pngPath;
516 info.entries.insert(
info.entries.begin(), std::move(iconEntry));
517 }
else if (m_supportsSvg) {
518 const QString svgPath = subDir + svgIconName;
520 auto iconEntry = std::make_unique<ScalableEntry>();
522 iconEntry->filename = svgPath;
523 info.entries.push_back(std::move(iconEntry));
529 if (!
info.entries.empty()) {
530 info.iconName = iconNameFallback.toString();
534 if (
info.entries.empty()) {
536 qCDebug(lcIconLoader) <<
"Did not find matching icons in theme;"
537 <<
"trying parent themes" << parents
538 <<
"skipping visited" << visited;
541 for (
int i = 0 ;
i < parents.size() ; ++
i) {
543 const QString parentTheme = parents.at(
i).trimmed();
545 if (!visited.contains(parentTheme))
546 info = findIconHelper(parentTheme, iconName, visited, QIconLoader::NoFallBack);
548 if (!
info.entries.empty())
553 if (
rule == QIconLoader::FallBack &&
info.entries.empty()) {
555 const int indexOfDash = iconNameFallback.lastIndexOf(u
'-');
556 if (indexOfDash != -1) {
557 qCDebug(lcIconLoader) <<
"Did not find matching icons in all themes;"
558 <<
"trying dash fallback";
559 iconNameFallback.truncate(indexOfDash);
561 info = findIconHelper(
themeName, iconNameFallback.toString(), _visited, QIconLoader::FallBack);
570 qCDebug(lcIconLoader) <<
"Looking up fallback icon" << iconName;
574 const QString pngIconName = iconName +
".png"_L1;
575 const QString xpmIconName = iconName +
".xpm"_L1;
576 const QString svgIconName = iconName +
".svg"_L1;
579 for (
const QString &iconDir: searchPaths) {
580 QDir currentDir(iconDir);
581 std::unique_ptr<QIconLoaderEngineEntry> iconEntry;
582 if (currentDir.exists(pngIconName)) {
583 iconEntry = std::make_unique<PixmapEntry>();
585 iconEntry->filename = currentDir.filePath(pngIconName);
586 }
else if (currentDir.exists(xpmIconName)) {
587 iconEntry = std::make_unique<PixmapEntry>();
589 iconEntry->filename = currentDir.filePath(xpmIconName);
590 }
else if (m_supportsSvg &&
591 currentDir.exists(svgIconName)) {
592 iconEntry = std::make_unique<ScalableEntry>();
594 iconEntry->filename = currentDir.filePath(svgIconName);
597 info.entries.push_back(std::move(iconEntry));
602 if (!
info.entries.empty())
603 info.iconName = iconName;
616 iconInfo = findIconHelper(
themeName(),
name, visitedThemes, QIconLoader::FallBack);
621 if (iconInfo.entries.empty())
622 iconInfo = lookupFallbackIcon(
name);
624 qCDebug(lcIconLoader) <<
"Resulting icon entries" << iconInfo.entries;
628#ifndef QT_NO_DEBUG_STREAM
635 debug << static_cast<const void *>(
engine);
642 debug <<
"QIconEngine(nullptr)";
650 qCDebug(lcIconLoader) <<
"Resolving icon engine for icon" << iconName;
656 qCDebug(lcIconLoader) <<
"Icon is not available from theme or fallback theme.";
658 qCDebug(lcIconLoader) <<
"Trying platform engine.";
659 std::unique_ptr<QIconEngine> themeEngine(platformTheme->createIconEngine(iconName));
660 if (themeEngine && !themeEngine->isNull()) {
662 qCDebug(lcIconLoader) <<
"Icon provided by platform engine.";
691 , m_iconName(iconName)
697 , m_iconName(
other.m_iconName)
706 return u
"QThemeIconEngine"_s;
728 auto mostRecentThemeKey = iconLoader->themeKey();
729 if (mostRecentThemeKey != m_themeKey) {
730 qCDebug(lcIconLoader) <<
"Theme key" << mostRecentThemeKey <<
"is different"
731 <<
"than cached key" << m_themeKey <<
"for icon" << m_iconName;
732 m_proxiedEngine.reset(iconLoader->iconEngine(m_iconName));
733 m_themeKey = mostRecentThemeKey;
735 return m_proxiedEngine.get();
750 : m_iconName(iconName)
751 , m_info(
QIconLoader::instance()->loadIcon(m_iconName))
763bool QIconLoaderEngine::hasIcon()
const
765 return !(m_info.
entries.empty());
781 if (
dir.scale != iconscale)
788 return iconsize <=
dir.maxSize &&
789 iconsize >=
dir.minSize;
792 return iconsize >=
dir.
size -
dir.threshold &&
808 const int scaledIconSize = iconsize * iconscale;
813 if (scaledIconSize <
dir.minSize *
dir.scale)
814 return dir.minSize *
dir.scale - scaledIconSize;
815 else if (scaledIconSize >
dir.maxSize *
dir.scale)
816 return scaledIconSize -
dir.maxSize *
dir.scale;
822 return dir.minSize *
dir.scale - scaledIconSize;
823 else if (scaledIconSize > (
dir.
size +
dir.threshold) *
dir.scale)
824 return scaledIconSize -
dir.maxSize *
dir.scale;
849 int minimalSize = INT_MAX;
905 % HexString<int>(
mode)
907 % HexString<int>(actualSize.
width())
908 % HexString<int>(actualSize.
height());
950 return u
"QIconLoaderEngine"_s;
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
QString path() const
Returns the path.
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
void setFileName(const QString &name)
Sets the name of the file.
bool exists() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qint64 size() const override
\reimp
static QPlatformTheme * platformTheme()
static QPalette palette()
Returns the current application palette.
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
QIconCacheGtkReader(const QString &themeDir)
QList< const char * > lookup(QStringView)
The QIconEngine class provides an abstract base class for QIcon renderers.
An icon engine based on icon entries collected by QIconLoader.
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.
static Q_GUI_EXPORT QIconLoaderEngineEntry * entryForSize(const QThemeIconInfo &info, const QSize &size, int scale=1)
QString key() const override
\variable QIconEngine::ScaledPixmapArgument::size
QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override
QIconLoaderEngine(const QString &iconName=QString())
QString iconName() override
QList< QSize > availableSizes(QIcon::Mode mode, QIcon::State state) override
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.
QIconEngine * clone() const override
Reimplement this method to return a clone of this icon engine.
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.
QThemeIconInfo loadIcon(const QString &iconName) const
void setFallbackThemeName(const QString &themeName)
bool hasUserTheme() const
QStringList fallbackSearchPaths() const
void setFallbackSearchPaths(const QStringList &searchPaths)
QIconDirInfo dirInfo(int dirindex)
void setThemeSearchPath(const QStringList &searchPaths)
static QIconLoader * instance()
QString fallbackThemeName() const
QStringList themeSearchPaths() const
QIconEngine * iconEngine(const QString &iconName) const
QString themeName() const
void setThemeName(const QString &themeName)
QStringList contentDirs()
QStringList parents() const
QList< QIconDirInfo > keyList()
QList< QSharedPointer< QIconCacheGtkReader > > m_gtkCaches
The QIcon class provides scalable icons in different modes and states.
static QStringList fallbackSearchPaths()
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Mode
This enum type describes the mode for which a pixmap is intended to be used.
QList< QSize > availableSizes(Mode mode=Normal, State state=Off) const
State
This enum describes the state for which a pixmap is intended to be used.
static QStringList themeSearchPaths()
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.
const_reference at(qsizetype i) const noexcept
void append(parameter_type t)
static QObjectPrivate * get(QObject *o)
qreal devicePixelRatio() const
The QPainter class performs low-level painting on widgets and other paint devices.
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.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
QPixmap scaled(int w, int h, Qt::AspectRatioMode aspectMode=Qt::IgnoreAspectRatio, Qt::TransformationMode mode=Qt::FastTransformation) const
QSize size() const
Returns the size of the pixmap.
bool load(const QString &fileName, const char *format=nullptr, Qt::ImageConversionFlags flags=Qt::AutoColor)
Loads a pixmap from the file with the given fileName.
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
qint64 cacheKey() const
Returns a number that identifies this QPixmap.
\inmodule QtCore\reentrant
const_iterator cend() const noexcept
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
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:
constexpr bool isNull() const noexcept
Returns true if both the width and height is 0; otherwise returns false.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString left(qsizetype n) const &
static QString fromLocal8Bit(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
qsizetype size() const noexcept
Returns the number of characters in this string.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype length() const noexcept
Returns the number of characters in this string.
A named-based icon engine for providing theme icons.
QThemeIconEngine(const QString &iconName=QString())
QString key() const override
\variable QIconEngine::ScaledPixmapArgument::size
bool write(QDataStream &out) const override
Writes the contents of this engine to the QDataStream out.
bool read(QDataStream &in) override
Reads icon engine contents from the QDataStream in.
QIconEngine * clone() const override
Reimplement this method to return a clone of this icon engine.
QIconEngine * proxiedEngine() const override
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
QStringList toStringList() const
Returns the variant as a QStringList if the variant has userType() \l QMetaType::QStringList,...
QHash< int, QWidget * > hash
[35multi]
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char * rule
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
static QStringList systemIconSearchPaths()
QFactoryLoader * qt_iconEngineFactoryLoader()
QDebug operator<<(QDebug debug, const std::unique_ptr< QIconLoaderEngineEntry > &entry)
static QStringList systemFallbackSearchPaths()
static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int iconscale)
static QString systemThemeName()
static QString systemFallbackThemeName()
static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize, int iconscale)
static quint32 icon_name_hash(const char *p)
static int closestMatch(QRgb pixel, const QList< QRgb > &clut)
static QByteArray cacheKey(Args &&...args)
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr T qAbs(const T &t)
static QString themeName()
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLsizei GLfloat distance
GLenum GLuint GLintptr offset
GLfloat GLfloat GLfloat GLfloat h
GLuint GLsizei const GLuint const GLintptr const GLsizeiptr * sizes
GLsizei const GLchar *const * path
GLenum GLenum GLenum GLenum GLenum scale
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
unsigned long long quint64
static const struct @450 keyMap[]
QTextStream out(stdout)
[7]
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override
QThemeIconEntries entries
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override