mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 11:45:47 +00:00
Properly migrate internal NAND, Load, etc. directories (#167)
Signed-off-by: crueter <swurl@swurl.xyz> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/167 Co-authored-by: crueter <swurl@swurl.xyz> Co-committed-by: crueter <swurl@swurl.xyz>
This commit is contained in:
parent
8ff1b9d282
commit
c4ca8d2367
6 changed files with 192 additions and 160 deletions
|
@ -1,7 +1,6 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -36,6 +35,7 @@
|
||||||
#include "configuration/configure_per_game.h"
|
#include "configuration/configure_per_game.h"
|
||||||
#include "configuration/configure_tas.h"
|
#include "configuration/configure_tas.h"
|
||||||
#include "core/file_sys/romfs_factory.h"
|
#include "core/file_sys/romfs_factory.h"
|
||||||
|
#include "core/core_timing.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
#include "core/file_sys/vfs/vfs.h"
|
||||||
#include "core/file_sys/vfs/vfs_real.h"
|
#include "core/file_sys/vfs/vfs_real.h"
|
||||||
#include "core/frontend/applets/cabinet.h"
|
#include "core/frontend/applets/cabinet.h"
|
||||||
|
@ -121,7 +121,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
||||||
#endif
|
#endif
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/card_image.h"
|
#include "core/file_sys/card_image.h"
|
||||||
#include "core/file_sys/common_funcs.h"
|
#include "core/file_sys/common_funcs.h"
|
||||||
|
@ -149,7 +148,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
|
||||||
#include "video_core/shader_notify.h"
|
#include "video_core/shader_notify.h"
|
||||||
#include "yuzu/about_dialog.h"
|
#include "yuzu/about_dialog.h"
|
||||||
#include "yuzu/bootmanager.h"
|
#include "yuzu/bootmanager.h"
|
||||||
#include "yuzu/compatdb.h"
|
|
||||||
#include "yuzu/compatibility_list.h"
|
#include "yuzu/compatibility_list.h"
|
||||||
#include "yuzu/configuration/configure_dialog.h"
|
#include "yuzu/configuration/configure_dialog.h"
|
||||||
#include "yuzu/configuration/configure_input_per_game.h"
|
#include "yuzu/configuration/configure_input_per_game.h"
|
||||||
|
@ -319,6 +317,22 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
Common::FS::CreateEdenPaths();
|
Common::FS::CreateEdenPaths();
|
||||||
this->config = std::make_unique<QtConfig>();
|
this->config = std::make_unique<QtConfig>();
|
||||||
|
|
||||||
|
if (user_data_migrator.migrated) {
|
||||||
|
// Sort-of hack whereby we only move the old dir if it's a subfolder of the user dir
|
||||||
|
#define MIGRATE_DIR(type) std::string type##path = Common::FS::GetEdenPathString(Common::FS::EdenPath::type##Dir); \
|
||||||
|
if (type##path.starts_with(user_data_migrator.selected_emu.get_user_dir())) { \
|
||||||
|
boost::replace_all(type##path, user_data_migrator.selected_emu.lower_name(), "eden"); \
|
||||||
|
Common::FS::SetEdenPath(Common::FS::EdenPath::type##Dir, type##path); \
|
||||||
|
}
|
||||||
|
|
||||||
|
MIGRATE_DIR(NAND)
|
||||||
|
MIGRATE_DIR(SDMC)
|
||||||
|
MIGRATE_DIR(Dump)
|
||||||
|
MIGRATE_DIR(Load)
|
||||||
|
|
||||||
|
#undef MIGRATE_DIR
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
SetupSigInterrupts();
|
SetupSigInterrupts();
|
||||||
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
|
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
|
||||||
|
@ -506,13 +520,14 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
||||||
|
|
||||||
SetupPrepareForSleep();
|
SetupPrepareForSleep();
|
||||||
|
|
||||||
|
// Some moron added a race condition to the status bar
|
||||||
|
// so now we have to make this completely unnecessary call
|
||||||
|
// to prevent the UI from blowing up.
|
||||||
|
UpdateUITheme();
|
||||||
|
|
||||||
QStringList args = QApplication::arguments();
|
QStringList args = QApplication::arguments();
|
||||||
|
|
||||||
if (args.size() < 2) {
|
if (args.size() < 2) {
|
||||||
// Some moron added a race condition to the status bar
|
|
||||||
// so now we have to make this completely unnecessary call
|
|
||||||
// to prevent the UI from blowing up.
|
|
||||||
UpdateUITheme();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,11 @@ QAbstractButton *MigrationDialog::addButton(
|
||||||
m_buttons->addWidget(button, 1);
|
m_buttons->addWidget(button, 1);
|
||||||
|
|
||||||
connect(button, &QAbstractButton::clicked, this, [this, button, reject]() {
|
connect(button, &QAbstractButton::clicked, this, [this, button, reject]() {
|
||||||
|
m_clickedButton = button;
|
||||||
|
|
||||||
if (reject) {
|
if (reject) {
|
||||||
this->reject();
|
this->reject();
|
||||||
} else {
|
} else {
|
||||||
m_clickedButton = button;
|
|
||||||
this->accept();
|
this->accept();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
#include "migration_worker.h"
|
#include "migration_worker.h"
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
|
||||||
MigrationWorker::MigrationWorker(const LegacyEmu selected_legacy_emu_,
|
MigrationWorker::MigrationWorker(const Emulator selected_legacy_emu_,
|
||||||
const bool clear_shader_cache_,
|
const bool clear_shader_cache_,
|
||||||
const MigrationStrategy strategy_)
|
const MigrationStrategy strategy_)
|
||||||
: QObject()
|
: QObject()
|
||||||
|
@ -18,31 +21,13 @@ void MigrationWorker::process()
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
const auto copy_options = fs::copy_options::update_existing | fs::copy_options::recursive;
|
const auto copy_options = fs::copy_options::update_existing | fs::copy_options::recursive;
|
||||||
|
|
||||||
std::string legacy_user_dir;
|
std::string legacy_user_dir = selected_legacy_emu.get_user_dir();
|
||||||
std::string legacy_config_dir;
|
std::string legacy_config_dir = selected_legacy_emu.get_config_dir();
|
||||||
std::string legacy_cache_dir;
|
std::string legacy_cache_dir = selected_legacy_emu.get_cache_dir();
|
||||||
|
|
||||||
#define LEGACY_EMU(emu) \
|
fs::path eden_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::EdenDir);
|
||||||
case LegacyEmu::emu: \
|
|
||||||
legacy_user_dir = Common::FS::GetLegacyPath(Common::FS::LegacyPath::emu##Dir).string(); \
|
|
||||||
legacy_config_dir = Common::FS::GetLegacyPath(Common::FS::LegacyPath::emu##ConfigDir) \
|
|
||||||
.string(); \
|
|
||||||
legacy_cache_dir = Common::FS::GetLegacyPath(Common::FS::LegacyPath::emu##CacheDir) \
|
|
||||||
.string(); \
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (selected_legacy_emu) {
|
|
||||||
LEGACY_EMU(Citron)
|
|
||||||
LEGACY_EMU(Sudachi)
|
|
||||||
LEGACY_EMU(Yuzu)
|
|
||||||
LEGACY_EMU(Suyu)
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef LEGACY_EMU
|
|
||||||
|
|
||||||
fs::path eden_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::EdenDir);
|
|
||||||
fs::path config_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir);
|
fs::path config_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir);
|
||||||
fs::path cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir);
|
fs::path cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir);
|
||||||
fs::path shader_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
fs::path shader_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -62,7 +47,7 @@ void MigrationWorker::process()
|
||||||
emit error(tr("Linking the old directory failed. You may need to re-run with "
|
emit error(tr("Linking the old directory failed. You may need to re-run with "
|
||||||
"administrative privileges on Windows.\nOS gave error: %1")
|
"administrative privileges on Windows.\nOS gave error: %1")
|
||||||
.arg(tr(e.what())));
|
.arg(tr(e.what())));
|
||||||
return;
|
std::exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows doesn't need any more links, because cache and config
|
// Windows doesn't need any more links, because cache and config
|
||||||
|
@ -119,5 +104,5 @@ void MigrationWorker::process()
|
||||||
fs::create_directory(shader_dir);
|
fs::create_directory(shader_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit finished(success_text);
|
emit finished(success_text, legacy_user_dir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,25 +2,58 @@
|
||||||
#define MIGRATION_WORKER_H
|
#define MIGRATION_WORKER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include "common/fs/path_util.h"
|
||||||
|
|
||||||
|
using namespace Common::FS;
|
||||||
|
|
||||||
|
typedef struct Emulator {
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
LegacyPath e_user_dir;
|
||||||
|
LegacyPath e_config_dir;
|
||||||
|
LegacyPath e_cache_dir;
|
||||||
|
|
||||||
|
const std::string get_user_dir() const {
|
||||||
|
return Common::FS::GetLegacyPath(e_user_dir).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string get_config_dir() const {
|
||||||
|
return Common::FS::GetLegacyPath(e_config_dir).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string get_cache_dir() const {
|
||||||
|
return Common::FS::GetLegacyPath(e_cache_dir).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string lower_name() const {
|
||||||
|
std::string lower_name{name};
|
||||||
|
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(),
|
||||||
|
[](unsigned char c){ return std::tolower(c); });
|
||||||
|
|
||||||
|
return lower_name;
|
||||||
|
}
|
||||||
|
} Emulator;
|
||||||
|
|
||||||
|
#define EMU(name) Emulator{#name, name##Dir, name##ConfigDir, name##CacheDir}
|
||||||
|
static constexpr std::array<Emulator, 4> legacy_emus = {
|
||||||
|
EMU(Citron),
|
||||||
|
EMU(Sudachi),
|
||||||
|
EMU(Suyu),
|
||||||
|
EMU(Yuzu),
|
||||||
|
};
|
||||||
|
#undef EMU
|
||||||
|
|
||||||
class MigrationWorker : public QObject
|
class MigrationWorker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum class LegacyEmu {
|
|
||||||
Citron,
|
|
||||||
Sudachi,
|
|
||||||
Yuzu,
|
|
||||||
Suyu,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MigrationStrategy {
|
enum class MigrationStrategy {
|
||||||
Copy,
|
Copy,
|
||||||
Move,
|
Move,
|
||||||
Link,
|
Link,
|
||||||
};
|
};
|
||||||
|
|
||||||
MigrationWorker(const LegacyEmu selected_legacy_emu,
|
MigrationWorker(const Emulator selected_legacy_emu,
|
||||||
const bool clear_shader_cache,
|
const bool clear_shader_cache,
|
||||||
const MigrationStrategy strategy);
|
const MigrationStrategy strategy);
|
||||||
|
|
||||||
|
@ -28,11 +61,11 @@ public slots:
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished(const QString &success_text);
|
void finished(const QString &success_text, const std::string &user_dir);
|
||||||
void error(const QString &error_message);
|
void error(const QString &error_message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LegacyEmu selected_legacy_emu;
|
Emulator selected_legacy_emu;
|
||||||
bool clear_shader_cache;
|
bool clear_shader_cache;
|
||||||
MigrationStrategy strategy;
|
MigrationStrategy strategy;
|
||||||
QString success_text = tr("Data was migrated successfully.");
|
QString success_text = tr("Data was migrated successfully.");
|
||||||
|
|
|
@ -40,150 +40,144 @@ void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
||||||
{
|
{
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
const QString migration_prompt_message = main_window->tr(
|
// define strings here for easy access
|
||||||
"Would you like to migrate your data for use in Eden?\n"
|
static constexpr const char *prompt_prefix_text
|
||||||
"Select the corresponding button to migrate data from that emulator.\n"
|
= "Eden has detected user data for the following emulators:";
|
||||||
"This may take a while.");
|
|
||||||
|
|
||||||
bool any_found = false;
|
static constexpr const char *migration_prompt_message
|
||||||
|
= "Would you like to migrate your data for use in Eden?\n"
|
||||||
|
"Select the corresponding button to migrate data from that emulator.\n"
|
||||||
|
"This may take a while.";
|
||||||
|
|
||||||
|
static constexpr const char *clear_shader_tooltip
|
||||||
|
= "Clearing shader cache is recommended for all "
|
||||||
|
"users.\nDo not uncheck unless you know what "
|
||||||
|
"you're doing.";
|
||||||
|
|
||||||
|
static constexpr const char *keep_old_data_tooltip
|
||||||
|
= "Keeps the old data directory. This is recommended if you aren't\n"
|
||||||
|
"space-constrained and want to keep separate data for the old emulator.";
|
||||||
|
|
||||||
|
static constexpr const char *clear_old_data_tooltip
|
||||||
|
= "Deletes the old data directory.\nThis is recommended on "
|
||||||
|
"devices with space constraints.";
|
||||||
|
|
||||||
|
static constexpr const char *link_old_dir_tooltip
|
||||||
|
= "Creates a filesystem link between the old directory and Eden directory.\n"
|
||||||
|
"This is recommended if you want to share data between emulators.";
|
||||||
|
|
||||||
|
// actual migration code
|
||||||
|
|
||||||
MigrationDialog migration_prompt;
|
MigrationDialog migration_prompt;
|
||||||
migration_prompt.setWindowTitle(main_window->tr("Migration"));
|
migration_prompt.setWindowTitle(QObject::tr("Migration"));
|
||||||
|
|
||||||
QCheckBox *clear_shaders = new QCheckBox(&migration_prompt);
|
// mutually exclusive
|
||||||
clear_shaders->setText(main_window->tr("Clear Shader Cache"));
|
|
||||||
clear_shaders->setToolTip(main_window->tr(
|
|
||||||
"Clearing shader cache is recommended for all users.\nDo not uncheck unless you know what "
|
|
||||||
"you're doing."));
|
|
||||||
clear_shaders->setChecked(true);
|
|
||||||
|
|
||||||
QRadioButton *keep_old = new QRadioButton(&migration_prompt);
|
|
||||||
keep_old->setText(main_window->tr("Keep Old Data"));
|
|
||||||
keep_old->setToolTip(
|
|
||||||
main_window->tr("Keeps the old data directory. This is recommended if you aren't\n"
|
|
||||||
"space-constrained and want to keep separate data for the old emulator."));
|
|
||||||
keep_old->setChecked(true);
|
|
||||||
|
|
||||||
QRadioButton *clear_old = new QRadioButton(&migration_prompt);
|
|
||||||
clear_old->setText(main_window->tr("Clear Old Data"));
|
|
||||||
clear_old->setToolTip(main_window->tr("Deletes the old data directory.\nThis is recommended on "
|
|
||||||
"devices with space constraints."));
|
|
||||||
clear_old->setChecked(false);
|
|
||||||
|
|
||||||
QRadioButton *link = new QRadioButton(&migration_prompt);
|
|
||||||
link->setText(main_window->tr("Link Old Directory"));
|
|
||||||
link->setToolTip(
|
|
||||||
main_window->tr("Creates a filesystem link between the old directory and Eden directory.\n"
|
|
||||||
"This is recommended if you want to share data between emulators.."));
|
|
||||||
link->setChecked(false);
|
|
||||||
|
|
||||||
// Link and Clear Old are mutually exclusive
|
|
||||||
QButtonGroup *group = new QButtonGroup(&migration_prompt);
|
QButtonGroup *group = new QButtonGroup(&migration_prompt);
|
||||||
group->addButton(keep_old);
|
|
||||||
group->addButton(clear_old);
|
|
||||||
group->addButton(link);
|
|
||||||
|
|
||||||
migration_prompt.addBox(clear_shaders);
|
// MACRO MADNESS
|
||||||
migration_prompt.addBox(keep_old);
|
|
||||||
migration_prompt.addBox(clear_old);
|
|
||||||
migration_prompt.addBox(link);
|
|
||||||
|
|
||||||
// Reflection would make this code 10x better
|
#define BUTTON(clazz, name, text, tooltip, checkState) \
|
||||||
// but for now... MACRO MADNESS!!!!
|
clazz *name = new clazz(&migration_prompt); \
|
||||||
QMap<QString, bool> found;
|
name->setText(QObject::tr(text)); \
|
||||||
QMap<QString, MigrationWorker::LegacyEmu> legacyMap;
|
name->setToolTip(QObject::tr(tooltip)); \
|
||||||
QMap<QString, QAbstractButton *> buttonMap;
|
name->setChecked(checkState); \
|
||||||
|
migration_prompt.addBox(name);
|
||||||
|
|
||||||
#define EMU_MAP(name) \
|
BUTTON(QCheckBox, clear_shaders, "Clear Shader Cache", clear_shader_tooltip, true)
|
||||||
const bool name##_found = fs::is_directory( \
|
|
||||||
Common::FS::GetLegacyPath(Common::FS::LegacyPath::name##Dir)); \
|
|
||||||
legacyMap[main_window->tr(#name)] = MigrationWorker::LegacyEmu::name; \
|
|
||||||
found[main_window->tr(#name)] = name##_found; \
|
|
||||||
if (name##_found) \
|
|
||||||
any_found = true;
|
|
||||||
|
|
||||||
EMU_MAP(Citron)
|
#define RADIO(name, text, tooltip, checkState) \
|
||||||
EMU_MAP(Sudachi)
|
BUTTON(QRadioButton, name, text, tooltip, checkState) \
|
||||||
EMU_MAP(Yuzu)
|
group->addButton(name);
|
||||||
EMU_MAP(Suyu)
|
|
||||||
|
|
||||||
#undef EMU_MAP
|
RADIO(keep_old, "Keep Old Data", keep_old_data_tooltip, true)
|
||||||
|
RADIO(clear_old, "Clear Old Data", clear_old_data_tooltip, false)
|
||||||
|
RADIO(link_old, "Link Old Directory", link_old_dir_tooltip, false)
|
||||||
|
|
||||||
if (any_found) {
|
#undef RADIO
|
||||||
QString promptText = main_window->tr(
|
#undef BUTTON
|
||||||
"Eden has detected user data for the following emulators:");
|
|
||||||
QMapIterator iter(found);
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
std::vector<Emulator> found{};
|
||||||
iter.next();
|
|
||||||
if (!iter.value())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QAbstractButton *button = migration_prompt.addButton(iter.key());
|
for (const Emulator &emu : legacy_emus)
|
||||||
|
if (fs::is_directory(emu.get_user_dir()))
|
||||||
|
found.emplace_back(emu);
|
||||||
|
|
||||||
buttonMap[iter.key()] = button;
|
if (found.empty()) {
|
||||||
promptText.append(main_window->tr("\n- %1").arg(iter.key()));
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
promptText.append(main_window->tr("\n\n"));
|
|
||||||
|
|
||||||
migration_prompt.setText(promptText + migration_prompt_message);
|
|
||||||
migration_prompt.addButton(main_window->tr("No"), true);
|
|
||||||
|
|
||||||
migration_prompt.exec();
|
|
||||||
|
|
||||||
MigrationWorker::MigrationStrategy strategy;
|
|
||||||
if (link->isChecked()) {
|
|
||||||
strategy = MigrationWorker::MigrationStrategy::Link;
|
|
||||||
} else if (clear_old->isChecked()) {
|
|
||||||
strategy = MigrationWorker::MigrationStrategy::Move;
|
|
||||||
} else {
|
|
||||||
strategy = MigrationWorker::MigrationStrategy::Copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
QMapIterator buttonIter(buttonMap);
|
|
||||||
|
|
||||||
while (buttonIter.hasNext()) {
|
|
||||||
buttonIter.next();
|
|
||||||
if (buttonIter.value() == migration_prompt.clickedButton()) {
|
|
||||||
MigrateUserData(main_window,
|
|
||||||
legacyMap[buttonIter.key()],
|
|
||||||
clear_shaders->isChecked(),
|
|
||||||
strategy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're here, the user chose not to migrate
|
|
||||||
ShowMigrationCancelledMessage(main_window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else // no other data was found
|
// makes my life easier
|
||||||
return;
|
qRegisterMetaType<Emulator>();
|
||||||
|
|
||||||
|
QString prompt_text = QObject::tr(prompt_prefix_text);
|
||||||
|
|
||||||
|
// natural language processing is a nightmare
|
||||||
|
for (const Emulator &emu : found) {
|
||||||
|
prompt_text.append(QStringLiteral("\n- %1").arg(QObject::tr(emu.name)));
|
||||||
|
|
||||||
|
QAbstractButton *button = migration_prompt.addButton(QObject::tr(emu.name));
|
||||||
|
|
||||||
|
// This is cursed, but it's actually the most efficient way by a mile
|
||||||
|
button->setProperty("emulator", QVariant::fromValue(emu));
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_text.append(QObject::tr("\n\n"));
|
||||||
|
prompt_text.append(QObject::tr(migration_prompt_message));
|
||||||
|
|
||||||
|
migration_prompt.setText(prompt_text);
|
||||||
|
migration_prompt.addButton(QObject::tr("No"), true);
|
||||||
|
|
||||||
|
migration_prompt.exec();
|
||||||
|
|
||||||
|
QAbstractButton *button = migration_prompt.clickedButton();
|
||||||
|
|
||||||
|
if (button->text() == QObject::tr("No")) {
|
||||||
|
return ShowMigrationCancelledMessage(main_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
MigrationWorker::MigrationStrategy strategy;
|
||||||
|
switch (group->checkedId()) {
|
||||||
|
default:
|
||||||
|
[[fallthrough]];
|
||||||
|
case 0:
|
||||||
|
strategy = MigrationWorker::MigrationStrategy::Copy;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
strategy = MigrationWorker::MigrationStrategy::Move;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
strategy = MigrationWorker::MigrationStrategy::Link;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MigrateUserData(main_window,
|
||||||
|
button->property("emulator").value<Emulator>(),
|
||||||
|
clear_shaders->isChecked(),
|
||||||
|
strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserDataMigrator::ShowMigrationCancelledMessage(QMainWindow *main_window)
|
void UserDataMigrator::ShowMigrationCancelledMessage(QMainWindow *main_window)
|
||||||
{
|
{
|
||||||
QMessageBox::information(main_window,
|
QMessageBox::information(main_window,
|
||||||
main_window->tr("Migration"),
|
QObject::tr("Migration"),
|
||||||
main_window
|
QObject::tr("You can manually re-trigger this prompt by deleting the "
|
||||||
->tr("You can manually re-trigger this prompt by deleting the "
|
"new config directory:\n%1")
|
||||||
"new config directory:\n"
|
|
||||||
"%1")
|
|
||||||
.arg(QString::fromStdString(Common::FS::GetEdenPathString(
|
.arg(QString::fromStdString(Common::FS::GetEdenPathString(
|
||||||
Common::FS::EdenPath::ConfigDir))),
|
Common::FS::EdenPath::ConfigDir))),
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserDataMigrator::MigrateUserData(QMainWindow *main_window,
|
void UserDataMigrator::MigrateUserData(QMainWindow *main_window,
|
||||||
const MigrationWorker::LegacyEmu selected_legacy_emu,
|
const Emulator selected_legacy_emu,
|
||||||
const bool clear_shader_cache,
|
const bool clear_shader_cache,
|
||||||
const MigrationWorker::MigrationStrategy strategy)
|
const MigrationWorker::MigrationStrategy strategy)
|
||||||
{
|
{
|
||||||
// Create a dialog to let the user know it's migrating, some users noted confusion.
|
selected_emu = selected_legacy_emu;
|
||||||
|
|
||||||
|
// Create a dialog to let the user know it's migrating
|
||||||
QProgressDialog *progress = new QProgressDialog(main_window);
|
QProgressDialog *progress = new QProgressDialog(main_window);
|
||||||
progress->setWindowTitle(main_window->tr("Migrating"));
|
progress->setWindowTitle(QObject::tr("Migrating"));
|
||||||
progress->setLabelText(main_window->tr("Migrating, this may take a while..."));
|
progress->setLabelText(QObject::tr("Migrating, this may take a while..."));
|
||||||
progress->setRange(0, 0);
|
progress->setRange(0, 0);
|
||||||
progress->setCancelButton(nullptr);
|
progress->setCancelButton(nullptr);
|
||||||
progress->setWindowModality(Qt::WindowModality::ApplicationModal);
|
progress->setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||||
|
@ -194,13 +188,14 @@ void UserDataMigrator::MigrateUserData(QMainWindow *main_window,
|
||||||
|
|
||||||
thread->connect(thread, &QThread::started, worker, &MigrationWorker::process);
|
thread->connect(thread, &QThread::started, worker, &MigrationWorker::process);
|
||||||
|
|
||||||
thread->connect(worker, &MigrationWorker::finished, progress, [=](const QString &success_text) {
|
thread->connect(worker, &MigrationWorker::finished, progress, [=, this](const QString &success_text, const std::string &path) {
|
||||||
progress->close();
|
progress->close();
|
||||||
QMessageBox::information(main_window,
|
QMessageBox::information(main_window,
|
||||||
main_window->tr("Migration"),
|
QObject::tr("Migration"),
|
||||||
success_text,
|
success_text,
|
||||||
QMessageBox::Ok);
|
QMessageBox::Ok);
|
||||||
|
|
||||||
|
migrated = true;
|
||||||
thread->quit();
|
thread->quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,14 @@ class UserDataMigrator {
|
||||||
public:
|
public:
|
||||||
UserDataMigrator(QMainWindow* main_window);
|
UserDataMigrator(QMainWindow* main_window);
|
||||||
|
|
||||||
|
bool migrated{false};
|
||||||
|
Emulator selected_emu;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ShowMigrationPrompt(QMainWindow* main_window);
|
void ShowMigrationPrompt(QMainWindow* main_window);
|
||||||
void ShowMigrationCancelledMessage(QMainWindow* main_window);
|
void ShowMigrationCancelledMessage(QMainWindow* main_window);
|
||||||
void MigrateUserData(QMainWindow* main_window,
|
void MigrateUserData(QMainWindow* main_window,
|
||||||
const MigrationWorker::LegacyEmu selected_legacy_emu,
|
const Emulator selected_legacy_emu,
|
||||||
const bool clear_shader_cache,
|
const bool clear_shader_cache,
|
||||||
const MigrationWorker::MigrationStrategy strategy);
|
const MigrationWorker::MigrationStrategy strategy);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue