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 {
00164 kdWarning(264) << "Icon directory " << *itDir << " group " << *it << " not valid.\n";
00165 delete dir;
00166 }
00167 else
00168 mDirs.append(dir);
00169 }
00170 }
00171 }
00172
00173
00174 int i;
00175 QMap<int,QValueList<int> > scIcons;
00176 for (KIconThemeDir *dir=mDirs.first(); dir!=0L; dir=mDirs.next())
00177 {
00178 if ((dir->type() == KIcon::Scalable) && !scIcons.contains(dir->size()))
00179 {
00180 QValueList<int> lst;
00181 for (i=dir->minSize(); i<=dir->maxSize(); i++)
00182 lst += i;
00183 scIcons[dir->size()] = lst;
00184 }
00185 }
00186
00187 QStringList groups;
00188 groups += "Desktop";
00189 groups += "Toolbar";
00190 groups += "MainToolbar";
00191 groups += "Small";
00192 groups += "Panel";
00193 const int defDefSizes[] = { 32, 22, 22, 16, 32 };
00194 cfg.setGroup(mainSection);
00195 for (it=groups.begin(), i=0; it!=groups.end(); ++it, i++)
00196 {
00197 mDefSize[i] = cfg.readNumEntry(*it + "Default", defDefSizes[i]);
00198 QValueList<int> exp, lst = cfg.readIntListEntry(*it + "Sizes");
00199 QValueList<int>::ConstIterator it2;
00200 for (it2=lst.begin(); it2!=lst.end(); ++it2)
00201 {
00202 if (scIcons.contains(*it2))
00203 exp += scIcons[*it2];
00204 else
00205 exp += *it2;
00206 }
00207 mSizes[i] = exp;
00208 }
00209
00210 }
00211
00212 KIconTheme::~KIconTheme()
00213 {
00214 delete d;
00215 }
00216
00217 bool KIconTheme::isValid() const
00218 {
00219 return !mDirs.isEmpty();
00220 }
00221
00222 bool KIconTheme::isHidden() const
00223 {
00224 return d->hidden;
00225 }
00226
00227 QString KIconTheme::example() const { return d->example; }
00228 QString KIconTheme::screenshot() const { return d->screenshot; }
00229 QString KIconTheme::linkOverlay() const { return d->linkOverlay; }
00230 QString KIconTheme::lockOverlay() const { return d->lockOverlay; }
00231 QString KIconTheme::zipOverlay() const { return d->zipOverlay; }
00232 QString KIconTheme::shareOverlay() const { return d->shareOverlay; }
00233
00234 int KIconTheme::defaultSize(KIcon::Group group) const
00235 {
00236 if ((group < 0) || (group >= KIcon::LastGroup))
00237 {
00238 kdDebug(264) << "Illegal icon group: " << group << "\n";
00239 return -1;
00240 }
00241 return mDefSize[group];
00242 }
00243
00244 QValueList<int> KIconTheme::querySizes(KIcon::Group group) const
00245 {
00246 QValueList<int> empty;
00247 if ((group < 0) || (group >= KIcon::LastGroup))
00248 {
00249 kdDebug(264) << "Illegal icon group: " << group << "\n";
00250 return empty;
00251 }
00252 return mSizes[group];
00253 }
00254
00255 QStringList KIconTheme::queryIcons(int size, KIcon::Context context) const
00256 {
00257 int delta = 1000, dw;
00258
00259 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00260 KIconThemeDir *dir;
00261
00262
00263 QStringList result;
00264 for ( ; dirs.current(); ++dirs)
00265 {
00266 dir = dirs.current();
00267 if ((context != KIcon::Any) && (context != dir->context()))
00268 continue;
00269 if ((dir->type() == KIcon::Fixed) && (dir->size() == size))
00270 {
00271 result += dir->iconList();
00272 continue;
00273 }
00274 if ((dir->type() == KIcon::Scalable) &&
00275 (size >= dir->minSize()) && (size <= dir->maxSize()))
00276 {
00277 result += dir->iconList();
00278 continue;
00279 }
00280 if ((dir->type() == KIcon::Threshold) &&
00281 (abs(size-dir->size())<dir->threshold()))
00282 result+=dir->iconList();
00283 }
00284
00285 return result;
00286
00287 dirs.toFirst();
00288
00289
00290 KIconThemeDir *best = 0L;
00291 for ( ; dirs.current(); ++dirs)
00292 {
00293 dir = dirs.current();
00294 if ((context != KIcon::Any) && (context != dir->context()))
00295 continue;
00296 dw = dir->size() - size;
00297 if ((dw > 6) || (abs(dw) >= abs(delta)))
00298 continue;
00299 delta = dw;
00300 best = dir;
00301 }
00302 if (best == 0L)
00303 return QStringList();
00304
00305 return best->iconList();
00306 }
00307
00308 QStringList KIconTheme::queryIconsByContext(int size, KIcon::Context context) const
00309 {
00310 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00311 int dw;
00312 KIconThemeDir *dir;
00313
00314
00315
00316
00317 QStringList iconlist[128];
00318
00319
00320
00321
00322 for ( ; dirs.current(); ++dirs)
00323 {
00324 dir = dirs.current();
00325 if ((context != KIcon::Any) && (context != dir->context()))
00326 continue;
00327 dw = abs(dir->size() - size);
00328 iconlist[(dw<127)?dw:127]+=dir->iconList();
00329 }
00330
00331 QStringList iconlistResult;
00332 for (int i=0; i<128; i++) iconlistResult+=iconlist[i];
00333
00334 return iconlistResult;
00335 }
00336
00337 KIcon KIconTheme::iconPath(const QString& name, int size, KIcon::MatchType match) const
00338 {
00339 KIcon icon;
00340 QString path;
00341 int delta = 1000, dw;
00342 KIconThemeDir *dir;
00343
00344 dw = 1000;
00345 QPtrListIterator<KIconThemeDir> dirs(mDirs);
00346 for ( ; dirs.current(); ++dirs)
00347 {
00348 dir = dirs.current();
00349
00350 if (match == KIcon::MatchExact)
00351 {
00352 if ((dir->type() == KIcon::Fixed) && (dir->size() != size))
00353 continue;
00354 if ((dir->type() == KIcon::Scalable) &&
00355 ((size < dir->minSize()) || (size > dir->maxSize())))
00356 continue;
00357 if ((dir->type() == KIcon::Threshold) &&
00358 (abs(dir->size()-size) > dir->threshold()))
00359 continue;
00360 } else
00361 {
00362
00363 if (dir->type() == KIcon::Fixed)
00364 {
00365 dw = dir->size() - size;
00366 } else if (dir->type() == KIcon::Scalable)
00367 {
00368 if (size < dir->minSize())
00369 dw = dir->minSize() - size;
00370 else if (size > dir->maxSize())
00371 dw = dir->maxSize() - size;
00372 else
00373 dw = 0;
00374 } else if (dir->type() == KIcon::Threshold)
00375 {
00376 if (size < dir->size() - dir->threshold())
00377 dw = dir->size() - dir->threshold() - size;
00378 else if (size > dir->size() + dir->threshold())
00379 dw = dir->size() + dir->threshold() - size;
00380 else
00381 dw = 0;
00382 }
00383
00384
00385
00386
00387 if ((abs(dw) >= abs(delta)) &&
00388 !(delta > 0 && dw < 0))
00389 continue;
00390 }
00391
00392 path = dir->iconPath(name);
00393 if (path.isEmpty())
00394 continue;
00395 icon.path = path;
00396 icon.size = dir->size();
00397 icon.type = dir->type();
00398 icon.threshold = dir->threshold();
00399 icon.context = dir->context();
00400
00401
00402 if (match == KIcon::MatchExact)
00403 return icon;
00404 else
00405 {
00406 delta = dw;
00407 if (delta==0) return icon;
00408 }
00409 }
00410 return icon;
00411 }
00412
00413
00414 QString *KIconTheme::_theme = 0L;
00415
00416
00417 QStringList *KIconTheme::_theme_list = 0L;
00418
00419
00420 QString KIconTheme::current()
00421 {
00422
00423 if (_theme != 0L)
00424 return *_theme;
00425
00426 _theme = new QString();
00427 KConfig *config = KGlobal::config();
00428 KConfigGroupSaver saver(config, "Icons");
00429 *_theme = config->readEntry("Theme",defaultThemeName());
00430 if ( *_theme == QString::fromLatin1("hicolor") ) *_theme = defaultThemeName();
00431
00432
00433
00434
00435
00436
00437
00438 return *_theme;
00439 }
00440
00441
00442 QStringList KIconTheme::list()
00443 {
00444
00445 if (_theme_list != 0L)
00446 return *_theme_list;
00447
00448 _theme_list = new QStringList();
00449 QStringList icnlibs = KGlobal::dirs()->resourceDirs("icon");
00450 QStringList::ConstIterator it;
00451 for (it=icnlibs.begin(); it!=icnlibs.end(); ++it)
00452 {
00453 QDir dir(*it);
00454 if (!dir.exists())
00455 continue;
00456 QStringList lst = dir.entryList(QDir::Dirs);
00457 QStringList::ConstIterator it2;
00458 for (it2=lst.begin(); it2!=lst.end(); ++it2)
00459 {
00460 if ((*it2 == ".") || (*it2 == "..") || (*it2).startsWith("default.") )
00461 continue;
00462 if (!KStandardDirs::exists(*it + *it2 + "/index.desktop") && !KStandardDirs::exists(*it + *it2 + "/index.theme"))
00463 continue;
00464 KIconTheme oink(*it2);
00465 if (!oink.isValid()) continue;
00466
00467 if (!_theme_list->contains(*it2))
00468 _theme_list->append(*it2);
00469 }
00470 }
00471 return *_theme_list;
00472 }
00473
00474
00475 void KIconTheme::reconfigure()
00476 {
00477 delete _theme;
00478 _theme=0L;
00479 delete _theme_list;
00480 _theme_list=0L;
00481 }
00482
00483
00484 QString KIconTheme::defaultThemeName()
00485 {
00486 return QString::fromLatin1("crystalsvg");
00487 }
00488
00489
00490
00491 KIconThemeDir::KIconThemeDir(const QString& dir, const KConfigBase *config)
00492 {
00493 mbValid = false;
00494 mDir = dir;
00495 mSize = config->readNumEntry("Size");
00496 mMinSize = 1;
00497 mMaxSize = 50;
00498 mType = KIcon::Fixed;
00499
00500 if (mSize == 0)
00501 return;
00502
00503 QString tmp = config->readEntry("Context");
00504 if (tmp == "Devices")
00505 mContext = KIcon::Device;
00506 else if (tmp == "MimeTypes")
00507 mContext = KIcon::MimeType;
00508 else if (tmp == "FileSystems")
00509 mContext = KIcon::FileSystem;
00510 else if (tmp == "Applications")
00511 mContext = KIcon::Application;
00512 else if (tmp == "Actions")
00513 mContext = KIcon::Action;
00514 else {
00515 kdDebug(264) << "Invalid Context= line for icon theme: " << mDir << "\n";
00516 return;
00517 }
00518 tmp = config->readEntry("Type");
00519 if (tmp == "Fixed")
00520 mType = KIcon::Fixed;
00521 else if (tmp == "Scalable")
00522 mType = KIcon::Scalable;
00523 else if (tmp == "Threshold")
00524 mType = KIcon::Threshold;
00525 else {
00526 kdDebug(264) << "Invalid Type= line for icon theme: " << mDir << "\n";
00527 return;
00528 }
00529 if (mType == KIcon::Scalable)
00530 {
00531 mMinSize = config->readNumEntry("MinSize", mSize);
00532 mMaxSize = config->readNumEntry("MaxSize", mSize);
00533 } else if (mType == KIcon::Threshold)
00534 mThreshold = config->readNumEntry("Threshold", 2);
00535 mbValid = true;
00536 }
00537
00538 QString KIconThemeDir::iconPath(const QString& name) const
00539 {
00540 if (!mbValid)
00541 return QString::null;
00542 QString file = mDir + "/" + name;
00543
00544 if (access(QFile::encodeName(file), R_OK) == 0)
00545 return file;
00546
00547 return QString::null;
00548 }
00549
00550 QStringList KIconThemeDir::iconList() const
00551 {
00552 QDir dir(mDir);
00553 #ifdef HAVE_LIBART
00554 QStringList lst = dir.entryList("*.png;*.svg;*.svgz;*.xpm", QDir::Files);
00555 #else
00556 QStringList lst = dir.entryList("*.png;*.xpm", QDir::Files);
00557 #endif
00558 QStringList result;
00559 QStringList::ConstIterator it;
00560 for (it=lst.begin(); it!=lst.end(); ++it)
00561 result += mDir + "/" + *it;
00562 return result;
00563 }
This file is part of the documentation for kdecore Library Version 3.2.3.