1 /* ============================================================ 2 * 3 * This file is a part of digiKam project 4 * https://www.digikam.org 5 * 6 * Date : 2021-02-18 7 * Description : Qt5 and Qt6 interface for exiftool. 8 * Based on ZExifTool Qt interface published at 18 Feb 2021 9 * https://github.com/philvl/ZExifTool 10 * 11 * Copyright (C) 2021 by Gilles Caulier <caulier dot gilles at gmail dot com> 12 * Copyright (c) 2021 by Philippe Vianney Liaud <philvl dot dev at gmail dot com> 13 * 14 * This program is free software; you can redistribute it 15 * and/or modify it under the terms of the GNU General 16 * Public License as published by the Free Software Foundation; 17 * either version 2, or (at your option) 18 * any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * ============================================================ */ 26 27 #ifndef DIGIKAM_EXIFTOOL_PROCESS_H 28 #define DIGIKAM_EXIFTOOL_PROCESS_H 29 30 // Qt Core 31 32 #include <QObject> 33 #include <QString> 34 #include <QProcess> 35 #include <QMutex> 36 37 // Local includes 38 39 #include "digikam_export.h" 40 41 namespace Digikam 42 { 43 44 class DIGIKAM_EXPORT ExifToolProcess : public QObject 45 { 46 Q_OBJECT 47 48 public: 49 50 /** 51 * ExifTool actions to process. 52 */ 53 enum Action 54 { 55 LOAD_METADATA = 0, ///< Load all metadata from a file with ExifTool. 56 LOAD_CHUNKS, ///< Load Exif, Iptc, and Xmp chunks from a file as byte-array for MetaEngine. 57 APPLY_CHANGES, ///< Apply tag changes in a file with ExifTool. 58 APPLY_CHANGES_EXV, ///< Apply tag changes in a file with ExifTool using an EXV container. 59 READ_FORMATS, ///< Return the list of readable ExifTool file formats. 60 WRITE_FORMATS, ///< Return the list of writable ExifTool file formats. 61 TRANSLATIONS_LIST, ///< List of ExifTool languages available for translations. 62 TAGS_DATABASE, ///< List of ExifTool tags from database. 63 VERSION_STRING, ///< Return the ExifTool version as string. 64 COPY_TAGS, ///< Copy tags from one file to another one. See CopyTagsSource enum for details. 65 TRANS_TAGS, ///< Translate tags in file. See TranslateTagsOps enum for details. 66 NO_ACTION ///< Last value from this list. Do nothing. 67 }; 68 69 /** 70 * Possible copying tags operations to OR combine with COPY_TAGS action. 71 */ 72 enum CopyTagsSource 73 { 74 COPY_EXIF = 0x01, ///< Copy all Exif Tags from source file. 75 COPY_MAKERNOTES = 0x02, ///< Copy all Makernotes tags from source file. 76 COPY_IPTC = 0x04, ///< Copy all Iptc tags from source file. 77 COPY_XMP = 0x08, ///< Copy all Xmp tags from source file. 78 COPY_ICC = 0x10, ///< Copy ICC profile from source file. 79 COPY_ALL = 0x20, ///< Copy all tags from source file. 80 COPY_NONE = 0x40 ///< No copy operation. 81 }; 82 83 /** 84 * Possible writing tags mode to OR combine with COPY_TAGS action. 85 */ 86 enum WritingTagsMode 87 { 88 WRITE_EXISTING_TAGS = 0x01, ///< Overwrite existing tags. 89 CREATE_NEW_TAGS = 0x02, ///< Create new tags. 90 CREATE_NEW_GROUPS = 0x04, ///< Create new groups if necessary. 91 ALL_MODES = WRITE_EXISTING_TAGS | 92 CREATE_NEW_TAGS | 93 CREATE_NEW_GROUPS 94 }; 95 96 /** 97 * Possible translating tags operations to OR combine with COPY_TAGS action. 98 */ 99 enum TranslateTagsOps 100 { 101 TRANS_ALL_XMP = 0x01, ///< Translate all existing Tags from source file to Xmp. 102 TRANS_ALL_IPTC = 0x02, ///< Translate all existing Tags from source file to Iptc. 103 TRANS_ALL_EXIF = 0x04 ///< Translate all existing Tags from source file to Exif. 104 }; 105 106 public: 107 108 /** 109 * Constructs a ExifToolProcess object with the given parent. 110 */ 111 explicit ExifToolProcess(QObject* const parent); 112 113 /** 114 * Destructs the ExifToolProcess object, i.e., killing the process. 115 * Note that this function will not return until the process is terminated. 116 */ 117 ~ExifToolProcess(); 118 119 public: 120 121 /** 122 * Setup the ExifTool configuration. This function must be called before start(). 123 */ 124 void setProgram(const QString& etExePath, 125 const QString& perlExePath = QString()); 126 127 QString program() const; 128 129 bool checkExifToolProgram(); 130 131 /** 132 * Starts exiftool in a new process. 133 */ 134 bool start(); 135 136 /** 137 * Attempts to terminate the process. 138 */ 139 void terminate(); 140 141 /** 142 * Kills the current process, causing it to exit immediately. 143 * On Windows, kill() uses TerminateProcess, and on Unix and macOS, 144 * the SIGKILL signal is sent to the process. 145 */ 146 void kill(); 147 148 public: 149 150 /** 151 * Returns true if ExifToolProcess is running (process state == Running) 152 */ 153 bool isRunning() const; 154 155 /** 156 * Returns true if a command is running 157 */ 158 bool isBusy() const; 159 160 /** 161 * Returns the native process identifier for the running process, if available. 162 * If no process is currently running, 0 is returned. 163 */ 164 qint64 processId() const; 165 166 /** 167 * Returns the current state of the process. 168 */ 169 QProcess::ProcessState state() const; 170 171 /** 172 * Returns the type of error that occurred last. 173 */ 174 QProcess::ProcessError error() const; 175 176 /** 177 * Returns an error message. 178 */ 179 QString errorString() const; 180 181 /** 182 * Returns the exit status of the last process that finished. 183 */ 184 QProcess::ExitStatus exitStatus() const; 185 186 int exitCode() const; 187 188 /** 189 * Blocks until the process has started and the started() signal has been emitted, 190 * or until msecs milliseconds have passed. 191 */ 192 bool waitForStarted(int msecs = 30000) const; 193 194 /** 195 * Blocks until the process has finished and the finished() signal has been emitted, 196 * or until msecs milliseconds have passed. 197 */ 198 bool waitForFinished(int msecs = 30000) const; 199 200 /** 201 * Send a command to exiftool process 202 * Return 0: ExitTool not running, write channel is closed or args is empty 203 */ 204 int command(const QByteArrayList& args, Action ac); 205 206 Q_SIGNALS: 207 208 void signalStarted(int cmdAction); 209 210 void signalStateChanged(int cmdAction, 211 QProcess::ProcessState newState); 212 213 void signalErrorOccurred(int cmdAction, 214 QProcess::ProcessError error); 215 216 void signalFinished(int cmdAction, 217 int exitCode, 218 QProcess::ExitStatus exitStatus); 219 220 void signalCmdCompleted(int cmdAction, 221 int execTime, 222 const QByteArray& cmdOutputChannel, 223 const QByteArray& cmdErrorChannel); 224 225 private Q_SLOTS: 226 227 void slotStarted(); 228 void slotStateChanged(QProcess::ProcessState newState); 229 void slotErrorOccurred(QProcess::ProcessError error); 230 void slotReadyReadStandardOutput(); 231 void slotReadyReadStandardError(); 232 void slotFinished(int exitCode, 233 QProcess::ExitStatus exitStatus); 234 235 private: 236 237 QString exifToolBin() const; 238 239 private: 240 241 class Private; 242 Private* const d; 243 }; 244 245 } // namespace Digikam 246 247 #endif // DIGIKAM_EXIFTOOL_PROCESS_H 248