KIconThemes

kicontheme.cpp
1/*
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 <KColorSchemeManager>
17#include <KConfigGroup>
18#include <KLocalizedString> // KLocalizedString::localizedFilePath. Need such functionality in, hmm, QLocale? QStandardPaths?
19#include <KSharedConfig>
20
21#include <QAction>
22#include <QCoreApplication>
23#include <QDebug>
24#include <QDir>
25#include <QFileInfo>
26#include <QMap>
27#include <QResource>
28#include <QSet>
29#include <QTimer>
30
31#include <private/qguiapplication_p.h>
32#include <qpa/qplatformtheme.h>
33
34#include <qplatformdefs.h>
35
36#include <array>
37#include <cmath>
38
39#include "config.h"
40
41Q_GLOBAL_STATIC(QString, _themeOverride)
42
43#if !USE_BreezeIcons
44
45// on Android icon theme loading works differently and is managed by code in Kirigami
46// so don't actually touch anything icon-related here
47static void initThemeHelper()
48{
49 // postpone until QGuiApplication applies initial palette
50 QTimer::singleShot(0, [] {
51 // follow the system color, construct the global manager for that
53 });
54}
55
57{
58}
59
60#else
61
62#include <BreezeIcons>
63
64// do init only once and avoid later helpers to mess with it again
65static bool initThemeUsed = false;
66
67// startup function to set theme once the app got constructed
68static void initThemeHelper()
69{
70 // make sure we add application install path to search path, for e.g. bundles on Windows
71 if (initThemeUsed) {
72 // do that similar to QCoreApplicationPrivate::appendApplicationPathToLibraryPaths() with minimal extra API use
74 path.truncate(path.lastIndexOf(QLatin1Char('/')));
75 if (const QString ourPath = path + QStringLiteral("/kiconthemes6"); QFile::exists(ourPath)) {
77 }
78 }
79
80 // Makes sure the icon theme fallback is set to breeze or one of its
81 // variants. Most of our apps use "lots" of icons that most of the times
82 // are only available with breeze, we still honour the user icon theme
83 // but if the icon is not found there, we go to breeze since it's almost
84 // sure it'll be there
86
87 // ensure lib call above did the job
88 Q_ASSERT(!QIcon::fallbackThemeName().isEmpty());
89
90 // only do further stuff if we requested it
91 if (!initThemeUsed) {
92 return;
93 }
94
95 // do nothing if we have the proper platform theme already
96 if (QGuiApplicationPrivate::platformTheme() && QGuiApplicationPrivate::platformTheme()->name() == QLatin1String("kde")) {
97 return;
98 }
99
100 // get config, with fallback to kdeglobals
101 const auto config = KSharedConfig::openConfig();
102
103 // TODO: add Qt API to really fully override the engine
104 // https://codereview.qt-project.org/c/qt/qtbase/+/559108
105
106 // enforce the theme configured by the user, with kdeglobals fallback
107 // if not set, use Breeze
108 QString themeToUse = KConfigGroup(config, "Icons").readEntry("Theme", QStringLiteral("breeze"));
109 QIcon::setThemeName(themeToUse);
110 // Tell KIconTheme about the theme, in case KIconLoader is used directly
111 *_themeOverride() = themeToUse;
112 qCDebug(KICONTHEMES) << "KIconTheme::initTheme() enforces the icon theme:" << themeToUse;
113
114 // postpone until QGuiApplication applies initial palette
115 QTimer::singleShot(0, [] {
116 // follow the system color, construct the global manager for that
118 });
119}
120
122{
123 // inject paths only once
124 if (!initThemeUsed) {
125 // inject our icon engine in the search path
126 // it will be used as the first found engine for a suffix will be taken
127 // this must be done before the QCoreApplication is constructed
128 const auto paths = QCoreApplication::libraryPaths();
129 for (const auto &path : paths) {
130 if (const QString ourPath = path + QStringLiteral("/kiconthemes6"); QFile::exists(ourPath)) {
132 }
133 }
134 }
135
136 // initThemeHelper will do the remaining work via Q_COREAPP_STARTUP_FUNCTION(initThemeHelper) above
137 initThemeUsed = true;
138}
139
140#endif
141
142Q_COREAPP_STARTUP_FUNCTION(initThemeHelper)
143
144class KIconThemeDir;
145class KIconThemePrivate
146{
147public:
148 QString example, screenshot;
149 bool hidden;
150 KSharedConfig::Ptr sharedConfig;
151
152 struct GroupInfo {
154 const char *name;
155 int defaultSize;
156 QList<int> availableSizes{};
157 };
158 std::array<GroupInfo, KIconLoader::LastGroup> m_iconGroups = {{
159 {KIconLoader::Desktop, "Desktop", 32},
160 {KIconLoader::Toolbar, "Toolbar", 22},
161 {KIconLoader::MainToolbar, "MainToolbar", 22},
162 {KIconLoader::Small, "Small", 16},
163 {KIconLoader::Panel, "Panel", 48},
164 {KIconLoader::Dialog, "Dialog", 32},
165 }};
166
167 int mDepth;
168 QString mDir, mName, mInternalName, mDesc;
169 QStringList mInherits;
170 QStringList mExtensions;
172 QList<KIconThemeDir *> mScaledDirs;
173 bool followsColorScheme : 1;
174
175 /// Searches the given dirs vector for a matching icon
176 QString iconPath(const QList<KIconThemeDir *> &dirs, const QString &name, int size, qreal scale, KIconLoader::MatchType match) const;
177};
178Q_GLOBAL_STATIC(QString, _theme)
179Q_GLOBAL_STATIC(QStringList, _theme_list)
180
181/**
182 * A subdirectory in an icon theme.
183 */
184class KIconThemeDir
185{
186public:
187 KIconThemeDir(const QString &basedir, const QString &themedir, const KConfigGroup &config);
188
189 bool isValid() const
190 {
191 return mbValid;
192 }
193 QString iconPath(const QString &name) const;
194 QStringList iconList() const;
195 QString constructFileName(const QString &file) const
196 {
197 return mBaseDir + mThemeDir + QLatin1Char('/') + file;
198 }
199
200 KIconLoader::Context context() const
201 {
202 return mContext;
203 }
204 KIconLoader::Type type() const
205 {
206 return mType;
207 }
208 int size() const
209 {
210 return mSize;
211 }
212 int scale() const
213 {
214 return mScale;
215 }
216 int minSize() const
217 {
218 return mMinSize;
219 }
220 int maxSize() const
221 {
222 return mMaxSize;
223 }
224 int threshold() const
225 {
226 return mThreshold;
227 }
228
229private:
230 bool mbValid = false;
232 KIconLoader::Context mContext;
233 int mSize = 0;
234 int mScale = 1;
235 int mMinSize = 1;
236 int mMaxSize = 50;
237 int mThreshold = 2;
238
239 const QString mBaseDir;
240 const QString mThemeDir;
241};
242
243QString KIconThemePrivate::iconPath(const QList<KIconThemeDir *> &dirs, const QString &name, int size, qreal scale, KIconLoader::MatchType match) const
244{
246 QString tempPath; // used to cache icon path if it exists
247
248 int delta = -INT_MAX; // current icon size delta of 'icon'
249 int dw = INT_MAX; // icon size delta of current directory
250
251 // Rather downsample than upsample
252 int integerScale = std::ceil(scale);
253
254 // Search the directory that contains the icon which matches best to the requested
255 // size. If there is no directory which matches exactly to the requested size, the
256 // following criteria get applied:
257 // - Take a directory having icons with a minimum difference to the requested size.
258 // - Prefer directories that allow a downscaling even if the difference to
259 // the requested size is bigger than a directory where an upscaling is required.
260 for (KIconThemeDir *dir : dirs) {
261 if (dir->scale() != integerScale) {
262 continue;
263 }
264
265 if (match == KIconLoader::MatchExact) {
266 if ((dir->type() == KIconLoader::Fixed) && (dir->size() != size)) {
267 continue;
268 }
269 if ((dir->type() == KIconLoader::Scalable) //
270 && ((size < dir->minSize()) || (size > dir->maxSize()))) {
271 continue;
272 }
273 if ((dir->type() == KIconLoader::Threshold) //
274 && (abs(dir->size() - size) > dir->threshold())) {
275 continue;
276 }
277 } else {
278 // dw < 0 means need to scale up to get an icon of the requested size.
279 // Upscaling should only be done if no larger icon is available.
280 if (dir->type() == KIconLoader::Fixed) {
281 dw = dir->size() - size;
282 } else if (dir->type() == KIconLoader::Scalable) {
283 if (size < dir->minSize()) {
284 dw = dir->minSize() - size;
285 } else if (size > dir->maxSize()) {
286 dw = dir->maxSize() - size;
287 } else {
288 dw = 0;
289 }
290 } else if (dir->type() == KIconLoader::Threshold) {
291 if (size < dir->size() - dir->threshold()) {
292 dw = dir->size() - dir->threshold() - size;
293 } else if (size > dir->size() + dir->threshold()) {
294 dw = dir->size() + dir->threshold() - size;
295 } else {
296 dw = 0;
297 }
298 }
299 // Usually if the delta (= 'dw') of the current directory is
300 // not smaller than the delta (= 'delta') of the currently best
301 // matching icon, this candidate can be skipped. But skipping
302 // the candidate may only be done, if this does not imply
303 // in an upscaling of the icon (it is OK to use a directory with
304 // smaller icons that what we've already found, however).
305 if ((abs(dw) >= abs(delta)) && ((dw < 0) || (delta > 0))) {
306 continue;
307 }
308
309 if (match == KIconLoader::MatchBestOrGreaterSize && dw < 0) {
310 continue;
311 }
312 }
313
314 // cache the result of iconPath() call which checks if file exists
315 tempPath = dir->iconPath(name);
316
317 if (tempPath.isEmpty()) {
318 continue;
319 }
320
321 path = tempPath;
322
323 // if we got in MatchExact that far, we find no better
324 if (match == KIconLoader::MatchExact) {
325 return path;
326 }
327 delta = dw;
328 if (delta == 0) {
329 return path; // We won't find a better match anyway
330 }
331 }
332 return path;
333}
334
335KIconTheme::KIconTheme(const QString &name, const QString &appName, const QString &basePathHint)
336 : d(new KIconThemePrivate)
337{
338 d->mInternalName = name;
339
340 QStringList themeDirs;
341
342 // Applications can have local additions to the global "locolor" and
343 // "hicolor" icon themes. For these, the _global_ theme description
344 // files are used..
345
346 /* clang-format off */
347 if (!appName.isEmpty()
348 && (name == defaultThemeName()
349 || name == QLatin1String("hicolor")
350 || name == QLatin1String("locolor"))) { /* clang-format on */
351 const QString suffix = QLatin1Char('/') + appName + QLatin1String("/icons/") + name + QLatin1Char('/');
353 for (auto &cDir : dataDirs) {
354 cDir += suffix;
355 if (QFileInfo::exists(cDir)) {
356 themeDirs += cDir;
357 }
358 }
359
360 if (!basePathHint.isEmpty()) {
361 // Checks for dir existing are done below
362 themeDirs += basePathHint + QLatin1Char('/') + name + QLatin1Char('/');
363 }
364 }
365
366 // Find the theme description file. These are either locally in the :/icons resource path or global.
367 QStringList icnlibs;
368
369 // local embedded icons have preference
370 icnlibs << QStringLiteral(":/icons");
371
372#ifdef Q_OS_ANDROID
373 // Android icon theme installed by Kirigami
374 icnlibs << QStringLiteral("assets:/qml/org/kde/kirigami");
375#endif
376
377 // global icons
379
380 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
382
383 QString fileName;
384 QString mainSection;
385 const QString pathSuffix = QLatin1Char('/') + name + QLatin1Char('/');
386 const QLatin1String indexTheme("index.theme");
387 const QLatin1String indexDesktop("theme.desktop");
388 for (auto &iconDir : icnlibs) {
389 iconDir += pathSuffix;
390 const QFileInfo fi(iconDir);
391 if (!fi.exists() || !fi.isDir()) {
392 continue;
393 }
394 themeDirs.append(iconDir);
395
396 if (d->mDir.isEmpty()) {
397 QString possiblePath;
398 if (possiblePath = iconDir + indexTheme; QFileInfo::exists(possiblePath)) {
399 d->mDir = iconDir;
400 fileName = possiblePath;
401 mainSection = QStringLiteral("Icon Theme");
402 } else if (possiblePath = iconDir + indexDesktop; QFileInfo::exists(possiblePath)) {
403 d->mDir = iconDir;
404 fileName = possiblePath;
405 mainSection = QStringLiteral("KDE Icon Theme");
406 }
407 }
408 }
409
410 if (d->mDir.isEmpty()) {
411 qCDebug(KICONTHEMES) << "Icon theme" << name << "not found.";
412 return;
413 }
414
415 // Use KSharedConfig to avoid parsing the file many times, from each component.
416 // Need to keep a ref to it to make this useful
417 d->sharedConfig = KSharedConfig::openConfig(fileName, KConfig::SimpleConfig);
418
419 KConfigGroup cfg(d->sharedConfig, mainSection);
420 d->mName = cfg.readEntry("Name");
421 d->mDesc = cfg.readEntry("Comment");
422 d->mDepth = cfg.readEntry("DisplayDepth", 32);
423 d->mInherits = cfg.readEntry("Inherits", QStringList());
424 if (name != defaultThemeName()) {
425 for (auto &inheritedTheme : d->mInherits) {
426 if (inheritedTheme == QLatin1String("default")) {
427 inheritedTheme = defaultThemeName();
428 }
429 }
430 }
431
432 d->hidden = cfg.readEntry("Hidden", false);
433 d->followsColorScheme = cfg.readEntry("FollowsColorScheme", false);
434 d->example = cfg.readPathEntry("Example", QString());
435 d->screenshot = cfg.readPathEntry("ScreenShot", QString());
436 d->mExtensions =
437 cfg.readEntry("KDE-Extensions", QStringList{QStringLiteral(".png"), QStringLiteral(".svgz"), QStringLiteral(".svg"), QStringLiteral(".xpm")});
438
439 QSet<QString> addedDirs; // Used for avoiding duplicates.
440 const QStringList dirs = cfg.readPathEntry("Directories", QStringList()) + cfg.readPathEntry("ScaledDirectories", QStringList());
441 for (const auto &dirName : dirs) {
442 KConfigGroup cg(d->sharedConfig, dirName);
443 for (const auto &themeDir : std::as_const(themeDirs)) {
444 const QString currentDir(themeDir + dirName + QLatin1Char('/'));
445 if (!addedDirs.contains(currentDir) && QFileInfo::exists(currentDir)) {
446 addedDirs.insert(currentDir);
447 KIconThemeDir *dir = new KIconThemeDir(themeDir, dirName, cg);
448 if (dir->isValid()) {
449 if (dir->scale() > 1) {
450 d->mScaledDirs.append(dir);
451 } else {
452 d->mDirs.append(dir);
453 }
454 } else {
455 delete dir;
456 }
457 }
458 }
459 }
460
461 KConfigGroup cg(d->sharedConfig, mainSection);
462 for (auto &iconGroup : d->m_iconGroups) {
463 iconGroup.defaultSize = cg.readEntry(iconGroup.name + QLatin1String("Default"), iconGroup.defaultSize);
464 iconGroup.availableSizes = cg.readEntry(iconGroup.name + QLatin1String("Sizes"), QList<int>());
465 }
466}
467
468KIconTheme::~KIconTheme()
469{
470 qDeleteAll(d->mDirs);
471 qDeleteAll(d->mScaledDirs);
472}
473
475{
476 return d->mName;
477}
478
480{
481 return d->mInternalName;
482}
483
485{
486 return d->mDesc;
487}
488
490{
491 return d->example;
492}
493
495{
496 return d->screenshot;
497}
498
500{
501 return d->mDir;
502}
503
505{
506 return d->mInherits;
507}
508
510{
511 return !d->mDirs.isEmpty() || !d->mScaledDirs.isEmpty();
512}
513
515{
516 return d->hidden;
517}
518
520{
521 return d->mDepth;
522}
523
525{
526 if (group < 0 || group >= KIconLoader::LastGroup) {
527 qCWarning(KICONTHEMES) << "Invalid icon group:" << group << ", should be one of KIconLoader::Group";
528 return -1;
529 }
530 return d->m_iconGroups[group].defaultSize;
531}
532
534{
535 if (group < 0 || group >= KIconLoader::LastGroup) {
536 qCWarning(KICONTHEMES) << "Invalid icon group:" << group << ", should be one of KIconLoader::Group";
537 return QList<int>();
538 }
539 return d->m_iconGroups[group].availableSizes;
540}
541
542static bool isAnyOrDirContext(const KIconThemeDir *dir, KIconLoader::Context context)
543{
544 return context == KIconLoader::Any || context == dir->context();
545}
546
548{
549 // Try to find exact match
550 QStringList result;
551 const QList<KIconThemeDir *> listDirs = d->mDirs + d->mScaledDirs;
552 for (const KIconThemeDir *dir : listDirs) {
553 if (!isAnyOrDirContext(dir, context)) {
554 continue;
555 }
556
557 const int dirSize = dir->size();
558 if ((dir->type() == KIconLoader::Fixed && dirSize == size) //
559 || (dir->type() == KIconLoader::Scalable && size >= dir->minSize() && size <= dir->maxSize())
560 || (dir->type() == KIconLoader::Threshold && abs(size - dirSize) < dir->threshold())) {
561 result += dir->iconList();
562 }
563 }
564
565 return result;
566}
567
569{
570 int dw;
571
572 // We want all the icons for a given context, but we prefer icons
573 // of size "size" . Note that this may (will) include duplicate icons
574 // QStringList iconlist[34]; // 33 == 48-16+1
575 QStringList iconlist[128]; // 33 == 48-16+1
576 // Usually, only the 0, 6 (22-16), 10 (32-22), 16 (48-32 or 32-16),
577 // 26 (48-22) and 32 (48-16) will be used, but who knows if someone
578 // will make icon themes with different icon sizes.
579 const auto listDirs = d->mDirs + d->mScaledDirs;
580 for (KIconThemeDir *dir : listDirs) {
581 if (!isAnyOrDirContext(dir, context)) {
582 continue;
583 }
584 dw = abs(dir->size() - size);
585 iconlist[(dw < 127) ? dw : 127] += dir->iconList();
586 }
587
588 QStringList iconlistResult;
589 for (int i = 0; i < 128; i++) {
590 iconlistResult += iconlist[i];
591 }
592
593 return iconlistResult;
594}
595
597{
598 const auto listDirs = d->mDirs + d->mScaledDirs;
599 for (KIconThemeDir *dir : listDirs) {
600 if (isAnyOrDirContext(dir, context)) {
601 return true;
602 }
603 }
604 return false;
605}
606
608{
609 return iconPathByName(iconName, size, match, 1 /*scale*/);
610}
611
612QString KIconTheme::iconPathByName(const QString &iconName, int size, KIconLoader::MatchType match, qreal scale) const
613{
614 for (const QString &current : std::as_const(d->mExtensions)) {
615 const QString path = iconPath(iconName + current, size, match, scale);
616 if (!path.isEmpty()) {
617 return path;
618 }
619 }
620 return QString();
621}
622
624{
625 return d->followsColorScheme;
626}
627
629{
630 return iconPath(name, size, match, 1 /*scale*/);
631}
632
633QString KIconTheme::iconPath(const QString &name, int size, KIconLoader::MatchType match, qreal scale) const
634{
635 // first look for a scaled image at exactly the requested size
636 QString path = d->iconPath(d->mScaledDirs, name, size, scale, KIconLoader::MatchExact);
637
638 // then look for an unscaled one but request it at larger size so it doesn't become blurry
639 if (path.isEmpty()) {
640 path = d->iconPath(d->mDirs, name, size * scale, 1, match);
641 }
642 return path;
643}
644
645// static
647{
648 // Static pointers because of unloading problems wrt DSO's.
649 if (_themeOverride && !_themeOverride->isEmpty()) {
650 *_theme() = *_themeOverride();
651 }
652 if (!_theme()->isEmpty()) {
653 return *_theme();
654 }
655
656 QString theme;
657 // Check application specific config for a theme setting.
659 theme = app_cg.readEntry("Theme", QString());
660 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
661 // No theme, try to use Qt's. A Platform plugin might have set
662 // a good theme there.
663 theme = QIcon::themeName();
664 }
665 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
666 // Still no theme, try config with kdeglobals.
668 theme = cg.readEntry("Theme", QStringLiteral("breeze"));
669 }
670 if (theme.isEmpty() || theme == QLatin1String("hicolor")) {
671 // Still no good theme, use default.
672 theme = defaultThemeName();
673 }
674 *_theme() = theme;
675 return *_theme();
676}
677
679{
680 *_themeOverride() = themeName;
681 _theme()->clear(); // ::current sets this again based on conditions
682}
683
684// static
686{
687 // Static pointer because of unloading problems wrt DSO's.
688 if (!_theme_list()->isEmpty()) {
689 return *_theme_list();
690 }
691
692 // Find the theme description file. These are either locally in the :/icons resource path or global.
693 QStringList icnlibs;
694
695 // local embedded icons have preference
696 icnlibs << QStringLiteral(":/icons");
697
698 // global icons
700
701 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
703
704 for (const QString &iconDir : std::as_const(icnlibs)) {
705 QDir dir(iconDir);
706 const QStringList themeDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
707 for (const auto &theme : themeDirs) {
708 if (theme.startsWith(QLatin1String("default."))) {
709 continue;
710 }
711
712 const QString prefix = iconDir + QLatin1Char('/') + theme;
713 if (!QFileInfo::exists(prefix + QLatin1String("/index.desktop")) //
714 && !QFileInfo::exists(prefix + QLatin1String("/index.theme"))) {
715 continue;
716 }
717
718 if (!KIconTheme(theme).isValid()) {
719 continue;
720 }
721
722 if (!_theme_list()->contains(theme)) {
723 _theme_list()->append(theme);
724 }
725 }
726 }
727 return *_theme_list();
728}
729
730// static
732{
733 _theme()->clear();
734 _theme_list()->clear();
735}
736
737// static
739{
740 return QStringLiteral("hicolor");
741}
742
743/*** KIconThemeDir ***/
744
745KIconThemeDir::KIconThemeDir(const QString &basedir, const QString &themedir, const KConfigGroup &config)
746 : mSize(config.readEntry("Size", 0))
747 , mScale(config.readEntry("Scale", 1))
748 , mBaseDir(basedir)
749 , mThemeDir(themedir)
750{
751 if (mSize == 0) {
752 return;
753 }
754
755 QString tmp = config.readEntry("Context", QString());
756 if (tmp == QLatin1String("Devices")) {
757 mContext = KIconLoader::Device;
758 } else if (tmp == QLatin1String("MimeTypes")) {
759 mContext = KIconLoader::MimeType;
760 } else if (tmp == QLatin1String("Applications")) {
761 mContext = KIconLoader::Application;
762 } else if (tmp == QLatin1String("Actions")) {
763 mContext = KIconLoader::Action;
764 } else if (tmp == QLatin1String("Animations")) {
765 mContext = KIconLoader::Animation;
766 } else if (tmp == QLatin1String("Categories")) {
767 mContext = KIconLoader::Category;
768 } else if (tmp == QLatin1String("Emblems")) {
769 mContext = KIconLoader::Emblem;
770 } else if (tmp == QLatin1String("Emotes")) {
771 mContext = KIconLoader::Emote;
772 } else if (tmp == QLatin1String("International")) {
774 } else if (tmp == QLatin1String("Places")) {
775 mContext = KIconLoader::Place;
776 } else if (tmp == QLatin1String("Status")) {
777 mContext = KIconLoader::StatusIcon;
778 } else if (tmp == QLatin1String("Stock")) { // invalid, but often present context, skip warning
779 return;
780 } else if (tmp == QLatin1String("FileSystems")) { // invalid, but present context for hicolor, skip warning
781 return;
782 } else if (tmp == QLatin1String("Legacy")) { // invalid, but often present context for Adwaita, skip warning
783 return;
784 } else if (tmp == QLatin1String("UI")) { // invalid, but often present context for Adwaita, skip warning
785 return;
786 } else if (tmp.isEmpty()) {
787 // do nothing. key not required
788 } else {
789 qCDebug(KICONTHEMES) << "Invalid Context=" << tmp << "line for icon theme: " << constructFileName(QString());
790 return;
791 }
792 tmp = config.readEntry("Type", QStringLiteral("Threshold"));
793 if (tmp == QLatin1String("Fixed")) {
794 mType = KIconLoader::Fixed;
795 } else if (tmp == QLatin1String("Scalable")) {
796 mType = KIconLoader::Scalable;
797 } else if (tmp == QLatin1String("Threshold")) {
799 } else {
800 qCDebug(KICONTHEMES) << "Invalid Type=" << tmp << "line for icon theme: " << constructFileName(QString());
801 return;
802 }
803 if (mType == KIconLoader::Scalable) {
804 mMinSize = config.readEntry("MinSize", mSize);
805 mMaxSize = config.readEntry("MaxSize", mSize);
806 } else if (mType == KIconLoader::Threshold) {
807 mThreshold = config.readEntry("Threshold", 2);
808 }
809 mbValid = true;
810}
811
812QString KIconThemeDir::iconPath(const QString &name) const
813{
814 if (!mbValid) {
815 return QString();
816 }
817
818 const QString file = constructFileName(name);
819 if (QFileInfo::exists(file)) {
821 }
822
823 return QString();
824}
825
826QStringList KIconThemeDir::iconList() const
827{
828 const QDir icondir = constructFileName(QString());
829
830 const QStringList formats = QStringList() << QStringLiteral("*.png") << QStringLiteral("*.svg") << QStringLiteral("*.svgz") << QStringLiteral("*.xpm");
831 const QStringList lst = icondir.entryList(formats, QDir::Files);
832
833 QStringList result;
834 result.reserve(lst.size());
835 for (const QString &file : lst) {
836 result += constructFileName(file);
837 }
838 return result;
839}
static KColorSchemeManager * instance()
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:80
@ Category
An icon that represents a category.
Definition kiconloader.h:87
@ Emblem
An icon that adds information to an existing icon.
Definition kiconloader.h:88
@ StatusIcon
An icon that represents an event.
Definition kiconloader.h:92
@ Application
An icon that represents an application.
Definition kiconloader.h:83
@ Emote
An icon that expresses an emotion.
Definition kiconloader.h:89
@ Any
Some icon with unknown purpose.
Definition kiconloader.h:81
@ Place
An icon that represents a location (e.g. 'home', 'trash').
Definition kiconloader.h:91
@ MimeType
An icon that represents a mime type (or file type).
Definition kiconloader.h:85
@ Action
An action icon (e.g. 'save', 'print').
Definition kiconloader.h:82
@ International
An icon that represents a country's flag.
Definition kiconloader.h:90
@ Animation
An icon that is animated.
Definition kiconloader.h:86
@ Device
An icon that represents a device.
Definition kiconloader.h:84
Type
The type of the icon.
Definition kiconloader.h:99
@ Fixed
Fixed-size icon.
@ Scalable
Scalable-size icon.
@ 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.
static void initTheme()
Enforces the Breeze icon theme (including our KIconEngine for re-coloring).
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)
QString name(StandardAction id)
void addLibraryPath(const QString &path)
QString applicationFilePath()
QStringList libraryPaths()
QStringList entryList(Filters filters, SortFlags sort) const const
bool exists() const const
bool exists() const const
bool exists(const QString &path)
bool isDir() const const
QString fallbackThemeName()
void setThemeName(const QString &name)
QString themeName()
void append(QList< T > &&value)
void reserve(qsizetype size)
qsizetype size() const const
bool contains(const QSet< T > &other) const const
iterator insert(const T &value)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList standardLocations(StandardLocation type)
void clear()
bool isEmpty() const const
qsizetype lastIndexOf(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype size() const const
void truncate(qsizetype position)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:08:02 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.