File indexing completed on 2024-12-08 11:10:44
0001 // SPDX-License-Identifier: GPL-2.0-or-later 0002 // SPDX-FileCopyrightText: 2001 Dominik Seichter <domseichter@web.de> 0003 0004 #ifndef BATCHRENAMER_H 0005 #define BATCHRENAMER_H 0006 0007 #include <QList> 0008 #include <QObject> 0009 0010 #include "krenamefile.h" 0011 0012 class QFile; 0013 class QProgressDialog; 0014 class QString; 0015 class QTextStream; 0016 0017 typedef struct __tag_tCounterValues { 0018 int value; // current value of this counter 0019 int start; // start value of this counter (for findResetCounter) 0020 int step; // stepping value of this counter; 0021 } tCounterValues; 0022 0023 /** A structure describing a string or regular 0024 * expression that is to be found in the final/resulting 0025 * filename and to be replaced with another string. 0026 */ 0027 typedef struct __tag_TReplaceItem { 0028 QString find; ///< Text to replace 0029 QString replace; ///< Replace with 0030 bool reg; ///< is it a reg expression ? 0031 bool doProcessTokens; ///< Process tokens in result 0032 } TReplaceItem; 0033 0034 /** An enum to set the renaming mode of KRename 0035 */ 0036 enum ERenameMode { 0037 eRenameMode_Rename, ///< All files are renamed in place 0038 eRenameMode_Move, ///< All files are moved to a new directory and renamed 0039 eRenameMode_Copy, ///< Only copies of the files are renamed 0040 eRenameMode_Link ///< Symbolic links are created and renamed 0041 }; 0042 0043 class QObject; 0044 class ProgressDialog; 0045 0046 /** This is the core class for renaming. 0047 * 0048 * It transforms the filenames according to 0049 * the users settings using custom functions 0050 * and external plugins. 0051 * Also the actual renaming, copying or moving 0052 * of the files is done by this class 0053 * 0054 * @author Dominik Seichter 0055 */ 0056 class BatchRenamer : public QObject 0057 { 0058 Q_OBJECT 0059 0060 public: 0061 BatchRenamer(); 0062 ~BatchRenamer() override; 0063 0064 /** Sets the list of files 0065 * which contains all filenames which should be transformed. 0066 * 0067 * The renamed filenames are stored in this list, too,. 0068 * 0069 * @param list a list of KRenameFile objects 0070 */ 0071 inline void setFiles(KRenameFile::List *list); 0072 0073 /** Get access to the list of files used for renaming. 0074 * @returns the list of files or NULL if none was set. 0075 */ 0076 inline const KRenameFile::List *files() const; 0077 0078 /** 0079 * @returns the current renaming mode 0080 */ 0081 inline ERenameMode renameMode() const; 0082 0083 /** 0084 * @returns the current start index for counters 0085 */ 0086 inline int numberStartIndex() const; 0087 0088 /** 0089 * @returns the stepping for counters 0090 */ 0091 inline int numberStepping() const; 0092 0093 /** 0094 * @returns if counters are reset on new directories 0095 */ 0096 inline int numberReset() const; 0097 0098 /** 0099 * @returns the list of numbers that are skipped during renaming 0100 */ 0101 inline QList<int> numberSkipList() const; 0102 0103 /** Does the actuall renaming, 0104 * transforming all source filenames in the file list 0105 * to the new destination filenames. 0106 * 0107 * No actuall renaming is done, only the new filenames 0108 * are calculated. 0109 */ 0110 void processFilenames(); 0111 0112 /** Process all files 0113 * 0114 * processFilenames has to be called before 0115 * 0116 * All files will be renamed according to the users settings. 0117 * 0118 * Output will be reported through a progress dialog 0119 * 0120 * @param p use this dialog to report progress to the user 0121 */ 0122 void processFiles(ProgressDialog *p); 0123 0124 /** undo all files 0125 * 0126 * processFiles has to be called before 0127 * 0128 * A previous renaming operation will be undone. 0129 * 0130 * Output will be reported through a progress dialog 0131 * 0132 * @param p use this dialog to report progress to the user 0133 */ 0134 void undoFiles(ProgressDialog *p); 0135 0136 /** Build the destination url from a KRenameFile 0137 * 0138 * @param file a KRenameFile 0139 * @returns a valid QUrl 0140 */ 0141 const QUrl buildDestinationUrl(const KRenameFile &file) const; 0142 0143 inline void setUndoScript(const QString &t) 0144 { 0145 m_undoScript = t; 0146 } 0147 inline void setUndo(bool b) 0148 { 0149 undo = b; 0150 } 0151 0152 inline void setReplaceList(const QList<TReplaceItem> &r) 0153 { 0154 m_replace = r; 0155 } 0156 inline const QList<TReplaceItem> &replaceList() const 0157 { 0158 return m_replace; 0159 } 0160 0161 inline void setMode(int m) 0162 { 0163 m_mode = m; 0164 } 0165 inline int mode() const 0166 { 0167 return m_mode; 0168 } 0169 0170 QString findToken(const QString &oldname, QString token, int i); 0171 QString findPartStrings(QString oldname, QString token); 0172 static QString findDirName(QString token, QString path); 0173 0174 /** 0175 * Replace the token [dirsep] with a slash "/". 0176 * This token is useful to create directories from within regular expressions. 0177 */ 0178 static QString findDirSep(const QString &token, const QString &path); 0179 0180 static QString &doEscape(QString &text); 0181 static QString &unEscape(QString &text); 0182 static void escape(QString &text, const QString &token, const QString &sequence); 0183 0184 /** Capitalize a string. 0185 * 0186 * Used to implement the * token. 0187 * 0188 * @param a text string 0189 * @return a capitalized version of this string (every first letter is a capital letter now) 0190 */ 0191 QString capitalize(const QString &text) const; 0192 0193 /** Handle the [length] tokens 0194 * 0195 * @param token a token found in square brackets 0196 * @param name the filename of the current file 0197 * 0198 * @return an empty QString if no length token was found or the new string 0199 */ 0200 QString findLength(const QString &token, const QString &name); 0201 0202 /** Handle the [trimmed] token 0203 * 0204 * @param token a token found in square brackets 0205 * @param name the filename of the current file 0206 * @param index index of the current file 0207 * 0208 * @return an empty QString if no length token was found or the new string 0209 */ 0210 QString findTrimmed(const QString &token, const QString &name, int index); 0211 0212 QString processString(QString text, const QString &originalName, int i, bool doFindReplace = true); 0213 QString processBrackets(QString text, int *length, const QString &oldname, int index); 0214 QString processNumber(int length, const QString &appendix); 0215 QString processToken(const QString &token, const QString &oldname, int i); 0216 0217 public Q_SLOTS: 0218 0219 /** Sets the current mode of renaming. 0220 * KRename can rename files, move them while 0221 * renaming to another directory, rename copies 0222 * or create renamed sym-links. 0223 * 0224 * This mode specifies what should be done with the files. 0225 * 0226 * @param mode the renaming mode. 0227 */ 0228 inline void setRenameMode(ERenameMode mode); 0229 0230 /** Sets the template for the filename that is used 0231 * to transform the filename to its final representation. 0232 * 0233 * @param t the new template 0234 */ 0235 inline void setFilenameTemplate(const QString &t); 0236 0237 /** Sets the template for the filename that is used 0238 * to transform the filename to its final representation. 0239 * 0240 * @param t the new template 0241 */ 0242 inline void setExtensionTemplate(const QString &t); 0243 0244 /** Set the start index for the basic counters 0245 * which do not specify an own start index in their 0246 * appendiy (e.g. ###{7}, means 7 is the start index 0247 * 0248 * @param i start index 0249 */ 0250 inline void setNumberStartIndex(int i) 0251 { 0252 m_index = i; 0253 } 0254 0255 /** Set the stepping for the basic counters 0256 * which do not specify an own stepping in their 0257 * appendiy (e.g. ###{1,2}, means 2 is the stepping 0258 * 0259 * @param s stepping 0260 */ 0261 inline void setNumberStepping(int s) 0262 { 0263 m_step = s; 0264 } 0265 0266 /** Sets whether all counters should be reset for new 0267 * directories 0268 * 0269 * @param r if true counters will be reset 0270 */ 0271 inline void setNumberReset(bool r) 0272 { 0273 m_reset = r; 0274 } 0275 0276 /** Sets the list of numbers that are skipped by counters 0277 * 0278 * @param s a list of numbers that is skipped 0279 */ 0280 inline void setNumberSkipList(const QList<int> &s) 0281 { 0282 m_skip = s; 0283 } 0284 0285 /** Sets if existing files maybe overwritten during renaming 0286 * 0287 * @param overwrite if true existing files will be overwritten 0288 */ 0289 inline void setOverwriteExistingFiles(bool overwrite) 0290 { 0291 m_overwrite = overwrite; 0292 } 0293 0294 /** Sets the destination url (a directory) for copy, move and link operations 0295 * 0296 * @param url destination directory 0297 */ 0298 inline void setDestinationDir(const QUrl &url) 0299 { 0300 m_destination = url; 0301 } 0302 0303 private: 0304 /** Do find and replace on the final resulting filename. 0305 * 0306 * \param text the new final filename with all other changes applied. 0307 * 0308 * \returns the new filename with all find and replace being done. 0309 * 0310 * \see m_replace 0311 */ 0312 QString findReplace(const QString &text, const QString &origFilename, int index); 0313 0314 /** 0315 * Replace one string (which might be a regular expression) in the final filename 0316 * with another string and return a new filename. 0317 * 0318 * \param text the new final filename with all other changes applied. 0319 * \param find the string or regular expression to find 0320 * \param replace replace a matched string with this value 0321 * \param reg if true treat find as regular expression 0322 * \param doProcessTokens process tokens in replaced results 0323 * \param originalName original filename for replacing tokens 0324 * \param index current index 0325 * 0326 * \returns the new filename with find and replace being done. 0327 */ 0328 QString doReplace(const QString &text, const QString &find, const QString &replace, 0329 bool reg, bool doProcessTokens, const QString &origFilename, int index); 0330 0331 private: 0332 /** Execute all plugins of a certain type 0333 * 0334 * @param index the current index 0335 * @param filenameOrPath the current filename or path 0336 * @param type the type of the plugins to run 0337 * @param errorCount the number of errors will be written to this value 0338 * @param p dialog for error reporting (maybe NULL) 0339 * 0340 * @returns either a new filename or an error message (depends on plugin type) 0341 */ 0342 QString executePlugin(int index, const QString &filenameOrPath, int type, int &errorCount, ProgressDialog *p); 0343 0344 void work(ProgressDialog *p); 0345 void writeUndoScript(QTextStream *t); 0346 0347 /** 0348 * Parse a new filename and create missing subdirectories. 0349 * 0350 * This will look for '/' and create all not existing directories 0351 * 0352 * @param destUrl to check for not existing directories 0353 * @param dialog ProgressDialog for error reporting 0354 */ 0355 void createMissingSubDirs(const QUrl &destUrl, ProgressDialog *dialog); 0356 0357 /** resets all counters to there start value if the directory name at @p i 0358 * in m_files changes. 0359 * The caller has to check m_reset before calling this function. 0360 */ 0361 void findCounterReset(int i); 0362 0363 QString text; // template 0364 QString extext; // Extension template 0365 QString m_undoScript; // Filename of undoscript 0366 bool undo; // create an undo script 0367 bool m_reset; // reset counter on new directories 0368 int m_mode; // renaming mode 0369 QList<int> m_skip; // Numbers to skip 0370 0371 // a is used in find number and 0372 // required for skipping. 0373 int m_counter_index; 0374 int m_index; // index for numbers 0375 int m_step; // step for numbers 0376 0377 QList<tCounterValues> m_counters; 0378 0379 private: 0380 KRenameFile::List *m_files; ///< The list of files to rename and the resulting renamed filenames 0381 ERenameMode m_renameMode; ///< The rename mode specifies if files are renamed, copied or moved (or linked) 0382 bool m_overwrite; ///< Overwrite existing files 0383 QUrl m_destination; ///< Destination directory for copy, move and link 0384 0385 QList<TReplaceItem> m_replace; ///< List of strings for find and replace 0386 0387 protected: 0388 QFile *f; 0389 QTime t; 0390 QProgressDialog *progress; 0391 }; 0392 0393 void BatchRenamer::setFiles(KRenameFile::List *list) 0394 { 0395 m_files = list; 0396 } 0397 0398 const KRenameFile::List *BatchRenamer::files() const 0399 { 0400 return m_files; 0401 } 0402 0403 void BatchRenamer::setRenameMode(ERenameMode mode) 0404 { 0405 m_renameMode = mode; 0406 } 0407 0408 ERenameMode BatchRenamer::renameMode() const 0409 { 0410 return m_renameMode; 0411 } 0412 0413 void BatchRenamer::setFilenameTemplate(const QString &t) 0414 { 0415 text = t; 0416 } 0417 0418 void BatchRenamer::setExtensionTemplate(const QString &t) 0419 { 0420 extext = t; 0421 } 0422 0423 int BatchRenamer::numberStartIndex() const 0424 { 0425 return m_index; 0426 } 0427 0428 int BatchRenamer::numberStepping() const 0429 { 0430 return m_step; 0431 } 0432 0433 int BatchRenamer::numberReset() const 0434 { 0435 return m_reset; 0436 } 0437 0438 QList<int> BatchRenamer::numberSkipList() const 0439 { 0440 return m_skip; 0441 } 0442 0443 #endif