diff --git a/installwizard.cpp b/installwizard.cpp index e45808c..2b61496 100644 --- a/installwizard.cpp +++ b/installwizard.cpp @@ -3,6 +3,7 @@ #include "ui_installwizard.h" #include "installwizard_installtype.h" #include "installwizard_locate.h" +#include "installwizard_copy.h" #include "installwizard_eula.h" #include "installwizard_install.h" #include "installwizard_patch.h" @@ -33,6 +34,7 @@ InstallWizard::InstallWizard(QWidget *parent, Settings *settings) : setPage(Page_Install, new InstallWizard_Install()); setPage(Page_Eula, new InstallWizard_Eula()); + setPage(Page_Copy, new InstallWizard_Copy()); setPage(Page_Patch, new InstallWizard_Patch()); setPage(Page_Finished, new InstallWizard_Finished()); } @@ -44,7 +46,11 @@ InstallWizard::~InstallWizard() void InstallWizard::cancel() { - if (currentId() == Page_Patch) + if (currentId() == Page_Copy) + { + ((InstallWizard_Copy *)currentPage())->cancel(); + } + else if (currentId() == Page_Patch) { ((InstallWizard_Patch *)currentPage())->cancel(); } diff --git a/installwizard.h b/installwizard.h index f3d292b..90b4d27 100644 --- a/installwizard.h +++ b/installwizard.h @@ -24,6 +24,7 @@ public: Page_Locate, Page_Install, Page_Eula, + Page_Copy, Page_Patch, Page_Finished }; diff --git a/installwizard_copy.cpp b/installwizard_copy.cpp new file mode 100644 index 0000000..161ce74 --- /dev/null +++ b/installwizard_copy.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include "installwizard_copy.h" +#include "ui_installwizard_copy.h" + +CopyWorker::CopyWorker() : isCancelled(false) +{ +} + +void CopyWorker::copy(const QString &source, const QString &destination) +{ + QFile sourceFile(source); + + if (!sourceFile.open(QIODevice::ReadOnly)) + { + emit errorMessage(QString("'%1': %2").arg(source).arg(sourceFile.errorString())); + return; + } + + QFile destinationFile(destination); + + if (!destinationFile.open(QIODevice::WriteOnly)) + { + emit errorMessage(QString("'%1': %2").arg(destination).arg(destinationFile.errorString())); + return; + } + + const qint64 totalBytes = sourceFile.size(); + qint64 totalBytesWritten = 0; + + for (;;) + { + const qint64 bytesRead = sourceFile.read(buffer, bufferSize); + + if (bytesRead == 0) + break; + + const qint64 bytesWritten = destinationFile.write(buffer, bytesRead); + totalBytesWritten += bytesWritten; + emit progressChanged(totalBytesWritten, totalBytes); + + /*if (totalBytesWritten > 1024 * 1024 * 10) + break;*/ + + QMutexLocker locker(&cancelMutex); + + if (isCancelled) + break; + } + + emit copyFinished(); +} + +void CopyWorker::cancel() +{ + QMutexLocker locker(&cancelMutex); + isCancelled = true; +} + +InstallWizard_Copy::InstallWizard_Copy(QWidget *parent) : + QWizardPage(parent), + ui(new Ui::InstallWizard_Copy), + copyWorker(NULL), + isCopyFinished(false) +{ + ui->setupUi(this); +} + +InstallWizard_Copy::~InstallWizard_Copy() +{ + copyThread.quit(); + copyThread.wait(); + delete ui; +} + +void InstallWizard_Copy::initializePage() +{ + isCopyFinished = false; + + // Try to create the destination directory and baseq3 subdirectory. + const QString quake3Path(field("quake3Path").toString() + QString("/baseq3")); + QDir dir; + + if (!dir.mkpath(quake3Path)) + { + ui->lblStatus->setText(QString("Error creating directory '%1'").arg(quake3Path)); + return; + } + + // Start copy thread. + copyWorker = new CopyWorker; + copyWorker->moveToThread(©Thread); + connect(©Thread, &QThread::finished, copyWorker, &QObject::deleteLater); + connect(this, &InstallWizard_Copy::copy, copyWorker, &CopyWorker::copy); + connect(copyWorker, &CopyWorker::progressChanged, this, &InstallWizard_Copy::setCopyProgress); + connect(copyWorker, &CopyWorker::errorMessage, this, &InstallWizard_Copy::setCopyErrorMessage); + connect(copyWorker, &CopyWorker::copyFinished, this, &InstallWizard_Copy::finishCopy); + copyThread.start(); + emit copy(field("pak0").toString(), quake3Path + QString("/pak0.pk3")); +} + +bool InstallWizard_Copy::isComplete() const +{ + return isCopyFinished; +} + +void InstallWizard_Copy::cancel() +{ + if (!isCopyFinished) + { + copyWorker->cancel(); + } +} + +void InstallWizard_Copy::setCopyProgress(qint64 bytesWritten, qint64 bytesTotal) +{ + ui->lblStatus->setText(QString("Copying %1MB / %2MB").arg(bytesWritten / 1024.0 / 1024.0, 0, 'f', 2).arg(bytesTotal / 1024.0 / 1024.0, 0, 'f', 2)); + ui->pbProgress->setMaximum((int)bytesTotal); + ui->pbProgress->setValue((int)bytesWritten); +} + +void InstallWizard_Copy::setCopyErrorMessage(const QString &message) +{ + ui->lblStatus->setText(message); +} + +void InstallWizard_Copy::finishCopy() +{ + copyThread.quit(); + copyThread.wait(); + isCopyFinished = true; + emit completeChanged(); +} diff --git a/installwizard_copy.h b/installwizard_copy.h new file mode 100644 index 0000000..560aa45 --- /dev/null +++ b/installwizard_copy.h @@ -0,0 +1,61 @@ +#ifndef INSTALLWIZARD_COPY_H +#define INSTALLWIZARD_COPY_H + +#include +#include +#include + +namespace Ui { +class InstallWizard_Copy; +} + +class CopyWorker : public QObject +{ + Q_OBJECT + +public: + CopyWorker(); + void cancel(); + +public slots: + void copy(const QString &source, const QString &destination); + +signals: + void progressChanged(qint64 bytesWritten, qint64 bytesTotal); + void errorMessage(const QString &message); + void copyFinished(); + +private: + static const int bufferSize = 32 * 1024; + char buffer[bufferSize]; + bool isCancelled; + QMutex cancelMutex; +}; + +class InstallWizard_Copy : public QWizardPage +{ + Q_OBJECT + +public: + explicit InstallWizard_Copy(QWidget *parent = 0); + ~InstallWizard_Copy(); + virtual void initializePage(); + virtual bool isComplete() const; + void cancel(); + +private slots: + void setCopyProgress(qint64 bytesWritten, qint64 bytesTotal); + void setCopyErrorMessage(const QString &message); + void finishCopy(); + +signals: + void copy(const QString &source, const QString &destination); + +private: + Ui::InstallWizard_Copy *ui; + CopyWorker *copyWorker; + QThread copyThread; + bool isCopyFinished; +}; + +#endif // INSTALLWIZARD_COPY_H diff --git a/installwizard_copy.ui b/installwizard_copy.ui new file mode 100644 index 0000000..1f2984f --- /dev/null +++ b/installwizard_copy.ui @@ -0,0 +1,38 @@ + + + InstallWizard_Copy + + + + 0 + 0 + 400 + 300 + + + + WizardPage + + + Installing Quake III Arena + + + + + + + + + + + + + 0 + + + + + + + + diff --git a/installwizard_eula.cpp b/installwizard_eula.cpp index 50d5663..204a5ba 100644 --- a/installwizard_eula.cpp +++ b/installwizard_eula.cpp @@ -1,5 +1,6 @@ #include "installwizard_eula.h" #include "ui_installwizard_eula.h" +#include "installwizard.h" InstallWizard_Eula::InstallWizard_Eula(QWidget *parent) : QWizardPage(parent), @@ -12,3 +13,13 @@ InstallWizard_Eula::~InstallWizard_Eula() { delete ui; } + +int InstallWizard_Eula::nextId() const +{ + if (!field("pak0").toString().isEmpty()) + { + return InstallWizard::Page_Copy; + } + + return InstallWizard::Page_Patch; +} diff --git a/installwizard_eula.h b/installwizard_eula.h index 3f4f6a3..22034e7 100644 --- a/installwizard_eula.h +++ b/installwizard_eula.h @@ -14,6 +14,7 @@ class InstallWizard_Eula : public QWizardPage public: explicit InstallWizard_Eula(QWidget *parent = 0); ~InstallWizard_Eula(); + virtual int nextId() const; private: Ui::InstallWizard_Eula *ui; diff --git a/installwizard_install.cpp b/installwizard_install.cpp index 8749208..ea29dcd 100644 --- a/installwizard_install.cpp +++ b/installwizard_install.cpp @@ -46,7 +46,7 @@ bool InstallWizard_Install::isComplete() const int InstallWizard_Install::nextId() const { - return InstallWizard::Page_Finished; + return InstallWizard::Page_Eula; } void InstallWizard_Install::on_btnBrowseSource_clicked() diff --git a/launch.pro b/launch.pro index 67710dd..a3c5c0a 100644 --- a/launch.pro +++ b/launch.pro @@ -21,7 +21,8 @@ SOURCES += main.cpp\ installwizard_finished.cpp \ installwizard_patch.cpp \ installwizard_eula.cpp \ - installwizard_install.cpp + installwizard_install.cpp \ + installwizard_copy.cpp HEADERS += mainwindow.h \ settings.h \ @@ -31,7 +32,8 @@ HEADERS += mainwindow.h \ installwizard_finished.h \ installwizard_patch.h \ installwizard_eula.h \ - installwizard_install.h + installwizard_install.h \ + installwizard_copy.h FORMS += mainwindow.ui \ installwizard.ui \ @@ -40,7 +42,8 @@ FORMS += mainwindow.ui \ installwizard_finished.ui \ installwizard_patch.ui \ installwizard_eula.ui \ - installwizard_install.ui + installwizard_install.ui \ + installwizard_copy.ui OTHER_FILES += \ README.md \