option to enter new name in overwrite dialog
authorLukas Hrazky <lukkash@email.cz>
Fri, 30 Jul 2010 20:12:23 +0000 (22:12 +0200)
committerLukas Hrazky <lukkash@email.cz>
Fri, 30 Jul 2010 20:12:23 +0000 (22:12 +0200)
Signed-off-by: Lukas Hrazky <lukkash@email.cz>

src/addressbar.cpp
src/fileoperator.cpp
src/fileoperator.h

index 8ef21fb..0bc1038 100644 (file)
@@ -18,6 +18,7 @@
 #include "addressbar.h"
 #include "fileoperator.h"
 
+
 AddressBar::AddressBar(QWidget *parent) : QLineEdit(parent) {
     setMaximumHeight(60);
     setContentsMargins(-4, -4, -4, -4);
index 90cb7da..a779a87 100644 (file)
 {                                                                                           \
     response = FileOperator::NONE;                                                          \
                                                                                             \
-    if (newFile.exists()) {                                                                 \
+    while (response == FileOperator::NONE && newFile.exists()) {                            \
         if (overwriteAll != FileOperator::NONE) {                                           \
             response = overwriteAll;                                                        \
         } else {                                                                            \
-            bool dirOverDir = false;                                                        \
-            if (newFile.isDir() && file.isDir()) dirOverDir = true;                         \
-            emit showOverwritePrompt(this, newFile.absoluteFilePath(), dirOverDir);         \
+            emit showOverwritePrompt(this, newFile.absoluteFilePath(),                      \
+                newFile.isDir() && file.isDir());                                           \
             waitCond.wait(&mutex);                                                          \
+                                                                                            \
+            if (response == FileOperator::NONE) {                                           \
+                emit showInputFilenamePrompt(this, newFile, file.isDir());                  \
+                waitCond.wait(&mutex);                                                      \
+                if (newNameFromDialog.size()) {                                             \
+                    newFile.setFile(newNameFromDialog);                                     \
+                }                                                                           \
+            }                                                                               \
         }                                                                                   \
     }                                                                                       \
+    if (response == FileOperator::ASK) response = FileOperator::NONE;                       \
 }
 
 
@@ -92,6 +100,7 @@ FileOperator::FileOperator(QWidget *parent) : QWidget(parent) {
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setSpacing(0);
     setLayout(layout);
+    qRegisterMetaType<QFileInfo>("QFileInfo");
 }
 
 
@@ -227,6 +236,7 @@ void FileOperator::showOverwritePrompt(
     QAbstractButton *noButton = msgBox.addButtonSecond(QDialogButtonBox::No);
     QAbstractButton *noToAllButton = msgBox.addButtonSecond(QDialogButtonBox::NoToAll);
     QAbstractButton *abortButton = msgBox.addButtonSecond(tr("Abort"), QDialogButtonBox::DestructiveRole);
+    QAbstractButton *newNameButton = msgBox.addButtonFirst(tr("New Name"), QDialogButtonBox::AcceptRole);
     QAbstractButton *askButton = 0;
     QAbstractButton *skipDirButton = 0;
 
@@ -252,13 +262,55 @@ void FileOperator::showOverwritePrompt(
     } else if (msgBox.clickedButton == noToAllButton) {
         manipulator->setResponse(KEEP, true);
     } else if (msgBox.clickedButton == askButton) {
-        manipulator->setResponse(NONE, true);
+        manipulator->setResponse(ASK);
+    } else if (msgBox.clickedButton == newNameButton) {
+        manipulator->setResponse(NONE);
     } else if (msgBox.clickedButton == skipDirButton) {
         manipulator->setResponse(SKIP_DIR);
     }
 }
 
 
+void FileOperator::showInputFilenamePrompt(FileManipulatorThread* manipulator,
+    const QFileInfo &file,
+    const bool dir)
+{
+    bool ok;
+    QString prompt, error;
+
+    if (dir) {
+        prompt = tr("Enter the new directory name.");
+    } else {
+        prompt = tr("Enter the new file name.");
+    }
+
+    manipulator->mutex.lock();
+
+    manipulator->newNameFromDialog = "";
+    QString text = file.fileName();
+
+    
+    while (true) {
+        text = QInputDialog::getText(this, QString(), prompt + error, QLineEdit::Normal, text, &ok);
+
+        if (!ok) break;
+
+        error = "";
+        if (text.contains(QRegExp("[\"*/:<>?\\\\|]"))) {
+            error = "<small><br/><font color = 'red'>" + tr("The name cannot contain any of the following characters: ") +
+                "\"*/:&lt;&gt;?\\|</font></small>";
+        } else if (ok && !text.isEmpty()) {
+            QFileInfo info(file.path() + "/" + text);
+            manipulator->newNameFromDialog = info.absoluteFilePath();
+            break;
+        }
+    }
+
+    manipulator->mutex.unlock();
+    manipulator->waitCond.wakeAll();
+}
+
+
 void FileOperator::remove(FileManipulatorThread* manipulator) {
     manipulator->wait();
     layout()->removeWidget(manipulator->progressBar);
@@ -288,6 +340,8 @@ void FileOperator::caterNewThread(FileManipulatorThread *thread) {
         this, SLOT(showErrorPrompt(FileManipulatorThread*, const QString&, const QString&, const int)));
     connect(thread, SIGNAL(showOverwritePrompt(FileManipulatorThread*, const QString&, bool)),
         this, SLOT(showOverwritePrompt(FileManipulatorThread*, const QString&, bool)));
+    connect(thread, SIGNAL(showInputFilenamePrompt(FileManipulatorThread*, const QFileInfo&, bool)),
+        this, SLOT(showInputFilenamePrompt(FileManipulatorThread*, const QFileInfo&, bool)));
     connect(thread, SIGNAL(finished(FileManipulatorThread*)),
         this, SLOT(remove(FileManipulatorThread*)));
     connect(thread, SIGNAL(setBarSize(FileManipulatorThread*, unsigned int)),
@@ -295,8 +349,6 @@ void FileOperator::caterNewThread(FileManipulatorThread *thread) {
     connect(thread, SIGNAL(updateProgress(FileManipulatorThread*, int)),
         this, SLOT(updateProgress(FileManipulatorThread*, int)));
 
-    thread->progressBar->setValue(0);
-
     layout()->addWidget(thread->progressBar);
     thread->start(QThread::LowestPriority);
 }
@@ -317,7 +369,9 @@ FileManipulatorThread::FileManipulatorThread(const QFileInfoList files, QDir des
     fileValue(0)
 {
     memset(ignoreAll, false, sizeof(ignoreAll));
-    progressBar->setMaximum(0);
+    progressBar->setMaximum(1);
+    progressBar->setValue(0);
+    progressBar->setMinimum(0);
     QFont barFont = progressBar->font();
     barFont.setPointSize(12);
     progressBar->setFont(barFont);
@@ -428,10 +482,8 @@ void FileManipulatorThread::copy(const QFileInfo &file) {
         << " to " << dest.absolutePath().toStdString() << std::endl;
 
     QString path(file.absoluteFilePath());
-    QString newPath(dest.absolutePath() + "/" + file.fileName());
     QFSFileEngine engine(path);
-    QFSFileEngine newEngine(newPath);
-    QFileInfo newFile(newPath);
+    QFileInfo newFile(dest.absolutePath() + "/" + file.fileName());
 
     updateFile(path);
 
@@ -442,6 +494,9 @@ void FileManipulatorThread::copy(const QFileInfo &file) {
         OVERWRITE_PROMPT(file, newFile)
     }
 
+    QString newPath(newFile.absoluteFilePath());
+    QFSFileEngine newEngine(newPath);
+
     if (abort) return;
 
     if (file.isDir()) {
@@ -732,13 +787,15 @@ void MoveThread::rename(const QFileInfoList &files, const QDir &dest) {
     for (int i = 0; i < files.size(); ++i) {
         QString path = files[i].absoluteFilePath();
         QFSFileEngine engine(path);
-        QString newPath = dest.absolutePath() + "/" + files[i].fileName();
-        QFileInfo newFile(newPath);
+        QFileInfo newFile(dest.absolutePath() + "/" + files[i].fileName());
 
         updateFile(path);
 
         OVERWRITE_PROMPT(files[i], newFile)
 
+        // if we are owerwriting dir over a dir, we will get SKIP_DIR
+        // as a response from OVERWRITE_PROMT meaning we should skip it
+        // (KEEP would mean to keep the files inside)
         if (files[i].isDir() && newFile.exists() && newFile.isDir()) {
             if (response == FileOperator::SKIP_DIR) {
                 if (abort) break;
@@ -755,6 +812,9 @@ void MoveThread::rename(const QFileInfoList &files, const QDir &dest) {
             }
         }
 
+        QString newPath(newFile.absoluteFilePath());
+        QFSFileEngine newEngine(newPath);
+
         while (!abort && !engine.rename(newPath)) {
             // source and target are on different partitions
             // this should happen on the first file, unless some are skipped by overwrite prompt
index 8a8430d..4d2563b 100644 (file)
@@ -37,7 +37,7 @@ class FileOperator : public QWidget {
 
 public:
     // DONT_ASK_ONCE is a hackish way to avoid asking twice to overwrite the same directory when moving
-    enum Response{NONE, ABORT, RETRY, IGNORE, KEEP, OVERWRITE, SKIP_DIR, DONT_ASK_ONCE};
+    enum Response{NONE, ABORT, RETRY, IGNORE, KEEP, OVERWRITE, SKIP_DIR, ASK, DONT_ASK_ONCE};
 
     FileOperator(QWidget *parent = 0);
 
@@ -55,6 +55,9 @@ public slots:
     void showOverwritePrompt(FileManipulatorThread* manipulator,
         const QString &fileName,
         const bool dirOverDir);
+    void showInputFilenamePrompt(FileManipulatorThread* manipulator,
+        const QFileInfo &fileName,
+        const bool dirOverDir);
 
     void remove(FileManipulatorThread* manipulator);
     void setBarSize(FileManipulatorThread* manipulator, unsigned int size);
@@ -80,6 +83,10 @@ public:
     QProgressBar *progressBar;
 
     time_t startTime;
+    QMutex mutex;
+    QWaitCondition waitCond;
+    // the new name entered from the overwrite dialog
+    QString newNameFromDialog;
 
 protected:
     void processFiles(const QFileInfoList &files);
@@ -101,31 +108,40 @@ protected:
     void updateProgress(int value);
     void updateFile(const QString &name);
 
+    // files to process by the operation
     const QFileInfoList files;
+    // destination for files - changes as the operation recurses into directories
     QDir dest;
 
+    // responses from the dialog prompts (error and overwrite)
     FileOperator::Response response;
     FileOperator::Response overwriteAll;
+    // a flag to abort the operation
     bool abort;
+    // an array indicating whether to always ignore the error of index errno
     bool ignoreAll[256];
 
     // set of files that won't be deleted by the remove(...) functions
     // used when move(...) would not overwrite target file to ensure the source file doesn't get deleted
     QSet<QString> removeExcludeFiles;
 
+    // A map of file paths to their size. Not the actual size, but what is calculated for the
+    // purpose of the progressbar for the given operation. So either fileSize/BLOCK_SIZE or simply
+    // 1 for a file and file count for dirs (or both for copy&delete)
     QMap<QString, qint64> fileSizeMap;
 
-    QMutex mutex;
-    QWaitCondition waitCond;
-
+    // the name of the file thats being processed (for progressBar) and the text of the progressBar (the format)
     QString fileName, barText;
+    // stamp of the last ETA recalculation - done every second
     time_t lastTimeUpdate;
     char timeBuf[10];
+    // progress information of the bar and for the current file
     unsigned int barSize, barValue, fileSize, fileValue;
 
 signals:
     void showErrorPrompt(FileManipulatorThread*, const QString&, const QString&, const int);
     void showOverwritePrompt(FileManipulatorThread*, const QString&, const bool);
+    void showInputFilenamePrompt(FileManipulatorThread*, const QFileInfo&, const bool);
     void finished(FileManipulatorThread*);
     void setBarSize(FileManipulatorThread*, unsigned int);
     void updateProgress(FileManipulatorThread*, int);