[qt] fix translations (#2773)
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>
This commit is contained in:
parent
b330117a14
commit
a53823646c
11 changed files with 234 additions and 193 deletions
|
|
@ -15,21 +15,12 @@
|
|||
#include <core/hle/service/am/frontend/applet_mii_edit.h>
|
||||
#include <string>
|
||||
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/set/settings_types.h"
|
||||
#include "core/hle/service/set/system_settings_server.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace FirmwareManager {
|
||||
|
||||
static constexpr std::array<const char *, 5> KEY_INSTALL_RESULT_STRINGS = {
|
||||
"Decryption Keys were successfully installed",
|
||||
"Unable to read key directory, aborting",
|
||||
"One or more keys failed to copy.",
|
||||
"Verify your keys file has a .keys extension and try again.",
|
||||
"Decryption Keys failed to initialize. Check that your dumping tools are up to date and "
|
||||
"re-dump keys.",
|
||||
};
|
||||
|
||||
static constexpr std::array<u64, 1> FIRMWARE_REQUIRED_GAMES = {
|
||||
0x0100152000022000ULL, // MK8DX
|
||||
};
|
||||
|
|
@ -50,16 +41,6 @@ enum KeyInstallResult {
|
|||
*/
|
||||
KeyInstallResult InstallKeys(std::string location, std::string expected_extension);
|
||||
|
||||
/**
|
||||
* \brief Get a string representation of a result from InstallKeys.
|
||||
* \param result The result code.
|
||||
* \return A string representation of the passed result code.
|
||||
*/
|
||||
inline constexpr const char *GetKeyInstallResultString(KeyInstallResult result)
|
||||
{
|
||||
return KEY_INSTALL_RESULT_STRINGS.at(static_cast<std::size_t>(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the specified program requires firmware to run properly.
|
||||
* It is the responsibility of the frontend to properly expose this to the user.
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ target_compile_definitions(qt_common PUBLIC
|
|||
|
||||
add_subdirectory(externals)
|
||||
|
||||
find_package(frozen REQUIRED)
|
||||
# pass targets
|
||||
find_package(frozen)
|
||||
|
||||
target_link_libraries(qt_common PRIVATE core Qt6::Core Qt6::Concurrent SimpleIni::SimpleIni QuaZip::QuaZip)
|
||||
target_link_libraries(qt_common PUBLIC frozen::frozen-headers)
|
||||
|
|
|
|||
3
src/qt_common/externals/cpmfile.json
vendored
3
src/qt_common/externals/cpmfile.json
vendored
|
|
@ -13,7 +13,6 @@
|
|||
"package": "frozen",
|
||||
"repo": "serge-sans-paille/frozen",
|
||||
"sha": "61dce5ae18",
|
||||
"hash": "1ae3d073e659c1f24b2cdd76379c90d6af9e06bc707d285a4fafce05f7a4c9e592ff208c94a9ae0f0d07620b3c6cec191f126b03d70ad4dfa496a86ed5658a6d",
|
||||
"bundled": true
|
||||
"hash": "1ae3d073e659c1f24b2cdd76379c90d6af9e06bc707d285a4fafce05f7a4c9e592ff208c94a9ae0f0d07620b3c6cec191f126b03d70ad4dfa496a86ed5658a6d"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <frozen/string.h>
|
||||
#include <frozen/unordered_map.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qtmetamacros.h>
|
||||
#include "frozen/map.h"
|
||||
#include "frozen/string.h"
|
||||
|
||||
namespace QtCommon::StringLookup {
|
||||
|
||||
|
|
@ -20,19 +19,85 @@ enum StringKey {
|
|||
UserNandTooltip,
|
||||
SysNandTooltip,
|
||||
ModsTooltip,
|
||||
|
||||
// Key install results
|
||||
KeyInstallSuccess,
|
||||
KeyInstallInvalidDir,
|
||||
KeyInstallErrorFailedCopy,
|
||||
KeyInstallErrorWrongFilename,
|
||||
KeyInstallErrorFailedInit,
|
||||
|
||||
// Firmware install results
|
||||
FwInstallSuccess,
|
||||
FwInstallNoNCAs,
|
||||
FwInstallFailedDelete,
|
||||
FwInstallFailedCopy,
|
||||
FwInstallFailedCorrupted,
|
||||
|
||||
// user data migrator
|
||||
MigrationPromptPrefix,
|
||||
MigrationPrompt,
|
||||
MigrationTooltipClearShader,
|
||||
MigrationTooltipKeepOld,
|
||||
MigrationTooltipClearOld,
|
||||
MigrationTooltipLinkOld,
|
||||
|
||||
};
|
||||
|
||||
static constexpr const frozen::unordered_map<StringKey, frozen::string, 5> strings = {
|
||||
{SavesTooltip, "Contains game save data. DO NOT REMOVE UNLESS YOU KNOW WHAT YOU'RE DOING!"},
|
||||
{ShadersTooltip, "Contains Vulkan and OpenGL pipeline caches. Generally safe to remove."},
|
||||
{UserNandTooltip, "Contains updates and DLC for games."},
|
||||
{SysNandTooltip, "Contains firmware and applet data."},
|
||||
{ModsTooltip, "Contains game mods, patches, and cheats."},
|
||||
static const frozen::map<StringKey, frozen::string, 21> strings = {
|
||||
{SavesTooltip,
|
||||
QT_TR_NOOP("Contains game save data. DO NOT REMOVE UNLESS YOU KNOW WHAT YOU'RE DOING!")},
|
||||
{ShadersTooltip,
|
||||
QT_TR_NOOP("Contains Vulkan and OpenGL pipeline caches. Generally safe to remove.")},
|
||||
{UserNandTooltip, QT_TR_NOOP("Contains updates and DLC for games.")},
|
||||
{SysNandTooltip, QT_TR_NOOP("Contains firmware and applet data.")},
|
||||
{ModsTooltip, QT_TR_NOOP("Contains game mods, patches, and cheats.")},
|
||||
|
||||
// Key install
|
||||
{KeyInstallSuccess, QT_TR_NOOP("Decryption Keys were successfully installed")},
|
||||
{KeyInstallInvalidDir, QT_TR_NOOP("Unable to read key directory, aborting")},
|
||||
{KeyInstallErrorFailedCopy, QT_TR_NOOP("One or more keys failed to copy.")},
|
||||
{KeyInstallErrorWrongFilename,
|
||||
QT_TR_NOOP("Verify your keys file has a .keys extension and try again.")},
|
||||
{KeyInstallErrorFailedInit,
|
||||
QT_TR_NOOP(
|
||||
"Decryption Keys failed to initialize. Check that your dumping tools are up to date and "
|
||||
"re-dump keys.")},
|
||||
|
||||
// fw install
|
||||
{FwInstallSuccess, QT_TR_NOOP("Successfully installed firmware version %1")},
|
||||
{FwInstallNoNCAs, QT_TR_NOOP("Unable to locate potential firmware NCA files")},
|
||||
{FwInstallFailedDelete, QT_TR_NOOP("Failed to delete one or more firmware files.")},
|
||||
{FwInstallFailedCopy, QT_TR_NOOP("One or more firmware files failed to copy into NAND.")},
|
||||
{FwInstallFailedCorrupted,
|
||||
QT_TR_NOOP(
|
||||
"Firmware installation cancelled, firmware may be in a bad state or corrupted. Restart "
|
||||
"Eden or re-install firmware.")},
|
||||
|
||||
// migrator
|
||||
{MigrationPromptPrefix, QT_TR_NOOP("Eden has detected user data for the following emulators:")},
|
||||
{MigrationPrompt,
|
||||
QT_TR_NOOP("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.")},
|
||||
{MigrationTooltipClearShader,
|
||||
QT_TR_NOOP("Clearing shader cache is recommended for all "
|
||||
"users.\nDo not uncheck unless you know what "
|
||||
"you're doing.")},
|
||||
{MigrationTooltipKeepOld,
|
||||
QT_TR_NOOP("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.")},
|
||||
{MigrationTooltipClearOld,
|
||||
QT_TR_NOOP("Deletes the old data directory.\nThis is recommended on "
|
||||
"devices with space constraints.")},
|
||||
{MigrationTooltipLinkOld,
|
||||
QT_TR_NOOP("Creates a filesystem link between the old directory and Eden directory.\n"
|
||||
"This is recommended if you want to share data between emulators.")},
|
||||
};
|
||||
|
||||
static inline const QString Lookup(StringKey key)
|
||||
{
|
||||
return QString::fromStdString(strings.at(key).data());
|
||||
return QObject::tr(strings.at(key).data());
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace QtCommon::StringLookup
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@
|
|||
#include "frontend_common/data_manager.h"
|
||||
#include "frontend_common/firmware_manager.h"
|
||||
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "compress.h"
|
||||
#include "qt_common/abstract/qt_progress_dialog.h"
|
||||
#include "qt_common/abstract/qt_frontend_util.h"
|
||||
#include "qt_common/abstract/qt_progress_dialog.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QtConcurrentRun>
|
||||
#include <JlCompress.h>
|
||||
#include <QFutureWatcher>
|
||||
|
||||
namespace QtCommon::Content {
|
||||
|
||||
|
|
@ -60,15 +60,15 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
return progress.wasCanceled();
|
||||
};
|
||||
|
||||
static constexpr const char* failedTitle = "Firmware Install Failed";
|
||||
static constexpr const char* successTitle = "Firmware Install Succeeded";
|
||||
QString failedTitle = tr("Firmware Install Failed");
|
||||
QString successTitle = tr("Firmware Install Succeeded");
|
||||
QMessageBox::Icon icon;
|
||||
FirmwareInstallResult result;
|
||||
|
||||
const auto ShowMessage = [&]() {
|
||||
QtCommon::Frontend::ShowMessage(icon,
|
||||
tr(failedTitle),
|
||||
tr(GetFirmwareInstallResultString(result)));
|
||||
failedTitle,
|
||||
GetFirmwareInstallResultString(result));
|
||||
};
|
||||
|
||||
LOG_INFO(Frontend, "Installing firmware from {}", location.toStdString());
|
||||
|
|
@ -188,10 +188,9 @@ void InstallFirmware(const QString& location, bool recursive)
|
|||
const std::string display_version(firmware_data.display_version.data());
|
||||
|
||||
result = FirmwareInstallResult::Success;
|
||||
QtCommon::Frontend::Information(
|
||||
rootObject,
|
||||
tr(successTitle),
|
||||
tr(GetFirmwareInstallResultString(result)).arg(QString::fromStdString(display_version)));
|
||||
QtCommon::Frontend::Information(successTitle,
|
||||
GetFirmwareInstallResultString(result).arg(
|
||||
QString::fromStdString(display_version)));
|
||||
}
|
||||
|
||||
QString UnzipFirmwareToTmp(const QString& location)
|
||||
|
|
@ -277,14 +276,13 @@ void InstallKeys()
|
|||
|
||||
system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
|
||||
|
||||
const QString resMsg = GetKeyInstallResultString(result);
|
||||
switch (result) {
|
||||
case FirmwareManager::KeyInstallResult::Success:
|
||||
QtCommon::Frontend::Information(tr("Decryption Keys install succeeded"),
|
||||
tr("Decryption Keys were successfully installed"));
|
||||
QtCommon::Frontend::Information(tr("Decryption Keys install succeeded"), resMsg);
|
||||
break;
|
||||
default:
|
||||
QtCommon::Frontend::Critical(tr("Decryption Keys install failed"),
|
||||
tr(FirmwareManager::GetKeyInstallResultString(result)));
|
||||
QtCommon::Frontend::Critical(tr("Decryption Keys install failed"), resMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -296,7 +294,7 @@ void VerifyInstalledContents()
|
|||
tr("Cancel"),
|
||||
0,
|
||||
100,
|
||||
QtCommon::rootObject);
|
||||
rootObject);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setMinimumDuration(100);
|
||||
progress.setAutoClose(false);
|
||||
|
|
@ -415,7 +413,9 @@ void ExportDataDir(FrontendCommon::DataManager::DataDir data_dir,
|
|||
QGuiApplication::processEvents();
|
||||
|
||||
auto progress_callback = [=](size_t total_size, size_t processed_size) {
|
||||
QMetaObject::invokeMethod(progress, "setValue", Qt::DirectConnection,
|
||||
QMetaObject::invokeMethod(progress,
|
||||
"setValue",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
|
||||
return !progress->wasCanceled();
|
||||
};
|
||||
|
|
@ -499,8 +499,11 @@ void ImportDataDir(FrontendCommon::DataManager::DataDir data_dir,
|
|||
|
||||
QObject::connect(delete_watcher, &QFutureWatcher<bool>::finished, rootObject, [=]() {
|
||||
auto progress_callback = [=](size_t total_size, size_t processed_size) {
|
||||
QMetaObject::invokeMethod(progress, "setValue", Qt::DirectConnection,
|
||||
Q_ARG(int, static_cast<int>((processed_size * 100) / total_size)));
|
||||
QMetaObject::invokeMethod(progress,
|
||||
"setValue",
|
||||
Qt::DirectConnection,
|
||||
Q_ARG(int,
|
||||
static_cast<int>((processed_size * 100) / total_size)));
|
||||
return !progress->wasCanceled();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,33 +7,36 @@
|
|||
#include <QObject>
|
||||
#include "common/common_types.h"
|
||||
#include "frontend_common/data_manager.h"
|
||||
#include "frontend_common/firmware_manager.h"
|
||||
#include "qt_common/qt_string_lookup.h"
|
||||
|
||||
namespace QtCommon::Content {
|
||||
|
||||
//
|
||||
bool CheckGameFirmware(u64 program_id, QObject *parent);
|
||||
|
||||
static constexpr std::array<const char *, 6> FIRMWARE_RESULTS
|
||||
= {"Successfully installed firmware version %1",
|
||||
"",
|
||||
"Unable to locate potential firmware NCA files",
|
||||
"Failed to delete one or more firmware files.",
|
||||
"One or more firmware files failed to copy into NAND.",
|
||||
"Firmware installation cancelled, firmware may be in a bad state or corrupted."
|
||||
"Restart Eden or re-install firmware."};
|
||||
|
||||
enum class FirmwareInstallResult {
|
||||
Success,
|
||||
NoOp,
|
||||
NoNCAs,
|
||||
FailedDelete,
|
||||
FailedCopy,
|
||||
FailedCorrupted,
|
||||
};
|
||||
|
||||
inline constexpr const char *GetFirmwareInstallResultString(FirmwareInstallResult result)
|
||||
inline const QString GetFirmwareInstallResultString(FirmwareInstallResult result)
|
||||
{
|
||||
return FIRMWARE_RESULTS.at(static_cast<std::size_t>(result));
|
||||
return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>((int) result + (int) QtCommon::StringLookup::FwInstallSuccess));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get a string representation of a result from InstallKeys.
|
||||
* \param result The result code.
|
||||
* \return A string representation of the passed result code.
|
||||
*/
|
||||
inline const QString GetKeyInstallResultString(FirmwareManager::KeyInstallResult result)
|
||||
{
|
||||
// this can probably be made into a common function of sorts
|
||||
return QtCommon::StringLookup::Lookup(static_cast<StringLookup::StringKey>((int) result + (int) QtCommon::StringLookup::KeyInstallSuccess));
|
||||
}
|
||||
|
||||
void InstallFirmware(const QString &location, bool recursive);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@
|
|||
#include "core/file_sys/savedata_factory.h"
|
||||
#include "core/hle/service/am/am_types.h"
|
||||
#include "frontend_common/content_manager.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
#include "qt_common/abstract/qt_frontend_util.h"
|
||||
#include "qt_common/config/uisettings.h"
|
||||
#include "qt_common/qt_common.h"
|
||||
#include "yuzu/util/util.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
|
|
@ -166,7 +166,8 @@ bool MakeShortcutIcoPath(const u64 program_id,
|
|||
|
||||
void OpenEdenFolder(const Common::FS::EdenPath& path)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(Common::FS::GetEdenPathString(path))));
|
||||
QDesktopServices::openUrl(
|
||||
QUrl::fromLocalFile(QString::fromStdString(Common::FS::GetEdenPathString(path))));
|
||||
}
|
||||
|
||||
void OpenRootDataFolder()
|
||||
|
|
@ -181,7 +182,8 @@ void OpenNANDFolder()
|
|||
|
||||
void OpenSaveFolder()
|
||||
{
|
||||
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir) / "user/save/0000000000000000";
|
||||
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
|
||||
/ "user/save/0000000000000000";
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(path.string())));
|
||||
}
|
||||
|
||||
|
|
@ -220,12 +222,11 @@ void RemoveBaseContent(u64 program_id, InstalledEntryType type)
|
|||
const auto res = ContentManager::RemoveBaseContent(system->GetFileSystemController(),
|
||||
program_id);
|
||||
if (res) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed the installed base game."));
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(
|
||||
rootObject,
|
||||
|
||||
GetGameListErrorRemoving(type),
|
||||
tr("The base game is not installed in the NAND and cannot be removed."));
|
||||
}
|
||||
|
|
@ -235,12 +236,10 @@ void RemoveUpdateContent(u64 program_id, InstalledEntryType type)
|
|||
{
|
||||
const auto res = ContentManager::RemoveUpdate(system->GetFileSystemController(), program_id);
|
||||
if (res) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed the installed update."));
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
GetGameListErrorRemoving(type),
|
||||
QtCommon::Frontend::Warning(GetGameListErrorRemoving(type),
|
||||
tr("There is no update installed for this title."));
|
||||
}
|
||||
}
|
||||
|
|
@ -249,14 +248,12 @@ void RemoveAddOnContent(u64 program_id, InstalledEntryType type)
|
|||
{
|
||||
const size_t count = ContentManager::RemoveAllDLC(*system, program_id);
|
||||
if (count == 0) {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
GetGameListErrorRemoving(type),
|
||||
QtCommon::Frontend::Warning(GetGameListErrorRemoving(type),
|
||||
tr("There are no DLCs installed for this title."));
|
||||
return;
|
||||
}
|
||||
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed %1 installed DLC.").arg(count));
|
||||
}
|
||||
|
||||
|
|
@ -279,18 +276,15 @@ void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target)
|
|||
const auto target_file = shader_cache_folder_path / target_file_name;
|
||||
|
||||
if (!Common::FS::Exists(target_file)) {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Transferable Shader Cache"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Transferable Shader Cache"),
|
||||
tr("A shader cache for this title does not exist."));
|
||||
return;
|
||||
}
|
||||
if (Common::FS::RemoveFile(target_file)) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed the transferable shader cache."));
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Transferable Shader Cache"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Transferable Shader Cache"),
|
||||
tr("Failed to remove the transferable shader cache."));
|
||||
}
|
||||
}
|
||||
|
|
@ -307,8 +301,7 @@ void RemoveVulkanDriverPipelineCache(u64 program_id)
|
|||
return;
|
||||
}
|
||||
if (!Common::FS::RemoveFile(target_file)) {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Vulkan Driver Pipeline Cache"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Vulkan Driver Pipeline Cache"),
|
||||
tr("Failed to remove the driver pipeline cache."));
|
||||
}
|
||||
}
|
||||
|
|
@ -319,18 +312,16 @@ void RemoveAllTransferableShaderCaches(u64 program_id)
|
|||
const auto program_shader_cache_dir = shader_cache_dir / fmt::format("{:016x}", program_id);
|
||||
|
||||
if (!Common::FS::Exists(program_shader_cache_dir)) {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Transferable Shader Caches"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Transferable Shader Caches"),
|
||||
tr("A shader cache for this title does not exist."));
|
||||
return;
|
||||
}
|
||||
if (Common::FS::RemoveDirRecursively(program_shader_cache_dir)) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed the transferable shader caches."));
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(
|
||||
rootObject,
|
||||
|
||||
tr("Error Removing Transferable Shader Caches"),
|
||||
tr("Failed to remove the transferable shader cache directory."));
|
||||
}
|
||||
|
|
@ -339,27 +330,23 @@ void RemoveAllTransferableShaderCaches(u64 program_id)
|
|||
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path)
|
||||
{
|
||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
|
||||
const auto config_file_name = program_id == 0
|
||||
? Common::FS::PathToUTF8String(file_path.filename())
|
||||
.append(".ini")
|
||||
: fmt::format("{:016X}.ini", program_id);
|
||||
const auto config_file_name
|
||||
= program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
|
||||
: fmt::format("{:016X}.ini", program_id);
|
||||
const auto custom_config_file_path = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir)
|
||||
/ "custom" / config_file_name;
|
||||
|
||||
if (!Common::FS::Exists(custom_config_file_path)) {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Custom Configuration"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Custom Configuration"),
|
||||
tr("A custom configuration for this title does not exist."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Common::FS::RemoveFile(custom_config_file_path)) {
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
tr("Successfully Removed"),
|
||||
QtCommon::Frontend::Information(tr("Successfully Removed"),
|
||||
tr("Successfully removed the custom game configuration."));
|
||||
} else {
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
tr("Error Removing Custom Configuration"),
|
||||
QtCommon::Frontend::Warning(tr("Error Removing Custom Configuration"),
|
||||
tr("Failed to remove the custom game configuration."));
|
||||
}
|
||||
}
|
||||
|
|
@ -392,18 +379,23 @@ void ResetMetadata(bool show_message)
|
|||
|
||||
if (!Common::FS::Exists(Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir)
|
||||
/ "game_list/")) {
|
||||
if (show_message) QtCommon::Frontend::Warning(rootObject, title, tr("The metadata cache is already empty."));
|
||||
if (show_message)
|
||||
QtCommon::Frontend::Warning(rootObject,
|
||||
title,
|
||||
tr("The metadata cache is already empty."));
|
||||
} else if (Common::FS::RemoveDirRecursively(
|
||||
Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir) / "game_list")) {
|
||||
if (show_message) QtCommon::Frontend::Information(rootObject,
|
||||
title,
|
||||
tr("The operation completed successfully."));
|
||||
if (show_message)
|
||||
QtCommon::Frontend::Information(rootObject,
|
||||
title,
|
||||
tr("The operation completed successfully."));
|
||||
UISettings::values.is_game_list_reload_pending.exchange(true);
|
||||
} else {
|
||||
if (show_message) QtCommon::Frontend::Warning(
|
||||
rootObject,
|
||||
title,
|
||||
tr("The metadata cache couldn't be deleted. It might be in use or non-existent."));
|
||||
if (show_message)
|
||||
QtCommon::Frontend::Warning(
|
||||
|
||||
title,
|
||||
tr("The metadata cache couldn't be deleted. It might be in use or non-existent."));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -446,7 +438,7 @@ inline constexpr bool CreateShortcutMessagesGUI(ShortcutMessages imsg, const QSt
|
|||
void CreateShortcut(const std::string& game_path,
|
||||
const u64 program_id,
|
||||
const std::string& game_title_,
|
||||
const ShortcutTarget &target,
|
||||
const ShortcutTarget& target,
|
||||
std::string arguments_,
|
||||
const bool needs_title)
|
||||
{
|
||||
|
|
@ -458,16 +450,18 @@ void CreateShortcut(const std::string& game_path,
|
|||
|
||||
if (!std::filesystem::exists(shortcut_path)) {
|
||||
CreateShortcutMessagesGUI(ShortcutMessages::Failed,
|
||||
QString::fromStdString(shortcut_path.generic_string()));
|
||||
QString::fromStdString(shortcut_path.generic_string()));
|
||||
LOG_ERROR(Frontend, "Invalid shortcut target {}", shortcut_path.generic_string());
|
||||
return;
|
||||
}
|
||||
|
||||
const FileSys::PatchManager pm{program_id, QtCommon::system->GetFileSystemController(),
|
||||
const FileSys::PatchManager pm{program_id,
|
||||
QtCommon::system->GetFileSystemController(),
|
||||
QtCommon::system->GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
const auto loader =
|
||||
Loader::GetLoader(*QtCommon::system, QtCommon::vfs->OpenFile(game_path, FileSys::OpenMode::Read));
|
||||
const auto loader = Loader::GetLoader(*QtCommon::system,
|
||||
QtCommon::vfs->OpenFile(game_path,
|
||||
FileSys::OpenMode::Read));
|
||||
|
||||
std::string game_title{game_title_};
|
||||
|
||||
|
|
@ -498,8 +492,8 @@ void CreateShortcut(const std::string& game_path,
|
|||
LOG_WARNING(Frontend, "Could not read icon from {:s}", game_path);
|
||||
}
|
||||
|
||||
QImage icon_data =
|
||||
QImage::fromData(icon_image_file.data(), static_cast<int>(icon_image_file.size()));
|
||||
QImage icon_data = QImage::fromData(icon_image_file.data(),
|
||||
static_cast<int>(icon_image_file.size()));
|
||||
std::filesystem::path out_icon_path;
|
||||
if (QtCommon::Game::MakeShortcutIcoPath(program_id, game_title, out_icon_path)) {
|
||||
if (!SaveIconToFile(out_icon_path, icon_data)) {
|
||||
|
|
@ -532,33 +526,39 @@ void CreateShortcut(const std::string& game_path,
|
|||
const std::string categories = "Game;Emulator;Qt;";
|
||||
const std::string keywords = "Switch;Nintendo;";
|
||||
|
||||
if (QtCommon::Game::CreateShortcutLink(shortcut_path, comment, out_icon_path, command,
|
||||
arguments, categories, keywords, game_title)) {
|
||||
CreateShortcutMessagesGUI(ShortcutMessages::Success,
|
||||
qgame_title);
|
||||
if (QtCommon::Game::CreateShortcutLink(shortcut_path,
|
||||
comment,
|
||||
out_icon_path,
|
||||
command,
|
||||
arguments,
|
||||
categories,
|
||||
keywords,
|
||||
game_title)) {
|
||||
CreateShortcutMessagesGUI(ShortcutMessages::Success, qgame_title);
|
||||
return;
|
||||
}
|
||||
CreateShortcutMessagesGUI(ShortcutMessages::Failed,
|
||||
qgame_title);
|
||||
CreateShortcutMessagesGUI(ShortcutMessages::Failed, qgame_title);
|
||||
}
|
||||
|
||||
// TODO: You want this to be constexpr? Well too bad, clang19 doesn't believe this is a string literal
|
||||
std::string GetShortcutPath(ShortcutTarget target) {
|
||||
std::string GetShortcutPath(ShortcutTarget target)
|
||||
{
|
||||
{
|
||||
std::string shortcut_path{};
|
||||
if (target == ShortcutTarget::Desktop) {
|
||||
shortcut_path = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)
|
||||
.toStdString();
|
||||
shortcut_path
|
||||
= QStandardPaths::writableLocation(QStandardPaths::DesktopLocation).toStdString();
|
||||
} else if (target == ShortcutTarget::Applications) {
|
||||
shortcut_path = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation)
|
||||
.toStdString();
|
||||
shortcut_path
|
||||
= QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation).toStdString();
|
||||
}
|
||||
|
||||
return shortcut_path;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateHomeMenuShortcut(ShortcutTarget target) {
|
||||
void CreateHomeMenuShortcut(ShortcutTarget target)
|
||||
{
|
||||
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
|
||||
auto bis_system = QtCommon::system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ GMainWindow::GMainWindow(bool has_broken_vulkan)
|
|||
#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"); \
|
||||
boost::replace_all(type##path, user_data_migrator.selected_emu.lower_name().toStdString(), "eden"); \
|
||||
Common::FS::SetEdenPath(Common::FS::EdenPath::type##Dir, type##path); \
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ void MigrationWorker::process()
|
|||
namespace fs = std::filesystem;
|
||||
constexpr auto copy_options = fs::copy_options::update_existing | fs::copy_options::recursive;
|
||||
|
||||
const fs::path legacy_user_dir = selected_legacy_emu.get_user_dir();
|
||||
const fs::path legacy_user_dir = selected_legacy_emu.get_user_dir();
|
||||
const fs::path legacy_config_dir = selected_legacy_emu.get_config_dir();
|
||||
const fs::path legacy_cache_dir = selected_legacy_emu.get_cache_dir();
|
||||
const fs::path legacy_cache_dir = selected_legacy_emu.get_cache_dir();
|
||||
|
||||
// TODO(crueter): Make these constexpr since they're defaulted
|
||||
const fs::path eden_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::EdenDir);
|
||||
const fs::path eden_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::EdenDir);
|
||||
const fs::path config_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ConfigDir);
|
||||
const fs::path cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir);
|
||||
const fs::path cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir);
|
||||
const fs::path shader_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::ShaderDir);
|
||||
|
||||
try {
|
||||
|
|
@ -68,7 +68,7 @@ void MigrationWorker::process()
|
|||
|
||||
success_text.append(tr("\n\nNote that your configuration and data will be shared with %1.\n"
|
||||
"If this is not desirable, delete the following files:\n%2\n%3\n%4")
|
||||
.arg(tr(selected_legacy_emu.name),
|
||||
.arg(selected_legacy_emu.name(),
|
||||
QString::fromStdString(eden_dir.string()),
|
||||
QString::fromStdString(config_dir.string()),
|
||||
QString::fromStdString(cache_dir.string())));
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
using namespace Common::FS;
|
||||
|
||||
typedef struct Emulator {
|
||||
const char *name;
|
||||
const char *m_name;
|
||||
|
||||
LegacyPath e_user_dir;
|
||||
LegacyPath e_config_dir;
|
||||
|
|
@ -28,23 +28,19 @@ typedef struct Emulator {
|
|||
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); });
|
||||
const QString name() const { return QObject::tr(m_name);
|
||||
}
|
||||
|
||||
return lower_name;
|
||||
const QString lower_name() const { return name().toLower();
|
||||
}
|
||||
} 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),
|
||||
Emulator{QT_TR_NOOP("Citron"), CitronDir, CitronConfigDir, CitronCacheDir},
|
||||
Emulator{QT_TR_NOOP("Sudachi"), SudachiDir, SudachiConfigDir, SudachiCacheDir},
|
||||
Emulator{QT_TR_NOOP("Suyu"), SuyuDir, SuyuConfigDir, SuyuCacheDir},
|
||||
Emulator{QT_TR_NOOP("Yuzu"), YuzuDir, YuzuConfigDir, YuzuCacheDir},
|
||||
};
|
||||
#undef EMU
|
||||
|
||||
class MigrationWorker : public QObject
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,12 +11,13 @@
|
|||
#include <QString>
|
||||
#include <QTranslator>
|
||||
#include "common/fs/path_util.h"
|
||||
#include "../yuzu/migration_dialog.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 <QGuiApplication>
|
||||
#include <QButtonGroup>
|
||||
#include <QCheckBox>
|
||||
#include <QGuiApplication>
|
||||
#include <QProgressDialog>
|
||||
#include <QRadioButton>
|
||||
#include <QThread>
|
||||
|
|
@ -41,30 +42,19 @@ void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
|||
namespace fs = std::filesystem;
|
||||
|
||||
// define strings here for easy access
|
||||
static constexpr const char *prompt_prefix_text
|
||||
= "Eden has detected user data for the following emulators:";
|
||||
|
||||
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.";
|
||||
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
|
||||
|
||||
|
|
@ -78,12 +68,12 @@ void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
|||
|
||||
#define BUTTON(clazz, name, text, tooltip, checkState) \
|
||||
clazz *name = new clazz(&migration_prompt); \
|
||||
name->setText(QObject::tr(text)); \
|
||||
name->setToolTip(QObject::tr(tooltip)); \
|
||||
name->setText(text); \
|
||||
name->setToolTip(tooltip); \
|
||||
name->setChecked(checkState); \
|
||||
migration_prompt.addBox(name);
|
||||
|
||||
BUTTON(QCheckBox, clear_shaders, "Clear Shader Cache", clear_shader_tooltip, true)
|
||||
BUTTON(QCheckBox, clear_shaders, QObject::tr("Clear Shader Cache"), clear_shader_tooltip, true)
|
||||
|
||||
u32 id = 0;
|
||||
|
||||
|
|
@ -91,9 +81,9 @@ void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
|||
BUTTON(QRadioButton, name, text, tooltip, checkState) \
|
||||
group->addButton(name, ++id);
|
||||
|
||||
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)
|
||||
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
|
||||
|
|
@ -111,20 +101,20 @@ void UserDataMigrator::ShowMigrationPrompt(QMainWindow *main_window)
|
|||
// makes my life easier
|
||||
qRegisterMetaType<Emulator>();
|
||||
|
||||
QString prompt_text = QObject::tr(prompt_prefix_text);
|
||||
QString prompt_text = 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)));
|
||||
prompt_text = prompt_text % QStringLiteral("\n ") % emu.name();
|
||||
|
||||
QAbstractButton *button = migration_prompt.addButton(QObject::tr(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.append(QObject::tr(migration_prompt_message));
|
||||
prompt_text = prompt_text % QStringLiteral("\n\n") % migration_prompt_message;
|
||||
|
||||
migration_prompt.setText(prompt_text);
|
||||
migration_prompt.addButton(QObject::tr("No"), true);
|
||||
|
|
@ -191,16 +181,19 @@ void UserDataMigrator::MigrateUserData(QMainWindow *main_window,
|
|||
|
||||
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);
|
||||
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();
|
||||
});
|
||||
migrated = true;
|
||||
thread->quit();
|
||||
});
|
||||
|
||||
thread->connect(worker, &MigrationWorker::finished, worker, &QObject::deleteLater);
|
||||
thread->connect(thread, &QThread::finished, thread, &QObject::deleteLater);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue