kiconloader.cpp

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