• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • icons
kiconloader.cpp
Go to the documentation of this file.
1/* vi: ts=8 sts=4 sw=4
2 *
3 * kiconloader.cpp: An icon loader for KDE with theming functionality.
4 *
5 * This file is part of the KDE project, module kdeui.
6 * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
7 * Antonio Larrosa <larrosa@kde.org>
8 * 2010 Michael Pyne <mpyne@kde.org>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License version 2 as published by the Free Software Foundation.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
23 */
24
25#include "kiconloader.h"
26
27#include <sys/types.h>
28#include <stdlib.h> //for abs
29#include <unistd.h> //for readlink
30#include <dirent.h>
31#include <assert.h>
32
33#include <QtCore/QCache>
34#include <QtCore/QFileInfo>
35#include <QtCore/QDir>
36#include <QtCore/QBuffer>
37#include <QtCore/QDataStream>
38#include <QtCore/QByteArray>
39#include <QtCore/QStringBuilder> // % operator for QString
40#include <QtGui/QIcon>
41#include <QtGui/QImage>
42#include <QtGui/QMovie>
43#include <QtGui/QPainter>
44#include <QtGui/QPixmap>
45#include <QtGui/QPixmapCache>
46#ifndef _WIN32_WCE
47#include <QtSvg/QSvgRenderer>
48#endif
49
50// kdecore
51#include <kconfig.h>
52#include <kconfiggroup.h>
53#include <kdebug.h>
54#include <kstandarddirs.h>
55#include <kglobal.h>
56#include <kglobalsettings.h>
57#include <kcomponentdata.h>
58#include <kde_file.h>
59#include <kshareddatacache.h>
60
61// kdeui
62#include "kicontheme.h"
63#include "kiconeffect.h"
64#include "k3icon_p.h"
65
66// Used to make cache keys for icons with no group. Result type is QString*
67K_GLOBAL_STATIC_WITH_ARGS(QString, NULL_EFFECT_FINGERPRINT, (QString::fromLatin1("noeffect")))
68
69
72static bool pathIsRelative(const QString &path)
73{
74#ifdef Q_OS_UNIX
75 return (!path.isEmpty() && path[0] != QChar('/'));
76#else
77 return QDir::isRelativePath(path);
78#endif
79}
80
84struct PixmapWithPath
85{
86 QPixmap pixmap;
87 QString path;
88};
89
90/*** KIconThemeNode: A node in the icon theme dependancy tree. ***/
91
92class KIconThemeNode
93{
94public:
95
96 KIconThemeNode(KIconTheme *_theme);
97 ~KIconThemeNode();
98
99 void queryIcons(QStringList *lst, int size, KIconLoader::Context context) const;
100 void queryIconsByContext(QStringList *lst, int size, KIconLoader::Context context) const;
101 K3Icon findIcon(const QString& name, int size, KIconLoader::MatchType match) const;
102 void printTree(QString& dbgString) const;
103
104 KIconTheme *theme;
105};
106
107KIconThemeNode::KIconThemeNode(KIconTheme *_theme)
108{
109 theme = _theme;
110}
111
112KIconThemeNode::~KIconThemeNode()
113{
114 delete theme;
115}
116
117void KIconThemeNode::printTree(QString& dbgString) const
118{
119 /* This method doesn't have much sense anymore, so maybe it should
120 be removed in the (near?) future */
121 dbgString += '(';
122 dbgString += theme->name();
123 dbgString += ')';
124}
125
126void KIconThemeNode::queryIcons(QStringList *result,
127 int size, KIconLoader::Context context) const
128{
129 // add the icons of this theme to it
130 *result += theme->queryIcons(size, context);
131}
132
133void KIconThemeNode::queryIconsByContext(QStringList *result,
134 int size, KIconLoader::Context context) const
135{
136 // add the icons of this theme to it
137 *result += theme->queryIconsByContext(size, context);
138}
139
140K3Icon KIconThemeNode::findIcon(const QString& name, int size,
141 KIconLoader::MatchType match) const
142{
143 return theme->iconPath(name, size, match);
144}
145
146
147/*** KIconGroup: Icon type description. ***/
148
149struct KIconGroup
150{
151 int size;
152 bool alphaBlending;
153};
154
155
156/*** d pointer for KIconLoader. ***/
157class KIconLoaderPrivate
158{
159public:
160 KIconLoaderPrivate(KIconLoader *q)
161 : q(q)
162 , mpGroups(0)
163 , mIconCache(0)
164 {
165 }
166
167 ~KIconLoaderPrivate()
168 {
169 /* antlarr: There's no need to delete d->mpThemeRoot as it's already
170 deleted when the elements of d->links are deleted */
171 qDeleteAll(links);
172 delete[] mpGroups;
173 delete mIconCache;
174 }
175
179 void init( const QString& _appname, KStandardDirs *_dirs );
180
184 bool initIconThemes();
185
191 K3Icon findMatchingIcon(const QString& name, int size) const;
192
199 K3Icon findMatchingIconWithGenericFallbacks(const QString& name, int size) const;
200
205 void addAppThemes(const QString& appname);
206
212 void addBaseThemes(KIconThemeNode *node, const QString &appname);
213
219 void addInheritedThemes(KIconThemeNode *node, const QString &appname);
220
227 void addThemeByName(const QString &themename, const QString &appname);
228
233 QString unknownIconPath( int size ) const;
234
239 QString removeIconExtension(const QString &name) const;
240
247 void normalizeIconMetadata(KIconLoader::Group &group, int &size, int &state) const;
248
254 QString makeCacheKey(const QString &name, KIconLoader::Group group, const QStringList &overlays,
255 int size, int state) const;
256
263 QImage createIconImage(const QString &path, int size = 0);
264
269 void insertCachedPixmapWithPath(const QString &key, const QPixmap &data, const QString &path);
270
276 bool findCachedPixmapWithPath(const QString &key, QPixmap &data, QString &path);
277
278 KIconLoader *const q;
279
280 QStringList mThemesInTree;
281 KIconGroup *mpGroups;
282 KIconThemeNode *mpThemeRoot;
283 KStandardDirs *mpDirs;
284 KIconEffect mpEffect;
285 QList<KIconThemeNode *> links;
286
287 // This shares the icons across all processes
288 KSharedDataCache* mIconCache;
289
290 // This caches rendered QPixmaps in just this process.
291 QCache<QString, PixmapWithPath> mPixmapCache;
292
293 bool extraDesktopIconsLoaded :1;
294 // lazy loading: initIconThemes() is only needed when the "links" list is needed
295 // mIconThemeInited is used inside initIconThemes() to init only once
296 bool mIconThemeInited :1;
297 QString appname;
298
299 void drawOverlays(const KIconLoader *loader, KIconLoader::Group group, int state, QPixmap& pix, const QStringList& overlays);
300};
301
302class KIconLoaderGlobalData
303{
304public:
305 KIconLoaderGlobalData() {
306 const QStringList genericIconsFiles = KGlobal::dirs()->findAllResources("xdgdata-mime", "generic-icons");
307 //kDebug() << genericIconsFiles;
308 Q_FOREACH(const QString& file, genericIconsFiles) {
309 parseGenericIconsFiles(file);
310 }
311 }
312
313 QString genericIconFor(const QString& icon) const {
314 return m_genericIcons.value(icon);
315 }
316
317private:
318 void parseGenericIconsFiles(const QString& fileName);
319 QHash<QString, QString> m_genericIcons;
320};
321
322void KIconLoaderGlobalData::parseGenericIconsFiles(const QString& fileName)
323{
324 QFile file(fileName);
325 if (file.open(QIODevice::ReadOnly)) {
326 QTextStream stream(&file);
327 stream.setCodec("ISO 8859-1");
328 while (!stream.atEnd()) {
329 const QString line = stream.readLine();
330 if (line.isEmpty() || line[0] == '#')
331 continue;
332 const int pos = line.indexOf(':');
333 if (pos == -1) // syntax error
334 continue;
335 QString mimeIcon = line.left(pos);
336 const int slashindex = mimeIcon.indexOf(QLatin1Char('/'));
337 if (slashindex != -1) {
338 mimeIcon[slashindex] = QLatin1Char('-');
339 }
340
341 const QString genericIcon = line.mid(pos+1);
342 m_genericIcons.insert(mimeIcon, genericIcon);
343 //kDebug(264) << mimeIcon << "->" << genericIcon;
344 }
345 }
346}
347
348K_GLOBAL_STATIC(KIconLoaderGlobalData, s_globalData)
349
350void KIconLoaderPrivate::drawOverlays(const KIconLoader *iconLoader, KIconLoader::Group group, int state, QPixmap& pix, const QStringList& overlays)
351{
352 if (overlays.isEmpty()) {
353 return;
354 }
355
356 const int width = pix.size().width();
357 const int height = pix.size().height();
358 const int iconSize = qMin(width, height);
359 int overlaySize;
360
361 if (iconSize < 32) {
362 overlaySize = 8;
363 } else if (iconSize <= 48) {
364 overlaySize = 16;
365 } else if (iconSize <= 96) {
366 overlaySize = 22;
367 } else if (iconSize < 256) {
368 overlaySize = 32;
369 } else {
370 overlaySize = 64;
371 }
372
373 QPainter painter(&pix);
374
375 int count = 0;
376 foreach (const QString& overlay, overlays) {
377 // Ensure empty strings fill up a emblem spot
378 // Needed when you have several emblems to ensure they're always painted
379 // at the same place, even if one is not here
380 if (overlay.isEmpty()) {
381 ++count;
382 continue;
383 }
384
385 //TODO: should we pass in the kstate? it results in a slower
386 // path, and perhaps emblems should remain in the default state
387 // anyways?
388 const QPixmap pixmap = iconLoader->loadIcon(overlay, group, overlaySize, state, QStringList(), 0, true);
389
390 if (pixmap.isNull()) {
391 continue;
392 }
393
394 QPoint startPoint;
395 switch (count) {
396 case 0:
397 // bottom left corner
398 startPoint = QPoint(2, height - overlaySize - 2);
399 break;
400 case 1:
401 // bottom right corner
402 startPoint = QPoint(width - overlaySize - 2,
403 height - overlaySize - 2);
404 break;
405 case 2:
406 // top right corner
407 startPoint = QPoint(width - overlaySize - 2, 2);
408 break;
409 case 3:
410 // top left corner
411 startPoint = QPoint(2, 2);
412 break;
413 }
414
415 painter.drawPixmap(startPoint, pixmap);
416
417 ++count;
418 if (count > 3) {
419 break;
420 }
421 }
422}
423
424KIconLoader::KIconLoader(const QString& _appname, KStandardDirs *_dirs, QObject* parent)
425 : QObject(parent)
426{
427 setObjectName(_appname);
428 d = new KIconLoaderPrivate(this);
429
430 connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)),
431 this, SLOT(newIconLoader()));
432 d->init( _appname, _dirs );
433}
434
435KIconLoader::KIconLoader(const KComponentData &componentData, QObject* parent)
436 : QObject(parent)
437{
438 setObjectName(componentData.componentName());
439 d = new KIconLoaderPrivate(this);
440
441 connect(KGlobalSettings::self(), SIGNAL(iconChanged(int)),
442 this, SLOT(newIconLoader()));
443 d->init(componentData.componentName(), componentData.dirs());
444}
445
446void KIconLoader::reconfigure( const QString& _appname, KStandardDirs *_dirs )
447{
448 d->mIconCache->clear();
449 delete d;
450 d = new KIconLoaderPrivate(this);
451 d->init( _appname, _dirs );
452}
453
454void KIconLoaderPrivate::init( const QString& _appname, KStandardDirs *_dirs )
455{
456 extraDesktopIconsLoaded=false;
457 mIconThemeInited = false;
458 mpThemeRoot = 0;
459
460 if (_dirs)
461 mpDirs = _dirs;
462 else
463 mpDirs = KGlobal::dirs();
464
465 appname = _appname;
466 if (appname.isEmpty())
467 appname = KGlobal::mainComponent().componentName();
468
469 // Initialize icon cache
470 mIconCache = new KSharedDataCache("icon-cache", 10 * 1024 * 1024);
471 // Cost here is number of pixels, not size. So this is actually a bit
472 // smaller.
473 mPixmapCache.setMaxCost(10 * 1024 * 1024);
474
475 // These have to match the order in kicontheme.h
476 static const char * const groups[] = { "Desktop", "Toolbar", "MainToolbar", "Small", "Panel", "Dialog", 0L };
477 KSharedConfig::Ptr config = KGlobal::config();
478
479 // loading config and default sizes
480 initIconThemes();
481 KIconTheme *defaultSizesTheme = links.empty() ? 0 : links.first()->theme;
482 mpGroups = new KIconGroup[(int) KIconLoader::LastGroup];
483 for (KIconLoader::Group i = KIconLoader::FirstGroup; i < KIconLoader::LastGroup; ++i) {
484 if (groups[i] == 0L) {
485 break;
486 }
487
488 KConfigGroup cg(config, QLatin1String(groups[i]) + "Icons");
489 mpGroups[i].size = cg.readEntry("Size", 0);
490 if (QPixmap::defaultDepth() > 8) {
491 mpGroups[i].alphaBlending = cg.readEntry("AlphaBlending", true);
492 } else {
493 mpGroups[i].alphaBlending = false;
494 }
495
496 if (!mpGroups[i].size && defaultSizesTheme) {
497 mpGroups[i].size = defaultSizesTheme->defaultSize(i);
498 }
499 }
500}
501
502bool KIconLoaderPrivate::initIconThemes()
503{
504 if (mIconThemeInited) {
505 // If mpThemeRoot isn't 0 then initing has succeeded
506 return (mpThemeRoot != 0);
507 }
508 //kDebug(264);
509 mIconThemeInited = true;
510
511 // Add the default theme and its base themes to the theme tree
512 KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
513 if (!def->isValid())
514 {
515 delete def;
516 // warn, as this is actually a small penalty hit
517 kDebug(264) << "Couldn't find current icon theme, falling back to default.";
518 def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
519 if (!def->isValid())
520 {
521 kError(264) << "Error: standard icon theme" << KIconTheme::defaultThemeName() << "not found!" << endl;
522 delete def;
523 return false;
524 }
525 }
526 mpThemeRoot = new KIconThemeNode(def);
527 mThemesInTree.append(def->internalName());
528 links.append(mpThemeRoot);
529 addBaseThemes(mpThemeRoot, appname);
530
531 // Insert application specific themes at the top.
532 mpDirs->addResourceType("appicon", "data", appname + "/pics/");
533 // ################## KDE5: consider removing the toolbar directory
534 mpDirs->addResourceType("appicon", "data", appname + "/toolbar/");
535
536 // Add legacy icon dirs.
537 QStringList dirs;
538 dirs += mpDirs->resourceDirs("icon");
539 dirs += mpDirs->resourceDirs("pixmap");
540 dirs += mpDirs->resourceDirs("xdgdata-icon");
541 dirs += "/usr/share/pixmaps";
542 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
543 dirs += mpDirs->resourceDirs("xdgdata-pixmap");
544 for (QStringList::ConstIterator it = dirs.constBegin(); it != dirs.constEnd(); ++it)
545 mpDirs->addResourceDir("appicon", *it);
546
547#ifndef NDEBUG
548 QString dbgString = "Theme tree: ";
549 mpThemeRoot->printTree(dbgString);
550 kDebug(264) << dbgString;
551#endif
552
553 return true;
554}
555
556KIconLoader::~KIconLoader()
557{
558 delete d;
559}
560
561void KIconLoader::addAppDir(const QString& appname)
562{
563 d->initIconThemes();
564
565 d->mpDirs->addResourceType("appicon", "data", appname + "/pics/");
566 // ################## KDE5: consider removing the toolbar directory
567 d->mpDirs->addResourceType("appicon", "data", appname + "/toolbar/");
568 d->addAppThemes(appname);
569}
570
571void KIconLoaderPrivate::addAppThemes(const QString& appname)
572{
573 initIconThemes();
574
575 KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
576 if (!def->isValid()) {
577 delete def;
578 def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
579 }
580 KIconThemeNode* node = new KIconThemeNode(def);
581 bool addedToLinks = false;
582
583 if (!mThemesInTree.contains(node->theme->internalName())) {
584 mThemesInTree.append(node->theme->internalName());
585 links.append(node);
586 addedToLinks = true;
587 }
588 addBaseThemes(node, appname);
589
590 if (!addedToLinks) {
591 // Nodes in links are being deleted later - this one needs manual care.
592 delete node;
593 }
594}
595
596void KIconLoaderPrivate::addBaseThemes(KIconThemeNode *node, const QString &appname)
597{
598 // Quote from the icon theme specification:
599 // The lookup is done first in the current theme, and then recursively
600 // in each of the current theme's parents, and finally in the
601 // default theme called "hicolor" (implementations may add more
602 // default themes before "hicolor", but "hicolor" must be last).
603 //
604 // So we first make sure that all inherited themes are added, then we
605 // add the KDE default theme as fallback for all icons that might not be
606 // present in an inherited theme, and hicolor goes last.
607
608 addInheritedThemes(node, appname);
609 addThemeByName(KIconTheme::defaultThemeName(), appname);
610 addThemeByName("hicolor", appname);
611}
612
613void KIconLoaderPrivate::addInheritedThemes(KIconThemeNode *node, const QString &appname)
614{
615 const QStringList lst = node->theme->inherits();
616
617 for (QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it) {
618 if ((*it) == "hicolor") {
619 // The icon theme spec says that "hicolor" must be the very last
620 // of all inherited themes, so don't add it here but at the very end
621 // of addBaseThemes().
622 continue;
623 }
624 addThemeByName(*it, appname);
625 }
626}
627
628void KIconLoaderPrivate::addThemeByName(const QString &themename, const QString &appname)
629{
630 if (mThemesInTree.contains(themename + appname)) {
631 return;
632 }
633 KIconTheme *theme = new KIconTheme(themename, appname);
634 if (!theme->isValid()) {
635 delete theme;
636 return;
637 }
638 KIconThemeNode *n = new KIconThemeNode(theme);
639 mThemesInTree.append(themename + appname);
640 links.append(n);
641 addInheritedThemes(n, appname);
642}
643
644void KIconLoader::addExtraDesktopThemes()
645{
646 if ( d->extraDesktopIconsLoaded ) return;
647
648 d->initIconThemes();
649
650 QStringList list;
651 const QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
652 QStringList::ConstIterator it;
653 char buf[1000];
654 int r;
655 for (it=icnlibs.begin(); it!=icnlibs.end(); ++it)
656 {
657 QDir dir(*it);
658 if (!dir.exists())
659 continue;
660 const QStringList lst = dir.entryList(QStringList( "default.*" ), QDir::Dirs);
661 QStringList::ConstIterator it2;
662 for (it2=lst.begin(); it2!=lst.end(); ++it2)
663 {
664 if (!KStandardDirs::exists(*it + *it2 + "/index.desktop")
665 && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
666 continue;
667 r=readlink( QFile::encodeName(*it + *it2) , buf, sizeof(buf)-1);
668 if ( r>0 )
669 {
670 buf[r]=0;
671 const QDir dir2( buf );
672 QString themeName=dir2.dirName();
673
674 if (!list.contains(themeName))
675 list.append(themeName);
676 }
677 }
678 }
679
680 for (it = list.constBegin(); it != list.constEnd(); ++it)
681 {
682 // Don't add the KDE defaults once more, we have them anyways.
683 if (*it == QLatin1String("default.kde")
684 || *it == QLatin1String("default.kde4")) {
685 continue;
686 }
687 d->addThemeByName(*it, "");
688 }
689
690 d->extraDesktopIconsLoaded=true;
691
692}
693
694bool KIconLoader::extraDesktopThemesAdded() const
695{
696 return d->extraDesktopIconsLoaded;
697}
698
699void KIconLoader::drawOverlays(const QStringList &overlays, QPixmap &pixmap, KIconLoader::Group group, int state) const
700{
701 d->drawOverlays(this, group, state, pixmap, overlays);
702}
703
704QString KIconLoaderPrivate::removeIconExtension(const QString &name) const
705{
706 if (name.endsWith(QLatin1String(".png"))
707 || name.endsWith(QLatin1String(".xpm"))
708 || name.endsWith(QLatin1String(".svg"))) {
709 return name.left(name.length() - 4);
710 } else if (name.endsWith(QLatin1String(".svgz"))) {
711 return name.left(name.length() - 5);
712 }
713
714 return name;
715}
716
717void KIconLoaderPrivate::normalizeIconMetadata(KIconLoader::Group &group, int &size, int &state) const
718{
719 if ((state < 0) || (state >= KIconLoader::LastState))
720 {
721 kWarning(264) << "Illegal icon state: " << state;
722 state = KIconLoader::DefaultState;
723 }
724
725 if (size < 0) {
726 size = 0;
727 }
728
729 // For "User" icons, bail early since the size should be based on the size on disk,
730 // which we've already checked.
731 if (group == KIconLoader::User) {
732 return;
733 }
734
735 if ((group < -1) || (group >= KIconLoader::LastGroup))
736 {
737 kWarning(264) << "Illegal icon group: " << group;
738 group = KIconLoader::Desktop;
739 }
740
741 // If size == 0, use default size for the specified group.
742 if (size == 0)
743 {
744 if (group < 0)
745 {
746 kWarning(264) << "Neither size nor group specified!";
747 group = KIconLoader::Desktop;
748 }
749 size = mpGroups[group].size;
750 }
751}
752
753QString KIconLoaderPrivate::makeCacheKey(const QString &name, KIconLoader::Group group,
754 const QStringList &overlays, int size, int state) const
755{
756 // The KSharedDataCache is shared so add some namespacing. The following code
757 // uses QStringBuilder (new in Qt 4.6)
758
759 return (group == KIconLoader::User
760 ? QLatin1Literal("$kicou_")
761 : QLatin1Literal("$kico_"))
762 % name
763 % QLatin1Char('_')
764 % QString::number(size)
765 % QLatin1Char('_')
766 % overlays.join("_")
767 % ( group >= 0 ? mpEffect.fingerprint(group, state)
768 : *NULL_EFFECT_FINGERPRINT);
769}
770
771QImage KIconLoaderPrivate::createIconImage(const QString &path, int size)
772{
773 // Use the extension as the format. Works for XPM and PNG, but not for SVG. The
774 // "VGZ" is the last 3 characters of "SVGZ"
775 QString ext = path.right(3).toUpper();
776 QImage img;
777
778 if (ext != "SVG" && ext != "VGZ")
779 {
780 // Not a SVG or SVGZ
781 img = QImage(path, ext.toLatin1());
782
783 if (size != 0 && !img.isNull()) {
784 img = img.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
785 }
786 }
787 else
788 {
789#ifndef _WIN32_WCE
790 QSvgRenderer renderer(path, q);
791
792 if (renderer.isValid()) {
793 img = QImage(size, size, QImage::Format_ARGB32_Premultiplied);
794 img.fill(0);
795 QPainter p(&img);
796 renderer.render(&p);
797 }
798#endif
799 }
800
801 return img;
802}
803
804void KIconLoaderPrivate::insertCachedPixmapWithPath(
805 const QString &key,
806 const QPixmap &data,
807 const QString &path = QString())
808{
809 // Even if the pixmap is null, we add it to the caches so that we record
810 // the fact that whatever icon led to us getting a null pixmap doesn't
811 // exist.
812
813 QBuffer output;
814 output.open(QIODevice::WriteOnly);
815
816 QDataStream outputStream(&output);
817 outputStream.setVersion(QDataStream::Qt_4_6);
818
819 outputStream << path;
820
821 // Convert the QPixmap to PNG. This is actually done by Qt's own operator.
822 outputStream << data;
823
824 output.close();
825
826 // The byte array contained in the QBuffer is what we want in the cache.
827 mIconCache->insert(key, output.buffer());
828
829 // Also insert the object into our process-local cache for even more
830 // speed.
831 PixmapWithPath *pixmapPath = new PixmapWithPath;
832 pixmapPath->pixmap = data;
833 pixmapPath->path = path;
834
835 mPixmapCache.insert(key, pixmapPath, data.width() * data.height() + 1);
836}
837
838bool KIconLoaderPrivate::findCachedPixmapWithPath(const QString &key, QPixmap &data, QString &path)
839{
840 // If the pixmap is present in our local process cache, use that since we
841 // don't need to decompress and upload it to the X server/graphics card.
842 const PixmapWithPath *pixmapPath = mPixmapCache.object(key);
843 if (pixmapPath) {
844 path = pixmapPath->path;
845 data = pixmapPath->pixmap;
846
847 return true;
848 }
849
850 // Otherwise try to find it in our shared memory cache since that will
851 // be quicker than the disk, especially for SVGs.
852 QByteArray result;
853
854 if (!mIconCache->find(key, &result) || result.isEmpty()) {
855 return false;
856 }
857
858 QBuffer buffer;
859 buffer.setBuffer(&result);
860 buffer.open(QIODevice::ReadOnly);
861
862 QDataStream inputStream(&buffer);
863 inputStream.setVersion(QDataStream::Qt_4_6);
864
865 QString tempPath;
866 inputStream >> tempPath;
867
868 if (inputStream.status() == QDataStream::Ok) {
869 QPixmap tempPixmap;
870 inputStream >> tempPixmap;
871
872 if (inputStream.status() == QDataStream::Ok) {
873 data = tempPixmap;
874 path = tempPath;
875
876 // Since we're here we didn't have a QPixmap cache entry, add one now.
877 PixmapWithPath *newPixmapWithPath = new PixmapWithPath;
878 newPixmapWithPath->pixmap = data;
879 newPixmapWithPath->path = path;
880
881 mPixmapCache.insert(key, newPixmapWithPath, data.width() * data.height() + 1);
882
883 return true;
884 }
885 }
886
887 return false;
888}
889
890K3Icon KIconLoaderPrivate::findMatchingIconWithGenericFallbacks(const QString& name, int size) const
891{
892 K3Icon icon = findMatchingIcon(name, size);
893 if (icon.isValid())
894 return icon;
895
896 const QString genericIcon = s_globalData->genericIconFor(name);
897 if (!genericIcon.isEmpty()) {
898 icon = findMatchingIcon(genericIcon, size);
899 }
900 return icon;
901}
902
903K3Icon KIconLoaderPrivate::findMatchingIcon(const QString& name, int size) const
904{
905 const_cast<KIconLoaderPrivate*>(this)->initIconThemes();
906
907 K3Icon icon;
908
909 const char * const ext[4] = { ".png", ".svgz", ".svg", ".xpm" };
910 bool genericFallback = name.endsWith(QLatin1String("-x-generic"));
911
912 // Do two passes through themeNodes.
913 //
914 // The first pass looks for an exact match in each themeNode one after the other.
915 // If one is found and it is an app icon then return that icon.
916 //
917 // In the next pass (assuming the first pass failed), it looks for exact matches
918 // and then generic fallbacks in each themeNode one after the other
919 //
920 // The reasoning is that application icons should always match exactly, all other
921 // icons may fallback. Since we do not know what the context is here when we start
922 // looking for it, we can only go by the path found.
923 foreach (KIconThemeNode *themeNode, links) {
924 for (int i = 0 ; i < 4 ; i++) {
925 icon = themeNode->theme->iconPath(name + ext[i], size, KIconLoader::MatchExact);
926 if (icon.isValid()) {
927 break;
928 }
929
930 icon = themeNode->theme->iconPath(name + ext[i], size, KIconLoader::MatchBest);
931 if (icon.isValid()) {
932 break;
933 }
934 }
935
936 if (icon.isValid() && icon.path.contains("/apps/")) {
937 return icon;
938 }
939 }
940
941 foreach (KIconThemeNode *themeNode, links) {
942 QString currentName = name;
943
944 while (!currentName.isEmpty()) {
945 //kDebug(264) << "Looking up" << currentName;
946
947 for (int i = 0 ; i < 4 ; i++) {
948 icon = themeNode->theme->iconPath(currentName + ext[i], size, KIconLoader::MatchExact);
949 if (icon.isValid()) {
950 return icon;
951 }
952
953 icon = themeNode->theme->iconPath(currentName + ext[i], size, KIconLoader::MatchBest);
954 if (icon.isValid()) {
955 return icon;
956 }
957 }
958 //kDebug(264) << "Looking up" << currentName;
959
960 if (genericFallback) {
961 // we already tested the base name
962 break;
963 }
964
965 int rindex = currentName.lastIndexOf('-');
966 if (rindex > 1) { // > 1 so that we don't split x-content or x-epoc
967 currentName.truncate(rindex);
968
969 if (currentName.endsWith(QLatin1String("-x")))
970 currentName.chop(2);
971 } else {
972 // From update-mime-database.c
973 static const QSet<QString> mediaTypes = QSet<QString>()
974 << "text" << "application" << "image" << "audio"
975 << "inode" << "video" << "message" << "model" << "multipart"
976 << "x-content" << "x-epoc";
977 // Shared-mime-info spec says:
978 // "If [generic-icon] is not specified then the mimetype is used to generate the
979 // generic icon by using the top-level media type (e.g. "video" in "video/ogg")
980 // and appending "-x-generic" (i.e. "video-x-generic" in the previous example)."
981 if (mediaTypes.contains(currentName)) {
982 currentName += QLatin1String("-x-generic");
983 genericFallback = true;
984 } else {
985 break;
986 }
987 }
988 }
989 }
990 return icon;
991}
992
993inline QString KIconLoaderPrivate::unknownIconPath( int size ) const
994{
995 static const QString &str_unknown = KGlobal::staticQString("unknown");
996
997 K3Icon icon = findMatchingIcon(str_unknown, size);
998 if (!icon.isValid())
999 {
1000 kDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
1001 << size << endl;
1002 return QString();
1003 }
1004 return icon.path;
1005}
1006
1007// Finds the absolute path to an icon.
1008
1009QString KIconLoader::iconPath(const QString& _name, int group_or_size,
1010 bool canReturnNull) const
1011{
1012 if (!d->initIconThemes()) {
1013 return QString();
1014 }
1015
1016 if (_name.isEmpty() || !pathIsRelative(_name))
1017 {
1018 // we have either an absolute path or nothing to work with
1019 return _name;
1020 }
1021
1022 QString name = d->removeIconExtension( _name );
1023
1024 QString path;
1025 if (group_or_size == KIconLoader::User)
1026 {
1027 static const QString &png_ext = KGlobal::staticQString(".png");
1028 static const QString &xpm_ext = KGlobal::staticQString(".xpm");
1029 path = d->mpDirs->findResource("appicon", name + png_ext);
1030
1031 static const QString &svgz_ext = KGlobal::staticQString(".svgz");
1032 static const QString &svg_ext = KGlobal::staticQString(".svg");
1033 if (path.isEmpty())
1034 path = d->mpDirs->findResource("appicon", name + svgz_ext);
1035 if (path.isEmpty())
1036 path = d->mpDirs->findResource("appicon", name + svg_ext);
1037 if (path.isEmpty())
1038 path = d->mpDirs->findResource("appicon", name + xpm_ext);
1039 return path;
1040 }
1041
1042 if (group_or_size >= KIconLoader::LastGroup)
1043 {
1044 kDebug(264) << "Illegal icon group: " << group_or_size;
1045 return path;
1046 }
1047
1048 int size;
1049 if (group_or_size >= 0)
1050 size = d->mpGroups[group_or_size].size;
1051 else
1052 size = -group_or_size;
1053
1054 if (_name.isEmpty()) {
1055 if (canReturnNull)
1056 return QString();
1057 else
1058 return d->unknownIconPath(size);
1059 }
1060
1061 K3Icon icon = d->findMatchingIconWithGenericFallbacks(name, size);
1062
1063 if (!icon.isValid())
1064 {
1065 // Try "User" group too.
1066 path = iconPath(name, KIconLoader::User, true);
1067 if (!path.isEmpty() || canReturnNull)
1068 return path;
1069
1070 return d->unknownIconPath(size);
1071 }
1072 return icon.path;
1073}
1074
1075QPixmap KIconLoader::loadMimeTypeIcon( const QString& _iconName, KIconLoader::Group group, int size,
1076 int state, const QStringList& overlays, QString *path_store ) const
1077{
1078 QString iconName = _iconName;
1079 const int slashindex = iconName.indexOf(QLatin1Char('/'));
1080 if (slashindex != -1) {
1081 iconName[slashindex] = QLatin1Char('-');
1082 }
1083
1084 if ( !d->extraDesktopIconsLoaded )
1085 {
1086 const QPixmap pixmap = loadIcon( iconName, group, size, state, overlays, path_store, true );
1087 if (!pixmap.isNull() ) {
1088 return pixmap;
1089 }
1090 const_cast<KIconLoader *>(this)->addExtraDesktopThemes();
1091 }
1092 const QPixmap pixmap = loadIcon(iconName, group, size, state, overlays, path_store, true);
1093 if (pixmap.isNull()) {
1094 // Icon not found, fallback to application/octet-stream
1095 return loadIcon("application-octet-stream", group, size, state, overlays, path_store, false);
1096 }
1097 return pixmap;
1098}
1099
1100QPixmap KIconLoader::loadIcon(const QString& _name, KIconLoader::Group group, int size,
1101 int state, const QStringList& overlays,
1102 QString *path_store, bool canReturnNull) const
1103{
1104 QString name = _name;
1105 bool favIconOverlay = false;
1106
1107 if (size < 0 || _name.isEmpty())
1108 return QPixmap();
1109
1110 /*
1111 * This method works in a kind of pipeline, with the following steps:
1112 * 1. Sanity checks.
1113 * 2. Convert _name, group, size, etc. to a key name.
1114 * 3. Check if the key is already cached.
1115 * 4. If not, initialize the theme and find/load the icon.
1116 * 4a Apply overlays
1117 * 4b Re-add to cache.
1118 */
1119
1120 // Special case for absolute path icons.
1121 if (name.startsWith(QLatin1String("favicons/")))
1122 {
1123 favIconOverlay = true;
1124 name = KStandardDirs::locateLocal("cache", name+".png");
1125 }
1126
1127 bool absolutePath = !pathIsRelative(name);
1128 if (!absolutePath) {
1129 name = d->removeIconExtension(name);
1130 }
1131
1132 // Don't bother looking for an icon with no name.
1133 if (name.isEmpty()) {
1134 return QPixmap();
1135 }
1136
1137 // May modify group, size, or state. This function puts them into sane
1138 // states.
1139 d->normalizeIconMetadata(group, size, state);
1140
1141 // See if the image is already cached.
1142 QString key = d->makeCacheKey(name, group, overlays, size, state);
1143 QPixmap pix;
1144 bool iconWasUnknown = false;
1145 K3Icon icon;
1146
1147 // icon.path would be empty for "unknown" icons, which should be searched for
1148 // anew each time.
1149 if (d->findCachedPixmapWithPath(key, pix, icon.path) && !icon.path.isEmpty()) {
1150 if (path_store) {
1151 *path_store = icon.path;
1152 }
1153
1154 return pix;
1155 }
1156
1157 // Image is not cached... go find it and apply effects.
1158 if (!d->initIconThemes()) {
1159 return QPixmap();
1160 }
1161
1162 favIconOverlay = favIconOverlay && size > 22;
1163
1164 // First we look for non-User icons. If we don't find one we'd search in
1165 // the User space anyways...
1166 if (group != KIconLoader::User) {
1167 // K3Icon seems to hold some needed information.
1168
1169 if (absolutePath && !favIconOverlay)
1170 {
1171 icon.context = KIconLoader::Any;
1172 icon.type = KIconLoader::Scalable;
1173 icon.path = name;
1174 }
1175 else
1176 {
1177 icon = d->findMatchingIconWithGenericFallbacks(favIconOverlay ? QString("text-html") : name, size);
1178 }
1179 }
1180
1181 if (icon.path.isEmpty()) {
1182 // We do have a "User" icon, or we couldn't find the non-User one.
1183 icon.path = (absolutePath) ? name :
1184 iconPath(name, KIconLoader::User, canReturnNull);
1185 }
1186
1187 // Still can't find it? Use "unknown" if we can't return null.
1188 // We keep going in the function so we can ensure this result gets cached.
1189 if (icon.path.isEmpty() && !canReturnNull) {
1190 icon.path = d->unknownIconPath(size);
1191 iconWasUnknown = true;
1192 }
1193
1194 QImage img = d->createIconImage(icon.path, size);
1195
1196 if (group >= 0)
1197 {
1198 img = d->mpEffect.apply(img, group, state);
1199 }
1200
1201 if (favIconOverlay)
1202 {
1203 QImage favIcon(name, "PNG");
1204 if (!favIcon.isNull()) // if favIcon not there yet, don't try to blend it
1205 {
1206 QPainter p(&img);
1207
1208 // Align the favicon overlay
1209 QRect r(favIcon.rect());
1210 r.moveBottomRight(img.rect().bottomRight());
1211 r.adjust(-1, -1, -1, -1); // Move off edge
1212
1213 // Blend favIcon over img.
1214 p.drawImage(r, favIcon);
1215 }
1216 }
1217
1218 pix = QPixmap::fromImage(img);
1219
1220 // TODO: If we make a loadIcon that returns the image we can convert
1221 // drawOverlays to use the image instead of pixmaps as well so we don't
1222 // have to transfer so much to the graphics card.
1223 d->drawOverlays(this, group, state, pix, overlays);
1224
1225 // Don't add the path to our unknown icon to the cache, only cache the
1226 // actual image.
1227 if (iconWasUnknown) {
1228 icon.path.clear();
1229 }
1230
1231 d->insertCachedPixmapWithPath(key, pix, icon.path);
1232
1233 if (path_store) {
1234 *path_store = icon.path;
1235 }
1236
1237 return pix;
1238}
1239
1240QMovie *KIconLoader::loadMovie(const QString& name, KIconLoader::Group group, int size, QObject *parent) const
1241{
1242 QString file = moviePath( name, group, size );
1243 if (file.isEmpty())
1244 return 0;
1245 int dirLen = file.lastIndexOf('/');
1246 QString icon = iconPath(name, size ? -size : group, true);
1247 if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
1248 return 0;
1249 QMovie *movie = new QMovie(file, QByteArray(), parent);
1250 if (!movie->isValid())
1251 {
1252 delete movie;
1253 return 0;
1254 }
1255 return movie;
1256}
1257
1258QString KIconLoader::moviePath(const QString& name, KIconLoader::Group group, int size) const
1259{
1260 if (!d->mpGroups) return QString();
1261
1262 d->initIconThemes();
1263
1264 if ( (group < -1 || group >= KIconLoader::LastGroup) && group != KIconLoader::User )
1265 {
1266 kDebug(264) << "Illegal icon group: " << group;
1267 group = KIconLoader::Desktop;
1268 }
1269 if (size == 0 && group < 0)
1270 {
1271 kDebug(264) << "Neither size nor group specified!";
1272 group = KIconLoader::Desktop;
1273 }
1274
1275 QString file = name + ".mng";
1276 if (group == KIconLoader::User)
1277 {
1278 file = d->mpDirs->findResource("appicon", file);
1279 }
1280 else
1281 {
1282 if (size == 0)
1283 size = d->mpGroups[group].size;
1284
1285 K3Icon icon;
1286
1287 foreach(KIconThemeNode *themeNode, d->links)
1288 {
1289 icon = themeNode->theme->iconPath(file, size, KIconLoader::MatchExact);
1290 if (icon.isValid())
1291 break;
1292 }
1293
1294 if ( !icon.isValid() )
1295 {
1296 foreach(KIconThemeNode *themeNode, d->links)
1297 {
1298 icon = themeNode->theme->iconPath(file, size, KIconLoader::MatchBest);
1299 if (icon.isValid())
1300 break;
1301 }
1302 }
1303
1304 file = icon.isValid() ? icon.path : QString();
1305 }
1306 return file;
1307}
1308
1309
1310QStringList KIconLoader::loadAnimated(const QString& name, KIconLoader::Group group, int size) const
1311{
1312 QStringList lst;
1313
1314 if (!d->mpGroups) return lst;
1315
1316 d->initIconThemes();
1317
1318 if ((group < -1) || (group >= KIconLoader::LastGroup))
1319 {
1320 kDebug(264) << "Illegal icon group: " << group;
1321 group = KIconLoader::Desktop;
1322 }
1323 if ((size == 0) && (group < 0))
1324 {
1325 kDebug(264) << "Neither size nor group specified!";
1326 group = KIconLoader::Desktop;
1327 }
1328
1329 QString file = name + "/0001";
1330 if (group == KIconLoader::User)
1331 {
1332 file = d->mpDirs->findResource("appicon", file + ".png");
1333 } else
1334 {
1335 if (size == 0)
1336 size = d->mpGroups[group].size;
1337 K3Icon icon = d->findMatchingIcon(file, size);
1338 file = icon.isValid() ? icon.path : QString();
1339
1340 }
1341 if (file.isEmpty())
1342 return lst;
1343
1344 QString path = file.left(file.length()-8);
1345 DIR* dp = opendir( QFile::encodeName(path) );
1346 if(!dp)
1347 return lst;
1348
1349 KDE_struct_dirent* ep;
1350 while( ( ep = KDE_readdir( dp ) ) != 0L )
1351 {
1352 QString fn(QFile::decodeName(ep->d_name));
1353 if(!(fn.left(4)).toUInt())
1354 continue;
1355
1356 lst += path + fn;
1357 }
1358 closedir ( dp );
1359 lst.sort();
1360 return lst;
1361}
1362
1363KIconTheme *KIconLoader::theme() const
1364{
1365 d->initIconThemes();
1366 if (d->mpThemeRoot) return d->mpThemeRoot->theme;
1367 return 0L;
1368}
1369
1370int KIconLoader::currentSize(KIconLoader::Group group) const
1371{
1372 if (!d->mpGroups) return -1;
1373
1374 if (group < 0 || group >= KIconLoader::LastGroup)
1375 {
1376 kDebug(264) << "Illegal icon group: " << group;
1377 return -1;
1378 }
1379 return d->mpGroups[group].size;
1380}
1381
1382QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
1383{
1384 const QDir dir(iconsDir);
1385 const QStringList formats = QStringList() << "*.png" << "*.xpm" << "*.svg" << "*.svgz";
1386 const QStringList lst = dir.entryList(formats, QDir::Files);
1387 QStringList result;
1388 QStringList::ConstIterator it;
1389 for (it=lst.begin(); it!=lst.end(); ++it)
1390 result += iconsDir + '/' + *it;
1391 return result;
1392}
1393
1394QStringList KIconLoader::queryIconsByContext(int group_or_size,
1395 KIconLoader::Context context) const
1396{
1397 d->initIconThemes();
1398
1399 QStringList result;
1400 if (group_or_size >= KIconLoader::LastGroup)
1401 {
1402 kDebug(264) << "Illegal icon group: " << group_or_size;
1403 return result;
1404 }
1405 int size;
1406 if (group_or_size >= 0)
1407 size = d->mpGroups[group_or_size].size;
1408 else
1409 size = -group_or_size;
1410
1411 foreach(KIconThemeNode *themeNode, d->links)
1412 themeNode->queryIconsByContext(&result, size, context);
1413
1414 // Eliminate duplicate entries (same icon in different directories)
1415 QString name;
1416 QStringList res2, entries;
1417 QStringList::ConstIterator it;
1418 for (it=result.constBegin(); it!=result.constEnd(); ++it)
1419 {
1420 int n = (*it).lastIndexOf('/');
1421 if (n == -1)
1422 name = *it;
1423 else
1424 name = (*it).mid(n+1);
1425 name = d->removeIconExtension(name);
1426 if (!entries.contains(name))
1427 {
1428 entries += name;
1429 res2 += *it;
1430 }
1431 }
1432 return res2;
1433
1434}
1435
1436QStringList KIconLoader::queryIcons(int group_or_size, KIconLoader::Context context) const
1437{
1438 d->initIconThemes();
1439
1440 QStringList result;
1441 if (group_or_size >= KIconLoader::LastGroup)
1442 {
1443 kDebug(264) << "Illegal icon group: " << group_or_size;
1444 return result;
1445 }
1446 int size;
1447 if (group_or_size >= 0)
1448 size = d->mpGroups[group_or_size].size;
1449 else
1450 size = -group_or_size;
1451
1452 foreach(KIconThemeNode *themeNode, d->links)
1453 themeNode->queryIcons(&result, size, context);
1454
1455 // Eliminate duplicate entries (same icon in different directories)
1456 QString name;
1457 QStringList res2, entries;
1458 QStringList::ConstIterator it;
1459 for (it=result.constBegin(); it!=result.constEnd(); ++it)
1460 {
1461 int n = (*it).lastIndexOf('/');
1462 if (n == -1)
1463 name = *it;
1464 else
1465 name = (*it).mid(n+1);
1466 name = d->removeIconExtension(name);
1467 if (!entries.contains(name))
1468 {
1469 entries += name;
1470 res2 += *it;
1471 }
1472 }
1473 return res2;
1474}
1475
1476// used by KIconDialog to find out which contexts to offer in a combobox
1477bool KIconLoader::hasContext(KIconLoader::Context context) const
1478{
1479 d->initIconThemes();
1480
1481 foreach(KIconThemeNode *themeNode, d->links)
1482 if( themeNode->theme->hasContext( context ))
1483 return true;
1484 return false;
1485}
1486
1487KIconEffect * KIconLoader::iconEffect() const
1488{
1489 return &d->mpEffect;
1490}
1491
1492bool KIconLoader::alphaBlending(KIconLoader::Group group) const
1493{
1494 if (!d->mpGroups) return false;
1495
1496 if (group < 0 || group >= KIconLoader::LastGroup)
1497 {
1498 kDebug(264) << "Illegal icon group: " << group;
1499 return false;
1500 }
1501 return d->mpGroups[group].alphaBlending;
1502}
1503
1504// deprecated
1505#ifndef KDE_NO_DEPRECATED
1506QIcon KIconLoader::loadIconSet( const QString& name, KIconLoader::Group g, int s,
1507 bool canReturnNull )
1508{
1509 QIcon iconset;
1510 QPixmap tmp = loadIcon(name, g, s, KIconLoader::ActiveState, QStringList(), NULL, canReturnNull);
1511 iconset.addPixmap( tmp, QIcon::Active, QIcon::On );
1512 // we don't use QIconSet's resizing anyway
1513 tmp = loadIcon(name, g, s, KIconLoader::DisabledState, QStringList(), NULL, canReturnNull);
1514 iconset.addPixmap( tmp, QIcon::Disabled, QIcon::On );
1515 tmp = loadIcon(name, g, s, KIconLoader::DefaultState, QStringList(), NULL, canReturnNull);
1516 iconset.addPixmap( tmp, QIcon::Normal, QIcon::On );
1517 return iconset;
1518}
1519#endif
1520
1521// Easy access functions
1522
1523QPixmap DesktopIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1524{
1525 KIconLoader *loader = KIconLoader::global();
1526 return loader->loadIcon(name, KIconLoader::Desktop, force_size, state, overlays);
1527}
1528
1529// deprecated
1530#ifndef KDE_NO_DEPRECATED
1531QIcon DesktopIconSet(const QString& name, int force_size)
1532{
1533 KIconLoader *loader = KIconLoader::global();
1534 return loader->loadIconSet(name, KIconLoader::Desktop, force_size);
1535}
1536#endif
1537
1538QPixmap BarIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1539{
1540 KIconLoader *loader = KIconLoader::global();
1541 return loader->loadIcon(name, KIconLoader::Toolbar, force_size, state, overlays);
1542}
1543
1544// deprecated
1545#ifndef KDE_NO_DEPRECATED
1546QIcon BarIconSet(const QString& name, int force_size)
1547{
1548 KIconLoader *loader = KIconLoader::global();
1549 return loader->loadIconSet( name, KIconLoader::Toolbar, force_size );
1550}
1551#endif
1552
1553QPixmap SmallIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1554{
1555 KIconLoader *loader = KIconLoader::global();
1556 return loader->loadIcon(name, KIconLoader::Small, force_size, state, overlays);
1557}
1558
1559// deprecated
1560#ifndef KDE_NO_DEPRECATED
1561QIcon SmallIconSet(const QString& name, int force_size)
1562{
1563 KIconLoader *loader = KIconLoader::global();
1564 return loader->loadIconSet( name, KIconLoader::Small, force_size );
1565}
1566#endif
1567
1568QPixmap MainBarIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1569{
1570 KIconLoader *loader = KIconLoader::global();
1571 return loader->loadIcon(name, KIconLoader::MainToolbar, force_size, state, overlays);
1572}
1573
1574// deprecated
1575#ifndef KDE_NO_DEPRECATED
1576QIcon MainBarIconSet(const QString& name, int force_size)
1577{
1578 KIconLoader *loader = KIconLoader::global();
1579 return loader->loadIconSet( name, KIconLoader::MainToolbar, force_size );
1580}
1581#endif
1582
1583QPixmap UserIcon(const QString& name, int state, const QStringList &overlays)
1584{
1585 KIconLoader *loader = KIconLoader::global();
1586 return loader->loadIcon(name, KIconLoader::User, 0, state, overlays);
1587}
1588
1589// deprecated
1590#ifndef KDE_NO_DEPRECATED
1591QIcon UserIconSet(const QString& name)
1592{
1593 KIconLoader *loader = KIconLoader::global();
1594 return loader->loadIconSet( name, KIconLoader::User );
1595}
1596#endif
1597
1598int IconSize(KIconLoader::Group group)
1599{
1600 KIconLoader *loader = KIconLoader::global();
1601 return loader->currentSize(group);
1602}
1603
1604QPixmap KIconLoader::unknown()
1605{
1606 QPixmap pix;
1607 if ( QPixmapCache::find("unknown", pix) ) //krazy:exclude=iconnames
1608 return pix;
1609
1610 QString path = global()->iconPath("unknown", KIconLoader::Small, true); //krazy:exclude=iconnames
1611 if (path.isEmpty())
1612 {
1613 kDebug(264) << "Warning: Cannot find \"unknown\" icon.";
1614 pix = QPixmap(32,32);
1615 } else
1616 {
1617 pix.load(path);
1618 QPixmapCache::insert("unknown", pix); //krazy:exclude=iconnames
1619 }
1620
1621 return pix;
1622}
1623
1624/*** the global icon loader ***/
1625K_GLOBAL_STATIC_WITH_ARGS(KIconLoader, globalIconLoader, (KGlobal::mainComponent(), 0))
1626
1627KIconLoader *KIconLoader::global()
1628{
1629 return globalIconLoader;
1630}
1631
1632void KIconLoader::newIconLoader()
1633{
1634 if ( global() == this) {
1635 KIconTheme::reconfigure();
1636 }
1637
1638 reconfigure( objectName(), d->mpDirs );
1639 emit iconLoaderSettingsChanged();
1640}
1641
1642#include "kiconloader.moc"
1643
KComponentData
KComponentData::componentName
QString componentName() const
KComponentData::dirs
KStandardDirs * dirs() const
KConfigGroup
KGlobalSettings::self
static KGlobalSettings * self()
Return the KGlobalSettings singleton.
Definition: kglobalsettings.cpp:188
KIconEffect
Applies effects to icons.
Definition: kiconeffect.h:48
KIconLoader
Iconloader for KDE.
Definition: kiconloader.h:78
KIconLoader::queryIconsByContext
QStringList queryIconsByContext(int group_or_size, KIconLoader::Context context=KIconLoader::Any) const
Queries all available icons for a specific context.
Definition: kiconloader.cpp:1394
KIconLoader::alphaBlending
bool alphaBlending(KIconLoader::Group group) const
Checks whether the user wants to blend the icons with the background using the alpha channel informat...
Definition: kiconloader.cpp:1492
KIconLoader::Group
Group
The group of the icon.
Definition: kiconloader.h:127
KIconLoader::Small
@ Small
Small icons, e.g. for buttons.
Definition: kiconloader.h:139
KIconLoader::FirstGroup
@ FirstGroup
First group.
Definition: kiconloader.h:133
KIconLoader::User
@ User
User icons.
Definition: kiconloader.h:147
KIconLoader::LastGroup
@ LastGroup
Last group.
Definition: kiconloader.h:145
KIconLoader::Desktop
@ Desktop
Desktop icons.
Definition: kiconloader.h:131
KIconLoader::MainToolbar
@ MainToolbar
Main toolbar icons.
Definition: kiconloader.h:137
KIconLoader::Toolbar
@ Toolbar
Toolbar icons.
Definition: kiconloader.h:135
KIconLoader::KIconLoader
KIconLoader(const QString &appname=QString(), KStandardDirs *dirs=0, QObject *parent=0)
Constructs an iconloader.
Definition: kiconloader.cpp:424
KIconLoader::addAppDir
void addAppDir(const QString &appname)
Adds appname to the list of application specific directories.
Definition: kiconloader.cpp:561
KIconLoader::queryIcons
QStringList queryIcons(int group_or_size, KIconLoader::Context context=KIconLoader::Any) const
Queries all available icons for a specific group, having a specific context.
Definition: kiconloader.cpp:1436
KIconLoader::~KIconLoader
~KIconLoader()
Cleanup.
Definition: kiconloader.cpp:556
KIconLoader::loadIconSet
QIcon loadIconSet(const QString &name, KIconLoader::Group group, int size=0, bool canReturnNull=false)
Creates an icon set, that will do on-demand loading of the icon.
Definition: kiconloader.cpp:1506
KIconLoader::global
static KIconLoader * global()
Returns the global icon loader initialized with the global KComponentData.
KIconLoader::hasContext
bool hasContext(KIconLoader::Context context) const
Definition: kiconloader.cpp:1477
KIconLoader::ActiveState
@ ActiveState
Icon is active.
Definition: kiconloader.h:173
KIconLoader::DisabledState
@ DisabledState
Icon is disabled.
Definition: kiconloader.h:174
KIconLoader::LastState
@ LastState
Last state (last constant)
Definition: kiconloader.h:175
KIconLoader::DefaultState
@ DefaultState
The default state.
Definition: kiconloader.h:172
KIconLoader::moviePath
QString moviePath(const QString &name, KIconLoader::Group group, int size=0) const
Returns the path to an animated icon.
Definition: kiconloader.cpp:1258
KIconLoader::queryIconsByDir
QStringList queryIconsByDir(const QString &iconsDir) const
Returns a list of all icons (*.png or *.xpm extension) in the given directory.
Definition: kiconloader.cpp:1382
KIconLoader::loadMimeTypeIcon
QPixmap loadMimeTypeIcon(const QString &iconName, KIconLoader::Group group, int size=0, int state=KIconLoader::DefaultState, const QStringList &overlays=QStringList(), QString *path_store=0) const
Loads an icon for a mimetype.
Definition: kiconloader.cpp:1075
KIconLoader::currentSize
int currentSize(KIconLoader::Group group) const
Returns the current size of the icon group.
Definition: kiconloader.cpp:1370
KIconLoader::extraDesktopThemesAdded
bool extraDesktopThemesAdded() const
Returns if the default icon themes of other desktops have been added to the list of icon themes where...
Definition: kiconloader.cpp:694
KIconLoader::theme
KIconTheme * theme() const
Returns a pointer to the current theme.
Definition: kiconloader.cpp:1363
KIconLoader::loadMovie
QMovie * loadMovie(const QString &name, KIconLoader::Group group, int size=0, QObject *parent=0) const
Loads an animated icon.
Definition: kiconloader.cpp:1240
KIconLoader::loadIcon
QPixmap loadIcon(const QString &name, KIconLoader::Group group, int size=0, int state=KIconLoader::DefaultState, const QStringList &overlays=QStringList(), QString *path_store=0L, bool canReturnNull=false) const
Loads an icon.
Definition: kiconloader.cpp:1100
KIconLoader::reconfigure
void reconfigure(const QString &_appname, KStandardDirs *_dirs)
Called by KComponentData::newIconLoader to reconfigure the icon loader.
Definition: kiconloader.cpp:446
KIconLoader::drawOverlays
void drawOverlays(const QStringList &overlays, QPixmap &pixmap, KIconLoader::Group group, int state=KIconLoader::DefaultState) const
Draws overlays on the specified pixmap, it takes the width and height of the pixmap into consideratio...
Definition: kiconloader.cpp:699
KIconLoader::loadAnimated
QStringList loadAnimated(const QString &name, KIconLoader::Group group, int size=0) const
Loads an animated icon as a series of still frames.
Definition: kiconloader.cpp:1310
KIconLoader::iconEffect
KIconEffect * iconEffect() const
Returns a pointer to the KIconEffect object used by the icon loader.
Definition: kiconloader.cpp:1487
KIconLoader::addExtraDesktopThemes
void addExtraDesktopThemes()
Adds all the default themes from other desktops at the end of the list of icon themes.
Definition: kiconloader.cpp:644
KIconLoader::newIconLoader
void newIconLoader()
Re-initialize the global icon loader.
Definition: kiconloader.cpp:1632
KIconLoader::Context
Context
Defines the context of the icon.
Definition: kiconloader.h:91
KIconLoader::Any
@ Any
Some icon with unknown purpose.
Definition: kiconloader.h:92
KIconLoader::Scalable
@ Scalable
Scalable-size icon.
Definition: kiconloader.h:112
KIconLoader::iconLoaderSettingsChanged
void iconLoaderSettingsChanged()
Emitted by newIconLoader once the new settings have been loaded.
KIconLoader::MatchType
MatchType
The type of a match.
Definition: kiconloader.h:119
KIconLoader::MatchBest
@ MatchBest
Take the best match if there is no exact match.
Definition: kiconloader.h:121
KIconLoader::MatchExact
@ MatchExact
Only try to find an exact match.
Definition: kiconloader.h:120
KIconLoader::iconPath
QString iconPath(const QString &name, int group_or_size, bool canReturnNull=false) const
Returns the path of an icon.
Definition: kiconloader.cpp:1009
KIconLoader::unknown
static QPixmap unknown()
Returns the unknown icon.
Definition: kiconloader.cpp:1604
KIconTheme
Definition: kicontheme.h:47
KIconTheme::isValid
bool isValid() const
The icon theme exists?
Definition: kicontheme.cpp:306
KIconTheme::internalName
QString internalName() const
The internal name of the icon theme (same as the name argument passed to the constructor).
Definition: kicontheme.cpp:276
KIconTheme::reconfigure
static void reconfigure()
Reconfigure the theme.
Definition: kicontheme.cpp:587
KIconTheme::current
static QString current()
Returns the current icon theme.
Definition: kicontheme.cpp:522
KIconTheme::name
QString name() const
The stylized name of the icon theme.
Definition: kicontheme.cpp:271
KIconTheme::defaultSize
int defaultSize(KIconLoader::Group group) const
The default size of this theme for a certain icon group.
Definition: kicontheme.cpp:321
KIconTheme::defaultThemeName
static QString defaultThemeName()
Returns the default icon theme.
Definition: kicontheme.cpp:594
KSharedDataCache
KSharedPtr< KSharedConfig >
KStandardDirs
KStandardDirs::findAllResources
QStringList findAllResources(const char *type, const QString &filter, SearchOptions options, QStringList &relPaths) const
KStandardDirs::exists
static bool exists(const QString &fullPath)
KStandardDirs::locateLocal
static QString locateLocal(const char *type, const QString &filename, bool createDir, const KComponentData &cData=KGlobal::mainComponent())
KStandardDirs::resourceDirs
QStringList resourceDirs(const char *type) const
QHash
QList
QObject
QSet
QSvgRenderer
output
void output(QList< Action > actions, QHash< QString, QString > domain)
K_GLOBAL_STATIC
#define K_GLOBAL_STATIC(TYPE, NAME)
kDebug
#define kDebug
kWarning
#define kWarning
kcomponentdata.h
kconfig.h
kconfiggroup.h
kdebug.h
K_GLOBAL_STATIC_WITH_ARGS
K_GLOBAL_STATIC_WITH_ARGS(KComponentData, fakeComponent,(KGlobalPrivate::initFakeComponent())) KStandardDirs *KGlobal
kglobal.h
kglobalsettings.h
kiconeffect.h
MainBarIconSet
QIcon MainBarIconSet(const QString &name, int force_size)
Definition: kiconloader.cpp:1576
BarIcon
QPixmap BarIcon(const QString &name, int force_size, int state, const QStringList &overlays)
Definition: kiconloader.cpp:1538
BarIconSet
QIcon BarIconSet(const QString &name, int force_size)
Definition: kiconloader.cpp:1546
SmallIcon
QPixmap SmallIcon(const QString &name, int force_size, int state, const QStringList &overlays)
Definition: kiconloader.cpp:1553
DesktopIconSet
QIcon DesktopIconSet(const QString &name, int force_size)
Definition: kiconloader.cpp:1531
SmallIconSet
QIcon SmallIconSet(const QString &name, int force_size)
Definition: kiconloader.cpp:1561
MainBarIcon
QPixmap MainBarIcon(const QString &name, int force_size, int state, const QStringList &overlays)
Definition: kiconloader.cpp:1568
IconSize
int IconSize(KIconLoader::Group group)
Definition: kiconloader.cpp:1598
UserIconSet
QIcon UserIconSet(const QString &name)
Definition: kiconloader.cpp:1591
DesktopIcon
QPixmap DesktopIcon(const QString &name, int force_size, int state, const QStringList &overlays)
Definition: kiconloader.cpp:1523
UserIcon
QPixmap UserIcon(const QString &name, int state, const QStringList &overlays)
Definition: kiconloader.cpp:1583
kiconloader.h
kicontheme.h
kshareddatacache.h
kstandarddirs.h
KGlobal::staticQString
const QString & staticQString(const char *str)
KGlobal::mainComponent
const KComponentData & mainComponent()
KGlobal::dirs
KStandardDirs * dirs()
config
KSharedConfigPtr config()
group
group
KStandardAction::name
const char * name(StandardAction id)
This will return the internal name of a given standard action.
Definition: kstandardaction.cpp:223
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal