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

KDE's Doxygen guidelines are available online.