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