kicontheme.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <sys/stat.h>
00017 #include <unistd.h>
00018 #include <stdlib.h>
00019 #include <config.h>
00020
00021 #include <qstring.h>
00022 #include <qstringlist.h>
00023 #include <qvaluelist.h>
00024 #include <qmap.h>
00025 #include <qpixmap.h>
00026 #include <qpixmapcache.h>
00027 #include <qimage.h>
00028 #include <qfileinfo.h>
00029 #include <qdir.h>
00030
00031 #include <kdebug.h>
00032 #include <kstandarddirs.h>
00033 #include <kglobal.h>
00034 #include <kconfig.h>
00035 #include <ksimpleconfig.h>
00036 #include <kinstance.h>
00037
00038 #include "kicontheme.h"
00039
00040 class KIconThemePrivate
00041 {
00042 public:
00043 QString example, screenshot;
00044 QString linkOverlay, lockOverlay, zipOverlay, shareOverlay;
00045 bool hidden;
00046 };
00047
00051 class KIconThemeDir
00052 {
00053 public:
00054 KIconThemeDir(const QString& dir, const KConfigBase *config);
00055
00056 bool isValid() const { return mbValid; }
00057 QString iconPath(const QString& name) const;
00058 QStringList iconList() const;
00059 QString dir() const { return mDir; }
00060
00061 KIcon::Context context() const { return mContext; }
00062 KIcon::Type type() const { return mType; }
00063 int size() const { return mSize; }
00064 int minSize() const { return mMinSize; }
00065 int maxSize() const { return mMaxSize; }
00066 int threshold() const { return mThreshold; }
00067
00068 private:
00069 bool mbValid;
00070 KIcon::Type mType;
00071 KIcon::Context mContext;
00072 int mSize, mMinSize, mMaxSize;
00073 int mThreshold;
00074
00075 QString mDir;
00076 };
00077
00078
00079
00080
00081 KIconTheme::KIconTheme(const QString& name, const QString& appName)
00082 {
00083 d = new KIconThemePrivate;
00084
00085 QStringList icnlibs;
00086 QStringList::ConstIterator it, itDir;
00087 QStringList themeDirs;
00088 QString cDir;
00089
00090
00091
00092
00093
00094 if (!appName.isEmpty() &&
00095 ( name == "crystalsvg" || name== "hicolor" || name == "locolor" ) )
00096 {
00097 icnlibs = KGlobal::dirs()->resourceDirs("data");
00098 for (it=icnlibs.begin(); it!=icnlibs.end(); it++)
00099 {
00100 cDir = *it + appName + "/icons/" + name;
00101 if (QFile::exists( cDir ))
00102 themeDirs += cDir + "/";
00103 }
00104 }
00105
00106
00107 icnlibs = KGlobal::dirs()->resourceDirs("icon");
00108 for (it=icnlibs.begin(); it!=icnlibs.end(); it++)
00109 {
00110 cDir = *it + name + "/";
00111 if (KStandardDirs::exists(cDir))
00112 {
00113 themeDirs += cDir;
00114 if (mDir.isEmpty()
00115 && (KStandardDirs::exists( cDir + "index.desktop") || KStandardDirs::exists( cDir + "index.theme")))
00116 mDir = cDir;
00117 }
00118 }
00119
00120 if (mDir.isEmpty())
00121 {
00122 kdDebug(264) << "Icon theme " << name << " not found.\n";
00123 return;
00124 }
00125
00126 QString fileName, mainSection;
00127 if(QFile::exists(mDir + "index.desktop")) {
00128 fileName = mDir + "index.desktop";
00129 mainSection="KDE Icon Theme";
00130 } else {
00131 fileName = mDir + "index.theme";
00132 mainSection="Icon Theme";
00133 }
00134 KSimpleConfig cfg(fileName);
00135 cfg.setGroup(mainSection);
00136 mName = cfg.readEntry("Name");
00137 mDesc = cfg.readEntry("Comment");
00138 mDepth = cfg.readNumEntry("DisplayDepth", 32);
00139 mInherits = cfg.readListEntry("Inherits");
00140 if ( name != "crystalsvg" )
00141 for ( QStringList::Iterator it = mInherits.begin(); it != mInherits.end(); ++it )
00142 if ( *it == "default" || *it == "hicolor" ) *it="crystalsvg";
00143
00144 d->hidden = cfg.readBoolEntry("Hidden", false);
00145 d->example = cfg.readPathEntry("Example");
00146 d->screenshot = cfg.readPathEntry("ScreenShot");
00147 d->linkOverlay = cfg.readEntry("LinkOverlay", "link");
00148 d->lockOverlay = cfg.readEntry("LockOverlay", "lock");
00149 d->zipOverlay = cfg.readEntry("ZipOverlay", "zip");
00150 d->shareOverlay = cfg.readEntry("ShareOverlay","share");
00151
00152 QStringList dirs = cfg.readPathListEntry("Directories");
00153 mDirs.setAutoDelete(true);
00154 for (it=dirs.begin(); it!=dirs.end(); it++)
00155 {
00156 cfg.setGroup(*it);
00157 for (itDir=themeDirs.begin(); itDir!=themeDirs.end(); itDir++)
00158 {
00159 if (KStandardDirs::exists(*itDir + *it + "/"))
00160 {
00161 KIconThemeDir *dir = new KIconThemeDir(*itDir + *it, &cfg);
00162 if (!dir->isValid())
00163 delete dir;
00164 else
00165 mDirs.append(dir);
00166 }
00167 }
00168 }
00169
00170
00171 int i;
00172 QMap<int,QValueList<int> > scIcons;
00173 for (KIconThemeDir *dir=mDirs.first(); dir!=0L; dir=mDirs.next())
00174 {
00175 if ((dir->type() == KIcon::Scalable) && !scIcons.contains(dir->size()))
00176 {
00177 QValueList<int> lst;
00178 for (i=dir->minSize(); i<=dir->maxSize(); i++)
00179 lst += i;
00180 scIcons[dir->size()] = lst;
00181 }
00182 }
00183
00184 QStringList groups;
00185 groups += "Desktop";
00186 groups += "Toolbar";
00187 groups += "MainToolbar";
00188 groups += "Small";
00189 groups += "Panel";
00190 const int defDefSizes[] = { 32, 22, 22, 16, 32 };
00191 cfg.setGroup(mainSection);
00192 for (it=groups.begin(), i=0; it!=groups.end(); it++, i++)
00193 {
00194 mDefSize[i] = cfg.readNumEntry(*it + "Default", defDefSizes[i]);
00195 QValueList<int> lst = cfg.readIntListEntry(*it + "Sizes"), exp;
00196 QValueList<int>::ConstIterator it2;
00197 for (it2=lst.begin(); it2!=lst.end(); it2++)
00198 {
00199 if (scIcons.contains(*it2))
00200 exp += scIcons[*it2];
00201 else
00202 exp += *it2;
00203 }
00204 mSizes[i] = exp;
00205 }
00206
00207 }
00208
00209 KIconTheme::~KIconTheme()
00210 {
00211 delete d;
00212 }
00213
00214 bool KIconTheme::isValid() const
00215 {
00216 return !mDirs.isEmpty();
00217 }
00218
00219 bool KIconTheme::isHidden() const
00220 {
00221 return d->hidden;
00222 }
00223
00224 QString KIconTheme::example() const { return d->example; }
00225 QString KIconTheme::screenshot() const { return d->screenshot; }
00226 QString KIconTheme::linkOverlay() const { return d->linkOverlay; }
00227 QString KIconTheme::lockOverlay() const { return d->lockOverlay; }
00228 QString KIconTheme::zipOverlay() const { return d->zipOverlay; }
00229 QString KIconTheme::shareOverlay() const { return d->shareOverlay; }
00230
00231 int KIconTheme::defaultSize(KIcon::Group group) const
00232 {
00233 if ((group < 0) || (group >= KIcon::LastGroup))
00234 {
00235 kdDebug(264) << "Illegal icon group: " << group << "\n";
00236 return -1;
00237 }
00238 return mDefSize[group];
00239 }
00240
00241 QValueList<int> KIconTheme::querySizes(KIcon::Group group) const
00242 {
00243 QValueList<int> empty;
00244 if ((group < 0) || (group >= KIcon::LastGroup))
00245 {
00246 kdDebug(264) << "Illegal icon group: " << group << "\n";
00247 return empty;
00248 }
00249 return mSizes[group];
00250 }
00251
00252 QStringList KIconTheme::queryIcons(int size, KIcon::Context context) const
00253 {
00254 int delta = 1000, dw;
00255
00256 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00257 KIconThemeDir *dir;
00258
00259
00260 QStringList result;
00261 for ( ; dirs.current(); ++dirs)
00262 {
00263 dir = dirs.current();
00264 if ((context != KIcon::Any) && (context != dir->context()))
00265 continue;
00266 if ((dir->type() == KIcon::Fixed) && (dir->size() == size))
00267 {
00268 result += dir->iconList();
00269 continue;
00270 }
00271 if ((dir->type() == KIcon::Scalable) &&
00272 (size >= dir->minSize()) && (size <= dir->maxSize()))
00273 {
00274 result += dir->iconList();
00275 continue;
00276 }
00277 if ((dir->type() == KIcon::Threshold) &&
00278 (abs(size-dir->size())<dir->threshold()))
00279 result+=dir->iconList();
00280 }
00281
00282 return result;
00283
00284 dirs.toFirst();
00285
00286
00287 KIconThemeDir *best = 0L;
00288 for ( ; dirs.current(); ++dirs)
00289 {
00290 dir = dirs.current();
00291 if ((context != KIcon::Any) && (context != dir->context()))
00292 continue;
00293 dw = dir->size() - size;
00294 if ((dw > 6) || (abs(dw) >= abs(delta)))
00295 continue;
00296 delta = dw;
00297 best = dir;
00298 }
00299 if (best == 0L)
00300 return QStringList();
00301
00302 return best->iconList();
00303 }
00304
00305 QStringList KIconTheme::queryIconsByContext(int size, KIcon::Context context) const
00306 {
00307 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00308 int dw;
00309 KIconThemeDir *dir;
00310
00311
00312
00313 QStringList iconlist[34];
00314
00315
00316
00317
00318 for ( ; dirs.current(); ++dirs)
00319 {
00320 dir = dirs.current();
00321 if ((context != KIcon::Any) && (context != dir->context()))
00322 continue;
00323 dw = abs(dir->size() - size);
00324 iconlist[(dw<33)?dw:33]+=dir->iconList();
00325 }
00326
00327 QStringList iconlistResult;
00328 for (int i=0; i<34; i++) iconlistResult+=iconlist[i];
00329
00330 return iconlistResult;
00331 }
00332
00333 KIcon KIconTheme::iconPath(const QString& name, int size, KIcon::MatchType match) const
00334 {
00335 KIcon icon;
00336 QString path;
00337 int delta = 1000, dw;
00338 KIconThemeDir *dir;
00339
00340 dw = 1000;
00341 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00342 for ( ; dirs.current(); ++dirs)
00343 {
00344 dir = dirs.current();
00345
00346 if (match == KIcon::MatchExact)
00347 {
00348 if ((dir->type() == KIcon::Fixed) && (dir->size() != size))
00349 continue;
00350 if ((dir->type() == KIcon::Scalable) &&
00351 ((size < dir->minSize()) || (size > dir->maxSize())))
00352 continue;
00353 if ((dir->type() == KIcon::Threshold) &&
00354 (abs(dir->size()-size) > dir->threshold()))
00355 continue;
00356 } else
00357 {
00358
00359 if (dir->type() == KIcon::Fixed)
00360 {
00361 dw = dir->size() - size;
00362 } else if (dir->type() == KIcon::Scalable)
00363 {
00364 if (size < dir->minSize())
00365 dw = dir->minSize() - size;
00366 else if (size > dir->maxSize())
00367 dw = dir->maxSize() - size;
00368 else
00369 dw = 0;
00370 } else if (dir->type() == KIcon::Threshold)
00371 {
00372 if (size < dir->size() - dir->threshold())
00373 dw = dir->size() - dir->threshold() - size;
00374 else if (size > dir->size() + dir->threshold())
00375 dw = dir->size() + dir->threshold() - size;
00376 else
00377 dw = 0;
00378 }
00379
00380
00381
00382
00383 if ((abs(dw) >= abs(delta)) &&
00384 !(delta > 0 && dw < 0))
00385 continue;
00386 }
00387
00388 path = dir->iconPath(name);
00389 if (path.isEmpty())
00390 continue;
00391 icon.path = path;
00392 icon.size = dir->size();
00393 icon.type = dir->type();
00394 icon.threshold = dir->threshold();
00395 icon.context = dir->context();
00396
00397
00398 if (match == KIcon::MatchExact)
00399 return icon;
00400 else
00401 {
00402 delta = dw;
00403 if (delta==0) return icon;
00404 }
00405 }
00406 return icon;
00407 }
00408
00409
00410 QString *KIconTheme::_theme = 0L;
00411
00412
00413 QStringList *KIconTheme::_theme_list = 0L;
00414
00415
00416 QString KIconTheme::current()
00417 {
00418
00419 if (_theme != 0L)
00420 return *_theme;
00421
00422 _theme = new QString();
00423 KConfig *config = KGlobal::config();
00424 KConfigGroupSaver saver(config, "Icons");
00425 *_theme = config->readEntry("Theme",defaultThemeName());
00426 if ( *_theme == QString::fromLatin1("hicolor") ) *_theme = defaultThemeName();
00427
00428
00429
00430
00431
00432
00433
00434 return *_theme;
00435 }
00436
00437
00438 QStringList KIconTheme::list()
00439 {
00440
00441 if (_theme_list != 0L)
00442 return *_theme_list;
00443
00444 _theme_list = new QStringList();
00445 QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00446 QStringList::ConstIterator it;
00447 for (it=icnlibs.begin(); it!=icnlibs.end(); it++)
00448 {
00449 QDir dir(*it);
00450 if (!dir.exists())
00451 continue;
00452 QStringList lst = dir.entryList(QDir::Dirs);
00453 QStringList::ConstIterator it2;
00454 for (it2=lst.begin(); it2!=lst.end(); it2++)
00455 {
00456 if ((*it2 == ".") || (*it2 == "..") || (*it2).startsWith("default.") )
00457 continue;
00458 if (!KStandardDirs::exists(*it + *it2 + "/index.desktop") && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00459 continue;
00460 if (!_theme_list->contains(*it2))
00461 _theme_list->append(*it2);
00462 }
00463 }
00464 return *_theme_list;
00465 }
00466
00467
00468 void KIconTheme::reconfigure()
00469 {
00470 delete _theme;
00471 _theme=0L;
00472 delete _theme_list;
00473 _theme_list=0L;
00474 }
00475
00476
00477 QString KIconTheme::defaultThemeName()
00478 {
00479 return QString::fromLatin1("crystalsvg");
00480 }
00481
00482
00483
00484 KIconThemeDir::KIconThemeDir(const QString& dir, const KConfigBase *config)
00485 {
00486 mbValid = false;
00487 mDir = dir;
00488 mSize = config->readNumEntry("Size");
00489 mMinSize = 1;
00490 mMaxSize = 50;
00491 mType = KIcon::Fixed;
00492
00493 if (mSize == 0)
00494 return;
00495
00496 QString tmp = config->readEntry("Context");
00497 if (tmp == "Devices")
00498 mContext = KIcon::Device;
00499 else if (tmp == "MimeTypes")
00500 mContext = KIcon::MimeType;
00501 else if (tmp == "FileSystems")
00502 mContext = KIcon::FileSystem;
00503 else if (tmp == "Applications")
00504 mContext = KIcon::Application;
00505 else if (tmp == "Actions")
00506 mContext = KIcon::Action;
00507 else {
00508 kdDebug(264) << "Invalid Context= line for icon theme: " << mDir << "\n";
00509 return;
00510 }
00511 tmp = config->readEntry("Type");
00512 if (tmp == "Fixed")
00513 mType = KIcon::Fixed;
00514 else if (tmp == "Scalable")
00515 mType = KIcon::Scalable;
00516 else if (tmp == "Threshold")
00517 mType = KIcon::Threshold;
00518 else {
00519 kdDebug(264) << "Invalid Type= line for icon theme: " << mDir << "\n";
00520 return;
00521 }
00522 if (mType == KIcon::Scalable)
00523 {
00524 mMinSize = config->readNumEntry("MinSize", mSize);
00525 mMaxSize = config->readNumEntry("MaxSize", mSize);
00526 } else if (mType == KIcon::Threshold)
00527 mThreshold = config->readNumEntry("Threshold", 2);
00528 mbValid = true;
00529 }
00530
00531 QString KIconThemeDir::iconPath(const QString& name) const
00532 {
00533 if (!mbValid)
00534 return QString::null;
00535 QString file = mDir + "/" + name;
00536
00537 if (access(QFile::encodeName(file), R_OK) == 0)
00538 return file;
00539
00540 return QString::null;
00541 }
00542
00543 QStringList KIconThemeDir::iconList() const
00544 {
00545 QDir dir(mDir);
00546 #ifdef HAVE_LIBART
00547 QStringList lst = dir.entryList("*.png;*.svg;*.svgz;*.xpm", QDir::Files);
00548 #else
00549 QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
00550 #endif
00551 QStringList result;
00552 QStringList::ConstIterator it;
00553 for (it=lst.begin(); it!=lst.end(); it++)
00554 result += mDir + "/" + *it;
00555 return result;
00556 }
This file is part of the documentation for kdelibs Version 3.1.3.