diff options
author | Petr Mrázek <peterix@gmail.com> | 2016-10-26 18:12:33 +0200 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2016-10-26 18:21:25 +0200 |
commit | 1b4851a941cbafb7bf7a45feee7149cefa7e0acb (patch) | |
tree | 6626a47c9d2f2b4a37302b0e036ab1ffc5033f3f | |
parent | d66fdcd4cc6913508d2987c14cd9fc4d6760b8a5 (diff) | |
download | MultiMC-1b4851a941cbafb7bf7a45feee7149cefa7e0acb.tar MultiMC-1b4851a941cbafb7bf7a45feee7149cefa7e0acb.tar.gz MultiMC-1b4851a941cbafb7bf7a45feee7149cefa7e0acb.tar.lz MultiMC-1b4851a941cbafb7bf7a45feee7149cefa7e0acb.tar.xz MultiMC-1b4851a941cbafb7bf7a45feee7149cefa7e0acb.zip |
NOISSUE use QtConcurrent to run FS operations in worker threads
Not all operations - only the ones that aren't in error handling.
The API for QFuture is too nasty to do much more in a sensible way.
-rw-r--r-- | api/logic/FileSystem.h | 1 | ||||
-rw-r--r-- | api/logic/FolderInstanceProvider.cpp | 4 | ||||
-rw-r--r-- | api/logic/InstanceCopyTask.cpp | 35 | ||||
-rw-r--r-- | api/logic/InstanceCopyTask.h | 8 | ||||
-rw-r--r-- | api/logic/InstanceImportTask.cpp | 32 | ||||
-rw-r--r-- | api/logic/InstanceImportTask.h | 7 | ||||
-rw-r--r-- | application/groupview/GroupView.cpp | 2 |
7 files changed, 70 insertions, 19 deletions
diff --git a/api/logic/FileSystem.h b/api/logic/FileSystem.h index 80637f90..564f94f9 100644 --- a/api/logic/FileSystem.h +++ b/api/logic/FileSystem.h @@ -43,7 +43,6 @@ MULTIMC_LOGIC_EXPORT bool ensureFolderPathExists(QString filenamepath); class MULTIMC_LOGIC_EXPORT copy { public: - copy(const copy&) = delete; copy(const QString & src, const QString & dst) { m_src = src; diff --git a/api/logic/FolderInstanceProvider.cpp b/api/logic/FolderInstanceProvider.cpp index a1f3f1f2..ea0d4ef0 100644 --- a/api/logic/FolderInstanceProvider.cpp +++ b/api/logic/FolderInstanceProvider.cpp @@ -113,7 +113,7 @@ InstancePtr FolderInstanceProvider::loadInstance(const InstanceId& id) #include "InstanceImportTask.h" Task * FolderInstanceProvider::zipImportTask(const QUrl sourceUrl, const QString& instName, const QString& instGroup, const QString& instIcon) { - return new InstanceImportTask(m_globalSettings, sourceUrl, this, instName, instGroup, instIcon); + return new InstanceImportTask(m_globalSettings, sourceUrl, this, instName, instIcon, instGroup); } #include "InstanceCreationTask.h" @@ -346,7 +346,7 @@ bool FolderInstanceProvider::commitStagedInstance(const QString& keyPath, const emit instancesChanged(); } saveGroupList(); - return destroyStagingPath(keyPath); + return true; } bool FolderInstanceProvider::destroyStagingPath(const QString& keyPath) diff --git a/api/logic/InstanceCopyTask.cpp b/api/logic/InstanceCopyTask.cpp index 1e231478..3150c383 100644 --- a/api/logic/InstanceCopyTask.cpp +++ b/api/logic/InstanceCopyTask.cpp @@ -4,6 +4,7 @@ #include "FileSystem.h" #include "NullInstance.h" #include "pathmatcher/RegexpMatcher.h" +#include <QtConcurrentRun> InstanceCopyTask::InstanceCopyTask(SettingsObjectPtr settings, BaseInstanceProvider* target, InstancePtr origInstance, const QString& instName, const QString& instIcon, const QString& instGroup, bool copySaves) { @@ -28,26 +29,42 @@ void InstanceCopyTask::executeTask() matcher.reset(matcherReal); } - QString stagingPath = m_target->getStagedInstancePath(); - FS::copy folderCopy(m_origInstance->instanceRoot(), stagingPath); + m_stagingPath = m_target->getStagedInstancePath(); + FS::copy folderCopy(m_origInstance->instanceRoot(), m_stagingPath); folderCopy.followSymlinks(false).blacklist(matcher.get()); - if (!folderCopy()) + + m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), folderCopy); + connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &InstanceCopyTask::copyFinished); + connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &InstanceCopyTask::copyAborted); + m_copyFutureWatcher.setFuture(m_copyFuture); +} + +void InstanceCopyTask::copyFinished() +{ + auto successful = m_copyFuture.result(); + if(!successful) { - m_target->destroyStagingPath(stagingPath); + m_target->destroyStagingPath(m_stagingPath); emitFailed(tr("Instance folder copy failed.")); return; } - // FIXME: shouldn't this be able to report errors? - auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(stagingPath, "instance.cfg")); + auto instanceSettings = std::make_shared<INISettingsObject>(FS::PathCombine(m_stagingPath, "instance.cfg")); instanceSettings->registerSetting("InstanceType", "Legacy"); // FIXME: and this too? errors??? - m_origInstance->copy(stagingPath); + m_origInstance->copy(m_stagingPath); - InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, stagingPath)); + InstancePtr inst(new NullInstance(m_globalSettings, instanceSettings, m_stagingPath)); inst->setName(m_instName); inst->setIconKey(m_instIcon); - m_target->commitStagedInstance(stagingPath, stagingPath, m_instName, m_instGroup); + m_target->commitStagedInstance(m_stagingPath, m_stagingPath, m_instName, m_instGroup); emitSucceeded(); } + +void InstanceCopyTask::copyAborted() +{ + m_target->destroyStagingPath(m_stagingPath); + emitFailed(tr("Instance folder copy has been aborted.")); + return; +} diff --git a/api/logic/InstanceCopyTask.h b/api/logic/InstanceCopyTask.h index a663ddbd..1ecf8313 100644 --- a/api/logic/InstanceCopyTask.h +++ b/api/logic/InstanceCopyTask.h @@ -4,10 +4,13 @@ #include "multimc_logic_export.h" #include "net/NetJob.h" #include <QUrl> +#include <QFuture> +#include <QFutureWatcher> #include "settings/SettingsObject.h" #include "BaseVersion.h" #include "BaseInstance.h" + class BaseInstanceProvider; class MULTIMC_LOGIC_EXPORT InstanceCopyTask : public Task @@ -20,6 +23,8 @@ public: protected: //! Entry point for tasks. virtual void executeTask() override; + void copyFinished(); + void copyAborted(); private: /* data */ SettingsObjectPtr m_globalSettings; @@ -28,7 +33,10 @@ private: /* data */ QString m_instName; QString m_instIcon; QString m_instGroup; + QString m_stagingPath; bool m_copySaves = false; + QFuture<bool> m_copyFuture; + QFutureWatcher<bool> m_copyFutureWatcher; }; diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp index 99f2553f..23897778 100644 --- a/api/logic/InstanceImportTask.cpp +++ b/api/logic/InstanceImportTask.cpp @@ -8,6 +8,7 @@ #include "NullInstance.h" #include "settings/INISettingsObject.h" #include "icons/IIconList.h" +#include <QtConcurrentRun> InstanceImportTask::InstanceImportTask(SettingsObjectPtr settings, const QUrl sourceUrl, BaseInstanceProvider * target, const QString &instName, const QString &instIcon, const QString &instGroup) @@ -86,19 +87,29 @@ static QFileInfo findRecursive(const QString &dir, const QString &name) void InstanceImportTask::extractAndTweak() { setStatus(tr("Extracting modpack")); - QString stagingPath = m_target->getStagedInstancePath(); - QDir extractDir(stagingPath); + m_stagingPath = m_target->getStagedInstancePath(); + QDir extractDir(m_stagingPath); qDebug() << "Attempting to create instance from" << m_archivePath; - if (MMCZip::extractDir(m_archivePath, extractDir.absolutePath()).isEmpty()) + + m_extractFuture = QtConcurrent::run(QThreadPool::globalInstance(), MMCZip::extractDir, m_archivePath, extractDir.absolutePath()); + connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::finished, this, &InstanceImportTask::extractFinished); + connect(&m_extractFutureWatcher, &QFutureWatcher<QStringList>::canceled, this, &InstanceImportTask::extractAborted); + m_extractFutureWatcher.setFuture(m_extractFuture); +} + +void InstanceImportTask::extractFinished() +{ + if (m_extractFuture.result().isEmpty()) { - m_target->destroyStagingPath(stagingPath); + m_target->destroyStagingPath(m_stagingPath); emitFailed(tr("Failed to extract modpack")); return; } + QDir extractDir(m_stagingPath); const QFileInfo instanceCfgFile = findRecursive(extractDir.absolutePath(), "instance.cfg"); if (!instanceCfgFile.isFile() || !instanceCfgFile.exists()) { - m_target->destroyStagingPath(stagingPath); + m_target->destroyStagingPath(m_stagingPath); emitFailed(tr("Archive does not contain instance.cfg")); return; } @@ -136,11 +147,18 @@ void InstanceImportTask::extractAndTweak() iconList->installIcons({importIconPath}); } } - if (!m_target->commitStagedInstance(stagingPath, actualDir, m_instName, m_instGroup)) + if (!m_target->commitStagedInstance(m_stagingPath, actualDir, m_instName, m_instGroup)) { - m_target->destroyStagingPath(stagingPath); + m_target->destroyStagingPath(m_stagingPath); emitFailed(tr("Unable to commit instance")); return; } emitSucceeded(); } + +void InstanceImportTask::extractAborted() +{ + m_target->destroyStagingPath(m_stagingPath); + emitFailed(tr("Instance import has been aborted.")); + return; +} diff --git a/api/logic/InstanceImportTask.h b/api/logic/InstanceImportTask.h index a551ec68..fe227e07 100644 --- a/api/logic/InstanceImportTask.h +++ b/api/logic/InstanceImportTask.h @@ -4,6 +4,8 @@ #include "multimc_logic_export.h" #include "net/NetJob.h" #include <QUrl> +#include <QFuture> +#include <QFutureWatcher> #include "settings/SettingsObject.h" class BaseInstanceProvider; @@ -26,6 +28,8 @@ private slots: void downloadSucceeded(); void downloadFailed(QString reason); void downloadProgressChanged(qint64 current, qint64 total); + void extractFinished(); + void extractAborted(); private: /* data */ SettingsObjectPtr m_globalSettings; @@ -37,4 +41,7 @@ private: /* data */ QString m_instName; QString m_instIcon; QString m_instGroup; + QString m_stagingPath; + QFuture<QStringList> m_extractFuture; + QFutureWatcher<QStringList> m_extractFutureWatcher; }; diff --git a/application/groupview/GroupView.cpp b/application/groupview/GroupView.cpp index aa85bec7..5a380318 100644 --- a/application/groupview/GroupView.cpp +++ b/application/groupview/GroupView.cpp @@ -641,6 +641,8 @@ QRect GroupView::geometryRect(const QModelIndex &index) const QModelIndex GroupView::indexAt(const QPoint &point) const { + const_cast<GroupView*>(this)->executeDelayedItemsLayout(); + for (int i = 0; i < model()->rowCount(); ++i) { QModelIndex index = model()->index(i, 0); |