diff options
author | Arno <arno@disconnect.de> | 2016-12-03 00:00:16 +0100 |
---|---|---|
committer | Arno <arno@disconnect.de> | 2016-12-03 00:00:16 +0100 |
commit | 0432c09d7889009beb9557e0546d0c4f240bb37e (patch) | |
tree | b401ce1815e4e33e4ef79b9a69727f70a80e6e1b | |
parent | c8d8c71460c7e7d403c9dba1addc850a361d3e9c (diff) | |
download | ShemovCleaner-0432c09d7889009beb9557e0546d0c4f240bb37e.tar.gz ShemovCleaner-0432c09d7889009beb9557e0546d0c4f240bb37e.tar.bz2 ShemovCleaner-0432c09d7889009beb9557e0546d0c4f240bb37e.zip |
Actually use Copy Files to...
Create a FileCopier and show a custom, non-modal progress dialog when
we're copying files.
Turns out that a QProgressDialog always shows when it's created. This is
by design, so I had to implement one that fits my needs.
Also, a buffer size of 32K (as used in MKVMerger) is way too small to
max out the available bandwidth, so I set it to an (arbitrary) value of
16MB.
-rw-r--r-- | ShemovCleaner.pro | 8 | ||||
-rw-r--r-- | filecopier.cpp | 66 | ||||
-rw-r--r-- | filecopier.h | 29 | ||||
-rw-r--r-- | filewidget.cpp | 68 | ||||
-rw-r--r-- | filewidget.h | 9 | ||||
-rw-r--r-- | progressdialog.cpp | 25 | ||||
-rw-r--r-- | progressdialog.h | 27 |
7 files changed, 229 insertions, 3 deletions
diff --git a/ShemovCleaner.pro b/ShemovCleaner.pro index f838cce..acf5065 100644 --- a/ShemovCleaner.pro +++ b/ShemovCleaner.pro @@ -27,7 +27,9 @@ SOURCES += main.cpp\ globals.cpp \ actorwidget.cpp \ origindialog.cpp \ - viewer.cpp + viewer.cpp \ + filecopier.cpp \ + progressdialog.cpp HEADERS += \ filesorter.h \ @@ -42,7 +44,9 @@ HEADERS += \ globals.h \ actorwidget.h \ origindialog.h \ - viewer.h + viewer.h \ + filecopier.h \ + progressdialog.h DISTFILES += diff --git a/filecopier.cpp b/filecopier.cpp new file mode 100644 index 0000000..3475b74 --- /dev/null +++ b/filecopier.cpp @@ -0,0 +1,66 @@ +#include <QMutexLocker> +#include <QFile> + +#include "filecopier.h" + +FileCopier::FileCopier(QObject *parent) : QThread(parent), mCancel(false){} + +void FileCopier::addJob(const QString &source, const QString &dest){ + QMutexLocker l(&mAddJobMutex); + if(!mJobs.contains(source)){ + mJobs[source] = dest; + } +} + +QHash<QString, QString> FileCopier::jobs(){ + QMutexLocker l(&mAddJobMutex); + return mJobs; +} + +void FileCopier::run(){ + int bufsize = 16 * 1024 * 1024; + char *buf = new char[bufsize]; + mCancel = false; + while(!mJobs.isEmpty()){ + mAddJobMutex.lock(); + auto first = mJobs.constBegin(); + auto source = first.key(); + auto dest = first.value(); + mJobs.remove(source); + mAddJobMutex.unlock(); + QFile sFile(source); + QFile dFile(dest); + bool openSource = sFile.open(QIODevice::ReadOnly); + bool openDest = dFile.open(QIODevice::WriteOnly); + if(!openSource || !openDest){ + emit success(false, source); + goto cleanup; + } + emit newFile(source, sFile.size()); + int read = 0; + qint64 total = 0; + while(!sFile.atEnd()){ + mCancelMutex.lock(); + bool cancel = mCancel; + mCancelMutex.unlock(); + if(cancel){ + QFile::remove(dest); + emit success(false, source); + goto cleanup; + } + read = sFile.read(buf, bufsize); + dFile.write(buf, read); + total += read; + emit bytesRead(total); + } + emit success(true, source); + } + + cleanup: + delete buf; +} + +void FileCopier::cancel(){ + QMutexLocker l(&mCancelMutex); + mCancel = true; +} diff --git a/filecopier.h b/filecopier.h new file mode 100644 index 0000000..8ffdd4d --- /dev/null +++ b/filecopier.h @@ -0,0 +1,29 @@ +#ifndef FILECOPIER_H +#define FILECOPIER_H + +#include <QThread> +#include <QMutex> +#include <QHash> + +class FileCopier : public QThread { + Q_OBJECT + public: + FileCopier(QObject *parent = 0); + void addJob(const QString &source, const QString &dest); + QHash<QString, QString> jobs(); + virtual void run(); + void cancel(); + + signals: + void newFile(const QString &source, qint64 size); + void success(bool s, QString source); + void bytesRead(qint64 bytes); + + private: + QHash<QString, QString> mJobs; + QMutex mAddJobMutex; + QMutex mCancelMutex; + bool mCancel; +}; + +#endif // FILECOPIER_H diff --git a/filewidget.cpp b/filewidget.cpp index 30254d4..409c551 100644 --- a/filewidget.cpp +++ b/filewidget.cpp @@ -35,12 +35,21 @@ #include "filewidget.h" #include "filesorter.h" #include "filedisplay.h" +#include "filecopier.h" #include "origindialog.h" #include "helper.h" #include "globals.h" #include "viewer.h" +#include "progressdialog.h" FileWidget::FileWidget(QWidget *parent) : QWidget(parent), mCopyToMenu(0), mCopyToMapper(0) { + mFileCopier = new FileCopier(this); + mCopyProgress = new ProgressDialog; + connect(mFileCopier, SIGNAL(newFile(QString,qint64)), this, SLOT(setupProgress(QString,qint64))); + connect(mFileCopier, SIGNAL(bytesRead(qint64)), this, SLOT(setCopyProgress(qint64))); + connect(mFileCopier, SIGNAL(finished()), this, SLOT(hideCopyProgress())); + connect(mFileCopier, SIGNAL(success(bool,QString)), this, SLOT(copySuccess(bool,QString))); + connect(mCopyProgress, SIGNAL(cancelled()), this, SLOT(hideCopyProgress())); setupGui(); } @@ -116,6 +125,7 @@ void FileWidget::setupGui(){ createActions(); mMimeData = new QMimeData; mFileView->setFocus(); + mCopyProgress->setVisible(false); } void FileWidget::createActions(){ @@ -501,6 +511,59 @@ void FileWidget::addAsOrigin(){ mOrignDlg->show(); } +void FileWidget::setupProgress(QString file, qint64 size){ + mCopyProgress->setMaximum(size / 1024 / 1024); + mCopyProgress->setValue(0); + QString progressLabel = QString(tr("Copying %1")).arg(file); + mCopyProgress->setLabelText(progressLabel); +} + +void FileWidget::setCopyProgress(qint64 bytes){ + int val = bytes / 1024 / 1024; + mCopyProgress->setValue(val); +} + +void FileWidget::copyFiles(QString destDir){ + QModelIndexList files = mFileView->selectionModel()->selectedRows(); + if(!files.isEmpty()){ + foreach(auto idx, files){ + QString fp = idx.data(FullPathRole).toString(); + QFileInfo fi(fp); + if(!fi.exists()){ + continue; + } + QString destFile = QString("%1%2%3").arg(destDir).arg(QDir::separator()).arg(fi.fileName()); + mFileCopier->addJob(fp, destFile); + } + mCopyProgress->show(); + if(!mFileCopier->isRunning()){ + mFileCopier->start(); + } + } +} + +void FileWidget::hideCopyProgress(){ + if(mFileCopier->isRunning()){ + mFileCopier->cancel(); + } + mCopyProgress->hide(); +} + +void FileWidget::copySuccess(bool success, QString source){ + if(success){ + QFileInfo fi(source); + auto sourceFiles = mModel->findItems(fi.fileName(), Qt::MatchExactly, NameColumn); + if(!sourceFiles.isEmpty()){ + QModelIndex idx = mModel->indexFromItem(sourceFiles.first()); + if(idx.isValid()){ + QModelIndex copyIdx = idx.sibling(idx.row(), CopiedColumn); + mModel->setData(copyIdx, QColor(Qt::blue), Qt::ForegroundRole); + mModel->setData(copyIdx, QChar(0x2642)); + } + } + } +} + void FileWidget::fileSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ Q_UNUSED(selected); Q_UNUSED(deselected); @@ -645,7 +708,9 @@ void FileWidget::contextMenuEvent(QContextMenuEvent *e){ mCopyToMenu->clear(); mCopyToMenu->setTitle(tr("Copy Files to...")); mCopyToMenu->setIcon(QIcon(":/hourglass_figure.png")); - mCopyToMapper->deleteLater(); + if(mCopyToMapper){ + mCopyToMapper->deleteLater(); + } mCopyToMapper = new QSignalMapper; QStringList copyToDirs = s.value("copydirs").toStringList(); foreach(auto d, copyToDirs){ @@ -657,6 +722,7 @@ void FileWidget::contextMenuEvent(QContextMenuEvent *e){ mCopyToMenu->addAction(copyA); } } + connect(mCopyToMapper, SIGNAL(mapped(QString)), this, SLOT(copyFiles(QString))); contextMenu.addMenu(mCopyToMenu); contextMenu.addAction(createSeparator()); contextMenu.addActions(actions()); diff --git a/filewidget.h b/filewidget.h index 296944e..6d427ff 100644 --- a/filewidget.h +++ b/filewidget.h @@ -22,6 +22,8 @@ class FileDisplay; class OriginDialog; class QMenu; class QSignalMapper; +class FileCopier; +class ProgressDialog; class FileWidget : public QWidget { Q_OBJECT @@ -63,6 +65,11 @@ class FileWidget : public QWidget { void paste(); void selectFirst(); void addAsOrigin(); + void setupProgress(QString file, qint64 size); + void setCopyProgress(qint64 bytes); + void copyFiles(QString destDir); + void hideCopyProgress(); + void copySuccess(bool success, QString source); protected: virtual void keyPressEvent(QKeyEvent *e); @@ -107,9 +114,11 @@ class FileWidget : public QWidget { QAction *mPasteA; QAction *mDeleteA; QAction *mAddAsOriginA; + ProgressDialog *mCopyProgress; FileDisplay *mFileDisplay; VideoSorter *mProxy; OriginDialog *mOrignDlg; + FileCopier *mFileCopier; int mFileAction; }; diff --git a/progressdialog.cpp b/progressdialog.cpp new file mode 100644 index 0000000..778a3b4 --- /dev/null +++ b/progressdialog.cpp @@ -0,0 +1,25 @@ +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QPushButton> + +#include "progressdialog.h" + +ProgressDialog::ProgressDialog(QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f){ + mLabel = new QLabel; + mProgress = new QProgressBar; + QPushButton *cancelBtn = new QPushButton(tr("Cancel")); + connect(cancelBtn, SIGNAL(clicked()), this, SIGNAL(cancelled())); + QHBoxLayout *btnLayout = new QHBoxLayout; + btnLayout->addStretch(); + btnLayout->addWidget(cancelBtn); + btnLayout->addStretch(); + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addWidget(mLabel); + mainLayout->addWidget(mProgress); + mainLayout->addLayout(btnLayout); + setLayout(mainLayout); +} + +void ProgressDialog::setValue(int val){ + mProgress->setValue(val); +} diff --git a/progressdialog.h b/progressdialog.h new file mode 100644 index 0000000..6aee406 --- /dev/null +++ b/progressdialog.h @@ -0,0 +1,27 @@ +#ifndef PROGRESSDIALOG_H +#define PROGRESSDIALOG_H + +#include <QDialog> +#include <QLabel> +#include <QProgressBar> + +class ProgressDialog : public QDialog { + Q_OBJECT + public: + ProgressDialog(QWidget *parent = 0, Qt::WindowFlags f = 0); + void setLabelText(const QString &text) { mLabel->setText(text); } + void setMaximum(int max) { mProgress->setMaximum(max); } + + public slots: + void setValue(int val); + + signals: + void cancelled(); + + private: + QLabel *mLabel; + QProgressBar *mProgress; + +}; + +#endif // PROGRESSDIALOG_H |