X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Ffileoperator.cpp;fp=src%2Ffileoperator.cpp;h=b25ab3bdeac79f37b6cba9ef741526069f2c177c;hb=2edb4f2f10329116492492b442c2957653381c28;hp=bd4c667de5395eaad74fa098463261c0414cb9cd;hpb=55d99074d0b0b5eca3530d0c0f683faee48f10f9;p=case diff --git a/src/fileoperator.cpp b/src/fileoperator.cpp index bd4c667..b25ab3b 100644 --- a/src/fileoperator.cpp +++ b/src/fileoperator.cpp @@ -18,145 +18,34 @@ #include "fileoperator.h" #include -#include #include #include -#include #include "dialog.h" #include "utils.h" -#include -#include -#include - - -#define BLOCK_SIZE 524288 - - -#define PAUSE() \ - if (pause) { \ - emit operationPaused(this); \ - waitOnCond(); \ - } - - -#define SHOW_ERROR_PROMPT(promptString, fileName) \ - response = FileOperator::NONE; \ - if (ignoreAll[errno]) { \ - response = FileOperator::IGNORE; \ - } else { \ - char buf[255]; \ - char *realBuf = buf; \ - if (errno == 255) { \ - strcpy(buf, tr("File is sequential").toStdString().c_str()); \ - } else { \ - realBuf = strerror_r(errno, buf, 255); \ - } \ - emit showErrorPrompt(this, promptString + " " + realBuf + ".", fileName, errno); \ - waitOnCond(); \ - } - - -#define ERROR_PROMPT(operation, promptString, fileName) \ -{ \ - response = FileOperator::NONE; \ - while (!abort && operation) { \ - SHOW_ERROR_PROMPT(promptString, fileName) \ - if (response == FileOperator::IGNORE) { \ - break; \ - } \ - PAUSE() \ - } \ -} - - -#define SPECIAL_COPY_ERROR_PROMPT(operation, promptString, fileName) \ -{ \ - ERROR_PROMPT(operation, promptString, fileName) \ - if (abort || response == FileOperator::IGNORE) { \ - if (!abort) { \ - updateProgress(fileSizeMap[path]); \ - removeExcludeFiles.insert(path); \ - } \ - return; \ - } \ -} - - -#define OVERWRITE_PROMPT(file, newFile) \ -{ \ - response = FileOperator::NONE; \ - \ - while (!abort && response == FileOperator::NONE && newFile.exists()) { \ - if (overwriteAll != FileOperator::NONE) { \ - response = overwriteAll; \ - } else { \ - emit showOverwritePrompt(this, newFile.absoluteFilePath(), \ - newFile.isDir() && file.isDir()); \ - waitOnCond(); \ - \ - PAUSE() \ - else if (response == FileOperator::NONE) { \ - emit showInputFilenamePrompt(this, newFile, file.isDir()); \ - waitOnCond(); \ - if (newNameFromDialog.size()) { \ - newFile.setFile(newNameFromDialog); \ - } \ - } \ - } \ - } \ - if (response == FileOperator::ASK) response = FileOperator::NONE; \ -} - FileOperator::FileOperator(QWidget *parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(1); setLayout(layout); + qRegisterMetaType("QFileInfo"); + qRegisterMetaType("time_t"); + loadOperationIcons(palette(), "delete_small", deleteIcon, inverseDeleteIcon); loadOperationIcons(palette(), "copy_small", copyIcon, inverseCopyIcon); loadOperationIcons(palette(), "move_small", moveIcon, inverseMoveIcon); } -QString FileOperator::shortenPath(const QString &path) { - QString homePath = QFSFileEngine::homePath(); - - if (path.indexOf(homePath, 0) == 0) { - QString result = path; - - result.replace(0, homePath.size(), "~"); - return result; - } - - return path; -} - - -QString FileOperator::unwindPath(const QString &path) { - QString result = path; - // if ~ is the first character and / or nothing follows it, replace with home dir - if (path == "~" || path.indexOf("~/", 0) == 0) { - QString homePath = QFSFileEngine::homePath(); - result.replace(0, 1, homePath); - // in case someone wants to enter a dir called ~ in the current dir, he can escape it with \~ - } else if (path == "\\~" || path.indexOf("\\~/", 0) == 0) { - result.replace(0, 2, "~"); - } - - return result; -} - - void FileOperator::deleteFiles(const QFileInfoList &files) { QString title, desc; if (files.size() == 1) { title = tr("Delete file"); desc = tr("Are you sure you want to delete %1?") - .arg(FileOperator::shortenPath(files[0].absoluteFilePath())); + .arg(shortenPath(files[0].absoluteFilePath())); } else { title = tr("Delete files"); desc = tr("You are about to delete %1 files. Are you sure you want to continue?").arg(files.size()); @@ -171,9 +60,8 @@ void FileOperator::deleteFiles(const QFileInfoList &files) { ); if(confirm == QMessageBox::Yes) { - DeleteThread *t = new DeleteThread(files); - t->progressBar->setIcons(deleteIcon, inverseDeleteIcon); - caterNewThread(t); + ProgressBar *bar = new ProgressBar(deleteIcon, inverseDeleteIcon); + initOperation(new DeleteThread(files), bar); } } @@ -183,12 +71,12 @@ void FileOperator::copyFiles(const QFileInfoList &files, QDir &destination) { if (files.size() == 1) { title = tr("Copy file"); desc = tr("Are you sure you want to copy %1 to %2?") - .arg(FileOperator::shortenPath(files[0].absoluteFilePath())) - .arg(FileOperator::shortenPath(destination.absolutePath())); + .arg(shortenPath(files[0].absoluteFilePath())) + .arg(shortenPath(destination.absolutePath())); } else { title = tr("Copy files"); desc = tr("You are about to copy %1 files to %2. Are you sure you want to continue?") - .arg(files.size()).arg(FileOperator::shortenPath(destination.absolutePath())); + .arg(files.size()).arg(shortenPath(destination.absolutePath())); } int confirm = QMessageBox::warning( @@ -200,11 +88,9 @@ void FileOperator::copyFiles(const QFileInfoList &files, QDir &destination) { ); if(confirm == QMessageBox::Yes) { - CopyThread *t = new CopyThread(files, destination); - t->progressBar->setIcons(copyIcon, inverseCopyIcon); - t->progressBar->fromText = shortenPath(files[0].absolutePath()); - t->progressBar->toText = FileOperator::shortenPath(destination.absolutePath()); - caterNewThread(t); + ProgressBar *bar = new ProgressBar(copyIcon, inverseCopyIcon); + bar->setBottomTexts(shortenPath(files[0].absolutePath()), shortenPath(destination.absolutePath())); + initOperation(new CopyThread(files, destination), bar); } } @@ -217,12 +103,12 @@ void FileOperator::moveFiles(const QFileInfoList &files, QDir &destination) { if (files.size() == 1) { title = tr("Move file"); desc = tr("Are you sure you want to move %1 to %2?") - .arg(FileOperator::shortenPath(files[0].absoluteFilePath())) - .arg(FileOperator::shortenPath(destination.absolutePath())); + .arg(shortenPath(files[0].absoluteFilePath())) + .arg(shortenPath(destination.absolutePath())); } else { title = tr("Move files"); desc = tr("You are about to move %1 files to %2. Are you sure you want to continue?") - .arg(files.size()).arg(FileOperator::shortenPath(destination.absolutePath())); + .arg(files.size()).arg(shortenPath(destination.absolutePath())); } int confirm = QMessageBox::warning( @@ -234,16 +120,14 @@ void FileOperator::moveFiles(const QFileInfoList &files, QDir &destination) { ); if(confirm == QMessageBox::Yes) { - MoveThread *t = new MoveThread(files, destination); - t->progressBar->setIcons(moveIcon, inverseMoveIcon); - t->progressBar->fromText = shortenPath(files[0].absolutePath()); - t->progressBar->toText = shortenPath(destination.absolutePath()); - caterNewThread(t); + ProgressBar *bar = new ProgressBar(moveIcon, inverseMoveIcon); + bar->setBottomTexts(shortenPath(files[0].absolutePath()), shortenPath(destination.absolutePath())); + initOperation(new MoveThread(files, destination), bar); } } -void FileOperator::showErrorPrompt(FileManipulatorThread* manipulator, +void FileOperator::showErrorPrompt(OperationThread* op, const QString &message, const QString &fileName, const int err) @@ -254,27 +138,27 @@ void FileOperator::showErrorPrompt(FileManipulatorThread* manipulator, QAbstractButton *retryButton = msgBox.addButton(QMessageBox::Retry); QAbstractButton *ignoreButton = msgBox.addButton(QMessageBox::Ignore); QAbstractButton *ignoreAllButton = msgBox.addButton(tr("Ignore All"), QMessageBox::AcceptRole); - msgBox.setText(message.arg(FileOperator::shortenPath(fileName))); + msgBox.setText(message.arg(shortenPath(fileName))); msgBox.exec(); if (msgBox.clickedButton() == cancelButton) { - manipulator->pause = true; - manipulator->setResponse(RETRY); + op->pause = true; + op->setResponse(OperationThread::RETRY); } else if (msgBox.clickedButton() == abortButton) { - manipulator->setResponse(ABORT); + op->setResponse(OperationThread::ABORT); } else if (msgBox.clickedButton() == retryButton) { - manipulator->setResponse(RETRY); + op->setResponse(OperationThread::RETRY); } else if (msgBox.clickedButton() == ignoreButton) { - manipulator->setResponse(IGNORE); + op->setResponse(OperationThread::IGNORE); } else if (msgBox.clickedButton() == ignoreAllButton) { - manipulator->setResponse(IGNORE, true, err); + op->setResponse(OperationThread::IGNORE, true, err); } } void FileOperator::showOverwritePrompt( - FileManipulatorThread* manipulator, + OperationThread* op, const QString &fileName, const bool dirOverDir) { @@ -290,39 +174,39 @@ void FileOperator::showOverwritePrompt( if (dirOverDir) { msgBox.setText(tr("Directory %1 already exists. Overwrite the files inside?") - .arg(FileOperator::shortenPath(fileName))); + .arg(shortenPath(fileName))); askButton = msgBox.addButtonFirst(tr("Ask"), QDialogButtonBox::AcceptRole); skipDirButton = msgBox.addButtonSecond(tr("Skip"), QDialogButtonBox::NoRole); } else { - msgBox.setText(tr("File %1 already exists. Overwrite?").arg(FileOperator::shortenPath(fileName))); + msgBox.setText(tr("File %1 already exists. Overwrite?").arg(shortenPath(fileName))); } msgBox.exec(); if (msgBox.clickedButton == 0) { - manipulator->pause = true; - manipulator->setResponse(NONE); + op->pause = true; + op->setResponse(OperationThread::NONE); } else if (msgBox.clickedButton == abortButton) { - manipulator->setResponse(ABORT); + op->setResponse(OperationThread::ABORT); } else if (msgBox.clickedButton == yesButton) { - manipulator->setResponse(OVERWRITE); + op->setResponse(OperationThread::OVERWRITE); } else if (msgBox.clickedButton == yesToAllButton) { - manipulator->setResponse(OVERWRITE, true); + op->setResponse(OperationThread::OVERWRITE, true); } else if (msgBox.clickedButton == noButton) { - manipulator->setResponse(KEEP); + op->setResponse(OperationThread::KEEP); } else if (msgBox.clickedButton == noToAllButton) { - manipulator->setResponse(KEEP, true); + op->setResponse(OperationThread::KEEP, true); } else if (msgBox.clickedButton == askButton) { - manipulator->setResponse(ASK); + op->setResponse(OperationThread::ASK); } else if (msgBox.clickedButton == newNameButton) { - manipulator->setResponse(NONE); + op->setResponse(OperationThread::NONE); } else if (msgBox.clickedButton == skipDirButton) { - manipulator->setResponse(SKIP_DIR); + op->setResponse(OperationThread::SKIP_DIR); } } -void FileOperator::showInputFilenamePrompt(FileManipulatorThread* manipulator, +void FileOperator::showInputFilenamePrompt(OperationThread* op, const QFileInfo &file, const bool dir) { @@ -335,9 +219,7 @@ void FileOperator::showInputFilenamePrompt(FileManipulatorThread* manipulator, prompt = tr("Enter the new file name."); } - manipulator->mutex.lock(); - - manipulator->newNameFromDialog = ""; + op->newNameFromDialog = ""; QString text = file.fileName(); while (true) { @@ -347,65 +229,44 @@ void FileOperator::showInputFilenamePrompt(FileManipulatorThread* manipulator, error = ""; if (text.contains(QRegExp("[\"*/:<>?\\\\|]"))) { - error = "
" + tr("The name cannot contain any of the following characters: ") + + error = "
" + + tr("The name cannot contain any of the following characters: ") + "\"*/:<>?\\|
"; } else if (ok && !text.isEmpty()) { QFileInfo info(file.path() + "/" + text); - manipulator->newNameFromDialog = info.absoluteFilePath(); + op->newNameFromDialog = info.absoluteFilePath(); break; } } - manipulator->mutex.unlock(); - manipulator->wake(); -} - - -void FileOperator::remove(FileManipulatorThread* manipulator) { - manipulator->wait(); - layout()->removeWidget(manipulator->progressBar); - manipulatorList.removeAll(manipulator); - delete manipulator; + op->wake(); } -void FileOperator::setBarSize(FileManipulatorThread* manipulator, unsigned int size) { - manipulator->progressBar->setMinimum(0); - manipulator->progressBar->setMaximum(size); +void FileOperator::remove(OperationThread* op) { + op->wait(); + ProgressBar *bar = get(op); + layout()->removeWidget(bar); + opList.removeAll(qMakePair(op, bar)); + delete op; + delete bar; } -void FileOperator::updateProgress(FileManipulatorThread* manipulator, int value) { - manipulator->setText(value); -} - - -void FileOperator::updateMainText(FileManipulatorThread* manipulator, const QString &text) { - manipulator->progressBar->mainText = text; - manipulator->progressBar->mainText.remove(0, manipulator->progressBar->fromText.size() + 1); - manipulator->progressBar->repaint(); -} - +void FileOperator::togglePauseOperation(ProgressBar* bar) { + OperationThread *op = get(bar); -void FileOperator::showPaused(FileManipulatorThread* manipulator) { - manipulator->progressBar->paused = true; - manipulator->progressBar->repaint(); -} - - -void FileOperator::togglePauseOperation(FileManipulatorThread* manipulator) { - if (manipulator->pause) { - manipulator->pause = false; - manipulator->progressBar->paused = false; - manipulator->progressBar->repaint(); - manipulator->wake(); + if (op->pause) { + op->wake(); } else { - manipulator->pause = true; + op->pause = true; } } -void FileOperator::abortOperation(FileManipulatorThread* manipulator) { +void FileOperator::abortOperation(ProgressBar* bar) { + OperationThread *op = get(bar); + int confirm = QMessageBox::warning( 0, tr("Abort operation"), @@ -415,598 +276,52 @@ void FileOperator::abortOperation(FileManipulatorThread* manipulator) { ); if(confirm == QMessageBox::Yes) { - manipulator->abort = true; - manipulator->pause = false; - manipulator->wake(); - } -} - - -void FileOperator::caterNewThread(FileManipulatorThread *thread) { - manipulatorList.append(thread); - - connect(thread, SIGNAL(showErrorPrompt(FileManipulatorThread*, const QString&, const QString&, const int)), - 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)), - this, SLOT(setBarSize(FileManipulatorThread*, unsigned int))); - connect(thread, SIGNAL(updateProgress(FileManipulatorThread*, int)), - this, SLOT(updateProgress(FileManipulatorThread*, int))); - connect(thread, SIGNAL(updateFileName(FileManipulatorThread*, QString)), - this, SLOT(updateMainText(FileManipulatorThread*, QString))); - connect(thread, SIGNAL(operationPaused(FileManipulatorThread*)), - this, SLOT(showPaused(FileManipulatorThread*))); - - connect(thread->progressBar, SIGNAL(togglePauseOperation(FileManipulatorThread*)), - this, SLOT(togglePauseOperation(FileManipulatorThread*))); - connect(thread->progressBar, SIGNAL(abortOperation(FileManipulatorThread*)), - this, SLOT(abortOperation(FileManipulatorThread*))); - - layout()->addWidget(thread->progressBar); - thread->start(QThread::LowestPriority); -} - - -FileManipulatorThread::FileManipulatorThread(const QFileInfoList files, QDir dest) : - progressBar(new ProgressBar(this)), - abort(false), - pause(false), - files(files), - dest(dest), - response(FileOperator::NONE), - overwriteAll(FileOperator::NONE), - lastTimeUpdate(0), - startTime(0), - waitTime(0), - barSize(0), - barValue(0), - fileSize(0), - fileValue(0) -{ - memset(ignoreAll, false, sizeof(ignoreAll)); -} - - -FileManipulatorThread::~FileManipulatorThread() { - if (!abort && 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; -} - - -void FileManipulatorThread::setResponse( - const FileOperator::Response response, - const bool applyToAll, - const int err) -{ - mutex.lock(); - - this->response = response; - - if (applyToAll) { - if (response == FileOperator::KEEP - || response == FileOperator::OVERWRITE - || response == FileOperator::NONE) - { - overwriteAll = response; - } - - if (response == FileOperator::IGNORE) { - ignoreAll[err] = true; - } - } - - if (response == FileOperator::ABORT) abort = true; - - mutex.unlock(); - wake(); -} - - -void FileManipulatorThread::processFiles(const QFileInfoList &files) { - for (QFileInfoList::const_iterator it = files.begin(); it != files.end(); ++it) { - PAUSE(); - if (abort) break; - perform(*it); - } -} - - -bool FileManipulatorThread::remove(QString &fileName, const bool doUpdates) { - return remove(QFileInfo(fileName), doUpdates); -} - - -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, doUpdates)) res = false; - PAUSE(); - if (abort) break; - } - return res; -} - - -bool FileManipulatorThread::remove(const QFileInfo &file, const bool doUpdates) { - std::cout << "DELETING " << file.absoluteFilePath().toStdString() << std::endl; - - QString path = file.absoluteFilePath(); - - if (removeExcludeFiles.contains(path)) { - if (doUpdates) updateProgress(1); - return false; - } - - QFSFileEngine engine(path); - - if (doUpdates) updateFile(path); - - if (file.isDir()) { - if (!remove(listDirFiles(path), doUpdates)) { - if (doUpdates) updateProgress(1); - return false; - } - - 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 && doUpdates) updateProgress(1); - - PAUSE(); - if (abort || response == FileOperator::IGNORE) return false; - return true; -} - - -void FileManipulatorThread::copy(const QFileInfo &file) { - std::cout << "COPYING " << file.absoluteFilePath().toStdString() - << " to " << dest.absolutePath().toStdString() << std::endl; - - QString path(file.absoluteFilePath()); - QFSFileEngine engine(path); - QFileInfo newFile(dest.absolutePath() + "/" + file.fileName()); - - updateFile(path); - - // hack to prevent asking about the same file if we already asked in the rename(...) function - if (overwriteAll == FileOperator::DONT_ASK_ONCE) { - overwriteAll = FileOperator::NONE; - } else { - OVERWRITE_PROMPT(file, newFile) - } - - QString newPath(newFile.absoluteFilePath()); - QFSFileEngine newEngine(newPath); - - PAUSE(); - if (abort) return; - - if (file.isDir()) { - // save the overwrite response, because the response variable will get ovewritten in remove(...) - FileOperator::Response overwriteResponse = response; - - if (newFile.exists() && !newFile.isDir()) { - // overwriting a file, so check for KEEP and handle it - if (response == FileOperator::KEEP) { - updateProgress(fileSizeMap[path]); - removeExcludeFiles.insert(path); - return; - } - - // if it should not be kept, remove it and return on failure - if(!remove(newPath)) { - updateProgress(fileSizeMap[path]); - return; - } - // create new info since we deleted the file - is it needed? - newFile = QFileInfo(newPath); - } else { - // overwriting a directory - response KEEP means to keep the files inside, - // SKIP_DIR means to skip the dir completely - if (response == FileOperator::SKIP_DIR) { - updateProgress(fileSizeMap[path]); - removeExcludeFiles.insert(path); - return; - } - } - - if (!newFile.exists()) { - SPECIAL_COPY_ERROR_PROMPT(!engine.mkdir(newPath, false), - tr("Error creating directory %1."), newPath) - } - - // we've done the job with the dir, so update progress and recurse into the dir - updateProgress(1); - - // change the dest for the recursion - QDir destBackup = dest; - dest = newPath; - - // and set overwriteAll to the response we got a while ago - // because it applies to the files inside the dir - FileOperator::Response tmpResp = overwriteAll; - overwriteAll = overwriteResponse; - - processFiles(listDirFiles(path)); - - overwriteAll = tmpResp; - - ERROR_PROMPT(!newEngine.setPermissions(file.permissions()), - tr("Error setting permissions for directory %1."), newPath) - - PAUSE(); - if (abort) return; - - dest = destBackup; - } else { - if (response == FileOperator::KEEP) { - updateProgress(fileSizeMap[path]); - removeExcludeFiles.insert(path); - return; - } - - SPECIAL_COPY_ERROR_PROMPT(checkSequentialFile(engine), tr("Cannot copy file %1."), path) - - if (newFile.exists() && newFile.isDir()) { - SPECIAL_COPY_ERROR_PROMPT(!remove(newPath), - tr("Cannot replace directory %1 due to previous errors."), newPath) - } - - SPECIAL_COPY_ERROR_PROMPT(!engine.open(QIODevice::ReadOnly), tr("Error reading file %1."), path) - - bool ignore = false, newFileWritten = false; - while (!abort && !ignore) { - engine.seek(0); - fileValue = 0; - - 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]); - removeExcludeFiles.insert(path); - ignore = true; - } - break; - } - - newFileWritten = 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); - } - - if (!abort) { - if (response == FileOperator::IGNORE) { - updateProgress(fileSizeMap[path] - fileValue); - removeExcludeFiles.insert(path); - ignore = true; - } else { - updateProgress(-fileValue); - } - } - error = true; - break; - } - - PAUSE(); - if (abort) break; - - updateProgress(1); - } - - if (!error) break; - PAUSE(); - } - - engine.close(); - newEngine.close(); - - PAUSE(); - if (abort || ignore) { - if (newFileWritten) { - newEngine.remove(); - } - } else { - ERROR_PROMPT(!newEngine.setPermissions(file.permissions()), - tr("Error setting permissions for file %1."), newPath) - } - } -} - - -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 = 0; - - PAUSE(); - if (abort) break; - - if (it->isDir()) { - size += calculateFileSize(listDirFiles(it->absoluteFilePath()), count, addSize); - } - - if (addSize) { - if (it->isDir()) { - ++size; - } else { - size += ceil(static_cast(it->size()) / BLOCK_SIZE); - } - fileSizeMap[it->absoluteFilePath()] = size; - } - - if (count) { - ++size; - } - - res += size; + op->abort = true; + op->pause = false; + op->wake(); } - - return res; -} - - -QFileInfoList FileManipulatorThread::listDirFiles(const QString &dirPath) { - QDir dir = dirPath; - return dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries | QDir::System | QDir::Hidden); } -void FileManipulatorThread::setBarSize(unsigned int size) { - barSize = size; - emit setBarSize(this, size); -} +void FileOperator::initOperation(OperationThread *thread, ProgressBar *bar) { + opList.append(qMakePair(thread, bar)); + connect(thread, SIGNAL(showErrorPrompt(OperationThread*, const QString&, const QString&, const int)), + this, SLOT(showErrorPrompt(OperationThread*, const QString&, const QString&, const int))); + connect(thread, SIGNAL(showOverwritePrompt(OperationThread*, const QString&, bool)), + this, SLOT(showOverwritePrompt(OperationThread*, const QString&, bool))); + connect(thread, SIGNAL(showInputFilenamePrompt(OperationThread*, const QFileInfo&, bool)), + this, SLOT(showInputFilenamePrompt(OperationThread*, const QFileInfo&, bool))); + connect(thread, SIGNAL(finished(OperationThread*)), + this, SLOT(remove(OperationThread*))); -void FileManipulatorThread::updateProgress(int value) { - barValue += value; - fileValue += value; - emit updateProgress(this, value); -} - - -void FileManipulatorThread::updateFile(const QString &name) { - fileValue = 0; - emit updateFileName(this, FileOperator::shortenPath(name)); -} + connect(thread, SIGNAL(totalSizeChanged(int)), bar, SLOT(setMaximum(int))); + connect(thread, SIGNAL(progressUpdate(int)), bar, SLOT(updateProgress(int))); + connect(thread, SIGNAL(fileNameUpdated(QString)), bar, SLOT(updateMainText(QString))); + connect(thread, SIGNAL(operationStarted(time_t)), bar, SLOT(setStartTime(time_t))); + connect(thread, SIGNAL(operationPaused()), bar, SLOT(pause())); + connect(thread, SIGNAL(operationResumed(time_t)), bar, SLOT(resume(time_t))); + connect(thread, SIGNAL(removeAfterCopy()), bar, SLOT(showRemoveNotice())); + connect(bar, SIGNAL(togglePauseOperation(ProgressBar*)), this, SLOT(togglePauseOperation(ProgressBar*))); + connect(bar, SIGNAL(abortOperation(ProgressBar*)), this, SLOT(abortOperation(ProgressBar*))); -void FileManipulatorThread::waitOnCond() { - waitTime = time(0); - waitCond.wait(&mutex); -} - - -bool FileManipulatorThread::checkSequentialFile(const QFSFileEngine &engine) { - errno = 0; - if (engine.isSequential()) { - if (!errno) errno = 255; - return true; - } - - return false; -} - - -void FileManipulatorThread::wake() { - startTime += time(0) - waitTime; - waitCond.wakeAll(); + layout()->addWidget(bar); + thread->start(QThread::LowestPriority); } -void FileManipulatorThread::setText(int value) { - if (progressBar->value() + value > progressBar->maximum()) { - std::cout << "WARNING: exceeding progressbar maximum (" << progressBar->maximum() - << ") by " << value << std::endl; - } - - time_t now = time(0); - if (lastTimeUpdate < now) { - lastTimeUpdate = now; - - time_t elapsed = now - startTime; - time_t remaining = (time_t) ((float) elapsed / barValue * (barSize - barValue)); - struct tm *ts = gmtime(&remaining); - - if (remaining < 60) { - strftime(timeBuf, sizeof(timeBuf), "%Ss", ts); - } else if (remaining < 3600) { - strftime(timeBuf, sizeof(timeBuf), "%M:%S", ts); - } else { - strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", ts); - } +ProgressBar *FileOperator::get(OperationThread *op) const { + for (OperationList::const_iterator it = opList.begin(); it != opList.end(); ++it) { + if (it->first == op) return it->second; } - - - progressBar->setFormat(QString("%p% ") + timeBuf); - progressBar->setValue(progressBar->value() + value); -} - - -DeleteThread::DeleteThread(const QFileInfoList &files) : FileManipulatorThread(files) { - barText = tr("deleting %1"); -} - - -void DeleteThread::run() { - mutex.lock(); - - setBarSize(calculateFileSize(files, true)); - startTime = time(0); - - processFiles(files); - - sleep(0.5); - emit finished(this); -} - - -void DeleteThread::perform(const QFileInfo &file) { - remove(file, true); -} - - -CopyThread::CopyThread(const QFileInfoList &files, QDir &dest) : FileManipulatorThread(files, dest) { - barText = tr("copying %1"); -} - - -void CopyThread::run() { - mutex.lock(); - - setBarSize(calculateFileSize(files, false, true)); - startTime = time(0); - - processFiles(files); - - sleep(0.5); - emit finished(this); -} - - -void CopyThread::perform(const QFileInfo &file) { - copy(file); -} - - -MoveThread::MoveThread(const QFileInfoList &files, QDir &dest) : FileManipulatorThread(files, dest) { - barText = tr("moving %1"); + return 0; } -void MoveThread::run() { - mutex.lock(); - - rename(files, dest); - - sleep(0.5); - emit finished(this); -} - - -void MoveThread::rename(const QFileInfoList &files, const QDir &dest) { - setBarSize(barSize + files.size()); - startTime = time(0); - - for (int i = 0; i < files.size(); ++i) { - QString path = files[i].absoluteFilePath(); - QFSFileEngine engine(path); - 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) { - PAUSE(); - if (abort) break; - updateProgress(1); - removeExcludeFiles.insert(path); - continue; - } - } else { - if (response == FileOperator::KEEP) { - PAUSE(); - if (abort) break; - updateProgress(1); - removeExcludeFiles.insert(path); - continue; - } - } - - QString newPath(newFile.absoluteFilePath()); - QFSFileEngine newEngine(newPath); - - bool done = false; - - 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 - // we calculate the actual file sizes, because from now on copy & remove takes over - if (errno == EXDEV) { - 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; - - QFileInfoList remainingFiles = files.mid(i); - - setBarSize(barValue + calculateFileSize(remainingFiles, true, true)); - - processFiles(remainingFiles); - - barText = tr("deleting %1"); - - remove(remainingFiles, true); - - done = true; - break; - // the target is nonempty dir. lets call this recursively and rename the contents one by one - } else if (errno == ENOTEMPTY || errno == EEXIST) { - FileOperator::Response tmpResp = overwriteAll; - overwriteAll = response; - - rename(listDirFiles(path), QDir(newPath)); - PAUSE(); - if (abort) break; - - overwriteAll = tmpResp; - - remove(files[i]); - - break; - // source and target are nonmatching types(file and dir) - // remove the target and let it loop once again - } else if (errno == ENOTDIR || errno == EISDIR) { - if (!remove(newPath)) break; - } else { - SHOW_ERROR_PROMPT(tr("Error moving %1."), path) - - if (response == FileOperator::IGNORE) { - break; - } - } - PAUSE(); - } - - if (done) break; - - PAUSE(); - if (abort) break; - updateProgress(1); +OperationThread *FileOperator::get(ProgressBar *bar) const { + for (OperationList::const_iterator it = opList.begin(); it != opList.end(); ++it) { + if (it->second == bar) return it->first; } -} - - -void MoveThread::perform(const QFileInfo &file) { - copy(file); + return 0; }