altered behavior of the 'move' operation
[case] / src / fileoperator.cpp
index 68ca019..8d422e6 100644 (file)
@@ -28,6 +28,9 @@
 #include <iostream>
 
 
+#define BLOCK_SIZE 524288
+
+
 #define SHOW_ERROR_PROMPT(promptString, fileName)                                           \
     response = FileOperator::NONE;                                                          \
     if (ignoreAll[errno]) {                                                                 \
@@ -317,6 +320,10 @@ FileManipulatorThread::FileManipulatorThread(const QFileInfoList files, QDir des
 
 
 FileManipulatorThread::~FileManipulatorThread() {
+    if (progressBar->value() < progressBar->maximum()) {
+        std::cout << "WARNING: deleting a progressbar which's value " << progressBar->value() <<
+            " has not reached maximum of " << progressBar->maximum() << std::endl;
+    }
     delete progressBar;
 }
 
@@ -358,46 +365,48 @@ void FileManipulatorThread::processFiles(const QFileInfoList &files) {
 }
 
 
-bool FileManipulatorThread::remove(QString &fileName, const bool ignoreDirNotEmpty) {
-    return remove(QFileInfo(fileName), ignoreDirNotEmpty);
+bool FileManipulatorThread::remove(QString &fileName, const bool doUpdates) {
+    return remove(QFileInfo(fileName), doUpdates);
 }
 
 
-bool FileManipulatorThread::remove(const QFileInfoList &files, const bool ignoreDirNotEmpty) {
+bool FileManipulatorThread::remove(const QFileInfoList &files, const bool doUpdates) {
     bool res = true;
     for (QFileInfoList::const_iterator it = files.begin(); it != files.end(); ++it) {
-        if (!remove(*it, ignoreDirNotEmpty)) res = false;
+        if (!remove(*it, doUpdates)) res = false;
         if (abort) break;
     }
     return res;
 }
 
 
-bool FileManipulatorThread::remove(const QFileInfo &file, const bool ignoreDirNotEmpty) {
+bool FileManipulatorThread::remove(const QFileInfo &file, const bool doUpdates) {
+    std::cout << "DELETING " << file.absoluteFilePath().toStdString() << std::endl;
+
     QString path = file.absoluteFilePath();
     QFSFileEngine engine(path);
 
-    if (file.isDir()) {
-        QFileInfoList list = listDirFiles(path);
+    if (doUpdates) updateFile(path);
 
-        if (ignoreDirNotEmpty && list.size()) return true;
-
-        if (!remove(list, ignoreDirNotEmpty)) return false;
+    if (file.isDir()) {
+        if (!remove(listDirFiles(path), doUpdates)) return false;
 
-        ERROR_PROMPT(!engine.rmdir(path, false),
-            tr("Error deleting directory %1."), path)
+        if (!listDirFiles(path).size()) {
+            ERROR_PROMPT(!engine.rmdir(path, false), tr("Error deleting directory %1."), path)
+        }
     } else {
-        ERROR_PROMPT(!engine.remove(),
-            tr("Error deleting file %1."), path)
+        ERROR_PROMPT(!engine.remove(), tr("Error deleting file %1."), path)
     }
 
+    if (!abort && doUpdates) updateProgress(1);
+
     if (abort || response == FileOperator::IGNORE) return false;
     return true;
 }
 
 
-void FileManipulatorThread::copy(const QFileInfo &file, const bool removeAfterCopy) {
-    std::cout << (removeAfterCopy ? "MOVING " : "COPYING ") << file.absoluteFilePath().toStdString()
+void FileManipulatorThread::copy(const QFileInfo &file) {
+    std::cout << "COPYING " << file.absoluteFilePath().toStdString()
         << " to " << dest.absolutePath().toStdString() << std::endl;
 
     QString path(file.absoluteFilePath());
@@ -417,161 +426,149 @@ void FileManipulatorThread::copy(const QFileInfo &file, const bool removeAfterCo
 
     if (abort) return;
 
-    // this loop is here only to allow easily breaking out to the end (and remove the source file/dir)
-    while (1) {
-        if (response == FileOperator::KEEP) {
-            updateProgress(fileSizeMap[path]);
-            break;
-        }
+    if (response == FileOperator::KEEP) {
+        updateProgress(fileSizeMap[path]);
+        return;
+    }
 
+    if (file.isDir()) {
         FileOperator::Response overwriteResponse = response;
 
-        if (file.isDir()) {
-            if (newFile.exists() && !newFile.isDir()) {
-                if(!remove(newPath)) {
-                    updateProgress(fileSizeMap[path]);
-                    break;
-                }
-                newFile = QFileInfo(newPath);
+        if (newFile.exists() && !newFile.isDir()) {
+            if(!remove(newPath)) {
+                updateProgress(fileSizeMap[path]);
+                return;
             }
+            newFile = QFileInfo(newPath);
+        }
 
-            if (!newFile.exists()) {
-                ERROR_PROMPT_XP(!engine.mkdir(newPath, false),
-                    tr("Error creating directory %1."), newPath,
-                    updateProgress(fileSizeMap[path]),
-                    break)
-            }
+        if (!newFile.exists()) {
+            ERROR_PROMPT_XP(!engine.mkdir(newPath, false),
+                tr("Error creating directory %1."), newPath,
+                updateProgress(fileSizeMap[path]),
+                return)
+        }
 
-            updateProgress(1);
-            
-            QDir destBackup = dest;
-            dest = newPath;
+        updateProgress(1);
+        
+        QDir destBackup = dest;
+        dest = newPath;
 
-            FileOperator::Response tmpResp = overwriteAll;
-            overwriteAll = overwriteResponse;
+        FileOperator::Response tmpResp = overwriteAll;
+        overwriteAll = overwriteResponse;
 
-            processFiles(listDirFiles(path));
+        processFiles(listDirFiles(path));
 
-            overwriteAll = tmpResp;
+        overwriteAll = tmpResp;
 
-            ERROR_PROMPT(!newEngine.setPermissions(file.permissions()),
-                tr("Error setting permissions for directory %1."), newPath)
+        ERROR_PROMPT(!newEngine.setPermissions(file.permissions()),
+            tr("Error setting permissions for directory %1."), newPath)
 
-            if (abort) return;
+        if (abort) return;
 
-            dest = destBackup;
-        } else {
-            ERROR_PROMPT_XP(engine.isSequential(),
-                tr("Cannot copy sequential file %1."), path,
+        dest = destBackup;
+    } else {
+        ERROR_PROMPT_XP(engine.isSequential(),
+            tr("Cannot copy sequential file %1."), path,
+            updateProgress(fileSizeMap[path]),
+            return)
+
+        if (newFile.exists() && newFile.isDir()) {
+            ERROR_PROMPT_XP(!remove(newPath),
+                tr("Cannot replace directory %1 due to previous errors."), newPath,
                 updateProgress(fileSizeMap[path]),
-                break)
+                return)
+        }
 
-            if (newFile.exists() && newFile.isDir()) {
-                ERROR_PROMPT_XP(!remove(newPath),
-                    tr("Cannot replace directory %1 due to previous errors."), newPath,
-                    updateProgress(fileSizeMap[path]),
-                    break)
-            }
+        ERROR_PROMPT_XP(!engine.open(QIODevice::ReadOnly),
+            tr("Error reading file %1."), path,
+            updateProgress(fileSizeMap[path]),
+            return)
 
-            ERROR_PROMPT_XP(!engine.open(QIODevice::ReadOnly),
-                tr("Error reading file %1."), path,
-                updateProgress(fileSizeMap[path]),
-                break)
+        bool ignore = false;
+        while (!abort && !ignore) {
+            engine.seek(0);
 
-            bool ignore = false;
-            while (!abort && !ignore) {
-                engine.seek(0);
+            ERROR_PROMPT(!newEngine.open(QIODevice::WriteOnly | QIODevice::Truncate),
+                tr("Error writing file %1."), newPath)
 
-                ERROR_PROMPT(!newEngine.open(QIODevice::WriteOnly | QIODevice::Truncate),
-                    tr("Error writing file %1."), newPath)
+            if (abort || response == FileOperator::IGNORE) {
+                if (response == FileOperator::IGNORE) {
+                    updateProgress(fileSizeMap[path] - fileValue);
+                    ignore = true;
+                }
+                break;
+            }
 
-                if (abort || response == FileOperator::IGNORE) {
-                    if (response == FileOperator::IGNORE) {
-                        updateProgress(fileSizeMap[path] - fileValue);
-                        ignore = true;
+            bool error = false;
+            char block[BLOCK_SIZE];
+            qint64 bytes;
+            while ((bytes = engine.read(block, sizeof(block))) > 0) {
+                if (bytes == -1 || bytes != newEngine.write(block, bytes)) {
+                    if (bytes == -1) {
+                        SHOW_ERROR_PROMPT(tr("Error while reading from file %1."), path);
+                    } else {
+                        SHOW_ERROR_PROMPT(tr("Error while writing to file %1."), newPath);
                     }
-                    break;
-                }
 
-                bool error = false;
-                char block[524288];
-                qint64 bytes;
-                while ((bytes = engine.read(block, sizeof(block))) > 0) {
-                    if (bytes == -1 || bytes != newEngine.write(block, bytes)) {
-                        if (bytes == -1) {
-                            SHOW_ERROR_PROMPT(tr("Error while reading from file %1."), path);
+                    if (!abort) {
+                        if (response == FileOperator::IGNORE) {
+                            updateProgress(fileSizeMap[path] - fileValue);
+                            ignore = true;
                         } else {
-                            SHOW_ERROR_PROMPT(tr("Error while writing to file %1."), newPath);
+                            updateProgress(-fileValue);
                         }
-
-                        if (!abort) {
-                            if (response == FileOperator::IGNORE) {
-                                updateProgress(fileSizeMap[path] - fileValue);
-                                ignore = true;
-                            } else {
-                                updateProgress(-fileValue);
-                            }
-                        }
-                        error = true;
-                        break;
                     }
-
-                    updateProgress(1);
+                    error = true;
+                    break;
                 }
 
-                if (!error) break;
+                updateProgress(1);
             }
 
-            engine.close();
-            newEngine.close();
-
-            if (abort || ignore) {
-                newEngine.remove();
-            } else {
-                ERROR_PROMPT(!newEngine.setPermissions(file.permissions()),
-                    tr("Error setting permissions for file %1."), newPath)
-            }
+            if (!error) break;
         }
 
-        break;
-    }
+        engine.close();
+        newEngine.close();
 
-    if (removeAfterCopy && !abort) remove(path, true);
+        if (abort || ignore) {
+            newEngine.remove();
+        } else {
+            ERROR_PROMPT(!newEngine.setPermissions(file.permissions()),
+                tr("Error setting permissions for file %1."), newPath)
+        }
+    }
 }
 
 
-unsigned int FileManipulatorThread::countFiles(const QFileInfoList &files) {
+unsigned int FileManipulatorThread::calculateFileSize(const QFileInfoList &files,
+    const bool count,
+    const bool addSize)
+{
     unsigned int res = 0;
 
     for (QFileInfoList::const_iterator it = files.begin(); it != files.end(); ++it) {
-        unsigned int size = 1;
+        unsigned int size = 0;
 
         if (it->isDir()) {
-            size += countFiles(listDirFiles(it->absoluteFilePath()));
+            size += calculateFileSize(listDirFiles(it->absoluteFilePath()), count, addSize);
         }
 
-        res += size;
-        fileSizeMap[it->absoluteFilePath()] = size;
-    }
-
-    return res;
-}
-
-
-unsigned int FileManipulatorThread::calculateFileSize(const QFileInfoList &files) {
-    unsigned int res = 0;
-
-    for (QFileInfoList::const_iterator it = files.begin(); it != files.end(); ++it) {
-        unsigned int size = 1;
+        if (addSize) {
+            if (it->isDir()) {
+                ++size;
+            } else {
+                size += ceil(static_cast<float>(it->size()) / BLOCK_SIZE);
+            }
+            fileSizeMap[it->absoluteFilePath()] = size;
+        }
 
-        if (it->isDir()) {
-            size += calculateFileSize(listDirFiles(it->absoluteFilePath()));
-        } else {
-            size = ceil(static_cast<float>(it->size()) / 524288);
+        if (count) {
+            ++size;
         }
 
         res += size;
-        fileSizeMap[it->absoluteFilePath()] = size;
     }
 
     return res;
@@ -606,7 +603,8 @@ void FileManipulatorThread::updateFile(const QString &name) {
 
 void FileManipulatorThread::setText(int value) {
     if (progressBar->value() + value > progressBar->maximum()) {
-        std::cout << "WARNING, EXCEEDING MAXIMUM BY " << value << std::endl;
+        std::cout << "WARNING: exceeding progressbar maximum (" << progressBar->maximum()
+            << ") by " << value << std::endl;
     }
  
     time_t now = time(0);
@@ -639,7 +637,7 @@ DeleteThread::DeleteThread(const QFileInfoList &files) : FileManipulatorThread(f
 void DeleteThread::run() {
     mutex.lock();
 
-    setBarSize(countFiles(files));
+    setBarSize(calculateFileSize(files, true));
 
     processFiles(files);
 
@@ -649,26 +647,7 @@ void DeleteThread::run() {
 
 
 void DeleteThread::perform(const QFileInfo &file) {
-    std::cout << "DELETING " << file.absoluteFilePath().toStdString() << std::endl;
-
-    QString path = file.absoluteFilePath();
-    QFSFileEngine engine(path);
-
-    updateFile(path);
-
-    if (file.isDir()) {
-        processFiles(listDirFiles(path));
-
-        if (!listDirFiles(path).size()) {
-            ERROR_PROMPT(!engine.rmdir(path, false),
-                tr("Error deleting directory %1."), path)
-        }
-    } else {
-        ERROR_PROMPT(!engine.remove(),
-            tr("Error deleting file %1."), path)
-    }
-
-    if (!abort) updateProgress(1);
+    remove(file, true);
 }
 
 
@@ -680,7 +659,7 @@ CopyThread::CopyThread(const QFileInfoList &files, QDir &dest) : FileManipulator
 void CopyThread::run() {
     mutex.lock();
 
-    setBarSize(calculateFileSize(files));
+    setBarSize(calculateFileSize(files, false, true));
 
     processFiles(files);
 
@@ -690,7 +669,7 @@ void CopyThread::run() {
 
 
 void CopyThread::perform(const QFileInfo &file) {
-    copy(file, false);
+    copy(file);
 }
 
 
@@ -722,7 +701,8 @@ void MoveThread::rename(const QFileInfoList &files, const QDir &dest) {
         OVERWRITE_PROMPT(files[i], QFileInfo(newPath))
 
         if (response == FileOperator::KEEP) {
-            remove(path);
+            // TODO lets not remove the source for now, I'm not sure what is correct behavior
+            // remove(path);
             if (abort) break;
             updateProgress(1);
             continue;
@@ -733,17 +713,20 @@ void MoveThread::rename(const QFileInfoList &files, const QDir &dest) {
             // this should happen on the first file, unless some are skipped by overwrite prompt
             // we calculate the actual file sizes, because from now on copy & remove takes over
             if (errno == EXDEV) {
-                setBarSize(barValue + calculateFileSize(files));
-
-                FileOperator::Response tmpResp = overwriteAll;
                 overwriteAll = response;
                 // hack: we already checked the first file we are sending to processFiles(...)
                 // so we don't want to ask about this one again
                 if (overwriteAll == FileOperator::NONE) overwriteAll = FileOperator::DONT_ASK_ONCE;
 
-                processFiles(files.mid(i));
+                QFileInfoList remainingFiles = files.mid(i);
 
-                overwriteAll = tmpResp;
+                setBarSize(barValue + calculateFileSize(remainingFiles, true, true));
+
+                processFiles(remainingFiles);
+
+                barText = tr("deleting %1");
+
+                remove(remainingFiles, true);
 
                 // just to quit the loops, we are done
                 abort = true;
@@ -780,5 +763,5 @@ void MoveThread::rename(const QFileInfoList &files, const QDir &dest) {
 
 
 void MoveThread::perform(const QFileInfo &file) {
-    copy(file, true);
+    copy(file);
 }