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