├── pics
└── QRenamer.rc
├── installer
├── genInstaller.bat
├── packages
│ └── main.component
│ │ └── meta
│ │ ├── package.xml
│ │ ├── LGPL_EXCEPTION.txt
│ │ └── installscript.qs
├── config
│ └── config.xml
└── readme.txt
├── js.qrc
├── .gitignore
├── js
└── globalConstant.js
├── qml
├── BackButton.qml
├── filter
│ ├── RemoveFilter.qml
│ ├── Exclude.qml
│ └── Include.qml
├── ButtonDelegate.qml
├── Miscellaneous.qml
├── Main.qml
├── FilterList.qml
├── qml.qrc
├── methods
│ ├── AppendWords.qml
│ ├── PrependWords.qml
│ ├── ReplaceWords.qml
│ ├── ReplaceSuffix.qml
│ ├── RemoveWords.qml
│ ├── InsertWords.qml
│ ├── PrependZeroOnNum.qml
│ ├── RegexGlobalModifier.qml
│ ├── RegexUsingCaptures.qml
│ └── RegexNumbering.qml
├── miscellaneous
│ ├── SpanHeader.qml
│ └── AddFolderRecursive.qml
├── ListStackView.qml
├── MethodsList.qml
├── TutorialSteps.qml
├── RainingParticle.qml
└── StepLabel.qml
├── utility
├── initializer.cpp
├── quickCloseSignal.cpp
├── initializer.hpp
├── quickCloseSignal.hpp
├── stringUtility.hpp
└── stringUtility.cpp
├── globalconst.hpp
├── readme.txt
├── main.cpp
├── help_pics.qrc
├── ui
├── numberStep.hpp
├── filterDialog.hpp
├── numberStep.cpp
├── filterDialog.cpp
├── numberstep.ui
├── MainWindow.hpp
├── filterDialog.ui
├── MainWindow.cpp
└── MainWindow.ui
├── model
├── fileModelItem.hpp
├── fileModelItem.cpp
├── fileNameModel.hpp
└── fileNameModel.cpp
├── workerThreads
├── addDirThread.hpp
├── scanDirThread.cpp
├── addDirThread.cpp
├── scanDirThread.hpp
├── renameFileThread.hpp
└── renameFileThread.cpp
├── modelProxy
├── sortAndFilterFile.hpp
└── sortAndFilterFile.cpp
├── LGPL_EXCEPTION.txt
├── QRenamer.pro
└── pics.qrc
/pics/QRenamer.rc:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON DISCARDABLE "macro_names.ico"
--------------------------------------------------------------------------------
/installer/genInstaller.bat:
--------------------------------------------------------------------------------
1 | binarycreator --offline-only -c config/config.xml -p packages QRenamer
--------------------------------------------------------------------------------
/js.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | js/globalConstant.js
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.db
2 | *.autosave
3 | *.user
4 | Makefile
5 | *.Debug
6 | *.Release
7 | *.5pre1
8 | *.pro.user
9 | pics
10 |
--------------------------------------------------------------------------------
/js/globalConstant.js:
--------------------------------------------------------------------------------
1 | .pragma library
2 |
3 | var global_const = {
4 |
5 | list_view_foot_height: function(){
6 | return 40;
7 | }
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/qml/BackButton.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 |
4 | Item {
5 | width: parent.width
6 | height :parent.height
7 |
8 | Button {
9 | anchors.fill: parent
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/utility/initializer.cpp:
--------------------------------------------------------------------------------
1 | #include "initializer.hpp"
2 |
3 | #include
4 | #include
5 |
6 | std::vector initialize_vector_index(int size)
7 | {
8 | std::vector result(size);
9 | std::iota(std::begin(result), std::end(result), 0);
10 |
11 | return result;
12 | }
13 |
--------------------------------------------------------------------------------
/globalconst.hpp:
--------------------------------------------------------------------------------
1 | #ifndef GLOBALCONST_HPP
2 | #define GLOBALCONST_HPP
3 |
4 | enum class fileNameHeader{
5 | Path, OldName, NewName,
6 | OldSuffix, NewSuffix,
7 | LastElem
8 | };
9 |
10 | enum class filterType{
11 | Exclude, Include
12 | };
13 |
14 | enum class RenameType{
15 | Base, Suffix, BaseAndSuffix
16 | };
17 |
18 | #endif // GLOBALCONST_HPP
19 |
20 |
--------------------------------------------------------------------------------
/utility/quickCloseSignal.cpp:
--------------------------------------------------------------------------------
1 | #include "quickCloseSignal.hpp"
2 |
3 | quickCloseSignal::quickCloseSignal(QWidget *parent) :
4 | QQuickWidget(parent)
5 | {
6 |
7 | }
8 |
9 | quickCloseSignal::~quickCloseSignal()
10 | {
11 |
12 | }
13 |
14 | void quickCloseSignal::closeEvent(QCloseEvent *event)
15 | {
16 | event->accept();
17 | emit widget_close();
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/utility/initializer.hpp:
--------------------------------------------------------------------------------
1 | #ifndef INITIALIZER_HPP
2 | #define INITIALIZER_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | template
10 | std::vector generate_vector_index(int size, T initial_value = {})
11 | {
12 | std::vector result(size);
13 | std::iota(std::begin(result), std::end(result), initial_value);
14 |
15 | return result;
16 | }
17 |
18 | #endif // INITIALIZER_HPP
19 |
--------------------------------------------------------------------------------
/utility/quickCloseSignal.hpp:
--------------------------------------------------------------------------------
1 | #ifndef QUICKCLOSESIGNAL_H
2 | #define QUICKCLOSESIGNAL_H
3 |
4 | #include
5 |
6 | class quickCloseSignal : public QQuickWidget
7 | {
8 | Q_OBJECT
9 | public:
10 | explicit quickCloseSignal(QWidget *parent = nullptr);
11 | ~quickCloseSignal();
12 |
13 | signals:
14 | void widget_close();
15 |
16 | protected:
17 | void closeEvent(QCloseEvent *event) override;
18 | };
19 |
20 | #endif // QUICKCLOSESIGNAL_H
21 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | This app is not for sale or commercial purpose
2 |
3 | All of the icons are come from
4 | http://www.fatcow.com/free-icons
5 |
6 | You can download the icons use by this app from
7 | https://mega.nz/#!UslFiYQJ!-eNluUhjH5S2XBlpep5RdZZ8aGYJwqgWDBXvxh5dmOA
8 | and place it in the pics folder, this way the Qt resource
9 | system should be able to find the pics
10 |
11 | All of the icons are not for commercial use, please follow the license of http://www.fatcow.com/free-icons
--------------------------------------------------------------------------------
/installer/packages/main.component/meta/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Main component
4 | Install Main component
5 | 1.0.0
6 | 2015-05-28
7 |
8 |
9 |
10 | true
11 |
12 | true
13 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "MainWindow.hpp"
2 | #include
3 | #include
4 | #include
5 |
6 | #include
7 |
8 | int main(int argc, char *argv[])
9 | {
10 | QApplication a(argc, argv);
11 |
12 | try{
13 | MainWindow w;
14 | w.show();
15 |
16 | return a.exec();
17 | }catch(std::exception const &ex){
18 | QMessageBox::critical(nullptr, QObject::tr("Error"),
19 | QObject::tr(ex.what()));
20 |
21 | return -1;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/help_pics.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | helps/pics/methods/appendWords00.png
4 | helps/pics/methods/selectFolder.png
5 | helps/pics/methods/appendWords01.png
6 | helps/pics/methods/renameFiles.png
7 | helps/pics/methods/prependWords00.png
8 | helps/pics/methods/prependWords01.png
9 | helps/pics/methods/replaceWords00.png
10 | helps/pics/methods/replaceWords01.png
11 |
12 |
13 |
--------------------------------------------------------------------------------
/installer/config/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | QRenamer
4 | 1.0.0
5 | QRenamer
6 | Tham Ngap Wei
7 |
8 | macro_names
9 | macro_names
10 | QRenamer
11 | @HomeDir@/QRenamer
12 | maintenanceTool
13 |
--------------------------------------------------------------------------------
/installer/readme.txt:
--------------------------------------------------------------------------------
1 | How to generate the installer for windows :
2 |
3 | 1 : download the pics from the mega link(https://mega.nz/#!UslFiYQJ!-eNluUhjH5S2XBlpep5RdZZ8aGYJwqgWDBXvxh5dmOA)
4 | unzip it and place the icon "macro_names.ico" under the folder "installer/config"
5 |
6 | 2 : Install the Qt installer(version 2.0 or above)
7 |
8 | 3 : setup the environment path of Qt installer(ex : C:\Qt\QtIFW2.0.1\bin)
9 |
10 | 4 : create a "data" folder under "installer/packages/main.component"
11 |
12 | 5 : copy the QRenamer.exe under the folder "data"
13 |
14 | 6 : open command prompt and enter the command "windeployqt QRenamer.exe"(make sure you setup the path before)
15 |
16 | 7 : double click the "genInstaller.bat" under the folder "installer"
17 |
18 | 8 : done
--------------------------------------------------------------------------------
/ui/numberStep.hpp:
--------------------------------------------------------------------------------
1 | #ifndef NUMBERSTEP_HPP
2 | #define NUMBERSTEP_HPP
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class numberStep;
8 | }
9 |
10 | class numberStep : public QDialog
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit numberStep(QWidget *parent = 0);
16 | ~numberStep();
17 |
18 | int increment() const Q_DECL_NOEXCEPT;
19 | QString pad() const Q_DECL_NOEXCEPT;
20 | int reset() const Q_DECL_NOEXCEPT;
21 | int start() const Q_DECL_NOEXCEPT;
22 |
23 | signals:
24 | void ok_button_clicked();
25 |
26 | private slots:
27 | void on_cancelPushButton_clicked();
28 |
29 | void on_okPushButton_clicked();
30 |
31 | void on_numPadLineEdit_textEdited(const QString &arg1);
32 |
33 | private:
34 | Ui::numberStep *ui;
35 | };
36 |
37 | #endif // NUMBERSTEP_HPP
38 |
--------------------------------------------------------------------------------
/model/fileModelItem.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FILEMODELITEM_HPP
2 | #define FILEMODELITEM_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class fileModelItem
10 | {
11 | public:
12 | fileModelItem();
13 | ~fileModelItem();
14 |
15 | void add_new_file();
16 | void add_new_file(QString const &input);
17 |
18 | void remove_at(int row);
19 |
20 | QStringList dir_paths_;
21 | QStringList insert_file_name_;
22 | QStringList new_base_name_;
23 | QStringList new_suffix_;
24 | QStringList old_file_name_complete_;
25 | QStringList old_suffix_;
26 | QStringList old_base_name_;
27 |
28 | std::vector source_indexes_;
29 | QVector match_regex_file_;
30 | };
31 |
32 | #endif // FILEMODELITEM_HPP
33 |
--------------------------------------------------------------------------------
/workerThreads/addDirThread.hpp:
--------------------------------------------------------------------------------
1 | #ifndef ADDDIRTHREAD_HPP
2 | #define ADDDIRTHREAD_HPP
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | class addDirThread : public QThread
11 | {
12 | Q_OBJECT
13 | public:
14 | explicit addDirThread(QObject *parent = nullptr);
15 | addDirThread(addDirThread const&) = delete;
16 | addDirThread& operator=(addDirThread const&) = delete;
17 |
18 | QStringList get_old_file_name_complete() const;
19 |
20 | void set_dirs_to_scan(QStringList dirs);
21 |
22 | signals:
23 | void end();
24 | void increment(int value);
25 |
26 | private:
27 | void run() override;
28 |
29 | private:
30 | QStringList old_file_name_complete_;
31 |
32 | QStringList dirs_to_scan_;
33 | };
34 |
35 | #endif // ADDDIRTHREAD_HPP
36 |
--------------------------------------------------------------------------------
/qml/filter/RemoveFilter.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: filter_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the Remove filter icons";
18 | img: "../pics/filter/removeFitler00.png"
19 | img_details: "
20 | - The filter you apply before will be removed
21 | - You cannot press on this icon if you have not apply any filter
22 | - You can press the short cut \"F6\" to remove the filter too
23 |
"}
24 | }
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/qml/ButtonDelegate.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | Item {
4 | id: root
5 | width: parent.width
6 | height: 88
7 |
8 | property alias text: textitem.text
9 | signal clicked
10 |
11 | Rectangle {
12 | anchors.fill: parent
13 | color: "#11ffffff"
14 | visible: mouse.pressed
15 | }
16 |
17 | Text {
18 | id: textitem
19 | color: "white"
20 | font.pixelSize: 32
21 | text: modelData
22 | anchors.verticalCenter: parent.verticalCenter
23 | anchors.left: parent.left
24 | anchors.leftMargin: 30
25 | }
26 |
27 | Rectangle {
28 | anchors.left: parent.left
29 | anchors.right: parent.right
30 | anchors.margins: 15
31 | height: 1
32 | color: "#424246"
33 | }
34 |
35 | MouseArea {
36 | id: mouse
37 | anchors.fill: parent
38 | onClicked: root.clicked()
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/ui/filterDialog.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FILTERDIALOG_HPP
2 | #define FILTERDIALOG_HPP
3 |
4 | #include
5 | #include
6 |
7 | namespace Ui {
8 | class filterDialog;
9 | }
10 |
11 | enum class fileNameHeader;
12 | enum class filterType;
13 |
14 | class filterDialog : public QDialog
15 | {
16 | Q_OBJECT
17 |
18 | public:
19 | explicit filterDialog(QWidget *parent = nullptr);
20 | ~filterDialog();
21 |
22 | fileNameHeader get_filter_column() const Q_DECL_NOEXCEPT;
23 | QString get_filter_string() const Q_DECL_NOEXCEPT;
24 | filterType get_filter_type() const Q_DECL_NOEXCEPT;
25 | QRegularExpression::PatternOption get_filter_pattern() const Q_DECL_NOEXCEPT;
26 |
27 | signals:
28 | void ok();
29 |
30 | private slots:
31 | void on_cancelPushButton_clicked();
32 |
33 | void on_okPushButton_clicked();
34 |
35 | private:
36 | Ui::filterDialog *ui;
37 | };
38 |
39 | #endif // FILTERDIALOG_HPP
40 |
--------------------------------------------------------------------------------
/workerThreads/scanDirThread.cpp:
--------------------------------------------------------------------------------
1 | #include "scanDirThread.hpp"
2 |
3 | #include
4 |
5 | scanDirThread::scanDirThread(QObject *parent) :
6 | QThread(parent)
7 | {
8 | }
9 |
10 | QStringList scanDirThread::get_result_dirs() const Q_DECL_NOEXCEPT
11 | {
12 | return result_dirs_;
13 | }
14 |
15 | /**
16 | * @brief setup the starting dir to scan
17 | * @param dir the starting dir to scan
18 | */
19 | void scanDirThread::set_scan_dir(const QString dir) Q_DECL_NOEXCEPT
20 | {
21 | dir_ = dir;
22 | }
23 |
24 | void scanDirThread::run()
25 | {
26 | QDirIterator directories(dir_,
27 | QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
28 | QStringList dirs;
29 | while(directories.hasNext()){
30 | directories.next();
31 | dirs.push_back(directories.filePath());
32 | emit scan_dir(directories.filePath(), 2000);
33 | }
34 |
35 | result_dirs_ = dirs;
36 | emit end();
37 | }
38 |
--------------------------------------------------------------------------------
/modelProxy/sortAndFilterFile.hpp:
--------------------------------------------------------------------------------
1 | #ifndef SORTANDFILTERFILE_HPP
2 | #define SORTANDFILTERFILE_HPP
3 |
4 | #include
5 |
6 | #include
7 |
8 | enum class fileNameHeader;
9 | enum class filterType;
10 |
11 | class QRegularExpression;
12 |
13 | class sortAndFilterFile : public QSortFilterProxyModel
14 | {
15 | public:
16 | explicit sortAndFilterFile(QObject *parent = nullptr);
17 | ~sortAndFilterFile();
18 |
19 | void set_filter_column(fileNameHeader header, bool invalidate = true);
20 | void set_filter_type(filterType type, bool invalidate = true);
21 | void set_regex(QRegularExpression reg, bool invalidate = true);
22 |
23 | protected:
24 | bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
25 | bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
26 |
27 | private:
28 | struct pimpl;
29 | std::unique_ptr impl_;
30 | };
31 |
32 | #endif // SORTANDFILTERFILE_HPP
33 |
--------------------------------------------------------------------------------
/workerThreads/addDirThread.cpp:
--------------------------------------------------------------------------------
1 | #include "addDirThread.hpp"
2 |
3 | #include
4 |
5 | addDirThread::addDirThread(QObject *parent) :
6 | QThread(parent)
7 | {
8 | }
9 |
10 | QStringList addDirThread::get_old_file_name_complete() const
11 | {
12 | return old_file_name_complete_;
13 | }
14 |
15 | void addDirThread::set_dirs_to_scan(const QStringList dirs)
16 | {
17 | dirs_to_scan_ = dirs;
18 | }
19 |
20 | void addDirThread::run()
21 | {
22 | QStringList old_file_name_complete;
23 | for(int i = 0, dir_size = dirs_to_scan_.size(); i != dir_size; ++i){
24 | QDir directory(dirs_to_scan_[i]);
25 | auto const file_infos = directory.entryInfoList({}, QDir::Files);
26 | for(int j = 0, file_size = file_infos.size(); j != file_size; ++j){
27 | old_file_name_complete.push_back(file_infos[j].absoluteFilePath());
28 | }
29 | emit increment(i);
30 | }
31 |
32 | old_file_name_complete_ = old_file_name_complete;
33 | emit end();
34 | }
35 |
--------------------------------------------------------------------------------
/workerThreads/scanDirThread.hpp:
--------------------------------------------------------------------------------
1 | #ifndef SCANDIRTHREAD_HPP
2 | #define SCANDIRTHREAD_HPP
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | class scanDirThread : public QThread
11 | {
12 | Q_OBJECT
13 | public:
14 | explicit scanDirThread(QObject *parent = nullptr);
15 | scanDirThread(scanDirThread const&) = delete;
16 | scanDirThread& operator=(scanDirThread const&) = delete;
17 |
18 | QStringList get_result_dirs() const Q_DECL_NOEXCEPT;
19 |
20 | void set_scan_dir(QString dir) Q_DECL_NOEXCEPT;
21 |
22 | signals:
23 | /**
24 | * @brief scan_dir this signal will emit when dir was scanned
25 | * @param dir scanned directory
26 | * @param msec The longest time(milli seconds) to show the message
27 | */
28 | void scan_dir(QString dir, int msec);
29 | void end();
30 |
31 | private:
32 | void run() override;
33 |
34 | private:
35 | QString dir_;
36 | QStringList result_dirs_;
37 | };
38 |
39 | #endif // SCANDIRTHREAD_HPP
40 |
--------------------------------------------------------------------------------
/qml/Miscellaneous.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 | import QtQuick.Layouts 1.1
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | gradient: Gradient {
10 | GradientStop { position: 0.0; color: "#f5baee" }
11 | GradientStop { position: 1.0; color: "#db44ca" }
12 | }
13 |
14 | ListModel {
15 | id: miscellaneous_page_model
16 | ListElement {
17 | title: "Add folder recursive"
18 | page: "qrc:/miscellaneous/AddFolderRecursive.qml"
19 | }
20 | ListElement {
21 | title: "Span header"
22 | page: "qrc:/miscellaneous/SpanHeader.qml"
23 | }
24 | ListElement {
25 | title: "Back"
26 | page: "qrc:/BackButton.qml"
27 | }
28 | }
29 |
30 | ListStackView{
31 | id: miscellaneous_stack_view
32 | anchors.fill: parent
33 | list_view_model: miscellaneous_page_model
34 | parent_stack_view: menu_stack_view
35 | }
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/qml/Main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 |
4 | Rectangle{
5 | width: 640
6 | height: 480
7 |
8 | gradient: Gradient {
9 | GradientStop { position: 0.0; color: "lightblue" }
10 | GradientStop { position: 1.0; color: "blue" }
11 | }
12 |
13 | ListModel {
14 | id: page_model
15 | ListElement {
16 | title: "Methods"
17 | page: "qrc:/MethodsList.qml"
18 | }
19 | ListElement {
20 | title: "Filter"
21 | page: "qrc:/FilterList.qml"
22 | }
23 | ListElement {
24 | title: "Miscellaneous"
25 | page: "qrc:/Miscellaneous.qml"
26 | }
27 | }
28 |
29 | ListStackView{
30 | id: menu_stack_view
31 | anchors.fill: parent
32 | list_view_model: page_model
33 | focus: true
34 | should_disable_raining_particle: false
35 | }
36 |
37 | RainingParticle{
38 | id: raining_particle
39 | anchors.fill: parent
40 | particle_source: "../pics/bullet_star.png"
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/qml/FilterList.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 | import QtQuick.Layouts 1.1
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | gradient: Gradient {
10 | GradientStop { position: 0.0; color: "tomato" }
11 | GradientStop { position: 1.0; color: "coral" }
12 | }
13 |
14 | ListModel {
15 | id: filter_page_model
16 | ListElement {
17 | title: "Exclude"
18 | page: "qrc:/filter/Exclude.qml"
19 | }
20 | ListElement {
21 | title: "Include"
22 | page: "qrc:/filter/Include.qml"
23 | }
24 | ListElement {
25 | title: "Remove filter"
26 | page: "qrc:/filter/RemoveFilter.qml"
27 | }
28 | ListElement {
29 | title: "Back"
30 | page: "qrc:/BackButton.qml"
31 | }
32 | }
33 |
34 | ListStackView{
35 | id: filter_stack_view
36 | anchors.fill: parent
37 | list_view_model: filter_page_model
38 | parent_stack_view: menu_stack_view
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/model/fileModelItem.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "fileModelItem.hpp"
4 |
5 | fileModelItem::fileModelItem()
6 | {
7 |
8 | }
9 |
10 | fileModelItem::~fileModelItem()
11 | {
12 |
13 | }
14 |
15 | void fileModelItem::add_new_file()
16 | {
17 | dir_paths_.push_back("");
18 | old_suffix_.push_back("");
19 | new_suffix_.push_back("");
20 | old_base_name_.push_back("");
21 | new_base_name_.push_back("");
22 | old_file_name_complete_.push_back("");
23 | }
24 |
25 | void fileModelItem::add_new_file(const QString &input)
26 | {
27 | QFileInfo const info(input);
28 | dir_paths_.push_back(info.absolutePath());
29 | old_suffix_.push_back(info.suffix());
30 | new_suffix_.push_back(old_suffix_.back());
31 | old_base_name_.push_back(info.completeBaseName());
32 | new_base_name_.push_back(old_base_name_.back());
33 | old_file_name_complete_.push_back(input);
34 | }
35 |
36 | void fileModelItem::remove_at(int row)
37 | {
38 | dir_paths_.removeAt(row);
39 | old_suffix_.removeAt(row);
40 | new_suffix_.removeAt(row);
41 | new_base_name_.removeAt(row);
42 | old_base_name_.removeAt(row);
43 | old_file_name_complete_.removeAt(row);
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/qml/qml.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | Main.qml
4 | MethodsList.qml
5 | ButtonDelegate.qml
6 | methods/AppendWords.qml
7 | BackButton.qml
8 | StepLabel.qml
9 | methods/PrependWords.qml
10 | methods/ReplaceWords.qml
11 | RainingParticle.qml
12 | methods/ReplaceSuffix.qml
13 | methods/RemoveWords.qml
14 | methods/InsertWords.qml
15 | methods/PrependZeroOnNum.qml
16 | methods/RegexUsingCaptures.qml
17 | methods/RegexNumbering.qml
18 | methods/RegexGlobalModifier.qml
19 | TutorialSteps.qml
20 | FilterList.qml
21 | ListStackView.qml
22 | filter/Exclude.qml
23 | filter/Include.qml
24 | filter/RemoveFilter.qml
25 | Miscellaneous.qml
26 | miscellaneous/AddFolderRecursive.qml
27 | miscellaneous/SpanHeader.qml
28 |
29 |
30 |
--------------------------------------------------------------------------------
/LGPL_EXCEPTION.txt:
--------------------------------------------------------------------------------
1 | Digia Qt LGPL Exception version 1.1
2 |
3 | As an additional permission to the GNU Lesser General Public License version
4 | 2.1, the object code form of a "work that uses the Library" may incorporate
5 | material from a header file that is part of the Library. You may distribute
6 | such object code under terms of your choice, provided that:
7 | (i) the header files of the Library have not been modified; and
8 | (ii) the incorporated material is limited to numerical parameters, data
9 | structure layouts, accessors, macros, inline functions and
10 | templates; and
11 | (iii) you comply with the terms of Section 6 of the GNU Lesser General
12 | Public License version 2.1.
13 |
14 | Moreover, you may apply this exception to a modified version of the Library,
15 | provided that such modification does not involve copying material from the
16 | Library into the modified Library's header files unless such material is
17 | limited to (i) numerical parameters; (ii) data structure layouts;
18 | (iii) accessors; and (iv) small macros, templates and inline functions of
19 | five lines or less in length.
20 |
21 | Furthermore, you are not required to apply this additional permission to a
22 | modified version of the Library.
23 |
--------------------------------------------------------------------------------
/qml/methods/AppendWords.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Append words";
19 | img: "../pics/methods/appendWords00.png"
20 | img_details: "This tag allow users to append words."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : Append the words";
25 | img: "../pics/methods/appendWords01.png"
26 | img_details: "Enter the words you want to append"}
27 | ListElement { help:"Step 4 : Rename the Files";
28 | img: "../pics/methods/renameFiles.png"
29 | img_details: "Click on the ok button to rename the files, if anything wrong,
30 | you can always revert the change with the revert button"}
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/qml/methods/PrependWords.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Prepend words";
19 | img: "../pics/methods/prependWords00.png"
20 | img_details: "This tag allow users to prepend words."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : prepend the words";
25 | img: "../pics/methods/prependWords01.png"
26 | img_details: "Enter the words you want to prepend"}
27 | ListElement { help:"Step 4 : Rename the Files";
28 | img: "../pics/methods/renameFiles.png"
29 | img_details: "Click on the ok button to rename the files, if anything wrong,
30 | you can always revert the change with the revert button"}
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/installer/packages/main.component/meta/LGPL_EXCEPTION.txt:
--------------------------------------------------------------------------------
1 | Digia Qt LGPL Exception version 1.1
2 |
3 | As an additional permission to the GNU Lesser General Public License version
4 | 2.1, the object code form of a "work that uses the Library" may incorporate
5 | material from a header file that is part of the Library. You may distribute
6 | such object code under terms of your choice, provided that:
7 | (i) the header files of the Library have not been modified; and
8 | (ii) the incorporated material is limited to numerical parameters, data
9 | structure layouts, accessors, macros, inline functions and
10 | templates; and
11 | (iii) you comply with the terms of Section 6 of the GNU Lesser General
12 | Public License version 2.1.
13 |
14 | Moreover, you may apply this exception to a modified version of the Library,
15 | provided that such modification does not involve copying material from the
16 | Library into the modified Library's header files unless such material is
17 | limited to (i) numerical parameters; (ii) data structure layouts;
18 | (iii) accessors; and (iv) small macros, templates and inline functions of
19 | five lines or less in length.
20 |
21 | Furthermore, you are not required to apply this additional permission to a
22 | modified version of the Library.
23 |
--------------------------------------------------------------------------------
/qml/methods/ReplaceWords.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Replace words";
19 | img: "../pics/methods/replaceWords00.png"
20 | img_details: "This tag allow users to replace words."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : Replace the words";
25 | img: "../pics/methods/replaceWords01.png"
26 | img_details: "Enter the words you want to replace"}
27 | ListElement { help:"Step 4 : Rename the Files";
28 | img: "../pics/methods/renameFiles.png"
29 | img_details: "Click on the ok button to rename the files, if anything wrong,
30 | you can always revert the change with the revert button"}
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/qml/methods/ReplaceSuffix.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Replace suffix";
19 | img: "../pics/methods/replaceSuffix00.png"
20 | img_details: "This tag allow users to replace suffix of files."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : Rename the suffix";
25 | img: "../pics/methods/replaceSuffix01.png"
26 | img_details: "Enter the new suffix you want to replace"}
27 | ListElement { help:"Step 4 : Rename the Files";
28 | img: "../pics/methods/renameFiles.png"
29 | img_details: "Click on the ok button to rename the files, if anything wrong,
30 | you can always revert the change with the revert button"}
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/utility/stringUtility.hpp:
--------------------------------------------------------------------------------
1 | #ifndef STRINGUTILITY_HPP
2 | #define STRINGUTILITY_HPP
3 |
4 | #include
5 | #include
6 |
7 | class QRegularExpression;
8 |
9 | QString prepend_symbol_on_match(QString const &old_file_name,
10 | int number_length,
11 | QRegularExpression const ®,
12 | QChar symbol);
13 |
14 | QStringList prepend_symbol_on_match(QStringList const &input,
15 | int number_length,
16 | QRegularExpression const ®,
17 | QChar symbol);
18 |
19 | QString prepend_symbol_on_nth_match(QString const &input,
20 | int number_length,
21 | int nth,
22 | QRegularExpression const ®,
23 | QChar symbol);
24 |
25 | QStringList prepend_symbol_on_nth_match(QStringList const &input,
26 | int number_length,
27 | int nth,
28 | QRegularExpression const ®,
29 | QChar symbol);
30 |
31 | #endif // STRINGUTILITY_HPP
32 |
--------------------------------------------------------------------------------
/qml/filter/Exclude.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: filter_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Filter files";
18 | img: "../pics/filter/filterSample.png"
19 | img_details: "Say you want to rename part of the files in the folder"}
20 |
21 | ListElement { help:"Step 1 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder"}
24 |
25 | ListElement { help:"Step 2 : Open filter";
26 | img: "../pics/filter/filterSelect.png"
27 | img_details: "Open the filter dialog"}
28 |
29 | ListElement { help:"Step 3 : Exclude files";
30 | img: "../pics/filter/filterExclude00.png"
31 | img_details: "Enter the key words you want to exclude(support regular expression)\n
32 | and select the Exclude circle"}
33 |
34 | ListElement { help:"Step 4 : Click ok";
35 | img: "../pics/filter/filterExclude01.png"
36 | img_details: "Click on the ok button to exclude the files,you can\n
37 | press on F6 to remove the filter."}
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/qml/filter/Include.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: filter_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Filter files";
18 | img: "../pics/filter/filterSample.png"
19 | img_details: "Say you want to rename part of the files in the folder"}
20 |
21 | ListElement { help:"Step 1 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder"}
24 |
25 | ListElement { help:"Step 2 : Open filter";
26 | img: "../pics/filter/filterSelect.png"
27 | img_details: "Open the filter dialog"}
28 |
29 | ListElement { help:"Step 3 : Include files";
30 | img: "../pics/filter/filterInclude00.png"
31 | img_details: "Enter the key words you want to include(support regular expression)\n
32 | and select the Include circle"}
33 |
34 | ListElement { help:"Step 4 : Click ok";
35 | img: "../pics/filter/filterInclude01.png"
36 | img_details: "Click on the ok button to include the files,you can\n
37 | press on F6 to remove the filter."}
38 | }
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/qml/miscellaneous/SpanHeader.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: miscellaneous_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"See the full contents of the Original name
18 | and New Name";
19 | img: "../pics/miscellaneous/spanHeader00.png"
20 | img_details: "Say the Original name and
21 | New name are too long,
22 | you can not see the whole text, you can use the span function to adjust the space"}
23 |
24 | ListElement { help:"Step 1 : Press the Span header icon";
25 | img: "../pics/miscellaneous/spanHeader01.png"
26 | img_details: "There are three ways to adjust the space
27 |
28 | - Click on the Span header icon
29 | - Press the shortcut button \"Ctrl+S\"
30 | - Drag on the header
31 |
"}
32 |
33 | ListElement { help:"Step 2 : Result after span";
34 | img: "../pics/miscellaneous/spanHeader02.png"
35 | img_details: "You can see the space of the headers are long enough to show the contents"}
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/qml/miscellaneous/AddFolderRecursive.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: miscellaneous_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Adding a lot of folders";
18 | img: "../pics/miscellaneous/addRecursiveFolder00.png"
19 | img_details: "Say you have a lot of folders want to add, it will be tedious
20 | if you have to add them one by one.
21 | If the folders have subfolders, things could go from bad to worse"}
22 |
23 | ListElement { help:"Step 1 : Press the add recursive folder icon";
24 | img: "../pics/miscellaneous/addRecursiveFolder01.png"
25 | img_details: "You can add the folder recursive by clicking on the recursive icons
26 | or press the shortcut \"F3\""}
27 |
28 | ListElement { help:"Step 2 : Add the folders recursive";
29 | img: "../pics/miscellaneous/addRecursiveFolder02.png"
30 | img_details: "Go into the folder you want to add recursively,
31 | then press the button Select Folder"}
32 |
33 | ListElement { help:"Step 3 : The results";
34 | img: "../pics/miscellaneous/addRecursiveFolder03.png"
35 | img_details: "All of the files under the folder will be added"}
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/qml/methods/RemoveWords.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Remove words";
19 | img: "../pics/methods/removeWords00.png"
20 | img_details: "This tag allow users to remove words."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : Select the position and range";
25 | img: "../pics/methods/removeWords01.png"
26 | img_details: "Enter the position you want to start to remove the words,
27 | then select the range(how many characters you want to remove).
28 | Example : if the RemoveAt is 0, range is 5, then the file [shirobako_001] will become [bako_001].
29 | If the RemoveAt is 1, range is 3, then the file [shirobako_001] will become [sobako_001]"}
30 | ListElement { help:"Step 4 : Rename the Files";
31 | img: "../pics/methods/renameFiles.png"
32 | img_details: "Click on the ok button to rename the files, if anything wrong,
33 | you can always revert the change with the revert button"}
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/QRenamer.pro:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------
2 | #
3 | # Project created by QtCreator 2014-01-13T18:58:57
4 | #
5 | #-------------------------------------------------
6 |
7 | QT += concurrent core gui quickwidgets quick
8 |
9 | CONFIG += c++17
10 |
11 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
12 |
13 | TARGET = QRenamer
14 | TEMPLATE = app
15 |
16 | win32{
17 | RC_FILE = pics/QRenamer.rc
18 | }
19 |
20 | #Release:DESTDIR = ../../Qt_apps
21 | INCLUDEPATH += ui
22 |
23 | SOURCES += main.cpp\
24 | ui/MainWindow.cpp \
25 | utility/stringUtility.cpp \
26 | workerThreads/renameFileThread.cpp \
27 | workerThreads/addDirThread.cpp \
28 | workerThreads/scanDirThread.cpp \
29 | model/fileNameModel.cpp \
30 | modelProxy/sortAndFilterFile.cpp \
31 | ui/filterDialog.cpp \
32 | ui/numberStep.cpp \
33 | utility/quickCloseSignal.cpp \
34 | model/fileModelItem.cpp
35 |
36 | HEADERS += ui/MainWindow.hpp \
37 | utility/stringUtility.hpp \
38 | workerThreads/renameFileThread.hpp \
39 | workerThreads/addDirThread.hpp \
40 | workerThreads/scanDirThread.hpp \
41 | model/fileNameModel.hpp \
42 | utility/initializer.hpp \
43 | modelProxy/sortAndFilterFile.hpp \
44 | ui/filterDialog.hpp \
45 | globalconst.hpp \
46 | ui/numberStep.hpp \
47 | utility/quickCloseSignal.hpp \
48 | model/fileModelItem.hpp
49 |
50 | FORMS += ui/MainWindow.ui \
51 | ui/filterDialog.ui \
52 | ui/numberstep.ui
53 |
54 | RESOURCES += \
55 | pics.qrc \
56 | qml/qml.qrc \
57 | js.qrc
58 |
--------------------------------------------------------------------------------
/qml/methods/InsertWords.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Insert words";
19 | img: "../pics/methods/insertWords00.png"
20 | img_details: "This tag allow users to insert words."}
21 | ListElement { help:"Step 2 : Select the folder";
22 | img: "../pics/methods/selectFolder.png"
23 | img_details: "This step will load the files in the folder."}
24 | ListElement { help:"Step 3 : Select the position to insert word";
25 | img: "../pics/methods/insertWords01.png"
26 | img_details: "Enter the position you want to insert the words"
27 | }
28 | ListElement { help:"Step 4 : Enter the words want to insert";
29 | img: "../pics/methods/insertWords02.png"
30 | img_details: "Enter the words you want to insert.
31 | Example : Remove At is 3, Insert Words is CowBoy, then [shirobako_001] will
32 | become [shiCowBoyrobako_001]"
33 | }
34 | ListElement { help:"Step 5 : Rename the Files";
35 | img: "../pics/methods/renameFiles.png"
36 | img_details: "Click on the ok button to rename the files, if anything wrong,
37 | you can always revert the change with the revert button"}
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/ui/numberStep.cpp:
--------------------------------------------------------------------------------
1 | #include "numberStep.hpp"
2 | #include "ui_numberstep.h"
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | numberStep::numberStep(QWidget *parent) :
10 | QDialog(parent),
11 | ui(new Ui::numberStep)
12 | {
13 | ui->setupUi(this);
14 | }
15 |
16 | numberStep::~numberStep()
17 | {
18 | delete ui;
19 | }
20 |
21 | int numberStep::increment() const Q_DECL_NOEXCEPT
22 | {
23 | return ui->numIncSpinBox->value();
24 | }
25 |
26 | QString numberStep::pad() const Q_DECL_NOEXCEPT
27 | {
28 | return ui->numPadLineEdit->text();
29 | }
30 |
31 | int numberStep::reset() const Q_DECL_NOEXCEPT
32 | {
33 | return ui->numResetSpinBox->value();
34 | }
35 |
36 | int numberStep::start() const Q_DECL_NOEXCEPT
37 | {
38 | return ui->numStartSpinBox->value();
39 | }
40 |
41 | void numberStep::on_cancelPushButton_clicked()
42 | {
43 | close();
44 | }
45 |
46 | void numberStep::on_okPushButton_clicked()
47 | {
48 | emit ok_button_clicked();
49 | }
50 |
51 | void numberStep::on_numPadLineEdit_textEdited(const QString &arg1)
52 | {
53 | if(!arg1.isEmpty()){
54 | auto const Target = arg1[0];
55 | auto const Func = [Target](decltype(Target) a){ return a == Target; };
56 | if(!std::all_of(std::begin(arg1), std::end(arg1), Func)){
57 | QMessageBox::warning(this, tr("Padding error"),
58 | tr("All of the padding characters should be the same"));
59 | auto replace = arg1;
60 | replace.replace(arg1[arg1.size() - 1], Target);
61 | ui->numPadLineEdit->setText(replace);
62 | }
63 | }else{
64 | QMessageBox::warning(this, tr("Padding error"), tr("Padding charaters should not be empty"));
65 | return;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/ui/filterDialog.cpp:
--------------------------------------------------------------------------------
1 | #include "filterDialog.hpp"
2 | #include "ui_filterDialog.h"
3 |
4 | #include "globalconst.hpp"
5 |
6 | filterDialog::filterDialog(QWidget *parent) :
7 | QDialog{parent},
8 | ui{new Ui::filterDialog}
9 | {
10 | ui->setupUi(this);
11 | }
12 |
13 | filterDialog::~filterDialog()
14 | {
15 | delete ui;
16 | }
17 |
18 | fileNameHeader filterDialog::get_filter_column() const Q_DECL_NOEXCEPT
19 | {
20 | if(ui->newNameRadioButton->isChecked()){
21 | return fileNameHeader::NewName;
22 | }else if(ui->originNameRadioButton->isChecked()){
23 | return fileNameHeader::OldName;
24 | }else if(ui->newSuffixRadioButton->isChecked()){
25 | return fileNameHeader::NewSuffix;
26 | }else if(ui->originSuffixRadioButton->isChecked()){
27 | return fileNameHeader::OldSuffix;
28 | }else if(ui->pathRadioButton->isChecked()){
29 | return fileNameHeader::Path;
30 | }
31 |
32 | return fileNameHeader::OldName;
33 | }
34 |
35 | QString filterDialog::get_filter_string() const Q_DECL_NOEXCEPT
36 | {
37 | return ui->FilterlineEdit->text();
38 | }
39 |
40 | filterType filterDialog::get_filter_type() const Q_DECL_NOEXCEPT
41 | {
42 | if(ui->excludeRadioButton->isChecked()){
43 | return filterType::Exclude;
44 | }else{
45 | return filterType::Include;
46 | }
47 | }
48 |
49 | QRegularExpression::PatternOption
50 | filterDialog::get_filter_pattern() const Q_DECL_NOEXCEPT
51 | {
52 | return ui->icaseCheckBox->isChecked() ?
53 | QRegularExpression::CaseInsensitiveOption :
54 | QRegularExpression::NoPatternOption;
55 | }
56 |
57 | void filterDialog::on_cancelPushButton_clicked()
58 | {
59 | close();
60 | }
61 |
62 | void filterDialog::on_okPushButton_clicked()
63 | {
64 | emit ok();
65 | }
66 |
--------------------------------------------------------------------------------
/qml/ListStackView.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 |
4 | FocusScope{
5 | width: parent.width
6 | height: parent.height
7 |
8 | property alias list_view_model: list_view.model
9 | property variant parent_stack_view
10 |
11 | property bool should_disable_raining_particle: true
12 |
13 | function pop(){
14 | stack_view.pop()
15 | }
16 |
17 | Item{
18 | width: parent.width
19 | height: parent.height
20 |
21 | StackView {
22 | id: stack_view
23 | anchors.fill: parent
24 | focus: true
25 |
26 | Keys.onReleased: if ((event.key === Qt.Key_Backspace)
27 | && stack_view.depth > 1) {
28 | stack_view.pop();
29 | raining_particle.emit_enabled = true
30 | event.accepted = true;
31 | }
32 |
33 | initialItem: Item {
34 | width: parent.width
35 | height: parent.height
36 | ListView {
37 | id: list_view
38 | anchors.fill: parent
39 | delegate: ButtonDelegate {
40 | text: title
41 |
42 | //onClicked: stack_view.push(Qt.resolvedUrl(page))
43 | onClicked: {
44 | if(title != "Back"){
45 | if(should_disable_raining_particle){
46 | raining_particle.emit_enabled = false;
47 | }
48 | stack_view.push(Qt.resolvedUrl(page));
49 | }else if(parent_stack_view){
50 | parent_stack_view.pop();
51 | }
52 | }
53 | }
54 | }
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/workerThreads/renameFileThread.hpp:
--------------------------------------------------------------------------------
1 | #ifndef RENAMEFILETHREAD_HPP
2 | #define RENAMEFILETHREAD_HPP
3 |
4 | #include
5 |
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | class renameFileWorker;
12 |
13 | class renameFileThread : public QThread
14 | {
15 | Q_OBJECT
16 | public:
17 | using Map = std::pair;
18 |
19 | explicit renameFileThread(QObject *parent = nullptr);
20 | renameFileThread& operator=(renameFileThread const &) = delete;
21 | renameFileThread(renameFileThread const&) = delete;
22 |
23 | void enable_revert(bool value = true) Q_DECL_NOEXCEPT;
24 |
25 | QStringList get_error_message() const Q_DECL_NOEXCEPT;
26 | Map get_revert_map() const Q_DECL_NOEXCEPT;
27 |
28 | void set_dirs_to_scan(QStringList dirs) Q_DECL_NOEXCEPT;
29 | void set_new_file_names(QStringList *new_file_names) Q_DECL_NOEXCEPT;
30 | void set_new_suffix(QStringList suffix) Q_DECL_NOEXCEPT;
31 | void set_old_file_names(QStringList old_file_names) Q_DECL_NOEXCEPT;
32 | void set_old_suffix(QStringList suffix) Q_DECL_NOEXCEPT;
33 | void set_source_indexes(std::vector const &indexes) Q_DECL_NOEXCEPT;
34 |
35 | void rename(int Row);
36 | signals:
37 | void end();
38 | void increment(int value);
39 |
40 | private:
41 | void run() override;
42 |
43 | private:
44 | QStringList dirs_to_scan_;
45 | bool enable_revert_;
46 | QStringList error_message_;
47 | QStringList *new_file_names_;
48 | QStringList new_suffix_;
49 | QStringList old_file_names_;
50 | QStringList old_suffix_;
51 | std::pair revert_map_;
52 |
53 | //if not revert, renameFileThread have to
54 | //build up the revert map and make sure the
55 | //indexes store the row number of source
56 | //but not the row number of proxy model
57 | //This is the reason why source_index_ exist
58 | std::vector const *source_indexes_;
59 | };
60 |
61 | #endif // RENAMEFILETHREAD_HPP
62 |
--------------------------------------------------------------------------------
/qml/MethodsList.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Controls 1.3
3 | import QtQuick.Layouts 1.1
4 | import "methods"
5 |
6 | Rectangle {
7 | width: parent.width
8 | height: parent.height
9 |
10 | gradient: Gradient {
11 | GradientStop { position: 0.0; color: "darkgreen" }
12 | GradientStop { position: 0.33; color: "green" }
13 | GradientStop { position: 1.0; color: "lightgreen" }
14 | }
15 |
16 | ListModel {
17 | id: method_page_model
18 | ListElement {
19 | title: "Append words"
20 | page: "qrc:/methods/AppendWords.qml"
21 | }
22 | ListElement {
23 | title: "Insert words"
24 | page: "qrc:/methods/InsertWords.qml"
25 | }
26 | ListElement {
27 | title: "Prepend words"
28 | page: "qrc:/methods/PrependWords.qml"
29 | }
30 | ListElement {
31 | title: "Prepend zero on number"
32 | page: "qrc:/methods/PrependZeroOnNum.qml"
33 | }
34 | ListElement {
35 | title: "Regex--Global modifier"
36 | page: "qrc:/methods/RegexGlobalModifier.qml"
37 | }
38 | ListElement {
39 | title: "Regex--Numbering files"
40 | page: "qrc:/methods/RegexNumbering.qml"
41 | }
42 | ListElement {
43 | title: "Regex--Using captures"
44 | page: "qrc:/methods/RegexUsingCaptures.qml"
45 | }
46 | ListElement {
47 | title: "Remove words"
48 | page: "qrc:/methods/RemoveWords.qml"
49 | }
50 | ListElement {
51 | title: "Replace suffix"
52 | page: "qrc:/methods/ReplaceSuffix.qml"
53 | }
54 | ListElement {
55 | title: "Replace words"
56 | page: "qrc:/methods/ReplaceWords.qml"
57 | }
58 | ListElement {
59 | title: "Back"
60 | page: "qrc:/BackButton.qml"
61 | }
62 | }
63 |
64 | ListStackView{
65 | id: method_stack_view
66 | anchors.fill: parent
67 | list_view_model: method_page_model
68 | parent_stack_view: menu_stack_view
69 | }
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/qml/TutorialSteps.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 | import "../js/globalConstant.js" as Global
5 |
6 | Item {
7 | width: parent.width
8 | height: parent.height
9 |
10 | property variant stack_view
11 | property alias model: list_view.model
12 |
13 | Rectangle{
14 | anchors.fill: parent
15 | gradient: Gradient {
16 | GradientStop { position: 0.0; color: "#4a4a4a" }
17 | GradientStop { position: 1.0; color: "#2b2b2b" }
18 | }
19 | }
20 |
21 | ListView {
22 | id: list_view
23 |
24 | anchors.fill: parent
25 |
26 | delegate: StepLabel{
27 | help_str: help
28 | img_src : img
29 | details : img_details
30 | }
31 |
32 | //model: tutorial //this model is come from the other methods(ex : AppendWords, PrependWords)
33 | footer: Rectangle{
34 | id: foot
35 | height: Global.global_const.list_view_foot_height()
36 | width: list_view.width
37 | color: "silver"
38 |
39 | Text{
40 | anchors.fill: parent
41 | text: "Back"
42 | horizontalAlignment: Text.AlignHCenter
43 | }
44 |
45 | MouseArea{
46 | anchors.fill: parent
47 | onClicked: {
48 | parent.state = "press";
49 | stack_view.pop();
50 | }
51 | onReleased: {
52 | raining_particle.emit_enabled = true;
53 | parent.state = ""
54 | }
55 | }
56 |
57 | states: [
58 | State {
59 | name: "press"
60 |
61 | PropertyChanges { target: foot; color: "blue"}
62 | }
63 | ]
64 |
65 | transitions: [
66 | Transition {
67 | ColorAnimation {
68 | to: "blue"
69 | duration: 500
70 | }
71 | }
72 | ]
73 | }
74 | }
75 | }
76 |
77 |
--------------------------------------------------------------------------------
/installer/packages/main.component/meta/installscript.qs:
--------------------------------------------------------------------------------
1 | /**************************************************************************
2 | **
3 | ** Copyright (C) 2015 The Qt Company Ltd.
4 | ** Contact: http://www.qt.io/licensing/
5 | **
6 | ** This file is part of the Qt Installer Framework.
7 | **
8 | ** $QT_BEGIN_LICENSE:LGPL$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see http://qt.io/terms-conditions. For further
15 | ** information use the contact form at http://www.qt.io/contact-us.
16 | **
17 | ** GNU Lesser General Public License Usage
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser
19 | ** General Public License version 2.1 or version 3 as published by the Free
20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 | ** following information to ensure the GNU Lesser General Public License
23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 | **
26 | ** As a special exception, The Qt Company gives you certain additional
27 | ** rights. These rights are described in The Qt Company LGPL Exception
28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 | **
30 | **
31 | ** $QT_END_LICENSE$
32 | **
33 | **************************************************************************/
34 |
35 | function Component()
36 | {
37 | // default constructor
38 | }
39 |
40 | Component.prototype.createOperations = function()
41 | {
42 | // call default implementation to actually install README.txt!
43 | component.createOperations();
44 |
45 | if (systemInfo.productType === "windows") {
46 | component.addOperation("CreateShortcut", "@TargetDir@/QRenamer.exe", "@StartMenuDir@/QRenamer.lnk",
47 | "workingDirectory=@TargetDir@");
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/qml/methods/PrependZeroOnNum.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Step 1 : Select the tag--
18 | Prepend zero on number";
19 | img: "../pics/methods/prependZeroOnNum00.png"
20 | img_details: "This tag allow users to prepend zero on number.
21 | ex : make [rockman_0] to [rockman_00]"}
22 |
23 | ListElement { help:"Step 2 : Select the folder";
24 | img: "../pics/methods/selectFolder.png"
25 | img_details: "This step will load the files in the folder."}
26 |
27 | ListElement { help:"Step 3a-1 : Select how many 0 you want to
28 | prepend on the last number";
29 | img: "../pics/methods/prependZeroOnNum01.png"
30 | img_details: "If you select 2(minimum is 1), [001_0] will become [001_00].
31 | If you select 3, [001_0] will become [001_000]"}
32 |
33 | ListElement { help:"Step 3b-1 : Change the box from
34 | last number to custom"
35 | img: "../pics/methods/prependZeroOnNum02.png"
36 | img_details: "This option will allow you to prepend 0 on specific number."}
37 |
38 | ListElement { help:"Step 3b-2 : Select the number you want to prepend zero"
39 | img: "../pics/methods/prependZeroOnNum03.png"
40 | img_details: "If you select Position as 1 on [001_0] and set the
41 | Number length as 4, the number will become [0001_0].
42 | If you select Position as 2 on [001_0] and set the
43 | Number length as 4, the number will become [001_0000].
"}
44 |
45 | ListElement { help:"Step 4 : Rename the Files";
46 | img: "../pics/methods/renameFiles.png"
47 | img_details: "Click on the ok button to rename the files, if anything wrong,
48 | you can always revert the change with the revert button"}
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/qml/methods/RegexGlobalModifier.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Changing special characters to underscore"
18 | img: "../pics/methods/regexGlobalModifier00.png"
19 | img_details: "Lets say your files have some evil spaces(a right royal pain
20 | in some cases), unwanted characters, and you want to replace them.
21 | In this case, we want to replace each space or # character with an underscore"}
22 |
23 | ListElement { help:"Step 1 : Select the tag--
24 | Regex"
25 | img: "../pics/methods/selectRegex.png"
26 | img_details: "This tag allow users to rename the files with regular expression."}
27 |
28 | ListElement { help:"Step 2 : Select the folder"
29 | img: "../pics/methods/selectFolder.png"
30 | img_details: "This step will load the files in the folder."}
31 |
32 | ListElement { help:"Step 3 : Captured the unwanted characters"
33 | img: "../pics/methods/regexGlobalModifier01.png"
34 | img_details: "Type the following regex in the Match field: [ #](match either a space or a # character)
"}
35 |
36 | ListElement { help:"Step 4 : Change the unwanted characters to \"_\""
37 | img: "../pics/methods/regexGlobalModifier02.png"
38 | img_details: "Type the following regex in the Replace field: [ #]
39 |
40 | - The files will be highlighted blue to indicate they match
41 | - The space and # will be removed from the filename in the preview column.
42 |
"}
43 |
44 | ListElement { help:"Step 5 : Rename the Files"
45 | img: "../pics/methods/renameFiles.png"
46 | img_details: "Click on the ok button to rename the files, if anything wrong,
47 | you can always revert the change with the revert button"}
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/qml/methods/RegexUsingCaptures.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import ".."
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Converting logfile dates(1)"
18 | img: "../pics/methods/regexUsingCaptures00.png"
19 | img_details: "Say you have a bunch of access logs with every day
20 | in the format: accesslog_dd_mm_yyyy.txt"}
21 |
22 | ListElement { help:"Converting logfile dates(2)"
23 | img: "../pics/methods/regexUsingCaptures01.png"
24 | img_details: "Using captures we can easily rename these files to a yyyy_mm_dd format"}
25 |
26 | ListElement { help:"Step 1 : Select the tag--
27 | Regex"
28 | img: "../pics/methods/selectRegex.png"
29 | img_details: "This tag allow users to rename the files with regular expression."}
30 |
31 | ListElement { help:"Step 2 : Select the folder"
32 | img: "../pics/methods/selectFolder.png"
33 | img_details: "This step will load the files in the folder."}
34 |
35 | ListElement { help:"Step 3 : Captured the format(dd_mm_yyyy)"
36 | img: "../pics/methods/regexUsingCaptures02.png"
37 | img_details: "Type the following regex in the Match field: (\d+)_(\d+)_(\d+)
38 |
39 | - The files will be highlighted blue to indicate they match
40 | - The numbers will be removed from the filename in the preview column.
41 |
"}
42 |
43 | ListElement { help:"Step 4 : Change the format"
44 | img: "../pics/methods/regexUsingCaptures03.png"
45 | img_details: "Type the following regex in the Replace field: \\3_\\2_\\1
46 | You will see the format of date change to yyyy_mm_dd"}
47 |
48 | ListElement { help:"Step 5 : Rename the Files"
49 | img: "../pics/methods/renameFiles.png"
50 | img_details: "Click on the ok button to rename the files, if anything wrong,
51 | you can always revert the change with the revert button"}
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/modelProxy/sortAndFilterFile.cpp:
--------------------------------------------------------------------------------
1 | #include "sortAndFilterFile.hpp"
2 |
3 | #include "globalconst.hpp"
4 |
5 | #include
6 |
7 | #include
8 | #include
9 |
10 | struct sortAndFilterFile::pimpl
11 | {
12 | pimpl();
13 |
14 | fileNameHeader filter_column_;
15 | filterType filter_type_;
16 | QRegularExpression reg_;
17 | };
18 |
19 | sortAndFilterFile::sortAndFilterFile(QObject *parent)
20 | : QSortFilterProxyModel(parent),
21 | impl_(new pimpl)
22 | {
23 | }
24 |
25 | sortAndFilterFile::~sortAndFilterFile()
26 | {
27 |
28 | }
29 |
30 | void sortAndFilterFile::set_filter_column(fileNameHeader header, bool invalidate)
31 | {
32 | impl_->filter_column_ = header;
33 | if(invalidate){
34 | invalidateFilter();
35 | }
36 | }
37 |
38 | void sortAndFilterFile::set_filter_type(filterType type, bool invalidate)
39 | {
40 | impl_->filter_type_ = type;
41 | if(invalidate){
42 | invalidateFilter();
43 | }
44 | }
45 |
46 | void sortAndFilterFile::set_regex(QRegularExpression reg, bool invalidate)
47 | {
48 | if(reg.isValid()){
49 | impl_->reg_ = std::move(reg);
50 | if(invalidate){
51 | invalidateFilter();
52 | }
53 | }
54 | }
55 |
56 | bool sortAndFilterFile::filterAcceptsRow(int source_row,
57 | const QModelIndex &source_parent) const
58 | {
59 | if(impl_->filter_column_ == fileNameHeader::LastElem){
60 | return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
61 | }
62 |
63 | auto const Col = static_cast(impl_->filter_column_);
64 | auto const Index = sourceModel()->index(source_row, Col, source_parent);
65 | auto const Data = sourceModel()->data(Index).value();
66 | if(impl_->reg_.match(Data).hasMatch()){
67 | if(impl_->filter_type_ == filterType::Include){
68 | return true;
69 | }else{
70 | return false;
71 | }
72 | }else{
73 | if(impl_->filter_type_ == filterType::Include){
74 | return false;
75 | }else{
76 | return true;
77 | }
78 | }
79 | }
80 |
81 | bool sortAndFilterFile::lessThan(const QModelIndex &left, const QModelIndex &right) const
82 | {
83 | auto const leftStr = sourceModel()->data(left).value();
84 | auto const rightStr = sourceModel()->data(right).value();
85 |
86 | return leftStr < rightStr;
87 | }
88 |
89 |
90 | sortAndFilterFile::pimpl::pimpl() :
91 | filter_column_(fileNameHeader::LastElem),
92 | filter_type_(filterType::Include)
93 | {
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/qml/methods/RegexNumbering.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import "../"
4 |
5 | Rectangle {
6 | width: parent.width
7 | height: parent.height
8 |
9 | TutorialSteps{
10 | anchors.fill: parent
11 | stack_view: method_stack_view
12 | model: tutorial
13 | }
14 |
15 | ListModel {
16 | id: tutorial
17 | ListElement { help:"Renaming photos"
18 | img: "../pics/methods/regexNumbering00.png"
19 | img_details: "If you have ever used a digital camera you’ll
20 | know they aren’t very creative when they name your files.
21 | With Cute Renamer, you can make these more descriptive"}
22 |
23 | ListElement { help:"Step 1 : Select the tag--
24 | Regex"
25 | img: "../pics/methods/selectRegex.png"
26 | img_details: "This tag allow users to rename the files with regular expression."}
27 |
28 | ListElement { help:"Step 2 : Select the folder"
29 | img: "../pics/methods/selectFolder.png"
30 | img_details: "This step will load the files in the folder."}
31 |
32 | ListElement { help:"Step 3 : Captured the number"
33 | img: "../pics/methods/regexNumbering01.png"
34 | img_details: "Type the following regex in the Match field: \d+
35 |
36 | - The files will be highlighted blue to indicate they match
37 | - The numbers will be removed from the filename in the preview column.
38 |
"}
39 |
40 | ListElement { help:"Step 4 : Change the number"
41 | img: "../pics/methods/regexNumbering02.png"
42 | img_details: "
43 |
44 | - Type the following regex in the Replace field: $#
45 | - Click on the Numbering circle
46 | - The new name column will now contain the new filenames with the
47 | default numbering settings
48 | - Note the order is still the same as the original filenames
49 |
"}
50 |
51 | ListElement { help:"Step 5(option) : Configure the number sequence"
52 | img: "../pics/methods/regexNumbering03.png"
53 | img_details: "The defaults are (start at 1, pad to 3 digits,
54 | increment by 1, don’t ever reset the sequence)"}
55 |
56 | ListElement { help:"Step 6 : Rename the Files"
57 | img: "../pics/methods/renameFiles.png"
58 | img_details: "Click on the ok button to rename the files, if anything wrong,
59 | you can always revert the change with the revert button"}
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/qml/RainingParticle.qml:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013, Juergen Bocklage-Ryannel, Johan Thelin
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are met:
7 | * * Redistributions of source code must retain the above copyright
8 | * notice, this list of conditions and the following disclaimer.
9 | * * Redistributions in binary form must reproduce the above copyright
10 | * notice, this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | * * Neither the name of the editors nor the
13 | * names of its contributors may be used to endorse or promote products
14 | * derived from this software without specific prior written permission.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 | */
27 |
28 | import QtQuick 2.0
29 | import QtQuick.Particles 2.0
30 |
31 | Item {
32 | id: root
33 | width: parent.width; height: parent.height
34 |
35 | property alias emit_enabled: emitter.enabled
36 | property alias particle_source: im_particle.source
37 |
38 | ParticleSystem {
39 | id: particleSystem
40 | }
41 |
42 | ImageParticle {
43 | id: im_particle
44 | system: particleSystem
45 | color: '#FFD700'
46 | opacity: 0.5
47 | colorVariation: 0.2
48 | rotation: 0
49 | rotationVariation: 45
50 | rotationVelocity: 15
51 | rotationVelocityVariation: 15
52 | entryEffect: ImageParticle.Scale
53 | }
54 |
55 | Emitter {
56 | id: emitter
57 | anchors.bottom: parent.top
58 | width: root.width; height: 1
59 | system: particleSystem
60 | lifeSpan: root.height * 10 + 50
61 | size: 32
62 | velocity: AngleDirection {
63 | angle: 90
64 | angleVariation: 15
65 | magnitude: root.height / 6
66 | magnitudeVariation: 50
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/pics.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | pics/add.png
4 | pics/delete.png
5 | pics/folder.png
6 | pics/clipboard_empty.png
7 | pics/folders_explorer.png
8 | pics/setting_tools.png
9 | pics/spanHeader.png
10 | pics/revert.png
11 | pics/filter.png
12 | pics/help.png
13 | pics/num_step.png
14 | pics/accept.png
15 | pics/cancel.png
16 | pics/filter_clear.png
17 | pics/bullet_star.png
18 | pics/methods/appendWords00.png
19 | pics/methods/appendWords01.png
20 | pics/methods/prependWords00.png
21 | pics/methods/prependWords01.png
22 | pics/methods/renameFiles.png
23 | pics/methods/replaceWords00.png
24 | pics/methods/replaceWords01.png
25 | pics/methods/selectFolder.png
26 | pics/methods/replaceSuffix00.png
27 | pics/methods/replaceSuffix01.png
28 | pics/methods/removeWords00.png
29 | pics/methods/removeWords01.png
30 | pics/methods/insertWords00.png
31 | pics/methods/insertWords01.png
32 | pics/methods/insertWords02.png
33 | pics/methods/prependZeroOnNum00.png
34 | pics/methods/prependZeroOnNum01.png
35 | pics/methods/prependZeroOnNum03.png
36 | pics/methods/regexUsingCaptures00.png
37 | pics/methods/regexUsingCaptures01.png
38 | pics/methods/regexUsingCaptures02.png
39 | pics/methods/regexUsingCaptures03.png
40 | pics/methods/selectRegex.png
41 | pics/methods/prependZeroOnNum02.png
42 | pics/app_icons.png
43 | pics/methods/regexNumbering00.png
44 | pics/methods/regexNumbering01.png
45 | pics/methods/regexNumbering02.png
46 | pics/methods/regexNumbering03.png
47 | pics/methods/regexGlobalModifier00.png
48 | pics/methods/regexGlobalModifier01.png
49 | pics/methods/regexGlobalModifier02.png
50 | pics/cross_reference.png
51 | pics/filter/filterExclude00.png
52 | pics/filter/filterExclude01.png
53 | pics/filter/filterInclude00.png
54 | pics/filter/filterInclude01.png
55 | pics/filter/filterSample.png
56 | pics/filter/filterSelect.png
57 | pics/filter/removeFitler00.png
58 | pics/miscellaneous/addRecursiveFolder00.png
59 | pics/miscellaneous/addRecursiveFolder01.png
60 | pics/miscellaneous/addRecursiveFolder02.png
61 | pics/miscellaneous/addRecursiveFolder03.png
62 | pics/miscellaneous/spanHeader00.png
63 | pics/miscellaneous/spanHeader01.png
64 | pics/miscellaneous/spanHeader02.png
65 | pics/macro_names.png
66 |
67 |
68 |
--------------------------------------------------------------------------------
/qml/StepLabel.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 |
3 | import "../js/globalConstant.js" as Global
4 |
5 | Rectangle {
6 | id : root
7 | width: parent.width
8 | height: 90
9 |
10 | property string details
11 | property string help_str
12 | property string img_src
13 |
14 | Rectangle {
15 | id: brief
16 | width: parent.width * 3 / 4
17 | height: parent.height
18 |
19 | anchors.left: parent.left
20 | anchors.right: parent.right
21 | anchors.top: parent.top
22 |
23 | color: "#333"
24 | border.color: Qt.lighter(color, 1.2)
25 | Text {
26 | id: help_text
27 |
28 | anchors.fill: parent
29 | font.pointSize: 12
30 | color: "white"
31 | text: help_str
32 | textFormat: Text.RichText
33 | }
34 | }
35 |
36 | Rectangle{
37 | id: image
38 |
39 | width: parent.width / 4
40 | height: parent.height
41 |
42 | anchors.right: brief.right
43 | anchors.top: parent.top
44 |
45 | color: "black"
46 |
47 | Image {
48 | anchors.fill: parent
49 |
50 | fillMode: Image.PreserveAspectFit
51 | source: img_src
52 | asynchronous: true
53 | }
54 | }
55 |
56 | MouseArea {
57 | anchors.fill: parent
58 | onClicked: {
59 | if(parent.state.length == 0){
60 | parent.state = "expanded"
61 | }else{
62 | parent.state = ""
63 | }
64 | }
65 | }
66 |
67 | Item {
68 | id: detailsView
69 |
70 | anchors.top: image.bottom
71 | anchors.left: parent.left
72 | anchors.right: parent.right
73 | anchors.bottom: parent.bottom
74 |
75 | opacity: 0
76 |
77 | Rectangle {
78 | anchors.fill: parent
79 |
80 | gradient: Gradient {
81 | GradientStop { position: 0.0; color: "#fcd978" }
82 | GradientStop { position: 1.0; color: "#fccc4f" }
83 | }
84 | border.color: "black"
85 | border.width: 2
86 |
87 | Text {
88 | anchors.fill: parent
89 | anchors.margins: 5
90 |
91 | clip: true
92 | wrapMode: Text.WordWrap
93 | color: "black"
94 | font.pixelSize: 12
95 | textFormat: Text.RichText
96 |
97 | text: details
98 | }
99 | }
100 | }
101 |
102 | states: [
103 | State {
104 | name: "expanded"
105 |
106 | PropertyChanges { target: root; height: list_view.height}
107 | PropertyChanges { target: image; width: list_view.width; height: list_view.height * 0.6; anchors.topMargin: 30 }
108 | PropertyChanges { target: detailsView; opacity: 1 }
109 | PropertyChanges { target: root.ListView.view; contentY: root.y; interactive: false }
110 | PropertyChanges { target: image; rotation: 360 }
111 | }
112 | ]
113 |
114 | transitions: [
115 | Transition {
116 | ParallelAnimation{
117 | NumberAnimation {
118 | duration: 200;
119 | properties: "height,width,rotation,anchors.topMargin,opacity,contentY"
120 | }
121 | }
122 | }
123 | ]
124 | }
125 |
126 |
--------------------------------------------------------------------------------
/workerThreads/renameFileThread.cpp:
--------------------------------------------------------------------------------
1 | #include "renameFileThread.hpp"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | renameFileThread::renameFileThread(QObject *parent) :
10 | QThread(parent),
11 | enable_revert_(false),
12 | new_file_names_(nullptr),
13 | source_indexes_(nullptr)
14 | {
15 | }
16 |
17 | /**
18 | * @brief setup the flag to indicate it is rename the\n
19 | * files or try to revert the renamed files
20 | *
21 | *
22 | * After the rename/revert process finish, the flag will be\n
23 | * set to false again automatic
24 | * @param value true : try to revert the renamed files;else false
25 | */
26 | void renameFileThread::enable_revert(bool value) Q_DECL_NOEXCEPT
27 | {
28 | enable_revert_ = value;
29 | }
30 |
31 | QStringList renameFileThread::get_error_message() const Q_DECL_NOEXCEPT
32 | {
33 | return error_message_;
34 | }
35 |
36 | renameFileThread::Map renameFileThread::get_revert_map() const Q_DECL_NOEXCEPT
37 | {
38 | return revert_map_;
39 | }
40 |
41 | void renameFileThread::set_dirs_to_scan(QStringList dirs) Q_DECL_NOEXCEPT
42 | {
43 | dirs_to_scan_ = dirs;
44 | }
45 |
46 | void renameFileThread::set_new_file_names(QStringList *new_file_names) Q_DECL_NOEXCEPT
47 | {
48 | new_file_names_ = new_file_names;
49 | }
50 |
51 | void renameFileThread::set_new_suffix(QStringList suffix) Q_DECL_NOEXCEPT
52 | {
53 | new_suffix_ = suffix;
54 | }
55 |
56 | void renameFileThread::set_old_file_names(QStringList old_file_names) Q_DECL_NOEXCEPT
57 | {
58 | old_file_names_ = old_file_names;
59 | }
60 |
61 | void renameFileThread::set_old_suffix(QStringList suffix) Q_DECL_NOEXCEPT
62 | {
63 | old_suffix_ = suffix;
64 | }
65 |
66 | void renameFileThread::set_source_indexes(std::vector const &indexes) Q_DECL_NOEXCEPT
67 | {
68 | source_indexes_ = &indexes;
69 | }
70 |
71 | void renameFileThread::rename(int Row)
72 | {
73 | auto const OldName = dirs_to_scan_[Row] + "/" +
74 | old_file_names_[Row] + "." +
75 | old_suffix_[Row];
76 | if(QFile::exists(OldName)){
77 | auto const NewName = dirs_to_scan_[Row] + "/" +
78 | (*new_file_names_)[Row] + "." + new_suffix_[Row];
79 | if(!QFile::exists(NewName)){
80 | if(OldName != NewName && QFile::rename(OldName, NewName)){
81 | revert_map_.first.push_back(NewName);
82 | revert_map_.second.push_back(OldName);
83 | }else{
84 | error_message_.push_back(NewName + " can not rename");
85 | }
86 | }
87 | }else{
88 | //(*new_file_names_)[Row] = old_file_names_[Row];
89 | error_message_.push_back(OldName + " do not exist");
90 | }
91 | }
92 |
93 | void renameFileThread::run()
94 | {
95 | error_message_.clear();
96 | revert_map_.first.clear();
97 | revert_map_.second.clear();
98 |
99 | if(!enable_revert_){
100 | for(decltype(source_indexes_->size()) i = 0; i
101 | != source_indexes_->size(); ++i){
102 | rename((*source_indexes_)[i].row());
103 | emit increment(static_cast(i));
104 | }
105 | }else{
106 | //if revert, the fileNameModel will setup
107 | //the mapping data into old_file_names and
108 | //new_file_names
109 | for(decltype(old_file_names_.size()) i = 0;
110 | i != old_file_names_.size(); ++i){
111 | rename(i);
112 | emit increment(i);
113 | }
114 | enable_revert_ = false;
115 | }
116 |
117 | emit end();
118 | }
119 |
--------------------------------------------------------------------------------
/model/fileNameModel.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FILENAMEMODEL_HPP
2 | #define FILENAMEMODEL_HPP
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | enum class fileNameHeader;
9 | enum class RenameType;
10 |
11 | class addDirThread;
12 | class fileModelItem;
13 | class QRegularExpression;
14 | class renameFileThread;
15 | class scanDirThread;
16 |
17 | /**
18 | * @brief The model in charge of file names manipulation
19 | *
20 | *
21 | * This class use QtConcurrent to process some string \n
22 | * but haven't do any benchmark yet.The main\n
23 | * reason I use it is because I want to get familiar with\n
24 | * the api of QtConcurrent but not performance.
25 | */
26 | class fileNameModel : public QAbstractTableModel
27 | {
28 | Q_OBJECT
29 |
30 | public:
31 | explicit fileNameModel(QObject *parent = nullptr);
32 | ~fileNameModel() override;
33 |
34 | void add_dirs_recursive(QString const &dir_path);
35 | void append_number_on_last_match(int length);
36 | void append_number_on_nth_match(int length, int position);
37 | void append_words(QString const &words);
38 | void change_name_with_increase_num(QString const &change_file_name_to, int zero_fill);
39 |
40 | int columnCount(const QModelIndex &parent) const override;
41 | void clear_all();
42 | void clear_match_regex_file();
43 |
44 | QVariant data(const QModelIndex &index, int role) const override;
45 | bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
46 | const QModelIndex &parent) override;
47 |
48 | Qt::ItemFlags flags(const QModelIndex &index) const override;
49 |
50 | QStringList get_rename_error_message() const Q_DECL_NOEXCEPT;
51 |
52 | QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
53 |
54 | void insert_at(int position, QString const &words);
55 | bool insertRows(int row, int count, const QModelIndex &parent) override;
56 |
57 | QStringList mimeTypes() const override;
58 |
59 | void numbering(int start, int increment, int reset, QString const &pad);
60 |
61 | void prepend_words(QString const &words);
62 |
63 | void remove_at(int position, int n);
64 | bool removeRow(int row, const QModelIndex &parent = QModelIndex());
65 | bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
66 | void rename_files();
67 | void replace_regex(QRegularExpression const &re, QString const &after);
68 | void replace_suffix(QString const &from, QString const &to);
69 | void replace_text(QString const &from, QString const &to);
70 | void revert_rename_result();
71 | int rowCount(const QModelIndex &parent = QModelIndex()) const override;
72 |
73 | bool setData(const QModelIndex &index, const QVariant &value, int role) override;
74 | void set_selected_index(std::vector &&indexes);
75 |
76 | void update_file(QStringList const &files);
77 |
78 | signals:
79 | void add_dirs_recursive_end();
80 | void drop_data(QStringList file);
81 | void increment(int);
82 | void rename_file_end();
83 | void scan_dir(QString dir, int msec);
84 | void set_size(int);
85 | void set_visible(bool);
86 |
87 | private slots:
88 | void add_dirs_recursive_end_slot();
89 | void rename_file_finished();
90 | void scan_dir_recursive_end_slot();
91 |
92 | private:
93 | void insert_data(QStringList const &input, fileNameHeader header);
94 | void insert_rows_if_needed(int current_size, int previous_size);
95 |
96 | private:
97 | QScopedPointer item_;
98 |
99 | addDirThread *add_dirs_thread_;
100 | renameFileThread *rename_file_thread_;
101 | scanDirThread *scan_dir_thread_;
102 | };
103 |
104 | #endif // FILENAMEMODEL_HPP
105 |
--------------------------------------------------------------------------------
/ui/numberstep.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | numberStep
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Numbering
15 |
16 |
17 |
18 | :/pics/num_step.png:/pics/num_step.png
19 |
20 |
21 | Numbering
22 |
23 |
24 | Numbering
25 |
26 |
27 | -
28 |
29 |
30 |
31 | 0
32 | 0
33 |
34 |
35 |
36 | Start
37 |
38 |
39 |
40 | -
41 |
42 |
43 | 999999
44 |
45 |
46 |
47 | -
48 |
49 |
50 | Pad
51 |
52 |
53 |
54 | -
55 |
56 |
57 | 99999
58 |
59 |
60 |
61 | -
62 |
63 |
64 | Reset
65 |
66 |
67 |
68 | -
69 |
70 |
71 | 1
72 |
73 |
74 | 99999
75 |
76 |
77 |
78 | -
79 |
80 |
81 | Inc
82 |
83 |
84 |
85 | -
86 |
87 |
88 | 0
89 |
90 |
91 |
92 | -
93 |
94 |
95 |
96 | 6
97 | 0
98 |
99 |
100 |
101 | Ok
102 |
103 |
104 | Ok
105 |
106 |
107 |
108 |
109 |
110 |
111 | :/pics/accept.png:/pics/accept.png
112 |
113 |
114 | Return
115 |
116 |
117 |
118 | -
119 |
120 |
121 | Cancel
122 |
123 |
124 | Cancel
125 |
126 |
127 |
128 |
129 |
130 |
131 | :/pics/cancel.png:/pics/cancel.png
132 |
133 |
134 | Esc
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
--------------------------------------------------------------------------------
/ui/MainWindow.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_HPP
2 | #define MAINWINDOW_HPP
3 |
4 | #include
5 | #include
6 |
7 | #include
8 | #include