File indexing completed on 2024-04-21 14:55:57
0001 /* 0002 * 0003 * This file is part of the KDE project. 0004 * Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License version 2 as published by the Free Software Foundation. 0009 * 0010 * This library is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 * Library General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU Library General Public License 0016 * along with this library; see the file COPYING.LIB. If not, write to 0017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #ifndef KPIXMAPCACHE_H 0022 #define KPIXMAPCACHE_H 0023 0024 #include <kdelibs4support_export.h> 0025 0026 #include <QList> 0027 #include <QSet> 0028 #include <QSize> 0029 #include <QDateTime> 0030 0031 class QString; 0032 class QPixmap; 0033 0034 /** 0035 * @brief General-purpose pixmap cache for KDE. 0036 * 0037 * The pixmap cache can be used to store pixmaps which can later be loaded 0038 * from the cache very quickly. 0039 * 0040 * Its most common use is storing SVG images which might be expensive to 0041 * render every time they are used. With the cache you can render each SVG 0042 * only once and later use the stored version unless the SVG file or requested 0043 * pixmap size changes. 0044 * 0045 * KPixmapCache's API is similar to that of the QPixmapCache so if you're 0046 * already using the latter then all you need to do is creating a KPixmapCache 0047 * object (unlike QPixmapCache, KPixmapCache doesn't have many static methods) 0048 * and calling @ref insert() and @ref find() method on that object: 0049 * @code 0050 * // Create KPixmapCache object 0051 * KPixmapCache* cache = new KPixmapCache("myapp-pixmaps"); 0052 * // Load a pixmap 0053 * QPixmap pix; 0054 * if (!cache->find("pixmap-1", pix)) { 0055 * // Pixmap isn't in the cache, create it and insert to cache 0056 * pix = createPixmapFromData(); 0057 * cache->insert("pixmap-1", pix); 0058 * } 0059 * // Use pix 0060 * @endcode 0061 * 0062 * The above example illustrates that you can also cache pixmaps created from 0063 * some data. In case such data is updated, you might need to discard cache 0064 * contents using @ref discard() method: 0065 * @code 0066 * // Discard the cache if it's too old 0067 * if (cache->timestamp() < mydataTimestamp()) { 0068 * cache->discard(); 0069 * } 0070 * // Now the cache contains up-to-date data 0071 * @endcode 0072 * As demonstrated, you can use cache's @ref timestamp() method to see when 0073 * the cache was created. If necessary, you can also change the timestamp 0074 * using @ref setTimestamp() method. 0075 * 0076 * @deprecated KPixmapCache is susceptible to various non-trivial locking bugs and 0077 * inefficiencies, and is supported for backward compatibility only (since it exposes 0078 * a QDataStream API for subclasses). Users should port to KImageCache for a very close 0079 * work-alike, or KSharedDataCache if they need more control. 0080 * 0081 * @see KImageCache, KSharedDataCache 0082 * 0083 * @author Rivo Laks 0084 */ 0085 class KDELIBS4SUPPORT_DEPRECATED_EXPORT KPixmapCache 0086 { 0087 public: 0088 /** 0089 * Constucts the pixmap cache object. 0090 * @param name unique name of the cache 0091 */ 0092 KDELIBS4SUPPORT_DEPRECATED explicit KPixmapCache(const QString &name); 0093 virtual ~KPixmapCache(); 0094 0095 /** 0096 * Tries to load pixmap with the specified @a key from cache. If the pixmap 0097 * is found it is stored in @a pix, otherwise @a pix is unchanged. 0098 * 0099 * @return true when pixmap was found and loaded from cache, false otherwise 0100 */ 0101 virtual bool find(const QString &key, QPixmap &pix); 0102 0103 /** 0104 * Inserts the pixmap @a pix into the cache, associated with the key @a key. 0105 * 0106 * Any existing pixmaps associated with @a key are overwritten. 0107 */ 0108 virtual void insert(const QString &key, const QPixmap &pix); 0109 0110 /** 0111 * Loads a pixmap from given file, using the cache. If the file does not 0112 * exist on disk, an empty pixmap is returned, even if that file had 0113 * previously been cached. In addition, if the file's modified-time is 0114 * more recent than cache's @ref timestamp(), the @em entire cache is 0115 * discarded (to be regenerated). This behavior may change in a future 0116 * KDE Platform release. If the cached data is current the pixmap 0117 * is returned directly from the cache without any file loading. 0118 * 0119 * @note The mapping between @a filename and the actual key used internally 0120 * is implementation-dependent and can change without warning. Use insert() 0121 * manually if you need control of the key, otherwise consistently use this 0122 * function. 0123 * 0124 * @param filename The name of the pixmap to load, cache, and return. 0125 * @return The given pixmap, or an empty pixmap if the file was invalid or did 0126 * not exist. 0127 */ 0128 QPixmap loadFromFile(const QString &filename); 0129 0130 /** 0131 * Same as loadFromFile(), but using an SVG file instead. You may optionally 0132 * pass in a @a size to control the size of the output pixmap. 0133 * 0134 * @note The returned pixmap is only cached for identical filenames and sizes. 0135 * If you change the size in between calls to this function then the 0136 * pixmap will have to be regenerated again. 0137 * 0138 * @param filename The filename of the SVG file to load. 0139 * @param size size of the pixmap where the SVG is render to. If not given 0140 * then the SVG file's default size is used. 0141 * @return an empty pixmap if the file does not exist or was invalid, otherwise 0142 * a pixmap of the desired @a size. 0143 */ 0144 QPixmap loadFromSvg(const QString &filename, const QSize &size = QSize()); 0145 0146 /** 0147 * @note KPixmapCache does not ever change the timestamp, so the application 0148 * must set the timestamp if it to be used. 0149 * @return Timestamp of the cache, set using the setTimestamp() method. 0150 */ 0151 QDateTime timestamp() const; 0152 0153 /** 0154 * Sets the timestamp of app-specific cache. It's saved in the cache file 0155 * and can later be retrieved using the timestamp() method. 0156 * By default the timestamp is set to the cache creation time. 0157 */ 0158 void setTimestamp(const QDateTime &time); 0159 0160 /** 0161 * Sets whether QPixmapCache (memory caching) should be used in addition 0162 * to disk cache. QPixmapCache is used by default. 0163 * 0164 * @note On most systems KPixmapCache can use shared-memory to share cached 0165 * pixmaps with other applications attached to the same shared pixmap, 0166 * which means additional memory caching is unnecessary and actually 0167 * wasteful of memory. 0168 * 0169 * @warning QPixmapCache is shared among the entire process and therefore 0170 * can cause strange interactions with other instances of KPixmapCache. 0171 * This may be fixed in the future and should be not relied upon. 0172 */ 0173 // KDE5 Get rid of QPixmapCache and use a sane cache instead. 0174 void setUseQPixmapCache(bool use); 0175 0176 /** 0177 * Whether QPixmapCache should be used to cache pixmaps in memory in 0178 * addition to caching them on the disk. 0179 * 0180 * @b NOTE: The design of QPixmapCache means that the entries stored in 0181 * the cache are shared throughout the entire process, and not just in 0182 * this particular KPixmapCache. KPixmapCache makes an effort to ensure 0183 * that entries from other KPixmapCaches do not inadvertently spill over 0184 * into this one, but is not entirely successful (see discard()) 0185 */ 0186 bool useQPixmapCache() const; 0187 0188 /** 0189 * @return approximate size of the cache, in kilobytes (1 kilobyte == 1024 bytes) 0190 */ 0191 int size() const; 0192 0193 /** 0194 * @return maximum size of the cache (in kilobytes). 0195 * Default setting is 3 megabytes (1 megabyte = 2^20 bytes). 0196 */ 0197 int cacheLimit() const; 0198 0199 /** 0200 * Sets the maximum size of the cache (in kilobytes). If cache gets bigger 0201 * than the limit then some entries are removed (according to 0202 * removeEntryStrategy()). 0203 * 0204 * Setting the cache limit to 0 disables caching (as all entries will get 0205 * immediately removed). 0206 * 0207 * Note that the cleanup might not be done immediately, so the cache might 0208 * temporarily (for a few seconds) grow bigger than the limit. 0209 */ 0210 void setCacheLimit(int kbytes); 0211 0212 /** 0213 * Describes which entries will be removed first during cache cleanup. 0214 * @see removeEntryStrategy(), @see setRemoveEntryStrategy() 0215 */ 0216 enum RemoveStrategy { /// oldest entries are removed first. 0217 RemoveOldest, 0218 /// least used entries are removed first. 0219 RemoveSeldomUsed, 0220 /// least recently used entries are removed first. 0221 RemoveLeastRecentlyUsed 0222 }; 0223 /** 0224 * @return current entry removal strategy. 0225 * Default is RemoveLeastRecentlyUsed. 0226 */ 0227 RemoveStrategy removeEntryStrategy() const; 0228 0229 /** 0230 * Sets the removeEntryStrategy used when removing entries. 0231 */ 0232 void setRemoveEntryStrategy(RemoveStrategy strategy); 0233 0234 /** 0235 * Cache will be disabled when e.g. its data file cannot be created or 0236 * read. 0237 * 0238 * @return true when the cache is enabled. 0239 */ 0240 bool isEnabled() const; 0241 0242 /** 0243 * @return true when the cache is ready to be used. Not being valid usually 0244 * means that some additional initialization has to be done before the 0245 * cache can be used. 0246 */ 0247 bool isValid() const; 0248 0249 /** 0250 * Deletes a pixmap cache. 0251 * @param name unique name of the cache to be deleted 0252 */ 0253 // KDE5: Static function oh how I hate you, this makes it very difficult to perform 0254 // appropriate locking and synchronization to actually remove the cache. 0255 static void deleteCache(const QString &name); 0256 0257 /** 0258 * Deletes all entries and reinitializes this cache. 0259 * 0260 * @b NOTE: If useQPixmapCache is set to true then that cache must also 0261 * be cleared. There is only one QPixmapCache for the entire process 0262 * however so other KPixmapCaches and other QPixmapCache users may also 0263 * be affected, leading to a temporary slowdown until the QPixmapCache is 0264 * repopulated. 0265 */ 0266 void discard(); 0267 0268 /** 0269 * Removes some of the entries in the cache according to current 0270 * removeEntryStrategy(). 0271 * 0272 * @param newsize wanted size of the cache, in bytes. If 0 is given then 0273 * current cacheLimit() is used. 0274 * 0275 * @warning This currently works by copying some entries to a new cache and 0276 * then replacing the old cache with the new one. Thus it might be slow and 0277 * will temporarily use extra disk space. 0278 */ 0279 void removeEntries(int newsize = 0); 0280 0281 protected: 0282 /** 0283 * Makes sure that the cache is initialized correctly, including the loading of the 0284 * cache index and data, and any shared memory attachments (for systems where that 0285 * is enabled). 0286 * 0287 * @note Although this method is protected you should not use it from any subclasses. 0288 * 0289 * @internal 0290 */ 0291 // KDE5: rename to ensureInitialized() 0292 // KDE5: Make private or move to Private 0293 void ensureInited() const; 0294 0295 /** 0296 * Can be used by subclasses to load custom data from the stream. 0297 * This function will be called by KPixmapCache immediately following the 0298 * image data for a single image being read from @a stream. 0299 * (This function is called once for every single image). 0300 * 0301 * @see writeCustomData 0302 * @see loadCustomIndexHeader 0303 * @param stream the QDataStream to read data from 0304 * @return true if custom data was successfully loaded, false otherwise. If 0305 * false is returned then the cached item is assumed to be invalid and 0306 * will not be available to find() or contains(). 0307 */ 0308 virtual bool loadCustomData(QDataStream &stream); 0309 0310 /** 0311 * Can be used by subclasses to write custom data into the stream. 0312 * This function will be called by KPixmapCache immediately after the 0313 * image data for a single image has been written to @a stream. 0314 * (This function is called once for every single image). 0315 * 0316 * @see loadCustomData 0317 * @see writeCustomIndexHeader 0318 * @param stream the QDataStream to write data to 0319 */ 0320 virtual bool writeCustomData(QDataStream &stream); 0321 0322 /** 0323 * Can be used by subclasses to load custom data from cache's header. 0324 * This function will be called by KPixmapCache immediately after the 0325 * index header has been written out. (This function is called one time 0326 * only for the entire cache). 0327 * 0328 * @see loadCustomData 0329 * @see writeCustomIndexHeader 0330 * @param stream the QDataStream to read data from 0331 * @return true if custom index header data was successfully read, false 0332 * otherwise. If false is returned then the cache is assumed to 0333 * be invalid and further processing does not occur. 0334 */ 0335 virtual bool loadCustomIndexHeader(QDataStream &stream); 0336 0337 /** 0338 * Can be used by subclasses to write custom data into cache's header. 0339 * This function will be called by KPixmapCache immediately following the 0340 * index header has being loaded. (This function is called one time 0341 * only for the entire cache). 0342 * 0343 * @see writeCustomData 0344 * @see loadCustomIndexHeader 0345 * @param stream the QDataStream to write data to 0346 */ 0347 virtual void writeCustomIndexHeader(QDataStream &stream); 0348 0349 /** 0350 * Sets whether this cache is valid or not. (The cache must be enabled in addition 0351 * for isValid() to return true. @see isEnabled(), @see setEnabled()). 0352 * 0353 * Most cache functions do not work if the cache is not valid. KPixmapCache assumes 0354 * the cache is valid as long as its cache files were able to be created (see 0355 * recreateCacheFiles()) even if the cache is not enabled. 0356 * 0357 * Can be used by subclasses to indicate that cache needs some additional 0358 * initialization before it can be used (note that KPixmapCache will @em not handle 0359 * actually performing this extra initialization). 0360 */ 0361 void setValid(bool valid); 0362 0363 /** 0364 * This function causes the cache files to be recreate by invalidating the cache. 0365 * Any shared memory mappings (if enabled) are dropped temporarily as well. 0366 * 0367 * @note The recreated cache will be initially empty, but with the same size limits 0368 * and entry removal strategy (see removeEntryStrategy()). 0369 * 0370 * If you use this in a subclass be prepared to handle writeCustomData() and 0371 * writeCustomIndexHeader(). 0372 * 0373 * @return true if the cache was successfully recreated. 0374 */ 0375 bool recreateCacheFiles(); 0376 0377 private: 0378 /// @internal 0379 class Private; 0380 friend class Private; 0381 Private *const d; ///< @internal 0382 }; 0383 0384 #endif // KPIXMAPCACHE_H