File indexing completed on 2025-04-27 03:58:08
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-12-17 0007 * Description : image file IO threaded interface. 0008 * 0009 * SPDX-FileCopyrightText: 2005-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #ifndef DIGIKAM_LOAD_SAVE_THREAD_H 0017 #define DIGIKAM_LOAD_SAVE_THREAD_H 0018 0019 // Qt includes 0020 0021 #include <QThread> 0022 #include <QMutex> 0023 #include <QList> 0024 #include <QDateTime> 0025 #include <QWaitCondition> 0026 #include <QEvent> 0027 0028 // Local includes 0029 0030 #include "dimg.h" 0031 #include "digikam_export.h" 0032 #include "dynamicthread.h" 0033 #include "loadingdescription.h" 0034 0035 namespace Digikam 0036 { 0037 0038 class DMetadata; 0039 class LoadSaveTask; 0040 0041 class DIGIKAM_EXPORT LoadSaveNotifier 0042 { 0043 public: 0044 0045 LoadSaveNotifier(); 0046 virtual ~LoadSaveNotifier(); 0047 0048 virtual void imageStartedLoading(const LoadingDescription& loadingDescription) = 0; 0049 virtual void loadingProgress(const LoadingDescription& loadingDescription, float progress) = 0; 0050 virtual void imageLoaded(const LoadingDescription& loadingDescription, const DImg& img) = 0; 0051 virtual void moreCompleteLoadingAvailable(const LoadingDescription& oldLoadingDescription, 0052 const LoadingDescription& newLoadingDescription) = 0; 0053 virtual void imageStartedSaving(const QString& filePath) = 0; 0054 virtual void savingProgress(const QString& filePath, float progress) = 0; 0055 virtual void imageSaved(const QString& filePath, bool success) = 0; 0056 virtual void thumbnailLoaded(const LoadingDescription& loadingDescription, const QImage& img) = 0; 0057 0058 private: 0059 0060 Q_DISABLE_COPY(LoadSaveNotifier) 0061 }; 0062 0063 // ------------------------------------------------------------------------------------------------------- 0064 0065 class DIGIKAM_EXPORT LoadSaveFileInfoProvider 0066 { 0067 public: 0068 0069 LoadSaveFileInfoProvider(); 0070 virtual ~LoadSaveFileInfoProvider(); 0071 0072 /** 0073 * Gives a hint at the orientation of the image. 0074 * This can be used to supersede the Exif information in the file. 0075 * Will not be used if DMetadata::ORIENTATION_UNSPECIFIED (default value) 0076 */ 0077 virtual int orientationHint(const QString& path) = 0; 0078 0079 /** 0080 * Gives a hint at the size of the image. 0081 * This can be used to supersede the Exif information in the file. 0082 */ 0083 virtual QSize dimensionsHint(const QString& path) = 0; 0084 0085 private: 0086 0087 Q_DISABLE_COPY(LoadSaveFileInfoProvider) 0088 }; 0089 0090 // ------------------------------------------------------------------------------------------------------- 0091 0092 class DIGIKAM_EXPORT LoadSaveThread : public DynamicThread, 0093 public LoadSaveNotifier 0094 { 0095 Q_OBJECT 0096 0097 public: 0098 0099 enum NotificationPolicy 0100 { 0101 /** 0102 * Always send notification, unless the last event is still in the event queue 0103 */ 0104 NotificationPolicyDirect, 0105 /** 0106 * Always wait for a certain amount of time after the last event sent. 0107 * In particular, the first event will be sent only after waiting for this time span. 0108 * (Or no event will be sent, when the loading has finished before) 0109 * This is the default. 0110 */ 0111 NotificationPolicyTimeLimited 0112 }; 0113 0114 /** 0115 * used by SharedLoadSaveThread only 0116 */ 0117 enum AccessMode 0118 { 0119 /** 0120 * image will only be used for reading 0121 */ 0122 AccessModeRead, 0123 /** 0124 * image data will possibly be changed 0125 */ 0126 AccessModeReadWrite 0127 }; 0128 0129 public: 0130 0131 explicit LoadSaveThread(QObject* const parent = nullptr); 0132 0133 /** 0134 * Destructor: 0135 * The thread will execute all pending tasks and wait for this upon destruction 0136 */ 0137 ~LoadSaveThread() override; 0138 0139 /** 0140 * Append a task to load the given file to the task list 0141 */ 0142 void load(const LoadingDescription& description); 0143 0144 /** 0145 * Append a task to save the image to the task list 0146 */ 0147 void save(const DImg& image, const QString& filePath, const QString& format); 0148 0149 void setNotificationPolicy(NotificationPolicy notificationPolicy); 0150 0151 public: 0152 0153 static void setInfoProvider(LoadSaveFileInfoProvider* const infoProvider); 0154 static LoadSaveFileInfoProvider* infoProvider(); 0155 0156 /** 0157 * Retrieves the Exif orientation, either from the info provider if available, 0158 * or from the metadata 0159 */ 0160 static int exifOrientation(const QString& filePath, 0161 const DMetadata& metadata, 0162 bool isRaw, 0163 bool fromRawEmbeddedPreview); 0164 0165 Q_SIGNALS: 0166 0167 /** 0168 * All signals are delivered to the thread from where the LoadSaveThread object 0169 * has been created. This thread must use its event loop to get the signals. 0170 * You must connect to these signals with Qt::AutoConnection (default) or Qt::QueuedConnection. 0171 */ 0172 0173 /** 0174 * This signal is emitted when the loading process begins. 0175 */ 0176 void signalImageStartedLoading(const LoadingDescription& loadingDescription); 0177 0178 /** 0179 * This signal is emitted whenever new progress info is available 0180 * and the notification policy allows emitting the signal. 0181 * No progress info will be sent for preloaded images (ManagedLoadSaveThread). 0182 */ 0183 void signalLoadingProgress(const LoadingDescription& loadingDescription, float progress); 0184 0185 /** 0186 * This signal is emitted when the loading process has finished. 0187 * If the process failed, img is null. 0188 */ 0189 void signalImageLoaded(const LoadingDescription& loadingDescription, const DImg& img); 0190 0191 /** 0192 * This signal is emitted if 0193 * - you are doing shared loading (SharedLoadSaveThread) 0194 * - you started a loading operation with a LoadingDescription for 0195 * a reduced version of the image 0196 * - another thread started a loading operation for a more complete version 0197 * You may want to cancel the current operation and start with the given loadingDescription 0198 */ 0199 void signalMoreCompleteLoadingAvailable(const LoadingDescription& oldLoadingDescription, 0200 const LoadingDescription& newLoadingDescription); 0201 0202 void signalImageStartedSaving(const QString& filePath); 0203 void signalSavingProgress(const QString& filePath, float progress); 0204 void signalImageSaved(const QString& filePath, bool success); 0205 0206 void signalThumbnailLoaded(const LoadingDescription& loadingDescription, const QImage& img); 0207 0208 public: 0209 0210 void imageStartedLoading(const LoadingDescription& loadingDescription) override; 0211 void loadingProgress(const LoadingDescription& loadingDescription, float progress) override; 0212 void imageLoaded(const LoadingDescription& loadingDescription, const DImg& img) override; 0213 void moreCompleteLoadingAvailable(const LoadingDescription& oldLoadingDescription, 0214 const LoadingDescription& newLoadingDescription) override; 0215 void imageStartedSaving(const QString& filePath) override; 0216 void savingProgress(const QString& filePath, float progress) override; 0217 void imageSaved(const QString& filePath, bool success) override; 0218 void thumbnailLoaded(const LoadingDescription& loadingDescription, const QImage& img) override; 0219 0220 virtual bool querySendNotifyEvent() const; 0221 virtual void taskHasFinished(); 0222 0223 protected: 0224 0225 void run() override; 0226 0227 void notificationReceived(); 0228 0229 protected: 0230 0231 QMutex m_mutex; 0232 0233 QList<LoadSaveTask*> m_todo; 0234 0235 LoadSaveTask* m_currentTask; 0236 0237 NotificationPolicy m_notificationPolicy; 0238 0239 private: 0240 0241 // Disable 0242 LoadSaveThread(const LoadSaveThread&) = delete; 0243 LoadSaveThread& operator=(const LoadSaveThread&) = delete; 0244 0245 private: 0246 0247 class Private; 0248 Private* const d; 0249 }; 0250 0251 } // namespace Digikam 0252 0253 #endif // DIGIKAM_LOAD_SAVE_THREAD_H