File indexing completed on 2025-04-27 03:58:07
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-01-11 0007 * Description : shared image loading and caching 0008 * 0009 * SPDX-FileCopyrightText: 2005-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #ifndef DIGIKAM_LOADING_CACHE_H 0016 #define DIGIKAM_LOADING_CACHE_H 0017 0018 // Qt includes 0019 0020 #include <QPixmap> 0021 0022 // Local includes 0023 0024 #include "dimg.h" 0025 #include "loadsavethread.h" 0026 #include "digikam_export.h" 0027 0028 namespace Digikam 0029 { 0030 0031 class ICCSettingsContainer; 0032 0033 class LoadingProcessListener 0034 { 0035 public: 0036 0037 LoadingProcessListener(); 0038 virtual ~LoadingProcessListener(); 0039 virtual bool querySendNotifyEvent() const = 0; 0040 virtual void setResult(const LoadingDescription& loadingDescription, const DImg& img) = 0; 0041 virtual LoadSaveNotifier* loadSaveNotifier() const = 0; 0042 virtual LoadSaveThread::AccessMode accessMode() const = 0; 0043 0044 private: 0045 0046 // Disable 0047 LoadingProcessListener(const LoadingProcessListener&) = delete; 0048 LoadingProcessListener& operator=(const LoadingProcessListener&) = delete; 0049 }; 0050 0051 // -------------------------------------------------------------------------------------------------------------- 0052 0053 class LoadingProcess 0054 { 0055 public: 0056 0057 LoadingProcess(); 0058 virtual ~LoadingProcess(); 0059 virtual bool completed() const = 0; 0060 virtual QString cacheKey() const = 0; 0061 virtual void addListener(LoadingProcessListener* const listener) = 0; 0062 virtual void removeListener(LoadingProcessListener* const listener) = 0; 0063 virtual void notifyNewLoadingProcess(LoadingProcess* const process, const LoadingDescription& description) = 0; 0064 0065 private: 0066 0067 // Disable 0068 LoadingProcess(const LoadingProcess&) = delete; 0069 LoadingProcess& operator=(const LoadingProcess&) = delete; 0070 }; 0071 0072 // -------------------------------------------------------------------------------------------------------------- 0073 0074 class DIGIKAM_EXPORT LoadingCacheFileWatch : public QObject 0075 { 0076 Q_OBJECT 0077 0078 public: 0079 0080 LoadingCacheFileWatch(); 0081 ~LoadingCacheFileWatch() override; 0082 0083 void addedImage(const QString& filePath); 0084 void removeImage(const QString& filePath); 0085 void checkFileWatch(const QString& filePath); 0086 0087 protected: 0088 0089 /** 0090 * Convenience method. 0091 * Call this to tell the cache to remove stored images for filePath from the cache. 0092 * Calling this method is fast, you do not need to check if the file is contained in the cache. 0093 * Do not hold the CacheLock when calling this method. 0094 */ 0095 void notifyFileChanged(const QString& filePath); 0096 0097 protected: 0098 0099 friend class LoadingCache; 0100 0101 QHash<QString, QPair<qint64, QDateTime> > m_watchHash; 0102 class LoadingCache* m_cache; 0103 0104 private: 0105 0106 // Disable 0107 LoadingCacheFileWatch(const LoadingCacheFileWatch&) = delete; 0108 LoadingCacheFileWatch& operator=(const LoadingCacheFileWatch&) = delete; 0109 LoadingCacheFileWatch(QObject*) = delete; 0110 }; 0111 0112 // -------------------------------------------------------------------------------------------------------------- 0113 0114 class DIGIKAM_EXPORT LoadingCache : public QObject 0115 { 0116 Q_OBJECT 0117 0118 public: 0119 0120 /** 0121 * NOTE: !! All methods of LoadingCache shall only be called when a CacheLock is held !! 0122 */ 0123 0124 class DIGIKAM_EXPORT CacheLock 0125 { 0126 public: 0127 0128 explicit CacheLock(LoadingCache* const cache); 0129 ~CacheLock(); 0130 void wakeAll(); 0131 void timedWait(); 0132 0133 private: 0134 0135 LoadingCache* m_cache; 0136 }; 0137 0138 public: 0139 0140 static LoadingCache* cache(); 0141 static void cleanUp(); 0142 0143 /** 0144 * Retrieves an image for the given string from the cache, 0145 * or 0 if no image is found. 0146 */ 0147 DImg* retrieveImage(const QString& cacheKey) const; 0148 0149 /** 0150 * Returns whether the given DImg fits in the cache. 0151 */ 0152 bool isCacheable(const DImg& img) const; 0153 0154 /** 0155 * Put image into for given string into the cache. 0156 * Returns true if image has been put in the cache, false otherwise. 0157 * Ownership of the DImg instance is passed to the cache. 0158 * When it cannot be put in the cache it is deleted. 0159 * The third parameter specifies a file path that will be watched. 0160 * If this file changes, the object will be removed from the cache. 0161 */ 0162 bool putImage(const QString& cacheKey, const DImg& img, const QString& filePath) const; 0163 0164 /** 0165 * Remove entries for the given cacheKey from the cache 0166 */ 0167 void removeImage(const QString& cacheKey); 0168 0169 /** 0170 * Remove all entries from the cache 0171 */ 0172 void removeImages(); 0173 0174 // ------- Loading process management ----------------------------------- 0175 0176 /** 0177 * Find the loading process for given cacheKey, or 0 if not found 0178 */ 0179 LoadingProcess* retrieveLoadingProcess(const QString& cacheKey) const; 0180 0181 /** 0182 * Add a loading process to the list. Only one loading process 0183 * for the same cache key is registered at a time. 0184 */ 0185 void addLoadingProcess(LoadingProcess* const process); 0186 0187 /** 0188 * Remove loading process for given cache key 0189 */ 0190 void removeLoadingProcess(LoadingProcess* const process); 0191 0192 /** 0193 * Notify all currently registered loading processes 0194 */ 0195 void notifyNewLoadingProcess(LoadingProcess* const process, const LoadingDescription& description); 0196 0197 /** 0198 * Sets the cache size in megabytes. 0199 * The thumbnail cache is not affected and setThumbnailCacheSize takes the maximum number. 0200 */ 0201 void setCacheSize(int megabytes); 0202 0203 /** 0204 * Get the cache size in bytes. 0205 */ 0206 quint64 getCacheSize() const; 0207 0208 // ------- Thumbnail cache ----------------------------------- 0209 0210 /** 0211 * The LoadingCache support both the caching of QImage and QPixmap objects. 0212 * QPixmaps can only be accessed from the main thread, so the tasks cannot access this cache. 0213 */ 0214 0215 /** 0216 * Retrieves a thumbnail for the given filePath from the thumbnail cache, 0217 * or a 0 if the thumbnail is not found. 0218 */ 0219 const QImage* retrieveThumbnail(const QString& cacheKey) const; 0220 const QPixmap* retrieveThumbnailPixmap(const QString& cacheKey) const; 0221 bool hasThumbnailPixmap(const QString& cacheKey) const; 0222 0223 /** 0224 * Puts a thumbnail into the thumbnail cache. 0225 */ 0226 void putThumbnail(const QString& cacheKey, const QImage& thumb, const QString& filePath); 0227 void putThumbnail(const QString& cacheKey, const QPixmap& thumb, const QString& filePath); 0228 0229 /** 0230 * Remove the thumbnail for the given file path from the thumbnail cache 0231 */ 0232 void removeThumbnail(const QString& cacheKey); 0233 0234 /** 0235 * Remove all thumbnails 0236 */ 0237 void removeThumbnails(); 0238 0239 /** 0240 * Sets the size of the thumbnail cache 0241 * @param numberOfQImages The maximum number of thumbnails of max possible size in QImage format 0242 * that will be cached. If the size of the images is smaller, a larger 0243 * number will be cached. 0244 * @param numberOfQPixmaps The maximum number of thumbnails of max possible size in QPixmap format 0245 * that will be cached. If the size of the images is smaller, a larger 0246 * number will be cached. 0247 * Note: The main cache is unaffected by this method, 0248 * and setCacheSize takes megabytes as parameter. 0249 * Note: A good caching strategy will be to set one of the numbers to 0 0250 * Default values: (0, 100) 0251 */ 0252 void setThumbnailCacheSize(int numberOfQImages, int numberOfQPixmaps); 0253 0254 // ------- File Watch Management ----------------------------------- 0255 0256 /** 0257 * Sets a LoadingCacheFileWatch to watch the files contained in this cache. 0258 * Ownership of this object is transferred to the cache. 0259 */ 0260 void setFileWatch(LoadingCacheFileWatch* const watch); 0261 0262 /** 0263 * Remove all entries from cache that were loaded from filePath. 0264 * Emits relevant signals if notify = true. 0265 */ 0266 void notifyFileChanged(const QString& filePath, bool notify = true); 0267 0268 Q_SIGNALS: 0269 0270 /** 0271 * This signal is emitted when the cache is notified that a file was changed. 0272 * There is no information in this signal if the file was ever contained in the cache. 0273 * The signal may be emitted under CacheLock. Strongly consider a queued connection. 0274 */ 0275 void fileChanged(const QString& filePath); 0276 0277 private Q_SLOTS: 0278 0279 void iccSettingsChanged(const ICCSettingsContainer& current, const ICCSettingsContainer& previous); 0280 0281 private: 0282 0283 // Disabled 0284 LoadingCache(); 0285 explicit LoadingCache(QObject*) = delete; 0286 ~LoadingCache() override; 0287 0288 LoadingCache(const LoadingCache&) = delete; 0289 LoadingCache& operator=(const LoadingCache&) = delete; 0290 0291 private: 0292 0293 friend class LoadingCacheFileWatch; 0294 friend class CacheLock; 0295 0296 private: 0297 0298 static LoadingCache* m_instance; 0299 0300 class Private; 0301 Private* const d; 0302 }; 0303 0304 } // namespace Digikam 0305 0306 #endif // DIGIKAM_LOADING_CACHE_H