diff options
Diffstat (limited to 'src/yuzu/configuration')
42 files changed, 1657 insertions, 936 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 4650f96a3..10e5c5c38 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> +#include <QKeySequence> #include <QSettings> #include "common/file_util.h" #include "configure_input_simple.h" @@ -17,7 +19,6 @@ Config::Config() { FileUtil::CreateFullPath(qt_config_loc); qt_config = std::make_unique<QSettings>(QString::fromStdString(qt_config_loc), QSettings::IniFormat); - Reload(); } @@ -205,59 +206,92 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default Qt::Key_Control, Qt::Key_Shift, Qt::Key_AltGr, Qt::Key_ApplicationRight, }; +// This shouldn't have anything except static initializers (no functions). So +// QKeySequence(...).toString() is NOT ALLOWED HERE. +// This must be in alphabetical order according to action name as it must have the same order as +// UISetting::values.shortcuts, which is alphabetically ordered. +// clang-format off +const std::array<UISettings::Shortcut, 15> default_hotkeys{{ + {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}}, + {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, + {QStringLiteral("Decrease Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("-"), Qt::ApplicationShortcut}}, + {QStringLiteral("Exit yuzu"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Q"), Qt::WindowShortcut}}, + {QStringLiteral("Exit Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("Esc"), Qt::WindowShortcut}}, + {QStringLiteral("Fullscreen"), QStringLiteral("Main Window"), {QStringLiteral("F11"), Qt::WindowShortcut}}, + {QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}}, + {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::ApplicationShortcut}}, + {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WindowShortcut}}, + {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, + {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, + {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, + {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, + {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}}, + {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, +}}; +// clang-format on + void Config::ReadPlayerValues() { for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { auto& player = Settings::values.players[p]; - player.connected = ReadSetting(QString("player_%1_connected").arg(p), false).toBool(); + player.connected = + ReadSetting(QStringLiteral("player_%1_connected").arg(p), false).toBool(); player.type = static_cast<Settings::ControllerType>( qt_config - ->value(QString("player_%1_type").arg(p), + ->value(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(Settings::ControllerType::DualJoycon)) .toUInt()); player.body_color_left = qt_config - ->value(QString("player_%1_body_color_left").arg(p), + ->value(QStringLiteral("player_%1_body_color_left").arg(p), Settings::JOYCON_BODY_NEON_BLUE) .toUInt(); player.body_color_right = qt_config - ->value(QString("player_%1_body_color_right").arg(p), + ->value(QStringLiteral("player_%1_body_color_right").arg(p), Settings::JOYCON_BODY_NEON_RED) .toUInt(); player.button_color_left = qt_config - ->value(QString("player_%1_button_color_left").arg(p), + ->value(QStringLiteral("player_%1_button_color_left").arg(p), Settings::JOYCON_BUTTONS_NEON_BLUE) .toUInt(); - player.button_color_right = qt_config - ->value(QString("player_%1_button_color_right").arg(p), - Settings::JOYCON_BUTTONS_NEON_RED) - .toUInt(); + player.button_color_right = + qt_config + ->value(QStringLiteral("player_%1_button_color_right").arg(p), + Settings::JOYCON_BUTTONS_NEON_RED) + .toUInt(); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - player.buttons[i] = - qt_config - ->value(QString("player_%1_").arg(p) + Settings::NativeButton::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player.buttons[i].empty()) - player.buttons[i] = default_param; + const std::string default_param = + InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& player_buttons = player.buttons[i]; + + player_buttons = qt_config + ->value(QStringLiteral("player_%1_").arg(p) + + QString::fromUtf8(Settings::NativeButton::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (player_buttons.empty()) { + player_buttons = default_param; + } } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - player.analogs[i] = - qt_config - ->value(QString("player_%1_").arg(p) + Settings::NativeAnalog::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (player.analogs[i].empty()) - player.analogs[i] = default_param; + auto& player_analogs = player.analogs[i]; + + player_analogs = qt_config + ->value(QStringLiteral("player_%1_").arg(p) + + QString::fromUtf8(Settings::NativeAnalog::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (player_analogs.empty()) { + player_analogs = default_param; + } } } @@ -269,36 +303,45 @@ void Config::ReadPlayerValues() { } void Config::ReadDebugValues() { - Settings::values.debug_pad_enabled = ReadSetting("debug_pad_enabled", false).toBool(); + Settings::values.debug_pad_enabled = + ReadSetting(QStringLiteral("debug_pad_enabled"), false).toBool(); + for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - Settings::values.debug_pad_buttons[i] = - qt_config - ->value(QString("debug_pad_") + Settings::NativeButton::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (Settings::values.debug_pad_buttons[i].empty()) - Settings::values.debug_pad_buttons[i] = default_param; + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + auto& debug_pad_buttons = Settings::values.debug_pad_buttons[i]; + + debug_pad_buttons = qt_config + ->value(QStringLiteral("debug_pad_") + + QString::fromUtf8(Settings::NativeButton::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (debug_pad_buttons.empty()) { + debug_pad_buttons = default_param; + } } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - Settings::values.debug_pad_analogs[i] = - qt_config - ->value(QString("debug_pad_") + Settings::NativeAnalog::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (Settings::values.debug_pad_analogs[i].empty()) - Settings::values.debug_pad_analogs[i] = default_param; + auto& debug_pad_analogs = Settings::values.debug_pad_analogs[i]; + + debug_pad_analogs = qt_config + ->value(QStringLiteral("debug_pad_") + + QString::fromUtf8(Settings::NativeAnalog::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (debug_pad_analogs.empty()) { + debug_pad_analogs = default_param; + } } } void Config::ReadKeyboardValues() { - Settings::values.keyboard_enabled = ReadSetting("keyboard_enabled", false).toBool(); + Settings::values.keyboard_enabled = + ReadSetting(QStringLiteral("keyboard_enabled"), false).toBool(); std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); @@ -311,31 +354,41 @@ void Config::ReadKeyboardValues() { } void Config::ReadMouseValues() { - Settings::values.mouse_enabled = ReadSetting("mouse_enabled", false).toBool(); + Settings::values.mouse_enabled = ReadSetting(QStringLiteral("mouse_enabled"), false).toBool(); for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - Settings::values.mouse_buttons[i] = - qt_config - ->value(QString("mouse_") + Settings::NativeMouseButton::mapping[i], - QString::fromStdString(default_param)) - .toString() - .toStdString(); - if (Settings::values.mouse_buttons[i].empty()) - Settings::values.mouse_buttons[i] = default_param; + const std::string default_param = + InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); + auto& mouse_buttons = Settings::values.mouse_buttons[i]; + + mouse_buttons = qt_config + ->value(QStringLiteral("mouse_") + + QString::fromUtf8(Settings::NativeMouseButton::mapping[i]), + QString::fromStdString(default_param)) + .toString() + .toStdString(); + if (mouse_buttons.empty()) { + mouse_buttons = default_param; + } } } void Config::ReadTouchscreenValues() { - Settings::values.touchscreen.enabled = ReadSetting("touchscreen_enabled", true).toBool(); + Settings::values.touchscreen.enabled = + ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); Settings::values.touchscreen.device = - ReadSetting("touchscreen_device", "engine:emu_window").toString().toStdString(); + ReadSetting(QStringLiteral("touchscreen_device"), QStringLiteral("engine:emu_window")) + .toString() + .toStdString(); - Settings::values.touchscreen.finger = ReadSetting("touchscreen_finger", 0).toUInt(); - Settings::values.touchscreen.rotation_angle = ReadSetting("touchscreen_angle", 0).toUInt(); - Settings::values.touchscreen.diameter_x = ReadSetting("touchscreen_diameter_x", 15).toUInt(); - Settings::values.touchscreen.diameter_y = ReadSetting("touchscreen_diameter_y", 15).toUInt(); - qt_config->endGroup(); + Settings::values.touchscreen.finger = + ReadSetting(QStringLiteral("touchscreen_finger"), 0).toUInt(); + Settings::values.touchscreen.rotation_angle = + ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); + Settings::values.touchscreen.diameter_x = + ReadSetting(QStringLiteral("touchscreen_diameter_x"), 15).toUInt(); + Settings::values.touchscreen.diameter_y = + ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt(); } void Config::ApplyDefaultProfileIfInputInvalid() { @@ -345,8 +398,25 @@ void Config::ApplyDefaultProfileIfInputInvalid() { } } -void Config::ReadValues() { - qt_config->beginGroup("Controls"); +void Config::ReadAudioValues() { + qt_config->beginGroup(QStringLiteral("Audio")); + + Settings::values.sink_id = ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) + .toString() + .toStdString(); + Settings::values.enable_audio_stretching = + ReadSetting(QStringLiteral("enable_audio_stretching"), true).toBool(); + Settings::values.audio_device_id = + ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) + .toString() + .toStdString(); + Settings::values.volume = ReadSetting(QStringLiteral("volume"), 1).toFloat(); + + qt_config->endGroup(); +} + +void Config::ReadControlValues() { + qt_config->beginGroup(QStringLiteral("Controls")); ReadPlayerValues(); ReadDebugValues(); @@ -355,223 +425,308 @@ void Config::ReadValues() { ReadTouchscreenValues(); Settings::values.motion_device = - ReadSetting("motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01") + ReadSetting(QStringLiteral("motion_device"), + QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) .toString() .toStdString(); - qt_config->beginGroup("Core"); - Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool(); - Settings::values.use_multi_core = ReadSetting("use_multi_core", false).toBool(); qt_config->endGroup(); +} - qt_config->beginGroup("Renderer"); - Settings::values.resolution_factor = ReadSetting("resolution_factor", 1.0).toFloat(); - Settings::values.use_frame_limit = ReadSetting("use_frame_limit", true).toBool(); - Settings::values.frame_limit = ReadSetting("frame_limit", 100).toInt(); - Settings::values.use_disk_shader_cache = ReadSetting("use_disk_shader_cache", true).toBool(); - Settings::values.use_accurate_gpu_emulation = - ReadSetting("use_accurate_gpu_emulation", false).toBool(); - Settings::values.use_asynchronous_gpu_emulation = - ReadSetting("use_asynchronous_gpu_emulation", false).toBool(); +void Config::ReadCoreValues() { + qt_config->beginGroup(QStringLiteral("Core")); - Settings::values.bg_red = ReadSetting("bg_red", 0.0).toFloat(); - Settings::values.bg_green = ReadSetting("bg_green", 0.0).toFloat(); - Settings::values.bg_blue = ReadSetting("bg_blue", 0.0).toFloat(); - qt_config->endGroup(); + Settings::values.use_cpu_jit = ReadSetting(QStringLiteral("use_cpu_jit"), true).toBool(); + Settings::values.use_multi_core = ReadSetting(QStringLiteral("use_multi_core"), false).toBool(); - qt_config->beginGroup("Audio"); - Settings::values.sink_id = ReadSetting("output_engine", "auto").toString().toStdString(); - Settings::values.enable_audio_stretching = - ReadSetting("enable_audio_stretching", true).toBool(); - Settings::values.audio_device_id = - ReadSetting("output_device", "auto").toString().toStdString(); - Settings::values.volume = ReadSetting("volume", 1).toFloat(); qt_config->endGroup(); +} + +void Config::ReadDataStorageValues() { + qt_config->beginGroup(QStringLiteral("Data Storage")); - qt_config->beginGroup("Data Storage"); - Settings::values.use_virtual_sd = ReadSetting("use_virtual_sd", true).toBool(); + Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool(); FileUtil::GetUserPath( FileUtil::UserPath::NANDDir, qt_config - ->value("nand_directory", + ->value(QStringLiteral("nand_directory"), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))) .toString() .toStdString()); FileUtil::GetUserPath( FileUtil::UserPath::SDMCDir, qt_config - ->value("sdmc_directory", + ->value(QStringLiteral("sdmc_directory"), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))) .toString() .toStdString()); + qt_config->endGroup(); +} + +void Config::ReadDebuggingValues() { + qt_config->beginGroup(QStringLiteral("Debugging")); + + Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); + Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); + Settings::values.program_args = + ReadSetting(QStringLiteral("program_args"), QStringLiteral("")).toString().toStdString(); + Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); + Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); - qt_config->beginGroup("Core"); - Settings::values.use_cpu_jit = ReadSetting("use_cpu_jit", true).toBool(); - Settings::values.use_multi_core = ReadSetting("use_multi_core", false).toBool(); qt_config->endGroup(); +} - qt_config->beginGroup("System"); - Settings::values.use_docked_mode = ReadSetting("use_docked_mode", false).toBool(); - Settings::values.enable_nfc = ReadSetting("enable_nfc", true).toBool(); +void Config::ReadDisabledAddOnValues() { + const auto size = qt_config->beginReadArray(QStringLiteral("DisabledAddOns")); - Settings::values.current_user = - std::clamp<int>(ReadSetting("current_user", 0).toInt(), 0, Service::Account::MAX_USERS - 1); + for (int i = 0; i < size; ++i) { + qt_config->setArrayIndex(i); + const auto title_id = ReadSetting(QStringLiteral("title_id"), 0).toULongLong(); + std::vector<std::string> out; + const auto d_size = qt_config->beginReadArray(QStringLiteral("disabled")); + for (int j = 0; j < d_size; ++j) { + qt_config->setArrayIndex(j); + out.push_back( + ReadSetting(QStringLiteral("d"), QStringLiteral("")).toString().toStdString()); + } + qt_config->endArray(); + Settings::values.disabled_addons.insert_or_assign(title_id, out); + } + + qt_config->endArray(); +} - Settings::values.language_index = ReadSetting("language_index", 1).toInt(); +void Config::ReadMiscellaneousValues() { + qt_config->beginGroup(QStringLiteral("Miscellaneous")); - const auto rng_seed_enabled = ReadSetting("rng_seed_enabled", false).toBool(); + Settings::values.log_filter = + ReadSetting(QStringLiteral("log_filter"), QStringLiteral("*:Info")) + .toString() + .toStdString(); + Settings::values.use_dev_keys = ReadSetting(QStringLiteral("use_dev_keys"), false).toBool(); + + qt_config->endGroup(); +} + +void Config::ReadPathValues() { + qt_config->beginGroup(QStringLiteral("Paths")); + + UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString(); + UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString(); + UISettings::values.game_directory_path = + ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString(); + UISettings::values.game_directory_deepscan = + ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool(); + UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList(); + + qt_config->endGroup(); +} + +void Config::ReadRendererValues() { + qt_config->beginGroup(QStringLiteral("Renderer")); + + Settings::values.resolution_factor = + ReadSetting(QStringLiteral("resolution_factor"), 1.0).toFloat(); + Settings::values.use_frame_limit = + ReadSetting(QStringLiteral("use_frame_limit"), true).toBool(); + Settings::values.frame_limit = ReadSetting(QStringLiteral("frame_limit"), 100).toInt(); + Settings::values.use_disk_shader_cache = + ReadSetting(QStringLiteral("use_disk_shader_cache"), true).toBool(); + Settings::values.use_accurate_gpu_emulation = + ReadSetting(QStringLiteral("use_accurate_gpu_emulation"), false).toBool(); + Settings::values.use_asynchronous_gpu_emulation = + ReadSetting(QStringLiteral("use_asynchronous_gpu_emulation"), false).toBool(); + Settings::values.force_30fps_mode = + ReadSetting(QStringLiteral("force_30fps_mode"), false).toBool(); + + Settings::values.bg_red = ReadSetting(QStringLiteral("bg_red"), 0.0).toFloat(); + Settings::values.bg_green = ReadSetting(QStringLiteral("bg_green"), 0.0).toFloat(); + Settings::values.bg_blue = ReadSetting(QStringLiteral("bg_blue"), 0.0).toFloat(); + + qt_config->endGroup(); +} + +void Config::ReadShortcutValues() { + qt_config->beginGroup(QStringLiteral("Shortcuts")); + + for (const auto& [name, group, shortcut] : default_hotkeys) { + const auto& [keyseq, context] = shortcut; + qt_config->beginGroup(group); + qt_config->beginGroup(name); + UISettings::values.shortcuts.push_back( + {name, + group, + {ReadSetting(QStringLiteral("KeySeq"), keyseq).toString(), + ReadSetting(QStringLiteral("Context"), context).toInt()}}); + qt_config->endGroup(); + qt_config->endGroup(); + } + + qt_config->endGroup(); +} + +void Config::ReadSystemValues() { + qt_config->beginGroup(QStringLiteral("System")); + + Settings::values.use_docked_mode = + ReadSetting(QStringLiteral("use_docked_mode"), false).toBool(); + + Settings::values.current_user = std::clamp<int>( + ReadSetting(QStringLiteral("current_user"), 0).toInt(), 0, Service::Account::MAX_USERS - 1); + + Settings::values.language_index = ReadSetting(QStringLiteral("language_index"), 1).toInt(); + + const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool(); if (rng_seed_enabled) { - Settings::values.rng_seed = ReadSetting("rng_seed", 0).toULongLong(); + Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong(); } else { Settings::values.rng_seed = std::nullopt; } - const auto custom_rtc_enabled = ReadSetting("custom_rtc_enabled", false).toBool(); + const auto custom_rtc_enabled = + ReadSetting(QStringLiteral("custom_rtc_enabled"), false).toBool(); if (custom_rtc_enabled) { Settings::values.custom_rtc = - std::chrono::seconds(ReadSetting("custom_rtc", 0).toULongLong()); + std::chrono::seconds(ReadSetting(QStringLiteral("custom_rtc"), 0).toULongLong()); } else { Settings::values.custom_rtc = std::nullopt; } qt_config->endGroup(); +} - qt_config->beginGroup("Miscellaneous"); - Settings::values.log_filter = ReadSetting("log_filter", "*:Info").toString().toStdString(); - Settings::values.use_dev_keys = ReadSetting("use_dev_keys", false).toBool(); - qt_config->endGroup(); +void Config::ReadUIValues() { + qt_config->beginGroup(QStringLiteral("UI")); - qt_config->beginGroup("Debugging"); - Settings::values.use_gdbstub = ReadSetting("use_gdbstub", false).toBool(); - Settings::values.gdbstub_port = ReadSetting("gdbstub_port", 24689).toInt(); - Settings::values.program_args = ReadSetting("program_args", "").toString().toStdString(); - Settings::values.dump_exefs = ReadSetting("dump_exefs", false).toBool(); - Settings::values.dump_nso = ReadSetting("dump_nso", false).toBool(); - qt_config->endGroup(); + UISettings::values.theme = + ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) + .toString(); + UISettings::values.enable_discord_presence = + ReadSetting(QStringLiteral("enable_discord_presence"), true).toBool(); + UISettings::values.screenshot_resolution_factor = + static_cast<u16>(ReadSetting(QStringLiteral("screenshot_resolution_factor"), 0).toUInt()); + UISettings::values.select_user_on_boot = + ReadSetting(QStringLiteral("select_user_on_boot"), false).toBool(); + + ReadUIGamelistValues(); + ReadUILayoutValues(); + ReadPathValues(); + ReadShortcutValues(); + + UISettings::values.single_window_mode = + ReadSetting(QStringLiteral("singleWindowMode"), true).toBool(); + UISettings::values.fullscreen = ReadSetting(QStringLiteral("fullscreen"), false).toBool(); + UISettings::values.display_titlebar = + ReadSetting(QStringLiteral("displayTitleBars"), true).toBool(); + UISettings::values.show_filter_bar = + ReadSetting(QStringLiteral("showFilterBar"), true).toBool(); + UISettings::values.show_status_bar = + ReadSetting(QStringLiteral("showStatusBar"), true).toBool(); + UISettings::values.confirm_before_closing = + ReadSetting(QStringLiteral("confirmClose"), true).toBool(); + UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); + UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); + UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); + UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt(); + + ApplyDefaultProfileIfInputInvalid(); - qt_config->beginGroup("WebService"); - Settings::values.enable_telemetry = ReadSetting("enable_telemetry", true).toBool(); - Settings::values.web_api_url = - ReadSetting("web_api_url", "https://api.yuzu-emu.org").toString().toStdString(); - Settings::values.yuzu_username = ReadSetting("yuzu_username").toString().toStdString(); - Settings::values.yuzu_token = ReadSetting("yuzu_token").toString().toStdString(); qt_config->endGroup(); +} - const auto size = qt_config->beginReadArray("DisabledAddOns"); - for (int i = 0; i < size; ++i) { - qt_config->setArrayIndex(i); - const auto title_id = ReadSetting("title_id", 0).toULongLong(); - std::vector<std::string> out; - const auto d_size = qt_config->beginReadArray("disabled"); - for (int j = 0; j < d_size; ++j) { - qt_config->setArrayIndex(j); - out.push_back(ReadSetting("d", "").toString().toStdString()); - } - qt_config->endArray(); - Settings::values.disabled_addons.insert_or_assign(title_id, out); - } - qt_config->endArray(); +void Config::ReadUIGamelistValues() { + qt_config->beginGroup(QStringLiteral("UIGameList")); + + UISettings::values.show_unknown = ReadSetting(QStringLiteral("show_unknown"), true).toBool(); + UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool(); + UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt(); + UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt(); + UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt(); + UISettings::values.cache_game_list = + ReadSetting(QStringLiteral("cache_game_list"), true).toBool(); - qt_config->beginGroup("UI"); - UISettings::values.theme = ReadSetting("theme", UISettings::themes[0].second).toString(); - UISettings::values.enable_discord_presence = - ReadSetting("enable_discord_presence", true).toBool(); - UISettings::values.screenshot_resolution_factor = - static_cast<u16>(ReadSetting("screenshot_resolution_factor", 0).toUInt()); - UISettings::values.select_user_on_boot = ReadSetting("select_user_on_boot", false).toBool(); - - qt_config->beginGroup("UIGameList"); - UISettings::values.show_unknown = ReadSetting("show_unknown", true).toBool(); - UISettings::values.show_add_ons = ReadSetting("show_add_ons", true).toBool(); - UISettings::values.icon_size = ReadSetting("icon_size", 64).toUInt(); - UISettings::values.row_1_text_id = ReadSetting("row_1_text_id", 3).toUInt(); - UISettings::values.row_2_text_id = ReadSetting("row_2_text_id", 2).toUInt(); qt_config->endGroup(); +} + +void Config::ReadUILayoutValues() { + qt_config->beginGroup(QStringLiteral("UILayout")); - qt_config->beginGroup("UILayout"); - UISettings::values.geometry = ReadSetting("geometry").toByteArray(); - UISettings::values.state = ReadSetting("state").toByteArray(); - UISettings::values.renderwindow_geometry = ReadSetting("geometryRenderWindow").toByteArray(); - UISettings::values.gamelist_header_state = ReadSetting("gameListHeaderState").toByteArray(); + UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray(); + UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray(); + UISettings::values.renderwindow_geometry = + ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray(); + UISettings::values.gamelist_header_state = + ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); UISettings::values.microprofile_geometry = - ReadSetting("microProfileDialogGeometry").toByteArray(); + ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); UISettings::values.microprofile_visible = - ReadSetting("microProfileDialogVisible", false).toBool(); - qt_config->endGroup(); + ReadSetting(QStringLiteral("microProfileDialogVisible"), false).toBool(); - qt_config->beginGroup("Paths"); - UISettings::values.roms_path = ReadSetting("romsPath").toString(); - UISettings::values.symbols_path = ReadSetting("symbolsPath").toString(); - UISettings::values.gamedir = ReadSetting("gameListRootDir", ".").toString(); - UISettings::values.gamedir_deepscan = ReadSetting("gameListDeepScan", false).toBool(); - UISettings::values.recent_files = ReadSetting("recentFiles").toStringList(); qt_config->endGroup(); +} - qt_config->beginGroup("Shortcuts"); - QStringList groups = qt_config->childGroups(); - for (auto group : groups) { - qt_config->beginGroup(group); +void Config::ReadWebServiceValues() { + qt_config->beginGroup(QStringLiteral("WebService")); - QStringList hotkeys = qt_config->childGroups(); - for (auto hotkey : hotkeys) { - qt_config->beginGroup(hotkey); - UISettings::values.shortcuts.emplace_back(UISettings::Shortcut( - group + "/" + hotkey, - UISettings::ContextualShortcut(ReadSetting("KeySeq").toString(), - ReadSetting("Context").toInt()))); - qt_config->endGroup(); - } + Settings::values.enable_telemetry = + ReadSetting(QStringLiteral("enable_telemetry"), true).toBool(); + Settings::values.web_api_url = + ReadSetting(QStringLiteral("web_api_url"), QStringLiteral("https://api.yuzu-emu.org")) + .toString() + .toStdString(); + Settings::values.yuzu_username = + ReadSetting(QStringLiteral("yuzu_username")).toString().toStdString(); + Settings::values.yuzu_token = + ReadSetting(QStringLiteral("yuzu_token")).toString().toStdString(); - qt_config->endGroup(); - } qt_config->endGroup(); +} - UISettings::values.single_window_mode = ReadSetting("singleWindowMode", true).toBool(); - UISettings::values.fullscreen = ReadSetting("fullscreen", false).toBool(); - UISettings::values.display_titlebar = ReadSetting("displayTitleBars", true).toBool(); - UISettings::values.show_filter_bar = ReadSetting("showFilterBar", true).toBool(); - UISettings::values.show_status_bar = ReadSetting("showStatusBar", true).toBool(); - UISettings::values.confirm_before_closing = ReadSetting("confirmClose", true).toBool(); - UISettings::values.first_start = ReadSetting("firstStart", true).toBool(); - UISettings::values.callout_flags = ReadSetting("calloutFlags", 0).toUInt(); - UISettings::values.show_console = ReadSetting("showConsole", false).toBool(); - UISettings::values.profile_index = ReadSetting("profileIndex", 0).toUInt(); - - ApplyDefaultProfileIfInputInvalid(); - - qt_config->endGroup(); +void Config::ReadValues() { + ReadControlValues(); + ReadCoreValues(); + ReadRendererValues(); + ReadAudioValues(); + ReadDataStorageValues(); + ReadSystemValues(); + ReadMiscellaneousValues(); + ReadDebugValues(); + ReadWebServiceValues(); + ReadDisabledAddOnValues(); + ReadUIValues(); } void Config::SavePlayerValues() { for (std::size_t p = 0; p < Settings::values.players.size(); ++p) { const auto& player = Settings::values.players[p]; - WriteSetting(QString("player_%1_connected").arg(p), player.connected, false); - WriteSetting(QString("player_%1_type").arg(p), static_cast<u8>(player.type), + WriteSetting(QStringLiteral("player_%1_connected").arg(p), player.connected, false); + WriteSetting(QStringLiteral("player_%1_type").arg(p), static_cast<u8>(player.type), static_cast<u8>(Settings::ControllerType::DualJoycon)); - WriteSetting(QString("player_%1_body_color_left").arg(p), player.body_color_left, + WriteSetting(QStringLiteral("player_%1_body_color_left").arg(p), player.body_color_left, Settings::JOYCON_BODY_NEON_BLUE); - WriteSetting(QString("player_%1_body_color_right").arg(p), player.body_color_right, + WriteSetting(QStringLiteral("player_%1_body_color_right").arg(p), player.body_color_right, Settings::JOYCON_BODY_NEON_RED); - WriteSetting(QString("player_%1_button_color_left").arg(p), player.button_color_left, + WriteSetting(QStringLiteral("player_%1_button_color_left").arg(p), player.button_color_left, Settings::JOYCON_BUTTONS_NEON_BLUE); - WriteSetting(QString("player_%1_button_color_right").arg(p), player.button_color_right, - Settings::JOYCON_BUTTONS_NEON_RED); + WriteSetting(QStringLiteral("player_%1_button_color_right").arg(p), + player.button_color_right, Settings::JOYCON_BUTTONS_NEON_RED); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - WriteSetting(QString("player_%1_").arg(p) + + const std::string default_param = + InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteSetting(QStringLiteral("player_%1_").arg(p) + QString::fromStdString(Settings::NativeButton::mapping[i]), QString::fromStdString(player.buttons[i]), QString::fromStdString(default_param)); } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - WriteSetting(QString("player_%1_").arg(p) + + WriteSetting(QStringLiteral("player_%1_").arg(p) + QString::fromStdString(Settings::NativeAnalog::mapping[i]), QString::fromStdString(player.analogs[i]), QString::fromStdString(default_param)); @@ -580,19 +735,19 @@ void Config::SavePlayerValues() { } void Config::SaveDebugValues() { - WriteSetting("debug_pad_enabled", Settings::values.debug_pad_enabled, false); + WriteSetting(QStringLiteral("debug_pad_enabled"), Settings::values.debug_pad_enabled, false); for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); - WriteSetting(QString("debug_pad_") + + const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); + WriteSetting(QStringLiteral("debug_pad_") + QString::fromStdString(Settings::NativeButton::mapping[i]), QString::fromStdString(Settings::values.debug_pad_buttons[i]), QString::fromStdString(default_param)); } for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) { - std::string default_param = InputCommon::GenerateAnalogParamFromKeys( + const std::string default_param = InputCommon::GenerateAnalogParamFromKeys( default_analogs[i][0], default_analogs[i][1], default_analogs[i][2], default_analogs[i][3], default_analogs[i][4], 0.5f); - WriteSetting(QString("debug_pad_") + + WriteSetting(QStringLiteral("debug_pad_") + QString::fromStdString(Settings::NativeAnalog::mapping[i]), QString::fromStdString(Settings::values.debug_pad_analogs[i]), QString::fromStdString(default_param)); @@ -600,11 +755,12 @@ void Config::SaveDebugValues() { } void Config::SaveMouseValues() { - WriteSetting("mouse_enabled", Settings::values.mouse_enabled, false); + WriteSetting(QStringLiteral("mouse_enabled"), Settings::values.mouse_enabled, false); for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); - WriteSetting(QString("mouse_") + + const std::string default_param = + InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); + WriteSetting(QStringLiteral("mouse_") + QString::fromStdString(Settings::NativeMouseButton::mapping[i]), QString::fromStdString(Settings::values.mouse_buttons[i]), QString::fromStdString(default_param)); @@ -612,170 +768,276 @@ void Config::SaveMouseValues() { } void Config::SaveTouchscreenValues() { - WriteSetting("touchscreen_enabled", Settings::values.touchscreen.enabled, true); - WriteSetting("touchscreen_device", QString::fromStdString(Settings::values.touchscreen.device), - "engine:emu_window"); + const auto& touchscreen = Settings::values.touchscreen; - WriteSetting("touchscreen_finger", Settings::values.touchscreen.finger, 0); - WriteSetting("touchscreen_angle", Settings::values.touchscreen.rotation_angle, 0); - WriteSetting("touchscreen_diameter_x", Settings::values.touchscreen.diameter_x, 15); - WriteSetting("touchscreen_diameter_y", Settings::values.touchscreen.diameter_y, 15); + WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true); + WriteSetting(QStringLiteral("touchscreen_device"), QString::fromStdString(touchscreen.device), + QStringLiteral("engine:emu_window")); + + WriteSetting(QStringLiteral("touchscreen_finger"), touchscreen.finger, 0); + WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0); + WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15); + WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); } void Config::SaveValues() { - qt_config->beginGroup("Controls"); + SaveControlValues(); + SaveCoreValues(); + SaveRendererValues(); + SaveAudioValues(); + SaveDataStorageValues(); + SaveSystemValues(); + SaveMiscellaneousValues(); + SaveDebuggingValues(); + SaveWebServiceValues(); + SaveDisabledAddOnValues(); + SaveUIValues(); +} + +void Config::SaveAudioValues() { + qt_config->beginGroup(QStringLiteral("Audio")); + + WriteSetting(QStringLiteral("output_engine"), QString::fromStdString(Settings::values.sink_id), + QStringLiteral("auto")); + WriteSetting(QStringLiteral("enable_audio_stretching"), + Settings::values.enable_audio_stretching, true); + WriteSetting(QStringLiteral("output_device"), + QString::fromStdString(Settings::values.audio_device_id), QStringLiteral("auto")); + WriteSetting(QStringLiteral("volume"), Settings::values.volume, 1.0f); + + qt_config->endGroup(); +} + +void Config::SaveControlValues() { + qt_config->beginGroup(QStringLiteral("Controls")); SavePlayerValues(); SaveDebugValues(); SaveMouseValues(); SaveTouchscreenValues(); - WriteSetting("motion_device", QString::fromStdString(Settings::values.motion_device), - "engine:motion_emu,update_period:100,sensitivity:0.01"); - WriteSetting("keyboard_enabled", Settings::values.keyboard_enabled, false); + WriteSetting(QStringLiteral("motion_device"), + QString::fromStdString(Settings::values.motion_device), + QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); + WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); qt_config->endGroup(); +} - qt_config->beginGroup("Core"); - WriteSetting("use_cpu_jit", Settings::values.use_cpu_jit, true); - WriteSetting("use_multi_core", Settings::values.use_multi_core, false); - qt_config->endGroup(); +void Config::SaveCoreValues() { + qt_config->beginGroup(QStringLiteral("Core")); - qt_config->beginGroup("Renderer"); - WriteSetting("resolution_factor", (double)Settings::values.resolution_factor, 1.0); - WriteSetting("use_frame_limit", Settings::values.use_frame_limit, true); - WriteSetting("frame_limit", Settings::values.frame_limit, 100); - WriteSetting("use_disk_shader_cache", Settings::values.use_disk_shader_cache, true); - WriteSetting("use_accurate_gpu_emulation", Settings::values.use_accurate_gpu_emulation, false); - WriteSetting("use_asynchronous_gpu_emulation", Settings::values.use_asynchronous_gpu_emulation, - false); + WriteSetting(QStringLiteral("use_cpu_jit"), Settings::values.use_cpu_jit, true); + WriteSetting(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false); - // Cast to double because Qt's written float values are not human-readable - WriteSetting("bg_red", (double)Settings::values.bg_red, 0.0); - WriteSetting("bg_green", (double)Settings::values.bg_green, 0.0); - WriteSetting("bg_blue", (double)Settings::values.bg_blue, 0.0); qt_config->endGroup(); +} - qt_config->beginGroup("Audio"); - WriteSetting("output_engine", QString::fromStdString(Settings::values.sink_id), "auto"); - WriteSetting("enable_audio_stretching", Settings::values.enable_audio_stretching, true); - WriteSetting("output_device", QString::fromStdString(Settings::values.audio_device_id), "auto"); - WriteSetting("volume", Settings::values.volume, 1.0f); - qt_config->endGroup(); +void Config::SaveDataStorageValues() { + qt_config->beginGroup(QStringLiteral("Data Storage")); - qt_config->beginGroup("Data Storage"); - WriteSetting("use_virtual_sd", Settings::values.use_virtual_sd, true); - WriteSetting("nand_directory", + WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true); + WriteSetting(QStringLiteral("nand_directory"), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir))); - WriteSetting("sdmc_directory", + WriteSetting(QStringLiteral("sdmc_directory"), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)), QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir))); - qt_config->endGroup(); - - qt_config->beginGroup("System"); - WriteSetting("use_docked_mode", Settings::values.use_docked_mode, false); - WriteSetting("enable_nfc", Settings::values.enable_nfc, true); - WriteSetting("current_user", Settings::values.current_user, 0); - WriteSetting("language_index", Settings::values.language_index, 1); - - WriteSetting("rng_seed_enabled", Settings::values.rng_seed.has_value(), false); - WriteSetting("rng_seed", Settings::values.rng_seed.value_or(0), 0); - - WriteSetting("custom_rtc_enabled", Settings::values.custom_rtc.has_value(), false); - WriteSetting("custom_rtc", - QVariant::fromValue<long long>( - Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), - 0); qt_config->endGroup(); +} - qt_config->beginGroup("Miscellaneous"); - WriteSetting("log_filter", QString::fromStdString(Settings::values.log_filter), "*:Info"); - WriteSetting("use_dev_keys", Settings::values.use_dev_keys, false); - qt_config->endGroup(); +void Config::SaveDebuggingValues() { + qt_config->beginGroup(QStringLiteral("Debugging")); - qt_config->beginGroup("Debugging"); - WriteSetting("use_gdbstub", Settings::values.use_gdbstub, false); - WriteSetting("gdbstub_port", Settings::values.gdbstub_port, 24689); - WriteSetting("program_args", QString::fromStdString(Settings::values.program_args), ""); - WriteSetting("dump_exefs", Settings::values.dump_exefs, false); - WriteSetting("dump_nso", Settings::values.dump_nso, false); - qt_config->endGroup(); + WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); + WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); + WriteSetting(QStringLiteral("program_args"), + QString::fromStdString(Settings::values.program_args), QStringLiteral("")); + WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); + WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); - qt_config->beginGroup("WebService"); - WriteSetting("enable_telemetry", Settings::values.enable_telemetry, true); - WriteSetting("web_api_url", QString::fromStdString(Settings::values.web_api_url), - "https://api.yuzu-emu.org"); - WriteSetting("yuzu_username", QString::fromStdString(Settings::values.yuzu_username)); - WriteSetting("yuzu_token", QString::fromStdString(Settings::values.yuzu_token)); qt_config->endGroup(); +} + +void Config::SaveDisabledAddOnValues() { + qt_config->beginWriteArray(QStringLiteral("DisabledAddOns")); - qt_config->beginWriteArray("DisabledAddOns"); int i = 0; for (const auto& elem : Settings::values.disabled_addons) { qt_config->setArrayIndex(i); - WriteSetting("title_id", QVariant::fromValue<u64>(elem.first), 0); - qt_config->beginWriteArray("disabled"); + WriteSetting(QStringLiteral("title_id"), QVariant::fromValue<u64>(elem.first), 0); + qt_config->beginWriteArray(QStringLiteral("disabled")); for (std::size_t j = 0; j < elem.second.size(); ++j) { qt_config->setArrayIndex(static_cast<int>(j)); - WriteSetting("d", QString::fromStdString(elem.second[j]), ""); + WriteSetting(QStringLiteral("d"), QString::fromStdString(elem.second[j]), + QStringLiteral("")); } qt_config->endArray(); ++i; } + qt_config->endArray(); +} + +void Config::SaveMiscellaneousValues() { + qt_config->beginGroup(QStringLiteral("Miscellaneous")); + + WriteSetting(QStringLiteral("log_filter"), QString::fromStdString(Settings::values.log_filter), + QStringLiteral("*:Info")); + WriteSetting(QStringLiteral("use_dev_keys"), Settings::values.use_dev_keys, false); - qt_config->beginGroup("UI"); - WriteSetting("theme", UISettings::values.theme, UISettings::themes[0].second); - WriteSetting("enable_discord_presence", UISettings::values.enable_discord_presence, true); - WriteSetting("screenshot_resolution_factor", UISettings::values.screenshot_resolution_factor, - 0); - WriteSetting("select_user_on_boot", UISettings::values.select_user_on_boot, false); - - qt_config->beginGroup("UIGameList"); - WriteSetting("show_unknown", UISettings::values.show_unknown, true); - WriteSetting("show_add_ons", UISettings::values.show_add_ons, true); - WriteSetting("icon_size", UISettings::values.icon_size, 64); - WriteSetting("row_1_text_id", UISettings::values.row_1_text_id, 3); - WriteSetting("row_2_text_id", UISettings::values.row_2_text_id, 2); qt_config->endGroup(); +} + +void Config::SavePathValues() { + qt_config->beginGroup(QStringLiteral("Paths")); + + WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path); + WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path); + WriteSetting(QStringLiteral("screenshotPath"), UISettings::values.screenshot_path); + WriteSetting(QStringLiteral("gameListRootDir"), UISettings::values.game_directory_path, + QStringLiteral(".")); + WriteSetting(QStringLiteral("gameListDeepScan"), UISettings::values.game_directory_deepscan, + false); + WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files); - qt_config->beginGroup("UILayout"); - WriteSetting("geometry", UISettings::values.geometry); - WriteSetting("state", UISettings::values.state); - WriteSetting("geometryRenderWindow", UISettings::values.renderwindow_geometry); - WriteSetting("gameListHeaderState", UISettings::values.gamelist_header_state); - WriteSetting("microProfileDialogGeometry", UISettings::values.microprofile_geometry); - WriteSetting("microProfileDialogVisible", UISettings::values.microprofile_visible, false); qt_config->endGroup(); +} + +void Config::SaveRendererValues() { + qt_config->beginGroup(QStringLiteral("Renderer")); + + WriteSetting(QStringLiteral("resolution_factor"), + static_cast<double>(Settings::values.resolution_factor), 1.0); + WriteSetting(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); + WriteSetting(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); + WriteSetting(QStringLiteral("use_disk_shader_cache"), Settings::values.use_disk_shader_cache, + true); + WriteSetting(QStringLiteral("use_accurate_gpu_emulation"), + Settings::values.use_accurate_gpu_emulation, false); + WriteSetting(QStringLiteral("use_asynchronous_gpu_emulation"), + Settings::values.use_asynchronous_gpu_emulation, false); + WriteSetting(QStringLiteral("force_30fps_mode"), Settings::values.force_30fps_mode, false); + + // Cast to double because Qt's written float values are not human-readable + WriteSetting(QStringLiteral("bg_red"), static_cast<double>(Settings::values.bg_red), 0.0); + WriteSetting(QStringLiteral("bg_green"), static_cast<double>(Settings::values.bg_green), 0.0); + WriteSetting(QStringLiteral("bg_blue"), static_cast<double>(Settings::values.bg_blue), 0.0); - qt_config->beginGroup("Paths"); - WriteSetting("romsPath", UISettings::values.roms_path); - WriteSetting("symbolsPath", UISettings::values.symbols_path); - WriteSetting("screenshotPath", UISettings::values.screenshot_path); - WriteSetting("gameListRootDir", UISettings::values.gamedir, "."); - WriteSetting("gameListDeepScan", UISettings::values.gamedir_deepscan, false); - WriteSetting("recentFiles", UISettings::values.recent_files); qt_config->endGroup(); +} + +void Config::SaveShortcutValues() { + qt_config->beginGroup(QStringLiteral("Shortcuts")); - qt_config->beginGroup("Shortcuts"); - for (auto shortcut : UISettings::values.shortcuts) { - WriteSetting(shortcut.first + "/KeySeq", shortcut.second.first); - WriteSetting(shortcut.first + "/Context", shortcut.second.second); + // Lengths of UISettings::values.shortcuts & default_hotkeys are same. + // However, their ordering must also be the same. + for (std::size_t i = 0; i < default_hotkeys.size(); i++) { + const auto& [name, group, shortcut] = UISettings::values.shortcuts[i]; + const auto& default_hotkey = default_hotkeys[i].shortcut; + + qt_config->beginGroup(group); + qt_config->beginGroup(name); + WriteSetting(QStringLiteral("KeySeq"), shortcut.first, default_hotkey.first); + WriteSetting(QStringLiteral("Context"), shortcut.second, default_hotkey.second); + qt_config->endGroup(); + qt_config->endGroup(); } + qt_config->endGroup(); +} + +void Config::SaveSystemValues() { + qt_config->beginGroup(QStringLiteral("System")); + + WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); + WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0); + WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1); + + WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false); + WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0); + + WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), + false); + WriteSetting(QStringLiteral("custom_rtc"), + QVariant::fromValue<long long>( + Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()), + 0); + + qt_config->endGroup(); +} + +void Config::SaveUIValues() { + qt_config->beginGroup(QStringLiteral("UI")); + + WriteSetting(QStringLiteral("theme"), UISettings::values.theme, + QString::fromUtf8(UISettings::themes[0].second)); + WriteSetting(QStringLiteral("enable_discord_presence"), + UISettings::values.enable_discord_presence, true); + WriteSetting(QStringLiteral("screenshot_resolution_factor"), + UISettings::values.screenshot_resolution_factor, 0); + WriteSetting(QStringLiteral("select_user_on_boot"), UISettings::values.select_user_on_boot, + false); + + SaveUIGamelistValues(); + SaveUILayoutValues(); + SavePathValues(); + SaveShortcutValues(); + + WriteSetting(QStringLiteral("singleWindowMode"), UISettings::values.single_window_mode, true); + WriteSetting(QStringLiteral("fullscreen"), UISettings::values.fullscreen, false); + WriteSetting(QStringLiteral("displayTitleBars"), UISettings::values.display_titlebar, true); + WriteSetting(QStringLiteral("showFilterBar"), UISettings::values.show_filter_bar, true); + WriteSetting(QStringLiteral("showStatusBar"), UISettings::values.show_status_bar, true); + WriteSetting(QStringLiteral("confirmClose"), UISettings::values.confirm_before_closing, true); + WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); + WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); + WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); + WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0); + + qt_config->endGroup(); +} + +void Config::SaveUIGamelistValues() { + qt_config->beginGroup(QStringLiteral("UIGameList")); + + WriteSetting(QStringLiteral("show_unknown"), UISettings::values.show_unknown, true); + WriteSetting(QStringLiteral("show_add_ons"), UISettings::values.show_add_ons, true); + WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64); + WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3); + WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2); + WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true); + + qt_config->endGroup(); +} + +void Config::SaveUILayoutValues() { + qt_config->beginGroup(QStringLiteral("UILayout")); + + WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry); + WriteSetting(QStringLiteral("state"), UISettings::values.state); + WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry); + WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); + WriteSetting(QStringLiteral("microProfileDialogGeometry"), + UISettings::values.microprofile_geometry); + WriteSetting(QStringLiteral("microProfileDialogVisible"), + UISettings::values.microprofile_visible, false); + + qt_config->endGroup(); +} + +void Config::SaveWebServiceValues() { + qt_config->beginGroup(QStringLiteral("WebService")); + + WriteSetting(QStringLiteral("enable_telemetry"), Settings::values.enable_telemetry, true); + WriteSetting(QStringLiteral("web_api_url"), + QString::fromStdString(Settings::values.web_api_url), + QStringLiteral("https://api.yuzu-emu.org")); + WriteSetting(QStringLiteral("yuzu_username"), + QString::fromStdString(Settings::values.yuzu_username)); + WriteSetting(QStringLiteral("yuzu_token"), QString::fromStdString(Settings::values.yuzu_token)); - WriteSetting("singleWindowMode", UISettings::values.single_window_mode, true); - WriteSetting("fullscreen", UISettings::values.fullscreen, false); - WriteSetting("displayTitleBars", UISettings::values.display_titlebar, true); - WriteSetting("showFilterBar", UISettings::values.show_filter_bar, true); - WriteSetting("showStatusBar", UISettings::values.show_status_bar, true); - WriteSetting("confirmClose", UISettings::values.confirm_before_closing, true); - WriteSetting("firstStart", UISettings::values.first_start, true); - WriteSetting("calloutFlags", UISettings::values.callout_flags, 0); - WriteSetting("showConsole", UISettings::values.show_console, false); - WriteSetting("profileIndex", UISettings::values.profile_index, 0); qt_config->endGroup(); } @@ -785,7 +1047,7 @@ QVariant Config::ReadSetting(const QString& name) const { QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) const { QVariant result; - if (qt_config->value(name + "/default", false).toBool()) { + if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { result = default_value; } else { result = qt_config->value(name, default_value); @@ -799,7 +1061,7 @@ void Config::WriteSetting(const QString& name, const QVariant& value) { void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value) { - qt_config->setValue(name + "/default", value == default_value); + qt_config->setValue(name + QStringLiteral("/default"), value == default_value); qt_config->setValue(name, value); } diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index f4185db18..6b523ecdd 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -36,12 +36,46 @@ private: void ReadTouchscreenValues(); void ApplyDefaultProfileIfInputInvalid(); + // Read functions bases off the respective config section names. + void ReadAudioValues(); + void ReadControlValues(); + void ReadCoreValues(); + void ReadDataStorageValues(); + void ReadDebuggingValues(); + void ReadDisabledAddOnValues(); + void ReadMiscellaneousValues(); + void ReadPathValues(); + void ReadRendererValues(); + void ReadShortcutValues(); + void ReadSystemValues(); + void ReadUIValues(); + void ReadUIGamelistValues(); + void ReadUILayoutValues(); + void ReadWebServiceValues(); + void SaveValues(); void SavePlayerValues(); void SaveDebugValues(); void SaveMouseValues(); void SaveTouchscreenValues(); + // Save functions based off the respective config section names. + void SaveAudioValues(); + void SaveControlValues(); + void SaveCoreValues(); + void SaveDataStorageValues(); + void SaveDebuggingValues(); + void SaveDisabledAddOnValues(); + void SaveMiscellaneousValues(); + void SavePathValues(); + void SaveRendererValues(); + void SaveShortcutValues(); + void SaveSystemValues(); + void SaveUIValues(); + void SaveUIGamelistValues(); + void SaveUILayoutValues(); + void SaveWebServiceValues(); + QVariant ReadSetting(const QString& name) const; QVariant ReadSetting(const QString& name, const QVariant& default_value) const; void WriteSetting(const QString& name, const QVariant& value); diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index 3f03f0b77..267717bc9 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui @@ -7,9 +7,15 @@ <x>0</x> <y>0</y> <width>382</width> - <height>241</height> + <height>650</height> </rect> </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>650</height> + </size> + </property> <property name="windowTitle"> <string>yuzu Configuration</string> </property> @@ -62,6 +68,11 @@ <string>Input</string> </attribute> </widget> + <widget class="ConfigureHotkeys" name="hotkeysTab"> + <attribute name="title"> + <string>Hotkeys</string> + </attribute> + </widget> <widget class="ConfigureGraphics" name="graphicsTab"> <attribute name="title"> <string>Graphics</string> @@ -150,6 +161,12 @@ <header>configuration/configure_input_simple.h</header> <container>1</container> </customwidget> + <customwidget> + <class>ConfigureHotkeys</class> + <extends>QWidget</extends> + <header>configuration/configure_hotkeys.h</header> + <container>1</container> + </customwidget> </customwidgets> <resources/> <connections> diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index 5d9ccc6e8..f370c690f 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp @@ -4,6 +4,8 @@ #include <memory> +#include <QSignalBlocker> + #include "audio_core/sink.h" #include "audio_core/sink_details.h" #include "core/core.h" @@ -15,42 +17,39 @@ ConfigureAudio::ConfigureAudio(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::ConfigureAudio>()) { ui->setupUi(this); - ui->output_sink_combo_box->clear(); - ui->output_sink_combo_box->addItem("auto"); - for (const char* id : AudioCore::GetSinkIDs()) { - ui->output_sink_combo_box->addItem(id); - } + InitializeAudioOutputSinkComboBox(); connect(ui->volume_slider, &QSlider::valueChanged, this, - &ConfigureAudio::setVolumeIndicatorText); + &ConfigureAudio::SetVolumeIndicatorText); + connect(ui->output_sink_combo_box, qOverload<int>(&QComboBox::currentIndexChanged), this, + &ConfigureAudio::UpdateAudioDevices); - this->setConfiguration(); - connect(ui->output_sink_combo_box, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, - &ConfigureAudio::updateAudioDevices); + SetConfiguration(); - ui->output_sink_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); - ui->audio_device_combo_box->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + const bool is_powered_on = Core::System::GetInstance().IsPoweredOn(); + ui->output_sink_combo_box->setEnabled(!is_powered_on); + ui->audio_device_combo_box->setEnabled(!is_powered_on); } ConfigureAudio::~ConfigureAudio() = default; -void ConfigureAudio::setConfiguration() { - setOutputSinkFromSinkID(); +void ConfigureAudio::SetConfiguration() { + SetOutputSinkFromSinkID(); // The device list cannot be pre-populated (nor listed) until the output sink is known. - updateAudioDevices(ui->output_sink_combo_box->currentIndex()); + UpdateAudioDevices(ui->output_sink_combo_box->currentIndex()); - setAudioDeviceFromDeviceID(); + SetAudioDeviceFromDeviceID(); ui->toggle_audio_stretching->setChecked(Settings::values.enable_audio_stretching); ui->volume_slider->setValue(Settings::values.volume * ui->volume_slider->maximum()); - setVolumeIndicatorText(ui->volume_slider->sliderPosition()); + SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); } -void ConfigureAudio::setOutputSinkFromSinkID() { - int new_sink_index = 0; +void ConfigureAudio::SetOutputSinkFromSinkID() { + [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box); + int new_sink_index = 0; const QString sink_id = QString::fromStdString(Settings::values.sink_id); for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { if (ui->output_sink_combo_box->itemText(index) == sink_id) { @@ -62,7 +61,7 @@ void ConfigureAudio::setOutputSinkFromSinkID() { ui->output_sink_combo_box->setCurrentIndex(new_sink_index); } -void ConfigureAudio::setAudioDeviceFromDeviceID() { +void ConfigureAudio::SetAudioDeviceFromDeviceID() { int new_device_index = -1; const QString device_id = QString::fromStdString(Settings::values.audio_device_id); @@ -76,11 +75,11 @@ void ConfigureAudio::setAudioDeviceFromDeviceID() { ui->audio_device_combo_box->setCurrentIndex(new_device_index); } -void ConfigureAudio::setVolumeIndicatorText(int percentage) { +void ConfigureAudio::SetVolumeIndicatorText(int percentage) { ui->volume_indicator->setText(tr("%1%", "Volume percentage (e.g. 50%)").arg(percentage)); } -void ConfigureAudio::applyConfiguration() { +void ConfigureAudio::ApplyConfiguration() { Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) .toStdString(); @@ -92,9 +91,17 @@ void ConfigureAudio::applyConfiguration() { static_cast<float>(ui->volume_slider->sliderPosition()) / ui->volume_slider->maximum(); } -void ConfigureAudio::updateAudioDevices(int sink_index) { +void ConfigureAudio::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureAudio::UpdateAudioDevices(int sink_index) { ui->audio_device_combo_box->clear(); - ui->audio_device_combo_box->addItem(AudioCore::auto_device_name); + ui->audio_device_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name)); const std::string sink_id = ui->output_sink_combo_box->itemText(sink_index).toStdString(); for (const auto& device : AudioCore::GetDeviceListForSink(sink_id)) { @@ -102,6 +109,16 @@ void ConfigureAudio::updateAudioDevices(int sink_index) { } } -void ConfigureAudio::retranslateUi() { +void ConfigureAudio::InitializeAudioOutputSinkComboBox() { + ui->output_sink_combo_box->clear(); + ui->output_sink_combo_box->addItem(QString::fromUtf8(AudioCore::auto_device_name)); + + for (const char* id : AudioCore::GetSinkIDs()) { + ui->output_sink_combo_box->addItem(QString::fromUtf8(id)); + } +} + +void ConfigureAudio::RetranslateUI() { ui->retranslateUi(this); + SetVolumeIndicatorText(ui->volume_slider->sliderPosition()); } diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 8771421c0..ea83bd72d 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h @@ -18,16 +18,21 @@ public: explicit ConfigureAudio(QWidget* parent = nullptr); ~ConfigureAudio() override; - void applyConfiguration(); - void retranslateUi(); + void ApplyConfiguration(); private: - void updateAudioDevices(int sink_index); + void changeEvent(QEvent* event) override; - void setConfiguration(); - void setOutputSinkFromSinkID(); - void setAudioDeviceFromDeviceID(); - void setVolumeIndicatorText(int percentage); + void InitializeAudioOutputSinkComboBox(); + + void RetranslateUI(); + + void UpdateAudioDevices(int sink_index); + + void SetConfiguration(); + void SetOutputSinkFromSinkID(); + void SetAudioDeviceFromDeviceID(); + void SetVolumeIndicatorText(int percentage); std::unique_ptr<Ui::ConfigureAudio> ui; }; diff --git a/src/yuzu/configuration/configure_audio.ui b/src/yuzu/configuration/configure_audio.ui index a29a0e265..a098b9acc 100644 --- a/src/yuzu/configuration/configure_audio.ui +++ b/src/yuzu/configuration/configure_audio.ui @@ -20,7 +20,7 @@ <item> <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_1"> <property name="text"> <string>Output Engine:</string> </property> @@ -44,7 +44,7 @@ <item> <layout class="QHBoxLayout"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_2"> <property name="text"> <string>Audio Device:</string> </property> @@ -61,7 +61,7 @@ <number>0</number> </property> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_3"> <property name="text"> <string>Volume:</string> </property> diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 550cf9dca..efc2bedfd 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -16,7 +16,8 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) { ui->setupUi(this); - this->setConfiguration(); + SetConfiguration(); + connect(ui->open_log_button, &QPushButton::pressed, []() { QString path = QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::LogDir)); QDesktopServices::openUrl(QUrl::fromLocalFile(path)); @@ -25,7 +26,7 @@ ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::Co ConfigureDebug::~ConfigureDebug() = default; -void ConfigureDebug::setConfiguration() { +void ConfigureDebug::SetConfiguration() { ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub); ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub); ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); @@ -37,7 +38,7 @@ void ConfigureDebug::setConfiguration() { ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso); } -void ConfigureDebug::applyConfiguration() { +void ConfigureDebug::ApplyConfiguration() { Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked(); Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); UISettings::values.show_console = ui->toggle_console->isChecked(); @@ -50,3 +51,15 @@ void ConfigureDebug::applyConfiguration() { filter.ParseFilterString(Settings::values.log_filter); Log::SetGlobalFilter(filter); } + +void ConfigureDebug::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureDebug::RetranslateUI() { + ui->retranslateUi(this); +} diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h index c6420b18c..f4805a1d8 100644 --- a/src/yuzu/configuration/configure_debug.h +++ b/src/yuzu/configuration/configure_debug.h @@ -18,10 +18,13 @@ public: explicit ConfigureDebug(QWidget* parent = nullptr); ~ConfigureDebug() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void changeEvent(QEvent* event) override; + + void RetranslateUI(); + void SetConfiguration(); std::unique_ptr<Ui::ConfigureDebug> ui; }; diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 758a92335..5ca9ce0e6 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -45,7 +45,7 @@ </spacer> </item> <item> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_1"> <property name="text"> <string>Port:</string> </property> @@ -70,11 +70,11 @@ <property name="title"> <string>Logging</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_4"> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_2"> <property name="text"> <string>Global Log Filter</string> </property> @@ -86,7 +86,7 @@ </layout> </item> <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> <item> <widget class="QCheckBox" name="toggle_console"> <property name="text"> @@ -111,11 +111,11 @@ <property name="title"> <string>Homebrew</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QVBoxLayout" name="verticalLayout_5"> <item> - <layout class="QHBoxLayout" name="horizontalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout_4"> <item> - <widget class="QLabel" name="label"> + <widget class="QLabel" name="label_3"> <property name="text"> <string>Arguments String</string> </property> @@ -134,7 +134,7 @@ <property name="title"> <string>Dump</string> </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> + <layout class="QVBoxLayout" name="verticalLayout_6"> <item> <widget class="QCheckBox" name="dump_decompressed_nso"> <property name="whatsThis"> diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 777050405..e636964e3 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -4,51 +4,81 @@ #include <QHash> #include <QListWidgetItem> +#include <QSignalBlocker> #include "core/settings.h" #include "ui_configure.h" #include "yuzu/configuration/config.h" #include "yuzu/configuration/configure_dialog.h" +#include "yuzu/configuration/configure_input_player.h" #include "yuzu/hotkeys.h" -ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry) - : QDialog(parent), ui(new Ui::ConfigureDialog) { +ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) + : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { ui->setupUi(this); - ui->generalTab->PopulateHotkeyList(registry); - this->setConfiguration(); - this->PopulateSelectionList(); + ui->hotkeysTab->Populate(registry); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + SetConfiguration(); + PopulateSelectionList(); + connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, &ConfigureDialog::UpdateVisibleTabs); adjustSize(); - ui->selectorList->setCurrentRow(0); } ConfigureDialog::~ConfigureDialog() = default; -void ConfigureDialog::setConfiguration() {} - -void ConfigureDialog::applyConfiguration() { - ui->generalTab->applyConfiguration(); - ui->gameListTab->applyConfiguration(); - ui->systemTab->applyConfiguration(); - ui->profileManagerTab->applyConfiguration(); - ui->inputTab->applyConfiguration(); - ui->graphicsTab->applyConfiguration(); - ui->audioTab->applyConfiguration(); - ui->debugTab->applyConfiguration(); - ui->webTab->applyConfiguration(); +void ConfigureDialog::SetConfiguration() {} + +void ConfigureDialog::ApplyConfiguration() { + ui->generalTab->ApplyConfiguration(); + ui->gameListTab->ApplyConfiguration(); + ui->systemTab->ApplyConfiguration(); + ui->profileManagerTab->ApplyConfiguration(); + ui->inputTab->ApplyConfiguration(); + ui->hotkeysTab->ApplyConfiguration(registry); + ui->graphicsTab->ApplyConfiguration(); + ui->audioTab->ApplyConfiguration(); + ui->debugTab->ApplyConfiguration(); + ui->webTab->ApplyConfiguration(); Settings::Apply(); Settings::LogSettings(); } +void ConfigureDialog::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureDialog::RetranslateUI() { + const int old_row = ui->selectorList->currentRow(); + const int old_index = ui->tabWidget->currentIndex(); + + ui->retranslateUi(this); + + PopulateSelectionList(); + ui->selectorList->setCurrentRow(old_row); + + UpdateVisibleTabs(); + ui->tabWidget->setCurrentIndex(old_index); +} + void ConfigureDialog::PopulateSelectionList() { const std::array<std::pair<QString, QStringList>, 4> items{ {{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}}, {tr("System"), {tr("System"), tr("Profiles"), tr("Audio")}}, {tr("Graphics"), {tr("Graphics")}}, - {tr("Controls"), {tr("Input")}}}}; + {tr("Controls"), {tr("Input"), tr("Hotkeys")}}}, + }; + [[maybe_unused]] const QSignalBlocker blocker(ui->selectorList); + + ui->selectorList->clear(); for (const auto& entry : items) { auto* const item = new QListWidgetItem(entry.first); item->setData(Qt::UserRole, entry.second); @@ -59,23 +89,28 @@ void ConfigureDialog::PopulateSelectionList() { void ConfigureDialog::UpdateVisibleTabs() { const auto items = ui->selectorList->selectedItems(); - if (items.isEmpty()) + if (items.isEmpty()) { return; + } - const std::map<QString, QWidget*> widgets = {{tr("General"), ui->generalTab}, - {tr("System"), ui->systemTab}, - {tr("Profiles"), ui->profileManagerTab}, - {tr("Input"), ui->inputTab}, - {tr("Graphics"), ui->graphicsTab}, - {tr("Audio"), ui->audioTab}, - {tr("Debug"), ui->debugTab}, - {tr("Web"), ui->webTab}, - {tr("Game List"), ui->gameListTab}}; + const std::map<QString, QWidget*> widgets = { + {tr("General"), ui->generalTab}, + {tr("System"), ui->systemTab}, + {tr("Profiles"), ui->profileManagerTab}, + {tr("Input"), ui->inputTab}, + {tr("Hotkeys"), ui->hotkeysTab}, + {tr("Graphics"), ui->graphicsTab}, + {tr("Audio"), ui->audioTab}, + {tr("Debug"), ui->debugTab}, + {tr("Web"), ui->webTab}, + {tr("Game List"), ui->gameListTab}, + }; - ui->tabWidget->clear(); + [[maybe_unused]] const QSignalBlocker blocker(ui->tabWidget); + ui->tabWidget->clear(); const QStringList tabs = items[0]->data(Qt::UserRole).toStringList(); - - for (const auto& tab : tabs) + for (const auto& tab : tabs) { ui->tabWidget->addTab(widgets.find(tab)->second, tab); + } } diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 243d9fa09..2d3bfc2da 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -17,15 +17,20 @@ class ConfigureDialog : public QDialog { Q_OBJECT public: - explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); + explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry); ~ConfigureDialog() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void changeEvent(QEvent* event) override; + + void RetranslateUI(); + + void SetConfiguration(); void UpdateVisibleTabs(); void PopulateSelectionList(); std::unique_ptr<Ui::ConfigureDialog> ui; + HotkeyRegistry& registry; }; diff --git a/src/yuzu/configuration/configure_gamelist.cpp b/src/yuzu/configuration/configure_gamelist.cpp index ae8cac243..d1724ba89 100644 --- a/src/yuzu/configuration/configure_gamelist.cpp +++ b/src/yuzu/configuration/configure_gamelist.cpp @@ -12,20 +12,20 @@ #include "yuzu/ui_settings.h" namespace { -constexpr std::array<std::pair<u32, const char*>, 5> default_icon_sizes{{ +constexpr std::array default_icon_sizes{ std::make_pair(0, QT_TR_NOOP("None")), std::make_pair(32, QT_TR_NOOP("Small (32x32)")), std::make_pair(64, QT_TR_NOOP("Standard (64x64)")), std::make_pair(128, QT_TR_NOOP("Large (128x128)")), std::make_pair(256, QT_TR_NOOP("Full Size (256x256)")), -}}; +}; -constexpr std::array<const char*, 4> row_text_names{{ +constexpr std::array row_text_names{ QT_TR_NOOP("Filename"), QT_TR_NOOP("Filetype"), QT_TR_NOOP("Title ID"), QT_TR_NOOP("Title Name"), -}}; +}; } // Anonymous namespace ConfigureGameList::ConfigureGameList(QWidget* parent) @@ -35,7 +35,7 @@ ConfigureGameList::ConfigureGameList(QWidget* parent) InitializeIconSizeComboBox(); InitializeRowComboBoxes(); - this->setConfiguration(); + SetConfiguration(); // Force game list reload if any of the relevant settings are changed. connect(ui->show_unknown, &QCheckBox::stateChanged, this, @@ -50,7 +50,7 @@ ConfigureGameList::ConfigureGameList(QWidget* parent) ConfigureGameList::~ConfigureGameList() = default; -void ConfigureGameList::applyConfiguration() { +void ConfigureGameList::ApplyConfiguration() { UISettings::values.show_unknown = ui->show_unknown->isChecked(); UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); @@ -63,7 +63,7 @@ void ConfigureGameList::RequestGameListUpdate() { UISettings::values.is_game_list_reload_pending.exchange(true); } -void ConfigureGameList::setConfiguration() { +void ConfigureGameList::SetConfiguration() { ui->show_unknown->setChecked(UISettings::values.show_unknown); ui->show_add_ons->setChecked(UISettings::values.show_add_ons); ui->icon_size_combobox->setCurrentIndex( @@ -77,7 +77,6 @@ void ConfigureGameList::setConfiguration() { void ConfigureGameList::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { RetranslateUI(); - return; } QWidget::changeEvent(event); @@ -100,13 +99,15 @@ void ConfigureGameList::RetranslateUI() { void ConfigureGameList::InitializeIconSizeComboBox() { for (const auto& size : default_icon_sizes) { - ui->icon_size_combobox->addItem(size.second, size.first); + ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); } } void ConfigureGameList::InitializeRowComboBoxes() { for (std::size_t i = 0; i < row_text_names.size(); ++i) { - ui->row_1_text_combobox->addItem(row_text_names[i], QVariant::fromValue(i)); - ui->row_2_text_combobox->addItem(row_text_names[i], QVariant::fromValue(i)); + const QString row_text_name = QString::fromUtf8(row_text_names[i]); + + ui->row_1_text_combobox->addItem(row_text_name, QVariant::fromValue(i)); + ui->row_2_text_combobox->addItem(row_text_name, QVariant::fromValue(i)); } } diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h index bf3f1cdfa..e11822919 100644 --- a/src/yuzu/configuration/configure_gamelist.h +++ b/src/yuzu/configuration/configure_gamelist.h @@ -18,12 +18,12 @@ public: explicit ConfigureGameList(QWidget* parent = nullptr); ~ConfigureGameList() override; - void applyConfiguration(); + void ApplyConfiguration(); private: void RequestGameListUpdate(); - void setConfiguration(); + void SetConfiguration(); void changeEvent(QEvent*) override; void RetranslateUI(); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 4116b6cd7..06d368dfc 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -14,10 +14,11 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) ui->setupUi(this); for (const auto& theme : UISettings::themes) { - ui->theme_combobox->addItem(theme.first, theme.second); + ui->theme_combobox->addItem(QString::fromUtf8(theme.first), + QString::fromUtf8(theme.second)); } - this->setConfiguration(); + SetConfiguration(); connect(ui->toggle_deepscan, &QCheckBox::stateChanged, this, [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); @@ -27,26 +28,32 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) ConfigureGeneral::~ConfigureGeneral() = default; -void ConfigureGeneral::setConfiguration() { - ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan); +void ConfigureGeneral::SetConfiguration() { + ui->toggle_deepscan->setChecked(UISettings::values.game_directory_deepscan); ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit); - ui->enable_nfc->setChecked(Settings::values.enable_nfc); } -void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) { - ui->widget->Populate(registry); -} - -void ConfigureGeneral::applyConfiguration() { - UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); +void ConfigureGeneral::ApplyConfiguration() { + UISettings::values.game_directory_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); UISettings::values.theme = ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked(); - Settings::values.enable_nfc = ui->enable_nfc->isChecked(); +} + +void ConfigureGeneral::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureGeneral::RetranslateUI() { + ui->retranslateUi(this); } diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 59738af40..ef05ce065 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -20,11 +20,13 @@ public: explicit ConfigureGeneral(QWidget* parent = nullptr); ~ConfigureGeneral() override; - void PopulateHotkeyList(const HotkeyRegistry& registry); - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void SetConfiguration(); std::unique_ptr<Ui::ConfigureGeneral> ui; }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index dff0ad5d0..1a5721fe7 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -71,26 +71,6 @@ </widget> </item> <item> - <widget class="QGroupBox" name="EmulationGroupBox"> - <property name="title"> - <string>Emulation</string> - </property> - <layout class="QHBoxLayout" name="EmulationHorizontalLayout"> - <item> - <layout class="QVBoxLayout" name="EmulationVerticalLayout"> - <item> - <widget class="QCheckBox" name="enable_nfc"> - <property name="text"> - <string>Enable NFC</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> <widget class="QGroupBox" name="theme_group_box"> <property name="title"> <string>Theme</string> @@ -118,22 +98,6 @@ </widget> </item> <item> - <widget class="QGroupBox" name="HotKeysGroupBox"> - <property name="title"> - <string>Hotkeys</string> - </property> - <layout class="QHBoxLayout" name="HotKeysHorizontalLayout"> - <item> - <layout class="QVBoxLayout" name="HotKeysVerticalLayout"> - <item> - <widget class="GHotkeysDialog" name="widget" native="true"/> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> @@ -150,14 +114,6 @@ </item> </layout> </widget> - <customwidgets> - <customwidget> - <class>GHotkeysDialog</class> - <extends>QWidget</extends> - <header>hotkeys.h</header> - <container>1</container> - </customwidget> - </customwidgets> <resources/> <connections/> </ui> diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index dd1d67488..2b17b250c 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -51,37 +51,42 @@ Resolution FromResolutionFactor(float factor) { ConfigureGraphics::ConfigureGraphics(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureGraphics) { - ui->setupUi(this); - this->setConfiguration(); - ui->frame_limit->setEnabled(Settings::values.use_frame_limit); - connect(ui->toggle_frame_limit, &QCheckBox::stateChanged, ui->frame_limit, - &QSpinBox::setEnabled); + SetConfiguration(); + + connect(ui->toggle_frame_limit, &QCheckBox::toggled, ui->frame_limit, &QSpinBox::setEnabled); connect(ui->bg_button, &QPushButton::clicked, this, [this] { const QColor new_bg_color = QColorDialog::getColor(bg_color); - if (!new_bg_color.isValid()) + if (!new_bg_color.isValid()) { return; + } UpdateBackgroundColorButton(new_bg_color); }); } ConfigureGraphics::~ConfigureGraphics() = default; -void ConfigureGraphics::setConfiguration() { +void ConfigureGraphics::SetConfiguration() { + const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); + ui->resolution_factor_combobox->setCurrentIndex( static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor))); ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit); + ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); ui->frame_limit->setValue(Settings::values.frame_limit); + ui->use_disk_shader_cache->setEnabled(runtime_lock); ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache); ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation); - ui->use_asynchronous_gpu_emulation->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + ui->use_asynchronous_gpu_emulation->setEnabled(runtime_lock); ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation); + ui->force_30fps_mode->setEnabled(runtime_lock); + ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode); UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue)); } -void ConfigureGraphics::applyConfiguration() { +void ConfigureGraphics::ApplyConfiguration() { Settings::values.resolution_factor = ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex())); Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked(); @@ -90,11 +95,24 @@ void ConfigureGraphics::applyConfiguration() { Settings::values.use_accurate_gpu_emulation = ui->use_accurate_gpu_emulation->isChecked(); Settings::values.use_asynchronous_gpu_emulation = ui->use_asynchronous_gpu_emulation->isChecked(); + Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked(); Settings::values.bg_red = static_cast<float>(bg_color.redF()); Settings::values.bg_green = static_cast<float>(bg_color.greenF()); Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); } +void ConfigureGraphics::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureGraphics::RetranslateUI() { + ui->retranslateUi(this); +} + void ConfigureGraphics::UpdateBackgroundColorButton(QColor color) { bg_color = color; diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index f2799822d..fae28d98e 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -18,10 +18,13 @@ public: explicit ConfigureGraphics(QWidget* parent = nullptr); ~ConfigureGraphics() override; - void applyConfiguration(); + void ApplyConfiguration(); private: - void setConfiguration(); + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void SetConfiguration(); void UpdateBackgroundColorButton(QColor color); diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index c6767e0ca..15ab18ecd 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -71,6 +71,13 @@ </widget> </item> <item> + <widget class="QCheckBox" name="force_30fps_mode"> + <property name="text"> + <string>Force 30 FPS mode</string> + </property> + </widget> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label"> diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp new file mode 100644 index 000000000..3ea0b8d67 --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -0,0 +1,129 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QMessageBox> +#include <QStandardItemModel> +#include "core/settings.h" +#include "ui_configure_hotkeys.h" +#include "yuzu/configuration/configure_hotkeys.h" +#include "yuzu/hotkeys.h" +#include "yuzu/util/sequence_dialog/sequence_dialog.h" + +ConfigureHotkeys::ConfigureHotkeys(QWidget* parent) + : QWidget(parent), ui(std::make_unique<Ui::ConfigureHotkeys>()) { + ui->setupUi(this); + setFocusPolicy(Qt::ClickFocus); + + model = new QStandardItemModel(this); + model->setColumnCount(3); + + connect(ui->hotkey_list, &QTreeView::doubleClicked, this, &ConfigureHotkeys::Configure); + ui->hotkey_list->setModel(model); + + // TODO(Kloen): Make context configurable as well (hiding the column for now) + ui->hotkey_list->hideColumn(2); + + ui->hotkey_list->setColumnWidth(0, 200); + ui->hotkey_list->resizeColumnToContents(1); + + RetranslateUI(); +} + +ConfigureHotkeys::~ConfigureHotkeys() = default; + +void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { + for (const auto& group : registry.hotkey_groups) { + auto* parent_item = new QStandardItem(group.first); + parent_item->setEditable(false); + for (const auto& hotkey : group.second) { + auto* action = new QStandardItem(hotkey.first); + auto* keyseq = + new QStandardItem(hotkey.second.keyseq.toString(QKeySequence::NativeText)); + action->setEditable(false); + keyseq->setEditable(false); + parent_item->appendRow({action, keyseq}); + } + model->appendRow(parent_item); + } + + ui->hotkey_list->expandAll(); +} + +void ConfigureHotkeys::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureHotkeys::RetranslateUI() { + ui->retranslateUi(this); + + model->setHorizontalHeaderLabels({tr("Action"), tr("Hotkey"), tr("Context")}); +} + +void ConfigureHotkeys::Configure(QModelIndex index) { + if (!index.parent().isValid()) { + return; + } + + index = index.sibling(index.row(), 1); + auto* const model = ui->hotkey_list->model(); + const auto previous_key = model->data(index); + + SequenceDialog hotkey_dialog{this}; + + const int return_code = hotkey_dialog.exec(); + const auto key_sequence = hotkey_dialog.GetSequence(); + if (return_code == QDialog::Rejected || key_sequence.isEmpty()) { + return; + } + + if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { + QMessageBox::warning(this, tr("Conflicting Key Sequence"), + tr("The entered key sequence is already assigned to another hotkey.")); + } else { + model->setData(index, key_sequence.toString(QKeySequence::NativeText)); + } +} + +bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { + for (int r = 0; r < model->rowCount(); r++) { + const QStandardItem* const parent = model->item(r, 0); + + for (int r2 = 0; r2 < parent->rowCount(); r2++) { + const QStandardItem* const key_seq_item = parent->child(r2, 1); + const auto key_seq_str = key_seq_item->text(); + const auto key_seq = QKeySequence::fromString(key_seq_str, QKeySequence::NativeText); + + if (key_sequence == key_seq) { + return true; + } + } + } + + return false; +} + +void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) { + for (int key_id = 0; key_id < model->rowCount(); key_id++) { + const QStandardItem* parent = model->item(key_id, 0); + for (int key_column_id = 0; key_column_id < parent->rowCount(); key_column_id++) { + const QStandardItem* action = parent->child(key_column_id, 0); + const QStandardItem* keyseq = parent->child(key_column_id, 1); + for (auto& [group, sub_actions] : registry.hotkey_groups) { + if (group != parent->text()) + continue; + for (auto& [action_name, hotkey] : sub_actions) { + if (action_name != action->text()) + continue; + hotkey.keyseq = QKeySequence(keyseq->text()); + } + } + } + } + + registry.SaveHotkeys(); +} diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h new file mode 100644 index 000000000..8f8c6173b --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.h @@ -0,0 +1,43 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <QWidget> + +namespace Ui { +class ConfigureHotkeys; +} + +class HotkeyRegistry; +class QStandardItemModel; + +class ConfigureHotkeys : public QWidget { + Q_OBJECT + +public: + explicit ConfigureHotkeys(QWidget* parent = nullptr); + ~ConfigureHotkeys() override; + + void ApplyConfiguration(HotkeyRegistry& registry); + + /** + * Populates the hotkey list widget using data from the provided registry. + * Called everytime the Configure dialog is opened. + * @param registry The HotkeyRegistry whose data is used to populate the list. + */ + void Populate(const HotkeyRegistry& registry); + +private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void Configure(QModelIndex index); + bool IsUsedKey(QKeySequence key_sequence) const; + + std::unique_ptr<Ui::ConfigureHotkeys> ui; + + QStandardItemModel* model; +}; diff --git a/src/yuzu/configuration/configure_hotkeys.ui b/src/yuzu/configuration/configure_hotkeys.ui new file mode 100644 index 000000000..0d0b70f38 --- /dev/null +++ b/src/yuzu/configuration/configure_hotkeys.ui @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ConfigureHotkeys</class> + <widget class="QWidget" name="ConfigureHotkeys"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>363</width> + <height>388</height> + </rect> + </property> + <property name="windowTitle"> + <string>Hotkey Settings</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Double-click on a binding to change it.</string> + </property> + </widget> + </item> + <item> + <widget class="QTreeView" name="hotkey_list"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="sortingEnabled"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>
\ No newline at end of file diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index f39d57998..4dd775aab 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -5,6 +5,7 @@ #include <algorithm> #include <memory> +#include <QSignalBlocker> #include <QTimer> #include "configuration/configure_touchscreen_advanced.h" @@ -50,12 +51,12 @@ void OnDockedModeChanged(bool last_state, bool new_state) { namespace { template <typename Dialog, typename... Args> void CallConfigureDialog(ConfigureInput& parent, Args&&... args) { - parent.applyConfiguration(); + parent.ApplyConfiguration(); Dialog dialog(&parent, std::forward<Args>(args)...); const auto res = dialog.exec(); if (res == QDialog::Accepted) { - dialog.applyConfiguration(); + dialog.ApplyConfiguration(); } } } // Anonymous namespace @@ -74,28 +75,25 @@ ConfigureInput::ConfigureInput(QWidget* parent) ui->player5_configure, ui->player6_configure, ui->player7_configure, ui->player8_configure, }; - for (auto* controller_box : players_controller) { - controller_box->addItems({"None", "Pro Controller", "Dual Joycons", "Single Right Joycon", - "Single Left Joycon"}); - } - - this->loadConfiguration(); - updateUIEnabled(); + RetranslateUI(); + LoadConfiguration(); + UpdateUIEnabled(); connect(ui->restore_defaults_button, &QPushButton::pressed, this, - &ConfigureInput::restoreDefaults); + &ConfigureInput::RestoreDefaults); - for (auto* enabled : players_controller) + for (auto* enabled : players_controller) { connect(enabled, QOverload<int>::of(&QComboBox::currentIndexChanged), this, - &ConfigureInput::updateUIEnabled); - connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); + } + connect(ui->use_docked_mode, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); connect(ui->handheld_connected, &QCheckBox::stateChanged, this, - &ConfigureInput::updateUIEnabled); - connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); - connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); - connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); + connect(ui->mouse_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); + connect(ui->keyboard_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); + connect(ui->debug_enabled, &QCheckBox::stateChanged, this, &ConfigureInput::UpdateUIEnabled); connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this, - &ConfigureInput::updateUIEnabled); + &ConfigureInput::UpdateUIEnabled); for (std::size_t i = 0; i < players_configure.size(); ++i) { connect(players_configure[i], &QPushButton::pressed, this, @@ -117,7 +115,7 @@ ConfigureInput::ConfigureInput(QWidget* parent) ConfigureInput::~ConfigureInput() = default; -void ConfigureInput::applyConfiguration() { +void ConfigureInput::ApplyConfiguration() { for (std::size_t i = 0; i < players_controller.size(); ++i) { const auto controller_type_index = players_controller[i]->currentIndex(); @@ -143,14 +141,41 @@ void ConfigureInput::applyConfiguration() { Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); } -void ConfigureInput::updateUIEnabled() { +void ConfigureInput::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureInput::RetranslateUI() { + ui->retranslateUi(this); + RetranslateControllerComboBoxes(); +} + +void ConfigureInput::RetranslateControllerComboBoxes() { + for (auto* controller_box : players_controller) { + [[maybe_unused]] const QSignalBlocker blocker(controller_box); + + controller_box->clear(); + controller_box->addItems({tr("None"), tr("Pro Controller"), tr("Dual Joycons"), + tr("Single Right Joycon"), tr("Single Left Joycon")}); + } + + LoadPlayerControllerIndices(); +} + +void ConfigureInput::UpdateUIEnabled() { bool hit_disabled = false; for (auto* player : players_controller) { player->setDisabled(hit_disabled); - if (hit_disabled) + if (hit_disabled) { player->setCurrentIndex(0); - if (!hit_disabled && player->currentIndex() == 0) + } + if (!hit_disabled && player->currentIndex() == 0) { hit_disabled = true; + } } for (std::size_t i = 0; i < players_controller.size(); ++i) { @@ -165,18 +190,14 @@ void ConfigureInput::updateUIEnabled() { ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); } -void ConfigureInput::loadConfiguration() { +void ConfigureInput::LoadConfiguration() { std::stable_partition( Settings::values.players.begin(), Settings::values.players.begin() + Service::HID::Controller_NPad::NPadIdToIndex(Service::HID::NPAD_HANDHELD), [](const auto& player) { return player.connected; }); - for (std::size_t i = 0; i < players_controller.size(); ++i) { - const auto connected = Settings::values.players[i].connected; - players_controller[i]->setCurrentIndex( - connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0); - } + LoadPlayerControllerIndices(); ui->use_docked_mode->setChecked(Settings::values.use_docked_mode); ui->handheld_connected->setChecked( @@ -188,10 +209,18 @@ void ConfigureInput::loadConfiguration() { ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); - updateUIEnabled(); + UpdateUIEnabled(); +} + +void ConfigureInput::LoadPlayerControllerIndices() { + for (std::size_t i = 0; i < players_controller.size(); ++i) { + const auto connected = Settings::values.players[i].connected; + players_controller[i]->setCurrentIndex( + connected ? static_cast<u8>(Settings::values.players[i].type) + 1 : 0); + } } -void ConfigureInput::restoreDefaults() { +void ConfigureInput::RestoreDefaults() { players_controller[0]->setCurrentIndex(2); for (std::size_t i = 1; i < players_controller.size(); ++i) { @@ -204,5 +233,5 @@ void ConfigureInput::restoreDefaults() { ui->keyboard_enabled->setCheckState(Qt::Unchecked); ui->debug_enabled->setCheckState(Qt::Unchecked); ui->touchscreen_enabled->setCheckState(Qt::Checked); - updateUIEnabled(); + UpdateUIEnabled(); } diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index b8e62cc2b..2f70cb3ca 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h @@ -30,15 +30,21 @@ public: ~ConfigureInput() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: - void updateUIEnabled(); + void changeEvent(QEvent* event) override; + void RetranslateUI(); + void RetranslateControllerComboBoxes(); + + void UpdateUIEnabled(); /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); + void LoadPlayerControllerIndices(); + /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); std::unique_ptr<Ui::ConfigureInput> ui; diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index f924e3494..efffd8487 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -17,7 +17,7 @@ <item> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_1"> <property name="title"> <string>Players</string> </property> @@ -260,7 +260,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_2"> <property name="title"> <string>Handheld</string> </property> @@ -332,7 +332,7 @@ </widget> </item> <item> - <widget class="QGroupBox" name="gridGroupBox"> + <widget class="QGroupBox" name="gridGroupBox_3"> <property name="title"> <string>Other</string> </property> diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index c5a245ebe..916baccc1 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -45,7 +45,7 @@ static QString GetKeyName(int key_code) { case Qt::Key_Alt: return QObject::tr("Alt"); case Qt::Key_Meta: - return ""; + return {}; default: return QKeySequence(key_code).toString(); } @@ -65,46 +65,70 @@ static void SetAnalogButton(const Common::ParamPackage& input_param, static QString ButtonToText(const Common::ParamPackage& param) { if (!param.Has("engine")) { return QObject::tr("[not set]"); - } else if (param.Get("engine", "") == "keyboard") { + } + + if (param.Get("engine", "") == "keyboard") { return GetKeyName(param.Get("code", 0)); - } else if (param.Get("engine", "") == "sdl") { + } + + if (param.Get("engine", "") == "sdl") { if (param.Has("hat")) { - return QString(QObject::tr("Hat %1 %2")) - .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); + const QString hat_str = QString::fromStdString(param.Get("hat", "")); + const QString direction_str = QString::fromStdString(param.Get("direction", "")); + + return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); } + if (param.Has("axis")) { - return QString(QObject::tr("Axis %1%2")) - .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); + const QString axis_str = QString::fromStdString(param.Get("axis", "")); + const QString direction_str = QString::fromStdString(param.Get("direction", "")); + + return QObject::tr("Axis %1%2").arg(axis_str, direction_str); } + if (param.Has("button")) { - return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str()); + const QString button_str = QString::fromStdString(param.Get("button", "")); + + return QObject::tr("Button %1").arg(button_str); } - return QString(); - } else { - return QObject::tr("[unknown]"); + + return {}; } -}; + + return QObject::tr("[unknown]"); +} static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) { if (!param.Has("engine")) { return QObject::tr("[not set]"); - } else if (param.Get("engine", "") == "analog_from_button") { + } + + if (param.Get("engine", "") == "analog_from_button") { return ButtonToText(Common::ParamPackage{param.Get(dir, "")}); - } else if (param.Get("engine", "") == "sdl") { + } + + if (param.Get("engine", "") == "sdl") { if (dir == "modifier") { - return QString(QObject::tr("[unused]")); + return QObject::tr("[unused]"); } if (dir == "left" || dir == "right") { - return QString(QObject::tr("Axis %1")).arg(param.Get("axis_x", "").c_str()); - } else if (dir == "up" || dir == "down") { - return QString(QObject::tr("Axis %1")).arg(param.Get("axis_y", "").c_str()); + const QString axis_x_str = QString::fromStdString(param.Get("axis_x", "")); + + return QObject::tr("Axis %1").arg(axis_x_str); } - return QString(); - } else { - return QObject::tr("[unknown]"); + + if (dir == "up" || dir == "down") { + const QString axis_y_str = QString::fromStdString(param.Get("axis_y", "")); + + return QObject::tr("Axis %1").arg(axis_y_str); + } + + return {}; } -}; + + return QObject::tr("[unknown]"); +} ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_index, bool debug) : QDialog(parent), ui(std::make_unique<Ui::ConfigureInputPlayer>()), player_index(player_index), @@ -214,47 +238,51 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i analog_map_stick = {ui->buttonLStickAnalog, ui->buttonRStickAnalog}; for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { - if (!button_map[button_id]) + auto* const button = button_map[button_id]; + if (button == nullptr) { continue; - button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); - connect(button_map[button_id], &QPushButton::released, [=]() { - handleClick( + } + + button->setContextMenuPolicy(Qt::CustomContextMenu); + connect(button, &QPushButton::released, [=] { + HandleClick( button_map[button_id], [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, InputCommon::Polling::DeviceType::Button); }); - connect(button_map[button_id], &QPushButton::customContextMenuRequested, - [=](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); - button_map[button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - buttons_param[button_id] = Common::ParamPackage{ - InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); - }); - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - }); + connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { + QMenu context_menu; + context_menu.addAction(tr("Clear"), [&] { + buttons_param[button_id].Clear(); + button_map[button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Restore Default"), [&] { + buttons_param[button_id] = Common::ParamPackage{ + InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); + context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); + }); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (!analog_map_buttons[analog_id][sub_button_id]) + auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; + if (analog_button == nullptr) { continue; - analog_map_buttons[analog_id][sub_button_id]->setContextMenuPolicy( - Qt::CustomContextMenu); - connect(analog_map_buttons[analog_id][sub_button_id], &QPushButton::released, [=]() { - handleClick(analog_map_buttons[analog_id][sub_button_id], + } + + analog_button->setContextMenuPolicy(Qt::CustomContextMenu); + connect(analog_button, &QPushButton::released, [=]() { + HandleClick(analog_map_buttons[analog_id][sub_button_id], [=](const Common::ParamPackage& params) { SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); }, InputCommon::Polling::DeviceType::Button); }); - connect(analog_map_buttons[analog_id][sub_button_id], - &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { + connect(analog_button, &QPushButton::customContextMenuRequested, + [=](const QPoint& menu_location) { QMenu context_menu; context_menu.addAction(tr("Clear"), [&] { analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); @@ -272,11 +300,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i menu_location)); }); } - connect(analog_map_stick[analog_id], &QPushButton::released, [=]() { + connect(analog_map_stick[analog_id], &QPushButton::released, [=] { QMessageBox::information(this, tr("Information"), tr("After pressing OK, first move your joystick horizontally, " "and then vertically.")); - handleClick( + HandleClick( analog_map_stick[analog_id], [=](const Common::ParamPackage& params) { analogs_param[analog_id] = params; }, InputCommon::Polling::DeviceType::Analog); @@ -284,17 +312,17 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i } connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this] { RestoreDefaults(); }); timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - connect(poll_timer.get(), &QTimer::timeout, [this]() { + connect(poll_timer.get(), &QTimer::timeout, [this] { Common::ParamPackage params; for (auto& poller : device_pollers) { params = poller->GetNextInput(); if (params.Has("engine")) { - setPollingResult(params, false); + SetPollingResult(params, false); return; } } @@ -312,8 +340,8 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i [this, i] { OnControllerButtonClick(static_cast<int>(i)); }); } - this->loadConfiguration(); - this->resize(0, 0); + LoadConfiguration(); + resize(0, 0); // TODO(wwylele): enable this when we actually emulate it ui->buttonHome->setEnabled(false); @@ -321,7 +349,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i ConfigureInputPlayer::~ConfigureInputPlayer() = default; -void ConfigureInputPlayer::applyConfiguration() { +void ConfigureInputPlayer::ApplyConfiguration() { auto& buttons = debug ? Settings::values.debug_pad_buttons : Settings::values.players[player_index].buttons; auto& analogs = @@ -345,16 +373,29 @@ void ConfigureInputPlayer::applyConfiguration() { Settings::values.players[player_index].button_color_right = colors[3]; } +void ConfigureInputPlayer::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureInputPlayer::RetranslateUI() { + ui->retranslateUi(this); + UpdateButtonLabels(); +} + void ConfigureInputPlayer::OnControllerButtonClick(int i) { const QColor new_bg_color = QColorDialog::getColor(controller_colors[i]); if (!new_bg_color.isValid()) return; controller_colors[i] = new_bg_color; controller_color_buttons[i]->setStyleSheet( - QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); + QStringLiteral("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); } -void ConfigureInputPlayer::loadConfiguration() { +void ConfigureInputPlayer::LoadConfiguration() { if (debug) { std::transform(Settings::values.debug_pad_buttons.begin(), Settings::values.debug_pad_buttons.end(), buttons_param.begin(), @@ -371,7 +412,7 @@ void ConfigureInputPlayer::loadConfiguration() { [](const std::string& str) { return Common::ParamPackage(str); }); } - updateButtonLabels(); + UpdateButtonLabels(); if (debug) return; @@ -388,11 +429,12 @@ void ConfigureInputPlayer::loadConfiguration() { for (std::size_t i = 0; i < colors.size(); ++i) { controller_color_buttons[i]->setStyleSheet( - QString("QPushButton { background-color: %1 }").arg(controller_colors[i].name())); + QStringLiteral("QPushButton { background-color: %1 }") + .arg(controller_colors[i].name())); } } -void ConfigureInputPlayer::restoreDefaults() { +void ConfigureInputPlayer::RestoreDefaults() { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { buttons_param[button_id] = Common::ParamPackage{ InputCommon::GenerateKeyboardParam(Config::default_buttons[button_id])}; @@ -405,42 +447,54 @@ void ConfigureInputPlayer::restoreDefaults() { SetAnalogButton(params, analogs_param[analog_id], analog_sub_buttons[sub_button_id]); } } - updateButtonLabels(); + UpdateButtonLabels(); } void ConfigureInputPlayer::ClearAll() { for (int button_id = 0; button_id < Settings::NativeButton::NumButtons; button_id++) { - if (button_map[button_id] && button_map[button_id]->isEnabled()) - buttons_param[button_id].Clear(); + const auto* const button = button_map[button_id]; + if (button == nullptr || !button->isEnabled()) { + continue; + } + + buttons_param[button_id].Clear(); } + for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (analog_map_buttons[analog_id][sub_button_id] && - analog_map_buttons[analog_id][sub_button_id]->isEnabled()) - analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); + const auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; + if (analog_button == nullptr || !analog_button->isEnabled()) { + continue; + } + + analogs_param[analog_id].Erase(analog_sub_buttons[sub_button_id]); } } - updateButtonLabels(); + UpdateButtonLabels(); } -void ConfigureInputPlayer::updateButtonLabels() { +void ConfigureInputPlayer::UpdateButtonLabels() { for (int button = 0; button < Settings::NativeButton::NumButtons; button++) { button_map[button]->setText(ButtonToText(buttons_param[button])); } for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) { for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) { - if (analog_map_buttons[analog_id][sub_button_id]) { - analog_map_buttons[analog_id][sub_button_id]->setText( - AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); + auto* const analog_button = analog_map_buttons[analog_id][sub_button_id]; + + if (analog_button == nullptr) { + continue; } + + analog_button->setText( + AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id])); } analog_map_stick[analog_id]->setText(tr("Set Analog Stick")); } } -void ConfigureInputPlayer::handleClick( +void ConfigureInputPlayer::HandleClick( QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type) { button->setText(tr("[press key]")); @@ -468,7 +522,7 @@ void ConfigureInputPlayer::handleClick( poll_timer->start(200); // Check for new inputs every 200ms } -void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, bool abort) { +void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { releaseKeyboard(); releaseMouse(); timeout_timer->stop(); @@ -481,22 +535,23 @@ void ConfigureInputPlayer::setPollingResult(const Common::ParamPackage& params, (*input_setter)(params); } - updateButtonLabels(); + UpdateButtonLabels(); input_setter = std::nullopt; } void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) + if (!input_setter || !event) { return; + } if (event->key() != Qt::Key_Escape) { if (want_keyboard_keys) { - setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, false); } else { // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling return; } } - setPollingResult({}, true); + SetPollingResult({}, true); } diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index ade8d4435..c66027651 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -38,28 +38,31 @@ public: ~ConfigureInputPlayer() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + void OnControllerButtonClick(int i); /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); /// Clear all input configuration void ClearAll(); /// Update UI to reflect current configuration. - void updateButtonLabels(); + void UpdateButtonLabels(); /// Called when the button was pressed. - void handleClick(QPushButton* button, + void HandleClick(QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type); /// Finish polling and configure input using the input_setter - void setPollingResult(const Common::ParamPackage& params, bool abort); + void SetPollingResult(const Common::ParamPackage& params, bool abort); /// Handle key press events. void keyPressEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/configure_input_simple.cpp b/src/yuzu/configuration/configure_input_simple.cpp index 07d71e9d1..864803ea3 100644 --- a/src/yuzu/configuration/configure_input_simple.cpp +++ b/src/yuzu/configuration/configure_input_simple.cpp @@ -15,12 +15,12 @@ namespace { template <typename Dialog, typename... Args> void CallConfigureDialog(ConfigureInputSimple* caller, Args&&... args) { - caller->applyConfiguration(); + caller->ApplyConfiguration(); Dialog dialog(caller, std::forward<Args>(args)...); const auto res = dialog.exec(); if (res == QDialog::Accepted) { - dialog.applyConfiguration(); + dialog.ApplyConfiguration(); } } @@ -103,27 +103,41 @@ ConfigureInputSimple::ConfigureInputSimple(QWidget* parent) &ConfigureInputSimple::OnSelectProfile); connect(ui->profile_configure, &QPushButton::pressed, this, &ConfigureInputSimple::OnConfigure); - this->loadConfiguration(); + LoadConfiguration(); } ConfigureInputSimple::~ConfigureInputSimple() = default; -void ConfigureInputSimple::applyConfiguration() { +void ConfigureInputSimple::ApplyConfiguration() { auto index = ui->profile_combobox->currentIndex(); // Make the stored index for "Custom" very large so that if new profiles are added it // doesn't change. - if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) + if (index >= static_cast<int>(INPUT_PROFILES.size() - 1)) { index = std::numeric_limits<int>::max(); + } UISettings::values.profile_index = index; } -void ConfigureInputSimple::loadConfiguration() { +void ConfigureInputSimple::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureInputSimple::RetranslateUI() { + ui->retranslateUi(this); +} + +void ConfigureInputSimple::LoadConfiguration() { const auto index = UISettings::values.profile_index; - if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) + if (index >= static_cast<int>(INPUT_PROFILES.size()) || index < 0) { ui->profile_combobox->setCurrentIndex(static_cast<int>(INPUT_PROFILES.size() - 1)); - else + } else { ui->profile_combobox->setCurrentIndex(index); + } } void ConfigureInputSimple::OnSelectProfile(int index) { diff --git a/src/yuzu/configuration/configure_input_simple.h b/src/yuzu/configuration/configure_input_simple.h index 5b6b69994..bb5050224 100644 --- a/src/yuzu/configuration/configure_input_simple.h +++ b/src/yuzu/configuration/configure_input_simple.h @@ -27,11 +27,14 @@ public: ~ConfigureInputSimple() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); void OnSelectProfile(int index); void OnConfigure(); diff --git a/src/yuzu/configuration/configure_mouse_advanced.cpp b/src/yuzu/configuration/configure_mouse_advanced.cpp index ef857035e..b7305e653 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.cpp +++ b/src/yuzu/configuration/configure_mouse_advanced.cpp @@ -25,7 +25,7 @@ static QString GetKeyName(int key_code) { case Qt::Key_Alt: return QObject::tr("Alt"); case Qt::Key_Meta: - return ""; + return {}; default: return QKeySequence(key_code).toString(); } @@ -34,24 +34,36 @@ static QString GetKeyName(int key_code) { static QString ButtonToText(const Common::ParamPackage& param) { if (!param.Has("engine")) { return QObject::tr("[not set]"); - } else if (param.Get("engine", "") == "keyboard") { + } + + if (param.Get("engine", "") == "keyboard") { return GetKeyName(param.Get("code", 0)); - } else if (param.Get("engine", "") == "sdl") { + } + + if (param.Get("engine", "") == "sdl") { if (param.Has("hat")) { - return QString(QObject::tr("Hat %1 %2")) - .arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str()); + const QString hat_str = QString::fromStdString(param.Get("hat", "")); + const QString direction_str = QString::fromStdString(param.Get("direction", "")); + + return QObject::tr("Hat %1 %2").arg(hat_str, direction_str); } + if (param.Has("axis")) { - return QString(QObject::tr("Axis %1%2")) - .arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str()); + const QString axis_str = QString::fromStdString(param.Get("axis", "")); + const QString direction_str = QString::fromStdString(param.Get("direction", "")); + + return QObject::tr("Axis %1%2").arg(axis_str, direction_str); } + if (param.Has("button")) { - return QString(QObject::tr("Button %1")).arg(param.Get("button", "").c_str()); + const QString button_str = QString::fromStdString(param.Get("button", "")); + + return QObject::tr("Button %1").arg(button_str); } - return QString(); - } else { - return QObject::tr("[unknown]"); + return {}; } + + return QObject::tr("[unknown]"); } ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) @@ -65,93 +77,108 @@ ConfigureMouseAdvanced::ConfigureMouseAdvanced(QWidget* parent) }; for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { - if (!button_map[button_id]) + auto* const button = button_map[button_id]; + if (button == nullptr) { continue; - button_map[button_id]->setContextMenuPolicy(Qt::CustomContextMenu); - connect(button_map[button_id], &QPushButton::released, [=]() { - handleClick( + } + + button->setContextMenuPolicy(Qt::CustomContextMenu); + connect(button, &QPushButton::released, [=] { + HandleClick( button_map[button_id], [=](const Common::ParamPackage& params) { buttons_param[button_id] = params; }, InputCommon::Polling::DeviceType::Button); }); - connect(button_map[button_id], &QPushButton::customContextMenuRequested, - [=](const QPoint& menu_location) { - QMenu context_menu; - context_menu.addAction(tr("Clear"), [&] { - buttons_param[button_id].Clear(); - button_map[button_id]->setText(tr("[not set]")); - }); - context_menu.addAction(tr("Restore Default"), [&] { - buttons_param[button_id] = - Common::ParamPackage{InputCommon::GenerateKeyboardParam( - Config::default_mouse_buttons[button_id])}; - button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); - }); - context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); - }); + connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) { + QMenu context_menu; + context_menu.addAction(tr("Clear"), [&] { + buttons_param[button_id].Clear(); + button_map[button_id]->setText(tr("[not set]")); + }); + context_menu.addAction(tr("Restore Default"), [&] { + buttons_param[button_id] = Common::ParamPackage{ + InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; + button_map[button_id]->setText(ButtonToText(buttons_param[button_id])); + }); + context_menu.exec(button_map[button_id]->mapToGlobal(menu_location)); + }); } connect(ui->buttonClearAll, &QPushButton::released, [this] { ClearAll(); }); - connect(ui->buttonRestoreDefaults, &QPushButton::released, [this]() { restoreDefaults(); }); + connect(ui->buttonRestoreDefaults, &QPushButton::released, [this] { RestoreDefaults(); }); timeout_timer->setSingleShot(true); - connect(timeout_timer.get(), &QTimer::timeout, [this]() { setPollingResult({}, true); }); + connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); }); - connect(poll_timer.get(), &QTimer::timeout, [this]() { + connect(poll_timer.get(), &QTimer::timeout, [this] { Common::ParamPackage params; for (auto& poller : device_pollers) { params = poller->GetNextInput(); if (params.Has("engine")) { - setPollingResult(params, false); + SetPollingResult(params, false); return; } } }); - loadConfiguration(); + LoadConfiguration(); resize(0, 0); } ConfigureMouseAdvanced::~ConfigureMouseAdvanced() = default; -void ConfigureMouseAdvanced::applyConfiguration() { +void ConfigureMouseAdvanced::ApplyConfiguration() { std::transform(buttons_param.begin(), buttons_param.end(), Settings::values.mouse_buttons.begin(), [](const Common::ParamPackage& param) { return param.Serialize(); }); } -void ConfigureMouseAdvanced::loadConfiguration() { +void ConfigureMouseAdvanced::LoadConfiguration() { std::transform(Settings::values.mouse_buttons.begin(), Settings::values.mouse_buttons.end(), buttons_param.begin(), [](const std::string& str) { return Common::ParamPackage(str); }); - updateButtonLabels(); + UpdateButtonLabels(); +} + +void ConfigureMouseAdvanced::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureMouseAdvanced::RetranslateUI() { + ui->retranslateUi(this); } -void ConfigureMouseAdvanced::restoreDefaults() { +void ConfigureMouseAdvanced::RestoreDefaults() { for (int button_id = 0; button_id < Settings::NativeMouseButton::NumMouseButtons; button_id++) { buttons_param[button_id] = Common::ParamPackage{ InputCommon::GenerateKeyboardParam(Config::default_mouse_buttons[button_id])}; } - updateButtonLabels(); + UpdateButtonLabels(); } void ConfigureMouseAdvanced::ClearAll() { for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { - if (button_map[i] && button_map[i]->isEnabled()) + const auto* const button = button_map[i]; + if (button != nullptr && button->isEnabled()) { buttons_param[i].Clear(); + } } - updateButtonLabels(); + UpdateButtonLabels(); } -void ConfigureMouseAdvanced::updateButtonLabels() { +void ConfigureMouseAdvanced::UpdateButtonLabels() { for (int button = 0; button < Settings::NativeMouseButton::NumMouseButtons; button++) { button_map[button]->setText(ButtonToText(buttons_param[button])); } } -void ConfigureMouseAdvanced::handleClick( +void ConfigureMouseAdvanced::HandleClick( QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type) { button->setText(tr("[press key]")); @@ -179,7 +206,7 @@ void ConfigureMouseAdvanced::handleClick( poll_timer->start(200); // Check for new inputs every 200ms } -void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params, bool abort) { +void ConfigureMouseAdvanced::SetPollingResult(const Common::ParamPackage& params, bool abort) { releaseKeyboard(); releaseMouse(); timeout_timer->stop(); @@ -192,22 +219,23 @@ void ConfigureMouseAdvanced::setPollingResult(const Common::ParamPackage& params (*input_setter)(params); } - updateButtonLabels(); + UpdateButtonLabels(); input_setter = std::nullopt; } void ConfigureMouseAdvanced::keyPressEvent(QKeyEvent* event) { - if (!input_setter || !event) + if (!input_setter || !event) { return; + } if (event->key() != Qt::Key_Escape) { if (want_keyboard_keys) { - setPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, + SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, false); } else { // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling return; } } - setPollingResult({}, true); + SetPollingResult({}, true); } diff --git a/src/yuzu/configuration/configure_mouse_advanced.h b/src/yuzu/configuration/configure_mouse_advanced.h index e04da4bf2..342b82412 100644 --- a/src/yuzu/configuration/configure_mouse_advanced.h +++ b/src/yuzu/configuration/configure_mouse_advanced.h @@ -25,26 +25,29 @@ public: explicit ConfigureMouseAdvanced(QWidget* parent); ~ConfigureMouseAdvanced() override; - void applyConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); /// Clear all input configuration void ClearAll(); /// Update UI to reflect current configuration. - void updateButtonLabels(); + void UpdateButtonLabels(); /// Called when the button was pressed. - void handleClick(QPushButton* button, + void HandleClick(QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, InputCommon::Polling::DeviceType type); /// Finish polling and configure input using the input_setter - void setPollingResult(const Common::ParamPackage& params, bool abort); + void SetPollingResult(const Common::ParamPackage& params, bool abort); /// Handle key press events. void keyPressEvent(QKeyEvent* event) override; diff --git a/src/yuzu/configuration/configure_per_general.cpp b/src/yuzu/configuration/configure_per_general.cpp index 022b94609..90336e235 100644 --- a/src/yuzu/configuration/configure_per_general.cpp +++ b/src/yuzu/configuration/configure_per_general.cpp @@ -13,6 +13,8 @@ #include <QTimer> #include <QTreeView> +#include "common/common_paths.h" +#include "common/file_util.h" #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/file_sys/xts_archive.h" @@ -65,12 +67,12 @@ ConfigurePerGameGeneral::ConfigurePerGameGeneral(QWidget* parent, u64 title_id) connect(item_model, &QStandardItemModel::itemChanged, [] { UISettings::values.is_game_list_reload_pending.exchange(true); }); - this->loadConfiguration(); + LoadConfiguration(); } ConfigurePerGameGeneral::~ConfigurePerGameGeneral() = default; -void ConfigurePerGameGeneral::applyConfiguration() { +void ConfigurePerGameGeneral::ApplyConfiguration() { std::vector<std::string> disabled_addons; for (const auto& item : list_items) { @@ -79,24 +81,44 @@ void ConfigurePerGameGeneral::applyConfiguration() { disabled_addons.push_back(item.front()->text().toStdString()); } + auto current = Settings::values.disabled_addons[title_id]; + std::sort(disabled_addons.begin(), disabled_addons.end()); + std::sort(current.begin(), current.end()); + if (disabled_addons != current) { + FileUtil::Delete(FileUtil::GetUserPath(FileUtil::UserPath::CacheDir) + DIR_SEP + + "game_list" + DIR_SEP + fmt::format("{:016X}.pv.txt", title_id)); + } + Settings::values.disabled_addons[title_id] = disabled_addons; } -void ConfigurePerGameGeneral::loadFromFile(FileSys::VirtualFile file) { +void ConfigurePerGameGeneral::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigurePerGameGeneral::RetranslateUI() { + ui->retranslateUi(this); +} + +void ConfigurePerGameGeneral::LoadFromFile(FileSys::VirtualFile file) { this->file = std::move(file); - this->loadConfiguration(); + LoadConfiguration(); } -void ConfigurePerGameGeneral::loadConfiguration() { - if (file == nullptr) +void ConfigurePerGameGeneral::LoadConfiguration() { + if (file == nullptr) { return; + } - const auto loader = Loader::GetLoader(file); - - ui->display_title_id->setText(fmt::format("{:016X}", title_id).c_str()); + ui->display_title_id->setText(QString::fromStdString(fmt::format("{:016X}", title_id))); FileSys::PatchManager pm{title_id}; const auto control = pm.GetControlMetadata(); + const auto loader = Loader::GetLoader(file); if (control.first != nullptr) { ui->display_version->setText(QString::fromStdString(control.first->GetVersionString())); @@ -142,8 +164,10 @@ void ConfigurePerGameGeneral::loadConfiguration() { const auto& disabled = Settings::values.disabled_addons[title_id]; for (const auto& patch : pm.GetPatchVersionNames(update_raw)) { - QStandardItem* first_item = new QStandardItem; - const auto name = QString::fromStdString(patch.first).replace("[D] ", ""); + const auto name = + QString::fromStdString(patch.first).replace(QStringLiteral("[D] "), QString{}); + + auto* const first_item = new QStandardItem; first_item->setText(name); first_item->setCheckable(true); diff --git a/src/yuzu/configuration/configure_per_general.h b/src/yuzu/configuration/configure_per_general.h index f8a7d5326..a3b2cdeff 100644 --- a/src/yuzu/configuration/configure_per_general.h +++ b/src/yuzu/configuration/configure_per_general.h @@ -30,11 +30,16 @@ public: ~ConfigurePerGameGeneral() override; /// Save all button configurations to settings file - void applyConfiguration(); + void ApplyConfiguration(); - void loadFromFile(FileSys::VirtualFile file); + void LoadFromFile(FileSys::VirtualFile file); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void LoadConfiguration(); + std::unique_ptr<Ui::ConfigurePerGameGeneral> ui; FileSys::VirtualFile file; u64 title_id; @@ -45,6 +50,4 @@ private: QGraphicsScene* scene; std::vector<QList<QStandardItem*>> list_items; - - void loadConfiguration(); }; diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index 41663e39a..c90f4cdd8 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp @@ -33,14 +33,13 @@ constexpr std::array<u8, 107> backup_jpeg{ 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, }; -QString GetImagePath(Service::Account::UUID uuid) { +QString GetImagePath(Common::UUID uuid) { const auto path = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; return QString::fromStdString(path); } -QString GetAccountUsername(const Service::Account::ProfileManager& manager, - Service::Account::UUID uuid) { +QString GetAccountUsername(const Service::Account::ProfileManager& manager, Common::UUID uuid) { Service::Account::ProfileBase profile; if (!manager.GetProfileBase(uuid, profile)) { return {}; @@ -51,14 +50,14 @@ QString GetAccountUsername(const Service::Account::ProfileManager& manager, return QString::fromStdString(text); } -QString FormatUserEntryText(const QString& username, Service::Account::UUID uuid) { +QString FormatUserEntryText(const QString& username, Common::UUID uuid) { return ConfigureProfileManager::tr("%1\n%2", "%1 is the profile username, %2 is the formatted UUID (e.g. " "00112233-4455-6677-8899-AABBCCDDEEFF))") .arg(username, QString::fromStdString(uuid.FormatSwitch())); } -QPixmap GetIcon(Service::Account::UUID uuid) { +QPixmap GetIcon(Common::UUID uuid) { QPixmap icon{GetImagePath(uuid)}; if (!icon) { @@ -81,11 +80,10 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent) profile_manager(std::make_unique<Service::Account::ProfileManager>()) { ui->setupUi(this); - layout = new QVBoxLayout; tree_view = new QTreeView; item_model = new QStandardItemModel(tree_view); + item_model->insertColumns(0, 1); tree_view->setModel(item_model); - tree_view->setAlternatingRowColors(true); tree_view->setSelectionMode(QHeaderView::SingleSelection); tree_view->setSelectionBehavior(QHeaderView::SelectRows); @@ -97,13 +95,11 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent) tree_view->setIconSize({64, 64}); tree_view->setContextMenuPolicy(Qt::NoContextMenu); - item_model->insertColumns(0, 1); - item_model->setHeaderData(0, Qt::Horizontal, "Users"); - // We must register all custom types with the Qt Automoc system so that we are able to use it // with signals/slots. In this case, QList falls under the umbrells of custom types. qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>"); + layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); layout->addWidget(tree_view); @@ -120,12 +116,26 @@ ConfigureProfileManager ::ConfigureProfileManager(QWidget* parent) scene = new QGraphicsScene; ui->current_user_icon->setScene(scene); - this->setConfiguration(); + SetConfiguration(); + RetranslateUI(); } ConfigureProfileManager::~ConfigureProfileManager() = default; -void ConfigureProfileManager::setConfiguration() { +void ConfigureProfileManager::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureProfileManager::RetranslateUI() { + ui->retranslateUi(this); + item_model->setHeaderData(0, Qt::Horizontal, tr("Users")); +} + +void ConfigureProfileManager::SetConfiguration() { enabled = !Core::System::GetInstance().IsPoweredOn(); item_model->removeRows(0, item_model->rowCount()); list_items.clear(); @@ -165,9 +175,10 @@ void ConfigureProfileManager::UpdateCurrentUser() { ui->current_user_username->setText(username); } -void ConfigureProfileManager::applyConfiguration() { - if (!enabled) +void ConfigureProfileManager::ApplyConfiguration() { + if (!enabled) { return; + } Settings::Apply(); } @@ -190,7 +201,7 @@ void ConfigureProfileManager::AddUser() { return; } - const auto uuid = Service::Account::UUID::Generate(); + const auto uuid = Common::UUID::Generate(); profile_manager->CreateNewUser(uuid, username.toStdString()); item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)}); diff --git a/src/yuzu/configuration/configure_profile_manager.h b/src/yuzu/configuration/configure_profile_manager.h index 7fe95a2a8..0a9bca2a6 100644 --- a/src/yuzu/configuration/configure_profile_manager.h +++ b/src/yuzu/configuration/configure_profile_manager.h @@ -30,10 +30,14 @@ public: explicit ConfigureProfileManager(QWidget* parent = nullptr); ~ConfigureProfileManager() override; - void applyConfiguration(); - void setConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void SetConfiguration(); + void PopulateUserList(); void UpdateCurrentUser(); diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 10645a2b3..e1b52f8d9 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -16,49 +16,43 @@ #include "ui_configure_system.h" #include "yuzu/configuration/configure_system.h" -namespace { -constexpr std::array<int, 12> days_in_month = {{ - 31, - 29, - 31, - 30, - 31, - 30, - 31, - 31, - 30, - 31, - 30, - 31, -}}; -} // Anonymous namespace - ConfigureSystem::ConfigureSystem(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureSystem) { ui->setupUi(this); - connect(ui->combo_birthmonth, - static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, - &ConfigureSystem::UpdateBirthdayComboBox); connect(ui->button_regenerate_console_id, &QPushButton::clicked, this, &ConfigureSystem::RefreshConsoleID); connect(ui->rng_seed_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { ui->rng_seed_edit->setEnabled(checked); - if (!checked) + if (!checked) { ui->rng_seed_edit->setText(QStringLiteral("00000000")); + } }); connect(ui->custom_rtc_checkbox, &QCheckBox::stateChanged, this, [this](bool checked) { ui->custom_rtc_edit->setEnabled(checked); - if (!checked) + if (!checked) { ui->custom_rtc_edit->setDateTime(QDateTime::currentDateTime()); + } }); - this->setConfiguration(); + SetConfiguration(); } ConfigureSystem::~ConfigureSystem() = default; -void ConfigureSystem::setConfiguration() { +void ConfigureSystem::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureSystem::RetranslateUI() { + ui->retranslateUi(this); +} + +void ConfigureSystem::SetConfiguration() { enabled = !Core::System::GetInstance().IsPoweredOn(); ui->combo_language->setCurrentIndex(Settings::values.language_index); @@ -66,8 +60,9 @@ void ConfigureSystem::setConfiguration() { ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value()); ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value()); - const auto rng_seed = - QString("%1").arg(Settings::values.rng_seed.value_or(0), 8, 16, QLatin1Char{'0'}).toUpper(); + const auto rng_seed = QStringLiteral("%1") + .arg(Settings::values.rng_seed.value_or(0), 8, 16, QLatin1Char{'0'}) + .toUpper(); ui->rng_seed_edit->setText(rng_seed); ui->custom_rtc_checkbox->setChecked(Settings::values.custom_rtc.has_value()); @@ -80,49 +75,27 @@ void ConfigureSystem::setConfiguration() { void ConfigureSystem::ReadSystemSettings() {} -void ConfigureSystem::applyConfiguration() { - if (!enabled) +void ConfigureSystem::ApplyConfiguration() { + if (!enabled) { return; + } Settings::values.language_index = ui->combo_language->currentIndex(); - if (ui->rng_seed_checkbox->isChecked()) + if (ui->rng_seed_checkbox->isChecked()) { Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16); - else + } else { Settings::values.rng_seed = std::nullopt; + } - if (ui->custom_rtc_checkbox->isChecked()) + if (ui->custom_rtc_checkbox->isChecked()) { Settings::values.custom_rtc = std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()); - else + } else { Settings::values.custom_rtc = std::nullopt; - - Settings::Apply(); -} - -void ConfigureSystem::UpdateBirthdayComboBox(int birthmonth_index) { - if (birthmonth_index < 0 || birthmonth_index >= 12) - return; - - // store current day selection - int birthday_index = ui->combo_birthday->currentIndex(); - - // get number of days in the new selected month - int days = days_in_month[birthmonth_index]; - - // if the selected day is out of range, - // reset it to 1st - if (birthday_index < 0 || birthday_index >= days) - birthday_index = 0; - - // update the day combo box - ui->combo_birthday->clear(); - for (int i = 1; i <= days; ++i) { - ui->combo_birthday->addItem(QString::number(i)); } - // restore the day selection - ui->combo_birthday->setCurrentIndex(birthday_index); + Settings::Apply(); } void ConfigureSystem::RefreshConsoleID() { @@ -133,8 +106,10 @@ void ConfigureSystem::RefreshConsoleID() { "if you use an outdated config savegame. Continue?"); reply = QMessageBox::critical(this, tr("Warning"), warning_text, QMessageBox::No | QMessageBox::Yes); - if (reply == QMessageBox::No) + if (reply == QMessageBox::No) { return; + } + u64 console_id{}; ui->label_console_id->setText( tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper())); diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index cf1e54de5..1eab3781d 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h @@ -20,20 +20,21 @@ public: explicit ConfigureSystem(QWidget* parent = nullptr); ~ConfigureSystem() override; - void applyConfiguration(); - void setConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + + void SetConfiguration(); + void ReadSystemSettings(); - void UpdateBirthdayComboBox(int birthmonth_index); void RefreshConsoleID(); std::unique_ptr<Ui::ConfigureSystem> ui; bool enabled = false; - int birthmonth = 0; - int birthday = 0; int language_index = 0; int sound_index = 0; }; diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 073327298..65745a2f8 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -22,14 +22,21 @@ <string>System Settings</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="2" column="0"> + <item row="1" column="0"> <widget class="QLabel" name="label_sound"> <property name="text"> <string>Sound output mode</string> </property> </widget> </item> - <item row="1" column="1"> + <item row="2" column="0"> + <widget class="QLabel" name="label_console_id"> + <property name="text"> + <string>Console ID:</string> + </property> + </widget> + </item> + <item row="0" column="1"> <widget class="QComboBox" name="combo_language"> <property name="toolTip"> <string>Note: this can be overridden when region setting is auto-select</string> @@ -121,108 +128,14 @@ </item> </widget> </item> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_birthday2"> - <item> - <widget class="QComboBox" name="combo_birthmonth"> - <item> - <property name="text"> - <string>January</string> - </property> - </item> - <item> - <property name="text"> - <string>February</string> - </property> - </item> - <item> - <property name="text"> - <string>March</string> - </property> - </item> - <item> - <property name="text"> - <string>April</string> - </property> - </item> - <item> - <property name="text"> - <string>May</string> - </property> - </item> - <item> - <property name="text"> - <string>June</string> - </property> - </item> - <item> - <property name="text"> - <string>July</string> - </property> - </item> - <item> - <property name="text"> - <string>August</string> - </property> - </item> - <item> - <property name="text"> - <string>September</string> - </property> - </item> - <item> - <property name="text"> - <string>October</string> - </property> - </item> - <item> - <property name="text"> - <string>November</string> - </property> - </item> - <item> - <property name="text"> - <string>December</string> - </property> - </item> - </widget> - </item> - <item> - <widget class="QComboBox" name="combo_birthday"/> - </item> - </layout> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_console_id"> - <property name="text"> - <string>Console ID:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_birthday"> - <property name="text"> - <string>Birthday</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QPushButton" name="button_regenerate_console_id"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="layoutDirection"> - <enum>Qt::RightToLeft</enum> - </property> + <item row="4" column="0"> + <widget class="QCheckBox" name="rng_seed_checkbox"> <property name="text"> - <string>Regenerate</string> + <string>RNG Seed</string> </property> </widget> </item> - <item row="2" column="1"> + <item row="1" column="1"> <widget class="QComboBox" name="combo_sound"> <item> <property name="text"> @@ -241,49 +154,37 @@ </item> </widget> </item> - <item row="5" column="0"> - <widget class="QCheckBox" name="rng_seed_checkbox"> - <property name="text"> - <string>RNG Seed</string> - </property> - </widget> - </item> - <item row="1" column="0"> + <item row="0" column="0"> <widget class="QLabel" name="label_language"> <property name="text"> <string>Language</string> </property> </widget> </item> - <item row="5" column="1"> - <widget class="QLineEdit" name="rng_seed_edit"> + <item row="2" column="1"> + <widget class="QPushButton" name="button_regenerate_console_id"> <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> - <property name="font"> - <font> - <family>Lucida Console</family> - </font> - </property> - <property name="inputMask"> - <string notr="true">HHHHHHHH</string> + <property name="layoutDirection"> + <enum>Qt::RightToLeft</enum> </property> - <property name="maxLength"> - <number>8</number> + <property name="text"> + <string>Regenerate</string> </property> </widget> </item> - <item row="4" column="0"> + <item row="3" column="0"> <widget class="QCheckBox" name="custom_rtc_checkbox"> <property name="text"> <string>Custom RTC</string> </property> </widget> </item> - <item row="4" column="1"> + <item row="3" column="1"> <widget class="QDateTimeEdit" name="custom_rtc_edit"> <property name="minimumDate"> <date> @@ -297,6 +198,27 @@ </property> </widget> </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="rng_seed_edit"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + <family>Lucida Console</family> + </font> + </property> + <property name="inputMask"> + <string notr="true">HHHHHHHH</string> + </property> + <property name="maxLength"> + <number>8</number> + </property> + </widget> + </item> </layout> </widget> </item> diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 9c1561e9d..8ced28c75 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp @@ -12,29 +12,41 @@ ConfigureTouchscreenAdvanced::ConfigureTouchscreenAdvanced(QWidget* parent) ui->setupUi(this); connect(ui->restore_defaults_button, &QPushButton::pressed, this, - &ConfigureTouchscreenAdvanced::restoreDefaults); + &ConfigureTouchscreenAdvanced::RestoreDefaults); - loadConfiguration(); + LoadConfiguration(); resize(0, 0); } ConfigureTouchscreenAdvanced::~ConfigureTouchscreenAdvanced() = default; -void ConfigureTouchscreenAdvanced::applyConfiguration() { +void ConfigureTouchscreenAdvanced::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QDialog::changeEvent(event); +} + +void ConfigureTouchscreenAdvanced::RetranslateUI() { + ui->retranslateUi(this); +} + +void ConfigureTouchscreenAdvanced::ApplyConfiguration() { Settings::values.touchscreen.finger = ui->finger_box->value(); Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); Settings::values.touchscreen.diameter_y = ui->diameter_y_box->value(); Settings::values.touchscreen.rotation_angle = ui->angle_box->value(); } -void ConfigureTouchscreenAdvanced::loadConfiguration() { +void ConfigureTouchscreenAdvanced::LoadConfiguration() { ui->finger_box->setValue(Settings::values.touchscreen.finger); ui->diameter_x_box->setValue(Settings::values.touchscreen.diameter_x); ui->diameter_y_box->setValue(Settings::values.touchscreen.diameter_y); ui->angle_box->setValue(Settings::values.touchscreen.rotation_angle); } -void ConfigureTouchscreenAdvanced::restoreDefaults() { +void ConfigureTouchscreenAdvanced::RestoreDefaults() { ui->finger_box->setValue(0); ui->diameter_x_box->setValue(15); ui->diameter_y_box->setValue(15); diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.h b/src/yuzu/configuration/configure_touchscreen_advanced.h index 3d0772c87..72061492c 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.h +++ b/src/yuzu/configuration/configure_touchscreen_advanced.h @@ -18,13 +18,16 @@ public: explicit ConfigureTouchscreenAdvanced(QWidget* parent); ~ConfigureTouchscreenAdvanced() override; - void applyConfiguration(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + /// Load configuration settings. - void loadConfiguration(); + void LoadConfiguration(); /// Restore all buttons to their default values. - void restoreDefaults(); + void RestoreDefaults(); std::unique_ptr<Ui::ConfigureTouchscreenAdvanced> ui; }; diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index 18566d028..5a70ef168 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp @@ -22,41 +22,61 @@ ConfigureWeb::ConfigureWeb(QWidget* parent) #ifndef USE_DISCORD_PRESENCE ui->discord_group->setVisible(false); #endif - this->setConfiguration(); + + SetConfiguration(); + RetranslateUI(); } ConfigureWeb::~ConfigureWeb() = default; -void ConfigureWeb::setConfiguration() { - ui->web_credentials_disclaimer->setWordWrap(true); - ui->telemetry_learn_more->setOpenExternalLinks(true); +void ConfigureWeb::changeEvent(QEvent* event) { + if (event->type() == QEvent::LanguageChange) { + RetranslateUI(); + } + + QWidget::changeEvent(event); +} + +void ConfigureWeb::RetranslateUI() { + ui->retranslateUi(this); + ui->telemetry_learn_more->setText( tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'><span style=\"text-decoration: " "underline; color:#039be5;\">Learn more</span></a>")); - ui->web_signup_link->setOpenExternalLinks(true); ui->web_signup_link->setText( tr("<a href='https://profile.yuzu-emu.org/'><span style=\"text-decoration: underline; " "color:#039be5;\">Sign up</span></a>")); - ui->web_token_info_link->setOpenExternalLinks(true); + ui->web_token_info_link->setText( tr("<a href='https://yuzu-emu.org/wiki/yuzu-web-service/'><span style=\"text-decoration: " "underline; color:#039be5;\">What is my token?</span></a>")); + ui->label_telemetry_id->setText( + tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper())); +} + +void ConfigureWeb::SetConfiguration() { + ui->web_credentials_disclaimer->setWordWrap(true); + + ui->telemetry_learn_more->setOpenExternalLinks(true); + ui->web_signup_link->setOpenExternalLinks(true); + ui->web_token_info_link->setOpenExternalLinks(true); + ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry); ui->edit_username->setText(QString::fromStdString(Settings::values.yuzu_username)); ui->edit_token->setText(QString::fromStdString(Settings::values.yuzu_token)); + // Connect after setting the values, to avoid calling OnLoginChanged now connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged); connect(ui->edit_username, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged); - ui->label_telemetry_id->setText( - tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper())); + user_verified = true; ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence); } -void ConfigureWeb::applyConfiguration() { +void ConfigureWeb::ApplyConfiguration() { Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked(); UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked(); if (user_verified) { @@ -78,12 +98,16 @@ void ConfigureWeb::RefreshTelemetryID() { void ConfigureWeb::OnLoginChanged() { if (ui->edit_username->text().isEmpty() && ui->edit_token->text().isEmpty()) { user_verified = true; - ui->label_username_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16)); - ui->label_token_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16)); + + const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16); + ui->label_username_verified->setPixmap(pixmap); + ui->label_token_verified->setPixmap(pixmap); } else { user_verified = false; - ui->label_username_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16)); - ui->label_token_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16)); + + const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16); + ui->label_username_verified->setPixmap(pixmap); + ui->label_token_verified->setPixmap(pixmap); } } @@ -101,18 +125,18 @@ void ConfigureWeb::OnLoginVerified() { ui->button_verify_login->setText(tr("Verify")); if (verify_watcher.result()) { user_verified = true; - ui->label_username_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16)); - ui->label_token_verified->setPixmap(QIcon::fromTheme("checked").pixmap(16)); + + const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16); + ui->label_username_verified->setPixmap(pixmap); + ui->label_token_verified->setPixmap(pixmap); } else { - ui->label_username_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16)); - ui->label_token_verified->setPixmap(QIcon::fromTheme("failed").pixmap(16)); + const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16); + ui->label_username_verified->setPixmap(pixmap); + ui->label_token_verified->setPixmap(pixmap); + QMessageBox::critical( this, tr("Verification failed"), tr("Verification failed. Check that you have entered your username and token " "correctly, and that your internet connection is working.")); } } - -void ConfigureWeb::retranslateUi() { - ui->retranslateUi(this); -} diff --git a/src/yuzu/configuration/configure_web.h b/src/yuzu/configuration/configure_web.h index 7752ae4a1..9054711ea 100644 --- a/src/yuzu/configuration/configure_web.h +++ b/src/yuzu/configuration/configure_web.h @@ -19,16 +19,18 @@ public: explicit ConfigureWeb(QWidget* parent = nullptr); ~ConfigureWeb() override; - void applyConfiguration(); - void retranslateUi(); + void ApplyConfiguration(); private: + void changeEvent(QEvent* event) override; + void RetranslateUI(); + void RefreshTelemetryID(); void OnLoginChanged(); void VerifyLogin(); void OnLoginVerified(); - void setConfiguration(); + void SetConfiguration(); bool user_verified = true; QFutureWatcher<bool> verify_watcher; |
