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