kiconloader.cpp

00001 /* vi: ts=8 sts=4 sw=4
00002  *
00003  * $Id: kiconloader.cpp 590791 2006-09-30 21:08:37Z chrsmrtn $
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 
00236     // Insert application specific themes at the top.
00237     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00238         appname + "/pics/");
00239     // ################## KDE4: consider removing the toolbar directory
00240     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00241         appname + "/toolbar/");
00242 
00243     // Add legacy icon dirs.
00244     QStringList dirs;
00245     dirs += d->mpDirs->resourceDirs("icon");
00246     dirs += d->mpDirs->resourceDirs("pixmap");
00247     dirs += d->mpDirs->resourceDirs("xdgdata-icon");
00248     dirs += "/usr/share/pixmaps";
00249     for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it)
00250     d->mpDirs->addResourceDir("appicon", *it);
00251 
00252 #ifndef NDEBUG
00253     QString dbgString = "Theme tree: ";
00254     d->mpThemeRoot->printTree(dbgString);
00255     kdDebug(264) << dbgString << endl;
00256 #endif
00257 }
00258 
00259 KIconLoader::~KIconLoader()
00260 {
00261 #ifdef KICONLOADER_CHECKS
00262     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
00263          it != kiconloaders->end();
00264          ++it )
00265         {
00266         if( (*it).loader == this )
00267             {
00268             (*it).valid = false;
00269             (*it).delete_bt = kdBacktrace();
00270             break;
00271             }
00272         }
00273 #endif
00274     /* antlarr: There's no need to delete d->mpThemeRoot as it's already
00275        deleted when the elements of d->links are deleted */
00276     d->mpThemeRoot=0;
00277     delete[] d->mpGroups;
00278     delete d;
00279 }
00280 
00281 void KIconLoader::enableDelayedIconSetLoading( bool enable )
00282 {
00283     d->delayedLoading = enable;
00284 }
00285 
00286 bool KIconLoader::isDelayedIconSetLoadingEnabled() const
00287 {
00288     return d->delayedLoading;
00289 }
00290 
00291 void KIconLoader::addAppDir(const QString& appname)
00292 {
00293     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00294         appname + "/pics/");
00295     // ################## KDE4: consider removing the toolbar directory
00296     d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") +
00297         appname + "/toolbar/");
00298     addAppThemes(appname);
00299 }
00300 
00301 void KIconLoader::addAppThemes(const QString& appname)
00302 {
00303     if ( KIconTheme::current() != KIconTheme::defaultThemeName() )
00304     {
00305         KIconTheme *def = new KIconTheme(KIconTheme::current(), appname);
00306         if (def->isValid())
00307         {
00308             KIconThemeNode* node = new KIconThemeNode(def);
00309             d->links.append(node);
00310             addBaseThemes(node, appname);
00311         }
00312         else
00313             delete def;
00314     }
00315 
00316     KIconTheme *def = new KIconTheme(KIconTheme::defaultThemeName(), appname);
00317     KIconThemeNode* node = new KIconThemeNode(def);
00318     d->links.append(node);
00319     addBaseThemes(node, appname);
00320 }
00321 
00322 void KIconLoader::addBaseThemes(KIconThemeNode *node, const QString &appname)
00323 {
00324     QStringList lst = node->theme->inherits();
00325     QStringList::ConstIterator it;
00326 
00327     for (it=lst.begin(); it!=lst.end(); ++it)
00328     {
00329     if( d->mThemesInTree.contains(*it) && (*it) != "hicolor")
00330         continue;
00331     KIconTheme *theme = new KIconTheme(*it,appname);
00332     if (!theme->isValid()) {
00333         delete theme;
00334         continue;
00335     }
00336         KIconThemeNode *n = new KIconThemeNode(theme);
00337     d->mThemesInTree.append(*it);
00338     d->links.append(n);
00339     addBaseThemes(n, appname);
00340     }
00341 }
00342 
00343 void KIconLoader::addExtraDesktopThemes()
00344 {
00345     if ( d->extraDesktopIconsLoaded ) return;
00346 
00347     QStringList list;
00348     QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00349     QStringList::ConstIterator it;
00350     char buf[1000];
00351     int r;
00352     for (it=icnlibs.begin(); it!=icnlibs.end(); ++it)
00353     {
00354     QDir dir(*it);
00355     if (!dir.exists())
00356         continue;
00357     QStringList lst = dir.entryList("default.*", QDir::Dirs);
00358     QStringList::ConstIterator it2;
00359     for (it2=lst.begin(); it2!=lst.end(); ++it2)
00360     {
00361         if (!KStandardDirs::exists(*it + *it2 + "/index.desktop")
00362         && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00363         continue;
00364         r=readlink( QFile::encodeName(*it + *it2) , buf, sizeof(buf)-1);
00365         if ( r>0 )
00366         {
00367           buf[r]=0;
00368           QDir dir2( buf );
00369           QString themeName=dir2.dirName();
00370 
00371           if (!list.contains(themeName))
00372         list.append(themeName);
00373         }
00374     }
00375     }
00376 
00377     for (it=list.begin(); it!=list.end(); ++it)
00378     {
00379     if ( d->mThemesInTree.contains(*it) )
00380         continue;
00381     if ( *it == QString("default.kde") ) continue;
00382 
00383     KIconTheme *def = new KIconTheme( *it, "" );
00384     KIconThemeNode* node = new KIconThemeNode(def);
00385     d->mThemesInTree.append(*it);
00386     d->links.append(node);
00387     addBaseThemes(node, "" );
00388     }
00389 
00390     d->extraDesktopIconsLoaded=true;
00391 
00392 }
00393 
00394 bool KIconLoader::extraDesktopThemesAdded() const
00395 {
00396     return d->extraDesktopIconsLoaded;
00397 }
00398 
00399 QString KIconLoader::removeIconExtension(const QString &name) const
00400 {
00401     int extensionLength=0;
00402 
00403     QString ext = name.right(4);
00404 
00405     static const QString &png_ext = KGlobal::staticQString(".png");
00406     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00407     if (ext == png_ext || ext == xpm_ext)
00408       extensionLength=4;
00409 #ifdef HAVE_LIBART
00410     else
00411     {
00412     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00413     static const QString &svg_ext = KGlobal::staticQString(".svg");
00414 
00415     if (name.right(5) == svgz_ext)
00416         extensionLength=5;
00417     else if (ext == svg_ext)
00418         extensionLength=4;
00419     }
00420 #endif
00421 
00422     if ( extensionLength > 0 )
00423     {
00424     return name.left(name.length() - extensionLength);
00425     }
00426     return name;
00427 }
00428 
00429 QString KIconLoader::removeIconExtensionInternal(const QString &name) const
00430 {
00431     QString name_noext = removeIconExtension(name);
00432 
00433 #ifndef NDEBUG
00434     if (name != name_noext)
00435     {
00436     kdDebug(264) << "Application " << KGlobal::instance()->instanceName()
00437              << " loads icon " << name << " with extension." << endl;
00438     }
00439 #endif
00440 
00441     return name_noext;
00442 }
00443 
00444 KIcon KIconLoader::findMatchingIcon(const QString& name, int size) const
00445 {
00446     KIcon icon;
00447 
00448     const QString *ext[4];
00449     int count=0;
00450     static const QString &png_ext = KGlobal::staticQString(".png");
00451     ext[count++]=&png_ext;
00452 #ifdef HAVE_LIBART
00453     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00454     ext[count++]=&svgz_ext;
00455     static const QString &svg_ext = KGlobal::staticQString(".svg");
00456     ext[count++]=&svg_ext;
00457 #endif
00458     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00459     ext[count++]=&xpm_ext;
00460 
00461     /* antlarr: Multiple inheritance is a broken concept on icon themes, so
00462        the next code doesn't support it on purpose because in fact, it was
00463        never supported at all. This makes the order in which we look for an
00464        icon as:
00465 
00466        png, svgz, svg, xpm exact match
00467        next theme in inheritance tree : png, svgz, svg, xpm exact match
00468        next theme in inheritance tree : png, svgz, svg, xpm exact match
00469        and so on
00470 
00471        And if the icon couldn't be found then it tries best match in the same
00472        order.
00473 
00474        */
00475     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00476     themeNode = d->links.next() )
00477     {
00478     for (int i = 0 ; i < count ; i++)
00479     {
00480         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchExact);
00481         if (icon.isValid())
00482         return icon;
00483     }
00484 
00485     }
00486 
00487     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00488     themeNode = d->links.next() )
00489     {
00490     for (int i = 0 ; i < count ; i++)
00491     {
00492         icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest);
00493         if (icon.isValid())
00494         return icon;
00495     }
00496 
00497     }
00498 
00499     return icon;
00500 }
00501 
00502 inline QString KIconLoader::unknownIconPath( int size ) const
00503 {
00504     static const QString &str_unknown = KGlobal::staticQString("unknown");
00505 
00506     KIcon icon = findMatchingIcon(str_unknown, size);
00507     if (!icon.isValid())
00508     {
00509         kdDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
00510                      << size << endl;
00511         return QString::null;
00512     }
00513     return icon.path;
00514 }
00515 
00516 // Finds the absolute path to an icon.
00517 
00518 QString KIconLoader::iconPath(const QString& _name, int group_or_size,
00519                   bool canReturnNull) const
00520 {
00521     if (d->mpThemeRoot == 0L)
00522     return QString::null;
00523 
00524     if (!QDir::isRelativePath(_name))
00525     return _name;
00526 
00527     QString name = removeIconExtensionInternal( _name );
00528 
00529     QString path;
00530     if (group_or_size == KIcon::User)
00531     {
00532     static const QString &png_ext = KGlobal::staticQString(".png");
00533     static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00534     path = d->mpDirs->findResource("appicon", name + png_ext);
00535 
00536 #ifdef HAVE_LIBART
00537     static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00538     static const QString &svg_ext = KGlobal::staticQString(".svg");
00539     if (path.isEmpty())
00540         path = d->mpDirs->findResource("appicon", name + svgz_ext);
00541     if (path.isEmpty())
00542        path = d->mpDirs->findResource("appicon", name + svg_ext);
00543 #endif
00544     if (path.isEmpty())
00545          path = d->mpDirs->findResource("appicon", name + xpm_ext);
00546     return path;
00547     }
00548 
00549     if (group_or_size >= KIcon::LastGroup)
00550     {
00551     kdDebug(264) << "Illegal icon group: " << group_or_size << endl;
00552     return path;
00553     }
00554 
00555     int size;
00556     if (group_or_size >= 0)
00557     size = d->mpGroups[group_or_size].size;
00558     else
00559     size = -group_or_size;
00560 
00561     if (_name.isEmpty()) {
00562         if (canReturnNull)
00563             return QString::null;
00564         else
00565             return unknownIconPath(size);
00566     }
00567 
00568     KIcon icon = findMatchingIcon(name, size);
00569 
00570     if (!icon.isValid())
00571     {
00572     // Try "User" group too.
00573     path = iconPath(name, KIcon::User, true);
00574     if (!path.isEmpty() || canReturnNull)
00575         return path;
00576 
00577     if (canReturnNull)
00578         return QString::null;
00579         else
00580             return unknownIconPath(size);
00581     }
00582     return icon.path;
00583 }
00584 
00585 QPixmap KIconLoader::loadIcon(const QString& _name, KIcon::Group group, int size,
00586                               int state, QString *path_store, bool canReturnNull) const
00587 {
00588     QString name = _name;
00589     QPixmap pix;
00590     QString key;
00591     bool absolutePath=false, favIconOverlay=false;
00592 
00593     if (d->mpThemeRoot == 0L)
00594     return pix;
00595 
00596     // Special case for absolute path icons.
00597     if (name.startsWith("favicons/"))
00598     {
00599        favIconOverlay = true;
00600        name = locateLocal("cache", name+".png");
00601     }
00602     if (!QDir::isRelativePath(name)) absolutePath=true;
00603 
00604     static const QString &str_unknown = KGlobal::staticQString("unknown");
00605 
00606     // Special case for "User" icons.
00607     if (group == KIcon::User)
00608     {
00609     key = "$kicou_";
00610         key += QString::number(size); key += '_';
00611     key += name;
00612     bool inCache = QPixmapCache::find(key, pix);
00613     if (inCache && (path_store == 0L))
00614         return pix;
00615 
00616     QString path = (absolutePath) ? name :
00617             iconPath(name, KIcon::User, canReturnNull);
00618     if (path.isEmpty())
00619     {
00620         if (canReturnNull)
00621         return pix;
00622         // We don't know the desired size: use small
00623         path = iconPath(str_unknown, KIcon::Small, true);
00624         if (path.isEmpty())
00625         {
00626         kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
00627         return pix;
00628         }
00629     }
00630 
00631     if (path_store != 0L)
00632         *path_store = path;
00633     if (inCache)
00634         return pix;
00635     QImage img(path);
00636     if (size != 0)
00637         img=img.smoothScale(size,size);
00638 
00639     pix.convertFromImage(img);
00640     QPixmapCache::insert(key, pix);
00641     return pix;
00642     }
00643 
00644     // Regular case: Check parameters
00645 
00646     if ((group < -1) || (group >= KIcon::LastGroup))
00647     {
00648     kdDebug(264) << "Illegal icon group: " << group << endl;
00649     group = KIcon::Desktop;
00650     }
00651 
00652     int overlay = (state & KIcon::OverlayMask);
00653     state &= ~KIcon::OverlayMask;
00654     if ((state < 0) || (state >= KIcon::LastState))
00655     {
00656     kdDebug(264) << "Illegal icon state: " << state << endl;
00657     state = KIcon::DefaultState;
00658     }
00659 
00660     if (size == 0 && group < 0)
00661     {
00662     kdDebug(264) << "Neither size nor group specified!" << endl;
00663     group = KIcon::Desktop;
00664     }
00665 
00666     if (!absolutePath)
00667     {
00668         if (!canReturnNull && name.isEmpty())
00669             name = str_unknown;
00670         else
00671         name = removeIconExtensionInternal(name);
00672     }
00673 
00674     // If size == 0, use default size for the specified group.
00675     if (size == 0)
00676     {
00677     size = d->mpGroups[group].size;
00678     }
00679     favIconOverlay = favIconOverlay && size > 22;
00680 
00681     // Generate a unique cache key for the icon.
00682 
00683     key = "$kico_";
00684     key += name; key += '_';
00685     key += QString::number(size); key += '_';
00686 
00687     QString overlayStr = QString::number( overlay );
00688 
00689     QString noEffectKey = key + '_' + overlayStr;
00690 
00691     if (group >= 0)
00692     {
00693     key += d->mpEffect.fingerprint(group, state);
00694     if (d->mpGroups[group].dblPixels)
00695         key += QString::fromLatin1(":dblsize");
00696     } else
00697     key += QString::fromLatin1("noeffect");
00698     key += '_';
00699     key += overlayStr;
00700 
00701     // Is the icon in the cache?
00702     bool inCache = QPixmapCache::find(key, pix);
00703     if (inCache && (path_store == 0L))
00704     return pix;
00705 
00706     QImage *img = 0;
00707     int iconType;
00708     int iconThreshold;
00709 
00710     if ( ( path_store != 0L ) ||
00711          noEffectKey != d->lastImageKey )
00712     {
00713         // No? load it.
00714         KIcon icon;
00715         if (absolutePath && !favIconOverlay)
00716         {
00717             icon.context=KIcon::Any;
00718             icon.type=KIcon::Scalable;
00719             icon.path=name;
00720         }
00721         else
00722         {
00723             if (!name.isEmpty())
00724                 icon = findMatchingIcon(favIconOverlay ? QString("www") : name, size);
00725 
00726             if (!icon.isValid())
00727             {
00728                 // Try "User" icon too. Some apps expect this.
00729                 if (!name.isEmpty())
00730                     pix = loadIcon(name, KIcon::User, size, state, path_store, true);
00731                 if (!pix.isNull() || canReturnNull)
00732                     return pix;
00733 
00734                 icon = findMatchingIcon(str_unknown, size);
00735                 if (!icon.isValid())
00736                 {
00737                     kdDebug(264)
00738                         << "Warning: could not find \"Unknown\" icon for size = "
00739                         << size << endl;
00740                     return pix;
00741                 }
00742             }
00743         }
00744 
00745         if (path_store != 0L)
00746             *path_store = icon.path;
00747         if (inCache)
00748             return pix;
00749 
00750     // Use the extension as the format. Works for XPM and PNG, but not for SVG
00751     QString ext = icon.path.right(3).upper();
00752     if(ext != "SVG" && ext != "VGZ")
00753     {
00754         img = new QImage(icon.path, ext.latin1());
00755         if (img->isNull()) {
00756                 delete img;
00757         return pix;
00758             }
00759     }
00760 #ifdef HAVE_LIBART
00761     else
00762     {
00763         // Special stuff for SVG icons
00764         KSVGIconEngine *svgEngine = new KSVGIconEngine();
00765 
00766         if(svgEngine->load(size, size, icon.path))
00767         img = svgEngine->painter()->image();
00768         else
00769         img = new QImage();
00770 
00771         delete svgEngine;
00772     }
00773 #endif
00774 
00775         iconType = icon.type;
00776         iconThreshold = icon.threshold;
00777 
00778         d->lastImage = img->copy();
00779         d->lastImageKey = noEffectKey;
00780         d->lastIconType = iconType;
00781         d->lastIconThreshold = iconThreshold;
00782     }
00783     else
00784     {
00785         img = new QImage( d->lastImage.copy() );
00786         iconType = d->lastIconType;
00787         iconThreshold = d->lastIconThreshold;
00788     }
00789 
00790     // Blend in all overlays
00791     if (overlay)
00792     {
00793     QImage *ovl;
00794     KIconTheme *theme = d->mpThemeRoot->theme;
00795     if ((overlay & KIcon::LockOverlay) &&
00796         ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00797         KIconEffect::overlay(*img, *ovl);
00798     if ((overlay & KIcon::LinkOverlay) &&
00799         ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00800         KIconEffect::overlay(*img, *ovl);
00801     if ((overlay & KIcon::ZipOverlay) &&
00802         ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00803         KIconEffect::overlay(*img, *ovl);
00804     if ((overlay & KIcon::ShareOverlay) &&
00805         ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00806       KIconEffect::overlay(*img, *ovl);
00807         if (overlay & KIcon::HiddenOverlay)
00808         {
00809         if (img->depth() != 32)
00810             *img = img->convertDepth(32);
00811             for (int y = 0; y < img->height(); y++)
00812             {
00813         QRgb *line = reinterpret_cast<QRgb *>(img->scanLine(y));
00814                 for (int x = 0; x < img->width();  x++)
00815                     line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00816         }
00817     }
00818     }
00819 
00820     // Scale the icon and apply effects if necessary
00821     if (iconType == KIcon::Scalable && size != img->width())
00822     {
00823         *img = img->smoothScale(size, size);
00824     }
00825     if (iconType == KIcon::Threshold && size != img->width())
00826     {
00827     if ( abs(size-img->width())>iconThreshold )
00828         *img = img->smoothScale(size, size);
00829     }
00830     if (group >= 0 && d->mpGroups[group].dblPixels)
00831     {
00832     *img = d->mpEffect.doublePixels(*img);
00833     }
00834     if (group >= 0)
00835     {
00836     *img = d->mpEffect.apply(*img, group, state);
00837     }
00838 
00839     if (favIconOverlay)
00840     {
00841         QImage favIcon(name, "PNG");
00842         int x = img->width() - favIcon.width() - 1,
00843             y = img->height() - favIcon.height() - 1;
00844         if( favIcon.depth() != 32 )
00845             favIcon = favIcon.convertDepth( 32 );
00846         if( img->depth() != 32 )
00847             *img = img->convertDepth( 32 );
00848         for( int line = 0;
00849              line < favIcon.height();
00850              ++line )
00851         {
00852             QRgb* fpos = reinterpret_cast< QRgb* >( favIcon.scanLine( line ));
00853             QRgb* ipos = reinterpret_cast< QRgb* >( img->scanLine( line + y )) + x;
00854             for( int i = 0;
00855                  i < favIcon.width();
00856                  ++i, ++fpos, ++ipos )
00857                 *ipos = qRgba( ( qRed( *ipos ) * ( 255 - qAlpha( *fpos )) + qRed( *fpos ) * qAlpha( *fpos )) / 255,
00858                                ( qGreen( *ipos ) * ( 255 - qAlpha( *fpos )) + qGreen( *fpos ) * qAlpha( *fpos )) / 255,
00859                                ( qBlue( *ipos ) * ( 255 - qAlpha( *fpos )) + qBlue( *fpos ) * qAlpha( *fpos )) / 255,
00860                                ( qAlpha( *ipos ) * ( 255 - qAlpha( *fpos )) + qAlpha( *fpos ) * qAlpha( *fpos )) / 255 );
00861         }
00862     }
00863 
00864     pix.convertFromImage(*img);
00865 
00866     delete img;
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 // used by KIconDialog to find out which contexts to offer in a combobox
01121 bool KIconLoader::hasContext(KIcon::Context context) const
01122 {
01123     for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01124             themeNode = d->links.next() )
01125        if( themeNode->theme->hasContext( context ))
01126            return true;
01127     return false;
01128 }
01129 
01130 KIconEffect * KIconLoader::iconEffect() const
01131 {
01132     return &d->mpEffect;
01133 }
01134 
01135 bool KIconLoader::alphaBlending(KIcon::Group group) const
01136 {
01137     if (!d->mpGroups) return false;
01138 
01139     if (group < 0 || group >= KIcon::LastGroup)
01140     {
01141     kdDebug(264) << "Illegal icon group: " << group << endl;
01142     return false;
01143     }
01144     return d->mpGroups[group].alphaBlending;
01145 }
01146 
01147 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size, bool canReturnNull)
01148 {
01149     return loadIconSet( name, group, size, canReturnNull, true );
01150 }
01151 
01152 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size)
01153 {
01154     return loadIconSet( name, group, size, false );
01155 }
01156 
01157 /*** class for delayed icon loading for QIconSet ***/
01158 
01159 class KIconFactory
01160     : public QIconFactory
01161     {
01162     public:
01163         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01164             int size_P, KIconLoader* loader_P );
01165         KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01166             int size_P, KIconLoader* loader_P, bool canReturnNull );
01167         virtual QPixmap* createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode, QIconSet::State );
01168     private:
01169         QString iconName;
01170         KIcon::Group group;
01171         int size;
01172         KIconLoader* loader;
01173         bool canReturnNull;
01174     };
01175 
01176 
01177 QIconSet KIconLoader::loadIconSet( const QString& name, KIcon::Group g, int s,
01178     bool canReturnNull, bool immediateExistenceCheck)
01179 {
01180     if ( !d->delayedLoading )
01181         return loadIconSetNonDelayed( name, g, s, canReturnNull );
01182 
01183     if (g < -1 || g > 6) {
01184         kdDebug() << "KIconLoader::loadIconSet " << name << " " << (int)g << " " << s << endl;
01185         qDebug("%s", kdBacktrace().latin1());
01186         abort();
01187     }
01188 
01189     if(canReturnNull && immediateExistenceCheck)
01190     { // we need to find out if the icon actually exists
01191         QPixmap pm = loadIcon( name, g, s, KIcon::DefaultState, NULL, true );
01192         if( pm.isNull())
01193             return QIconSet();
01194 
01195         QIconSet ret( pm );
01196         ret.installIconFactory( new KIconFactory( name, g, s, this ));
01197         return ret;
01198     }
01199 
01200     QIconSet ret;
01201     ret.installIconFactory( new KIconFactory( name, g, s, this, canReturnNull ));
01202     return ret;
01203 }
01204 
01205 QIconSet KIconLoader::loadIconSetNonDelayed( const QString& name,
01206                                              KIcon::Group g,
01207                                              int s, bool canReturnNull )
01208 {
01209     QIconSet iconset;
01210     QPixmap tmp = loadIcon(name, g, s, KIcon::ActiveState, NULL, canReturnNull);
01211     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Active );
01212     // we don't use QIconSet's resizing anyway
01213     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Active );
01214     tmp = loadIcon(name, g, s, KIcon::DisabledState, NULL, canReturnNull);
01215     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Disabled );
01216     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Disabled );
01217     tmp = loadIcon(name, g, s, KIcon::DefaultState, NULL, canReturnNull);
01218     iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Normal );
01219     iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Normal );
01220     return iconset;
01221 }
01222 
01223 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01224     int size_P, KIconLoader* loader_P )
01225     : iconName( iconName_P ), group( group_P ), size( size_P ), loader( loader_P )
01226 {
01227     canReturnNull = false;
01228     setAutoDelete( true );
01229 }
01230 
01231 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01232     int size_P, KIconLoader* loader_P, bool canReturnNull_P )
01233     : iconName( iconName_P ), group( group_P ), size( size_P ),
01234       loader( loader_P ), canReturnNull( canReturnNull_P)
01235 {
01236     setAutoDelete( true );
01237 }
01238 
01239 QPixmap* KIconFactory::createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode mode_P, QIconSet::State )
01240     {
01241 #ifdef KICONLOADER_CHECKS
01242     bool found = false;
01243     for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin();
01244          it != kiconloaders->end();
01245          ++it )
01246         {
01247         if( (*it).loader == loader )
01248             {
01249             found = true;
01250             if( !(*it).valid )
01251                 {
01252 #ifdef NDEBUG
01253                 loader = KGlobal::iconLoader();
01254                 iconName = "no_way_man_you_will_get_broken_icon";
01255 #else
01256                 kdWarning() << "Using already destroyed KIconLoader for loading an icon!" << endl;
01257                 kdWarning() << "Appname:" << (*it).appname << ", icon:" << iconName << endl;
01258                 kdWarning() << "Deleted at:" << endl;
01259                 kdWarning() << (*it).delete_bt << endl;
01260                 kdWarning() << "Current:" << endl;
01261                 kdWarning() << kdBacktrace() << endl;
01262                 abort();
01263                 return NULL;
01264 #endif
01265                 }
01266             break;
01267             }
01268         }
01269     if( !found )
01270         {
01271 #ifdef NDEBUG
01272         loader = KGlobal::iconLoader();
01273         iconName = "no_way_man_you_will_get_broken_icon";
01274 #else
01275         kdWarning() << "Using unknown KIconLoader for loading an icon!" << endl;
01276         kdWarning() << "Icon:" << iconName << endl;
01277         kdWarning() << kdBacktrace() << endl;
01278         abort();
01279         return NULL;
01280 #endif
01281         }
01282 #endif
01283     // QIconSet::Mode to KIcon::State conversion
01284     static const KIcon::States tbl[] = { KIcon::DefaultState, KIcon::DisabledState, KIcon::ActiveState };
01285     int state = KIcon::DefaultState;
01286     if( mode_P <= QIconSet::Active )
01287         state = tbl[ mode_P ];
01288     if( group >= 0 && state == KIcon::ActiveState )
01289     { // active and normal icon are usually the same
01290     if( loader->iconEffect()->fingerprint(group, KIcon::ActiveState )
01291             == loader->iconEffect()->fingerprint(group, KIcon::DefaultState ))
01292             return 0; // so let QIconSet simply duplicate it
01293     }
01294     // ignore passed size
01295     // ignore passed state (i.e. on/off)
01296     QPixmap pm = loader->loadIcon( iconName, group, size, state, 0, canReturnNull );
01297     return new QPixmap( pm );
01298     }
01299 
01300 // Easy access functions
01301 
01302 QPixmap DesktopIcon(const QString& name, int force_size, int state,
01303     KInstance *instance)
01304 {
01305     KIconLoader *loader = instance->iconLoader();
01306     return loader->loadIcon(name, KIcon::Desktop, force_size, state);
01307 }
01308 
01309 QPixmap DesktopIcon(const QString& name, KInstance *instance)
01310 {
01311     return DesktopIcon(name, 0, KIcon::DefaultState, instance);
01312 }
01313 
01314 QIconSet DesktopIconSet(const QString& name, int force_size, KInstance *instance)
01315 {
01316     KIconLoader *loader = instance->iconLoader();
01317     return loader->loadIconSet( name, KIcon::Desktop, force_size );
01318 }
01319 
01320 QPixmap BarIcon(const QString& name, int force_size, int state,
01321     KInstance *instance)
01322 {
01323     KIconLoader *loader = instance->iconLoader();
01324     return loader->loadIcon(name, KIcon::Toolbar, force_size, state);
01325 }
01326 
01327 QPixmap BarIcon(const QString& name, KInstance *instance)
01328 {
01329     return BarIcon(name, 0, KIcon::DefaultState, instance);
01330 }
01331 
01332 QIconSet BarIconSet(const QString& name, int force_size, KInstance *instance)
01333 {
01334     KIconLoader *loader = instance->iconLoader();
01335     return loader->loadIconSet( name, KIcon::Toolbar, force_size );
01336 }
01337 
01338 QPixmap SmallIcon(const QString& name, int force_size, int state,
01339     KInstance *instance)
01340 {
01341     KIconLoader *loader = instance->iconLoader();
01342     return loader->loadIcon(name, KIcon::Small, force_size, state);
01343 }
01344 
01345 QPixmap SmallIcon(const QString& name, KInstance *instance)
01346 {
01347     return SmallIcon(name, 0, KIcon::DefaultState, instance);
01348 }
01349 
01350 QIconSet SmallIconSet(const QString& name, int force_size, KInstance *instance)
01351 {
01352     KIconLoader *loader = instance->iconLoader();
01353     return loader->loadIconSet( name, KIcon::Small, force_size );
01354 }
01355 
01356 QPixmap MainBarIcon(const QString& name, int force_size, int state,
01357     KInstance *instance)
01358 {
01359     KIconLoader *loader = instance->iconLoader();
01360     return loader->loadIcon(name, KIcon::MainToolbar, force_size, state);
01361 }
01362 
01363 QPixmap MainBarIcon(const QString& name, KInstance *instance)
01364 {
01365     return MainBarIcon(name, 0, KIcon::DefaultState, instance);
01366 }
01367 
01368 QIconSet MainBarIconSet(const QString& name, int force_size, KInstance *instance)
01369 {
01370     KIconLoader *loader = instance->iconLoader();
01371     return loader->loadIconSet( name, KIcon::MainToolbar, force_size );
01372 }
01373 
01374 QPixmap UserIcon(const QString& name, int state, KInstance *instance)
01375 {
01376     KIconLoader *loader = instance->iconLoader();
01377     return loader->loadIcon(name, KIcon::User, 0, state);
01378 }
01379 
01380 QPixmap UserIcon(const QString& name, KInstance *instance)
01381 {
01382     return UserIcon(name, KIcon::DefaultState, instance);
01383 }
01384 
01385 QIconSet UserIconSet(const QString& name, KInstance *instance)
01386 {
01387     KIconLoader *loader = instance->iconLoader();
01388     return loader->loadIconSet( name, KIcon::User );
01389 }
01390 
01391 int IconSize(KIcon::Group group, KInstance *instance)
01392 {
01393     KIconLoader *loader = instance->iconLoader();
01394     return loader->currentSize(group);
01395 }
01396 
01397 QPixmap KIconLoader::unknown()
01398 {
01399     QPixmap pix;
01400     if ( QPixmapCache::find("unknown", pix) )
01401             return pix;
01402 
01403     QString path = KGlobal::iconLoader()->iconPath("unknown", KIcon::Small, true);
01404     if (path.isEmpty())
01405     {
01406     kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl;
01407     pix.resize(32,32);
01408     } else
01409     {
01410         pix.load(path);
01411         QPixmapCache::insert("unknown", pix);
01412     }
01413 
01414     return pix;
01415 }
01416 
01417 void KIconLoaderPrivate::reconfigure()
01418 {
01419   q->reconfigure(appname, mpDirs);
01420 }
01421 
01422 #include "kiconloader_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys