KDEUI
kiconcache.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kiconcache.h"
00022
00023 #include <QtCore/QString>
00024 #include <QtGui/QPixmap>
00025 #include <QtCore/QFile>
00026 #include <QtCore/QDataStream>
00027 #include <QtCore/QFileInfo>
00028 #include <QtCore/QDateTime>
00029
00030 #include <kglobal.h>
00031 #include <kstandarddirs.h>
00032 #include <kdebug.h>
00033
00034 #include <sys/file.h>
00035 #include <time.h>
00036
00037
00038 #define KDE_ICONCACHE_NAME "kde-icon-cache"
00039 #define KDE_ICONCACHE_VERSION 0x000100
00040
00041
00042 class KIconCache::Private
00043 {
00044 public:
00045 Private(KIconCache* _q)
00046 {
00047 q = _q;
00048 mUpdatesCheckedTime = 0;
00049 }
00050 bool themeDirsChanged()
00051 {
00052 if (q->existingIconThemeDirs(mThemeNames) != mThemeDirs ||
00053 q->mostRecentMTime(mThemeDirs) != mThemesMTime) {
00054 kDebug(264) << "Theme directory has been modified";
00055 return true;
00056 } else {
00057 return false;
00058 }
00059 }
00060 void checkForThemeUpdates()
00061 {
00062 if (!q->isEnabled()) {
00063 return;
00064 }
00065
00066 const quint32 now = ::time(0);
00067 if (now < mUpdatesCheckedTime + 5) {
00068 return;
00069 }
00070
00071 mUpdatesCheckedTime = now;
00072
00073 const QFileInfo fi(mUpdatesFile);
00074 if (fi.exists() && fi.lastModified().toTime_t() + 5 > now) {
00075 return;
00076 }
00077
00078 if (themeDirsChanged()) {
00079
00080 mThemeDirs = q->existingIconThemeDirs(mThemeNames);
00081 mThemesMTime = q->mostRecentMTime(mThemeDirs);
00082 q->discard();
00083 }
00084
00085 QFile f(mUpdatesFile);
00086 f.open(QIODevice::WriteOnly);
00087 }
00088
00089 KIconCache* q;
00090
00091 qint32 mDefaultIconSize[6];
00092 QStringList mThemeNames;
00093 QSet<QString> mThemeDirs;
00094 quint32 mThemesMTime;
00095 QString mUpdatesFile;
00096 quint32 mUpdatesCheckedTime;
00097
00098 QString* mLoadPath;
00099 QString mSavePath;
00100 };
00101
00102
00103 KIconCache::KIconCache()
00104 : KPixmapCache(KDE_ICONCACHE_NAME), d(new Private(this))
00105 {
00106 d->mUpdatesFile = KGlobal::dirs()->locateLocal("cache", "kpc/"KDE_ICONCACHE_NAME".updated");
00107
00108 setCacheLimit(10 * 1024);
00109 }
00110
00111 KIconCache::~KIconCache()
00112 {
00113 delete d;
00114 }
00115
00116 void KIconCache::deleteCache()
00117 {
00118 KPixmapCache::deleteCache(KDE_ICONCACHE_NAME);
00119 }
00120
00121 bool KIconCache::loadCustomIndexHeader(QDataStream& stream)
00122 {
00123 if (stream.atEnd()) {
00124 return false;
00125 }
00126
00127
00128 quint32 version;
00129 stream >> version;
00130 if (version != KDE_ICONCACHE_VERSION) {
00131 kDebug(264) << "Obsolete iconcache version" << version << "will recreate";
00132 return false;
00133 }
00134
00135
00136 for (int i = 0; i < 6; i++) {
00137 stream >> d->mDefaultIconSize[i];
00138 }
00139
00140
00141 stream >> d->mThemeNames;
00142 stream >> d->mThemeDirs;
00143
00144 stream >> d->mThemesMTime;
00145
00146 if (stream.status() != QDataStream::Ok) {
00147 kWarning() << "Failed to read index file's header";
00148 recreateCacheFiles();
00149 return false;
00150 }
00151
00152
00153 if (!d->mThemeNames.count()) {
00154 kDebug(264) << "Empty themes list";
00155 return false;
00156 }
00157
00158
00159 if (d->themeDirsChanged()) {
00160 return false;
00161 }
00162 d->mUpdatesCheckedTime= ::time(0);
00163
00164 return true;
00165 }
00166
00167 void KIconCache::writeCustomIndexHeader(QDataStream& stream)
00168 {
00169 setValid(false);
00170
00171 stream << (quint32)KDE_ICONCACHE_VERSION;
00172
00173 for (int i = 0; i < 6; i++) {
00174 stream << d->mDefaultIconSize[i];
00175 }
00176
00177
00178 stream << d->mThemeNames;
00179 stream << d->mThemeDirs;
00180 stream << d->mThemesMTime;
00181
00182
00183
00184 if (stream.status() == QDataStream::Ok && d->mThemeNames.count()) {
00185 setValid(true);
00186 }
00187 }
00188
00189 QSet<QString> KIconCache::existingIconThemeDirs(const QStringList& themeNames) const
00190 {
00191
00192
00193 const QStringList icondirs = KGlobal::dirs()->resourceDirs("icon")
00194 << KGlobal::dirs()->resourceDirs("xdgdata-icon")
00195 << "/usr/share/pixmaps"
00196
00197 << KGlobal::dirs()->resourceDirs("xdgdata-pixmap");
00198
00199
00200
00201 QSet<QString> dirs;
00202 for (QStringList::ConstIterator it = icondirs.begin(); it != icondirs.end(); ++it) {
00203 QStringList::ConstIterator themeIt;
00204 for (themeIt = themeNames.begin(); themeIt != themeNames.end(); ++themeIt) {
00205 QString dirName = *it + *themeIt + '/';
00206 if (KStandardDirs::exists(dirName)) {
00207 dirs.insert(dirName);
00208 }
00209 }
00210 }
00211
00212 return dirs;
00213 }
00214
00215 unsigned int KIconCache::mostRecentMTime(const QSet<QString>& dirNames) const
00216 {
00217 unsigned int timestamp = 0;
00218 foreach (const QString &dir, dirNames) {
00219 unsigned int mtime = QFileInfo(dir).lastModified().toTime_t();
00220 if (timestamp < mtime) {
00221 timestamp = mtime;
00222 }
00223 }
00224
00225 return timestamp;
00226 }
00227
00228 int KIconCache::defaultIconSize(KIconLoader::Group group) const
00229 {
00230 if ((group < 0) || (group >= KIconLoader::LastGroup))
00231 {
00232 kDebug(264) << "Illegal icon group:" << group;
00233 return -1;
00234 }
00235 return d->mDefaultIconSize[group];
00236 }
00237
00238 void KIconCache::setThemeInfo(const QList<KIconTheme*>& themes)
00239 {
00240 if (themes.isEmpty()) {
00241 for (KIconLoader::Group i = KIconLoader::FirstGroup; i < KIconLoader::LastGroup; i++) {
00242 d->mDefaultIconSize[i] = 0;
00243 }
00244 return;
00245 }
00246
00247 for (KIconLoader::Group i = KIconLoader::FirstGroup; i < KIconLoader::LastGroup; i++) {
00248 d->mDefaultIconSize[i] = themes.first()->defaultSize(i);
00249 }
00250
00251 if (!isEnabled()) {
00252 return;
00253 }
00254 setValid(false);
00255
00256
00257 d->mThemeNames.clear();
00258 foreach (KIconTheme* theme, themes) {
00259 d->mThemeNames.append(theme->internalName());
00260 }
00261 d->mThemeDirs = existingIconThemeDirs(d->mThemeNames);
00262 d->mThemesMTime = mostRecentMTime(d->mThemeDirs);
00263 d->mUpdatesCheckedTime= ::time(0);
00264
00265
00266 recreateCacheFiles();
00267 }
00268
00269 bool KIconCache::find(const QString& key, QPixmap& pix, QString* path)
00270 {
00271 d->checkForThemeUpdates();
00272
00273 d->mLoadPath = path;
00274
00275 setUseQPixmapCache(!path);
00276
00277 bool ret = find(key, pix);
00278 d->mLoadPath = 0;
00279 return ret;
00280 }
00281
00282 void KIconCache::insert(const QString& key, const QPixmap& pix, const QString& path)
00283 {
00284 d->mSavePath = path;
00285 insert(key, pix);
00286 d->mSavePath.clear();
00287 }
00288
00289 bool KIconCache::find(const QString& key, QPixmap& pix)
00290 {
00291
00292 return KPixmapCache::find(key, pix);
00293 }
00294
00295 void KIconCache::insert(const QString& key, const QPixmap& pix)
00296 {
00297
00298 KPixmapCache::insert(key, pix);
00299 }
00300
00301 bool KIconCache::loadCustomData(QDataStream& stream)
00302 {
00303 QString path;
00304 stream >> path;
00305 if (d->mLoadPath) {
00306 *d->mLoadPath = path;
00307 }
00308
00309 return true;
00310 }
00311
00312 bool KIconCache::writeCustomData(QDataStream& stream)
00313 {
00314 stream << d->mSavePath;
00315 return true;
00316 }
00317