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
00434 {
00435
00436 KIconThemeNode *themeNode = d->links.first();
00437 if (themeNode->theme->name() == "Bluecurve") {
00438 for (int i = 0 ; i < count ; i++)
00439 {
00440 icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest);
00441 if (icon.isValid())
00442 return icon;
00443 }
00444 }
00445
00446 }
00447
00448 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00449 themeNode = d->links.next() )
00450 {
00451 for (int i = 0 ; i < count ; i++)
00452 {
00453 icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchExact);
00454 if (icon.isValid())
00455 return icon;
00456 }
00457
00458 }
00459
00460 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
00461 themeNode = d->links.next() )
00462 {
00463 for (int i = 0 ; i < count ; i++)
00464 {
00465 icon = themeNode->theme->iconPath(name + *ext[i], size, KIcon::MatchBest);
00466 if (icon.isValid())
00467 return icon;
00468 }
00469
00470 }
00471
00472 return icon;
00473 }
00474
00475 inline QString KIconLoader::unknownIconPath( int size ) const
00476 {
00477 static const QString &str_unknown = KGlobal::staticQString("unknown");
00478
00479 KIcon icon = findMatchingIcon(str_unknown, size);
00480 if (!icon.isValid())
00481 {
00482 kdDebug(264) << "Warning: could not find \"Unknown\" icon for size = "
00483 << size << "\n";
00484 return QString::null;
00485 }
00486 return icon.path;
00487 }
00488
00489
00490
00491 QString KIconLoader::iconPath(const QString& _name, int group_or_size,
00492 bool canReturnNull) const
00493 {
00494 if (d->mpThemeRoot == 0L)
00495 return QString::null;
00496
00497 if (_name.at(0) == '/')
00498 return _name;
00499
00500 QString name = removeIconExtension( _name );
00501
00502 QString path;
00503 if (group_or_size == KIcon::User)
00504 {
00505 static const QString &png_ext = KGlobal::staticQString(".png");
00506 static const QString &xpm_ext = KGlobal::staticQString(".xpm");
00507 path = d->mpDirs->findResource("appicon", name + png_ext);
00508
00509 #ifdef HAVE_LIBART
00510 static const QString &svgz_ext = KGlobal::staticQString(".svgz");
00511 static const QString &svg_ext = KGlobal::staticQString(".svg");
00512 if (path.isEmpty())
00513 path = d->mpDirs->findResource("appicon", name + svgz_ext);
00514 if (path.isEmpty())
00515 path = d->mpDirs->findResource("appicon", name + svg_ext);
00516 #endif
00517 if (path.isEmpty())
00518 path = d->mpDirs->findResource("appicon", name + xpm_ext);
00519 return path;
00520 }
00521
00522 if (group_or_size >= KIcon::LastGroup)
00523 {
00524 kdDebug(264) << "Illegal icon group: " << group_or_size << "\n";
00525 return path;
00526 }
00527
00528 int size;
00529 if (group_or_size >= 0)
00530 size = d->mpGroups[group_or_size].size;
00531 else
00532 size = -group_or_size;
00533
00534 if (_name.isEmpty()) {
00535 if (canReturnNull)
00536 return QString::null;
00537 else
00538 return unknownIconPath(size);
00539 }
00540
00541 KIcon icon = findMatchingIcon(name, size);
00542
00543 if (!icon.isValid())
00544 {
00545
00546 path = iconPath(name, KIcon::User, true);
00547 if (!path.isEmpty() || canReturnNull)
00548 return path;
00549
00550 if (canReturnNull)
00551 return QString::null;
00552 else
00553 return unknownIconPath(size);
00554 }
00555 return icon.path;
00556 }
00557
00558 QPixmap KIconLoader::loadIcon(const QString& _name, KIcon::Group group, int size,
00559 int state, QString *path_store, bool canReturnNull) const
00560 {
00561 QString name = _name;
00562 QPixmap pix;
00563 QString key;
00564 bool absolutePath=false, favIconOverlay=false;
00565
00566 if (d->mpThemeRoot == 0L)
00567 return pix;
00568
00569
00570 if (name.startsWith("favicons/"))
00571 {
00572 favIconOverlay = true;
00573 name = locateLocal("cache", name+".png");
00574 }
00575 if (name.at(0) == '/') absolutePath=true;
00576
00577 static const QString &str_unknown = KGlobal::staticQString("unknown");
00578
00579
00580 if (group == KIcon::User)
00581 {
00582 key = "$kicou_";
00583 key += name;
00584 bool inCache = QPixmapCache::find(key, pix);
00585 if (inCache && (path_store == 0L))
00586 return pix;
00587
00588 QString path = (absolutePath) ? name :
00589 iconPath(name, KIcon::User, canReturnNull);
00590 if (path.isEmpty())
00591 {
00592 if (canReturnNull)
00593 return pix;
00594
00595 path = iconPath(str_unknown, KIcon::Small, true);
00596 if (path.isEmpty())
00597 {
00598 kdDebug(264) << "Warning: Cannot find \"unknown\" icon.\n";
00599 return pix;
00600 }
00601 }
00602
00603 if (path_store != 0L)
00604 *path_store = path;
00605 if (inCache)
00606 return pix;
00607 pix.load(path);
00608 QPixmapCache::insert(key, pix);
00609 return pix;
00610 }
00611
00612
00613
00614 if ((group < -1) || (group >= KIcon::LastGroup))
00615 {
00616 kdDebug(264) << "Illegal icon group: " << group << "\n";
00617 group = KIcon::Desktop;
00618 }
00619
00620 int overlay = (state & KIcon::OverlayMask);
00621 state &= ~KIcon::OverlayMask;
00622 if ((state < 0) || (state >= KIcon::LastState))
00623 {
00624 kdDebug(264) << "Illegal icon state: " << state << "\n";
00625 state = KIcon::DefaultState;
00626 }
00627
00628 if ((size == 0) && (group < 0))
00629 {
00630 kdDebug(264) << "Neither size nor group specified!\n";
00631 group = KIcon::Desktop;
00632 }
00633
00634 if (!absolutePath)
00635 {
00636 if (!canReturnNull && name.isEmpty())
00637 name = str_unknown;
00638 else
00639 name = removeIconExtension(name);
00640 }
00641
00642
00643 if (size == 0)
00644 {
00645 size = d->mpGroups[group].size;
00646 }
00647 favIconOverlay = favIconOverlay && (size > 22);
00648
00649
00650
00651 key = "$kico_";
00652 key += name; key += '_';
00653 key += QString::number(size); key += '_';
00654
00655 QString overlayStr = QString::number( overlay );
00656
00657 QString noEffectKey = key + '_' + overlayStr;
00658
00659 if (group >= 0)
00660 {
00661 key += d->mpEffect.fingerprint(group, state);
00662 if (d->mpGroups[group].dblPixels)
00663 key += QString::fromLatin1(":dblsize");
00664 } else
00665 key += QString::fromLatin1("noeffect");
00666 key += '_';
00667 key += overlayStr;
00668
00669
00670 bool inCache = QPixmapCache::find(key, pix);
00671 if (inCache && (path_store == 0L))
00672 return pix;
00673
00674 QImage *img = 0;
00675 int iconType;
00676 int iconThreshold;
00677
00678 if ( ( path_store != 0L ) ||
00679 noEffectKey != d->lastImageKey )
00680 {
00681
00682 KIcon icon;
00683 if (absolutePath && !favIconOverlay)
00684 {
00685 icon.context=KIcon::Any;
00686 icon.type=KIcon::Scalable;
00687 icon.path=name;
00688 }
00689 else
00690 {
00691 if (!name.isEmpty())
00692 icon = findMatchingIcon(favIconOverlay ? QString("www") : name, size);
00693
00694 if (!icon.isValid())
00695 {
00696
00697 if (!name.isEmpty())
00698 pix = loadIcon(name, KIcon::User, size, state, path_store, true);
00699 if (!pix.isNull() || canReturnNull) {
00700 if (pix.width() > size || pix.height() > size) {
00701 QImage tmp = pix.convertToImage();
00702 tmp = tmp.smoothScale(size, size);
00703 pix.convertFromImage(tmp);
00704 }
00705 return pix;
00706 }
00707
00708 icon = findMatchingIcon(str_unknown, size);
00709 if (!icon.isValid())
00710 {
00711 kdDebug(264)
00712 << "Warning: could not find \"Unknown\" icon for size = "
00713 << size << "\n";
00714 return pix;
00715 }
00716 }
00717 }
00718
00719 if (path_store != 0L)
00720 *path_store = icon.path;
00721 if (inCache)
00722 return pix;
00723
00724
00725 QString ext = icon.path.right(3).upper();
00726 if(ext != "SVG" && ext != "VGZ")
00727 {
00728 img = new QImage(icon.path, ext.latin1());
00729 if (img->isNull()) {
00730 delete img;
00731 return pix;
00732 }
00733 }
00734 #ifdef HAVE_LIBART
00735 else
00736 {
00737
00738 KSVGIconEngine *svgEngine = new KSVGIconEngine();
00739
00740 if(svgEngine->load(size, size, icon.path))
00741 img = svgEngine->painter()->image();
00742 else
00743 img = new QImage();
00744
00745 delete svgEngine;
00746 }
00747 #endif
00748
00749 iconType = icon.type;
00750 iconThreshold = icon.threshold;
00751
00752 d->lastImage = img->copy();
00753 d->lastImageKey = noEffectKey;
00754 d->lastIconType = iconType;
00755 d->lastIconThreshold = iconThreshold;
00756 }
00757 else
00758 {
00759 img = new QImage( d->lastImage.copy() );
00760 iconType = d->lastIconType;
00761 iconThreshold = d->lastIconThreshold;
00762 }
00763
00764
00765 if (overlay)
00766 {
00767 QImage *ovl;
00768 KIconTheme *theme = d->mpThemeRoot->theme;
00769 if ((overlay & KIcon::LockOverlay) &&
00770 ((ovl = loadOverlay(theme->lockOverlay(), size)) != 0L))
00771 KIconEffect::overlay(*img, *ovl);
00772 if ((overlay & KIcon::LinkOverlay) &&
00773 ((ovl = loadOverlay(theme->linkOverlay(), size)) != 0L))
00774 KIconEffect::overlay(*img, *ovl);
00775 if ((overlay & KIcon::ZipOverlay) &&
00776 ((ovl = loadOverlay(theme->zipOverlay(), size)) != 0L))
00777 KIconEffect::overlay(*img, *ovl);
00778 if ((overlay & KIcon::ShareOverlay) &&
00779 ((ovl = loadOverlay(theme->shareOverlay(), size)) != 0L))
00780 KIconEffect::overlay(*img, *ovl);
00781 if (overlay & KIcon::HiddenOverlay)
00782 for (int y = 0; y < img->height(); y++)
00783 {
00784 Q_UINT32 *line = reinterpret_cast<Q_UINT32 *>(img->scanLine(y));
00785 for (int x = 0; x < img->width(); x++)
00786 line[x] = (line[x] & 0x00ffffff) | (QMIN(0x80, qAlpha(line[x])) << 24);
00787 }
00788 }
00789
00790
00791 if ((iconType == KIcon::Scalable) && (size != img->width()))
00792 {
00793 *img = img->smoothScale(size, size);
00794 }
00795 if ((iconType == KIcon::Threshold) && (size != img->width()))
00796 {
00797 if ( abs(size-img->width())>iconThreshold )
00798 *img = img->smoothScale(size, size);
00799 }
00800 if ((iconType == KIcon::Fixed) && (size != img->width()))
00801 {
00802 *img = img->smoothScale(size, size);
00803 }
00804 if ((group >= 0) && d->mpGroups[group].dblPixels)
00805 {
00806 *img = d->mpEffect.doublePixels(*img);
00807 }
00808 if (group >= 0)
00809 {
00810 *img = d->mpEffect.apply(*img, group, state);
00811 }
00812
00813 pix.convertFromImage(*img);
00814
00815 delete img;
00816
00817 if (favIconOverlay)
00818 {
00819 QPixmap favIcon(name, "PNG");
00820 int x = pix.width() - favIcon.width() - 1,
00821 y = pix.height() - favIcon.height() - 1;
00822 if (pix.mask())
00823 {
00824 QBitmap mask = *pix.mask();
00825 QBitmap fmask;
00826 if (favIcon.mask())
00827 fmask = *favIcon.mask();
00828 else {
00829
00830 fmask = favIcon.createHeuristicMask();
00831 }
00832
00833 bitBlt(&mask, x, y, &fmask,
00834 0, 0, favIcon.width(), favIcon.height(),
00835 favIcon.mask() ? Qt::OrROP : Qt::SetROP);
00836 pix.setMask(mask);
00837 }
00838 bitBlt(&pix, x, y, &favIcon);
00839 }
00840
00841 QPixmapCache::insert(key, pix);
00842 return pix;
00843 }
00844
00845 QImage *KIconLoader::loadOverlay(const QString &name, int size) const
00846 {
00847 QString key = name + '_' + QString::number(size);
00848 QImage *image = d->imgDict.find(key);
00849 if (image != 0L)
00850 return image;
00851
00852 KIcon icon = findMatchingIcon(name, size);
00853 if (!icon.isValid())
00854 {
00855 kdDebug(264) << "Overlay " << name << "not found.\n";
00856 return 0L;
00857 }
00858 image = new QImage(icon.path);
00859 d->imgDict.insert(key, image);
00860 return image;
00861 }
00862
00863
00864
00865 QMovie KIconLoader::loadMovie(const QString& name, KIcon::Group group, int size) const
00866 {
00867 QString file = moviePath( name, group, size );
00868 if (file.isEmpty())
00869 return QMovie();
00870 int dirLen = file.findRev('/');
00871 QString icon = iconPath(name, size ? -size : group, true);
00872 if (!icon.isEmpty() && file.left(dirLen) != icon.left(dirLen))
00873 return QMovie();
00874 return QMovie(file);
00875 }
00876
00877 QString KIconLoader::moviePath(const QString& name, KIcon::Group group, int size) const
00878 {
00879 if (!d->mpGroups) return QString::null;
00880
00881 if ( ((group < -1) || (group >= KIcon::LastGroup)) && (group != KIcon::User) )
00882 {
00883 kdDebug(264) << "Illegal icon group: " << group << "\n";
00884 group = KIcon::Desktop;
00885 }
00886 if ((size == 0) && (group < 0))
00887 {
00888 kdDebug(264) << "Neither size nor group specified!\n";
00889 group = KIcon::Desktop;
00890 }
00891
00892 QString file = name + ".mng";
00893 if (group == KIcon::User)
00894 {
00895 file = d->mpDirs->findResource("appicon", file);
00896 }
00897 else
00898 {
00899 if (size == 0)
00900 size = d->mpGroups[group].size;
00901
00902 KIcon icon;
00903 icon = d->mpThemeRoot->findIcon(file, size, KIcon::MatchExact);
00904 if (!icon.isValid())
00905 {
00906 icon = d->mpThemeRoot->findIcon(file, size, KIcon::MatchBest);
00907 }
00908 file = icon.isValid() ? icon.path : QString::null;
00909
00910 }
00911 return file;
00912 }
00913
00914
00915 QStringList KIconLoader::loadAnimated(const QString& name, KIcon::Group group, int size) const
00916 {
00917 QStringList lst;
00918
00919 if (!d->mpGroups) return lst;
00920
00921 if ((group < -1) || (group >= KIcon::LastGroup))
00922 {
00923 kdDebug(264) << "Illegal icon group: " << group << "\n";
00924 group = KIcon::Desktop;
00925 }
00926 if ((size == 0) && (group < 0))
00927 {
00928 kdDebug(264) << "Neither size nor group specified!\n";
00929 group = KIcon::Desktop;
00930 }
00931
00932 QString file = name + "/0001";
00933 if (group == KIcon::User)
00934 {
00935 file = d->mpDirs->findResource("appicon", file + ".png");
00936 } else
00937 {
00938 if (size == 0)
00939 size = d->mpGroups[group].size;
00940 KIcon icon = findMatchingIcon(file, size);
00941 file = icon.isValid() ? icon.path : QString::null;
00942
00943 }
00944 if (file.isEmpty())
00945 return lst;
00946
00947 QString path = file.left(file.length()-8);
00948 DIR* dp = opendir( QFile::encodeName(path) );
00949 if(!dp)
00950 return lst;
00951
00952 struct dirent* ep;
00953 while( ( ep = readdir( dp ) ) != 0L )
00954 {
00955 QString fn(QFile::decodeName(ep->d_name));
00956 if(!(fn.left(4)).toUInt())
00957 continue;
00958
00959 lst += path + fn;
00960 }
00961 closedir ( dp );
00962 lst.sort();
00963 return lst;
00964 }
00965
00966 KIconTheme *KIconLoader::theme() const
00967 {
00968 if (d->mpThemeRoot) return d->mpThemeRoot->theme;
00969 return 0L;
00970 }
00971
00972 int KIconLoader::currentSize(KIcon::Group group) const
00973 {
00974 if (!d->mpGroups) return -1;
00975
00976 if ((group < 0) || (group >= KIcon::LastGroup))
00977 {
00978 kdDebug(264) << "Illegal icon group: " << group << "\n";
00979 return -1;
00980 }
00981 return d->mpGroups[group].size;
00982 }
00983
00984 QStringList KIconLoader::queryIconsByDir( const QString& iconsDir ) const
00985 {
00986 QDir dir(iconsDir);
00987 QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
00988 QStringList result;
00989 QStringList::ConstIterator it;
00990 for (it=lst.begin(); it!=lst.end(); it++)
00991 result += iconsDir + "/" + *it;
00992 return result;
00993 }
00994
00995 QStringList KIconLoader::queryIconsByContext(int group_or_size,
00996 KIcon::Context context) const
00997 {
00998 QStringList result;
00999 if (group_or_size >= KIcon::LastGroup)
01000 {
01001 kdDebug(264) << "Illegal icon group: " << group_or_size << "\n";
01002 return result;
01003 }
01004 int size;
01005 if (group_or_size >= 0)
01006 size = d->mpGroups[group_or_size].size;
01007 else
01008 size = -group_or_size;
01009
01010 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01011 themeNode = d->links.next() )
01012 themeNode->queryIconsByContext(&result, size, context);
01013
01014
01015 QString name;
01016 QStringList res2, entries;
01017 QStringList::ConstIterator it;
01018 for (it=result.begin(); it!=result.end(); it++)
01019 {
01020 int n = (*it).findRev('/');
01021 if (n == -1)
01022 name = *it;
01023 else
01024 name = (*it).mid(n+1);
01025 if (!entries.contains(name))
01026 {
01027 entries += name;
01028 res2 += *it;
01029 }
01030 }
01031 return res2;
01032
01033 }
01034
01035 QStringList KIconLoader::queryIcons(int group_or_size, KIcon::Context context) const
01036 {
01037 QStringList result;
01038 if (group_or_size >= KIcon::LastGroup)
01039 {
01040 kdDebug(264) << "Illegal icon group: " << group_or_size << "\n";
01041 return result;
01042 }
01043 int size;
01044 if (group_or_size >= 0)
01045 size = d->mpGroups[group_or_size].size;
01046 else
01047 size = -group_or_size;
01048
01049 for ( KIconThemeNode *themeNode = d->links.first() ; themeNode ;
01050 themeNode = d->links.next() )
01051 themeNode->queryIcons(&result, size, context);
01052
01053
01054 QString name;
01055 QStringList res2, entries;
01056 QStringList::ConstIterator it;
01057 for (it=result.begin(); it!=result.end(); it++)
01058 {
01059 int n = (*it).findRev('/');
01060 if (n == -1)
01061 name = *it;
01062 else
01063 name = (*it).mid(n+1);
01064 if (!entries.contains(name))
01065 {
01066 entries += name;
01067 res2 += *it;
01068 }
01069 }
01070 return res2;
01071 }
01072
01073 KIconEffect * KIconLoader::iconEffect() const
01074 {
01075 return &d->mpEffect;
01076 }
01077
01078 bool KIconLoader::alphaBlending(KIcon::Group group) const
01079 {
01080 if (!d->mpGroups) return -1;
01081
01082 if ((group < 0) || (group >= KIcon::LastGroup))
01083 {
01084 kdDebug(264) << "Illegal icon group: " << group << "\n";
01085 return -1;
01086 }
01087 return d->mpGroups[group].alphaBlending;
01088 }
01089
01090 QIconSet KIconLoader::loadIconSet(const QString& name, KIcon::Group group, int size)
01091 {
01092 return loadIconSet( name, group, size, false );
01093 }
01094
01095
01096
01097 class KIconFactory
01098 : public QIconFactory
01099 {
01100 public:
01101 KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01102 int size_P, KIconLoader* loader_P );
01103 virtual QPixmap* createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode, QIconSet::State );
01104 private:
01105 QString iconName;
01106 KIcon::Group group;
01107 int size;
01108 KIconLoader* loader;
01109 };
01110
01111
01112 QIconSet KIconLoader::loadIconSet( const QString& name, KIcon::Group group, int size,
01113 bool canReturnNull)
01114 {
01115 if ( !d->delayedLoading )
01116 return loadIconSetNonDelayed( name, group, size, canReturnNull );
01117
01118 if(canReturnNull)
01119 {
01120 QPixmap pm = loadIcon( name, group, size, KIcon::DefaultState, NULL, true );
01121 if( pm.isNull())
01122 return QIconSet();
01123
01124 QIconSet ret( pm );
01125 ret.installIconFactory( new KIconFactory( name, group, size, this ));
01126 return ret;
01127 }
01128
01129 QIconSet ret;
01130 ret.installIconFactory( new KIconFactory( name, group, size, this ));
01131 return ret;
01132 }
01133
01134 QIconSet KIconLoader::loadIconSetNonDelayed( const QString& name,
01135 KIcon::Group group,
01136 int size, bool canReturnNull )
01137 {
01138 QIconSet iconset;
01139 QPixmap tmp = loadIcon(name, group, size, KIcon::ActiveState, NULL, canReturnNull);
01140 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Active );
01141
01142 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Active );
01143 tmp = loadIcon(name, group, size, KIcon::DisabledState, NULL, canReturnNull);
01144 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Disabled );
01145 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Disabled );
01146 tmp = loadIcon(name, group, size, KIcon::DefaultState, NULL, canReturnNull);
01147 iconset.setPixmap( tmp, QIconSet::Small, QIconSet::Normal );
01148 iconset.setPixmap( tmp, QIconSet::Large, QIconSet::Normal );
01149 return iconset;
01150 }
01151
01152 KIconFactory::KIconFactory( const QString& iconName_P, KIcon::Group group_P,
01153 int size_P, KIconLoader* loader_P )
01154 : iconName( iconName_P ), group( group_P ), size( size_P ), loader( loader_P )
01155 {
01156 setAutoDelete( true );
01157 }
01158
01159 QPixmap* KIconFactory::createPixmap( const QIconSet&, QIconSet::Size, QIconSet::Mode mode_P, QIconSet::State )
01160 {
01161
01162 static const KIcon::States tbl[] = { KIcon::DefaultState, KIcon::DisabledState, KIcon::ActiveState };
01163 int state = KIcon::DefaultState;
01164 if( mode_P <= QIconSet::Active )
01165 state = tbl[ mode_P ];
01166 if( group >= 0 && state == KIcon::ActiveState )
01167 {
01168 if( loader->iconEffect()->fingerprint(group, KIcon::ActiveState )
01169 == loader->iconEffect()->fingerprint(group, KIcon::DefaultState ))
01170 return NULL;
01171 }
01172
01173
01174 QPixmap pm = loader->loadIcon( iconName, group, size, state );
01175 return new QPixmap( pm );
01176 }
01177
01178
01179
01180 QPixmap DesktopIcon(const QString& name, int force_size, int state,
01181 KInstance *instance)
01182 {
01183 KIconLoader *loader = instance->iconLoader();
01184 return loader->loadIcon(name, KIcon::Desktop, force_size, state);
01185 }
01186
01187 QPixmap DesktopIcon(const QString& name, KInstance *instance)
01188 {
01189 return DesktopIcon(name, 0, KIcon::DefaultState, instance);
01190 }
01191
01192 QIconSet DesktopIconSet(const QString& name, int force_size, KInstance *instance)
01193 {
01194 KIconLoader *loader = instance->iconLoader();
01195 return loader->loadIconSet( name, KIcon::Desktop, force_size );
01196 }
01197
01198 QPixmap BarIcon(const QString& name, int force_size, int state,
01199 KInstance *instance)
01200 {
01201 KIconLoader *loader = instance->iconLoader();
01202 return loader->loadIcon(name, KIcon::Toolbar, force_size, state);
01203 }
01204
01205 QPixmap BarIcon(const QString& name, KInstance *instance)
01206 {
01207 return BarIcon(name, 0, KIcon::DefaultState, instance);
01208 }
01209
01210 QIconSet BarIconSet(const QString& name, int force_size, KInstance *instance)
01211 {
01212 KIconLoader *loader = instance->iconLoader();
01213 return loader->loadIconSet( name, KIcon::Toolbar, force_size );
01214 }
01215
01216 QPixmap SmallIcon(const QString& name, int force_size, int state,
01217 KInstance *instance)
01218 {
01219 KIconLoader *loader = instance->iconLoader();
01220 return loader->loadIcon(name, KIcon::Small, force_size, state);
01221 }
01222
01223 QPixmap SmallIcon(const QString& name, KInstance *instance)
01224 {
01225 return SmallIcon(name, 0, KIcon::DefaultState, instance);
01226 }
01227
01228 QIconSet SmallIconSet(const QString& name, int force_size, KInstance *instance)
01229 {
01230 KIconLoader *loader = instance->iconLoader();
01231 return loader->loadIconSet( name, KIcon::Small, force_size );
01232 }
01233
01234 QPixmap MainBarIcon(const QString& name, int force_size, int state,
01235 KInstance *instance)
01236 {
01237 KIconLoader *loader = instance->iconLoader();
01238 return loader->loadIcon(name, KIcon::MainToolbar, force_size, state);
01239 }
01240
01241 QPixmap MainBarIcon(const QString& name, KInstance *instance)
01242 {
01243 return MainBarIcon(name, 0, KIcon::DefaultState, instance);
01244 }
01245
01246 QIconSet MainBarIconSet(const QString& name, int force_size, KInstance *instance)
01247 {
01248 KIconLoader *loader = instance->iconLoader();
01249 return loader->loadIconSet( name, KIcon::MainToolbar, force_size );
01250 }
01251
01252 QPixmap UserIcon(const QString& name, int state, KInstance *instance)
01253 {
01254 KIconLoader *loader = instance->iconLoader();
01255 return loader->loadIcon(name, KIcon::User, 0, state);
01256 }
01257
01258 QPixmap UserIcon(const QString& name, KInstance *instance)
01259 {
01260 return UserIcon(name, KIcon::DefaultState, instance);
01261 }
01262
01263 QIconSet UserIconSet(const QString& name, KInstance *instance)
01264 {
01265 KIconLoader *loader = instance->iconLoader();
01266 return loader->loadIconSet( name, KIcon::User );
01267 }
01268
01269 int IconSize(KIcon::Group group, KInstance *instance)
01270 {
01271 KIconLoader *loader = instance->iconLoader();
01272 return loader->currentSize(group);
01273 }
01274
01275 QPixmap KIconLoader::unknown()
01276 {
01277 QPixmap pix;
01278 if ( QPixmapCache::find("unknown", pix) )
01279 return pix;
01280
01281 QString path = KGlobal::iconLoader()->iconPath("unknown", KIcon::Small, true);
01282 if (path.isEmpty())
01283 {
01284 kdDebug(264) << "Warning: Cannot find \"unknown\" icon.\n";
01285 pix.resize(32,32);
01286 } else
01287 {
01288 pix.load(path);
01289 QPixmapCache::insert("unknown", pix);
01290 }
01291
01292 return pix;
01293 }