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 return pix;
00686
00687 icon = findMatchingIcon(str_unknown, size);
00688 if (!icon.isValid())
00689 {
00690 kdDebug(264)
00691 << "Warning: could not find \"Unknown\" icon for size = "
00692 << size << "\n";
00693 return pix;
00694 }
00695 }
00696 }
00697
00698 if (path_store != 0L)
00699 *path_store = icon.path;
00700 if (inCache)
00701 return pix;
00702
00703
00704 QString ext = icon.path.right(3).upper();
00705 if(ext != "SVG" && ext != "VGZ")
00706 {
00707 img = new QImage(icon.path, ext.latin1());
00708 if (img->isNull()) {
00709 delete img;
00710 return pix;
00711 }
00712 }
00713 #ifdef HAVE_LIBART
00714 else
00715 {
00716
00717 KSVGIconEngine *svgEngine = new KSVGIconEngine();
00718
00719 if(svgEngine->load(size, size, icon.path))
00720 img = svgEngine->painter()->image();
00721 else
00722 img = new QImage();
00723
00724 delete svgEngine;
00725 }
00726 #endif
00727
00728 iconType = icon.type;
00729 iconThreshold = icon.threshold;
00730
00731 d->lastImage = img->copy();
00732 d->lastImageKey = noEffectKey;
00733 d->lastIconType = iconType;
00734 d->lastIconThreshold = iconThreshold;
00735 }
00736 else
00737 {
00738 img = new QImage( d->lastImage.copy() );
00739 iconType = d->lastIconType;
00740 iconThreshold = d->lastIconThreshold;
00741 }
00742
00743
00744 if (overlay)
00745 {
00746 QImage *ovl;
00747 KIconTheme *theme = d->mpThemeRoot->theme;
00748 if ((overlay & KIcon::LockOverlay) &&
00749 ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00750 KIconEffect::overlay(*img, *ovl);
00751 if ((overlay & KIcon::LinkOverlay) &&
00752 ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00753 KIconEffect::overlay(*img, *ovl);
00754 if ((overlay & KIcon::ZipOverlay) &&
00755 ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00756 KIconEffect::overlay(*img, *ovl);
00757 if ((overlay & KIcon::ShareOverlay) &&
00758 ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00759 KIconEffect::overlay(*img, *ovl);
00760 if (overlay & KIcon::HiddenOverlay)
00761 for (int y = 0; y < img->height(); y++)
00762 {
00763 Q_UINT32 *line = reinterpret_cast<Q_UINT32 *>(img->scanLine(y));
00764 for (int x = 0; x < img->width(); x++)
00765 line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00766 }
00767 }
00768
00769
00770 if ((iconType == KIcon::Scalable) && (size != img->width()))
00771 {
00772 *img = img->smoothScale(size, size);
00773 }
00774 if ((iconType == KIcon::Threshold) && (size != img->width()))
00775 {
00776 if ( abs(size-img->width())>iconThreshold )
00777 *img = img->smoothScale(size, size);
00778 }
00779 if ((group >= 0) && d->mpGroups[group].dblPixels)
00780 {
00781 *img = d->mpEffect.doublePixels(*img);
00782 }
00783 if (group >= 0)
00784 {
00785 *img = d->mpEffect.apply(*img, group, state);
00786 }
00787
00788 pix.convertFromImage(*img);
00789
00790 delete img;
00791
00792 if (favIconOverlay)
00793 {
00794 QPixmap favIcon(name, "PNG");
00795 int x = pix.width() - favIcon.width() - 1,
00796 y = pix.height() - favIcon.height() - 1;
00797 if (pix.mask())
00798 {
00799 QBitmap mask = *pix.mask();
00800 QBitmap fmask;
00801 if (favIcon.mask())
00802 fmask = *favIcon.mask();
00803 else {
00804
00805 fmask = favIcon.createHeuristicMask();
00806 }
00807
00808 bitBlt(&mask, x, y, &fmask,
00809 0, 0, favIcon.width(), favIcon.height(),
00810 favIcon.mask() ? Qt::OrROP : Qt::SetROP);
00811 pix.setMask(mask);
00812 }
00813 bitBlt(&pix, x, y, &favIcon);
00814 }
00815
00816 QPixmapCache::insert(key, pix);
00817 return pix;
00818 }
00819
00820 QImage *KIconLoader::loadOverlay(const QString &name, int size) const
00821 {
00822 QString key = name + '_' + QString::number(size);
00823 QImage *image = d->imgDict.find(key);
00824 if (image != 0L)
00825 return image;
00826
00827 KIcon icon = findMatchingIcon(name, size);
00828 if (!icon.isValid())
00829 {
00830 kdDebug(264) << "Overlay " << name << "not found.\n";
00831 return 0L;
00832 }
00833 image = new QImage(icon.path);
00834 d->imgDict.insert(key, image);
00835 return image;
00836 }
00837
00838
00839
00840 QMovie KIconLoader::loadMovie(const QString& name, KIcon::Group group, int size) const
00841 {
00842 QString file = moviePath( name, group, size );
00843 if (file.isEmpty())
00844 return QMovie();
00845 int dirLen = file.findRev('/');
00846 QString icon = iconPath(name, size ? -size : group, true);
00847 if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
00848 return QMovie();
00849 return QMovie(file);
00850 }
00851
00852 QString KIconLoader::moviePath(const QString& name, KIcon::Group group, int size) const
00853 {
00854 if (!d->mpGroups) return QString::null;
00855
00856 if ( ((group < -1) || (group >= KIcon::LastGroup)) && (group != KIcon::User) )
00857 {
00858 kdDebug(264) << "Illegal icon group: " << group << "\n";
00859 group = KIcon::Desktop;
00860 }
00861 if ((size == 0) && (group < 0))
00862 {
00863 kdDebug(264) << "Neither size nor group specified!\n";
00864 group = KIcon::Desktop;
00865 }
00866
00867 QString file = name + ".mng";
00868 if (group == KIcon::User)
00869 {
00870 file = d->mpDirs->findResource("appicon", file);
00871 }
00872 else
00873 {
00874 if (size == 0)
00875 size = d->mpGroups[group].size;
00876
00877 KIcon icon;
00878 icon = d->mpThemeRoot->findIcon(file, size, KIcon::MatchExact);
00879 if (!icon.isValid())
00880 {
00881 icon = d->mpThemeRoot->findIcon(file, size, KIcon::MatchBest);
00882 }
00883 file = icon.isValid() ? icon.path : QString::null;
00884
00885 }
00886 return file;
00887 }
00888
00889
00890 QStringList KIconLoader::loadAnimated(const QString& name, KIcon::Group group, int size) const
00891 {
00892 QStringList lst;
00893
00894 if (!d->mpGroups) return lst;
00895
00896 if ((group < -1) || (group >= KIcon::LastGroup))
00897 {
00898 kdDebug(264) << "Illegal icon group: " << group << "\n";
00899 group = KIcon::Desktop;
00900 }
00901 if ((size == 0) && (group < 0))
00902 {
00903 kdDebug(264) << "Neither size nor group specified!\n";
00904 group = KIcon::Desktop;
00905 }
00906
00907 QString file = name + "/0001";
00908 if (group == KIcon::User)
00909 {
00910 file = d->mpDirs->findResource("appicon", file + ".png");
00911 } else
00912 {
00913 if (size == 0)
00914 size = d->mpGroups[group].size;
00915 KIcon icon = findMatchingIcon(file, size);
00916 file = icon.isValid() ? icon.path : QString::null;
00917
00918 }
00919 if (file.isEmpty())
00920 return lst;
00921
00922 QString path = file.left(file.length()-8);
00923 DIR* dp = opendir( QFile::encodeName(path) );
00924 if(!dp)
00925 return lst;
00926
00927 struct dirent* ep;
00928 while( ( ep = readdir( dp ) ) != 0L )
00929 {
00930 QString fn(QFile::decodeName(ep->d_name));
00931 if(!(fn.left(4)).toUInt())
00932 continue;
00933
00934 lst += path + fn;
00935 }
00936 closedir ( dp );
00937 lst.sort();
00938 return lst;
00939 }
00940
00941 KIconTheme *KIconLoader::theme() const
00942 {
00943 if (d->mpThemeRoot) return d->mpThemeRoot->theme;
00944 return 0L;
00945 }
00946
00947 int KIconLoader::currentSize(KIcon::Group group) const
00948 {
00949 if (!d->mpGroups) return -1;
00950
00951 if ((group < 0) || (group >= KIcon::LastGroup))
00952 {
00953 kdDebug(264) << "Illegal icon group: " << group << "\n";
00954 return -1;
00955 }
00956 return d->mpGroups[group].size;
00957 }
00958
00959 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
00960 {
00961 QDir dir(iconsDir);
00962 QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
00963 QStringList result;
00964 QStringList::ConstIterator it;
00965 for (it=lst.begin(); it!=lst.end(); it++)
00966 result += iconsDir + "/" + *it;
00967 return result;
00968 }
00969
00970 QStringList KIconLoader::queryIconsByContext(int group_or_size,
00971 KIcon::Context context) const
00972 {
00973 QStringList result;
00974 if (group_or_size >= KIcon::LastGroup)
00975 {
00976 kdDebug(264) << "Illegal icon group: " << group_or_size << "\n";
00977 return result;
00978 }
00979 int size;
00980 if (group_or_size >= 0)
00981 size = d->mpGroups[group_or_size].size;
00982 else
00983 size = -group_or_size;
00984
00985 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00986 themeNode = d->links.next() )
00987 themeNode->queryIconsByContext(&result, size, context);
00988
00989
00990 QString name;
00991 QStringList res2, entries;
00992 QStringList::ConstIterator it;
00993 for (it=result.begin(); it!=result.end(); it++)
00994 {
00995 int n = (*it).findRev('/');
00996 if (n == -1)
00997 name = *it;
00998 else
00999 name = (*it).mid(n+1);
01000 if (!entries.contains(name))
01001 {
01002 entries += name;
01003 res2 += *it;
01004 }
01005 }
01006 return res2;
01007
01008 }
01009
01010 QStringList KIconLoader::queryIcons(int group_or_size, KIcon::Context context) const
01011 {
01012 QStringList result;
01013 if (group_or_size >= KIcon::LastGroup)
01014 {
01015 kdDebug(264) << "Illegal icon group: " << group_or_size << "\n";
01016 return result;
01017 }
01018 int size;
01019 if (group_or_size >= 0)
01020 size = d->mpGroups[group_or_size].size;
01021 else
01022 size = -group_or_size;
01023
01024 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01025 themeNode = d->links.next() )
01026 themeNode->queryIcons(&result, size, context);
01027
01028
01029 QString name;
01030 QStringList res2, entries;
01031 QStringList::ConstIterator it;
01032 for (it=result.begin(); it!=result.end(); it++)
01033 {
01034 int n = (*it).findRev('/');
01035 if (n == -1)
01036 name = *it;
01037 else
01038 name = (*it).mid(n+1);
01039 if (!entries.contains(name))
01040 {
01041 entries += name;
01042 res2 += *it;
01043 }
01044 }
01045 return res2;
01046 }
01047
01048 KIconEffect * KIconLoader::iconEffect() const
01049 {
01050 return &d->mpEffect;
01051 }
01052
01053 bool KIconLoader::alphaBlending(KIcon::Group group) const
01054 {
01055 if (!d->mpGroups) return -1;
01056
01057 if ((group < 0) || (group >= KIcon::LastGroup))
01058 {
01059 kdDebug(264) << "Illegal icon group: " << group << "\n";
01060 return -1;
01061 }
01062 return d->mpGroups[group].alphaBlending;
01063 }
01064
01065 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size)
01066 {
01067 return loadIconSet( name, group, size, false );
01068 }
01069
01070
01071
01072 class KIconFactory
01073 : public QIconFactory
01074 {
01075 public:
01076 KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01077 int size_P, KIconLoader* loader_P );
01078 virtual QPixmap* createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode, QIconSet::State );
01079 private:
01080 QString iconName;
01081 KIcon::Group group;
01082 int size;
01083 KIconLoader* loader;
01084 };
01085
01086
01087 QIconSet KIconLoader::loadIconSet( const QString& name, KIcon::Group group, int size,
01088 bool canReturnNull)
01089 {
01090 if ( !d->delayedLoading )
01091 return loadIconSetNonDelayed( name, group, size, canReturnNull );
01092
01093 if(canReturnNull)
01094 {
01095 QPixmap pm = loadIcon( name, group, size, KIcon::DefaultState, NULL, true );
01096 if( pm.isNull())
01097 return QIconSet();
01098
01099 QIconSet ret( pm );
01100 ret.installIconFactory( new KIconFactory( name, group, size, this ));
01101 return ret;
01102 }
01103
01104 QIconSet ret;
01105 ret.installIconFactory( new KIconFactory( name, group, size, this ));
01106 return ret;
01107 }
01108
01109 QIconSet KIconLoader::loadIconSetNonDelayed( const QString& name,
01110 KIcon::Group group,
01111 int size, bool canReturnNull )
01112 {
01113 QIconSet iconset;
01114 QPixmap tmp = loadIcon(name, group, size, KIcon::ActiveState, NULL, canReturnNull);
01115 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Active );
01116
01117 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Active );
01118 tmp = loadIcon(name, group, size, KIcon::DisabledState, NULL, canReturnNull);
01119 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Disabled );
01120 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Disabled );
01121 tmp = loadIcon(name, group, size, KIcon::DefaultState, NULL, canReturnNull);
01122 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Normal );
01123 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Normal );
01124 return iconset;
01125 }
01126
01127 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01128 int size_P, KIconLoader* loader_P )
01129 : iconName( iconName_P ), group( group_P ), size( size_P ), loader( loader_P )
01130 {
01131 setAutoDelete( true );
01132 }
01133
01134 QPixmap* KIconFactory::createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode mode_P, QIconSet::State )
01135 {
01136
01137 static const KIcon::States tbl[] = { KIcon::DefaultState, KIcon::DisabledState, KIcon::ActiveState };
01138 int state = KIcon::DefaultState;
01139 if( mode_P <= QIconSet::Active )
01140 state = tbl[ mode_P ];
01141 if( group >= 0 && state == KIcon::ActiveState )
01142 {
01143 if( loader->iconEffect()->fingerprint(group, KIcon::ActiveState )
01144 == loader->iconEffect()->fingerprint(group, KIcon::DefaultState ))
01145 return NULL;
01146 }
01147
01148
01149 QPixmap pm = loader->loadIcon( iconName, group, size, state );
01150 return new QPixmap( pm );
01151 }
01152
01153
01154
01155 QPixmap DesktopIcon(const QString& name, int force_size, int state,
01156 KInstance *instance)
01157 {
01158 KIconLoader *loader = instance->iconLoader();
01159 return loader->loadIcon(name, KIcon::Desktop, force_size, state);
01160 }
01161
01162 QPixmap DesktopIcon(const QString& name, KInstance *instance)
01163 {
01164 return DesktopIcon(name, 0, KIcon::DefaultState, instance);
01165 }
01166
01167 QIconSet DesktopIconSet(const QString& name, int force_size, KInstance *instance)
01168 {
01169 KIconLoader *loader = instance->iconLoader();
01170 return loader->loadIconSet( name, KIcon::Desktop, force_size );
01171 }
01172
01173 QPixmap BarIcon(const QString& name, int force_size, int state,
01174 KInstance *instance)
01175 {
01176 KIconLoader *loader = instance->iconLoader();
01177 return loader->loadIcon(name, KIcon::Toolbar, force_size, state);
01178 }
01179
01180 QPixmap BarIcon(const QString& name, KInstance *instance)
01181 {
01182 return BarIcon(name, 0, KIcon::DefaultState, instance);
01183 }
01184
01185 QIconSet BarIconSet(const QString& name, int force_size, KInstance *instance)
01186 {
01187 KIconLoader *loader = instance->iconLoader();
01188 return loader->loadIconSet( name, KIcon::Toolbar, force_size );
01189 }
01190
01191 QPixmap SmallIcon(const QString& name, int force_size, int state,
01192 KInstance *instance)
01193 {
01194 KIconLoader *loader = instance->iconLoader();
01195 return loader->loadIcon(name, KIcon::Small, force_size, state);
01196 }
01197
01198 QPixmap SmallIcon(const QString& name, KInstance *instance)
01199 {
01200 return SmallIcon(name, 0, KIcon::DefaultState, instance);
01201 }
01202
01203 QIconSet SmallIconSet(const QString& name, int force_size, KInstance *instance)
01204 {
01205 KIconLoader *loader = instance->iconLoader();
01206 return loader->loadIconSet( name, KIcon::Small, force_size );
01207 }
01208
01209 QPixmap MainBarIcon(const QString& name, int force_size, int state,
01210 KInstance *instance)
01211 {
01212 KIconLoader *loader = instance->iconLoader();
01213 return loader->loadIcon(name, KIcon::MainToolbar, force_size, state);
01214 }
01215
01216 QPixmap MainBarIcon(const QString& name, KInstance *instance)
01217 {
01218 return MainBarIcon(name, 0, KIcon::DefaultState, instance);
01219 }
01220
01221 QIconSet MainBarIconSet(const QString& name, int force_size, KInstance *instance)
01222 {
01223 KIconLoader *loader = instance->iconLoader();
01224 return loader->loadIconSet( name, KIcon::MainToolbar, force_size );
01225 }
01226
01227 QPixmap UserIcon(const QString& name, int state, KInstance *instance)
01228 {
01229 KIconLoader *loader = instance->iconLoader();
01230 return loader->loadIcon(name, KIcon::User, 0, state);
01231 }
01232
01233 QPixmap UserIcon(const QString& name, KInstance *instance)
01234 {
01235 return UserIcon(name, KIcon::DefaultState, instance);
01236 }
01237
01238 QIconSet UserIconSet(const QString& name, KInstance *instance)
01239 {
01240 KIconLoader *loader = instance->iconLoader();
01241 return loader->loadIconSet( name, KIcon::User );
01242 }
01243
01244 int IconSize(KIcon::Group group, KInstance *instance)
01245 {
01246 KIconLoader *loader = instance->iconLoader();
01247 return loader->currentSize(group);
01248 }
01249
01250 QPixmap KIconLoader::unknown()
01251 {
01252 QPixmap pix;
01253 if ( QPixmapCache::find("unknown", pix) )
01254 return pix;
01255
01256 QString path = KGlobal::iconLoader()->iconPath("unknown", KIcon::Small, true);
01257 if (path.isEmpty())
01258 {
01259 kdDebug(264) << "Warning: Cannot find \"unknown\" icon.\n";
01260 pix.resize(32,32);
01261 } else
01262 {
01263 pix.load(path);
01264 QPixmapCache::insert("unknown", pix);
01265 }
01266
01267 return pix;
01268 }