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