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