summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2016-10-26 18:12:33 +0200
committerPetr Mrázek <peterix@gmail.com>2016-10-26 18:21:25 +0200
commit1b4851a941cbafb7bf7a45feee7149cefa7e0acb (patch)
tree6626a47c9d2f2b4a37302b0e036ab1ffc5033f3f
parentd66fdcd4cc6913508d2987c14cd9fc4d6760b8a5 (diff)
downloadMultiMC-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.h1
-rw-r--r--api/logic/FolderInstanceProvider.cpp4
-rw-r--r--api/logic/InstanceCopyTask.cpp35
-rw-r--r--api/logic/InstanceCopyTask.h8
-rw-r--r--api/logic/InstanceImportTask.cpp32
-rw-r--r--api/logic/InstanceImportTask.h7
-rw-r--r--application/groupview/GroupView.cpp2
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);