mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2025-03-13 17:22:30 +01:00
qt: Implement migration prompt to bring data from Citra/Lime3DS (#638)
This commit is contained in:
parent
43dbe42b29
commit
ac7671e247
@ -1,4 +1,4 @@
|
|||||||
// Copyright Citra Emulator Project / Lime3DS Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -167,6 +167,8 @@ void GMainWindow::ShowCommandOutput(std::string title, std::string message) {
|
|||||||
|
|
||||||
GMainWindow::GMainWindow(Core::System& system_)
|
GMainWindow::GMainWindow(Core::System& system_)
|
||||||
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{system.Movie()},
|
: ui{std::make_unique<Ui::MainWindow>()}, system{system_}, movie{system.Movie()},
|
||||||
|
emu_user_dir_exists{
|
||||||
|
std::filesystem::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::UserDir))},
|
||||||
config{std::make_unique<QtConfig>()}, emu_thread{nullptr} {
|
config{std::make_unique<QtConfig>()}, emu_thread{nullptr} {
|
||||||
Common::Log::Initialize();
|
Common::Log::Initialize();
|
||||||
Common::Log::Start();
|
Common::Log::Start();
|
||||||
@ -307,6 +309,11 @@ GMainWindow::GMainWindow(Core::System& system_)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if data migration from Citra/Lime3DS needs to be performed
|
||||||
|
if (!emu_user_dir_exists) {
|
||||||
|
ShowMigrationPrompt();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __unix__
|
#ifdef __unix__
|
||||||
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
|
SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue());
|
||||||
#endif
|
#endif
|
||||||
@ -1205,6 +1212,115 @@ void GMainWindow::ShowUpdaterWidgets() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void GMainWindow::ShowMigrationCancelledMessage() {
|
||||||
|
QMessageBox::information(
|
||||||
|
this, tr("Migration"),
|
||||||
|
tr("You can manually re-trigger this prompt by deleting the "
|
||||||
|
"new user data directory:\n"
|
||||||
|
"%1")
|
||||||
|
.arg(QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::UserDir))),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::ShowMigrationPrompt() {
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
const QString migration_prompt_message =
|
||||||
|
tr("Would you like to migrate your data for use in Azahar?\n"
|
||||||
|
"(This may take a while; The old data will not be deleted)");
|
||||||
|
const bool citra_dir_found =
|
||||||
|
fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::LegacyCitraUserDir));
|
||||||
|
const bool lime3ds_dir_found =
|
||||||
|
fs::is_directory(FileUtil::GetUserPath(FileUtil::UserPath::LegacyLime3DSUserDir));
|
||||||
|
|
||||||
|
if (citra_dir_found && lime3ds_dir_found) {
|
||||||
|
QMessageBox migration_prompt;
|
||||||
|
migration_prompt.setWindowTitle(tr("Migration"));
|
||||||
|
migration_prompt.setText(
|
||||||
|
tr("Azahar has detected emulator data for Citra and Lime3DS.\n\n") +
|
||||||
|
migration_prompt_message);
|
||||||
|
migration_prompt.setIcon(QMessageBox::Information);
|
||||||
|
|
||||||
|
const QAbstractButton* lime3dsButton =
|
||||||
|
migration_prompt.addButton(tr("Migrate from Lime3DS"), QMessageBox::YesRole);
|
||||||
|
const QAbstractButton* citraButton =
|
||||||
|
migration_prompt.addButton(tr("Migrate from Citra"), QMessageBox::YesRole);
|
||||||
|
migration_prompt.addButton(QMessageBox::No);
|
||||||
|
|
||||||
|
migration_prompt.exec();
|
||||||
|
|
||||||
|
if (citraButton == migration_prompt.clickedButton()) {
|
||||||
|
MigrateUserData(LegacyEmu::Citra);
|
||||||
|
}
|
||||||
|
if (lime3dsButton == migration_prompt.clickedButton()) {
|
||||||
|
MigrateUserData(LegacyEmu::Lime3DS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (citra_dir_found) {
|
||||||
|
if (QMessageBox::information(
|
||||||
|
this, tr("Migration"),
|
||||||
|
tr("Azahar has detected emulator data for Citra.\n\n") + migration_prompt_message,
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||||
|
MigrateUserData(LegacyEmu::Citra);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (lime3ds_dir_found) {
|
||||||
|
if (QMessageBox::information(
|
||||||
|
this, tr("Migration"),
|
||||||
|
tr("Azahar has detected emulator data for Lime3DS.\n\n") + migration_prompt_message,
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes) {
|
||||||
|
MigrateUserData(LegacyEmu::Lime3DS);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, the user chose not to migrate
|
||||||
|
ShowMigrationCancelledMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::MigrateUserData(const LegacyEmu selected_legacy_emu) {
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
const auto copy_options = fs::copy_options::update_existing | fs::copy_options::recursive;
|
||||||
|
|
||||||
|
std::string legacy_user_dir;
|
||||||
|
std::string legacy_config_dir;
|
||||||
|
std::string legacy_cache_dir;
|
||||||
|
if (LegacyEmu::Citra == selected_legacy_emu) {
|
||||||
|
legacy_user_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyCitraUserDir);
|
||||||
|
legacy_config_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyCitraConfigDir);
|
||||||
|
legacy_cache_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyCitraCacheDir);
|
||||||
|
} else if (LegacyEmu::Lime3DS == selected_legacy_emu) {
|
||||||
|
legacy_user_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyLime3DSUserDir);
|
||||||
|
legacy_config_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyLime3DSConfigDir);
|
||||||
|
legacy_cache_dir = FileUtil::GetUserPath(FileUtil::UserPath::LegacyLime3DSCacheDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::copy(legacy_user_dir, FileUtil::GetUserPath(FileUtil::UserPath::UserDir), copy_options);
|
||||||
|
|
||||||
|
if (fs::is_directory(legacy_config_dir)) {
|
||||||
|
fs::copy(legacy_config_dir, FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir),
|
||||||
|
copy_options);
|
||||||
|
}
|
||||||
|
if (fs::is_directory(legacy_cache_dir)) {
|
||||||
|
fs::copy(legacy_cache_dir, FileUtil::GetUserPath(FileUtil::UserPath::CacheDir),
|
||||||
|
copy_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMessageBox::information(
|
||||||
|
this, tr("Migration"),
|
||||||
|
tr("Data was migrated successfully. Azahar will now restart.\n\n"
|
||||||
|
"If you wish to clean up the files which were left in the old "
|
||||||
|
"data location, you can do so by deleting the following directory:\n"
|
||||||
|
"%1")
|
||||||
|
.arg(QString::fromStdString(legacy_user_dir)),
|
||||||
|
QMessageBox::Ok);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(HAVE_SDL2) && defined(__unix__) && !defined(__APPLE__)
|
#if defined(HAVE_SDL2) && defined(__unix__) && !defined(__APPLE__)
|
||||||
static std::optional<QDBusObjectPath> HoldWakeLockLinux(u32 window_id = 0) {
|
static std::optional<QDBusObjectPath> HoldWakeLockLinux(u32 window_id = 0) {
|
||||||
if (!QDBusConnection::sessionBus().isConnected()) {
|
if (!QDBusConnection::sessionBus().isConnected()) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright 2014 Citra Emulator Project
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
@ -173,6 +173,14 @@ private:
|
|||||||
void CheckForUpdates();
|
void CheckForUpdates();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum LegacyEmu {
|
||||||
|
Citra,
|
||||||
|
Lime3DS,
|
||||||
|
};
|
||||||
|
void ShowMigrationCancelledMessage();
|
||||||
|
void ShowMigrationPrompt();
|
||||||
|
void MigrateUserData(const LegacyEmu selected_legacy_emu);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the filename in the recently loaded files list.
|
* Stores the filename in the recently loaded files list.
|
||||||
* The new filename is stored at the beginning of the recently loaded files list.
|
* The new filename is stored at the beginning of the recently loaded files list.
|
||||||
@ -349,6 +357,10 @@ private:
|
|||||||
bool message_label_used_for_movie = false;
|
bool message_label_used_for_movie = false;
|
||||||
|
|
||||||
MultiplayerState* multiplayer_state = nullptr;
|
MultiplayerState* multiplayer_state = nullptr;
|
||||||
|
|
||||||
|
// Created before `config` to ensure that emu data directory
|
||||||
|
// isn't created before the check is performed
|
||||||
|
bool emu_user_dir_exists;
|
||||||
std::unique_ptr<QtConfig> config;
|
std::unique_ptr<QtConfig> config;
|
||||||
|
|
||||||
// Whether emulation is currently running in Citra.
|
// Whether emulation is currently running in Citra.
|
||||||
|
@ -23,18 +23,28 @@
|
|||||||
#define EMU_DATA_DIR USER_DIR
|
#define EMU_DATA_DIR USER_DIR
|
||||||
#else
|
#else
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define EMU_DATA_DIR "Citra"
|
#define EMU_DATA_DIR "Azahar"
|
||||||
|
#define LEGACY_CITRA_DATA_DIR "Citra"
|
||||||
|
#define LEGACY_LIME3DS_DATA_DIR "Lime3DS"
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#define APPLE_EMU_DATA_DIR "Documents" DIR_SEP "Citra"
|
#define EMU_APPLE_DATA_DIR "Documents" DIR_SEP "Azahar"
|
||||||
|
#define LEGACY_CITRA_APPLE_DATA_DIR "Documents" DIR_SEP "Citra"
|
||||||
|
#define LEGACY_LIME3DS_APPLE_DATA_DIR "Documents" DIR_SEP "Lime3DS"
|
||||||
#else
|
#else
|
||||||
#define APPLE_EMU_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Citra"
|
#define EMU_APPLE_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Azahar"
|
||||||
|
#define LEGACY_CITRA_APPLE_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Citra"
|
||||||
|
#define LEGACY_LIME3DS_APPLE_DATA_DIR "Library" DIR_SEP "Application Support" DIR_SEP "Lime3DS"
|
||||||
#endif
|
#endif
|
||||||
// For compatibility with XDG paths.
|
// For compatibility with XDG paths.
|
||||||
#define EMU_DATA_DIR "citra-emu"
|
#define EMU_DATA_DIR "azahar-emu"
|
||||||
|
#define LEGACY_CITRA_DATA_DIR "citra-emu"
|
||||||
|
#define LEGACY_LIME3DS_DATA_DIR "lime3ds-emu"
|
||||||
#else
|
#else
|
||||||
#define EMU_DATA_DIR "citra-emu"
|
#define EMU_DATA_DIR "azahar-emu"
|
||||||
|
#define LEGACY_CITRA_DATA_DIR "citra-emu"
|
||||||
|
#define LEGACY_LIME3DS_DATA_DIR "lime3ds-emu"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -783,8 +783,15 @@ void SetUserPath(const std::string& path) {
|
|||||||
} else {
|
} else {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
|
user_path = GetExeDirectory() + DIR_SEP USERDATA_DIR DIR_SEP;
|
||||||
|
std::string& legacy_citra_user_path = g_paths[UserPath::LegacyCitraUserDir];
|
||||||
|
std::string& legacy_lime3ds_user_path = g_paths[UserPath::LegacyLime3DSUserDir];
|
||||||
|
|
||||||
if (!FileUtil::IsDirectory(user_path)) {
|
if (!FileUtil::IsDirectory(user_path)) {
|
||||||
user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
user_path = AppDataRoamingDirectory() + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||||
|
legacy_citra_user_path =
|
||||||
|
AppDataRoamingDirectory() + DIR_SEP LEGACY_CITRA_DATA_DIR DIR_SEP;
|
||||||
|
legacy_lime3ds_user_path =
|
||||||
|
AppDataRoamingDirectory() + DIR_SEP LEGACY_LIME3DS_DATA_DIR DIR_SEP;
|
||||||
} else {
|
} else {
|
||||||
LOG_INFO(Common_Filesystem, "Using the local user directory");
|
LOG_INFO(Common_Filesystem, "Using the local user directory");
|
||||||
}
|
}
|
||||||
@ -796,6 +803,8 @@ void SetUserPath(const std::string& path) {
|
|||||||
g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
|
g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP);
|
||||||
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
||||||
#else
|
#else
|
||||||
|
std::string& legacy_citra_user_path = g_paths[UserPath::LegacyCitraUserDir];
|
||||||
|
std::string& legacy_lime3ds_user_path = g_paths[UserPath::LegacyLime3DSUserDir];
|
||||||
auto current_dir = FileUtil::GetCurrentDir();
|
auto current_dir = FileUtil::GetCurrentDir();
|
||||||
if (current_dir.has_value() &&
|
if (current_dir.has_value() &&
|
||||||
FileUtil::Exists(current_dir.value() + USERDATA_DIR DIR_SEP)) {
|
FileUtil::Exists(current_dir.value() + USERDATA_DIR DIR_SEP)) {
|
||||||
@ -804,23 +813,47 @@ void SetUserPath(const std::string& path) {
|
|||||||
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP);
|
||||||
} else {
|
} else {
|
||||||
std::string data_dir = GetUserDirectory("XDG_DATA_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
std::string data_dir = GetUserDirectory("XDG_DATA_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||||
|
|
||||||
|
std::string legacy_citra_data_dir =
|
||||||
|
GetUserDirectory("XDG_DATA_HOME") + DIR_SEP LEGACY_CITRA_DATA_DIR DIR_SEP;
|
||||||
|
std::string legacy_lime3ds_data_dir =
|
||||||
|
GetUserDirectory("XDG_DATA_HOME") + DIR_SEP LEGACY_LIME3DS_DATA_DIR DIR_SEP;
|
||||||
std::string config_dir =
|
std::string config_dir =
|
||||||
GetUserDirectory("XDG_CONFIG_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
GetUserDirectory("XDG_CONFIG_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||||
std::string cache_dir =
|
std::string cache_dir =
|
||||||
GetUserDirectory("XDG_CACHE_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
GetUserDirectory("XDG_CACHE_HOME") + DIR_SEP EMU_DATA_DIR DIR_SEP;
|
||||||
|
|
||||||
|
g_paths.emplace(UserPath::LegacyCitraConfigDir,
|
||||||
|
GetUserDirectory("XDG_CONFIG_HOME") +
|
||||||
|
DIR_SEP LEGACY_CITRA_DATA_DIR DIR_SEP);
|
||||||
|
g_paths.emplace(UserPath::LegacyCitraCacheDir,
|
||||||
|
GetUserDirectory("XDG_CACHE_HOME") +
|
||||||
|
DIR_SEP LEGACY_CITRA_DATA_DIR DIR_SEP);
|
||||||
|
g_paths.emplace(UserPath::LegacyLime3DSConfigDir,
|
||||||
|
GetUserDirectory("XDG_CONFIG_HOME") +
|
||||||
|
DIR_SEP LEGACY_LIME3DS_DATA_DIR DIR_SEP);
|
||||||
|
g_paths.emplace(UserPath::LegacyLime3DSCacheDir,
|
||||||
|
GetUserDirectory("XDG_CACHE_HOME") +
|
||||||
|
DIR_SEP LEGACY_LIME3DS_DATA_DIR DIR_SEP);
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
// If XDG directories don't already exist from a previous setup, use standard macOS
|
// If XDG directories don't already exist from a previous setup, use standard macOS
|
||||||
// paths.
|
// paths.
|
||||||
if (!FileUtil::Exists(data_dir) && !FileUtil::Exists(config_dir) &&
|
if (!FileUtil::Exists(data_dir) && !FileUtil::Exists(config_dir) &&
|
||||||
!FileUtil::Exists(cache_dir)) {
|
!FileUtil::Exists(cache_dir)) {
|
||||||
data_dir = GetHomeDirectory() + DIR_SEP APPLE_EMU_DATA_DIR DIR_SEP;
|
data_dir = GetHomeDirectory() + DIR_SEP EMU_APPLE_DATA_DIR DIR_SEP;
|
||||||
|
legacy_citra_data_dir =
|
||||||
|
GetHomeDirectory() + DIR_SEP LEGACY_CITRA_APPLE_DATA_DIR DIR_SEP;
|
||||||
|
legacy_lime3ds_data_dir =
|
||||||
|
GetHomeDirectory() + DIR_SEP LEGACY_LIME3DS_APPLE_DATA_DIR DIR_SEP;
|
||||||
config_dir = data_dir + CONFIG_DIR DIR_SEP;
|
config_dir = data_dir + CONFIG_DIR DIR_SEP;
|
||||||
cache_dir = data_dir + CACHE_DIR DIR_SEP;
|
cache_dir = data_dir + CACHE_DIR DIR_SEP;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
user_path = data_dir;
|
user_path = data_dir;
|
||||||
|
legacy_citra_user_path = legacy_citra_data_dir;
|
||||||
|
legacy_lime3ds_user_path = legacy_lime3ds_data_dir;
|
||||||
g_paths.emplace(UserPath::ConfigDir, config_dir);
|
g_paths.emplace(UserPath::ConfigDir, config_dir);
|
||||||
g_paths.emplace(UserPath::CacheDir, cache_dir);
|
g_paths.emplace(UserPath::CacheDir, cache_dir);
|
||||||
}
|
}
|
||||||
|
@ -39,17 +39,23 @@ enum class UserPath {
|
|||||||
ConfigDir,
|
ConfigDir,
|
||||||
DLLDir,
|
DLLDir,
|
||||||
DumpDir,
|
DumpDir,
|
||||||
|
IconsDir,
|
||||||
|
LegacyCitraCacheDir, // LegacyXXXCacheDir and LegacyXXXConfigDir are only defined if migrating
|
||||||
|
LegacyCitraConfigDir, // these directories is necessary (aka not a child of LegacyXXXUserDir)
|
||||||
|
LegacyCitraUserDir,
|
||||||
|
LegacyLime3DSCacheDir,
|
||||||
|
LegacyLime3DSConfigDir,
|
||||||
|
LegacyLime3DSUserDir,
|
||||||
LoadDir,
|
LoadDir,
|
||||||
LogDir,
|
LogDir,
|
||||||
NANDDir,
|
NANDDir,
|
||||||
|
PlayTimeDir,
|
||||||
RootDir,
|
RootDir,
|
||||||
SDMCDir,
|
SDMCDir,
|
||||||
ShaderDir,
|
ShaderDir,
|
||||||
StatesDir,
|
StatesDir,
|
||||||
SysDataDir,
|
SysDataDir,
|
||||||
UserDir,
|
UserDir,
|
||||||
IconsDir,
|
|
||||||
PlayTimeDir,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Replaces install-specific paths with standard placeholders, and back again
|
// Replaces install-specific paths with standard placeholders, and back again
|
||||||
|
Loading…
x
Reference in New Issue
Block a user