• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.2 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*
67 K_GLOBAL_STATIC_WITH_ARGS(QString, NULL_EFFECT_FINGERPRINT, (QString::fromLatin1("noeffect")))
68 
69 
72 static 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 
84 struct PixmapWithPath
85 {
86  QPixmap pixmap;
87  QString path;
88 };
89 
90 /*** KIconThemeNode: A node in the icon theme dependancy tree. ***/
91 
92 class KIconThemeNode
93 {
94 public:
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 
107 KIconThemeNode::KIconThemeNode(KIconTheme *_theme)
108 {
109  theme = _theme;
110 }
111 
112 KIconThemeNode::~KIconThemeNode()
113 {
114  delete theme;
115 }
116 
117 void 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 
126 void 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 
133 void 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 
140 K3Icon 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 
149 struct KIconGroup
150 {
151  int size;
152  bool alphaBlending;
153 };
154 
155 
156 /*** d pointer for KIconLoader. ***/
157 class KIconLoaderPrivate
158 {
159 public:
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 
302 class KIconLoaderGlobalData
303 {
304 public:
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 
317 private:
318  void parseGenericIconsFiles(const QString& fileName);
319  QHash<QString, QString> m_genericIcons;
320 };
321 
322 void 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 
348 K_GLOBAL_STATIC(KIconLoaderGlobalData, s_globalData)
349 
350 void 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 
424 KIconLoader::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 
435 KIconLoader::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 
446 void 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 
454 void 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 
502 bool 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 
556 KIconLoader::~KIconLoader()
557 {
558  delete d;
559 }
560 
561 void 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 
571 void 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 
596 void 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 
613 void 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 
628 void 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 
644 void 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 
694 bool KIconLoader::extraDesktopThemesAdded() const
695 {
696  return d->extraDesktopIconsLoaded;
697 }
698 
699 void KIconLoader::drawOverlays(const QStringList &overlays, QPixmap &pixmap, KIconLoader::Group group, int state) const
700 {
701  d->drawOverlays(this, group, state, pixmap, overlays);
702 }
703 
704 QString 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 
717 void 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 
753 QString 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 
771 QImage 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 
804 void 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 
838 bool 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 
890 K3Icon 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 
903 K3Icon 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  foreach(KIconThemeNode *themeNode, links)
913  {
914  QString currentName = name;
915 
916  while (!currentName.isEmpty())
917  {
918 
919  //kDebug(264) << "Looking up" << currentName;
920 
921 // The following code has been commented out because the Qt SVG renderer needs
922 // to be improved. If you are going to change/remove some code from this part,
923 // please contact me before (ereslibre@kde.org), or kde-core-devel@kde.org. (ereslibre)
924  for (int i = 0 ; i < 4 ; i++)
925  {
926  icon = themeNode->theme->iconPath(currentName + ext[i], size, KIconLoader::MatchExact);
927  if (icon.isValid())
928  return icon;
929 
930  icon = themeNode->theme->iconPath(currentName + ext[i], size, KIconLoader::MatchBest);
931  if (icon.isValid())
932  return icon;
933  }
934 
935  if (genericFallback)
936  // we already tested the base name
937  break;
938 
939  int rindex = currentName.lastIndexOf('-');
940  if (rindex > 1) { // > 1 so that we don't split x-content or x-epoc
941  currentName.truncate(rindex);
942 
943  if (currentName.endsWith(QLatin1String("-x")))
944  currentName.chop(2);
945  } else {
946  // From update-mime-database.c
947  static const QSet<QString> mediaTypes = QSet<QString>()
948  << "text" << "application" << "image" << "audio"
949  << "inode" << "video" << "message" << "model" << "multipart"
950  << "x-content" << "x-epoc";
951  // Shared-mime-info spec says:
952  // "If [generic-icon] is not specified then the mimetype is used to generate the
953  // generic icon by using the top-level media type (e.g. "video" in "video/ogg")
954  // and appending "-x-generic" (i.e. "video-x-generic" in the previous example)."
955  if (mediaTypes.contains(currentName)) {
956  currentName += QLatin1String("-x-generic");
957  genericFallback = true;
958  } else {
959  break;
960  }
961  }
962  }
963  }
964  return icon;
965 }
966 
967 inline QString KIconLoaderPrivate::unknownIconPath( int size ) const
968 {
969  static const QString &str_unknown = KGlobal::staticQString("unknown");
970 
971  K3Icon icon = findMatchingIcon(str_unknown, size);
972  if (!icon.isValid())
973  {
974  kDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
975  << size << endl;
976  return QString();
977  }
978  return icon.path;
979 }
980 
981 // Finds the absolute path to an icon.
982 
983 QString KIconLoader::iconPath(const QString& _name, int group_or_size,
984  bool canReturnNull) const
985 {
986  if (!d->initIconThemes()) {
987  return QString();
988  }
989 
990  if (_name.isEmpty() || !pathIsRelative(_name))
991  {
992  // we have either an absolute path or nothing to work with
993  return _name;
994  }
995 
996  QString name = d->removeIconExtension( _name );
997 
998  QString path;
999  if (group_or_size == KIconLoader::User)
1000  {
1001  static const QString &png_ext = KGlobal::staticQString(".png");
1002  static const QString &xpm_ext = KGlobal::staticQString(".xpm");
1003  path = d->mpDirs->findResource("appicon", name + png_ext);
1004 
1005  static const QString &svgz_ext = KGlobal::staticQString(".svgz");
1006  static const QString &svg_ext = KGlobal::staticQString(".svg");
1007  if (path.isEmpty())
1008  path = d->mpDirs->findResource("appicon", name + svgz_ext);
1009  if (path.isEmpty())
1010  path = d->mpDirs->findResource("appicon", name + svg_ext);
1011  if (path.isEmpty())
1012  path = d->mpDirs->findResource("appicon", name + xpm_ext);
1013  return path;
1014  }
1015 
1016  if (group_or_size >= KIconLoader::LastGroup)
1017  {
1018  kDebug(264) << "Illegal icon group: " << group_or_size;
1019  return path;
1020  }
1021 
1022  int size;
1023  if (group_or_size >= 0)
1024  size = d->mpGroups[group_or_size].size;
1025  else
1026  size = -group_or_size;
1027 
1028  if (_name.isEmpty()) {
1029  if (canReturnNull)
1030  return QString();
1031  else
1032  return d->unknownIconPath(size);
1033  }
1034 
1035  K3Icon icon = d->findMatchingIconWithGenericFallbacks(name, size);
1036 
1037  if (!icon.isValid())
1038  {
1039  // Try "User" group too.
1040  path = iconPath(name, KIconLoader::User, true);
1041  if (!path.isEmpty() || canReturnNull)
1042  return path;
1043 
1044  return d->unknownIconPath(size);
1045  }
1046  return icon.path;
1047 }
1048 
1049 QPixmap KIconLoader::loadMimeTypeIcon( const QString& _iconName, KIconLoader::Group group, int size,
1050  int state, const QStringList& overlays, QString *path_store ) const
1051 {
1052  QString iconName = _iconName;
1053  const int slashindex = iconName.indexOf(QLatin1Char('/'));
1054  if (slashindex != -1) {
1055  iconName[slashindex] = QLatin1Char('-');
1056  }
1057 
1058  if ( !d->extraDesktopIconsLoaded )
1059  {
1060  const QPixmap pixmap = loadIcon( iconName, group, size, state, overlays, path_store, true );
1061  if (!pixmap.isNull() ) {
1062  return pixmap;
1063  }
1064  const_cast<KIconLoader *>(this)->addExtraDesktopThemes();
1065  }
1066  const QPixmap pixmap = loadIcon(iconName, group, size, state, overlays, path_store, true);
1067  if (pixmap.isNull()) {
1068  // Icon not found, fallback to application/octet-stream
1069  return loadIcon("application-octet-stream", group, size, state, overlays, path_store, false);
1070  }
1071  return pixmap;
1072 }
1073 
1074 QPixmap KIconLoader::loadIcon(const QString& _name, KIconLoader::Group group, int size,
1075  int state, const QStringList& overlays,
1076  QString *path_store, bool canReturnNull) const
1077 {
1078  QString name = _name;
1079  bool favIconOverlay = false;
1080 
1081  if (size < 0 || _name.isEmpty())
1082  return QPixmap();
1083 
1084  /*
1085  * This method works in a kind of pipeline, with the following steps:
1086  * 1. Sanity checks.
1087  * 2. Convert _name, group, size, etc. to a key name.
1088  * 3. Check if the key is already cached.
1089  * 4. If not, initialize the theme and find/load the icon.
1090  * 4a Apply overlays
1091  * 4b Re-add to cache.
1092  */
1093 
1094  // Special case for absolute path icons.
1095  if (name.startsWith(QLatin1String("favicons/")))
1096  {
1097  favIconOverlay = true;
1098  name = KStandardDirs::locateLocal("cache", name+".png");
1099  }
1100 
1101  bool absolutePath = !pathIsRelative(name);
1102  if (!absolutePath) {
1103  name = d->removeIconExtension(name);
1104  }
1105 
1106  // Don't bother looking for an icon with no name.
1107  if (name.isEmpty()) {
1108  return QPixmap();
1109  }
1110 
1111  // May modify group, size, or state. This function puts them into sane
1112  // states.
1113  d->normalizeIconMetadata(group, size, state);
1114 
1115  // See if the image is already cached.
1116  QString key = d->makeCacheKey(name, group, overlays, size, state);
1117  QPixmap pix;
1118  bool iconWasUnknown = false;
1119  K3Icon icon;
1120 
1121  // icon.path would be empty for "unknown" icons, which should be searched for
1122  // anew each time.
1123  if (d->findCachedPixmapWithPath(key, pix, icon.path) && !icon.path.isEmpty()) {
1124  if (path_store) {
1125  *path_store = icon.path;
1126  }
1127 
1128  return pix;
1129  }
1130 
1131  // Image is not cached... go find it and apply effects.
1132  if (!d->initIconThemes()) {
1133  return QPixmap();
1134  }
1135 
1136  favIconOverlay = favIconOverlay && size > 22;
1137 
1138  // First we look for non-User icons. If we don't find one we'd search in
1139  // the User space anyways...
1140  if (group != KIconLoader::User) {
1141  // K3Icon seems to hold some needed information.
1142 
1143  if (absolutePath && !favIconOverlay)
1144  {
1145  icon.context = KIconLoader::Any;
1146  icon.type = KIconLoader::Scalable;
1147  icon.path = name;
1148  }
1149  else
1150  {
1151  icon = d->findMatchingIconWithGenericFallbacks(favIconOverlay ? QString("text-html") : name, size);
1152  }
1153  }
1154 
1155  if (icon.path.isEmpty()) {
1156  // We do have a "User" icon, or we couldn't find the non-User one.
1157  icon.path = (absolutePath) ? name :
1158  iconPath(name, KIconLoader::User, canReturnNull);
1159  }
1160 
1161  // Still can't find it? Use "unknown" if we can't return null.
1162  // We keep going in the function so we can ensure this result gets cached.
1163  if (icon.path.isEmpty() && !canReturnNull) {
1164  icon.path = d->unknownIconPath(size);
1165  iconWasUnknown = true;
1166  }
1167 
1168  QImage img = d->createIconImage(icon.path, size);
1169 
1170  if (group >= 0)
1171  {
1172  img = d->mpEffect.apply(img, group, state);
1173  }
1174 
1175  if (favIconOverlay)
1176  {
1177  QImage favIcon(name, "PNG");
1178  if (!favIcon.isNull()) // if favIcon not there yet, don't try to blend it
1179  {
1180  QPainter p(&img);
1181 
1182  // Align the favicon overlay
1183  QRect r(favIcon.rect());
1184  r.moveBottomRight(img.rect().bottomRight());
1185  r.adjust(-1, -1, -1, -1); // Move off edge
1186 
1187  // Blend favIcon over img.
1188  p.drawImage(r, favIcon);
1189  }
1190  }
1191 
1192  pix = QPixmap::fromImage(img);
1193 
1194  // TODO: If we make a loadIcon that returns the image we can convert
1195  // drawOverlays to use the image instead of pixmaps as well so we don't
1196  // have to transfer so much to the graphics card.
1197  d->drawOverlays(this, group, state, pix, overlays);
1198 
1199  // Don't add the path to our unknown icon to the cache, only cache the
1200  // actual image.
1201  if (iconWasUnknown) {
1202  icon.path.clear();
1203  }
1204 
1205  d->insertCachedPixmapWithPath(key, pix, icon.path);
1206 
1207  if (path_store) {
1208  *path_store = icon.path;
1209  }
1210 
1211  return pix;
1212 }
1213 
1214 QMovie *KIconLoader::loadMovie(const QString& name, KIconLoader::Group group, int size, QObject *parent) const
1215 {
1216  QString file = moviePath( name, group, size );
1217  if (file.isEmpty())
1218  return 0;
1219  int dirLen = file.lastIndexOf('/');
1220  QString icon = iconPath(name, size ? -size : group, true);
1221  if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
1222  return 0;
1223  QMovie *movie = new QMovie(file, QByteArray(), parent);
1224  if (!movie->isValid())
1225  {
1226  delete movie;
1227  return 0;
1228  }
1229  return movie;
1230 }
1231 
1232 QString KIconLoader::moviePath(const QString& name, KIconLoader::Group group, int size) const
1233 {
1234  if (!d->mpGroups) return QString();
1235 
1236  d->initIconThemes();
1237 
1238  if ( (group < -1 || group >= KIconLoader::LastGroup) && group != KIconLoader::User )
1239  {
1240  kDebug(264) << "Illegal icon group: " << group;
1241  group = KIconLoader::Desktop;
1242  }
1243  if (size == 0 && group < 0)
1244  {
1245  kDebug(264) << "Neither size nor group specified!";
1246  group = KIconLoader::Desktop;
1247  }
1248 
1249  QString file = name + ".mng";
1250  if (group == KIconLoader::User)
1251  {
1252  file = d->mpDirs->findResource("appicon", file);
1253  }
1254  else
1255  {
1256  if (size == 0)
1257  size = d->mpGroups[group].size;
1258 
1259  K3Icon icon;
1260 
1261  foreach(KIconThemeNode *themeNode, d->links)
1262  {
1263  icon = themeNode->theme->iconPath(file, size, KIconLoader::MatchExact);
1264  if (icon.isValid())
1265  break;
1266  }
1267 
1268  if ( !icon.isValid() )
1269  {
1270  foreach(KIconThemeNode *themeNode, d->links)
1271  {
1272  icon = themeNode->theme->iconPath(file, size, KIconLoader::MatchBest);
1273  if (icon.isValid())
1274  break;
1275  }
1276  }
1277 
1278  file = icon.isValid() ? icon.path : QString();
1279  }
1280  return file;
1281 }
1282 
1283 
1284 QStringList KIconLoader::loadAnimated(const QString& name, KIconLoader::Group group, int size) const
1285 {
1286  QStringList lst;
1287 
1288  if (!d->mpGroups) return lst;
1289 
1290  d->initIconThemes();
1291 
1292  if ((group < -1) || (group >= KIconLoader::LastGroup))
1293  {
1294  kDebug(264) << "Illegal icon group: " << group;
1295  group = KIconLoader::Desktop;
1296  }
1297  if ((size == 0) && (group < 0))
1298  {
1299  kDebug(264) << "Neither size nor group specified!";
1300  group = KIconLoader::Desktop;
1301  }
1302 
1303  QString file = name + "/0001";
1304  if (group == KIconLoader::User)
1305  {
1306  file = d->mpDirs->findResource("appicon", file + ".png");
1307  } else
1308  {
1309  if (size == 0)
1310  size = d->mpGroups[group].size;
1311  K3Icon icon = d->findMatchingIcon(file, size);
1312  file = icon.isValid() ? icon.path : QString();
1313 
1314  }
1315  if (file.isEmpty())
1316  return lst;
1317 
1318  QString path = file.left(file.length()-8);
1319  DIR* dp = opendir( QFile::encodeName(path) );
1320  if(!dp)
1321  return lst;
1322 
1323  KDE_struct_dirent* ep;
1324  while( ( ep = KDE_readdir( dp ) ) != 0L )
1325  {
1326  QString fn(QFile::decodeName(ep->d_name));
1327  if(!(fn.left(4)).toUInt())
1328  continue;
1329 
1330  lst += path + fn;
1331  }
1332  closedir ( dp );
1333  lst.sort();
1334  return lst;
1335 }
1336 
1337 KIconTheme *KIconLoader::theme() const
1338 {
1339  d->initIconThemes();
1340  if (d->mpThemeRoot) return d->mpThemeRoot->theme;
1341  return 0L;
1342 }
1343 
1344 int KIconLoader::currentSize(KIconLoader::Group group) const
1345 {
1346  if (!d->mpGroups) return -1;
1347 
1348  if (group < 0 || group >= KIconLoader::LastGroup)
1349  {
1350  kDebug(264) << "Illegal icon group: " << group;
1351  return -1;
1352  }
1353  return d->mpGroups[group].size;
1354 }
1355 
1356 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
1357 {
1358  const QDir dir(iconsDir);
1359  const QStringList formats = QStringList() << "*.png" << "*.xpm" << "*.svg" << "*.svgz";
1360  const QStringList lst = dir.entryList(formats, QDir::Files);
1361  QStringList result;
1362  QStringList::ConstIterator it;
1363  for (it=lst.begin(); it!=lst.end(); ++it)
1364  result += iconsDir + '/' + *it;
1365  return result;
1366 }
1367 
1368 QStringList KIconLoader::queryIconsByContext(int group_or_size,
1369  KIconLoader::Context context) const
1370 {
1371  d->initIconThemes();
1372 
1373  QStringList result;
1374  if (group_or_size >= KIconLoader::LastGroup)
1375  {
1376  kDebug(264) << "Illegal icon group: " << group_or_size;
1377  return result;
1378  }
1379  int size;
1380  if (group_or_size >= 0)
1381  size = d->mpGroups[group_or_size].size;
1382  else
1383  size = -group_or_size;
1384 
1385  foreach(KIconThemeNode *themeNode, d->links)
1386  themeNode->queryIconsByContext(&result, size, context);
1387 
1388  // Eliminate duplicate entries (same icon in different directories)
1389  QString name;
1390  QStringList res2, entries;
1391  QStringList::ConstIterator it;
1392  for (it=result.constBegin(); it!=result.constEnd(); ++it)
1393  {
1394  int n = (*it).lastIndexOf('/');
1395  if (n == -1)
1396  name = *it;
1397  else
1398  name = (*it).mid(n+1);
1399  name = d->removeIconExtension(name);
1400  if (!entries.contains(name))
1401  {
1402  entries += name;
1403  res2 += *it;
1404  }
1405  }
1406  return res2;
1407 
1408 }
1409 
1410 QStringList KIconLoader::queryIcons(int group_or_size, KIconLoader::Context context) const
1411 {
1412  d->initIconThemes();
1413 
1414  QStringList result;
1415  if (group_or_size >= KIconLoader::LastGroup)
1416  {
1417  kDebug(264) << "Illegal icon group: " << group_or_size;
1418  return result;
1419  }
1420  int size;
1421  if (group_or_size >= 0)
1422  size = d->mpGroups[group_or_size].size;
1423  else
1424  size = -group_or_size;
1425 
1426  foreach(KIconThemeNode *themeNode, d->links)
1427  themeNode->queryIcons(&result, size, context);
1428 
1429  // Eliminate duplicate entries (same icon in different directories)
1430  QString name;
1431  QStringList res2, entries;
1432  QStringList::ConstIterator it;
1433  for (it=result.constBegin(); it!=result.constEnd(); ++it)
1434  {
1435  int n = (*it).lastIndexOf('/');
1436  if (n == -1)
1437  name = *it;
1438  else
1439  name = (*it).mid(n+1);
1440  name = d->removeIconExtension(name);
1441  if (!entries.contains(name))
1442  {
1443  entries += name;
1444  res2 += *it;
1445  }
1446  }
1447  return res2;
1448 }
1449 
1450 // used by KIconDialog to find out which contexts to offer in a combobox
1451 bool KIconLoader::hasContext(KIconLoader::Context context) const
1452 {
1453  d->initIconThemes();
1454 
1455  foreach(KIconThemeNode *themeNode, d->links)
1456  if( themeNode->theme->hasContext( context ))
1457  return true;
1458  return false;
1459 }
1460 
1461 KIconEffect * KIconLoader::iconEffect() const
1462 {
1463  return &d->mpEffect;
1464 }
1465 
1466 bool KIconLoader::alphaBlending(KIconLoader::Group group) const
1467 {
1468  if (!d->mpGroups) return false;
1469 
1470  if (group < 0 || group >= KIconLoader::LastGroup)
1471  {
1472  kDebug(264) << "Illegal icon group: " << group;
1473  return false;
1474  }
1475  return d->mpGroups[group].alphaBlending;
1476 }
1477 
1478 // deprecated
1479 #ifndef KDE_NO_DEPRECATED
1480 QIcon KIconLoader::loadIconSet( const QString& name, KIconLoader::Group g, int s,
1481  bool canReturnNull )
1482 {
1483  QIcon iconset;
1484  QPixmap tmp = loadIcon(name, g, s, KIconLoader::ActiveState, QStringList(), NULL, canReturnNull);
1485  iconset.addPixmap( tmp, QIcon::Active, QIcon::On );
1486  // we don't use QIconSet's resizing anyway
1487  tmp = loadIcon(name, g, s, KIconLoader::DisabledState, QStringList(), NULL, canReturnNull);
1488  iconset.addPixmap( tmp, QIcon::Disabled, QIcon::On );
1489  tmp = loadIcon(name, g, s, KIconLoader::DefaultState, QStringList(), NULL, canReturnNull);
1490  iconset.addPixmap( tmp, QIcon::Normal, QIcon::On );
1491  return iconset;
1492 }
1493 #endif
1494 
1495 // Easy access functions
1496 
1497 QPixmap DesktopIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1498 {
1499  KIconLoader *loader = KIconLoader::global();
1500  return loader->loadIcon(name, KIconLoader::Desktop, force_size, state, overlays);
1501 }
1502 
1503 // deprecated
1504 #ifndef KDE_NO_DEPRECATED
1505 QIcon DesktopIconSet(const QString& name, int force_size)
1506 {
1507  KIconLoader *loader = KIconLoader::global();
1508  return loader->loadIconSet(name, KIconLoader::Desktop, force_size);
1509 }
1510 #endif
1511 
1512 QPixmap BarIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1513 {
1514  KIconLoader *loader = KIconLoader::global();
1515  return loader->loadIcon(name, KIconLoader::Toolbar, force_size, state, overlays);
1516 }
1517 
1518 // deprecated
1519 #ifndef KDE_NO_DEPRECATED
1520 QIcon BarIconSet(const QString& name, int force_size)
1521 {
1522  KIconLoader *loader = KIconLoader::global();
1523  return loader->loadIconSet( name, KIconLoader::Toolbar, force_size );
1524 }
1525 #endif
1526 
1527 QPixmap SmallIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1528 {
1529  KIconLoader *loader = KIconLoader::global();
1530  return loader->loadIcon(name, KIconLoader::Small, force_size, state, overlays);
1531 }
1532 
1533 // deprecated
1534 #ifndef KDE_NO_DEPRECATED
1535 QIcon SmallIconSet(const QString& name, int force_size)
1536 {
1537  KIconLoader *loader = KIconLoader::global();
1538  return loader->loadIconSet( name, KIconLoader::Small, force_size );
1539 }
1540 #endif
1541 
1542 QPixmap MainBarIcon(const QString& name, int force_size, int state, const QStringList &overlays)
1543 {
1544  KIconLoader *loader = KIconLoader::global();
1545  return loader->loadIcon(name, KIconLoader::MainToolbar, force_size, state, overlays);
1546 }
1547 
1548 // deprecated
1549 #ifndef KDE_NO_DEPRECATED
1550 QIcon MainBarIconSet(const QString& name, int force_size)
1551 {
1552  KIconLoader *loader = KIconLoader::global();
1553  return loader->loadIconSet( name, KIconLoader::MainToolbar, force_size );
1554 }
1555 #endif
1556 
1557 QPixmap UserIcon(const QString& name, int state, const QStringList &overlays)
1558 {
1559  KIconLoader *loader = KIconLoader::global();
1560  return loader->loadIcon(name, KIconLoader::User, 0, state, overlays);
1561 }
1562 
1563 // deprecated
1564 #ifndef KDE_NO_DEPRECATED
1565 QIcon UserIconSet(const QString& name)
1566 {
1567  KIconLoader *loader = KIconLoader::global();
1568  return loader->loadIconSet( name, KIconLoader::User );
1569 }
1570 #endif
1571 
1572 int IconSize(KIconLoader::Group group)
1573 {
1574  KIconLoader *loader = KIconLoader::global();
1575  return loader->currentSize(group);
1576 }
1577 
1578 QPixmap KIconLoader::unknown()
1579 {
1580  QPixmap pix;
1581  if ( QPixmapCache::find("unknown", pix) ) //krazy:exclude=iconnames
1582  return pix;
1583 
1584  QString path = global()->iconPath("unknown", KIconLoader::Small, true); //krazy:exclude=iconnames
1585  if (path.isEmpty())
1586  {
1587  kDebug(264) << "Warning: Cannot find \"unknown\" icon.";
1588  pix = QPixmap(32,32);
1589  } else
1590  {
1591  pix.load(path);
1592  QPixmapCache::insert("unknown", pix); //krazy:exclude=iconnames
1593  }
1594 
1595  return pix;
1596 }
1597 
1598 /*** the global icon loader ***/
1599 K_GLOBAL_STATIC_WITH_ARGS(KIconLoader, globalIconLoader, (KGlobal::mainComponent(), 0))
1600 
1601 KIconLoader *KIconLoader::global()
1602 {
1603  return globalIconLoader;
1604 }
1605 
1606 void KIconLoader::newIconLoader()
1607 {
1608  if ( global() == this) {
1609  KIconTheme::reconfigure();
1610  }
1611 
1612  reconfigure( objectName(), d->mpDirs );
1613  emit iconLoaderSettingsChanged();
1614 }
1615 
1616 #include "kiconloader.moc"
1617 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Apr 20 2013 06:01:47 by doxygen 1.8.3.1 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.10.2 API Reference

Skip menu "kdelibs-4.10.2 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