File indexing completed on 2024-04-14 15:51:31

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