kiconloader.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * $Id: kiconloader.cpp 539123 2006-05-09 19:15:18Z coolo $
00004  *
00005  * This file is part of the KDE project, module kdecore.
00006  * Copyright (C) 2000 Geert Jansen <jansen@kde.org>
00007  *                    Antonio Larrosa <larrosa@kde.org>
00008  *
00009  * This is free software; it comes under the GNU Library General
00010  * Public License, version 2. See the file "COPYING.LIB" for the
00011  * exact licensing terms.
00012  *
00013  * kiconloader.cpp: An icon loader for KDE with theming functionality.
00014  */
00015 
00016 #include <qstring.h>
00017 #include <qstringlist.h>
00018 #include <qptrlist.h>
00019 #include <qintdict.h>
00020 #include <qpixmap.h>
00021 #include <qpixmapcache.h>
00022 #include <qimage.h>
00023 #include <qfileinfo.h>
00024 #include <qdir.h>
00025 #include <qiconset.h>
00026 #include <qmovie.h>
00027 #include <qbitmap.h>
00028 
00029 #include <kdebug.h>
00030 #include <kstandarddirs.h>
00031 #include <kglobal.h>
00032 #include <kconfig.h>
00033 #include <ksimpleconfig.h>
00034 #include <kinstance.h>
00035 
00036 #include <kicontheme.h>
00037 #include <kiconloader.h>
00038 #include <kiconeffect.h>
00039 
00040 #include <sys/types.h>
00041 #include <stdlib.h> //for abs
00042 #include <unistd.h>     //for readlink
00043 #include <dirent.h>
00044 #include <config.h>
00045 #include <assert.h>
00046 
00047 #ifdef HAVE_LIBART
00048 #include "svgicons/ksvgiconengine.h"
00049 #include "svgicons/ksvgiconpainter.h"
00050 #endif
00051 
00052 /*** KIconThemeNode: A node in the icon theme dependancy tree. ***/
00053 
00054 class KIconThemeNode
00055 {
00056 public:
00057 
00058     KIconThemeNode(KIconTheme *_theme);
00059     ~KIconThemeNode();
00060 
00061     void queryIcons(QStringList *lst, int size, KIcon::Context context) const;
00062     void queryIconsByContext(QStringList *lst, int size, KIcon::Context context) const;
00063     KIcon findIcon(const QString& name, int size, KIcon::MatchType match) const;
00064     void printTree(QString& dbgString) const;
00065 
00066     KIconTheme *theme;
00067 };
00068 
00069 KIconThemeNode::KIconThemeNode(KIconTheme *_theme)
00070 {
00071     theme = _theme;
00072 }
00073 
00074 KIconThemeNode::~KIconThemeNode()
00075 {
00076     delete theme;
00077 }
00078 
00079 void KIconThemeNode::printTree(QString& dbgString) const
00080 {
00081     /* This method doesn't have much sense anymore, so maybe it should
00082        be removed in the (near?) future */
00083     dbgString += "(";
00084     dbgString += theme->name();
00085     dbgString += ")";
00086 }
00087 
00088 void KIconThemeNode::queryIcons(QStringList *result,
00089                 int size, KIcon::Context context) const
00090 {
00091     // add the icons of this theme to it
00092     *result += theme->queryIcons(size, context);
00093 }
00094 
00095 void KIconThemeNode::queryIconsByContext(QStringList *result,
00096                 int size, KIcon::Context context) const
00097 {
00098     // add the icons of this theme to it
00099     *result += theme->queryIconsByContext(size, context);
00100 }
00101 
00102 KIcon KIconThemeNode::findIcon(const QString& name, int size,
00103                    KIcon::MatchType match) const
00104 {
00105     return theme->iconPath(name, size, match);
00106 }
00107 
00108 
00109 /*** KIconGroup: Icon type description. ***/
00110 
00111 struct KIconGroup
00112 {
00113     int size;
00114     bool dblPixels;
00115     bool alphaBlending;
00116 };
00117 
00118 
00119 /*** d pointer for KIconLoader. ***/
00120 
00121 struct KIconLoaderPrivate
00122 {
00123     QStringList mThemesInTree;
00124     KIconGroup *mpGroups;
00125     KIconThemeNode *mpThemeRoot;
00126     KStandardDirs *mpDirs;
00127     KIconEffect mpEffect;
00128     QDict<QImage> imgDict;
00129     QImage lastImage; // last loaded image without effect applied
00130     QString lastImageKey; // key for icon without effect
00131     int lastIconType; // see KIcon::type
00132     int lastIconThreshold; // see KIcon::threshold
00133     QPtrList<KIconThemeNode> links;
00134     bool extraDesktopIconsLoaded :1;
00135     bool delayedLoading :1;
00136 };
00137 
00138 #define KICONLOADER_CHECKS
00139 #ifdef KICONLOADER_CHECKS
00140 // Keep a list of recently created and destroyed KIconLoader instances in order
00141 // to detect bugs like #68528.
00142 struct KIconLoaderDebug
00143     {
00144     KIconLoaderDebug( KIconLoader* l, const QString& a )
00145         : loader( l ), appname( a ), valid( true )
00146         {}
00147     KIconLoaderDebug() {}; // this QValueList feature annoys me
00148     KIconLoader* loader;
00149     QString appname;
00150     bool valid;
00151     QString delete_bt;
00152     };
00153 
00154 static QValueList< KIconLoaderDebug > *kiconloaders;
00155 #endif
00156 
00157 /*** KIconLoader: the icon loader ***/
00158 
00159 KIconLoader::KIconLoader(const QString& _appname, KStandardDirs *_dirs)
00160 {
00161 #ifdef KICONLOADER_CHECKS
00162     if( kiconloaders == NULL )
00163         kiconloaders = new QValueList< KIconLoaderDebug>();
00164     // check for the (very unlikely case) that new KIconLoader gets allocated
00165     // at exactly same address like some previous one
00166     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
00167          it != kiconloaders->end();
00168          )
00169         {
00170         if( (*it).loader == this )
00171             it = kiconloaders->remove( it );
00172         else
00173             ++it;
00174         }
00175     kiconloaders->append( KIconLoaderDebug( this, _appname ));
00176 #endif
00177     init( _appname, _dirs );
00178 }
00179 
00180 void KIconLoader::reconfigure( const QString& _appname, KStandardDirs *_dirs )
00181 {
00182     delete d;
00183     init( _appname, _dirs );
00184 }
00185 
00186 void KIconLoader::init( const QString& _appname, KStandardDirs *_dirs )
00187 {
00188     d = new KIconLoaderPrivate;
00189     d->imgDict.setAutoDelete( true );
00190     d->links.setAutoDelete(true);
00191     d->extraDesktopIconsLoaded=false;
00192     d->delayedLoading=false;
00193 
00194     if (_dirs)
00195     d->mpDirs = _dirs;
00196     else
00197     d->mpDirs = KGlobal::dirs();
00198 
00199     // If this is unequal to 0, the iconloader is initialized
00200     // successfully.
00201     d->mpThemeRoot = 0L;
00202 
00203     QString appname = _appname;
00204     if (appname.isEmpty())
00205     appname = KGlobal::instance()->instanceName();
00206 
00207     // Add the default theme and its base themes to the theme tree
00208     KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
00209     if (!def->isValid())
00210     {
00211     delete def;
00212         // warn, as this is actually a small penalty hit
00213         kdDebug(264) << "Couldn't find current icon theme, falling back to default." << endl;
00214     def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
00215         if (!def->isValid())
00216         {
00217             kdError(264) << "Error: standard icon theme"
00218                          << " \"" << KIconTheme::defaultThemeName() << "\" "
00219                          << " not found!" << endl;
00220             d->mpGroups=0L;
00221             return;
00222         }
00223     }
00224     d->mpThemeRoot = new KIconThemeNode(def);
00225     d->links.append(d->mpThemeRoot);
00226     d->mThemesInTree += KIconTheme::current();
00227     addBaseThemes(d->mpThemeRoot, appname);
00228 
00229     // These have to match the order in kicontheme.h
00230     static const char * const groups[] = { "Desktop", "Toolbar", "MainToolbar", "Small", "Panel", 0L };
00231     KConfig *config = KGlobal::config();
00232     KConfigGroupSaver cs(config, "dummy");
00233 
00234     // loading config and default sizes
00235     d->mpGroups = new KIconGroup[(int) KIcon::LastGroup];
00236     for (KIcon::Group i=KIcon::FirstGroup; i<KIcon::LastGroup; i++)
00237     {
00238     if (groups[i] == 0L)
00239         break;
00240     config->setGroup(QString::fromLatin1(groups[i]) + "Icons");
00241     d->mpGroups[i].size = config->readNumEntry("Size", 0);
00242     d->mpGroups[i].dblPixels = config->readBoolEntry("DoublePixels", false);
00243     if (QPixmap::defaultDepth()>8)
00244         d->mpGroups[i].alphaBlending = config->readBoolEntry("AlphaBlending", true);
00245     else
00246         d->mpGroups[i].alphaBlending = false;
00247 
00248     if (!d->mpGroups[i].size)
00249         d->mpGroups[i].size = d->mpThemeRoot->theme->defaultSize(i);
00250     }
00251 
00252     // Insert application specific themes at the top.
00253     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00254         appname + "/pics/");
00255     // ################## KDE4: consider removing the toolbar directory
00256     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00257         appname + "/toolbar/");
00258 
00259     // Add legacy icon dirs.
00260     QStringList dirs;
00261     dirs += d->mpDirs->resourceDirs("icon");
00262     dirs += d->mpDirs->resourceDirs("pixmap");
00263     for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it)
00264     d->mpDirs->addResourceDir("appicon", *it);
00265 
00266 #ifndef NDEBUG
00267     QString dbgString = "Theme tree: ";
00268     d->mpThemeRoot->printTree(dbgString);
00269     kdDebug(264) << dbgString << endl;
00270 #endif
00271 }
00272 
00273 KIconLoader::~KIconLoader()
00274 {
00275 #ifdef KICONLOADER_CHECKS
00276     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
00277          it != kiconloaders->end();
00278          ++it )
00279         {
00280         if( (*it).loader == this )
00281             {
00282             (*it).valid = false;
00283             (*it).delete_bt = kdBacktrace();
00284             break;
00285             }
00286         }
00287 #endif
00288     /* antlarr: There's no need to delete d->mpThemeRoot as it's already
00289        deleted when the elements of d->links are deleted */
00290     d->mpThemeRoot=0;
00291     delete[] d->mpGroups;
00292     delete d;
00293 }
00294 
00295 void KIconLoader::enableDelayedIconSetLoading( bool enable )
00296 {
00297     d->delayedLoading = enable;
00298 }
00299 
00300 bool KIconLoader::isDelayedIconSetLoadingEnabled() const
00301 {
00302     return d->delayedLoading;
00303 }
00304 
00305 void KIconLoader::addAppDir(const QString& appname)
00306 {
00307     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00308         appname + "/pics/");
00309     // ################## KDE4: consider removing the toolbar directory
00310     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00311         appname + "/toolbar/");
00312     addAppThemes(appname);
00313 }
00314 
00315 void KIconLoader::addAppThemes(const QString& appname)
00316 {
00317     if ( KIconTheme::current() != KIconTheme::defaultThemeName() )
00318     {
00319         KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
00320         if (def->isValid())
00321         {
00322             KIconThemeNode* node = new KIconThemeNode(def);
00323             d->links.append(node);
00324             addBaseThemes(node, appname);
00325         }
00326         else
00327             delete def;
00328     }
00329 
00330     KIconTheme *def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
00331     KIconThemeNode* node = new KIconThemeNode(def);
00332     d->links.append(node);
00333     addBaseThemes(node, appname);
00334 }
00335 
00336 void KIconLoader::addBaseThemes(KIconThemeNode *node, const QString &appname)
00337 {
00338     QStringList lst = node->theme->inherits();
00339     QStringList::ConstIterator it;
00340 
00341     for (it=lst.begin(); it!=lst.end(); ++it)
00342     {
00343     if( d->mThemesInTree.contains(*it) && (*it) != "hicolor")
00344         continue;
00345     KIconTheme *theme = new KIconTheme(*it,appname);
00346     if (!theme->isValid()) {
00347         delete theme;
00348         continue;
00349     }
00350         KIconThemeNode *n = new KIconThemeNode(theme);
00351     d->mThemesInTree.append(*it);
00352     d->links.append(n);
00353     addBaseThemes(n, appname);
00354     }
00355 }
00356 
00357 void KIconLoader::addExtraDesktopThemes()
00358 {
00359     if ( d->extraDesktopIconsLoaded ) return;
00360 
00361     QStringList list;
00362     QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00363     QStringList::ConstIterator it;
00364     char buf[1000];
00365     int r;
00366     for (it=icnlibs.begin(); it!=icnlibs.end(); ++it)
00367     {
00368     QDir dir(*it);
00369     if (!dir.exists())
00370         continue;
00371     QStringList lst = dir.entryList("default.*", QDir::Dirs);
00372     QStringList::ConstIterator it2;
00373     for (it2=lst.begin(); it2!=lst.end(); ++it2)
00374     {
00375         if (!KStandardDirs::exists(*it + *it2 + "/index.desktop")
00376         && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00377         continue;
00378         r=readlink( QFile::encodeName(*it + *it2) , buf, sizeof(buf)-1);
00379         if ( r>0 )
00380         {
00381           buf[r]=0;
00382           QDir dir2( buf );
00383           QString themeName=dir2.dirName();
00384 
00385           if (!list.contains(themeName))
00386         list.append(themeName);
00387         }
00388     }
00389     }
00390 
00391     for (it=list.begin(); it!=list.end(); ++it)
00392     {
00393     if ( d->mThemesInTree.contains(*it) )
00394         continue;
00395     if ( *it == QString("default.kde") ) continue;
00396 
00397     KIconTheme *def = new KIconTheme( *it, "" );
00398     KIconThemeNode* node = new KIconThemeNode(def);
00399     d->mThemesInTree.append(*it);
00400     d->links.append(node);
00401     addBaseThemes(node, "" );
00402     }
00403 
00404     d->extraDesktopIconsLoaded=true;
00405 
00406 }
00407 
00408 bool KIconLoader::extraDesktopThemesAdded() const
00409 {
00410     return d->extraDesktopIconsLoaded;
00411 }
00412 
00413 QString KIconLoader::removeIconExtension(const QString &name) const
00414 {
00415     int extensionLength=0;
00416 
00417     QString ext = name.right(4);
00418 
00419     static const QString &png_ext = KGlobal::staticQString(".png");
00420     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00421     if (ext == png_ext || ext == xpm_ext)
00422       extensionLength=4;
00423 #ifdef HAVE_LIBART
00424     else
00425     {
00426     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00427     static const QString &svg_ext = KGlobal::staticQString(".svg");
00428 
00429     if (name.right(5) == svgz_ext)
00430         extensionLength=5;
00431     else if (ext == svg_ext)
00432         extensionLength=4;
00433     }
00434 #endif
00435 
00436     if ( extensionLength > 0 )
00437     {
00438     return name.left(name.length() - extensionLength);
00439     }
00440     return name;
00441 }
00442 
00443 QString KIconLoader::removeIconExtensionInternal(const QString &name) const
00444 {
00445     QString name_noext = removeIconExtension(name);
00446 
00447 #ifndef NDEBUG
00448     if (name != name_noext)
00449     {
00450     kdDebug(264) << "Application " << KGlobal::instance()->instanceName()
00451              << " loads icon " << name << " with extension." << endl;
00452     }
00453 #endif
00454 
00455     return name_noext;
00456 }
00457 
00458 KIcon KIconLoader::findMatchingIcon(const QString& name, int size) const
00459 {
00460     KIcon icon;
00461 
00462     const QString *ext[4];
00463     int count=0;
00464     static const QString &png_ext = KGlobal::staticQString(".png");
00465     ext[count++]=&png_ext;
00466 #ifdef HAVE_LIBART
00467     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00468     ext[count++]=&svgz_ext;
00469     static const QString &svg_ext = KGlobal::staticQString(".svg");
00470     ext[count++]=&svg_ext;
00471 #endif
00472     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00473     ext[count++]=&xpm_ext;
00474 
00475     /* antlarr: Multiple inheritance is a broken concept on icon themes, so
00476        the next code doesn't support it on purpose because in fact, it was
00477        never supported at all. This makes the order in which we look for an
00478        icon as:
00479 
00480        png, svgz, svg, xpm exact match
00481        next theme in inheritance tree : png, svgz, svg, xpm exact match
00482        next theme in inheritance tree : png, svgz, svg, xpm exact match
00483        and so on
00484 
00485        And if the icon couldn't be found then it tries best match in the same
00486        order.
00487 
00488        */
00489     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00490     themeNode = d->links.next() )
00491     {
00492     for (int i = 0 ; i < count ; i++)
00493     {
00494         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchExact);
00495         if (icon.isValid())
00496         return icon;
00497     }
00498 
00499     }
00500 
00501     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00502     themeNode = d->links.next() )
00503     {
00504     for (int i = 0 ; i < count ; i++)
00505     {
00506         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest);
00507         if (icon.isValid())
00508         return icon;
00509     }
00510 
00511     }
00512 
00513     return icon;
00514 }
00515 
00516 inline QString KIconLoader::unknownIconPath( int size ) const
00517 {
00518     static const QString &str_unknown = KGlobal::staticQString("unknown");
00519 
00520     KIcon icon = findMatchingIcon(str_unknown, size);
00521     if (!icon.isValid())
00522     {
00523         kdDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
00524                      << size << endl;
00525         return QString::null;
00526     }
00527     return icon.path;
00528 }
00529 
00530 // Finds the absolute path to an icon.
00531 
00532 QString KIconLoader::iconPath(const QString& _name, int group_or_size,
00533                   bool canReturnNull) const
00534 {
00535     if (d->mpThemeRoot == 0L)
00536     return QString::null;
00537 
00538     if (!QDir::isRelativePath(_name))
00539     return _name;
00540 
00541     QString name = removeIconExtensionInternal( _name );
00542 
00543     QString path;
00544     if (group_or_size == KIcon::User)
00545     {
00546     static const QString &png_ext = KGlobal::staticQString(".png");
00547     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00548     path = d->mpDirs->findResource("appicon", name + png_ext);
00549 
00550 #ifdef HAVE_LIBART
00551     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00552     static const QString &svg_ext = KGlobal::staticQString(".svg");
00553     if (path.isEmpty())
00554         path = d->mpDirs->findResource("appicon", name + svgz_ext);
00555     if (path.isEmpty())
00556        path = d->mpDirs->findResource("appicon", name + svg_ext);
00557 #endif
00558     if (path.isEmpty())
00559          path = d->mpDirs->findResource("appicon", name + xpm_ext);
00560     return path;
00561     }
00562 
00563     if (group_or_size >= KIcon::LastGroup)
00564     {
00565     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
00566     return path;
00567     }
00568 
00569     int size;
00570     if (group_or_size >= 0)
00571     size = d->mpGroups[group_or_size].size;
00572     else
00573     size = -group_or_size;
00574 
00575     if (_name.isEmpty()) {
00576         if (canReturnNull)
00577             return QString::null;
00578         else
00579             return unknownIconPath(size);
00580     }
00581 
00582     KIcon icon = findMatchingIcon(name, size);
00583 
00584     if (!icon.isValid())
00585     {
00586     // Try "User" group too.
00587     path = iconPath(name, KIcon::User, true);
00588     if (!path.isEmpty() || canReturnNull)
00589         return path;
00590 
00591     if (canReturnNull)
00592         return QString::null;
00593         else
00594             return unknownIconPath(size);
00595     }
00596     return icon.path;
00597 }
00598 
00599 QPixmap KIconLoader::loadIcon(const QString& _name, KIcon::Group group, int size,
00600                               int state, QString *path_store, bool canReturnNull) const
00601 {
00602     QString name = _name;
00603     QPixmap pix;
00604     QString key;
00605     bool absolutePath=false, favIconOverlay=false;
00606 
00607     if (d->mpThemeRoot == 0L)
00608     return pix;
00609 
00610     // Special case for absolute path icons.
00611     if (name.startsWith("favicons/"))
00612     {
00613        favIconOverlay = true;
00614        name = locateLocal("cache", name+".png");
00615     }
00616     if (!QDir::isRelativePath(name)) absolutePath=true;
00617 
00618     static const QString &str_unknown = KGlobal::staticQString("unknown");
00619 
00620     // Special case for "User" icons.
00621     if (group == KIcon::User)
00622     {
00623     key = "$kicou_";
00624         key += QString::number(size); key += '_';
00625     key += name;
00626     bool inCache = QPixmapCache::find(key, pix);
00627     if (inCache && (path_store == 0L))
00628         return pix;
00629 
00630     QString path = (absolutePath) ? name :
00631             iconPath(name, KIcon::User, canReturnNull);
00632     if (path.isEmpty())
00633     {
00634         if (canReturnNull)
00635         return pix;
00636         // We don't know the desired size: use small
00637         path = iconPath(str_unknown, KIcon::Small, true);
00638         if (path.isEmpty())
00639         {
00640         kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
00641         return pix;
00642         }
00643     }
00644 
00645     if (path_store != 0L)
00646         *path_store = path;
00647     if (inCache)
00648         return pix;
00649     QImage img(path);
00650     if (size != 0)
00651         img=img.smoothScale(size,size);
00652 
00653     pix.convertFromImage(img);
00654     QPixmapCache::insert(key, pix);
00655     return pix;
00656     }
00657 
00658     // Regular case: Check parameters
00659 
00660     if ((group < -1) || (group >= KIcon::LastGroup))
00661     {
00662     kdDebug(264) << "Illegal icon group: " << group << endl;
00663     group = KIcon::Desktop;
00664     }
00665 
00666     int overlay = (state & KIcon::OverlayMask);
00667     state &= ~KIcon::OverlayMask;
00668     if ((state < 0) || (state >= KIcon::LastState))
00669     {
00670     kdDebug(264) << "Illegal icon state: " << state << endl;
00671     state = KIcon::DefaultState;
00672     }
00673 
00674     if (size == 0 && group < 0)
00675     {
00676     kdDebug(264) << "Neither size nor group specified!" << endl;
00677     group = KIcon::Desktop;
00678     }
00679 
00680     if (!absolutePath)
00681     {
00682         if (!canReturnNull && name.isEmpty())
00683             name = str_unknown;
00684         else
00685         name = removeIconExtensionInternal(name);
00686     }
00687 
00688     // If size == 0, use default size for the specified group.
00689     if (size == 0)
00690     {
00691     size = d->mpGroups[group].size;
00692     }
00693     favIconOverlay = favIconOverlay && size > 22;
00694 
00695     // Generate a unique cache key for the icon.
00696 
00697     key = "$kico_";
00698     key += name; key += '_';
00699     key += QString::number(size); key += '_';
00700 
00701     QString overlayStr = QString::number( overlay );
00702 
00703     QString noEffectKey = key + '_' + overlayStr;
00704 
00705     if (group >= 0)
00706     {
00707     key += d->mpEffect.fingerprint(group, state);
00708     if (d->mpGroups[group].dblPixels)
00709         key += QString::fromLatin1(":dblsize");
00710     } else
00711     key += QString::fromLatin1("noeffect");
00712     key += '_';
00713     key += overlayStr;
00714 
00715     // Is the icon in the cache?
00716     bool inCache = QPixmapCache::find(key, pix);
00717     if (inCache && (path_store == 0L))
00718     return pix;
00719 
00720     QImage *img = 0;
00721     int iconType;
00722     int iconThreshold;
00723 
00724     if ( ( path_store != 0L ) ||
00725          noEffectKey != d->lastImageKey )
00726     {
00727         // No? load it.
00728         KIcon icon;
00729         if (absolutePath && !favIconOverlay)
00730         {
00731             icon.context=KIcon::Any;
00732             icon.type=KIcon::Scalable;
00733             icon.path=name;
00734         }
00735         else
00736         {
00737             if (!name.isEmpty())
00738                 icon = findMatchingIcon(favIconOverlay ? QString("www") : name, size);
00739 
00740             if (!icon.isValid())
00741             {
00742                 // Try "User" icon too. Some apps expect this.
00743                 if (!name.isEmpty())
00744                     pix = loadIcon(name, KIcon::User, size, state, path_store, true);
00745                 if (!pix.isNull() || canReturnNull) {
00746             if ((group == KIcon::Small) && (pix.width() > 20 || pix.height() > 20)) {
00747             QImage tmp = pix.convertToImage();
00748             tmp = tmp.smoothScale(20, 20);
00749             pix.convertFromImage(tmp);
00750             }
00751                     return pix;
00752         }
00753 
00754                 icon = findMatchingIcon(str_unknown, size);
00755                 if (!icon.isValid())
00756                 {
00757                     kdDebug(264)
00758                         << "Warning: could not find \"Unknown\" icon for size = "
00759                         << size << endl;
00760                     return pix;
00761                 }
00762             }
00763         }
00764 
00765         if (path_store != 0L)
00766             *path_store = icon.path;
00767         if (inCache)
00768             return pix;
00769 
00770     // Use the extension as the format. Works for XPM and PNG, but not for SVG
00771     QString ext = icon.path.right(3).upper();
00772     if(ext != "SVG" && ext != "VGZ")
00773     {
00774         img = new QImage(icon.path, ext.latin1());
00775         if (img->isNull()) {
00776                 delete img;
00777         return pix;
00778             }
00779     }
00780 #ifdef HAVE_LIBART
00781     else
00782     {
00783         // Special stuff for SVG icons
00784         KSVGIconEngine *svgEngine = new KSVGIconEngine();
00785 
00786         if(svgEngine->load(size, size, icon.path))
00787         img = svgEngine->painter()->image();
00788         else
00789         img = new QImage();
00790 
00791         delete svgEngine;
00792     }
00793 #endif
00794 
00795         iconType = icon.type;
00796         iconThreshold = icon.threshold;
00797 
00798         d->lastImage = img->copy();
00799         d->lastImageKey = noEffectKey;
00800         d->lastIconType = iconType;
00801         d->lastIconThreshold = iconThreshold;
00802     }
00803     else
00804     {
00805         img = new QImage( d->lastImage.copy() );
00806         iconType = d->lastIconType;
00807         iconThreshold = d->lastIconThreshold;
00808     }
00809 
00810     // Blend in all overlays
00811     if (overlay)
00812     {
00813     QImage *ovl;
00814     KIconTheme *theme = d->mpThemeRoot->theme;
00815     if ((overlay & KIcon::LockOverlay) &&
00816         ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00817         KIconEffect::overlay(*img, *ovl);
00818     if ((overlay & KIcon::LinkOverlay) &&
00819         ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00820         KIconEffect::overlay(*img, *ovl);
00821     if ((overlay & KIcon::ZipOverlay) &&
00822         ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00823         KIconEffect::overlay(*img, *ovl);
00824     if ((overlay & KIcon::ShareOverlay) &&
00825         ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00826       KIconEffect::overlay(*img, *ovl);
00827         if (overlay & KIcon::HiddenOverlay)
00828         {
00829         if (img->depth() != 32)
00830             *img = img->convertDepth(32);
00831             for (int y = 0; y < img->height(); y++)
00832             {
00833         QRgb *line = reinterpret_cast<QRgb *>(img->scanLine(y));
00834                 for (int x = 0; x < img->width();  x++)
00835                     line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00836         }
00837     }
00838     }
00839 
00840     // Scale the icon and apply effects if necessary
00841     if (iconType == KIcon::Scalable && size != img->width())
00842     {
00843         *img = img->smoothScale(size, size);
00844     }
00845     if (iconType == KIcon::Threshold && size != img->width())
00846     {
00847     if ( abs(size-img->width())>iconThreshold )
00848         *img = img->smoothScale(size, size);
00849     }
00850     if (group >= 0 && d->mpGroups[group].dblPixels)
00851     {
00852     *img = d->mpEffect.doublePixels(*img);
00853     }
00854     if (group >= 0)
00855     {
00856     *img = d->mpEffect.apply(*img, group, state);
00857     }
00858 
00859     pix.convertFromImage(*img);
00860 
00861     delete img;
00862 
00863     if (favIconOverlay)
00864     {
00865         QPixmap favIcon(name, "PNG");
00866         int x = pix.width() - favIcon.width() - 1,
00867             y = pix.height() - favIcon.height() - 1;
00868         if (pix.mask())
00869         {
00870             QBitmap mask = *pix.mask();
00871             QBitmap fmask;
00872             if (favIcon.mask())
00873         fmask = *favIcon.mask();
00874         else {
00875         // expensive, but works
00876         fmask = favIcon.createHeuristicMask();
00877         }
00878 
00879             bitBlt(&mask, x, y, &fmask,
00880                    0, 0, favIcon.width(), favIcon.height(),
00881                    favIcon.mask() ? Qt::OrROP : Qt::SetROP);
00882             pix.setMask(mask);
00883         }
00884         bitBlt(&pix, x, y, &favIcon);
00885     }
00886 
00887     QPixmapCache::insert(key, pix);
00888     return pix;
00889 }
00890 
00891 QImage *KIconLoader::loadOverlay(const QString &name, int size) const
00892 {
00893     QString key = name + '_' + QString::number(size);
00894     QImage *image = d->imgDict.find(key);
00895     if (image != 0L)
00896     return image;
00897 
00898     KIcon icon = findMatchingIcon(name, size);
00899     if (!icon.isValid())
00900     {
00901     kdDebug(264) << "Overlay " << name << "not found." << endl;
00902     return 0L;
00903     }
00904     image = new QImage(icon.path);
00905     // In some cases (since size in findMatchingIcon() is more a hint than a
00906     // constraint) image->size can be != size. If so perform rescaling.
00907     if ( size != image->width() )
00908         *image = image->smoothScale( size, size );
00909     d->imgDict.insert(key, image);
00910     return image;
00911 }
00912 
00913 
00914 
00915 QMovie KIconLoader::loadMovie(const QString& name, KIcon::Group group, int size) const
00916 {
00917     QString file = moviePath( name, group, size );
00918     if (file.isEmpty())
00919     return QMovie();
00920     int dirLen = file.findRev('/');
00921     QString icon = iconPath(name, size ? -size : group, true);
00922     if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
00923     return QMovie();
00924     return QMovie(file);
00925 }
00926 
00927 QString KIconLoader::moviePath(const QString& name, KIcon::Group group, int size) const
00928 {
00929     if (!d->mpGroups) return QString::null;
00930 
00931     if ( (group < -1 || group >= KIcon::LastGroup) && group != KIcon::User )
00932     {
00933     kdDebug(264) << "Illegal icon group: " << group << endl;
00934     group = KIcon::Desktop;
00935     }
00936     if (size == 0 && group < 0)
00937     {
00938     kdDebug(264) << "Neither size nor group specified!" << endl;
00939     group = KIcon::Desktop;
00940     }
00941 
00942     QString file = name + ".mng";
00943     if (group == KIcon::User)
00944     {
00945     file = d->mpDirs->findResource("appicon", file);
00946     }
00947     else
00948     {
00949     if (size == 0)
00950         size = d->mpGroups[group].size;
00951 
00952         KIcon icon;
00953 
00954     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00955         themeNode = d->links.next() )
00956     {
00957         icon = themeNode->theme->iconPath(file, size, KIcon::MatchExact);
00958         if (icon.isValid())
00959         break;
00960     }
00961 
00962     if ( !icon.isValid() )
00963     {
00964         for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00965             themeNode = d->links.next() )
00966         {
00967         icon = themeNode->theme->iconPath(file, size, KIcon::MatchBest);
00968         if (icon.isValid())
00969             break;
00970         }
00971     }
00972 
00973     file = icon.isValid() ? icon.path : QString::null;
00974     }
00975     return file;
00976 }
00977 
00978 
00979 QStringList KIconLoader::loadAnimated(const QString& name, KIcon::Group group, int size) const
00980 {
00981     QStringList lst;
00982 
00983     if (!d->mpGroups) return lst;
00984 
00985     if ((group < -1) || (group >= KIcon::LastGroup))
00986     {
00987     kdDebug(264) << "Illegal icon group: " << group << endl;
00988     group = KIcon::Desktop;
00989     }
00990     if ((size == 0) && (group < 0))
00991     {
00992     kdDebug(264) << "Neither size nor group specified!" << endl;
00993     group = KIcon::Desktop;
00994     }
00995 
00996     QString file = name + "/0001";
00997     if (group == KIcon::User)
00998     {
00999     file = d->mpDirs->findResource("appicon", file + ".png");
01000     } else
01001     {
01002     if (size == 0)
01003         size = d->mpGroups[group].size;
01004     KIcon icon = findMatchingIcon(file, size);
01005     file = icon.isValid() ? icon.path : QString::null;
01006 
01007     }
01008     if (file.isEmpty())
01009     return lst;
01010 
01011     QString path = file.left(file.length()-8);
01012     DIR* dp = opendir( QFile::encodeName(path) );
01013     if(!dp)
01014         return lst;
01015 
01016     struct dirent* ep;
01017     while( ( ep = readdir( dp ) ) != 0L )
01018     {
01019         QString fn(QFile::decodeName(ep->d_name));
01020         if(!(fn.left(4)).toUInt())
01021             continue;
01022 
01023         lst += path + fn;
01024     }
01025     closedir ( dp );
01026     lst.sort();
01027     return lst;
01028 }
01029 
01030 KIconTheme *KIconLoader::theme() const
01031 {
01032     if (d->mpThemeRoot) return d->mpThemeRoot->theme;
01033     return 0L;
01034 }
01035 
01036 int KIconLoader::currentSize(KIcon::Group group) const
01037 {
01038     if (!d->mpGroups) return -1;
01039 
01040     if (group < 0 || group >= KIcon::LastGroup)
01041     {
01042     kdDebug(264) << "Illegal icon group: " << group << endl;
01043     return -1;
01044     }
01045     return d->mpGroups[group].size;
01046 }
01047 
01048 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
01049 {
01050   QDir dir(iconsDir);
01051   QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
01052   QStringList result;
01053   QStringList::ConstIterator it;
01054   for (it=lst.begin(); it!=lst.end(); ++it)
01055     result += iconsDir + "/" + *it;
01056   return result;
01057 }
01058 
01059 QStringList KIconLoader::queryIconsByContext(int group_or_size,
01060                         KIcon::Context context) const
01061 {
01062     QStringList result;
01063     if (group_or_size >= KIcon::LastGroup)
01064     {
01065     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01066     return result;
01067     }
01068     int size;
01069     if (group_or_size >= 0)
01070     size = d->mpGroups[group_or_size].size;
01071     else
01072     size = -group_or_size;
01073 
01074     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01075             themeNode = d->links.next() )
01076        themeNode->queryIconsByContext(&result, size, context);
01077 
01078     // Eliminate duplicate entries (same icon in different directories)
01079     QString name;
01080     QStringList res2, entries;
01081     QStringList::ConstIterator it;
01082     for (it=result.begin(); it!=result.end(); ++it)
01083     {
01084     int n = (*it).findRev('/');
01085     if (n == -1)
01086         name = *it;
01087     else
01088         name = (*it).mid(n+1);
01089     name = removeIconExtension(name);
01090     if (!entries.contains(name))
01091     {
01092         entries += name;
01093         res2 += *it;
01094     }
01095     }
01096     return res2;
01097 
01098 }
01099 
01100 QStringList KIconLoader::queryIcons(int group_or_size, KIcon::Context context) const
01101 {
01102     QStringList result;
01103     if (group_or_size >= KIcon::LastGroup)
01104     {
01105     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01106     return result;
01107     }
01108     int size;
01109     if (group_or_size >= 0)
01110     size = d->mpGroups[group_or_size].size;
01111     else
01112     size = -group_or_size;
01113 
01114     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01115             themeNode = d->links.next() )
01116        themeNode->queryIcons(&result, size, context);
01117 
01118     // Eliminate duplicate entries (same icon in different directories)
01119     QString name;
01120     QStringList res2, entries;
01121     QStringList::ConstIterator it;
01122     for (it=result.begin(); it!=result.end(); ++it)
01123     {
01124     int n = (*it).findRev('/');
01125     if (n == -1)
01126         name = *it;
01127     else
01128         name = (*it).mid(n+1);
01129     name = removeIconExtension(name);
01130     if (!entries.contains(name))
01131     {
01132         entries += name;
01133         res2 += *it;
01134     }
01135     }
01136     return res2;
01137 }
01138 
01139 KIconEffect * KIconLoader::iconEffect() const
01140 {
01141     return &d->mpEffect;
01142 }
01143 
01144 bool KIconLoader::alphaBlending(KIcon::Group group) const
01145 {
01146     if (!d->mpGroups) return false;
01147 
01148     if (group < 0 || group >= KIcon::LastGroup)
01149     {
01150     kdDebug(264) << "Illegal icon group: " << group << endl;
01151     return false;
01152     }
01153     return d->mpGroups[group].alphaBlending;
01154 }
01155 
01156 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size, bool canReturnNull)
01157 {
01158     return loadIconSet( name, group, size, canReturnNull, true );
01159 }
01160 
01161 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size)
01162 {
01163     return loadIconSet( name, group, size, false );
01164 }
01165 
01166 /*** class for delayed icon loading for QIconSet ***/
01167 
01168 class KIconFactory
01169     : public QIconFactory
01170     {
01171     public:
01172         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01173             int size_P, KIconLoader* loader_P );
01174         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01175             int size_P, KIconLoader* loader_P, bool canReturnNull );
01176         virtual QPixmap* createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode, QIconSet::State );
01177     private:
01178         QString iconName;
01179         KIcon::Group group;
01180         int size;
01181         KIconLoader* loader;
01182         bool canReturnNull;
01183     };
01184 
01185 
01186 QIconSet KIconLoader::loadIconSet( const QString& name, KIcon::Group g, int s,
01187     bool canReturnNull, bool immediateExistenceCheck)
01188 {
01189     if ( !d->delayedLoading )
01190         return loadIconSetNonDelayed( name, g, s, canReturnNull );
01191 
01192     if (g < -1 || g > 6) {
01193         kdDebug() << "KIconLoader::loadIconSet " << name << " " << (int)g << " " << s << endl;
01194         qDebug("%s", kdBacktrace().latin1());
01195         abort();
01196     }
01197 
01198     if(canReturnNull && immediateExistenceCheck)
01199     { // we need to find out if the icon actually exists
01200         QPixmap pm = loadIcon( name, g, s, KIcon::DefaultState, NULL, true );
01201         if( pm.isNull())
01202             return QIconSet();
01203 
01204         QIconSet ret( pm );
01205         ret.installIconFactory( new KIconFactory( name, g, s, this ));
01206         return ret;
01207     }
01208 
01209     QIconSet ret;
01210     ret.installIconFactory( new KIconFactory( name, g, s, this, canReturnNull ));
01211     return ret;
01212 }
01213 
01214 QIconSet KIconLoader::loadIconSetNonDelayed( const QString& name,
01215                                              KIcon::Group g,
01216                                              int s, bool canReturnNull )
01217 {
01218     QIconSet iconset;
01219     QPixmap tmp = loadIcon(name, g, s, KIcon::ActiveState, NULL, canReturnNull);
01220     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Active );
01221     // we don't use QIconSet's resizing anyway
01222     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Active );
01223     tmp = loadIcon(name, g, s, KIcon::DisabledState, NULL, canReturnNull);
01224     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Disabled );
01225     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Disabled );
01226     tmp = loadIcon(name, g, s, KIcon::DefaultState, NULL, canReturnNull);
01227     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Normal );
01228     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Normal );
01229     return iconset;
01230 }
01231 
01232 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01233     int size_P, KIconLoader* loader_P )
01234     : iconName( iconName_P ), group( group_P ), size( size_P ), loader( loader_P )
01235 {
01236     canReturnNull = false;
01237     setAutoDelete( true );
01238 }
01239 
01240 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01241     int size_P, KIconLoader* loader_P, bool canReturnNull_P )
01242     : iconName( iconName_P ), group( group_P ), size( size_P ),
01243       loader( loader_P ), canReturnNull( canReturnNull_P)
01244 {
01245     setAutoDelete( true );
01246 }
01247 
01248 QPixmap* KIconFactory::createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode mode_P, QIconSet::State )
01249     {
01250 #ifdef KICONLOADER_CHECKS
01251     bool found = false;
01252     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
01253          it != kiconloaders->end();
01254          ++it )
01255         {
01256         if( (*it).loader == loader )
01257             {
01258             found = true;
01259             if( !(*it).valid )
01260                 {
01261 #ifdef NDEBUG
01262                 loader = KGlobal::iconLoader();
01263                 iconName = "no_way_man_you_will_get_broken_icon";
01264 #else
01265                 kdWarning() << "Using already destroyed KIconLoader for loading an icon!" << endl;
01266                 kdWarning() << "Appname:" << (*it).appname << ", icon:" << iconName << endl;
01267                 kdWarning() << "Deleted at:" << endl;
01268                 kdWarning() << (*it).delete_bt << endl;
01269                 kdWarning() << "Current:" << endl;
01270                 kdWarning() << kdBacktrace() << endl;
01271                 abort();
01272                 return NULL;
01273 #endif
01274                 }
01275             break;
01276             }
01277         }
01278     if( !found )
01279         {
01280 #ifdef NDEBUG
01281         loader = KGlobal::iconLoader();
01282         iconName = "no_way_man_you_will_get_broken_icon";
01283 #else
01284         kdWarning() << "Using unknown KIconLoader for loading an icon!" << endl;
01285         kdWarning() << "Icon:" << iconName << endl;
01286         kdWarning() << kdBacktrace() << endl;
01287         abort();
01288         return NULL;
01289 #endif
01290         }
01291 #endif
01292     // QIconSet::Mode to KIcon::State conversion
01293     static const KIcon::States tbl[] = { KIcon::DefaultState, KIcon::DisabledState, KIcon::ActiveState };
01294     int state = KIcon::DefaultState;
01295     if( mode_P <= QIconSet::Active )
01296         state = tbl[ mode_P ];
01297     if( group >= 0 && state == KIcon::ActiveState )
01298     { // active and normal icon are usually the same
01299     if( loader->iconEffect()->fingerprint(group, KIcon::ActiveState )
01300             == loader->iconEffect()->fingerprint(group, KIcon::DefaultState ))
01301             return 0; // so let QIconSet simply duplicate it
01302     }
01303     // ignore passed size
01304     // ignore passed state (i.e. on/off)
01305     QPixmap pm = loader->loadIcon( iconName, group, size, state, 0, canReturnNull );
01306     return new QPixmap( pm );
01307     }
01308 
01309 // Easy access functions
01310 
01311 QPixmap DesktopIcon(const QString& name, int force_size, int state,
01312     KInstance *instance)
01313 {
01314     KIconLoader *loader = instance->iconLoader();
01315     return loader->loadIcon(name, KIcon::Desktop, force_size, state);
01316 }
01317 
01318 QPixmap DesktopIcon(const QString& name, KInstance *instance)
01319 {
01320     return DesktopIcon(name, 0, KIcon::DefaultState, instance);
01321 }
01322 
01323 QIconSet DesktopIconSet(const QString& name, int force_size, KInstance *instance)
01324 {
01325     KIconLoader *loader = instance->iconLoader();
01326     return loader->loadIconSet( name, KIcon::Desktop, force_size );
01327 }
01328 
01329 QPixmap BarIcon(const QString& name, int force_size, int state,
01330     KInstance *instance)
01331 {
01332     KIconLoader *loader = instance->iconLoader();
01333     return loader->loadIcon(name, KIcon::Toolbar, force_size, state);
01334 }
01335 
01336 QPixmap BarIcon(const QString& name, KInstance *instance)
01337 {
01338     return BarIcon(name, 0, KIcon::DefaultState, instance);
01339 }
01340 
01341 QIconSet BarIconSet(const QString& name, int force_size, KInstance *instance)
01342 {
01343     KIconLoader *loader = instance->iconLoader();
01344     return loader->loadIconSet( name, KIcon::Toolbar, force_size );
01345 }
01346 
01347 QPixmap SmallIcon(const QString& name, int force_size, int state,
01348     KInstance *instance)
01349 {
01350     KIconLoader *loader = instance->iconLoader();
01351     return loader->loadIcon(name, KIcon::Small, force_size, state);
01352 }
01353 
01354 QPixmap SmallIcon(const QString& name, KInstance *instance)
01355 {
01356     return SmallIcon(name, 0, KIcon::DefaultState, instance);
01357 }
01358 
01359 QIconSet SmallIconSet(const QString& name, int force_size, KInstance *instance)
01360 {
01361     KIconLoader *loader = instance->iconLoader();
01362     return loader->loadIconSet( name, KIcon::Small, force_size );
01363 }
01364 
01365 QPixmap MainBarIcon(const QString& name, int force_size, int state,
01366     KInstance *instance)
01367 {
01368     KIconLoader *loader = instance->iconLoader();
01369     return loader->loadIcon(name, KIcon::MainToolbar, force_size, state);
01370 }
01371 
01372 QPixmap MainBarIcon(const QString& name, KInstance *instance)
01373 {
01374     return MainBarIcon(name, 0, KIcon::DefaultState, instance);
01375 }
01376 
01377 QIconSet MainBarIconSet(const QString& name, int force_size, KInstance *instance)
01378 {
01379     KIconLoader *loader = instance->iconLoader();
01380     return loader->loadIconSet( name, KIcon::MainToolbar, force_size );
01381 }
01382 
01383 QPixmap UserIcon(const QString& name, int state, KInstance *instance)
01384 {
01385     KIconLoader *loader = instance->iconLoader();
01386     return loader->loadIcon(name, KIcon::User, 0, state);
01387 }
01388 
01389 QPixmap UserIcon(const QString& name, KInstance *instance)
01390 {
01391     return UserIcon(name, KIcon::DefaultState, instance);
01392 }
01393 
01394 QIconSet UserIconSet(const QString& name, KInstance *instance)
01395 {
01396     KIconLoader *loader = instance->iconLoader();
01397     return loader->loadIconSet( name, KIcon::User );
01398 }
01399 
01400 int IconSize(KIcon::Group group, KInstance *instance)
01401 {
01402     KIconLoader *loader = instance->iconLoader();
01403     return loader->currentSize(group);
01404 }
01405 
01406 QPixmap KIconLoader::unknown()
01407 {
01408     QPixmap pix;
01409     if ( QPixmapCache::find("unknown", pix) )
01410             return pix;
01411 
01412     QString path = KGlobal::iconLoader()->iconPath("unknown", KIcon::Small, true);
01413     if (path.isEmpty())
01414     {
01415     kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
01416     pix.resize(32,32);
01417     } else
01418     {
01419         pix.load(path);
01420         QPixmapCache::insert("unknown", pix);
01421     }
01422 
01423     return pix;
01424 }
KDE Home | KDE Accessibility Home | Description of Access Keys