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