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 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 // These are not in the icon spec, but e.g. GNOME puts some icons there anyway. 00250 dirs += d->mpDirs->resourceDirs("xdgdata-pixmap"); 00251 for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) 00252 d->mpDirs->addResourceDir("appicon", *it); 00253 00254 #ifndef NDEBUG 00255 QString dbgString = "Theme tree: "; 00256 d->mpThemeRoot->printTree(dbgString); 00257 kdDebug(264) << dbgString << endl; 00258 #endif 00259 } 00260 00261 KIconLoader::~KIconLoader() 00262 { 00263 #ifdef KICONLOADER_CHECKS 00264 for( QValueList< KIconLoaderDebug >::Iterator it = kiconloaders->begin(); 00265 it != kiconloaders->end(); 00266 ++it ) 00267 { 00268 if( (*it).loader == this ) 00269 { 00270 (*it).valid = false; 00271 (*it).delete_bt = kdBacktrace(); 00272 break; 00273 } 00274 } 00275 #endif 00276 /* antlarr: There's no need to delete d->mpThemeRoot as it's already 00277 deleted when the elements of d->links are deleted */ 00278 d->mpThemeRoot=0; 00279 delete[] d->mpGroups; 00280 delete d; 00281 } 00282 00283 void KIconLoader::enableDelayedIconSetLoading( bool enable ) 00284 { 00285 d->delayedLoading = enable; 00286 } 00287 00288 bool KIconLoader::isDelayedIconSetLoadingEnabled() const 00289 { 00290 return d->delayedLoading; 00291 } 00292 00293 void KIconLoader::addAppDir(const QString& appname) 00294 { 00295 d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") + 00296 appname + "/pics/"); 00297 // ################## KDE4: consider removing the toolbar directory 00298 d->mpDirs->addResourceType("appicon", KStandardDirs::kde_default("data") + 00299 appname + "/toolbar/"); 00300 addAppThemes(appname); 00301 } 00302 00303 void KIconLoader::addAppThemes(const QString& appname) 00304 { 00305 if ( KIconTheme::current() != KIconTheme::defaultThemeName() ) 00306 { 00307 KIconTheme *def = new KIconTheme(KIconTheme::current(), appname); 00308 if (def->isValid()) 00309 { 00310 KIconThemeNode* node = new KIconThemeNode(def); 00311 d->links.append(node); 00312 addBaseThemes(node, appname); 00313 } 00314 else 00315 delete def; 00316 } 00317 00318 KIconTheme *def = new KIconTheme(KIconTheme::defaultThemeName(), appname); 00319 KIconThemeNode* node = new KIconThemeNode(def); 00320 d->links.append(node); 00321 addBaseThemes(node, appname); 00322 } 00323 00324 void KIconLoader::addBaseThemes(KIconThemeNode *node, const QString &appname) 00325 { 00326 QStringList lst = node->theme->inherits(); 00327 QStringList::ConstIterator it; 00328 00329 for (it=lst.begin(); it!=lst.end(); ++it) 00330 { 00331 if( d->mThemesInTree.contains(*it) && (*it) != "hicolor") 00332 continue; 00333 KIconTheme *theme = new KIconTheme(*it,appname); 00334 if (!theme->isValid()) { 00335 delete theme; 00336 continue; 00337 } 00338 KIconThemeNode *n = new KIconThemeNode(theme); 00339 d->mThemesInTree.append(*it); 00340 d->links.append(n); 00341 addBaseThemes(n, appname); 00342 } 00343 } 00344 00345 void KIconLoader::addExtraDesktopThemes() 00346 { 00347 if ( d->extraDesktopIconsLoaded ) return; 00348 00349 QStringList list; 00350 QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon"); 00351 QStringList::ConstIterator it; 00352 char buf[1000]; 00353 int r; 00354 for (it=icnlibs.begin(); it!=icnlibs.end(); ++it) 00355 { 00356 QDir dir(*it); 00357 if (!dir.exists()) 00358 continue; 00359 QStringList lst = dir.entryList("default.*", QDir::Dirs); 00360 QStringList::ConstIterator it2; 00361 for (it2=lst.begin(); it2!=lst.end(); ++it2) 00362 { 00363 if (!KStandardDirs::exists(*it + *it2 + "/index.desktop") 00364 && !KStandardDirs::exists(*it + *it2 + "/index.theme")) 00365 continue; 00366 r=readlink( QFile::encodeName(*it + *it2) , buf, sizeof(buf)-1); 00367 if ( r>0 ) 00368 { 00369 buf[r]=0; 00370 QDir dir2( buf ); 00371 QString themeName=dir2.dirName(); 00372 00373 if (!list.contains(themeName)) 00374 list.append(themeName); 00375 } 00376 } 00377 } 00378 00379 for (it=list.begin(); it!=list.end(); ++it) 00380 { 00381 if ( d->mThemesInTree.contains(*it) ) 00382 continue; 00383 if ( *it == QString("default.kde") ) continue; 00384 00385 KIconTheme *def = new KIconTheme( *it, "" ); 00386 KIconThemeNode* node = new KIconThemeNode(def); 00387 d->mThemesInTree.append(*it); 00388 d->links.append(node); 00389 addBaseThemes(node, "" ); 00390 } 00391 00392 d->extraDesktopIconsLoaded=true; 00393 00394 } 00395 00396 bool KIconLoader::extraDesktopThemesAdded() const 00397 { 00398 return d->extraDesktopIconsLoaded; 00399 } 00400 00401 QString KIconLoader::removeIconExtension(const QString &name) const 00402 { 00403 int extensionLength=0; 00404 00405 QString ext = name.right(4); 00406 00407 static const QString &png_ext = KGlobal::staticQString(".png"); 00408 static const QString &xpm_ext = KGlobal::staticQString(".xpm"); 00409 if (ext == png_ext || ext == xpm_ext) 00410 extensionLength=4; 00411 #ifdef HAVE_LIBART 00412 else 00413 { 00414 static const QString &svgz_ext = KGlobal::staticQString(".svgz"); 00415 static const QString &svg_ext = KGlobal::staticQString(".svg"); 00416 00417 if (name.right(5) == svgz_ext) 00418 extensionLength=5; 00419 else if (ext == svg_ext) 00420 extensionLength=4; 00421 } 00422 #endif 00423 00424 if ( extensionLength > 0 ) 00425 { 00426 return name.left(name.length() - extensionLength); 00427 } 00428 return name; 00429 } 00430 00431 QString KIconLoader::removeIconExtensionInternal(const QString &name) const 00432 { 00433 QString name_noext = removeIconExtension(name); 00434 00435 #ifndef NDEBUG 00436 if (name != name_noext) 00437 { 00438 kdDebug(264) << "Application " << KGlobal::instance()->instanceName() 00439 << " loads icon " << name << " with extension." << endl; 00440 } 00441 #endif 00442 00443 return name_noext; 00444 } 00445 00446 KIcon KIconLoader::findMatchingIcon(const QString& name, int size) const 00447 { 00448 KIcon icon; 00449 00450 const QString *ext[4]; 00451 int count=0; 00452 static const QString &png_ext = KGlobal::staticQString(".png"); 00453 ext[count++]=&png_ext; 00454 #ifdef HAVE_LIBART 00455 static const QString &svgz_ext = KGlobal::staticQString(".svgz"); 00456 ext[count++]=&svgz_ext; 00457 static const QString &svg_ext = KGlobal::staticQString(".svg"); 00458 ext[count++]=&svg_ext; 00459 #endif 00460 static const QString &xpm_ext = KGlobal::staticQString(".xpm"); 00461 ext[count++]=&xpm_ext; 00462 00463 /* JRT: To follow the XDG spec, the order in which we look for an 00464 icon 1s: 00465 00466 png, svgz, svg, xpm exact match 00467 png, svgz, svg, xpm best match 00468 next theme in inheritance tree : png, svgz, svg, xpm exact match 00469 png, svgz, svg, xpm best match 00470 next theme in inheritance tree : png, svgz, svg, xpm exact match 00471 png, svgz, svg, xpm best match 00472 and so on 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()) goto icon_found ; 00482 } 00483 00484 for (int i = 0 ; i < count ; i++) 00485 { 00486 icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest); 00487 if (icon.isValid()) goto icon_found; 00488 } 00489 } 00490 icon_found: 00491 return icon; 00492 } 00493 00494 inline QString KIconLoader::unknownIconPath( int size ) const 00495 { 00496 static const QString &str_unknown = KGlobal::staticQString("unknown"); 00497 00498 KIcon icon = findMatchingIcon(str_unknown, size); 00499 if (!icon.isValid()) 00500 { 00501 kdDebug(264) << "Warning: could not find \"Unknown\" icon for size = " 00502 << size << endl; 00503 return QString::null; 00504 } 00505 return icon.path; 00506 } 00507 00508 // Finds the absolute path to an icon. 00509 00510 QString KIconLoader::iconPath(const QString& _name, int group_or_size, 00511 bool canReturnNull) const 00512 { 00513 if (d->mpThemeRoot == 0L) 00514 return QString::null; 00515 00516 if (!QDir::isRelativePath(_name)) 00517 return _name; 00518 00519 QString name = removeIconExtensionInternal( _name ); 00520 00521 QString path; 00522 if (group_or_size == KIcon::User) 00523 { 00524 static const QString &png_ext = KGlobal::staticQString(".png"); 00525 static const QString &xpm_ext = KGlobal::staticQString(".xpm"); 00526 path = d->mpDirs->findResource("appicon", name + png_ext); 00527 00528 #ifdef HAVE_LIBART 00529 static const QString &svgz_ext = KGlobal::staticQString(".svgz"); 00530 static const QString &svg_ext = KGlobal::staticQString(".svg"); 00531 if (path.isEmpty()) 00532 path = d->mpDirs->findResource("appicon", name + svgz_ext); 00533 if (path.isEmpty()) 00534 path = d->mpDirs->findResource("appicon", name + svg_ext); 00535 #endif 00536 if (path.isEmpty()) 00537 path = d->mpDirs->findResource("appicon", name + xpm_ext); 00538 return path; 00539 } 00540 00541 if (group_or_size >= KIcon::LastGroup) 00542 { 00543 kdDebug(264) << "Illegal icon group: " << group_or_size << endl; 00544 return path; 00545 } 00546 00547 int size; 00548 if (group_or_size >= 0) 00549 size = d->mpGroups[group_or_size].size; 00550 else 00551 size = -group_or_size; 00552 00553 if (_name.isEmpty()) { 00554 if (canReturnNull) 00555 return QString::null; 00556 else 00557 return unknownIconPath(size); 00558 } 00559 00560 KIcon icon = findMatchingIcon(name, size); 00561 00562 if (!icon.isValid()) 00563 { 00564 // Try "User" group too. 00565 path = iconPath(name, KIcon::User, true); 00566 if (!path.isEmpty() || canReturnNull) 00567 return path; 00568 00569 if (canReturnNull) 00570 return QString::null; 00571 else 00572 return unknownIconPath(size); 00573 } 00574 return icon.path; 00575 } 00576 00577 QPixmap KIconLoader::loadIcon(const QString& _name, KIcon::Group group, int size, 00578 int state, QString *path_store, bool canReturnNull) const 00579 { 00580 QString name = _name; 00581 QPixmap pix; 00582 QString key; 00583 bool absolutePath=false, favIconOverlay=false; 00584 00585 if (d->mpThemeRoot == 0L) 00586 return pix; 00587 00588 // Special case for absolute path icons. 00589 if (name.startsWith("favicons/")) 00590 { 00591 favIconOverlay = true; 00592 name = locateLocal("cache", name+".png"); 00593 } 00594 if (!QDir::isRelativePath(name)) absolutePath=true; 00595 00596 static const QString &str_unknown = KGlobal::staticQString("unknown"); 00597 00598 // Special case for "User" icons. 00599 if (group == KIcon::User) 00600 { 00601 key = "$kicou_"; 00602 key += QString::number(size); key += '_'; 00603 key += name; 00604 bool inCache = QPixmapCache::find(key, pix); 00605 if (inCache && (path_store == 0L)) 00606 return pix; 00607 00608 QString path = (absolutePath) ? name : 00609 iconPath(name, KIcon::User, canReturnNull); 00610 if (path.isEmpty()) 00611 { 00612 if (canReturnNull) 00613 return pix; 00614 // We don't know the desired size: use small 00615 path = iconPath(str_unknown, KIcon::Small, true); 00616 if (path.isEmpty()) 00617 { 00618 kdDebug(264) << "Warning: Cannot find \"unknown\" icon." << endl; 00619 return pix; 00620 } 00621 } 00622 00623 if (path_store != 0L) 00624 *path_store = path; 00625 if (inCache) 00626 return pix; 00627 QImage img(path); 00628 if (size != 0) 00629 img=img.smoothScale(size,size); 00630 00631 pix.convertFromImage(img); 00632 QPixmapCache::insert(key, pix); 00633 return pix; 00634 } 00635 00636 // Regular case: Check parameters 00637 00638 if ((group < -1) || (group >= KIcon::LastGroup)) 00639 { 00640 kdDebug(264) << "Illegal icon group: " << group << endl; 00641 group = KIcon::Desktop; 00642 } 00643 00644 int overlay = (state & KIcon::OverlayMask); 00645 state &= ~KIcon::OverlayMask; 00646 if ((state < 0) || (state >= KIcon::LastState)) 00647 { 00648 kdDebug(264) << "Illegal icon state: " << state << endl; 00649 state = KIcon::DefaultState; 00650 } 00651 00652 if (size == 0 && group < 0) 00653 { 00654 kdDebug(264) << "Neither size nor group specified!" << endl; 00655 group = KIcon::Desktop; 00656 } 00657 00658 if (!absolutePath) 00659 { 00660 if (!canReturnNull && name.isEmpty()) 00661 name = str_unknown; 00662 else 00663 name = removeIconExtensionInternal(name); 00664 } 00665 00666 // If size == 0, use default size for the specified group. 00667 if (size == 0) 00668 { 00669 size = d->mpGroups[group].size; 00670 } 00671 favIconOverlay = favIconOverlay && size > 22; 00672 00673 // Generate a unique cache key for the icon. 00674 00675 key = "$kico_"; 00676 key += name; key += '_'; 00677 key += QString::number(size); key += '_'; 00678 00679 QString overlayStr = QString::number( overlay ); 00680 00681 QString noEffectKey = key + '_' + overlayStr; 00682 00683 if (group >= 0) 00684 { 00685 key += d->mpEffect.fingerprint(group, state); 00686 if (d->mpGroups[group].dblPixels) 00687 key += QString::fromLatin1(":dblsize"); 00688 } else 00689 key += QString::fromLatin1("noeffect"); 00690 key += '_'; 00691 key += overlayStr; 00692 00693 // Is the icon in the cache? 00694 bool inCache = QPixmapCache::find(key, pix); 00695 if (inCache && (path_store == 0L)) 00696 return pix; 00697 00698 QImage *img = 0; 00699 int iconType; 00700 int iconThreshold; 00701 00702 if ( ( path_store != 0L ) || 00703 noEffectKey != d->lastImageKey ) 00704 { 00705 // No? load it. 00706 KIcon icon; 00707 if (absolutePath && !favIconOverlay) 00708 { 00709 icon.context=KIcon::Any; 00710 icon.type=KIcon::Scalable; 00711 icon.path=name; 00712 } 00713 else 00714 { 00715 if (!name.isEmpty()) 00716 icon = findMatchingIcon(favIconOverlay ? QString("www") : name, size); 00717 00718 if (!icon.isValid()) 00719 { 00720 // Try "User" icon too. Some apps expect this. 00721 if (!name.isEmpty()) 00722 pix = loadIcon(name, KIcon::User, size, state, path_store, true); 00723 if (!pix.isNull() || canReturnNull) { 00724 if ((group == KIcon::Small) && (pix.width() > 20 || pix.height() > 20)) { 00725 QImage tmp = pix.convertToImage(); 00726 tmp = tmp.smoothScale(20, 20); 00727 pix.convertFromImage(tmp); 00728 } 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"