mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-19 06:31:29 +00:00
a53823646c
Linguist strongly dislikes lookup tables of this sort due to the fact that it looks for tr(), qsTr(), etc. when determining what strings need translations. However, it does provide QT_TR_NOOP which marks the string for translation *without* running the translation, which is designed to allow for static or constexpr lookup tables. So let's use that. Signed-off-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2773 Reviewed-by: MaranBr <maranbr@eden-emu.dev>
204 lines
7.2 KiB
C++
204 lines
7.2 KiB
C++
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
|
// Licensed under GPLv2 or any later version
|
|
// Refer to the license.txt file included.
|
|
|
|
#include "user_data_migration.h"
|
|
#include <QMessageBox>
|
|
#include <QPushButton>
|
|
#include <QString>
|
|
#include <QTranslator>
|
|
#include "common/fs/path_util.h"
|
|
#include "qt_common/qt_string_lookup.h"
|
|
#include "yuzu/migration_dialog.h"
|
|
|
|
// Needs to be included at the end due to https://bugreports.qt.io/browse/QTBUG-73263
|
|
#include <QButtonGroup>
|
|
#include <QCheckBox>
|
|
#include <QGuiApplication>
|
|
#include <QProgressDialog>
|
|
#include <QRadioButton>
|
|
#include <QThread>
|
|
#include <filesystem>
|
|
|
|
namespace fs = std::filesystem;
|
|
|
|
UserDataMigrator::UserDataMigrator(QMainWindow *main_window)
|
|
{
|
|
// NOTE: Logging is not initialized yet, do not produce logs here.
|
|
|
|
// Check migration if config directory does not exist
|
|
// TODO: ProfileManager messes with us a bit here, and force-creates the /nand/system/save/8000000000000010/su/avators/profiles.dat
|
|
// file. Find a way to reorder operations and have it create after this guy runs.
|
|
if (!fs::is_directory(Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir))) {
|
|
ShowMigrationPrompt(main_window);
|
|
}
|
|
}
|
|
|
|
void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
|
{
|
|
namespace fs = std::filesystem;
|
|
|
|
// define strings here for easy access
|
|
|
|
QString prompt_prefix_text = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationPromptPrefix);
|
|
QString migration_prompt_message = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationPrompt);
|
|
QString clear_shader_tooltip = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationTooltipClearShader);
|
|
QString keep_old_data_tooltip = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationTooltipKeepOld);
|
|
QString clear_old_data_tooltip = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationTooltipClearOld);
|
|
QString link_old_dir_tooltip = QtCommon::StringLookup::Lookup(
|
|
QtCommon::StringLookup::MigrationTooltipLinkOld);
|
|
|
|
// actual migration code
|
|
|
|
MigrationDialog migration_prompt;
|
|
migration_prompt.setWindowTitle(QObject::tr("Migration"));
|
|
|
|
// mutually exclusive
|
|
QButtonGroup *group = new QButtonGroup(&migration_prompt);
|
|
|
|
// MACRO MADNESS
|
|
|
|
#define BUTTON(clazz, name, text, tooltip, checkState) \
|
|
clazz *name = new clazz(&migration_prompt); \
|
|
name->setText(text); \
|
|
name->setToolTip(tooltip); \
|
|
name->setChecked(checkState); \
|
|
migration_prompt.addBox(name);
|
|
|
|
BUTTON(QCheckBox, clear_shaders, QObject::tr("Clear Shader Cache"), clear_shader_tooltip, true)
|
|
|
|
u32 id = 0;
|
|
|
|
#define RADIO(name, text, tooltip, checkState) \
|
|
BUTTON(QRadioButton, name, text, tooltip, checkState) \
|
|
group->addButton(name, ++id);
|
|
|
|
RADIO(keep_old, QObject::tr("Keep Old Data"), keep_old_data_tooltip, true)
|
|
RADIO(clear_old, QObject::tr("Clear Old Data"), clear_old_data_tooltip, false)
|
|
RADIO(link_old, QObject::tr("Link Old Directory"), link_old_dir_tooltip, false)
|
|
|
|
#undef RADIO
|
|
#undef BUTTON
|
|
|
|
std::vector<Emulator> found{};
|
|
|
|
for (const Emulator &emu : legacy_emus)
|
|
if (fs::is_directory(emu.get_user_dir()))
|
|
found.emplace_back(emu);
|
|
|
|
if (found.empty()) {
|
|
return;
|
|
}
|
|
|
|
// makes my life easier
|
|
qRegisterMetaType<Emulator>();
|
|
|
|
QString prompt_text = prompt_prefix_text;
|
|
|
|
// natural language processing is a nightmare
|
|
for (const Emulator &emu : found) {
|
|
prompt_text = prompt_text % QStringLiteral("\n ") % emu.name();
|
|
|
|
QAbstractButton *button = migration_prompt.addButton(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 = prompt_text % QStringLiteral("\n\n") % 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 1:
|
|
strategy = MigrationWorker::MigrationStrategy::Copy;
|
|
break;
|
|
case 2:
|
|
strategy = MigrationWorker::MigrationStrategy::Move;
|
|
break;
|
|
case 3:
|
|
strategy = MigrationWorker::MigrationStrategy::Link;
|
|
break;
|
|
}
|
|
|
|
MigrateUserData(main_window,
|
|
button->property("emulator").value<Emulator>(),
|
|
clear_shaders->isChecked(),
|
|
strategy);
|
|
}
|
|
|
|
void UserDataMigrator::ShowMigrationCancelledMessage(QMainWindow *main_window)
|
|
{
|
|
QMessageBox::information(main_window,
|
|
QObject::tr("Migration"),
|
|
QObject::tr("You can manually re-trigger this prompt by deleting the "
|
|
"new config directory:\n%1")
|
|
.arg(QString::fromStdString(Common::FS::GetEdenPathString(
|
|
Common::FS::EdenPath::ConfigDir))),
|
|
QMessageBox::Ok);
|
|
}
|
|
|
|
void UserDataMigrator::MigrateUserData(QMainWindow *main_window,
|
|
const Emulator selected_legacy_emu,
|
|
const bool clear_shader_cache,
|
|
const MigrationWorker::MigrationStrategy strategy)
|
|
{
|
|
selected_emu = selected_legacy_emu;
|
|
|
|
// Create a dialog to let the user know it's migrating
|
|
QProgressDialog *progress = new QProgressDialog(main_window);
|
|
progress->setWindowTitle(QObject::tr("Migrating"));
|
|
progress->setLabelText(QObject::tr("Migrating, this may take a while..."));
|
|
progress->setRange(0, 0);
|
|
progress->setCancelButton(nullptr);
|
|
progress->setWindowModality(Qt::WindowModality::ApplicationModal);
|
|
|
|
QThread *thread = new QThread(main_window);
|
|
MigrationWorker *worker = new MigrationWorker(selected_legacy_emu, clear_shader_cache, strategy);
|
|
worker->moveToThread(thread);
|
|
|
|
thread->connect(thread, &QThread::started, worker, &MigrationWorker::process);
|
|
|
|
thread->connect(worker,
|
|
&MigrationWorker::finished,
|
|
progress,
|
|
[=, this](const QString &success_text, const std::string &path) {
|
|
progress->close();
|
|
QMessageBox::information(main_window,
|
|
QObject::tr("Migration"),
|
|
success_text,
|
|
QMessageBox::Ok);
|
|
|
|
migrated = true;
|
|
thread->quit();
|
|
});
|
|
|
|
thread->connect(worker, &MigrationWorker::finished, worker, &QObject::deleteLater);
|
|
thread->connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
|
|
|
thread->start();
|
|
progress->exec();
|
|
}
|