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