Integrated file selection dialogue with the main code. Improved the
[openvpnui.git] / src / filebrowse / fileworker.cpp
diff --git a/src/filebrowse/fileworker.cpp b/src/filebrowse/fileworker.cpp
new file mode 100644 (file)
index 0000000..4637862
--- /dev/null
@@ -0,0 +1,266 @@
+#include "fileworker.h"
+#include <QDateTime>
+#include "globals.h"
+
+FileWorker::FileWorker(QObject *parent) :
+    QThread(parent),
+    m_mode(DeleteMode),
+    m_cancelled(KeepRunning),
+    m_progress(0)
+{
+}
+
+FileWorker::~FileWorker()
+{
+}
+
+void FileWorker::startDeleteFiles(QStringList filenames)
+{
+    if (isRunning()) {
+        emit errorOccurred(tr("File operation already in progress"), "");
+        return;
+    }
+
+    // basic validity check
+    foreach (QString filename, filenames) {
+        if (filename.isEmpty()) {
+            emit errorOccurred(tr("Empty filename"), "");
+            return;
+        }
+    }
+
+    m_mode = DeleteMode;
+    m_filenames = filenames;
+    m_cancelled.storeRelease(KeepRunning);
+    start();
+}
+
+void FileWorker::startCopyFiles(QStringList filenames, QString destDirectory)
+{
+    if (isRunning()) {
+        emit errorOccurred(tr("File operation already in progress"), "");
+        return;
+    }
+
+    // basic validity check
+    foreach (QString filename, filenames) {
+        if (filename.isEmpty()) {
+            emit errorOccurred(tr("Empty filename"), "");
+            return;
+        }
+    }
+
+    m_mode = CopyMode;
+    m_filenames = filenames;
+    m_destDirectory = destDirectory;
+    m_cancelled.storeRelease(KeepRunning);
+    start();
+}
+
+void FileWorker::startMoveFiles(QStringList filenames, QString destDirectory)
+{
+    if (isRunning()) {
+        emit errorOccurred(tr("File operation already in progress"), "");
+        return;
+    }
+
+    // basic validity check
+    foreach (QString filename, filenames) {
+        if (filename.isEmpty()) {
+            emit errorOccurred(tr("Empty filename"), "");
+            return;
+        }
+    }
+
+    m_mode = MoveMode;
+    m_filenames = filenames;
+    m_destDirectory = destDirectory;
+    m_cancelled.storeRelease(KeepRunning);
+    start();
+}
+
+void FileWorker::cancel()
+{
+    m_cancelled.storeRelease(Cancelled);
+}
+
+void FileWorker::run() Q_DECL_OVERRIDE
+{
+    switch (m_mode) {
+    case DeleteMode:
+        deleteFiles();
+        break;
+
+    case MoveMode:
+    case CopyMode:
+        copyOrMoveFiles();
+        break;
+    }
+}
+
+QString FileWorker::deleteFile(QString filename)
+{
+    QFileInfo info(filename);
+    if (!info.exists())
+        return tr("File not found");
+
+    if (info.isDir()) {
+        // this should be custom function to get better error reporting
+        bool ok = QDir(info.absoluteFilePath()).removeRecursively();
+        if (!ok)
+            return tr("Folder delete failed");
+
+    } else {
+        QFile file(info.absoluteFilePath());
+        bool ok = file.remove();
+        if (!ok)
+            return file.errorString();
+    }
+    return QString();
+}
+
+void FileWorker::deleteFiles()
+{
+    int fileIndex = 0;
+    int fileCount = m_filenames.count();
+
+    foreach (QString filename, m_filenames) {
+        m_progress = 100 * fileIndex / fileCount;
+        emit progressChanged(m_progress, filename);
+
+        // stop if cancelled
+        if (m_cancelled.loadAcquire() == Cancelled) {
+            emit errorOccurred(tr("Cancelled"), filename);
+            return;
+        }
+
+        // delete file and stop if errors
+        QString errMsg = deleteFile(filename);
+        if (!errMsg.isEmpty()) {
+            emit errorOccurred(errMsg, filename);
+            return;
+        }
+        emit fileDeleted(filename);
+
+        fileIndex++;
+    }
+
+    m_progress = 100;
+    emit progressChanged(m_progress, "");
+    emit done();
+}
+
+void FileWorker::copyOrMoveFiles()
+{
+    int fileIndex = 0;
+    int fileCount = m_filenames.count();
+
+    QDir dest(m_destDirectory);
+    foreach (QString filename, m_filenames) {
+        m_progress = 100 * fileIndex / fileCount;
+        emit progressChanged(m_progress, filename);
+
+        // stop if cancelled
+        if (m_cancelled.loadAcquire() == Cancelled) {
+            emit errorOccurred(tr("Cancelled"), filename);
+            return;
+        }
+
+        // check destination does not exists, otherwise copy/move fails
+        QFileInfo fileInfo(filename);
+        QString newname = dest.absoluteFilePath(fileInfo.fileName());
+
+        // move or copy and stop if errors
+        QFile file(filename);
+        if (m_mode == MoveMode) {
+            if (!file.rename(newname)) {
+                emit errorOccurred(file.errorString(), filename);
+                return;
+            }
+        } else {
+            if (fileInfo.isDir()) {
+                QString errmsg = copyDirRecursively(filename, newname);
+                if (!errmsg.isEmpty()) {
+                    emit errorOccurred(errmsg, filename);
+                    return;
+                }
+            } else {
+                QString errmsg = copyOverwrite(filename, newname);
+                if (!errmsg.isEmpty()) {
+                    emit errorOccurred(errmsg, filename);
+                    return;
+                }
+            }
+        }
+
+        fileIndex++;
+    }
+
+    m_progress = 100;
+    emit progressChanged(m_progress, "");
+    emit done();
+}
+
+QString FileWorker::copyDirRecursively(QString srcDirectory, QString destDirectory)
+{
+    QDir srcDir(srcDirectory);
+    if (!srcDir.exists())
+        return tr("Source folder doesn't exist");
+
+    QDir destDir(destDirectory);
+    if (!destDir.exists()) {
+        QDir d(destDir);
+        d.cdUp();
+        if (!d.mkdir(destDir.dirName()))
+            return tr("Can't create target folder %1").arg(destDirectory);
+    }
+
+    // copy files
+    QStringList names = srcDir.entryList(QDir::Files);
+    for (int i = 0 ; i < names.count() ; ++i) {
+        // stop if cancelled
+        if (m_cancelled.loadAcquire() == Cancelled)
+            return tr("Cancelled");
+
+        QString filename = names.at(i);
+        emit progressChanged(m_progress, filename);
+        QString spath = srcDir.absoluteFilePath(filename);
+        QString dpath = destDir.absoluteFilePath(filename);
+        QString errmsg = copyOverwrite(spath, dpath);
+        if (!errmsg.isEmpty())
+            return errmsg;
+    }
+
+    // copy dirs
+    names = srcDir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs);
+    for (int i = 0 ; i < names.count() ; ++i) {
+        // stop if cancelled
+        if (m_cancelled.loadAcquire() == Cancelled)
+            return tr("Cancelled");
+
+        QString filename = names.at(i);
+        emit progressChanged(m_progress, filename);
+        QString spath = srcDir.absoluteFilePath(filename);
+        QString dpath = destDir.absoluteFilePath(filename);
+        QString errmsg = copyDirRecursively(spath, dpath);
+        if (!errmsg.isEmpty())
+            return errmsg;
+    }
+
+    return QString();
+}
+
+QString FileWorker::copyOverwrite(QString src, QString dest)
+{
+    QFile dfile(dest);
+    if (dfile.exists()) {
+        if (!dfile.remove())
+            return dfile.errorString();
+    }
+
+    QFile sfile(src);
+    if (!sfile.copy(dest))
+        return sfile.errorString();
+
+    return QString();
+}