File indexing completed on 2025-01-19 03:56:04
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2021-02-18 0007 * Description : Qt5 and Qt6 interface for exiftool. 0008 * Based on ZExifTool Qt interface published at 18 Feb 2021 0009 * https://github.com/philvl/ZExifTool 0010 * 0011 * SPDX-FileCopyrightText: 2021-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * SPDX-FileCopyrightText: 2021 by Philippe Vianney Liaud <philvl dot dev at gmail dot com> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #ifndef DIGIKAM_EXIFTOOL_PROCESS_H 0019 #define DIGIKAM_EXIFTOOL_PROCESS_H 0020 0021 // Qt includes 0022 0023 #include <QString> 0024 #include <QProcess> 0025 #include <QPointer> 0026 0027 // Local includes 0028 0029 #include "digikam_export.h" 0030 0031 namespace Digikam 0032 { 0033 class ExifToolParser; 0034 0035 class DIGIKAM_EXPORT ExifToolProcess : public QProcess 0036 { 0037 Q_OBJECT 0038 0039 public: 0040 0041 /** 0042 * ExifTool actions to process. 0043 */ 0044 enum Action 0045 { 0046 LOAD_METADATA = 0, ///< Load all metadata from a file with ExifTool. 0047 LOAD_CHUNKS, ///< Load Exif, Iptc, and Xmp chunks from a file as byte-array for MetaEngine. 0048 APPLY_CHANGES, ///< Apply tag changes in a file with ExifTool. 0049 APPLY_CHANGES_EXV, ///< Apply tag changes in a file with ExifTool using an EXV container. 0050 APPLY_METADATA_FILE, ///< Apply a metadata file to a file with ExifTool. 0051 READ_FORMATS, ///< Return the list of readable ExifTool file formats. 0052 WRITE_FORMATS, ///< Return the list of writable ExifTool file formats. 0053 TRANSLATIONS_LIST, ///< List of ExifTool languages available for translations. 0054 TAGS_DATABASE, ///< List of ExifTool tags from database. 0055 VERSION_STRING, ///< Return the ExifTool version as string. 0056 COPY_TAGS, ///< Copy tags from one file to another one. See CopyTagsSource enum for details. 0057 TRANS_TAGS, ///< Translate tags in file. See TranslateTagsOps enum for details. 0058 NO_ACTION ///< Last value from this list. Do nothing. 0059 }; 0060 0061 /** 0062 * Possible copying tags operations to OR combine with COPY_TAGS action. 0063 */ 0064 enum CopyTagsSource 0065 { 0066 COPY_EXIF = 0x01, ///< Copy all Exif Tags from source file. 0067 COPY_MAKERNOTES = 0x02, ///< Copy all Makernotes tags from source file. 0068 COPY_IPTC = 0x04, ///< Copy all Iptc tags from source file. 0069 COPY_XMP = 0x08, ///< Copy all Xmp tags from source file. 0070 COPY_ICC = 0x10, ///< Copy ICC profile from source file. 0071 COPY_ALL = 0x20, ///< Copy all tags from source file. 0072 COPY_NONE = 0x40 ///< No copy operation. 0073 }; 0074 0075 /** 0076 * Possible writing tags mode to OR combine with COPY_TAGS action. 0077 */ 0078 enum WritingTagsMode 0079 { 0080 WRITE_EXISTING_TAGS = 0x01, ///< Overwrite existing tags. 0081 CREATE_NEW_TAGS = 0x02, ///< Create new tags. 0082 CREATE_NEW_GROUPS = 0x04, ///< Create new groups if necessary. 0083 ALL_MODES = WRITE_EXISTING_TAGS | 0084 CREATE_NEW_TAGS | 0085 CREATE_NEW_GROUPS 0086 }; 0087 0088 /** 0089 * Possible translating tags operations to OR combine with COPY_TAGS action. 0090 */ 0091 enum TranslateTagsOps 0092 { 0093 TRANS_ALL_XMP = 0x01, ///< Translate all existing Tags from source file to Xmp. 0094 TRANS_ALL_IPTC = 0x02, ///< Translate all existing Tags from source file to Iptc. 0095 TRANS_ALL_EXIF = 0x04 ///< Translate all existing Tags from source file to Exif. 0096 }; 0097 0098 /** 0099 * Command result state. 0100 */ 0101 enum ResultStatus 0102 { 0103 COMMAND_RESULT = 0, 0104 FINISH_RESULT, 0105 ERROR_RESULT 0106 }; 0107 0108 public: 0109 0110 class Result 0111 { 0112 public: 0113 0114 Result() 0115 : waitError (false), 0116 cmdStatus (ExifToolProcess::COMMAND_RESULT), 0117 cmdAction (ExifToolProcess::NO_ACTION), 0118 cmdNumber (0), 0119 elapsed (0) 0120 { 0121 } 0122 0123 bool waitError; 0124 int cmdStatus; 0125 int cmdAction; 0126 int cmdNumber; 0127 int elapsed; 0128 QByteArray output; 0129 }; 0130 0131 public: 0132 0133 /** 0134 * Constructs a ExifToolProcess. 0135 */ 0136 explicit ExifToolProcess(); 0137 0138 /** 0139 * Destructs the ExifToolProcess object, i.e., killing the process. 0140 * Note that this function will not return until the process is terminated. 0141 */ 0142 ~ExifToolProcess(); 0143 0144 /** 0145 * @brief internalPtr - singleton implementation 0146 */ 0147 static QPointer<ExifToolProcess> internalPtr; 0148 static ExifToolProcess* instance(); 0149 static bool isCreated(); 0150 0151 /** 0152 * Setup connections, apply Settings and start ExifTool process. 0153 * This function cannot be called from another thread. 0154 */ 0155 void initExifTool(); 0156 0157 public: 0158 0159 /** 0160 * Change the ExifTool path configuration. 0161 * This function can be called from another thread. 0162 */ 0163 void setExifToolProgram(const QString& etExePath); 0164 0165 QString getExifToolProgram() const; 0166 0167 public: 0168 0169 /** 0170 * Returns true if ExifToolProcess is available (process state == Running) 0171 */ 0172 bool exifToolAvailable() const; 0173 0174 /** 0175 * Returns true if a command is running. 0176 */ 0177 bool exifToolIsBusy() const; 0178 0179 /** 0180 * Returns the type of error that occurred last. 0181 */ 0182 QProcess::ProcessError exifToolError() const; 0183 0184 /** 0185 * Returns an error message. 0186 */ 0187 QString exifToolErrorString() const; 0188 0189 /** 0190 * Returns the ExifToolProcess result. 0191 */ 0192 ExifToolProcess::Result getExifToolResult(int cmdId) const; 0193 0194 /** 0195 * WatCondition for the ExifToolParser class. 0196 * Returns the ExifToolProcess result. 0197 */ 0198 ExifToolProcess::Result waitForExifToolResult(int cmdId) const; 0199 0200 /** 0201 * Send a command to exiftool process. 0202 * This function can be called from another thread. 0203 * Return 0: ExitTool not running, write channel is closed or args is empty. 0204 */ 0205 int command(const QByteArrayList& args, Action ac); 0206 0207 Q_SIGNALS: 0208 0209 void signalExifToolResult(int cmdId); 0210 0211 private: 0212 0213 /** 0214 * Starts exiftool in a new process. 0215 */ 0216 bool startExifTool(); 0217 0218 /** 0219 * Restart exiftool in a new process. 0220 */ 0221 void restartExifTool(); 0222 0223 /** 0224 * Attempts to terminate the process. 0225 */ 0226 void terminateExifTool(); 0227 0228 /** 0229 * Kills the current process, causing it to exit immediately. 0230 * On Windows, kill() uses TerminateProcess, and on Unix and macOS, 0231 * the SIGKILL signal is sent to the process. 0232 */ 0233 void killExifTool(); 0234 0235 QString exifToolBin() const; 0236 0237 bool checkExifToolProgram() const; 0238 0239 void changeExifToolProgram(const QString& etExePath); 0240 0241 Q_SIGNALS: 0242 0243 void signalExecNextCmd(); 0244 void signalChangeProgram(const QString& etExePath); 0245 0246 private Q_SLOTS: 0247 0248 void slotStarted(); 0249 void slotApplySettingsAndStart(); 0250 void slotReadyReadStandardError(); 0251 void slotReadyReadStandardOutput(); 0252 void slotChangeProgram(const QString& etExePath); 0253 void slotErrorOccurred(QProcess::ProcessError error); 0254 void slotFinished(int exitCode, QProcess::ExitStatus exitStatus); 0255 0256 private: 0257 0258 // Disable 0259 explicit ExifToolProcess(QObject*) = delete; 0260 0261 private: 0262 0263 class Private; 0264 Private* const d; 0265 }; 0266 0267 } // namespace Digikam 0268 0269 #endif // DIGIKAM_EXIFTOOL_PROCESS_H