summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArno <arno@disconnect.de>2016-12-03 00:00:16 +0100
committerArno <arno@disconnect.de>2016-12-03 00:00:16 +0100
commit0432c09d7889009beb9557e0546d0c4f240bb37e (patch)
treeb401ce1815e4e33e4ef79b9a69727f70a80e6e1b
parentc8d8c71460c7e7d403c9dba1addc850a361d3e9c (diff)
downloadShemovCleaner-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.pro8
-rw-r--r--filecopier.cpp66
-rw-r--r--filecopier.h29
-rw-r--r--filewidget.cpp68
-rw-r--r--filewidget.h9
-rw-r--r--progressdialog.cpp25
-rw-r--r--progressdialog.h27
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