kiconloader.cpp

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