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