KIconThemes

kicontheme.cpp
1/* vi: ts=8 sts=4 sw=4
2
3 kicontheme.cpp: Lowlevel icon theme handling.
4
5 This file is part of the KDE project, module kdecore.
6 SPDX-FileCopyrightText: 2000 Geert Jansen <jansen@kde.org>
7 SPDX-FileCopyrightText: 2000 Antonio Larrosa <larrosa@kde.org>
8
9 SPDX-License-Identifier: LGPL-2.0-only
10*/
11
12#include "kicontheme.h"
13
14#include "debug.h"
15
16#include <KConfigGroup>
17#include <KLocalizedString> // KLocalizedString::localizedFilePath. Need such functionality in, hmm, QLocale? QStandardPaths?
18#include <KSharedConfig>
19
20#ifdef WITH_BREEZEICONS_LIB
21#include <BreezeIcons>
22#endif
23
24#include <QAction>
25#include <QCoreApplication>
26#include <QDebug>
27#include <QDir>
28#include <QFileInfo>
29#include <QMap>
30#include <QResource>
31#include <QSet>
32
33#include <private/qguiapplication_p.h>
34#include <qpa/qplatformtheme.h>
35
36#include <qplatformdefs.h>
37
38#include <array>
39#include <cmath>
40
41Q_GLOBAL_STATIC(QString, _themeOverride)
42
43// Support for icon themes in RCC files.
44// The intended use case is standalone apps on Windows / MacOS / etc.
45// For this reason we use AppDataLocation: BINDIR/data on Windows, Resources on OS X
46void initRCCIconTheme()
47{
48#ifdef WITH_BREEZEICONS
50#else
51 const QString iconThemeRcc = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("icontheme.rcc"));
52 if (!iconThemeRcc.isEmpty()) {
53 const QString iconThemeName = QStringLiteral("kf6_rcc_theme");
54 const QString iconSubdir = QStringLiteral("/icons/") + iconThemeName;
55 if (QResource::registerResource(iconThemeRcc, iconSubdir)) {
56 if (QFileInfo::exists(QLatin1Char(':') + iconSubdir + QStringLiteral("/index.theme"))) {
57 // Tell Qt about the theme
58 // Note that since qtbase commit a8621a3f8, this means the QPA (i.e. KIconLoader) will NOT be used.
59 QIcon::setThemeName(iconThemeName); // Qt looks under :/icons automatically
60 // Tell KIconTheme about the theme, in case KIconLoader is used directly
61 *_themeOverride() = iconThemeName;
62 } else {
63 qWarning() << "No index.theme found in" << iconThemeRcc;
64 QResource::unregisterResource(iconThemeRcc, iconSubdir);
65 }
66 } else {
67 qWarning() << "Invalid rcc file" << iconThemeRcc;
68 }
69 }
70#endif
71}
72Q_COREAPP_STARTUP_FUNCTION(initRCCIconTheme)
73
74// Makes sure the icon theme fallback is set to breeze or one of its
75// variants. Most of our apps use "lots" of icons that most of the times
76// are only available with breeze, we still honour the user icon theme
77// but if the icon is not found there, we go to breeze since it's almost
78// sure it'll be there
79static void setBreezeFallback()
80{
81 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
82 const QVariant themeHint = theme->themeHint(QPlatformTheme::SystemIconFallbackThemeName);
83 if (themeHint.isValid()) {
84 const QString iconTheme = themeHint.toString();
85 if (iconTheme.contains(QStringLiteral("breeze"), Qt::CaseInsensitive)) {
87 return;
88 }
89 }
90 }
91
92 QIcon::setFallbackThemeName(QStringLiteral("breeze"));
93}
94
95#ifndef Q_OS_ANDROID
96Q_COREAPP_STARTUP_FUNCTION(setBreezeFallback)
97#endif
98class KIconThemeDir;
99class KIconThemePrivate
100{
101public:
102 QString example, screenshot;
103 bool hidden;
104 KSharedConfig::Ptr sharedConfig;
105
106 struct GroupInfo {
108 const char *name;
109 int defaultSize;
110 QList<int> availableSizes{};
111 };
112 std::array<GroupInfo, KIconLoader::LastGroup> m_iconGroups = {{
113 {KIconLoader::Desktop, "Desktop", 32},
114 {KIconLoader::Toolbar, "Toolbar", 22},
115 {KIconLoader::MainToolbar, "MainToolbar", 22},
116 {KIconLoader::Small, "Small", 16},
117 {KIconLoader::Panel, "Panel", 48},
118 {KIconLoader::Dialog, "Dialog", 32},
119 }};
120
121 int mDepth;
122 QString mDir, mName, mInternalName, mDesc;
123 QStringList mInherits;
124 QStringList mExtensions;
126 QList<KIconThemeDir *> mScaledDirs;
127 bool followsColorScheme : 1;
128
129 /// Searches the given dirs vector for a matching icon
130 QString iconPath(const QList<KIconThemeDir *> &dirs, const QString &name, int size, qreal scale, KIconLoader::MatchType match) const;
131};
132Q_GLOBAL_STATIC(QString, _theme)
133Q_GLOBAL_STATIC(QStringList, _theme_list)
134
135/**
136 * A subdirectory in an icon theme.
137 */
138class KIconThemeDir
139{
140public:
141 KIconThemeDir(const QString &basedir, const QString &themedir, const KConfigGroup &config);
142
143 bool isValid() const
144 {
145 return mbValid;
146 }
147 QString iconPath(const QString &name) const;
148 QStringList iconList() const;
149 QString constructFileName(const QString &file) const
150 {
151 return mBaseDir + mThemeDir + QLatin1Char('/') + file;
152 }
153
154 KIconLoader::Context context() const
155 {
156 return mContext;
157 }
158 KIconLoader::Type type() const
159 {
160 return mType;
161 }
162 int size() const
163 {
164 return mSize;
165 }
166 int scale() const
167 {
168 return mScale;
169 }
170 int minSize() const
171 {
172 return mMinSize;
173 }
174 int maxSize() const
175 {
176 return mMaxSize;
177 }
178 int threshold() const
179 {
180 return mThreshold;
181 }
182
183private:
184 bool mbValid = false;
186 KIconLoader::Context mContext;
187 int mSize = 0;
188 int mScale = 1;
189 int mMinSize = 1;
190 int mMaxSize = 50;
191 int mThreshold = 2;
192
193 const QString mBaseDir;
194 const QString mThemeDir;
195};
196
197QString KIconThemePrivate::iconPath(const QList<KIconThemeDir *> &dirs, const QString &name, int size, qreal scale, KIconLoader::MatchType match) const
198{
200 QString tempPath; // used to cache icon path if it exists
201
202 int delta = -INT_MAX; // current icon size delta of 'icon'
203 int dw = INT_MAX; // icon size delta of current directory
204
205 // Rather downsample than upsample
206 int integerScale = std::ceil(scale);
207
208 // Search the directory that contains the icon which matches best to the requested
209 // size. If there is no directory which matches exactly to the requested size, the
210 // following criteria get applied:
211 // - Take a directory having icons with a minimum difference to the requested size.
212 // - Prefer directories that allow a downscaling even if the difference to
213 // the requested size is bigger than a directory where an upscaling is required.
214 for (KIconThemeDir *dir : dirs) {
215 if (dir->scale() != integerScale) {
216 continue;
217 }
218
219 if (match == KIconLoader::MatchExact) {
220 if ((dir->type() == KIconLoader::Fixed) && (dir->size() != size)) {
221 continue;
222 }
223 if ((dir->type() == KIconLoader::Scalable) //
224 && ((size < dir->minSize()) || (size > dir->maxSize()))) {
225 continue;
226 }
227 if ((dir->type() == KIconLoader::Threshold) //
228 && (abs(dir->size() - size) > dir->threshold())) {
229 continue;
230 }
231 } else {
232 // dw < 0 means need to scale up to get an icon of the requested size.
233 // Upscaling should only be done if no larger icon is available.
234 if (dir->type() == KIconLoader::Fixed) {
235 dw = dir->size() - size;
236 } else if (dir->type() == KIconLoader::Scalable) {
237 if (size < dir->minSize()) {
238 dw = dir->minSize() - size;
239 } else if (size > dir->maxSize()) {
240 dw = dir->maxSize() - size;
241 } else {
242 dw = 0;
243 }
244 } else if (dir->type() == KIconLoader::Threshold) {
245 if (size < dir->size() - dir->threshold()) {
246 dw = dir->size() - dir->threshold() - size;
247 } else if (size > dir->size() + dir->threshold()) {
248 dw = dir->size() + dir->threshold() - size;
249 } else {
250 dw = 0;
251 }
252 }
253 // Usually if the delta (= 'dw') of the current directory is
254 // not smaller than the delta (= 'delta') of the currently best
255 // matching icon, this candidate can be skipped. But skipping
256 // the candidate may only be done, if this does not imply
257 // in an upscaling of the icon (it is OK to use a directory with
258 // smaller icons that what we've already found, however).
259 if ((abs(dw) >= abs(delta)) && ((dw < 0) || (delta > 0))) {
260 continue;
261 }
262
263 if (match == KIconLoader::MatchBestOrGreaterSize && dw < 0) {
264 continue;
265 }
266 }
267
268 // cache the result of iconPath() call which checks if file exists
269 tempPath = dir->iconPath(name);
270
271 if (tempPath.isEmpty()) {
272 continue;
273 }
274
275 path = tempPath;
276
277 // if we got in MatchExact that far, we find no better
278 if (match == KIconLoader::MatchExact) {
279 return path;
280 }
281 delta = dw;
282 if (delta == 0) {
283 return path; // We won't find a better match anyway
284 }
285 }
286 return path;
287}
288
289KIconTheme::KIconTheme(const QString &name, const QString &appName, const QString &basePathHint)
290 : d(new KIconThemePrivate)
291{
292 d->mInternalName = name;
293
294 QStringList themeDirs;
295
296 // Applications can have local additions to the global "locolor" and
297 // "hicolor" icon themes. For these, the _global_ theme description
298 // files are used..
299
300 /* clang-format off */
301 if (!appName.isEmpty()
302 && (name == defaultThemeName()
303 || name == QLatin1String("hicolor")
304 || name == QLatin1String("locolor"))) { /* clang-format on */
305 const QString suffix = QLatin1Char('/') + appName + QLatin1String("/icons/") + name + QLatin1Char('/');
307 for (auto &cDir : dataDirs) {
308 cDir += suffix;
309 if (QFileInfo::exists(cDir)) {
310 themeDirs += cDir;
311 }
312 }
313
314 if (!basePathHint.isEmpty()) {
315 // Checks for dir existing are done below
316 themeDirs += basePathHint + QLatin1Char('/') + name + QLatin1Char('/');
317 }
318 }
319
320 // Find the theme description file. These are either locally in the :/icons resource path or global.
321 QStringList icnlibs;
322
323 // local embedded icons have preference
324 icnlibs << QStringLiteral(":/icons");
325
326 // global icons
328
329 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
331
332 QString fileName;
333 QString mainSection;
334 const QString pathSuffix = QLatin1Char('/') + name + QLatin1Char('/');
335 const QLatin1String indexTheme("index.theme");
336 const QLatin1String indexDesktop("theme.desktop");
337 for (auto &iconDir : icnlibs) {
338 iconDir += pathSuffix;
339 const QFileInfo fi(iconDir);
340 if (!fi.exists() || !fi.isDir()) {
341 continue;
342 }
343 themeDirs.append(iconDir);
344
345 if (d->mDir.isEmpty()) {
346 QString possiblePath;
347 if (possiblePath = iconDir + indexTheme; QFileInfo::exists(possiblePath)) {
348 d->mDir = iconDir;
349 fileName = possiblePath;
350 mainSection = QStringLiteral("Icon Theme");
351 } else if (possiblePath = iconDir + indexDesktop; QFileInfo::exists(possiblePath)) {
352 d->mDir = iconDir;
353 fileName = possiblePath;
354 mainSection = QStringLiteral("KDE Icon Theme");
355 }
356 }
357 }
358
359 if (d->mDir.isEmpty()) {
360 qCDebug(KICONTHEMES) << "Icon theme" << name << "not found.";
361 return;
362 }
363
364 // Use KSharedConfig to avoid parsing the file many times, from each component.
365 // Need to keep a ref to it to make this useful
366 d->sharedConfig = KSharedConfig::openConfig(fileName, KConfig::SimpleConfig);
367
368 KConfigGroup cfg(d->sharedConfig, mainSection);
369 d->mName = cfg.readEntry("Name");
370 d->mDesc = cfg.readEntry("Comment");
371 d->mDepth = cfg.readEntry("DisplayDepth", 32);
372 d->mInherits = cfg.readEntry("Inherits", QStringList());
373 if (name != defaultThemeName()) {
374 for (auto &inheritedTheme : d->mInherits) {
375 if (inheritedTheme == QLatin1String("default")) {
376 inheritedTheme = defaultThemeName();
377 }
378 }
379 }
380
381 d->hidden = cfg.readEntry("Hidden", false);
382 d->followsColorScheme = cfg.readEntry("FollowsColorScheme", false);
383 d->example = cfg.readPathEntry("Example", QString());
384 d->screenshot = cfg.readPathEntry("ScreenShot", QString());
385 d->mExtensions =
386 cfg.readEntry("KDE-Extensions", QStringList{QStringLiteral(".png"), QStringLiteral(".svgz"), QStringLiteral(".svg"), QStringLiteral(".xpm")});
387
388 QSet<QString> addedDirs; // Used for avoiding duplicates.
389 const QStringList dirs = cfg.readPathEntry("Directories", QStringList()) + cfg.readPathEntry("ScaledDirectories", QStringList());
390 for (const auto &dirName : dirs) {
391 KConfigGroup cg(d->sharedConfig, dirName);
392 for (const auto &themeDir : std::as_const(themeDirs)) {
393 const QString currentDir(themeDir + dirName + QLatin1Char('/'));
394 if (!addedDirs.contains(currentDir) && QDir(currentDir).exists()) {
395 addedDirs.insert(currentDir);
396 KIconThemeDir *dir = new KIconThemeDir(themeDir, dirName, cg);
397 if (dir->isValid()) {
398 if (dir->scale() > 1) {
399 d->mScaledDirs.append(dir);
400 } else {
401 d->mDirs.append(dir);
402 }
403 } else {
404 delete dir;
405 }
406 }
407 }
408 }
409
410 KConfigGroup cg(d->sharedConfig, mainSection);
411 for (auto &iconGroup : d->m_iconGroups) {
412 iconGroup.defaultSize = cg.readEntry(iconGroup.name + QLatin1String("Default"), iconGroup.defaultSize);
413 iconGroup.availableSizes = cg.readEntry(iconGroup.name + QLatin1String("Sizes"), QList<int>());
414 }
415}
416
417KIconTheme::~KIconTheme()
418{
419 qDeleteAll(d->mDirs);
420 qDeleteAll(d->mScaledDirs);
421}
422
424{
425 return d->mName;
426}
427
429{
430 return d->mInternalName;
431}
432
434{
435 return d->mDesc;
436}
437
439{
440 return d->example;
441}
442
444{
445 return d->screenshot;
446}
447
449{
450 return d->mDir;
451}
452
454{
455 return d->mInherits;
456}
457
459{
460 return !d->mDirs.isEmpty() || !d->mScaledDirs.isEmpty();
461}
462
464{
465 return d->hidden;
466}
467
469{
470 return d->mDepth;
471}
472
474{
475 if (group < 0 || group >= KIconLoader::LastGroup) {
476 qCWarning(KICONTHEMES) << "Invalid icon group:" << group << ", should be one of KIconLoader::Group";
477 return -1;
478 }
479 return d->m_iconGroups[group].defaultSize;
480}
481
483{
484 if (group < 0 || group >= KIconLoader::LastGroup) {
485 qCWarning(KICONTHEMES) << "Invalid icon group:" << group << ", should be one of KIconLoader::Group";
486 return QList<int>();
487 }
488 return d->m_iconGroups[group].availableSizes;
489}
490
491static bool isAnyOrDirContext(const KIconThemeDir *dir, KIconLoader::Context context)
492{
493 return context == KIconLoader::Any || context == dir->context();
494}
495
497{
498 // Try to find exact match
499 QStringList result;
500 const QList<KIconThemeDir *> listDirs = d->mDirs + d->mScaledDirs;
501 for (const KIconThemeDir *dir : listDirs) {
502 if (!isAnyOrDirContext(dir, context)) {
503 continue;
504 }
505
506 const int dirSize = dir->size();
507 if ((dir->type() == KIconLoader::Fixed && dirSize == size) //
508 || (dir->type() == KIconLoader::Scalable && size >= dir->minSize() && size <= dir->maxSize())
509 || (dir->type() == KIconLoader::Threshold && abs(size - dirSize) < dir->threshold())) {
510 result += dir->iconList();
511 }
512 }
513
514 return result;
515}
516
518{
519 int dw;
520
521 // We want all the icons for a given context, but we prefer icons
522 // of size "size" . Note that this may (will) include duplicate icons
523 // QStringList iconlist[34]; // 33 == 48-16+1
524 QStringList iconlist[128]; // 33 == 48-16+1
525 // Usually, only the 0, 6 (22-16), 10 (32-22), 16 (48-32 or 32-16),
526 // 26 (48-22) and 32 (48-16) will be used, but who knows if someone
527 // will make icon themes with different icon sizes.
528 const auto listDirs = d->mDirs + d->mScaledDirs;
529 for (KIconThemeDir *dir : listDirs) {
530 if (!isAnyOrDirContext(dir, context)) {
531 continue;
532 }
533 dw = abs(dir->size() - size);
534 iconlist[(dw < 127) ? dw : 127] += dir->iconList();
535 }
536
537 QStringList iconlistResult;
538 for (int i = 0; i < 128; i++) {
539 iconlistResult += iconlist[i];
540 }
541
542 return iconlistResult;
543}
544
546{
547 const auto listDirs = d->mDirs + d->mScaledDirs;
548 for (KIconThemeDir *dir : listDirs) {
549 if (isAnyOrDirContext(dir, context)) {
550 return true;
551 }
552 }
553 return false;
554}
555
557{
558 return iconPathByName(iconName, size, match, 1 /*scale*/);
559}
560
561QString KIconTheme::iconPathByName(const QString &iconName, int size, KIconLoader::MatchType match, qreal scale) const
562{
563 for (const QString &current : std::as_const(d->mExtensions)) {
564 const QString path = iconPath(iconName + current, size, match, scale);
565 if (!path.isEmpty()) {
566 return path;
567 }
568 }
569 return QString();
570}
571
573{
574 return d->followsColorScheme;
575}
576
578{
579 return iconPath(name, size, match, 1 /*scale*/);
580}
581
582QString KIconTheme::iconPath(const QString &name, int size, KIconLoader::MatchType match, qreal scale) const
583{
584 // first look for a scaled image at exactly the requested size
585 QString path = d->iconPath(d->mScaledDirs, name, size, scale, KIconLoader::MatchExact);
586
587 // then look for an unscaled one but request it at larger size so it doesn't become blurry
588 if (path.isEmpty()) {
589 path = d->iconPath(d->mDirs, name, size * scale, 1, match);
590 }
591 return path;
592}
593
594// static
596{
597 // Static pointers because of unloading problems wrt DSO's.
598 if (_themeOverride && !_themeOverride->isEmpty()) {
599 *_theme() = *_themeOverride();
600 }
601 if (!_theme()->isEmpty()) {
602 return *_theme();
603 }
604
605 QString theme;
606 // Check application specific config for a theme setting.
608 theme = app_cg.readEntry("Theme", QString());
609 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
610 // No theme, try to use Qt's. A Platform plugin might have set
611 // a good theme there.
612 theme = QIcon::themeName();
613 }
614 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
615 // Still no theme, try config with kdeglobals.
617 theme = cg.readEntry("Theme", QStringLiteral("breeze"));
618 }
619 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
620 // Still no good theme, use default.
621 theme = defaultThemeName();
622 }
623 *_theme() = theme;
624 return *_theme();
625}
626
628{
629 *_themeOverride() = themeName;
630 _theme()->clear(); // ::current sets this again based on conditions
631}
632
633// static
635{
636 // Static pointer because of unloading problems wrt DSO's.
637 if (!_theme_list()->isEmpty()) {
638 return *_theme_list();
639 }
640
641 // Find the theme description file. These are either locally in the :/icons resource path or global.
642 QStringList icnlibs;
643
644 // local embedded icons have preference
645 icnlibs << QStringLiteral(":/icons");
646
647 // global icons
649
650 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
652
653 for (const QString &iconDir : std::as_const(icnlibs)) {
654 QDir dir(iconDir);
655 const QStringList themeDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
656 for (const auto &theme : themeDirs) {
657 if (theme.startsWith(QLatin1String("default."))) {
658 continue;
659 }
660
661 const QString prefix = iconDir + QLatin1Char('/') + theme;
662 if (!QFileInfo::exists(prefix + QLatin1String("/index.desktop")) //
663 && !QFileInfo::exists(prefix + QLatin1String("/index.theme"))) {
664 continue;
665 }
666
667 if (!KIconTheme(theme).isValid()) {
668 continue;
669 }
670
671 if (!_theme_list()->contains(theme)) {
672 _theme_list()->append(theme);
673 }
674 }
675 }
676 return *_theme_list();
677}
678
679// static
681{
682 _theme()->clear();
683 _theme_list()->clear();
684}
685
686// static
688{
689 return QStringLiteral("hicolor");
690}
691
692/*** KIconThemeDir ***/
693
694KIconThemeDir::KIconThemeDir(const QString &basedir, const QString &themedir, const KConfigGroup &config)
695 : mSize(config.readEntry("Size", 0))
696 , mScale(config.readEntry("Scale", 1))
697 , mBaseDir(basedir)
698 , mThemeDir(themedir)
699{
700 if (mSize == 0) {
701 return;
702 }
703
704 QString tmp = config.readEntry(QStringLiteral("Context"));
705 if (tmp == QLatin1String("Devices")) {
706 mContext = KIconLoader::Device;
707 } else if (tmp == QLatin1String("MimeTypes")) {
708 mContext = KIconLoader::MimeType;
709 } else if (tmp == QLatin1String("Applications")) {
710 mContext = KIconLoader::Application;
711 } else if (tmp == QLatin1String("Actions")) {
712 mContext = KIconLoader::Action;
713 } else if (tmp == QLatin1String("Animations")) {
714 mContext = KIconLoader::Animation;
715 } else if (tmp == QLatin1String("Categories")) {
716 mContext = KIconLoader::Category;
717 } else if (tmp == QLatin1String("Emblems")) {
718 mContext = KIconLoader::Emblem;
719 } else if (tmp == QLatin1String("Emotes")) {
720 mContext = KIconLoader::Emote;
721 } else if (tmp == QLatin1String("International")) {
723 } else if (tmp == QLatin1String("Places")) {
724 mContext = KIconLoader::Place;
725 } else if (tmp == QLatin1String("Status")) {
726 mContext = KIconLoader::StatusIcon;
727 } else if (tmp == QLatin1String("Stock")) { // invalid, but often present context, skip warning
728 return;
729 } else if (tmp == QLatin1String("FileSystems")) { // invalid, but present context for hicolor, skip warning
730 return;
731 } else if (tmp == QLatin1String("Legacy")) { // invalid, but often present context for Adwaita, skip warning
732 return;
733 } else if (tmp == QLatin1String("UI")) { // invalid, but often present context for Adwaita, skip warning
734 return;
735 } else if (tmp.isEmpty()) {
736 // do nothing. key not required
737 } else {
738 qCDebug(KICONTHEMES) << "Invalid Context=" << tmp << "line for icon theme: " << constructFileName(QString());
739 return;
740 }
741 tmp = config.readEntry(QStringLiteral("Type"), QStringLiteral("Threshold"));
742 if (tmp == QLatin1String("Fixed")) {
743 mType = KIconLoader::Fixed;
744 } else if (tmp == QLatin1String("Scalable")) {
745 mType = KIconLoader::Scalable;
746 } else if (tmp == QLatin1String("Threshold")) {
748 } else {
749 qCDebug(KICONTHEMES) << "Invalid Type=" << tmp << "line for icon theme: " << constructFileName(QString());
750 return;
751 }
752 if (mType == KIconLoader::Scalable) {
753 mMinSize = config.readEntry(QStringLiteral("MinSize"), mSize);
754 mMaxSize = config.readEntry(QStringLiteral("MaxSize"), mSize);
755 } else if (mType == KIconLoader::Threshold) {
756 mThreshold = config.readEntry(QStringLiteral("Threshold"), 2);
757 }
758 mbValid = true;
759}
760
761QString KIconThemeDir::iconPath(const QString &name) const
762{
763 if (!mbValid) {
764 return QString();
765 }
766
767 const QString file = constructFileName(name);
768 if (QFileInfo::exists(file)) {
770 }
771
772 return QString();
773}
774
775QStringList KIconThemeDir::iconList() const
776{
777 const QDir icondir = constructFileName(QString());
778
779 const QStringList formats = QStringList() << QStringLiteral("*.png") << QStringLiteral("*.svg") << QStringLiteral("*.svgz") << QStringLiteral("*.xpm");
780 const QStringList lst = icondir.entryList(formats, QDir::Files);
781
782 QStringList result;
783 result.reserve(lst.size());
784 for (const QString &file : lst) {
785 result += constructFileName(file);
786 }
787 return result;
788}
QString readPathEntry(const char *key, const QString &aDefault) const
QString readEntry(const char *key, const char *aDefault=nullptr) const
Group
The group of the icon.
@ Small
Small icons, e.g. for buttons.
@ Panel
Panel (Plasma Taskbar) icons.
@ LastGroup
Last group.
@ Desktop
Desktop icons.
@ MainToolbar
Main toolbar icons.
@ Toolbar
Toolbar icons.
@ Dialog
Icons for use in dialog titles, page lists, etc.
Context
Defines the context of the icon.
Definition kiconloader.h:78
@ Category
An icon that represents a category.
Definition kiconloader.h:85
@ Emblem
An icon that adds information to an existing icon.
Definition kiconloader.h:86
@ StatusIcon
An icon that represents an event.
Definition kiconloader.h:90
@ Application
An icon that represents an application.
Definition kiconloader.h:81
@ Emote
An icon that expresses an emotion.
Definition kiconloader.h:87
@ Any
Some icon with unknown purpose.
Definition kiconloader.h:79
@ Place
An icon that represents a location (e.g. 'home', 'trash').
Definition kiconloader.h:89
@ MimeType
An icon that represents a mime type (or file type).
Definition kiconloader.h:83
@ Action
An action icon (e.g. 'save', 'print').
Definition kiconloader.h:80
@ International
An icon that represents a country's flag.
Definition kiconloader.h:88
@ Animation
An icon that is animated.
Definition kiconloader.h:84
@ Device
An icon that represents a device.
Definition kiconloader.h:82
Type
The type of the icon.
Definition kiconloader.h:97
@ Fixed
Fixed-size icon.
Definition kiconloader.h:98
@ Scalable
Scalable-size icon.
Definition kiconloader.h:99
@ Threshold
A threshold icon.
MatchType
The type of a match.
@ MatchExact
Only try to find an exact match.
@ MatchBestOrGreaterSize
Take the best match or the match with a greater size if there is no exact match.
static QStringList list()
List all icon themes installed on the system, global and local.
bool isValid() const
The icon theme exists?
QList< int > querySizes(KIconLoader::Group group) const
Query available sizes for a group.
QString iconPathByName(const QString &name, int size, KIconLoader::MatchType match) const
Lookup an icon in the theme.
QString internalName() const
The internal name of the icon theme (same as the name argument passed to the constructor).
QString screenshot() const
Return the name of the screenshot.
static void reconfigure()
Reconfigure the theme.
static void forceThemeForTests(const QString &themeName)
Force a current theme and disable automatic resolution of the current theme in favor of the forced th...
bool isHidden() const
The icon theme should be hidden to the user?
KIconTheme(const QString &name, const QString &appName=QString(), const QString &basePathHint=QString())
Load an icon theme by name.
QStringList queryIconsByContext(int size, KIconLoader::Context context=KIconLoader::Any) const
Query available icons for a context and preferred size.
QString description() const
A description for the icon theme.
static QString current()
Returns the current icon theme.
bool followsColorScheme() const
If true, this theme is made of SVG icons that will be colorized following the system color scheme.
QString dir() const
Returns the toplevel theme directory.
bool hasContext(KIconLoader::Context context) const
Returns true if the theme has any icons for the given context.
QString name() const
The stylized name of the icon theme.
QString iconPath(const QString &name, int size, KIconLoader::MatchType match) const
Lookup an icon in the theme.
QStringList inherits() const
The themes this icon theme falls back on.
QString example() const
Return the name of the "example" icon.
QStringList queryIcons(int size, KIconLoader::Context context=KIconLoader::Any) const
Query available icons for a size and context.
int defaultSize(KIconLoader::Group group) const
The default size of this theme for a certain icon group.
static QString defaultThemeName()
Returns the default icon theme.
int depth() const
The minimum display depth required for this theme.
static QString localizedFilePath(const QString &filePath)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
void initIcons()
QString path(const QString &relativePath)
KIOCORE_EXPORT QString dir(const QString &fileClass)
QStringList entryList(Filters filters, SortFlags sort) const const
bool exists() const const
bool exists(const QString &path)
bool isDir() const const
void setFallbackThemeName(const QString &name)
void setThemeName(const QString &name)
QString themeName()
void append(QList< T > &&value)
void reserve(qsizetype size)
qsizetype size() const const
bool registerResource(const QString &rccFileName, const QString &mapRoot)
bool unregisterResource(const QString &rccFileName, const QString &mapRoot)
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList standardLocations(StandardLocation type)
void clear()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype size() const const
CaseInsensitive
bool isValid() const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:15 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.