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 int delta = 1000, dw;
00337 KIconThemeDir *dir;
00338
00339 dw = 1000;
00340 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00341 for ( ; dirs.current(); ++dirs)
00342 {
00343 dir = dirs.current();
00344 if (dir->iconPath(name).isEmpty())
00345 continue;
00346
00347 if (match == KIcon::MatchExact)
00348 {
00349 if ((dir->type() == KIcon::Fixed) && (dir->size() != size))
00350 continue;
00351 if ((dir->type() == KIcon::Scalable) &&
00352 ((size < dir->minSize()) || (size > dir->maxSize())))
00353 continue;
00354 if ((dir->type() == KIcon::Threshold) &&
00355 (abs(dir->size()-size) > dir->threshold()))
00356 continue;
00357 } else
00358 {
00359
00360 int dw_ = dw;
00361
00362 if (dir->type() == KIcon::Fixed)
00363 {
00364 dw_ = dir->size() - size;
00365 } else if (dir->type() == KIcon::Scalable)
00366 {
00367 if (size < dir->minSize())
00368 dw_ = dir->minSize() - size;
00369 else if (size > dir->maxSize())
00370 dw_ = dir->maxSize() - size;
00371 else
00372 dw_ = 0;
00373 } else if (dir->type() == KIcon::Threshold)
00374 {
00375 if (size < dir->size() - dir->threshold())
00376 dw_ = dir->size() - dir->threshold() - size;
00377 else if (size > dir->size() + dir->threshold())
00378 dw_ = dir->size() + dir->threshold() - size;
00379 else
00380 dw_ = 0;
00381 }
00382
00383 if (dw != 1000 && dw_ < dw && dw < 0)
00384 continue;
00385
00386
00387
00388
00389
00390 if (abs(dw_) >= abs(delta) && dw_<0 && delta>0)
00391 continue;
00392 if (abs(dw_) >= abs(dw) && dw>0)
00393 continue;
00394 dw = dw_;
00395 }
00396
00397 icon.path = dir->iconPath(name);
00398 icon.size = dir->size();
00399 icon.type = dir->type();
00400 icon.threshold = dir->threshold();
00401 icon.context = dir->context();
00402
00403
00404 if (match == KIcon::MatchExact)
00405 return icon;
00406 else
00407 {
00408 if (dw == 0) return icon;
00409 delta = dw;
00410 }
00411 }
00412 return icon;
00413 }
00414
00415
00416 QString *KIconTheme::_theme = 0L;
00417
00418
00419 QStringList *KIconTheme::_theme_list = 0L;
00420
00421
00422 QString KIconTheme::current()
00423 {
00424
00425 if (_theme != 0L)
00426 return *_theme;
00427
00428 _theme = new QString();
00429 KConfig *config = KGlobal::config();
00430 KConfigGroupSaver saver(config, "Icons");
00431 *_theme = config->readEntry("Theme",defaultThemeName());
00432 if ( *_theme == QString::fromLatin1("hicolor") ) *_theme = defaultThemeName();
00433
00434
00435
00436
00437
00438
00439
00440 return *_theme;
00441 }
00442
00443
00444 QStringList KIconTheme::list()
00445 {
00446
00447 if (_theme_list != 0L)
00448 return *_theme_list;
00449
00450 _theme_list = new QStringList();
00451 QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00452 QStringList::ConstIterator it;
00453 for (it=icnlibs.begin(); it!=icnlibs.end(); it++)
00454 {
00455 QDir dir(*it);
00456 if (!dir.exists())
00457 continue;
00458 QStringList lst = dir.entryList(QDir::Dirs);
00459 QStringList::ConstIterator it2;
00460 for (it2=lst.begin(); it2!=lst.end(); it2++)
00461 {
00462 if ((*it2 == ".") || (*it2 == "..") || (*it2).startsWith("default.") )
00463 continue;
00464 if (!KStandardDirs::exists(*it + *it2 + "/index.desktop") && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00465 continue;
00466 if (!_theme_list->contains(*it2))
00467 _theme_list->append(*it2);
00468 }
00469 }
00470 return *_theme_list;
00471 }
00472
00473
00474 void KIconTheme::reconfigure()
00475 {
00476 delete _theme;
00477 _theme=0L;
00478 delete _theme_list;
00479 _theme_list=0L;
00480 }
00481
00482
00483 QString KIconTheme::defaultThemeName()
00484 {
00485 return QString::fromLatin1("crystalsvg");
00486 }
00487
00488
00489
00490 KIconThemeDir::KIconThemeDir(const QString& dir, const KConfigBase *config)
00491 {
00492 mbValid = false;
00493 mDir = dir;
00494 mSize = config->readNumEntry("Size");
00495 mMinSize = 1;
00496 mMaxSize = 50;
00497 mType = KIcon::Fixed;
00498
00499 if (mSize == 0)
00500 return;
00501
00502 QString tmp = config->readEntry("Context");
00503 if (tmp == "Devices")
00504 mContext = KIcon::Device;
00505 else if (tmp == "MimeTypes")
00506 mContext = KIcon::MimeType;
00507 else if (tmp == "FileSystems")
00508 mContext = KIcon::FileSystem;
00509 else if (tmp == "Applications")
00510 mContext = KIcon::Application;
00511 else if (tmp == "Actions")
00512 mContext = KIcon::Action;
00513 else {
00514 kdDebug(264) << "Invalid Context= line for icon theme: " << mDir << "\n";
00515 return;
00516 }
00517 tmp = config->readEntry("Type");
00518 if (tmp == "Fixed")
00519 mType = KIcon::Fixed;
00520 else if (tmp == "Scalable")
00521 mType = KIcon::Scalable;
00522 else if (tmp == "Threshold")
00523 mType = KIcon::Threshold;
00524 else {
00525 kdDebug(264) << "Invalid Type= line for icon theme: " << mDir << "\n";
00526 return;
00527 }
00528 if (mType == KIcon::Scalable)
00529 {
00530 mMinSize = config->readNumEntry("MinSize", mSize);
00531 mMaxSize = config->readNumEntry("MaxSize", mSize);
00532 } else if (mType == KIcon::Threshold)
00533 mThreshold = config->readNumEntry("Threshold", 2);
00534 mbValid = true;
00535 }
00536
00537 QString KIconThemeDir::iconPath(const QString& name) const
00538 {
00539 if (!mbValid)
00540 return QString::null;
00541 QString file = mDir + "/" + name;
00542
00543 if (access(QFile::encodeName(file), R_OK) == 0)
00544 return file;
00545
00546 return QString::null;
00547 }
00548
00549 QStringList KIconThemeDir::iconList() const
00550 {
00551 QDir dir(mDir);
00552 #ifdef HAVE_LIBART
00553 QStringList lst = dir.entryList("*.png;*.svg;*.svgz;*.xpm", QDir::Files);
00554 #else
00555 QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
00556 #endif
00557 QStringList result;
00558 QStringList::ConstIterator it;
00559 for (it=lst.begin(); it!=lst.end(); it++)
00560 result += mDir + "/" + *it;
00561 return result;
00562 }
This file is part of the documentation for kdelibs Version 3.1.4.