kiconloader.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * $Id: kiconloader.cpp 693955 2007-07-29 16:28:09Z tyrerj $
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 <kapplication.h>
00030 #include <kipc.h>
00031 #include <kdebug.h>
00032 #include <kstandarddirs.h>
00033 #include <kglobal.h>
00034 #include <kconfig.h>
00035 #include <ksimpleconfig.h>
00036 #include <kinstance.h>
00037 
00038 #include <kicontheme.h>
00039 #include <kiconloader.h>
00040 #include <kiconeffect.h>
00041 
00042 #include <sys/types.h>
00043 #include <stdlib.h> //for abs
00044 #include <unistd.h>     //for readlink
00045 #include <dirent.h>
00046 #include <config.h>
00047 #include <assert.h>
00048 
00049 #ifdef HAVE_LIBART
00050 #include "svgicons/ksvgiconengine.h"
00051 #include "svgicons/ksvgiconpainter.h"
00052 #endif
00053 
00054 #include "kiconloader_p.h"
00055 
00056 /*** KIconThemeNode: A node in the icon theme dependancy tree. ***/
00057 
00058 KIconThemeNode::KIconThemeNode(KIconTheme *_theme)
00059 {
00060     theme = _theme;
00061 }
00062 
00063 KIconThemeNode::~KIconThemeNode()
00064 {
00065     delete theme;
00066 }
00067 
00068 void KIconThemeNode::printTree(QString& dbgString) const
00069 {
00070     /* This method doesn't have much sense anymore, so maybe it should
00071        be removed in the (near?) future */
00072     dbgString += "(";
00073     dbgString += theme->name();
00074     dbgString += ")";
00075 }
00076 
00077 void KIconThemeNode::queryIcons(QStringList *result,
00078                 int size, KIcon::Context context) const
00079 {
00080     // add the icons of this theme to it
00081     *result += theme->queryIcons(size, context);
00082 }
00083 
00084 void KIconThemeNode::queryIconsByContext(QStringList *result,
00085                 int size, KIcon::Context context) const
00086 {
00087     // add the icons of this theme to it
00088     *result += theme->queryIconsByContext(size, context);
00089 }
00090 
00091 KIcon KIconThemeNode::findIcon(const QString& name, int size,
00092                    KIcon::MatchType match) const
00093 {
00094     return theme->iconPath(name, size, match);
00095 }
00096 
00097 
00098 /*** KIconGroup: Icon type description. ***/
00099 
00100 struct KIconGroup
00101 {
00102     int size;
00103     bool dblPixels;
00104     bool alphaBlending;
00105 };
00106 
00107 #define KICONLOADER_CHECKS
00108 #ifdef KICONLOADER_CHECKS
00109 // Keep a list of recently created and destroyed KIconLoader instances in order
00110 // to detect bugs like #68528.
00111 struct KIconLoaderDebug
00112     {
00113     KIconLoaderDebug( KIconLoader* l, const QString& a )
00114         : loader( l ), appname( a ), valid( true )
00115         {}
00116     KIconLoaderDebug() {}; // this QValueList feature annoys me
00117     KIconLoader* loader;
00118     QString appname;
00119     bool valid;
00120     QString delete_bt;
00121     };
00122 
00123 static QValueList< KIconLoaderDebug > *kiconloaders;
00124 #endif
00125 
00126 /*** KIconLoader: the icon loader ***/
00127 
00128 KIconLoader::KIconLoader(const QString& _appname, KStandardDirs *_dirs)
00129 {
00130 #ifdef KICONLOADER_CHECKS
00131     if( kiconloaders == NULL )
00132         kiconloaders = new QValueList< KIconLoaderDebug>();
00133     // check for the (very unlikely case) that new KIconLoader gets allocated
00134     // at exactly same address like some previous one
00135     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
00136          it != kiconloaders->end();
00137          )
00138         {
00139         if( (*it).loader == this )
00140             it = kiconloaders->remove( it );
00141         else
00142             ++it;
00143         }
00144     kiconloaders->append( KIconLoaderDebug( this, _appname ));
00145 #endif
00146     d = new KIconLoaderPrivate;
00147     d->q = this;
00148     d->mpGroups = 0L;
00149     d->imgDict.setAutoDelete(true);
00150     d->links.setAutoDelete(true);
00151 
00152     if (kapp) {
00153         kapp->addKipcEventMask(KIPC::IconChanged);
00154         QObject::connect(kapp, SIGNAL(updateIconLoaders()), d, SLOT(reconfigure()));
00155     }
00156 
00157     init( _appname, _dirs );
00158 }
00159 
00160 void KIconLoader::reconfigure( const QString& _appname, KStandardDirs *_dirs )
00161 {
00162     d->links.clear();
00163     d->imgDict.clear();
00164     d->mThemesInTree.clear();
00165     d->lastImage.reset();
00166     d->lastImageKey = QString::null;
00167     delete [] d->mpGroups;
00168 
00169     init( _appname, _dirs );
00170 }
00171 
00172 void KIconLoader::init( const QString& _appname, KStandardDirs *_dirs )
00173 {
00174     // If this is unequal to 0, the iconloader is initialized
00175     // successfully.
00176     d->mpThemeRoot = 0L;
00177 
00178     d->appname = _appname;
00179     d->extraDesktopIconsLoaded = false;
00180     d->delayedLoading = false;
00181 
00182     if (_dirs)
00183         d->mpDirs = _dirs;
00184     else
00185         d->mpDirs = KGlobal::dirs();
00186 
00187     QString appname = _appname;
00188     if (appname.isEmpty())
00189         appname = KGlobal::instance()->instanceName();
00190 
00191     // Add the default theme and its base themes to the theme tree
00192     KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
00193     if (!def->isValid())
00194     {
00195         delete def;
00196         // warn, as this is actually a small penalty hit
00197         kdDebug(264) << "Couldn't find current icon theme, falling back to default." << endl;
00198     def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
00199         if (!def->isValid())
00200         {
00201             kdError(264) << "Error: standard icon theme"
00202                          << " \"" << KIconTheme::defaultThemeName() << "\" "
00203                          << " not found!" << endl;
00204             d->mpGroups=0L;
00205             return;
00206         }
00207     }
00208     d->mpThemeRoot = new KIconThemeNode(def);
00209     d->links.append(d->mpThemeRoot);
00210     d->mThemesInTree += KIconTheme::current();
00211     addBaseThemes(d->mpThemeRoot, appname);
00212 
00213     // These have to match the order in kicontheme.h
00214     static const char * const groups[] = { "Desktop", "Toolbar", "MainToolbar", "Small", "Panel", 0L };
00215     KConfig *config = KGlobal::config();
00216     KConfigGroupSaver cs(config, "dummy");
00217 
00218     // loading config and default sizes
00219     d->mpGroups = new KIconGroup[(int) KIcon::LastGroup];
00220     for (KIcon::Group i=KIcon::FirstGroup; i<KIcon::LastGroup; i++)
00221     {
00222     if (groups[i] == 0L)
00223         break;
00224     config->setGroup(QString::fromLatin1(groups[i]) + "Icons");
00225     d->mpGroups[i].size = config->readNumEntry("Size", 0);
00226     d->mpGroups[i].dblPixels = config->readBoolEntry("DoublePixels", false);
00227     if (QPixmap::defaultDepth()>8)
00228         d->mpGroups[i].alphaBlending = config->readBoolEntry("AlphaBlending", true);
00229     else
00230         d->mpGroups[i].alphaBlending = false;
00231 
00232     if (!d->mpGroups[i].size)
00233         d->mpGroups[i].size = d->mpThemeRoot->theme->defaultSize(i);
00234     }
00235     // Make the app icons themable!!!
00236     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("icon") +
00237         KIconTheme::current() + appname + "/pics/");
00238     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("icon") +
00239         KIconTheme::current() + appname + "/toolbar/");
00240     // Insert application specific themes at the top.
00241     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00242         appname + "/pics/");
00243     // ################## KDE4: consider removing the toolbar directory
00244     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00245         appname + "/toolbar/");
00246 
00247     // Add legacy icon dirs.
00248     QStringList dirs;
00249     dirs += d->mpDirs->resourceDirs("icon");
00250     dirs += d->mpDirs->resourceDirs("pixmap");
00251     dirs += d->mpDirs->resourceDirs("xdgdata-icon");
00252     dirs += "/usr/share/pixmaps";
00253     // These are not in the icon spec, but e.g. GNOME puts some icons there anyway.
00254     dirs += d->mpDirs->resourceDirs("xdgdata-pixmap");
00255     for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it)
00256     d->mpDirs->addResourceDir("appicon", *it);
00257 
00258 #ifndef NDEBUG
00259     QString dbgString = "Theme tree: ";
00260     d->mpThemeRoot->printTree(dbgString);
00261     kdDebug(264) << dbgString << endl;
00262 #endif
00263 }
00264 
00265 KIconLoader::~KIconLoader()
00266 {
00267 #ifdef KICONLOADER_CHECKS
00268     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
00269          it != kiconloaders->end();
00270          ++it )
00271         {
00272         if( (*it).loader == this )
00273             {
00274             (*it).valid = false;
00275             (*it).delete_bt = kdBacktrace();
00276             break;
00277             }
00278         }
00279 #endif
00280     /* antlarr: There's no need to delete d->mpThemeRoot as it's already
00281        deleted when the elements of d->links are deleted */
00282     d->mpThemeRoot=0;
00283     delete[] d->mpGroups;
00284     delete d;
00285 }
00286 
00287 void KIconLoader::enableDelayedIconSetLoading( bool enable )
00288 {
00289     d->delayedLoading = enable;
00290 }
00291 
00292 bool KIconLoader::isDelayedIconSetLoadingEnabled() const
00293 {
00294     return d->delayedLoading;
00295 }
00296 
00297 void KIconLoader::addAppDir(const QString& appname)
00298 {
00299     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00300         appname + "/pics/");
00301     // ################## KDE4: consider removing the toolbar directory
00302     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00303         appname + "/toolbar/");
00304     addAppThemes(appname);
00305 }
00306 
00307 void KIconLoader::addAppThemes(const QString& appname)
00308 {
00309     if ( KIconTheme::current() != KIconTheme::defaultThemeName() )
00310     {
00311         KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
00312         if (def->isValid())
00313         {
00314             KIconThemeNode* node = new KIconThemeNode(def);
00315             d->links.append(node);
00316             addBaseThemes(node, appname);
00317         }
00318         else
00319             delete def;
00320     }
00321 
00322     KIconTheme *def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
00323     KIconThemeNode* node = new KIconThemeNode(def);
00324     d->links.append(node);
00325     addBaseThemes(node, appname);
00326 }
00327 
00328 void KIconLoader::addBaseThemes(KIconThemeNode *node, const QString &appname)
00329 {
00330     QStringList lst = node->theme->inherits();
00331     QStringList::ConstIterator it;
00332 
00333     for (it=lst.begin(); it!=lst.end(); ++it)
00334     {
00335     if( d->mThemesInTree.contains(*it) && (*it) != "hicolor")
00336         continue;
00337     KIconTheme *theme = new KIconTheme(*it,appname);
00338     if (!theme->isValid()) {
00339         delete theme;
00340         continue;
00341     }
00342         KIconThemeNode *n = new KIconThemeNode(theme);
00343     d->mThemesInTree.append(*it);
00344     d->links.append(n);
00345     addBaseThemes(n, appname);
00346     }
00347 }
00348 
00349 void KIconLoader::addExtraDesktopThemes()
00350 {
00351     if ( d->extraDesktopIconsLoaded ) return;
00352 
00353     QStringList list;
00354     QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00355     QStringList::ConstIterator it;
00356     char buf[1000];
00357     int r;
00358     for (it=icnlibs.begin(); it!=icnlibs.end(); ++it)
00359     {
00360     QDir dir(*it);
00361     if (!dir.exists())
00362         continue;
00363     QStringList lst = dir.entryList("default.*", QDir::Dirs);
00364     QStringList::ConstIterator it2;
00365     for (it2=lst.begin(); it2!=lst.end(); ++it2)
00366     {
00367         if (!KStandardDirs::exists(*it + *it2 + "/index.desktop")
00368         && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00369         continue;
00370         r=readlink( QFile::encodeName(*it + *it2) , buf, sizeof(buf)-1);
00371         if ( r>0 )
00372         {
00373           buf[r]=0;
00374           QDir dir2( buf );
00375           QString themeName=dir2.dirName();
00376 
00377           if (!list.contains(themeName))
00378         list.append(themeName);
00379         }
00380     }
00381     }
00382 
00383     for (it=list.begin(); it!=list.end(); ++it)
00384     {
00385     if ( d->mThemesInTree.contains(*it) )
00386         continue;
00387     if ( *it == QString("default.kde") ) continue;
00388 
00389     KIconTheme *def = new KIconTheme( *it, "" );
00390     KIconThemeNode* node = new KIconThemeNode(def);
00391     d->mThemesInTree.append(*it);
00392     d->links.append(node);
00393     addBaseThemes(node, "" );
00394     }
00395 
00396     d->extraDesktopIconsLoaded=true;
00397 
00398 }
00399 
00400 bool KIconLoader::extraDesktopThemesAdded() const
00401 {
00402     return d->extraDesktopIconsLoaded;
00403 }
00404 
00405 QString KIconLoader::removeIconExtension(const QString &name) const
00406 {
00407     int extensionLength=0;
00408 
00409     QString ext = name.right(4);
00410 
00411     static const QString &png_ext = KGlobal::staticQString(".png");
00412     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00413     if (ext == png_ext || ext == xpm_ext)
00414       extensionLength=4;
00415 #ifdef HAVE_LIBART
00416     else
00417     {
00418     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00419     static const QString &svg_ext = KGlobal::staticQString(".svg");
00420 
00421     if (name.right(5) == svgz_ext)
00422         extensionLength=5;
00423     else if (ext == svg_ext)
00424         extensionLength=4;
00425     }
00426 #endif
00427 
00428     if ( extensionLength > 0 )
00429     {
00430     return name.left(name.length() - extensionLength);
00431     }
00432     return name;
00433 }
00434 
00435 QString KIconLoader::removeIconExtensionInternal(const QString &name) const
00436 {
00437     QString name_noext = removeIconExtension(name);
00438 
00439 #ifndef NDEBUG
00440     if (name != name_noext)
00441     {
00442     kdDebug(264) << "Application " << KGlobal::instance()->instanceName()
00443              << " loads icon " << name << " with extension." << endl;
00444     }
00445 #endif
00446 
00447     return name_noext;
00448 }
00449 
00450 KIcon KIconLoader::findMatchingIcon(const QString& name, int size) const
00451 {
00452     KIcon icon;
00453 
00454     const QString *ext[4];
00455     int count=0;
00456     static const QString &png_ext = KGlobal::staticQString(".png");
00457     ext[count++]=&png_ext;
00458 #ifdef HAVE_LIBART
00459     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00460     ext[count++]=&svgz_ext;
00461     static const QString &svg_ext = KGlobal::staticQString(".svg");
00462     ext[count++]=&svg_ext;
00463 #endif
00464     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00465     ext[count++]=&xpm_ext;
00466 
00467     /* JRT: To follow the XDG spec, the order in which we look for an
00468        icon 1s:
00469 
00470        png, svgz, svg, xpm exact match
00471        png, svgz, svg, xpm best match
00472        next theme in inheritance tree : png, svgz, svg, xpm exact match
00473                                         png, svgz, svg, xpm best match
00474        next theme in inheritance tree : png, svgz, svg, xpm exact match
00475                                         png, svgz, svg, xpm best match
00476        and so on
00477 
00478        */
00479     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00480     themeNode = d->links.next() )
00481     {
00482     for (int i = 0 ; i < count ; i++)
00483     {
00484         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchExact);
00485         if (icon.isValid()) goto icon_found ;
00486     }
00487 
00488     for (int i = 0 ; i < count ; i++)
00489     {
00490         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest);
00491         if (icon.isValid()) goto icon_found;    
00492     }
00493     }
00494     icon_found:
00495     return icon;
00496 }
00497 
00498 inline QString KIconLoader::unknownIconPath( int size ) const
00499 {
00500     static const QString &str_unknown = KGlobal::staticQString("unknown");
00501 
00502     KIcon icon = findMatchingIcon(str_unknown, size);
00503     if (!icon.isValid())
00504     {
00505         kdDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
00506                      << size << endl;
00507         return QString::null;
00508     }
00509     return icon.path;
00510 }
00511 
00512 // Finds the absolute path to an icon.
00513 
00514 QString KIconLoader::iconPath(const QString& _name, int group_or_size,
00515                   bool canReturnNull) const
00516 {
00517     if (d->mpThemeRoot == 0L)
00518     return QString::null;
00519 
00520     if (!QDir::isRelativePath(_name))
00521     return _name;
00522 
00523     QString name = removeIconExtensionInternal( _name );
00524 
00525     QString path;
00526     if (group_or_size == KIcon::User)
00527     {
00528     static const QString &png_ext = KGlobal::staticQString(".png");
00529     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00530     path = d->mpDirs->findResource("appicon", name + png_ext);
00531 
00532 #ifdef HAVE_LIBART
00533     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00534     static const QString &svg_ext = KGlobal::staticQString(".svg");
00535     if (path.isEmpty())
00536         path = d->mpDirs->findResource("appicon", name + svgz_ext);
00537     if (path.isEmpty())
00538        path = d->mpDirs->findResource("appicon", name + svg_ext);
00539 #endif
00540     if (path.isEmpty())
00541          path = d->mpDirs->findResource("appicon", name + xpm_ext);
00542     return path;
00543     }
00544 
00545     if (group_or_size >= KIcon::LastGroup)
00546     {
00547     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
00548     return path;
00549     }
00550 
00551     int size;
00552     if (group_or_size >= 0)
00553     size = d->mpGroups[group_or_size].size;
00554     else
00555     size = -group_or_size;
00556 
00557     if (_name.isEmpty()) {
00558         if (canReturnNull)
00559             return QString::null;
00560         else
00561             return unknownIconPath(size);
00562     }
00563 
00564     KIcon icon = findMatchingIcon(name, size);
00565 
00566     if (!icon.isValid())
00567     {
00568     // Try "User" group too.
00569     path = iconPath(name, KIcon::User, true);
00570     if (!path.isEmpty() || canReturnNull)
00571         return path;
00572 
00573     if (canReturnNull)
00574         return QString::null;
00575         else
00576             return unknownIconPath(size);
00577     }
00578     return icon.path;
00579 }
00580 
00581 QPixmap KIconLoader::loadIcon(const QString& _name, KIcon::Group group, int size,
00582                               int state, QString *path_store, bool canReturnNull) const
00583 {
00584     QString name = _name;
00585     QPixmap pix;
00586     QString key;
00587     bool absolutePath=false, favIconOverlay=false;
00588 
00589     if (d->mpThemeRoot == 0L)
00590     return pix;
00591 
00592     // Special case for absolute path icons.
00593     if (name.startsWith("favicons/"))
00594     {
00595        favIconOverlay = true;
00596        name = locateLocal("cache", name+".png");
00597     }
00598     if (!QDir::isRelativePath(name)) absolutePath=true;
00599 
00600     static const QString &str_unknown = KGlobal::staticQString("unknown");
00601 
00602     // Special case for "User" icons.
00603     if (group == KIcon::User)
00604     {
00605     key = "$kicou_";
00606         key += QString::number(size); key += '_';
00607     key += name;
00608     bool inCache = QPixmapCache::find(key, pix);
00609     if (inCache && (path_store == 0L))
00610         return pix;
00611 
00612     QString path = (absolutePath) ? name :
00613             iconPath(name, KIcon::User, canReturnNull);
00614     if (path.isEmpty())
00615     {
00616         if (canReturnNull)
00617         return pix;
00618         // We don't know the desired size: use small
00619         path = iconPath(str_unknown, KIcon::Small, true);
00620         if (path.isEmpty())
00621         {
00622         kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
00623         return pix;
00624         }
00625     }
00626 
00627     if (path_store != 0L)
00628         *path_store = path;
00629     if (inCache)
00630         return pix;
00631     QImage img(path);
00632     if (size != 0)
00633         img=img.smoothScale(size,size);
00634 
00635     pix.convertFromImage(img);
00636     QPixmapCache::insert(key, pix);
00637     return pix;
00638     }
00639 
00640     // Regular case: Check parameters
00641 
00642     if ((group < -1) || (group >= KIcon::LastGroup))
00643     {
00644     kdDebug(264) << "Illegal icon group: " << group << endl;
00645     group = KIcon::Desktop;
00646     }
00647 
00648     int overlay = (state & KIcon::OverlayMask);
00649     state &= ~KIcon::OverlayMask;
00650     if ((state < 0) || (state >= KIcon::LastState))
00651     {
00652     kdDebug(264) << "Illegal icon state: " << state << endl;
00653     state = KIcon::DefaultState;
00654     }
00655 
00656     if (size == 0 && group < 0)
00657     {
00658     kdDebug(264) << "Neither size nor group specified!" << endl;
00659     group = KIcon::Desktop;
00660     }
00661 
00662     if (!absolutePath)
00663     {
00664         if (!canReturnNull && name.isEmpty())
00665             name = str_unknown;
00666         else
00667         name = removeIconExtensionInternal(name);
00668     }
00669 
00670     // If size == 0, use default size for the specified group.
00671     if (size == 0)
00672     {
00673     size = d->mpGroups[group].size;
00674     }
00675     favIconOverlay = favIconOverlay && size > 22;
00676 
00677     // Generate a unique cache key for the icon.
00678 
00679     key = "$kico_";
00680     key += name; key += '_';
00681     key += QString::number(size); key += '_';
00682 
00683     QString overlayStr = QString::number( overlay );
00684 
00685     QString noEffectKey = key + '_' + overlayStr;
00686 
00687     if (group >= 0)
00688     {
00689     key += d->mpEffect.fingerprint(group, state);
00690     if (d->mpGroups[group].dblPixels)
00691         key += QString::fromLatin1(":dblsize");
00692     } else
00693     key += QString::fromLatin1("noeffect");
00694     key += '_';
00695     key += overlayStr;
00696 
00697     // Is the icon in the cache?
00698     bool inCache = QPixmapCache::find(key, pix);
00699     if (inCache && (path_store == 0L))
00700     return pix;
00701 
00702     QImage *img = 0;
00703     int iconType;
00704     int iconThreshold;
00705 
00706     if ( ( path_store != 0L ) ||
00707          noEffectKey != d->lastImageKey )
00708     {
00709         // No? load it.
00710         KIcon icon;
00711         if (absolutePath && !favIconOverlay)
00712         {
00713             icon.context=KIcon::Any;
00714             icon.type=KIcon::Scalable;
00715             icon.path=name;
00716         }
00717         else
00718         {
00719             if (!name.isEmpty())
00720                 icon = findMatchingIcon(favIconOverlay ? QString("www") : name, size);
00721 
00722             if (!icon.isValid())
00723             {
00724                 // Try "User" icon too. Some apps expect this.
00725                 if (!name.isEmpty())
00726                     pix = loadIcon(name, KIcon::User, size, state, path_store, true);
00727                 if (!pix.isNull() || canReturnNull) {
00728                     QPixmapCache::insert(key, pix);
00729                     return pix;
00730                 }
00731 
00732                 icon = findMatchingIcon(str_unknown, size);
00733                 if (!icon.isValid())
00734                 {
00735                     kdDebug(264)
00736                         << "Warning: could not find \"Unknown\" icon for size = "
00737                         << size << endl;
00738                     return pix;
00739                 }
00740             }
00741         }
00742 
00743         if (path_store != 0L)
00744             *path_store = icon.path;
00745         if (inCache)
00746             return pix;
00747 
00748     // Use the extension as the format. Works for XPM and PNG, but not for SVG
00749     QString ext = icon.path.right(3).upper();
00750     if(ext != "SVG" && ext != "VGZ")
00751     {
00752         img = new QImage(icon.path, ext.latin1());
00753         if (img->isNull()) {
00754                 delete img;
00755         return pix;
00756             }
00757     }
00758 #ifdef HAVE_LIBART
00759     else
00760     {
00761         // Special stuff for SVG icons
00762         KSVGIconEngine *svgEngine = new KSVGIconEngine();
00763 
00764         if(svgEngine->load(size, size, icon.path))
00765         img = svgEngine->painter()->image();
00766         else
00767         img = new QImage();
00768 
00769         delete svgEngine;
00770     }
00771 #endif
00772 
00773         iconType = icon.type;
00774         iconThreshold = icon.threshold;
00775 
00776         d->lastImage = img->copy();
00777         d->lastImageKey = noEffectKey;
00778         d->lastIconType = iconType;
00779         d->lastIconThreshold = iconThreshold;
00780     }
00781     else
00782     {
00783         img = new QImage( d->lastImage.copy() );
00784         iconType = d->lastIconType;
00785         iconThreshold = d->lastIconThreshold;
00786     }
00787 
00788     // Blend in all overlays
00789     if (overlay)
00790     {
00791     QImage *ovl;
00792     KIconTheme *theme = d->mpThemeRoot->theme;
00793     if ((overlay & KIcon::LockOverlay) &&
00794         ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00795         KIconEffect::overlay(*img, *ovl);
00796     if ((overlay & KIcon::LinkOverlay) &&
00797         ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00798         KIconEffect::overlay(*img, *ovl);
00799     if ((overlay & KIcon::ZipOverlay) &&
00800         ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00801         KIconEffect::overlay(*img, *ovl);
00802     if ((overlay & KIcon::ShareOverlay) &&
00803         ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00804       KIconEffect::overlay(*img, *ovl);
00805         if (overlay & KIcon::HiddenOverlay)
00806         {
00807         if (img->depth() != 32)
00808             *img = img->convertDepth(32);
00809             for (int y = 0; y < img->height(); y++)
00810             {
00811         QRgb *line = reinterpret_cast<QRgb *>(img->scanLine(y));
00812                 for (int x = 0; x < img->width();  x++)
00813                     line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00814         }
00815     }
00816     }
00817 
00818     // Scale the icon and apply effects if necessary
00819     if (iconType == KIcon::Scalable && size != img->width())
00820     {
00821         *img = img->smoothScale(size, size);
00822     }
00823     if (iconType == KIcon::Threshold && size != img->width())
00824     {
00825     if ( abs(size-img->width())>iconThreshold )
00826         *img = img->smoothScale(size, size);
00827     }
00828     if (group >= 0 && d->mpGroups[group].dblPixels)
00829     {
00830     *img = d->mpEffect.doublePixels(*img);
00831     }
00832     if (group >= 0)
00833     {
00834     *img = d->mpEffect.apply(*img, group, state);
00835     }
00836 
00837     if (favIconOverlay)
00838     {
00839         QImage favIcon(name, "PNG");
00840         int x = img->width() - favIcon.width() - 1,
00841             y = img->height() - favIcon.height() - 1;
00842         if( favIcon.depth() != 32 )
00843             favIcon = favIcon.convertDepth( 32 );
00844         if( img->depth() != 32 )
00845             *img = img->convertDepth( 32 );
00846         for( int line = 0;
00847              line < favIcon.height();
00848              ++line )
00849         {
00850             QRgb* fpos = reinterpret_cast< QRgb* >( favIcon.scanLine( line ));
00851             QRgb* ipos = reinterpret_cast< QRgb* >( img->scanLine( line + y )) + x;
00852             for( int i = 0;
00853                  i < favIcon.width();
00854                  ++i, ++fpos, ++ipos )
00855                 *ipos = qRgba( ( qRed( *ipos ) * ( 255 - qAlpha( *fpos )) + qRed( *fpos ) * qAlpha( *fpos )) / 255,
00856                                ( qGreen( *ipos ) * ( 255 - qAlpha( *fpos )) + qGreen( *fpos ) * qAlpha( *fpos )) / 255,
00857                                ( qBlue( *ipos ) * ( 255 - qAlpha( *fpos )) + qBlue( *fpos ) * qAlpha( *fpos )) / 255,
00858                                ( qAlpha( *ipos ) * ( 255 - qAlpha( *fpos )) + qAlpha( *fpos ) * qAlpha( *fpos )) / 255 );
00859         }
00860     }
00861 
00862     pix.convertFromImage(*img);
00863 
00864     delete img;
00865 
00866     QPixmapCache::insert(key, pix);
00867     return pix;
00868 }
00869 
00870 QImage *KIconLoader::loadOverlay(const QString &name, int size) const
00871 {
00872     QString key = name + '_' + QString::number(size);
00873     QImage *image = d->imgDict.find(key);
00874     if (image != 0L)
00875     return image;
00876 
00877     KIcon icon = findMatchingIcon(name, size);
00878     if (!icon.isValid())
00879     {
00880     kdDebug(264) << "Overlay " << name << "not found." << endl;
00881     return 0L;
00882     }
00883     image = new QImage(icon.path);
00884     // In some cases (since size in findMatchingIcon() is more a hint than a
00885     // constraint) image->size can be != size. If so perform rescaling.
00886     if ( size != image->width() )
00887         *image = image->smoothScale( size, size );
00888     d->imgDict.insert(key, image);
00889     return image;
00890 }
00891 
00892 
00893 
00894 QMovie KIconLoader::loadMovie(const QString& name, KIcon::Group group, int size) const
00895 {
00896     QString file = moviePath( name, group, size );
00897     if (file.isEmpty())
00898     return QMovie();
00899     int dirLen = file.findRev('/');
00900     QString icon = iconPath(name, size ? -size : group, true);
00901     if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
00902     return QMovie();
00903     return QMovie(file);
00904 }
00905 
00906 QString KIconLoader::moviePath(const QString& name, KIcon::Group group, int size) const
00907 {
00908     if (!d->mpGroups) return QString::null;
00909 
00910     if ( (group < -1 || group >= KIcon::LastGroup) && group != KIcon::User )
00911     {
00912     kdDebug(264) << "Illegal icon group: " << group << endl;
00913     group = KIcon::Desktop;
00914     }
00915     if (size == 0 && group < 0)
00916     {
00917     kdDebug(264) << "Neither size nor group specified!" << endl;
00918     group = KIcon::Desktop;
00919     }
00920 
00921     QString file = name + ".mng";
00922     if (group == KIcon::User)
00923     {
00924     file = d->mpDirs->findResource("appicon", file);
00925     }
00926     else
00927     {
00928     if (size == 0)
00929         size = d->mpGroups[group].size;
00930 
00931         KIcon icon;
00932 
00933     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00934         themeNode = d->links.next() )
00935     {
00936         icon = themeNode->theme->iconPath(file, size, KIcon::MatchExact);
00937         if (icon.isValid()) goto icon_found ;
00938 
00939         icon = themeNode->theme->iconPath(file, size, KIcon::MatchBest);
00940         if (icon.isValid()) goto icon_found ;
00941     }
00942 
00943     icon_found:
00944     file = icon.isValid() ? icon.path : QString::null;
00945     }
00946     return file;
00947 }
00948 
00949 
00950 QStringList KIconLoader::loadAnimated(const QString& name, KIcon::Group group, int size) const
00951 {
00952     QStringList lst;
00953 
00954     if (!d->mpGroups) return lst;
00955 
00956     if ((group < -1) || (group >= KIcon::LastGroup))
00957     {
00958     kdDebug(264) << "Illegal icon group: " << group << endl;
00959     group = KIcon::Desktop;
00960     }
00961     if ((size == 0) && (group < 0))
00962     {
00963     kdDebug(264) << "Neither size nor group specified!" << endl;
00964     group = KIcon::Desktop;
00965     }
00966 
00967     QString file = name + "/0001";
00968     if (group == KIcon::User)
00969     {
00970     file = d->mpDirs->findResource("appicon", file + ".png");
00971     } else
00972     {
00973     if (size == 0)
00974         size = d->mpGroups[group].size;
00975     KIcon icon = findMatchingIcon(file, size);
00976     file = icon.isValid() ? icon.path : QString::null;
00977 
00978     }
00979     if (file.isEmpty())
00980     return lst;
00981 
00982     QString path = file.left(file.length()-8);
00983     DIR* dp = opendir( QFile::encodeName(path) );
00984     if(!dp)
00985         return lst;
00986 
00987     struct dirent* ep;
00988     while( ( ep = readdir( dp ) ) != 0L )
00989     {
00990         QString fn(QFile::decodeName(ep->d_name));
00991         if(!(fn.left(4)).toUInt())
00992             continue;
00993 
00994         lst += path + fn;
00995     }
00996     closedir ( dp );
00997     lst.sort();
00998     return lst;
00999 }
01000 
01001 KIconTheme *KIconLoader::theme() const
01002 {
01003     if (d->mpThemeRoot) return d->mpThemeRoot->theme;
01004     return 0L;
01005 }
01006 
01007 int KIconLoader::currentSize(KIcon::Group group) const
01008 {
01009     if (!d->mpGroups) return -1;
01010 
01011     if (group < 0 || group >= KIcon::LastGroup)
01012     {
01013     kdDebug(264) << "Illegal icon group: " << group << endl;
01014     return -1;
01015     }
01016     return d->mpGroups[group].size;
01017 }
01018 
01019 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
01020 {
01021   QDir dir(iconsDir);
01022   QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
01023   QStringList result;
01024   QStringList::ConstIterator it;
01025   for (it=lst.begin(); it!=lst.end(); ++it)
01026     result += iconsDir + "/" + *it;
01027   return result;
01028 }
01029 
01030 QStringList KIconLoader::queryIconsByContext(int group_or_size,
01031                         KIcon::Context context) const
01032 {
01033     QStringList result;
01034     if (group_or_size >= KIcon::LastGroup)
01035     {
01036     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01037     return result;
01038     }
01039     int size;
01040     if (group_or_size >= 0)
01041     size = d->mpGroups[group_or_size].size;
01042     else
01043     size = -group_or_size;
01044 
01045     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01046             themeNode = d->links.next() )
01047        themeNode->queryIconsByContext(&result, size, context);
01048 
01049     // Eliminate duplicate entries (same icon in different directories)
01050     QString name;
01051     QStringList res2, entries;
01052     QStringList::ConstIterator it;
01053     for (it=result.begin(); it!=result.end(); ++it)
01054     {
01055     int n = (*it).findRev('/');
01056     if (n == -1)
01057         name = *it;
01058     else
01059         name = (*it).mid(n+1);
01060     name = removeIconExtension(name);
01061     if (!entries.contains(name))
01062     {
01063         entries += name;
01064         res2 += *it;
01065     }
01066     }
01067     return res2;
01068 
01069 }
01070 
01071 QStringList KIconLoader::queryIcons(int group_or_size, KIcon::Context context) const
01072 {
01073     QStringList result;
01074     if (group_or_size >= KIcon::LastGroup)
01075     {
01076     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
01077     return result;
01078     }
01079     int size;
01080     if (group_or_size >= 0)
01081     size = d->mpGroups[group_or_size].size;
01082     else
01083     size = -group_or_size;
01084 
01085     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01086             themeNode = d->links.next() )
01087        themeNode->queryIcons(&result, size, context);
01088 
01089     // Eliminate duplicate entries (same icon in different directories)
01090     QString name;
01091     QStringList res2, entries;
01092     QStringList::ConstIterator it;
01093     for (it=result.begin(); it!=result.end(); ++it)
01094     {
01095     int n = (*it).findRev('/');
01096     if (n == -1)
01097         name = *it;
01098     else
01099         name = (*it).mid(n+1);
01100     name = removeIconExtension(name);
01101     if (!entries.contains(name))
01102     {
01103         entries += name;
01104         res2 += *it;
01105     }
01106     }
01107     return res2;
01108 }
01109 
01110 // used by KIconDialog to find out which contexts to offer in a combobox
01111 bool KIconLoader::hasContext(KIcon::Context context) const
01112 {
01113     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01114             themeNode = d->links.next() )
01115        if( themeNode->theme->hasContext( context ))
01116            return true;
01117     return false;
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 }
01406 
01407 void KIconLoaderPrivate::reconfigure()
01408 {
01409   q->reconfigure(appname, mpDirs);
01410 }
01411 
01412 #include "kiconloader_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys