feat: add initial Migration dialog
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
This commit is contained in:
parent
bd7065eece
commit
086304f7f2
@ -38,10 +38,14 @@
|
||||
#include "Application.h"
|
||||
#include "BuildConfig.h"
|
||||
|
||||
#include "DataMigrationTask.h"
|
||||
#include "net/PasteUpload.h"
|
||||
#include "pathmatcher/MultiMatcher.h"
|
||||
#include "pathmatcher/SimplePrefixMatcher.h"
|
||||
#include "ui/MainWindow.h"
|
||||
#include "ui/InstanceWindow.h"
|
||||
|
||||
#include "ui/dialogs/ProgressDialog.h"
|
||||
#include "ui/instanceview/AccessibleInstanceView.h"
|
||||
|
||||
#include "ui/pages/BasePageProvider.h"
|
||||
@ -423,6 +427,15 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
|
||||
qDebug() << "<> Log initialized.";
|
||||
}
|
||||
|
||||
{
|
||||
bool migrated = false;
|
||||
|
||||
if (!migrated)
|
||||
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../PolyMC"), "PolyMC", "polymc.cfg");
|
||||
if (!migrated)
|
||||
migrated = handleDataMigration(dataPath, FS::PathCombine(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), "../../multimc"), "MultiMC", "multimc.cfg");
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
qDebug() << BuildConfig.LAUNCHER_DISPLAYNAME << ", (c) 2013-2021 " << BuildConfig.LAUNCHER_COPYRIGHT;
|
||||
@ -1589,3 +1602,89 @@ int Application::suitableMaxMem()
|
||||
|
||||
return maxMemoryAlloc;
|
||||
}
|
||||
|
||||
bool Application::handleDataMigration(const QString& currentData,
|
||||
const QString& oldData,
|
||||
const QString& name,
|
||||
const QString& configFile) const
|
||||
{
|
||||
QString nomigratePath = FS::PathCombine(oldData, BuildConfig.LAUNCHER_NAME + "_nomigrate.txt");
|
||||
QStringList configPaths = { FS::PathCombine(oldData, configFile), FS::PathCombine(oldData, BuildConfig.LAUNCHER_CONFIGFILE) };
|
||||
|
||||
QDir dir; // helper for QDir::exists
|
||||
QLocale locale;
|
||||
|
||||
// Is there a valid config at the old location?
|
||||
bool configExists = false;
|
||||
for (QString configPath : configPaths) {
|
||||
configExists |= QFileInfo::exists(configPath);
|
||||
}
|
||||
|
||||
if (!configExists || QFileInfo::exists(nomigratePath)) {
|
||||
qDebug() << "<> No migration needed from" << name;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString message;
|
||||
bool currentExists = QFileInfo::exists(FS::PathCombine(currentData, BuildConfig.LAUNCHER_CONFIGFILE));
|
||||
|
||||
if (currentExists) {
|
||||
message = tr("Old data from %1 was found, but you already have existing data for %2. Sadly you will need to migrate yourself. Do "
|
||||
"you want to be reminded of the pending data migration next time you start %2?")
|
||||
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
|
||||
} else {
|
||||
message = tr("It looks like you used %1 before. Do you want to migrate your data to the new location of %2?")
|
||||
.arg(name, BuildConfig.LAUNCHER_DISPLAYNAME);
|
||||
|
||||
QFileInfo logInfo(FS::PathCombine(oldData, name + "-0.log"));
|
||||
if (logInfo.exists()) {
|
||||
QString lastModified = logInfo.lastModified().toString(locale.dateFormat());
|
||||
message = tr("It looks like you used %1 on %2 before. Do you want to migrate your data to the new location of %3?")
|
||||
.arg(name, lastModified, BuildConfig.LAUNCHER_DISPLAYNAME);
|
||||
}
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton askMoveDialogue =
|
||||
QMessageBox::question(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, message, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
|
||||
auto setDoNotMigrate = [&nomigratePath] {
|
||||
QFile file(nomigratePath);
|
||||
file.open(QIODevice::WriteOnly);
|
||||
};
|
||||
|
||||
// create no-migrate file if user doesn't want to migrate
|
||||
if (askMoveDialogue != QMessageBox::Yes) {
|
||||
qDebug() << "<> Migration declined for" << name;
|
||||
setDoNotMigrate();
|
||||
return currentExists; // cancel further migrations, if we already have a data directory
|
||||
}
|
||||
|
||||
if (!currentExists) {
|
||||
// Migrate!
|
||||
auto matcher = std::make_shared<MultiMatcher>();
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>(configFile));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>(
|
||||
BuildConfig.LAUNCHER_CONFIGFILE)); // it's possible that we already used that directory before
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts.json"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("accounts/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("assets/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("icons/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("instances/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("libraries/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("mods/"));
|
||||
matcher->add(std::make_shared<SimplePrefixMatcher>("themes/"));
|
||||
|
||||
ProgressDialog diag = ProgressDialog();
|
||||
DataMigrationTask task(nullptr, oldData, currentData, matcher);
|
||||
if (diag.execWithTask(&task)) {
|
||||
qDebug() << "<> Migration succeeded";
|
||||
setDoNotMigrate();
|
||||
} else {
|
||||
QString reason = task.failReason();
|
||||
QMessageBox::critical(nullptr, BuildConfig.LAUNCHER_DISPLAYNAME, tr("Migration failed! Reason: %1").arg(reason));
|
||||
}
|
||||
} else {
|
||||
qWarning() << "<> Migration was skipped, due to existing data";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -231,6 +231,7 @@ private slots:
|
||||
void setupWizardFinished(int status);
|
||||
|
||||
private:
|
||||
bool handleDataMigration(const QString & currentData, const QString & oldData, const QString & name, const QString & configFile) const;
|
||||
bool createSetupWizard();
|
||||
void performMainStartupAction();
|
||||
|
||||
|
@ -576,6 +576,8 @@ SET(LAUNCHER_SOURCES
|
||||
# Application base
|
||||
Application.h
|
||||
Application.cpp
|
||||
DataMigrationTask.h
|
||||
DataMigrationTask.cpp
|
||||
UpdateController.cpp
|
||||
UpdateController.h
|
||||
ApplicationMessage.h
|
||||
|
79
launcher/DataMigrationTask.cpp
Normal file
79
launcher/DataMigrationTask.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
#include "DataMigrationTask.h"
|
||||
|
||||
#include "FileSystem.h"
|
||||
|
||||
#include <QDirIterator>
|
||||
#include <QFileInfo>
|
||||
#include <QMap>
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
DataMigrationTask::DataMigrationTask(QObject* parent,
|
||||
const QString& sourcePath,
|
||||
const QString& targetPath,
|
||||
const IPathMatcher::Ptr pathMatcher)
|
||||
: Task(parent), m_sourcePath(sourcePath), m_targetPath(targetPath), m_pathMatcher(pathMatcher), m_copy(sourcePath, targetPath)
|
||||
{
|
||||
m_copy.matcher(m_pathMatcher.get()).whitelist(true);
|
||||
}
|
||||
|
||||
void DataMigrationTask::executeTask()
|
||||
{
|
||||
setStatus(tr("Scanning files..."));
|
||||
|
||||
// 1. Scan
|
||||
// Check how many files we gotta copy
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||
return m_copy(true); // dry run to collect amount of files
|
||||
});
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
||||
m_copyFutureWatcher.setFuture(m_copyFuture);
|
||||
}
|
||||
|
||||
void DataMigrationTask::dryRunFinished()
|
||||
{
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::dryRunFinished);
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::dryRunAborted);
|
||||
|
||||
if (!m_copyFuture.result()) {
|
||||
emitFailed("Some error"); // FIXME
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(tr("Migrating..."));
|
||||
|
||||
// 2. Copy
|
||||
// Actually copy all files now.
|
||||
m_toCopy = m_copy.totalCopied();
|
||||
connect(&m_copy, &FS::copy::fileCopied, [&, this] { setProgress(m_copy.totalCopied(), m_toCopy); });
|
||||
m_copyFuture = QtConcurrent::run(QThreadPool::globalInstance(), [&] {
|
||||
return m_copy(false); // actually copy now
|
||||
});
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||
connect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
||||
m_copyFutureWatcher.setFuture(m_copyFuture);
|
||||
}
|
||||
|
||||
void DataMigrationTask::dryRunAborted()
|
||||
{
|
||||
emitFailed(tr("Aborted"));
|
||||
}
|
||||
|
||||
void DataMigrationTask::copyFinished()
|
||||
{
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::finished, this, &DataMigrationTask::copyFinished);
|
||||
disconnect(&m_copyFutureWatcher, &QFutureWatcher<bool>::canceled, this, &DataMigrationTask::copyAborted);
|
||||
|
||||
if (!m_copyFuture.result()) {
|
||||
emitFailed("Some paths could not be copied!");
|
||||
return;
|
||||
}
|
||||
|
||||
emitSucceeded();
|
||||
}
|
||||
|
||||
void DataMigrationTask::copyAborted()
|
||||
{
|
||||
emitFailed(tr("Aborted"));
|
||||
}
|
38
launcher/DataMigrationTask.h
Normal file
38
launcher/DataMigrationTask.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "pathmatcher/IPathMatcher.h"
|
||||
#include "tasks/Task.h"
|
||||
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
/*
|
||||
* Migrate existing data from other MMC-like launchers.
|
||||
*/
|
||||
|
||||
class DataMigrationTask : public Task {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DataMigrationTask(QObject* parent, const QString& sourcePath, const QString& targetPath, const IPathMatcher::Ptr pathmatcher);
|
||||
~DataMigrationTask() override = default;
|
||||
|
||||
protected:
|
||||
virtual void executeTask() override;
|
||||
|
||||
protected slots:
|
||||
void dryRunFinished();
|
||||
void dryRunAborted();
|
||||
void copyFinished();
|
||||
void copyAborted();
|
||||
|
||||
private:
|
||||
const QString& m_sourcePath;
|
||||
const QString& m_targetPath;
|
||||
const IPathMatcher::Ptr m_pathMatcher;
|
||||
|
||||
FS::copy m_copy;
|
||||
int m_toCopy = 0;
|
||||
QFuture<bool> m_copyFuture;
|
||||
QFutureWatcher<bool> m_copyFutureWatcher;
|
||||
};
|
Loading…
Reference in New Issue
Block a user