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                     return pix;
00747 
00748                 icon = findMatchingIcon(str_unknown, size);
00749                 if (!icon.isValid())
00750                 {
00751                     kdDebug(264)
00752                         << "Warning: could not find \"Unknown\" icon for size = "
00753                         << size << endl;
00754                     return pix;
00755                 }
00756             }
00757         }
00758 
00759         if (path_store != 0L)
00760             *path_store = icon.path;
00761         if (inCache)
00762             return pix;
00763 
00764     // Use the extension as the format. Works for XPM and PNG, but not for SVG
00765     QString ext = icon.path.right(3).upper();
00766     if(ext != "SVG" && ext != "VGZ")
00767     {
00768         img = new QImage(icon.path, ext.latin1());
00769         if (img->isNull()) {
00770                 delete img;
00771         return pix;
00772             }
00773     }
00774 #ifdef HAVE_LIBART
00775     else
00776     {
00777         // Special stuff for SVG icons
00778         KSVGIconEngine *svgEngine = new KSVGIconEngine();
00779 
00780         if(svgEngine->load(size, size, icon.path))
00781         img = svgEngine->painter()->image();
00782         else
00783         img = new QImage();
00784 
00785         delete svgEngine;
00786     }
00787 #endif
00788 
00789         iconType = icon.type;
00790         iconThreshold = icon.threshold;
00791 
00792         d->lastImage = img->copy();
00793         d->lastImageKey = noEffectKey;
00794         d->lastIconType = iconType;
00795         d->lastIconThreshold = iconThreshold;
00796     }
00797     else
00798     {
00799         img = new QImage( d->lastImage.copy() );
00800         iconType = d->lastIconType;
00801         iconThreshold = d->lastIconThreshold;
00802     }
00803 
00804     // Blend in all overlays
00805     if (overlay)
00806     {
00807     QImage *ovl;
00808     KIconTheme *theme = d->mpThemeRoot->theme;
00809     if ((overlay & KIcon::LockOverlay) &&
00810         ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00811         KIconEffect::overlay(*img, *ovl);
00812     if ((overlay & KIcon::LinkOverlay) &&
00813         ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00814         KIconEffect::overlay(*img, *ovl);
00815     if ((overlay & KIcon::ZipOverlay) &&
00816         ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00817         KIconEffect::overlay(*img, *ovl);
00818     if ((overlay & KIcon::ShareOverlay) &&
00819         ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00820       KIconEffect::overlay(*img, *ovl);
00821         if (overlay & KIcon::HiddenOverlay)
00822         {
00823         if (img->depth() != 32)
00824             *img = img->convertDepth(32);
00825             for (int y = 0; y < img->height(); y++)
00826             {
00827         QRgb *line = reinterpret_cast<QRgb *>(img->scanLine(y));
00828                 for (int x = 0; x < img->width();  x++)
00829                     line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00830         }
00831     }
00832     }
00833 
00834     // Scale the icon and apply effects if necessary
00835     if (iconType == KIcon::Scalable && size != img->width())
00836     {
00837         *img = img->smoothScale(size, size);
00838     }
00839     if (iconType == KIcon::Threshold && size != img->width())
00840     {
00841     if ( abs(size-img->width())>iconThreshold )
00842         *img = img->smoothScale(size, size);
00843     }
00844     if (group >= 0 && d->mpGroups[group].dblPixels)
00845     {
00846     *img = d->mpEffect.doublePixels(*img);
00847     }
00848     if (group >= 0)
00849     {
00850     *img = d->mpEffect.apply(*img, group, state);
00851     }
00852 
00853     pix.convertFromImage(*img);
00854 
00855     delete img;
00856 
00857     if (favIconOverlay)
00858     {
00859         QPixmap favIcon(name, "PNG");
00860         int x = pix.width() - favIcon.width() - 1,
00861             y = pix.height() - favIcon.height() - 1;
00862         if (pix.mask())
00863         {
00864             QBitmap mask = *pix.mask();
00865             QBitmap fmask;
00866             if (favIcon.mask())
00867         fmask = *favIcon.mask();
00868         else {
00869         // expensive, but works
00870         fmask = favIcon.createHeuristicMask();
00871         }
00872 
00873             bitBlt(&mask, x, y, &fmask,
00874                    0, 0, favIcon.width(), favIcon.height(),
00875                    favIcon.mask() ? Qt::OrROP : Qt::SetROP);
00876             pix.setMask(mask);
00877         }
00878         bitBlt(&pix, x, y, &favIcon);
00879     }
00880 
00881     QPixmapCache::insert(key, pix);
00882     return pix;
00883 }
00884 
00885 QImage *KIconLoader::loadOverlay(const QString &name, int size) const
00886 {
00887     QString key = name + '_' + QString::number(size);
00888     QImage *image = d->imgDict.find(key);
00889     if (image != 0L)
00890     return image;
00891 
00892     KIcon icon = findMatchingIcon(name, size);
00893     if (!icon.isValid())
00894     {
00895     kdDebug(264) << "Overlay " << name << "not found." << endl;
00896     return 0L;
00897     }
00898     image = new QImage(icon.path);
00899     // In some cases (since size in findMatchingIcon() is more a hint than a
00900     // constraint) image->size can be != size. If so perform rescaling.
00901     if ( size != image->width() )
00902         *image = image->smoothScale( size, size );
00903     d->imgDict.insert(key, image);
00904     return image;
00905 }
00906 
00907 
00908 
00909 QMovie KIconLoader::loadMovie(const QString& name, KIcon::Group group, int size) const
00910 {
00911     QString file = moviePath( name, group, size );
00912     if (file.isEmpty())
00913     return QMovie();
00914     int dirLen = file.findRev('/');
00915     QString icon = iconPath(name, size ? -size : group, true);
00916     if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
00917     return QMovie();
00918     return QMovie(file);
00919 }
00920 
00921 QString KIconLoader::moviePath(const QString& name, KIcon::Group group, int size) const
00922 {
00923     if (!d->mpGroups) return QString::null;
00924 
00925     if ( (group < -1 || group >= KIcon::LastGroup) && group != KIcon::User )
00926     {
00927     kdDebug(264) << "Illegal icon group: " << group << endl;
00928     group = KIcon::Desktop;
00929     }
00930     if (size == 0 && group < 0)
00931     {
00932     kdDebug(264) << "Neither size nor group specified!" << endl;
00933     group = KIcon::Desktop;
00934     }
00935 
00936     QString file = name + ".mng";
00937     if (group == KIcon::User)
00938     {
00939     file = d->mpDirs->findResource("appicon", file);
00940     }
00941     else
00942     {
00943     if (size == 0)
00944         size = d->mpGroups[group].size;
00945 
00946         KIcon icon;
00947 
00948     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00949         themeNode = d->links.next() )
00950     {
00951         icon = themeNode->theme->iconPath(file, size, KIcon::MatchExact);
00952         if (icon.isValid())
00953         break;
00954     }
00955 
00956     if ( !icon.isValid() )
00957     {
00958         for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00959             themeNode = d->links.next() )
00960         {
00961         icon = themeNode->theme->iconPath(file, size, KIcon::MatchBest);
00962         if (icon.isValid())
00963             break;
00964         }
00965     }
00966 
00967     file = icon.isValid() ? icon.path : QString::null;
00968     }
00969     return file;
00970 }
00971 
00972 
00973 QStringList KIconLoader::loadAnimated(const QString& name, KIcon::Group group, int size) const
00974 {
00975     QStringList lst;
00976 
00977     if (!d->mpGroups) return lst;
00978 
00979     if ((group < -1) || (group >= KIcon::LastGroup))
00980     {
00981     kdDebug(264) << "Illegal icon group: " << group << endl;
00982     group = KIcon::Desktop;
00983     }
00984     if ((size == 0) && (group < 0))
00985     {
00986     kdDebug(264) << "Neither size nor group specified!" << endl;
00987     group = KIcon::Desktop;
00988     }
00989 
00990     QString file = name + "/0001";
00991     if (group == KIcon::User)
00992     {
00993     file = d->mpDirs->findResource("appicon", file + ".png");
00994     } else
00995     {
00996     if (size == 0)
00997         size = d->mpGroups[group].size;
00998     KIcon icon = findMatchingIcon(file, size);
00999     file = icon.isValid() ? icon.path : QString::null;
01000 
01001     }
01002     if (file.isEmpty())
01003     return lst;
01004 
01005     QString path = file.left(file.length()-8);
01006     DIR* dp = opendir( QFile::encodeName(path) );
01007     if(!dp)
01008         return lst;
01009 
01010     struct dirent* ep;
01011     while( ( ep = readdir( dp ) ) != 0L )
01012     {
01013         QString fn(QFile::decodeName(ep->d_name));
01014         if(!(fn.left(4)).toUInt())
01015             continue;
01016 
01017         lst += path + fn;
01018     }
01019     closedir ( dp );
01020     lst.sort();
01021     return lst;
01022 }
01023 
01024 KIconTheme *KIconLoader::theme() const
01025 {
01026     if (d->mpThemeRoot) return d->mpThemeRoot->theme;
01027     return 0L;
01028 }
01029 
01030 int KIconLoader::currentSize(KIcon::Group group) const
01031 {
01032     if (!d->mpGroups) return -1;
01033 
01034     if (group < 0 || group >= KIcon::LastGroup)
01035     {
01036     kdDebug(264) << "Illegal icon group: " << group << endl;
01037     return -1;
01038     }
01039     return d->mpGroups[group].size;
01040 }
01041 
01042 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
01043 {
01044   QDir dir(iconsDir);
01045   QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
01046   QStringList result;
01047   QStringList::ConstIterator it;
01048   for (it=lst.begin(); it!=lst.end(); ++it)
01049     result += iconsDir + "/" + *it;
01050   return result;
01051 }
01052 
01053 QStringList KIconLoader::queryIconsByContext(int group_or_size,
01054                         KIcon::Context context) const
01055 {
01056     QStringList result;
01057     if (group_or_size >= KIcon::LastGroup)
01058     {
01059     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01060     return result;
01061     }
01062     int size;
01063     if (group_or_size >= 0)
01064     size = d->mpGroups[group_or_size].size;
01065     else
01066     size = -group_or_size;
01067 
01068     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01069             themeNode = d->links.next() )
01070        themeNode->queryIconsByContext(&result, size, context);
01071 
01072     // Eliminate duplicate entries (same icon in different directories)
01073     QString name;
01074     QStringList res2, entries;
01075     QStringList::ConstIterator it;
01076     for (it=result.begin(); it!=result.end(); ++it)
01077     {
01078     int n = (*it).findRev('/');
01079     if (n == -1)
01080         name = *it;
01081     else
01082         name = (*it).mid(n+1);
01083     name = removeIconExtension(name);
01084     if (!entries.contains(name))
01085     {
01086         entries += name;
01087         res2 += *it;
01088     }
01089     }
01090     return res2;
01091 
01092 }
01093 
01094 QStringList KIconLoader::queryIcons(int group_or_size, KIcon::Context context) const
01095 {
01096     QStringList result;
01097     if (group_or_size >= KIcon::LastGroup)
01098     {
01099     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01100     return result;
01101     }
01102     int size;
01103     if (group_or_size >= 0)
01104     size = d->mpGroups[group_or_size].size;
01105     else
01106     size = -group_or_size;
01107 
01108     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01109             themeNode = d->links.next() )
01110        themeNode->queryIcons(&result, size, context);
01111 
01112     // Eliminate duplicate entries (same icon in different directories)
01113     QString name;
01114     QStringList res2, entries;
01115     QStringList::ConstIterator it;
01116     for (it=result.begin(); it!=result.end(); ++it)
01117     {
01118     int n = (*it).findRev('/');
01119     if (n == -1)
01120         name = *it;
01121     else
01122         name = (*it).mid(n+1);
01123     name = removeIconExtension(name);
01124     if (!entries.contains(name))
01125     {
01126         entries += name;
01127         res2 += *it;
01128     }
01129     }
01130     return res2;
01131 }
01132 
01133 // used by KIconDialog to find out which contexts to offer in a combobox
01134 bool KIconLoader::hasContext(KIcon::Context context) const
01135 {
01136     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01137             themeNode = d->links.next() )
01138        if( themeNode->theme->hasContext( context ))
01139            return true;
01140     return false;
01141 }
01142 
01143 KIconEffect * KIconLoader::iconEffect() const
01144 {
01145     return &d->mpEffect;
01146 }
01147 
01148 bool KIconLoader::alphaBlending(KIcon::Group group) const
01149 {
01150     if (!d->mpGroups) return false;
01151 
01152     if (group < 0 || group >= KIcon::LastGroup)
01153     {
01154     kdDebug(264) << "Illegal icon group: " << group << endl;
01155     return false;
01156     }
01157     return d->mpGroups[group].alphaBlending;
01158 }
01159 
01160 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size, bool canReturnNull)
01161 {
01162     return loadIconSet( name, group, size, canReturnNull, true );
01163 }
01164 
01165 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size)
01166 {
01167     return loadIconSet( name, group, size, false );
01168 }
01169 
01170 /*** class for delayed icon loading for QIconSet ***/
01171 
01172 class KIconFactory
01173     : public QIconFactory
01174     {
01175     public:
01176         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01177             int size_P, KIconLoader* loader_P );
01178         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01179             int size_P, KIconLoader* loader_P, bool canReturnNull );
01180         virtual QPixmap* createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode, QIconSet::State );
01181     private:
01182         QString iconName;
01183         KIcon::Group group;
01184         int size;
01185         KIconLoader* loader;
01186         bool canReturnNull;
01187     };
01188 
01189 
01190 QIconSet KIconLoader::loadIconSet( const QString& name, KIcon::Group g, int s,
01191     bool canReturnNull, bool immediateExistenceCheck)
01192 {
01193     if ( !d->delayedLoading )
01194         return loadIconSetNonDelayed( name, g, s, canReturnNull );
01195 
01196     if (g < -1 || g > 6) {
01197         kdDebug() << "KIconLoader::loadIconSet " << name << " " << (int)g << " " << s << endl;
01198         qDebug("%s", kdBacktrace().latin1());
01199         abort();
01200     }
01201 
01202     if(canReturnNull && immediateExistenceCheck)
01203     { // we need to find out if the icon actually exists
01204         QPixmap pm = loadIcon( name, g, s, KIcon::DefaultState, NULL, true );
01205         if( pm.isNull())
01206             return QIconSet();
01207 
01208         QIconSet ret( pm );
01209         ret.installIconFactory( new KIconFactory( name, g, s, this ));
01210         return ret;
01211     }
01212 
01213     QIconSet ret;
01214     ret.installIconFactory( new KIconFactory( name, g, s, this, canReturnNull ));
01215     return ret;
01216 }
01217 
01218 QIconSet KIconLoader::loadIconSetNonDelayed( const QString& name,
01219                                              KIcon::Group g,
01220                                              int s, bool canReturnNull )
01221 {
01222     QIconSet iconset;
01223     QPixmap tmp = loadIcon(name, g, s, KIcon::ActiveState, NULL, canReturnNull);
01224     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Active );
01225     // we don't use QIconSet's resizing anyway
01226     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Active );
01227     tmp = loadIcon(name, g, s, KIcon::DisabledState, NULL, canReturnNull);
01228     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Disabled );
01229     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Disabled );
01230     tmp = loadIcon(name, g, s, KIcon::DefaultState, NULL, canReturnNull);
01231     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Normal );
01232     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Normal );
01233     return iconset;
01234 }
01235 
01236 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01237     int size_P, KIconLoader* loader_P )
01238     : iconName( iconName_P ), group( group_P ), size( size_P ), loader( loader_P )
01239 {
01240     canReturnNull = false;
01241     setAutoDelete( true );
01242 }
01243 
01244 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01245     int size_P, KIconLoader* loader_P, bool canReturnNull_P )
01246     : iconName( iconName_P ), group( group_P ), size( size_P ),
01247       loader( loader_P ), canReturnNull( canReturnNull_P)
01248 {
01249     setAutoDelete( true );
01250 }
01251 
01252 QPixmap* KIconFactory::createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode mode_P, QIconSet::State )
01253     {
01254 #ifdef KICONLOADER_CHECKS
01255     bool found = false;
01256     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
01257          it != kiconloaders->end();
01258          ++it )
01259         {
01260         if( (*it).loader == loader )
01261             {
01262             found = true;
01263             if( !(*it).valid )
01264                 {
01265 #ifdef NDEBUG
01266                 loader = KGlobal::iconLoader();
01267                 iconName = "no_way_man_you_will_get_broken_icon";
01268 #else
01269                 kdWarning() << "Using already destroyed KIconLoader for loading an icon!" << endl;
01270                 kdWarning() << "Appname:" << (*it).appname << ", icon:" << iconName << endl;
01271                 kdWarning() << "Deleted at:" << endl;
01272                 kdWarning() << (*it).delete_bt << endl;
01273                 kdWarning() << "Current:" << endl;
01274                 kdWarning() << kdBacktrace() << endl;
01275                 abort();
01276                 return NULL;
01277 #endif
01278                 }
01279             break;
01280             }
01281         }
01282     if( !found )
01283         {
01284 #ifdef NDEBUG
01285         loader = KGlobal::iconLoader();
01286         iconName = "no_way_man_you_will_get_broken_icon";
01287 #else
01288         kdWarning() << "Using unknown KIconLoader for loading an icon!" << endl;
01289         kdWarning() << "Icon:" << iconName << endl;
01290         kdWarning() << kdBacktrace() << endl;
01291         abort();
01292         return NULL;
01293 #endif
01294         }
01295 #endif
01296     // QIconSet::Mode to KIcon::State conversion
01297     static const KIcon::States tbl[] = { KIcon::DefaultState, KIcon::DisabledState, KIcon::ActiveState };
01298     int state = KIcon::DefaultState;
01299     if( mode_P <= QIconSet::Active )
01300         state = tbl[ mode_P ];
01301     if( group >= 0 && state == KIcon::ActiveState )
01302     { // active and normal icon are usually the same
01303     if( loader->iconEffect()->fingerprint(group, KIcon::ActiveState )
01304             == loader->iconEffect()->fingerprint(group, KIcon::DefaultState ))
01305             return 0; // so let QIconSet simply duplicate it
01306     }
01307     // ignore passed size
01308     // ignore passed state (i.e. on/off)
01309     QPixmap pm = loader->loadIcon( iconName, group, size, state, 0, canReturnNull );
01310     return new QPixmap( pm );
01311     }
01312 
01313 // Easy access functions
01314 
01315 QPixmap DesktopIcon(const QString& name, int force_size, int state,
01316     KInstance *instance)
01317 {
01318     KIconLoader *loader = instance->iconLoader();
01319     return loader->loadIcon(name, KIcon::Desktop, force_size, state);
01320 }
01321 
01322 QPixmap DesktopIcon(const QString& name, KInstance *instance)
01323 {
01324     return DesktopIcon(name, 0, KIcon::DefaultState, instance);
01325 }
01326 
01327 QIconSet DesktopIconSet(const QString& name, int force_size, KInstance *instance)
01328 {
01329     KIconLoader *loader = instance->iconLoader();
01330     return loader->loadIconSet( name, KIcon::Desktop, force_size );
01331 }
01332 
01333 QPixmap BarIcon(const QString& name, int force_size, int state,
01334     KInstance *instance)
01335 {
01336     KIconLoader *loader = instance->iconLoader();
01337     return loader->loadIcon(name, KIcon::Toolbar, force_size, state);
01338 }
01339 
01340 QPixmap BarIcon(const QString& name, KInstance *instance)
01341 {
01342     return BarIcon(name, 0, KIcon::DefaultState, instance);
01343 }
01344 
01345 QIconSet BarIconSet(const QString& name, int force_size, KInstance *instance)
01346 {
01347     KIconLoader *loader = instance->iconLoader();
01348     return loader->loadIconSet( name, KIcon::Toolbar, force_size );
01349 }
01350 
01351 QPixmap SmallIcon(const QString& name, int force_size, int state,
01352     KInstance *instance)
01353 {
01354     KIconLoader *loader = instance->iconLoader();
01355     return loader->loadIcon(name, KIcon::Small, force_size, state);
01356 }
01357 
01358 QPixmap SmallIcon(const QString& name, KInstance *instance)
01359 {
01360     return SmallIcon(name, 0, KIcon::DefaultState, instance);
01361 }
01362 
01363 QIconSet SmallIconSet(const QString& name, int force_size, KInstance *instance)
01364 {
01365     KIconLoader *loader = instance->iconLoader();
01366     return loader->loadIconSet( name, KIcon::Small, force_size );
01367 }
01368 
01369 QPixmap MainBarIcon(const QString& name, int force_size, int state,
01370     KInstance *instance)
01371 {
01372     KIconLoader *loader = instance->iconLoader();
01373     return loader->loadIcon(name, KIcon::MainToolbar, force_size, state);
01374 }
01375 
01376 QPixmap MainBarIcon(const QString& name, KInstance *instance)
01377 {
01378     return MainBarIcon(name, 0, KIcon::DefaultState, instance);
01379 }
01380 
01381 QIconSet MainBarIconSet(const QString& name, int force_size, KInstance *instance)
01382 {
01383     KIconLoader *loader = instance->iconLoader();
01384     return loader->loadIconSet( name, KIcon::MainToolbar, force_size );
01385 }
01386 
01387 QPixmap UserIcon(const QString& name, int state, KInstance *instance)
01388 {
01389     KIconLoader *loader = instance->iconLoader();
01390     return loader->loadIcon(name, KIcon::User, 0, state);
01391 }
01392 
01393 QPixmap UserIcon(const QString& name, KInstance *instance)
01394 {
01395     return UserIcon(name, KIcon::DefaultState, instance);
01396 }
01397 
01398 QIconSet UserIconSet(const QString& name, KInstance *instance)
01399 {
01400     KIconLoader *loader = instance->iconLoader();
01401     return loader->loadIconSet( name, KIcon::User );
01402 }
01403 
01404 int IconSize(KIcon::Group group, KInstance *instance)
01405 {
01406     KIconLoader *loader = instance->iconLoader();
01407     return loader->currentSize(group);
01408 }
01409 
01410 QPixmap KIconLoader::unknown()
01411 {
01412     QPixmap pix;
01413     if ( QPixmapCache::find("unknown", pix) )
01414             return pix;
01415 
01416     QString path = KGlobal::iconLoader()->iconPath("unknown", KIcon::Small, true);
01417     if (path.isEmpty())
01418     {
01419     kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
01420     pix.resize(32,32);
01421     } else
01422     {
01423         pix.load(path);
01424         QPixmapCache::insert("unknown", pix);
01425     }
01426 
01427     return pix;
01428 }
KDE Home | KDE Accessibility Home | Description of Access Keys