1 /*
2     Copyright (C) 2017 Pedram Pourang (Tsu Jan) <tsujan2000@gmail.com>
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "bulkrename.h"
20 #include <QRegularExpression>
21 #include <QTimer>
22 #include <QPushButton>
23 #include <QMessageBox>
24 #include <QProgressDialog>
25 
26 #include <libfm-qt/utilities.h>
27 
28 namespace PCManFM {
29 
BulkRenameDialog(QWidget * parent,Qt::WindowFlags flags)30 BulkRenameDialog::BulkRenameDialog(QWidget* parent, Qt::WindowFlags flags) :
31     QDialog(parent, flags) {
32     ui.setupUi(this);
33     ui.lineEdit->setFocus();
34     connect(ui.buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &QDialog::accept);
35     connect(ui.buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked, this, &QDialog::reject);
36     resize(minimumSize());
37     setMaximumHeight(minimumHeight()); // no vertical resizing
38 }
39 
showEvent(QShowEvent * event)40 void BulkRenameDialog::showEvent(QShowEvent* event) {
41     QDialog::showEvent(event);
42     if(ui.lineEdit->text().endsWith(QLatin1Char('#'))) { // select what's before "#"
43         QTimer::singleShot(0, [this]() {
44             ui.lineEdit->setSelection(0, ui.lineEdit->text().size() - 1);
45         });
46     }
47 }
48 
BulkRenamer(const Fm::FileInfoList & files,QWidget * parent)49 BulkRenamer::BulkRenamer(const Fm::FileInfoList& files, QWidget* parent) {
50     if(files.size() <= 1) { // no bulk rename with just one file
51         return;
52     }
53     QString baseName;
54     int start = 0;
55     BulkRenameDialog dlg(parent);
56     switch(dlg.exec()) {
57     case QDialog::Accepted:
58         baseName = dlg.getBaseName();
59         start = dlg.getStart();
60         break;
61     default:
62         return;
63     }
64 
65     if(!baseName.contains(QLatin1Char('#'))) {
66         // insert "#" before the last dot
67         int end = baseName.lastIndexOf(QLatin1Char('.'));
68         if(end == -1) {
69             end = baseName.size();
70         }
71         baseName.insert(end, QLatin1Char('#'));
72     }
73     QProgressDialog progress(QObject::tr("Renaming files..."), QObject::tr("Abort"), 0, files.size(), parent);
74     progress.setWindowModality(Qt::WindowModal);
75     int i = 0, failed = 0;
76     const QRegularExpression extension(QStringLiteral("\\.[^.#]+$"));
77     bool noExtension(baseName.indexOf(extension) == -1);
78     for(auto& file: files) {
79         progress.setValue(i);
80         if(progress.wasCanceled()) {
81             progress.close();
82             QMessageBox::warning(parent, QObject::tr("Warning"), QObject::tr("Renaming is aborted."));
83             return;
84         }
85         // NOTE: "Edit name" seems to be the best way of handling non-UTF8 filename encoding.
86         auto fileName = QString::fromUtf8(g_file_info_get_edit_name(file->gFileInfo().get()));
87         if(fileName.isEmpty()) {
88             fileName = QString::fromStdString(file->name());
89         }
90         QString newName = baseName;
91 
92         // keep the extension if the new name doesn't have one
93         if(noExtension) {
94             QRegularExpressionMatch match;
95             if(fileName.indexOf(extension, 0, &match) > -1) {
96                 newName += match.captured();
97             }
98         }
99 
100         newName.replace(QLatin1Char('#'), QString::number(start + i));
101         if (newName == fileName || !Fm::changeFileName(file->path(), newName, nullptr, false)) {
102             ++failed;
103         }
104         ++i;
105     }
106     progress.setValue(i);
107     if(failed == i) {
108         QMessageBox::critical(parent, QObject::tr("Error"), QObject::tr("No file could be renamed."));
109     }
110     else if(failed > 0) {
111         QMessageBox::critical(parent, QObject::tr("Error"), QObject::tr("Some files could not be renamed."));
112     }
113 }
114 
115 BulkRenamer::~BulkRenamer() = default;
116 
117 } //namespace PCManFM
118