From f700e4d01dd04b46aaa85ba19b3ee67a52d6400a Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:32:12 +0000 Subject: [PATCH 01/10] theme.h --- src/citron/theme.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/citron/theme.h diff --git a/src/citron/theme.h b/src/citron/theme.h new file mode 100644 index 000000000..98c350e66 --- /dev/null +++ b/src/citron/theme.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2025 citron Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "citron/uisettings.h" + +namespace Theme { + + // Gets the user-defined accent color from settings, with a default fallback. + inline QString GetAccentColor() { + return QString::fromStdString(UISettings::values.accent_color.GetValue()); + } + + // Gets a lighter version of the accent color for hover effects. + inline QString GetAccentColorHover() { + QColor color(GetAccentColor()); + return color.lighter(115).name(); // 115% of original brightness + } + + // Gets a darker version of the accent color for pressed effects. + inline QString GetAccentColorPressed() { + QColor color(GetAccentColor()); + return color.darker(120).name(); // 120% of original darkness + } + +} // namespace Theme From 0b498caece7912398274da52bad7473bfb8474a2 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:33:32 +0000 Subject: [PATCH 02/10] Include theme.h --- src/citron/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/citron/CMakeLists.txt b/src/citron/CMakeLists.txt index 21e3ffbb2..1b18cd17d 100644 --- a/src/citron/CMakeLists.txt +++ b/src/citron/CMakeLists.txt @@ -209,6 +209,7 @@ add_executable(citron qt_common.h startup_checks.cpp startup_checks.h + theme.h uisettings.cpp uisettings.h util/clickable_label.cpp From a321bfdc9fb5bae20ce908ebc918da166fa63e71 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:34:26 +0000 Subject: [PATCH 03/10] Edit uisettings.h --- src/citron/uisettings.h | 386 ++++++++++++++++++++-------------------- 1 file changed, 195 insertions(+), 191 deletions(-) diff --git a/src/citron/uisettings.h b/src/citron/uisettings.h index 19b2cfd71..e8bb4445f 100644 --- a/src/citron/uisettings.h +++ b/src/citron/uisettings.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -23,234 +24,237 @@ using Settings::SwitchableSetting; #ifndef CANNOT_EXPLICITLY_INSTANTIATE namespace Settings { -extern template class Setting; -extern template class Setting; -extern template class Setting; -extern template class Setting; -extern template class Setting; -extern template class Setting; -extern template class Setting; + extern template class Setting; + extern template class Setting; + extern template class Setting; + extern template class Setting; + extern template class Setting; + extern template class Setting; + extern template class Setting; } // namespace Settings #endif namespace UISettings { -bool IsDarkTheme(); + bool IsDarkTheme(); -struct ContextualShortcut { - std::string keyseq; - std::string controller_keyseq; - int context; - bool repeat; -}; + struct ContextualShortcut { + std::string keyseq; + std::string controller_keyseq; + int context; + bool repeat; + }; -struct Shortcut { - std::string name; - std::string group; - ContextualShortcut shortcut; -}; + struct Shortcut { + std::string name; + std::string group; + ContextualShortcut shortcut; + }; -enum class Theme { - Default, - DefaultColorful, - Dark, - DarkColorful, - MidnightBlue, - MidnightBlueColorful, -}; + enum class Theme { + Default, + DefaultColorful, + Dark, + DarkColorful, + MidnightBlue, + MidnightBlueColorful, + }; -static constexpr Theme default_theme{ -#ifdef _WIN32 - Theme::DarkColorful -#else - Theme::DefaultColorful -#endif -}; + static constexpr Theme default_theme{ + #ifdef _WIN32 + Theme::DarkColorful + #else + Theme::DefaultColorful + #endif + }; -using Themes = std::array, 6>; -extern const Themes themes; + using Themes = std::array, 6>; + extern const Themes themes; -struct GameDir { - std::string path; - bool deep_scan = false; - bool expanded = false; - bool operator==(const GameDir& rhs) const { - return path == rhs.path; - } - bool operator!=(const GameDir& rhs) const { - return !operator==(rhs); - } -}; + struct GameDir { + std::string path; + bool deep_scan = false; + bool expanded = false; + bool operator==(const GameDir& rhs) const { + return path == rhs.path; + } + bool operator!=(const GameDir& rhs) const { + return !operator==(rhs); + } + }; -struct Values { - Settings::Linkage linkage{1000}; + struct Values { + Settings::Linkage linkage{1000}; - QByteArray geometry; - QByteArray state; + QByteArray geometry; + QByteArray state; - QByteArray renderwindow_geometry; + QByteArray renderwindow_geometry; - QByteArray gamelist_header_state; + QByteArray gamelist_header_state; - QByteArray microprofile_geometry; - Setting microprofile_visible{linkage, false, "microProfileDialogVisible", - Category::UiLayout}; + QByteArray microprofile_geometry; + Setting microprofile_visible{linkage, false, "microProfileDialogVisible", + Category::UiLayout}; - Setting single_window_mode{linkage, true, "singleWindowMode", Category::Ui}; - Setting fullscreen{linkage, false, "fullscreen", Category::Ui}; - Setting display_titlebar{linkage, true, "displayTitleBars", Category::Ui}; - Setting show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; - Setting show_status_bar{linkage, true, "showStatusBar", Category::Ui}; - Setting show_performance_overlay{linkage, false, "showPerformanceOverlay", Category::Ui}; - Setting show_vram_overlay{linkage, false, "showVramOverlay", Category::Ui}; + Setting single_window_mode{linkage, true, "singleWindowMode", Category::Ui}; + Setting fullscreen{linkage, false, "fullscreen", Category::Ui}; + Setting display_titlebar{linkage, true, "displayTitleBars", Category::Ui}; + Setting show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; + Setting show_status_bar{linkage, true, "showStatusBar", Category::Ui}; + Setting show_performance_overlay{linkage, false, "showPerformanceOverlay", Category::Ui}; + Setting show_vram_overlay{linkage, false, "showVramOverlay", Category::Ui}; - SwitchableSetting confirm_before_stopping{linkage, - ConfirmStop::Ask_Always, - "confirmStop", - Category::UiGeneral, - Settings::Specialization::Default, - true, - true}; + SwitchableSetting confirm_before_stopping{linkage, + ConfirmStop::Ask_Always, + "confirmStop", + Category::UiGeneral, + Settings::Specialization::Default, + true, + true}; - Setting first_start{linkage, true, "firstStart", Category::Ui}; - Setting pause_when_in_background{linkage, - false, - "pauseWhenInBackground", - Category::UiGeneral, - Settings::Specialization::Default, - true, - true}; - Setting mute_when_in_background{linkage, - false, - "muteWhenInBackground", - Category::UiAudio, - Settings::Specialization::Default, - true, - true}; - Setting hide_mouse{ - linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, - true, true}; - Setting controller_applet_disabled{linkage, false, "disableControllerApplet", - Category::UiGeneral}; - // Set when Vulkan is known to crash the application - bool has_broken_vulkan = false; + Setting first_start{linkage, true, "firstStart", Category::Ui}; + Setting pause_when_in_background{linkage, + false, + "pauseWhenInBackground", + Category::UiGeneral, + Settings::Specialization::Default, + true, + true}; + Setting mute_when_in_background{linkage, + false, + "muteWhenInBackground", + Category::UiAudio, + Settings::Specialization::Default, + true, + true}; + Setting hide_mouse{ + linkage, true, "hideInactiveMouse", Category::UiGeneral, Settings::Specialization::Default, + true, true}; + Setting controller_applet_disabled{linkage, false, "disableControllerApplet", + Category::UiGeneral}; + // Set when Vulkan is known to crash the application + bool has_broken_vulkan = false; - Setting select_user_on_boot{linkage, - false, - "select_user_on_boot", - Category::UiGeneral, - Settings::Specialization::Default, - true, - true}; - Setting disable_web_applet{linkage, true, "disable_web_applet", Category::Ui}; + Setting select_user_on_boot{linkage, + false, + "select_user_on_boot", + Category::UiGeneral, + Settings::Specialization::Default, + true, + true}; + Setting disable_web_applet{linkage, true, "disable_web_applet", Category::Ui}; - // Discord RPC - Setting enable_discord_presence{linkage, true, "enable_discord_presence", Category::Ui}; + // Discord RPC + Setting enable_discord_presence{linkage, true, "enable_discord_presence", Category::Ui}; - // logging - Setting show_console{linkage, false, "showConsole", Category::Ui}; + // logging + Setting show_console{linkage, false, "showConsole", Category::Ui}; - // Screenshots - Setting enable_screenshot_save_as{linkage, true, "enable_screenshot_save_as", - Category::Screenshots}; - Setting screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; + // Screenshots + Setting enable_screenshot_save_as{linkage, true, "enable_screenshot_save_as", + Category::Screenshots}; + Setting screenshot_height{linkage, 0, "screenshot_height", Category::Screenshots}; - std::string roms_path; - std::string game_dir_deprecated; - bool game_dir_deprecated_deepscan; - QVector game_dirs; - QStringList recent_files; - Setting language{linkage, {}, "language", Category::Paths}; + std::string roms_path; + std::string game_dir_deprecated; + bool game_dir_deprecated_deepscan; + QVector game_dirs; + QStringList recent_files; + Setting language{linkage, {}, "language", Category::Paths}; - std::string theme; + std::string theme; - // Shortcut name - std::vector shortcuts; + Setting accent_color{linkage, "#4a9eff", "accent_color", Category::Ui}; + Setting enable_rainbow_mode{linkage, false, "enable_rainbow_mode", Category::Ui}; - Setting callout_flags{linkage, 0, "calloutFlags", Category::Ui}; + // Shortcut name + std::vector shortcuts; - // multiplayer settings - Setting multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer}; - Setting multiplayer_filter_text{linkage, {}, "filter_text", Category::Multiplayer}; - Setting multiplayer_filter_games_owned{linkage, false, "filter_games_owned", - Category::Multiplayer}; - Setting multiplayer_filter_hide_empty{linkage, false, "filter_games_hide_empty", + Setting callout_flags{linkage, 0, "calloutFlags", Category::Ui}; + + // multiplayer settings + Setting multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer}; + Setting multiplayer_filter_text{linkage, {}, "filter_text", Category::Multiplayer}; + Setting multiplayer_filter_games_owned{linkage, false, "filter_games_owned", + Category::Multiplayer}; + Setting multiplayer_filter_hide_empty{linkage, false, "filter_games_hide_empty", Category::Multiplayer}; - Setting multiplayer_filter_hide_full{linkage, false, "filter_games_hide_full", - Category::Multiplayer}; - Setting multiplayer_ip{linkage, {}, "ip", Category::Multiplayer}; - Setting multiplayer_port{linkage, 24872, 0, - UINT16_MAX, "port", Category::Multiplayer}; - Setting multiplayer_room_nickname{ - linkage, {}, "room_nickname", Category::Multiplayer}; - Setting multiplayer_room_name{linkage, {}, "room_name", Category::Multiplayer}; - Setting multiplayer_max_player{linkage, 8, 0, 8, "max_player", Category::Multiplayer}; - Setting multiplayer_room_port{linkage, 24872, 0, - UINT16_MAX, "room_port", Category::Multiplayer}; - Setting multiplayer_host_type{linkage, 0, 0, 1, "host_type", Category::Multiplayer}; - Setting multiplayer_game_id{linkage, {}, "game_id", Category::Multiplayer}; - Setting multiplayer_room_description{ - linkage, {}, "room_description", Category::Multiplayer}; - std::pair, std::vector> multiplayer_ban_list; + Setting multiplayer_filter_hide_full{linkage, false, "filter_games_hide_full", + Category::Multiplayer}; + Setting multiplayer_ip{linkage, {}, "ip", Category::Multiplayer}; + Setting multiplayer_port{linkage, 24872, 0, + UINT16_MAX, "port", Category::Multiplayer}; + Setting multiplayer_room_nickname{ + linkage, {}, "room_nickname", Category::Multiplayer}; + Setting multiplayer_room_name{linkage, {}, "room_name", Category::Multiplayer}; + Setting multiplayer_max_player{linkage, 8, 0, 8, "max_player", Category::Multiplayer}; + Setting multiplayer_room_port{linkage, 24872, 0, + UINT16_MAX, "room_port", Category::Multiplayer}; + Setting multiplayer_host_type{linkage, 0, 0, 1, "host_type", Category::Multiplayer}; + Setting multiplayer_game_id{linkage, {}, "game_id", Category::Multiplayer}; + Setting multiplayer_room_description{ + linkage, {}, "room_description", Category::Multiplayer}; + std::pair, std::vector> multiplayer_ban_list; - // Game List - Setting show_add_ons{linkage, true, "show_add_ons", Category::UiGameList}; - Setting game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList}; - Setting folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList}; - Setting row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList}; - Setting row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList}; - Setting game_list_grid_view{linkage, false, "game_list_grid_view", Category::UiGameList}; - std::atomic_bool is_game_list_reload_pending{false}; - Setting cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; - Setting favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; - QVector favorited_ids; + // Game List + Setting show_add_ons{linkage, true, "show_add_ons", Category::UiGameList}; + Setting game_icon_size{linkage, 64, "game_icon_size", Category::UiGameList}; + Setting folder_icon_size{linkage, 48, "folder_icon_size", Category::UiGameList}; + Setting row_1_text_id{linkage, 3, "row_1_text_id", Category::UiGameList}; + Setting row_2_text_id{linkage, 2, "row_2_text_id", Category::UiGameList}; + Setting game_list_grid_view{linkage, false, "game_list_grid_view", Category::UiGameList}; + std::atomic_bool is_game_list_reload_pending{false}; + Setting cache_game_list{linkage, true, "cache_game_list", Category::UiGameList}; + Setting favorites_expanded{linkage, true, "favorites_expanded", Category::UiGameList}; + QVector favorited_ids; - // Compatibility List - Setting show_compat{linkage, false, "show_compat", Category::UiGameList}; + // Compatibility List + Setting show_compat{linkage, false, "show_compat", Category::UiGameList}; - // Size & File Types Column - Setting show_size{linkage, true, "show_size", Category::UiGameList}; - Setting show_types{linkage, true, "show_types", Category::UiGameList}; + // Size & File Types Column + Setting show_size{linkage, true, "show_size", Category::UiGameList}; + Setting show_types{linkage, true, "show_types", Category::UiGameList}; - // Play time - Setting show_play_time{linkage, true, "show_play_time", Category::UiGameList}; + // Play time + Setting show_play_time{linkage, true, "show_play_time", Category::UiGameList}; - bool configuration_applied; - bool reset_to_defaults; - bool shortcut_already_warned{false}; -}; + bool configuration_applied; + bool reset_to_defaults; + bool shortcut_already_warned{false}; + }; -extern Values values; + extern Values values; -u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); + u32 CalculateWidth(u32 height, Settings::AspectRatio ratio); -void SaveWindowState(); -void RestoreWindowState(std::unique_ptr& qtConfig); + void SaveWindowState(); + void RestoreWindowState(std::unique_ptr& qtConfig); -// 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 default_hotkeys{{ - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit citron")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}}, - {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}}, + // 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 default_hotkeys{{ + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Capture Screenshot")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+P"), std::string("Screenshot"), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Adapting Filter")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F8"), std::string("Home+L"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change Docked Mode")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F10"), std::string("Home+X"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Change GPU Accuracy")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F9"), std::string("Home+R"), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Continue/Pause Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F4"), std::string("Home+Plus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Esc"), std::string(""), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Exit citron")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+Q"), std::string("Home+Minus"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}}, + {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}}, @@ -262,7 +266,7 @@ const std::array default_hotkeys{{ {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F9"), std::string(""), Qt::ApplicationShortcut, false}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string(""), std::string(""), Qt::ApplicationShortcut, false}}, {QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+S"), std::string(""), Qt::WindowShortcut, false}}, -}}; + }}; // clang-format on } // namespace UISettings From 02edebb05a03169dde3dcfd83bd01aa106b437c9 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:35:06 +0000 Subject: [PATCH 04/10] Edit configure.ui --- src/citron/configuration/configure.ui | 1716 +++++++++++++------------ 1 file changed, 877 insertions(+), 839 deletions(-) diff --git a/src/citron/configuration/configure.ui b/src/citron/configuration/configure.ui index b785db8e2..7d1558662 100644 --- a/src/citron/configuration/configure.ui +++ b/src/citron/configuration/configure.ui @@ -1,842 +1,880 @@ - ConfigureDialog - - - - 0 - 0 - 1400 - 900 - - - - - 1200 - 800 - - - - citron Configuration - - - - 0 - 0 - - - - - Qt::ApplicationModal - - - - citron Configuration - - - QDialog { - background-color: #2b2b2b; - color: #ffffff; -} - -QWidget { - background-color: #2b2b2b; - color: #ffffff; -} - -QStackedWidget { - background-color: #2b2b2b; - border: 1px solid #3d3d3d; - border-radius: 8px; - margin: 0px; - padding: 0px; -} - -QScrollArea { - background-color: #2b2b2b; - border: none; - border-radius: 8px; -} - -QScrollArea > QWidget > QWidget { - background-color: #2b2b2b; -} - -QScrollBar:vertical { - background-color: #3d3d3d; - width: 14px; - border-radius: 7px; - margin: 2px; -} - -QScrollBar::handle:vertical { - background-color: #5d5d5d; - border-radius: 6px; - min-height: 30px; - margin: 1px; -} - -QScrollBar::handle:vertical:hover { - background-color: #4a9eff; -} - -QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { - border: none; - background: none; - height: 0px; -} - -QScrollBar:horizontal { - background-color: #3d3d3d; - height: 14px; - border-radius: 7px; - margin: 2px; -} - -QScrollBar::handle:horizontal { - background-color: #5d5d5d; - border-radius: 6px; - min-width: 30px; - margin: 1px; -} - -QScrollBar::handle:horizontal:hover { - background-color: #4a9eff; -} - -QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { - border: none; - background: none; - width: 0px; -} - -QPushButton.tabButton { - background-color: #383838; - color: #ffffff; - padding: 10px 14px; - margin: 2px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - border-bottom-left-radius: 8px; - border-bottom-right-radius: 8px; - min-width: 85px; - max-width: 160px; - font-weight: 500; - border: 1px solid #3d3d3d; - text-align: center; -} - -QPushButton.tabButton:checked { - background-color: #4a9eff; - color: #ffffff; - font-weight: bold; - border-color: #4a9eff; -} - -QPushButton.tabButton:hover:!checked { - background-color: #4d4d4d; - border-color: #5d5d5d; -} - -QPushButton.tabButton:pressed { - background-color: #2980b9; -} - -QTabWidget { - background-color: #2b2b2b; - border: none; -} - -QTabWidget::pane { - border: 1px solid #3d3d3d; - background-color: #2b2b2b; - border-radius: 8px; - margin: 0px; - padding: 0px; -} - -QTabWidget::tab-bar { - alignment: left; -} - -QTabBar { - background-color: #2b2b2b; - border: none; -} - -QTabBar::tab { - background-color: #383838; - color: #ffffff; - padding: 12px 20px; - margin-right: 2px; - margin-bottom: 2px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - min-width: 100px; - font-weight: 500; - border: 1px solid #3d3d3d; - border-bottom: none; -} - -QTabBar::tab:selected { - background-color: #4a9eff; - color: #ffffff; - font-weight: bold; - border-color: #4a9eff; -} - -QTabBar::tab:hover:!selected { - background-color: #4d4d4d; - border-color: #5d5d5d; -} - -QTabBar QToolButton { - background-color: #383838; - border: 1px solid #3d3d3d; - border-radius: 4px; - padding: 4px; - margin: 2px; -} - -QTabBar QToolButton:hover { - background-color: #4d4d4d; - border-color: #4a9eff; -} - -QTabBar::scroller { - width: 30px; -} - -QGroupBox { - font-weight: bold; - border: 1px solid #3d3d3d; - border-radius: 8px; - margin-top: 12px; - padding-top: 12px; - background-color: #2b2b2b; - color: #ffffff; -} - -QGroupBox::title { - subcontrol-origin: margin; - left: 12px; - padding: 0 8px 0 8px; - color: #ffffff; - font-weight: bold; -} - -QCheckBox { - color: #ffffff; - spacing: 10px; - padding: 4px; - background-color: transparent; -} - -QCheckBox::indicator { - width: 18px; - height: 18px; - border: 2px solid #5d5d5d; - border-radius: 4px; - background-color: #3d3d3d; -} - -QCheckBox::indicator:checked { - background-color: #4a9eff; - border-color: #4a9eff; -} - -QCheckBox::indicator:hover { - border-color: #4a9eff; -} - -QComboBox { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - padding: 8px 12px; - color: #ffffff; - min-width: 120px; - min-height: 28px; - selection-background-color: #4a9eff; -} - -QComboBox:hover { - border-color: #4a9eff; - background-color: #404040; -} - -QComboBox:focus { - border-color: #4a9eff; - background-color: #404040; -} - -QComboBox::drop-down { - border: none; - width: 25px; - subcontrol-origin: padding; - subcontrol-position: top right; - background-color: transparent; -} - -QComboBox::down-arrow { - width: 12px; - height: 12px; - background-color: #ffffff; -} - -QComboBox QAbstractItemView { - background-color: #3d3d3d; - border: 1px solid #4a9eff; - selection-background-color: #4a9eff; - color: #ffffff; - outline: none; -} - -QComboBox QAbstractItemView::item { - padding: 8px; - border: none; - background-color: transparent; -} - -QComboBox QAbstractItemView::item:selected { - background-color: #4a9eff; - color: #ffffff; -} - -QComboBox QAbstractItemView::item:hover { - background-color: #5dafff; - color: #ffffff; -} - -QLineEdit { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - padding: 8px 12px; - color: #ffffff; - min-height: 20px; - selection-background-color: #4a9eff; -} - -QLineEdit:focus { - border-color: #4a9eff; - background-color: #404040; -} - -QPushButton { - background-color: #4a9eff; - color: #ffffff; - border: none; - padding: 10px 20px; - border-radius: 6px; - font-weight: bold; - min-height: 20px; -} - -QPushButton:hover { - background-color: #5dafff; -} - -QPushButton:pressed { - background-color: #2980b9; -} - -QPushButton:disabled { - background-color: #5d5d5d; - color: #8d8d8d; -} - -QToolButton { - background-color: #4a9eff; - color: #ffffff; - border: none; - padding: 8px 12px; - border-radius: 6px; - font-weight: bold; - min-width: 32px; - min-height: 24px; -} - -QToolButton:hover { - background-color: #5dafff; -} - -QToolButton:pressed { - background-color: #2980b9; -} - -QLabel { - color: #ffffff; - background-color: transparent; - padding: 2px; -} - -QListWidget { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - color: #ffffff; - padding: 4px; -} - -QListWidget::item { - padding: 8px; - border-radius: 4px; - margin: 1px; -} - -QListWidget::item:selected { - background-color: #4a9eff; - color: #ffffff; -} - -QListWidget::item:hover:!selected { - background-color: #4d4d4d; -} - -QSlider::groove:horizontal { - border: 1px solid #5d5d5d; - height: 8px; - background-color: #3d3d3d; - border-radius: 4px; -} - -QSlider::handle:horizontal { - background-color: #4a9eff; - border: 1px solid #4a9eff; - width: 18px; - margin: -5px 0; - border-radius: 9px; -} - -QSlider::handle:horizontal:hover { - background-color: #5dafff; -} - -QSpinBox, QDoubleSpinBox { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - padding: 6px; - color: #ffffff; - min-height: 20px; -} - -QSpinBox:focus, QDoubleSpinBox:focus { - border-color: #4a9eff; - background-color: #404040; -} - -QRadioButton { - color: #ffffff; - spacing: 8px; - padding: 4px; -} - -QRadioButton::indicator { - width: 16px; - height: 16px; - border: 2px solid #5d5d5d; - border-radius: 8px; - background-color: #3d3d3d; -} - -QRadioButton::indicator:checked { - background-color: #4a9eff; - border-color: #4a9eff; -} - -QRadioButton::indicator:hover { - border-color: #4a9eff; -} - -/* High DPI specific styles */ -@media (min-resolution: 192dpi) { - QPushButton.tabButton { - padding: 12px 16px; - min-width: 90px; - max-width: 170px; - font-size: 14px; - } - - QComboBox { - min-width: 140px; - min-height: 32px; - padding: 10px 14px; - } - - QLineEdit { - min-height: 24px; - padding: 10px 14px; - } - - QPushButton { - min-height: 24px; - padding: 12px 24px; - } - - QCheckBox::indicator { - width: 20px; - height: 20px; - } - - QRadioButton::indicator { - width: 18px; - height: 18px; - } -} - -@media (min-resolution: 240dpi) { - QPushButton.tabButton { - padding: 14px 18px; - min-width: 95px; - max-width: 180px; - font-size: 16px; - } - - QComboBox { - min-width: 160px; - min-height: 36px; - padding: 12px 16px; - } - - QLineEdit { - min-height: 28px; - padding: 12px 16px; - } - - QPushButton { - min-height: 28px; - padding: 14px 28px; - } - - QCheckBox::indicator { - width: 22px; - height: 22px; - } - - QRadioButton::indicator { - width: 20px; - height: 20px; - } -} - - - - - 8 - - - 12 - - - 12 - - - 12 - - - 12 - - - - - 8 - - - - - 4 - - - - - General - - - true - - - true - - - tabButton - - - - - - - UI - - - true - - - tabButton - - - - - - - System - - - true - - - tabButton - - - - - - - CPU - - - true - - - tabButton - - - - - - - Graphics - - - true - - - tabButton - - - - - - - Graphics (Adv) - - - true - - - tabButton - - - - - - - Audio - - - true - - - tabButton - - - - - - - Input - - - true - - - tabButton - - - - - - - Hotkeys - - - true - - - tabButton - - - - - - - Network - - - true - - - tabButton - - - - - - - Web - - - true - - - tabButton - - - - - - - Filesystem - - - true - - - tabButton - - - - - - - Profiles - - - true - - - tabButton - - - - - - - Applets - - - true - - - tabButton - - - - - - - Logging - - - true - - - tabButton - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 0 - 0 - - - - 0 - - - - - - - - - 12 - - - 8 - - - 8 - - - 8 - - - 0 - - - - - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - ConfigureDialog - accept() - - - 20 - 20 - - - 20 - 20 - - - - - buttonBox - rejected() - ConfigureDialog - reject() - - - 20 - 20 - - - 20 - 20 - - - - + ConfigureDialog + + + + 0 + 0 + 1400 + 900 + + + + + 0 + 0 + + + + Qt::ApplicationModal + + + citron Configuration + + + + + + QDialog { + background-color: #2b2b2b; + color: #ffffff; + } + + QWidget { + background-color: #2b2b2b; + color: #ffffff; + } + + QStackedWidget { + background-color: #2b2b2b; + border: 1px solid #3d3d3d; + border-radius: 8px; + margin: 0px; + padding: 0px; + } + + QScrollArea { + background-color: #2b2b2b; + border: none; + border-radius: 8px; + } + + QScrollArea > QWidget > QWidget { + background-color: #2b2b2b; + } + + QScrollBar:vertical { + background-color: #3d3d3d; + width: 14px; + border-radius: 7px; + margin: 2px; + } + + QScrollBar::handle:vertical { + background-color: #5d5d5d; + border-radius: 6px; + min-height: 30px; + margin: 1px; + } + + QScrollBar::handle:vertical:hover { + background-color: %%ACCENT_COLOR%%; + } + + QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { + border: none; + background: none; + height: 0px; + } + + QScrollBar:horizontal { + background-color: #3d3d3d; + height: 14px; + border-radius: 7px; + margin: 2px; + } + + QScrollBar::handle:horizontal { + background-color: #5d5d5d; + border-radius: 6px; + min-width: 30px; + margin: 1px; + } + + QScrollBar::handle:horizontal:hover { + background-color: %%ACCENT_COLOR%%; + } + + QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { + border: none; + background: none; + width: 0px; + } + + QPushButton.tabButton { + background-color: #383838; + color: #ffffff; + padding: 10px 14px; + margin: 2px; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + border-bottom-left-radius: 8px; + border-bottom-right-radius: 8px; + min-width: 85px; + max-width: 160px; + font-weight: 500; + border: 1px solid #3d3d3d; + text-align: center; + } + + QPushButton.tabButton:checked { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + font-weight: bold; + border-color: %%ACCENT_COLOR%%; + } + + QPushButton.tabButton:hover:!checked { + background-color: #4d4d4d; + border-color: #5d5d5d; + } + + QPushButton.tabButton:pressed { + background-color: %%ACCENT_COLOR_PRESSED%%; + } + + QTabWidget { + background-color: #2b2b2b; + border: none; + } + + QTabWidget::pane { + border: 1px solid #3d3d3d; + background-color: #2b2b2b; + border-radius: 8px; + margin: 0px; + padding: 0px; + } + + QTabWidget::tab-bar { + alignment: left; + } + + QTabBar { + background-color: #2b2b2b; + border: none; + } + + QTabBar::tab { + background-color: #383838; + color: #ffffff; + padding: 12px 20px; + margin-right: 2px; + margin-bottom: 2px; + border-top-left-radius: 8px; + border-top-right-radius: 8px; + min-width: 100px; + font-weight: 500; + border: 1px solid #3d3d3d; + border-bottom: none; + } + + QTabBar::tab:selected { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + font-weight: bold; + border-color: %%ACCENT_COLOR%%; + } + + QTabBar::tab:hover:!selected { + background-color: #4d4d4d; + border-color: #5d5d5d; + } + + QTabBar QToolButton { + background-color: #383838; + border: 1px solid #3d3d3d; + border-radius: 4px; + padding: 4px; + margin: 2px; + } + + QTabBar QToolButton:hover { + background-color: #4d4d4d; + border-color: %%ACCENT_COLOR%%; + } + + QTabBar::scroller { + width: 30px; + } + + QGroupBox { + font-weight: bold; + border: 1px solid #3d3d3d; + border-radius: 8px; + margin-top: 12px; + padding-top: 12px; + background-color: #2b2b2b; + color: #ffffff; + } + + QGroupBox::title { + subcontrol-origin: margin; + left: 12px; + padding: 0 8px 0 8px; + color: #ffffff; + font-weight: bold; + } + + QCheckBox { + color: #ffffff; + spacing: 10px; + padding: 4px; + background-color: transparent; + } + + QCheckBox::indicator { + width: 18px; + height: 18px; + border: 2px solid #5d5d5d; + border-radius: 4px; + background-color: #3d3d3d; + } + + QCheckBox::indicator:checked { + background-color: %%ACCENT_COLOR%%; + border-color: %%ACCENT_COLOR%%; + } + + QCheckBox::indicator:hover { + border-color: %%ACCENT_COLOR%%; + } + + QComboBox { + background-color: #3d3d3d; + border: 1px solid #5d5d5d; + border-radius: 6px; + padding: 8px 12px; + color: #ffffff; + min-width: 120px; + min-height: 28px; + selection-background-color: %%ACCENT_COLOR%%; + } + + QComboBox:hover { + border-color: %%ACCENT_COLOR%%; + background-color: #404040; + } + + QComboBox:focus { + border-color: %%ACCENT_COLOR%%; + background-color: #404040; + } + + QComboBox::drop-down { + border: none; + width: 25px; + subcontrol-origin: padding; + subcontrol-position: top right; + background-color: transparent; + } + + QComboBox::down-arrow { + width: 12px; + height: 12px; + background-color: #ffffff; + } + + QComboBox QAbstractItemView { + background-color: #3d3d3d; + border: 1px solid %%ACCENT_COLOR%%; + selection-background-color: %%ACCENT_COLOR%%; + color: #ffffff; + outline: none; + } + + QComboBox QAbstractItemView::item { + padding: 8px; + border: none; + background-color: transparent; + } + + QComboBox QAbstractItemView::item:selected { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + } + + QComboBox QAbstractItemView::item:hover { + background-color: %%ACCENT_COLOR_HOVER%%; + color: #ffffff; + } + + QLineEdit { + background-color: #3d3d3d; + border: 1px solid #5d5d5d; + border-radius: 6px; + padding: 8px 12px; + color: #ffffff; + min-height: 20px; + selection-background-color: %%ACCENT_COLOR%%; + } + + QLineEdit:focus { + border-color: %%ACCENT_COLOR%%; + background-color: #404040; + } + + QPushButton { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + border: none; + padding: 10px 20px; + border-radius: 6px; + font-weight: bold; + min-height: 20px; + } + + QPushButton:hover { + background-color: %%ACCENT_COLOR_HOVER%%; + } + + QPushButton:pressed { + background-color: %%ACCENT_COLOR_PRESSED%%; + } + + QPushButton:disabled { + background-color: #5d5d5d; + color: #8d8d8d; + } + + QToolButton { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + border: none; + padding: 8px 12px; + border-radius: 6px; + font-weight: bold; + min-width: 32px; + min-height: 24px; + } + + QToolButton:hover { + background-color: %%ACCENT_COLOR_HOVER%%; + } + + QToolButton:pressed { + background-color: %%ACCENT_COLOR_PRESSED%%; + } + + QLabel { + color: #ffffff; + background-color: transparent; + padding: 2px; + } + + QListWidget { + background-color: #3d3d3d; + border: 1px solid #5d5d5d; + border-radius: 6px; + color: #ffffff; + padding: 4px; + } + + QListWidget::item { + padding: 8px; + border-radius: 4px; + margin: 1px; + } + + QListWidget::item:selected { + background-color: %%ACCENT_COLOR%%; + color: #ffffff; + } + + QListWidget::item:hover:!selected { + background-color: #4d4d4d; + } + + QSlider::groove:horizontal { + border: 1px solid #5d5d5d; + height: 8px; + background-color: #3d3d3d; + border-radius: 4px; + } + + QSlider::handle:horizontal { + background-color: %%ACCENT_COLOR%%; + border: 1px solid %%ACCENT_COLOR%%; + width: 18px; + margin: -5px 0; + border-radius: 9px; + } + + QSlider::handle:horizontal:hover { + background-color: %%ACCENT_COLOR_HOVER%%; + } + + QSpinBox, QDoubleSpinBox { + background-color: #3d3d3d; + border: 1px solid #5d5d5d; + border-radius: 6px; + padding: 6px; + color: #ffffff; + min-height: 20px; + } + + QSpinBox:focus, QDoubleSpinBox:focus { + border-color: %%ACCENT_COLOR%%; + background-color: #404040; + } + + QRadioButton { + color: #ffffff; + spacing: 8px; + padding: 4px; + } + + QRadioButton::indicator { + width: 16px; + height: 16px; + border: 2px solid #5d5d5d; + border-radius: 8px; + background-color: #3d3d3d; + } + + QRadioButton::indicator:checked { + background-color: %%ACCENT_COLOR%%; + border-color: %%ACCENT_COLOR%%; + } + + QRadioButton::indicator:hover { + border-color: %%ACCENT_COLOR%%; + } + + /* High DPI specific styles */ + @media (min-resolution: 192dpi) { + QPushButton.tabButton { + padding: 12px 16px; + min-width: 90px; + max-width: 170px; + font-size: 14px; + } + + QComboBox { + min-width: 140px; + min-height: 32px; + padding: 10px 14px; + } + + QLineEdit { + min-height: 24px; + padding: 10px 14px; + } + + QPushButton { + min-height: 24px; + padding: 12px 24px; + } + + QCheckBox::indicator { + width: 20px; + height: 20px; + } + + QRadioButton::indicator { + width: 18px; + height: 18px; + } + } + + @media (min-resolution: 240dpi) { + QPushButton.tabButton { + padding: 14px 18px; + min-width: 95px; + max-width: 180px; + font-size: 16px; + } + + QComboBox { + min-width: 160px; + min-height: 36px; + padding: 12px 16px; + } + + QLineEdit { + min-height: 28px; + padding: 12px 16px; + } + + QPushButton { + min-height: 28px; + padding: 14px 28px; + } + + QCheckBox::indicator { + width: 22px; + height: 22px; + } + + QRadioButton::indicator { + width: 20px; + height: 20px; + } + } + + + + + 8 + + + 12 + + + 12 + + + 12 + + + 12 + + + + + 8 + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAsNeeded + + + true + + + + + 0 + 0 + 1376 + 51 + + + + + 4 + + + + + General + + + true + + + true + + + tabButton + + + + + + + UI + + + true + + + tabButton + + + + + + + System + + + true + + + tabButton + + + + + + + CPU + + + true + + + tabButton + + + + + + + Graphics + + + true + + + tabButton + + + + + + + Graphics (Adv) + + + true + + + tabButton + + + + + + + Audio + + + true + + + tabButton + + + + + + + Input + + + true + + + tabButton + + + + + + + Hotkeys + + + true + + + tabButton + + + + + + + Network + + + true + + + tabButton + + + + + + + Web + + + true + + + tabButton + + + + + + + Filesystem + + + true + + + tabButton + + + + + + + Profiles + + + true + + + tabButton + + + + + + + Applets + + + true + + + tabButton + + + + + + + Logging + + + true + + + tabButton + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + true + + + + + 0 + 0 + 1376 + 745 + + + + + + + + 0 + 0 + + + + 0 + + + + + + + + + + + + + 12 + + + 8 + + + 8 + + + 8 + + + 0 + + + + + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + ConfigureDialog + accept() + + + 20 + 20 + + + 20 + 20 + + + + + buttonBox + rejected() + ConfigureDialog + reject() + + + 20 + 20 + + + 20 + 20 + + + + From 5a6c790a11d47c3ec4942586c877de0e3ee79b80 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:35:35 +0000 Subject: [PATCH 05/10] Edit configure_ui.ui --- src/citron/configuration/configure_ui.ui | 1202 ++++++++++------------ 1 file changed, 556 insertions(+), 646 deletions(-) diff --git a/src/citron/configuration/configure_ui.ui b/src/citron/configuration/configure_ui.ui index 0d889fe34..c035ebe3b 100644 --- a/src/citron/configuration/configure_ui.ui +++ b/src/citron/configuration/configure_ui.ui @@ -1,659 +1,569 @@ - ConfigureUi - - - - 0 - 0 - 1200 - 800 - - - - - 1000 - 600 - - - - Form - - - UI - - - QWidget { - background-color: #2b2b2b; - color: #ffffff; -} - -QGroupBox { - font-weight: bold; - border: 1px solid #3d3d3d; - border-radius: 8px; - margin-top: 12px; - padding-top: 12px; - background-color: #2b2b2b; -} - -QGroupBox::title { - subcontrol-origin: margin; - left: 12px; - padding: 0 8px 0 8px; - color: #ffffff; -} - -QCheckBox { - color: #ffffff; - spacing: 12px; - padding: 6px; - background-color: transparent; - min-height: 24px; -} - -QCheckBox::indicator { - width: 18px; - height: 18px; - border: 2px solid #5d5d5d; - border-radius: 4px; - background-color: #3d3d3d; -} - -QCheckBox::indicator:checked { - background-color: #4a9eff; - border-color: #4a9eff; -} - -QCheckBox::indicator:hover { - border-color: #4a9eff; -} - -QComboBox { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - padding: 8px 12px; - color: #ffffff; - min-width: 160px; - min-height: 28px; -} - -QComboBox:hover { - border-color: #4a9eff; - background-color: #404040; -} - -QComboBox:focus { - border-color: #4a9eff; - background-color: #404040; -} - -QComboBox::drop-down { - border: none; - width: 24px; - subcontrol-origin: padding; - subcontrol-position: top right; -} - -QComboBox::down-arrow { - width: 12px; - height: 12px; -} - -QComboBox QAbstractItemView { - background-color: #3d3d3d; - border: 1px solid #4a9eff; - selection-background-color: #4a9eff; - color: #ffffff; -} - -QLineEdit { - background-color: #3d3d3d; - border: 1px solid #5d5d5d; - border-radius: 6px; - padding: 8px 12px; - color: #ffffff; - min-height: 28px; -} - -QLineEdit:focus { - border-color: #4a9eff; - background-color: #404040; -} - -QToolButton { - background-color: #4a9eff; - color: #ffffff; - border: none; - padding: 8px 12px; - border-radius: 6px; - font-weight: bold; - min-width: 40px; - min-height: 32px; -} - -QToolButton:hover { - background-color: #5dafff; -} - -QToolButton:pressed { - background-color: #2980b9; -} - -QLabel { - color: #ffffff; - background-color: transparent; - padding: 4px; - min-width: 140px; -} - - - - - 32 - - - 32 - - - 32 - - - 32 - - - 32 - - - - - 20 - - - - - General - - - - 500 - 0 - - - - - 12 + ConfigureUi + + + + 0 + 0 + 1200 + 800 + - - 20 + + + 1000 + 600 + - - 20 + + Form - - 20 + + UI - - 20 + + /* This stylesheet is a template. Placeholders like %%ACCENT_COLOR%% are replaced in C++. */ - - - - Note: Changing language will apply your configuration. - - - true - - - color: #cccccc; font-size: 11px; - - - - - - - 16 - - - - - Interface language: + + + 32 - - - 140 - 0 - + + 32 - - - - - - - 0 - 0 - + + 32 - - - - - - - - 16 - - - - - Theme: + + 32 - - - 140 - 0 - + + 32 - - - - - - - 0 - 0 - - - - - - - - - - - - - Game List - - - - 500 - 0 - - - - - 12 - - - 20 - - - 20 - - - 20 - - - 20 - - - - - Show Compatibility List - - - - 0 - 32 - - - - - - - - Show Add-Ons Column - - - - 0 - 32 - - - - - - - - Show Size Column - - - - 0 - 32 - - - - - - - - Show File Types Column - - - - 0 - 32 - - - - - - - - Show Play Time Column - - - - 0 - 32 - - - - - - - - 16 - - - - - Game Icon Size: - - - - 140 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - 16 - - - - - Folder Icon Size: - - - - 140 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - 16 - - - - - Row 1 Text: - - - - 140 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - 16 - - - - - Row 2 Text: - - - - 140 - 0 - - - - - - - - - 0 - 0 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - 20 - - - - - Screenshots - - - - 500 - 0 - - - - - 16 - - - 20 - - - 20 - - - 20 - - - 20 - - - - - Ask Where To Save Screenshots (Windows Only) - - - - 0 - 32 - - - - - - - - 12 - - - - - Screenshots Path: - - - - 140 - 0 - - - - - - - - - 0 - 0 - - - - - - - - ... - - - - - - - - - 12 - - - - - Resolution: - - - - 80 - 0 - - - - - - - - TextLabel - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - 120 - 0 - - - - - - - - true - - - - 0 - 0 - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - + + + + 20 + + + + + General + + + + 500 + 0 + + + + + 12 + + + 20 + + + 20 + + + 20 + + + 20 + + + + + Note: Changing language will apply your configuration. + + + true + + + color: #cccccc; font-size: 11px; + + + + + + + 16 + + + + + Interface language: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + 16 + + + + + Theme: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + 16 + + + + + Accent Color: + + + + 140 + 0 + + + + + + + + Choose Color... + + + + + + + Enable Rainbow Mode + + + + + + + + + + + + Game List + + + + 500 + 0 + + + + + 12 + + + 20 + + + 20 + + + 20 + + + 20 + + + + + Show Compatibility List + + + + 0 + 32 + + + + + + + + Show Add-Ons Column + + + + 0 + 32 + + + + + + + + Show Size Column + + + + 0 + 32 + + + + + + + + Show File Types Column + + + + 0 + 32 + + + + + + + + Show Play Time Column + + + + 0 + 32 + + + + + + + + 16 + + + + + Game Icon Size: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + 16 + + + + + Folder Icon Size: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + 16 + + + + + Row 1 Text: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + 16 + + + + + Row 2 Text: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 20 + + + + + Screenshots + + + + 500 + 0 + + + + + 16 + + + 20 + + + 20 + + + 20 + + + 20 + + + + + Ask Where To Save Screenshots (Windows Only) + + + + 0 + 32 + + + + + + + + 12 + + + + + Screenshots Path: + + + + 140 + 0 + + + + + + + + + 0 + 0 + + + + + + + + ... + + + + + + + + + 12 + + + + + Resolution: + + + + 80 + 0 + + + + + + + + TextLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + 120 + 0 + + + + + + + + true + + + + 0 + 0 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + From 4fabdfd9a9917018c36bfeacf51638dae41a7ecd Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:36:10 +0000 Subject: [PATCH 06/10] Edit configure_ui.h --- src/citron/configuration/configure_ui.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/citron/configuration/configure_ui.h b/src/citron/configuration/configure_ui.h index 2a2563a13..a66c12cb9 100644 --- a/src/citron/configuration/configure_ui.h +++ b/src/citron/configuration/configure_ui.h @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project +// SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -8,11 +9,11 @@ #include "common/settings_enums.h" namespace Core { -class System; + class System; } namespace Ui { -class ConfigureUi; + class ConfigureUi; } class ConfigureUi : public QWidget { @@ -27,11 +28,13 @@ public: void UpdateScreenshotInfo(Settings::AspectRatio ratio, Settings::ResolutionSetup resolution_info); -private slots: - void OnLanguageChanged(int index); - signals: void LanguageChanged(const QString& locale); + void themeChanged(); + +private slots: + void OnLanguageChanged(int index); + void OnAccentColorButtonPressed(); private: void RequestGameListUpdate(); From a5d3efa8da96617d31e96cc4f87cae4b1dd252e2 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:37:07 +0000 Subject: [PATCH 07/10] Edit configure_ui.cpp --- src/citron/configuration/configure_ui.cpp | 143 ++++++++++++---------- 1 file changed, 80 insertions(+), 63 deletions(-) diff --git a/src/citron/configuration/configure_ui.cpp b/src/citron/configuration/configure_ui.cpp index a77efffdf..da8e6ba85 100644 --- a/src/citron/configuration/configure_ui.cpp +++ b/src/citron/configuration/configure_ui.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -33,42 +34,42 @@ #include "citron/uisettings.h" namespace { -constexpr std::array default_game_icon_sizes{ - std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")), - std::make_pair(32, QT_TRANSLATE_NOOP("ConfigureUI", "Small (32x32)")), - std::make_pair(64, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (64x64)")), - std::make_pair(128, QT_TRANSLATE_NOOP("ConfigureUI", "Large (128x128)")), - std::make_pair(256, QT_TRANSLATE_NOOP("ConfigureUI", "Full Size (256x256)")), -}; + constexpr std::array default_game_icon_sizes{ + std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")), + std::make_pair(32, QT_TRANSLATE_NOOP("ConfigureUI", "Small (32x32)")), + std::make_pair(64, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (64x64)")), + std::make_pair(128, QT_TRANSLATE_NOOP("ConfigureUI", "Large (128x128)")), + std::make_pair(256, QT_TRANSLATE_NOOP("ConfigureUI", "Full Size (256x256)")), + }; -constexpr std::array default_folder_icon_sizes{ - std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")), - std::make_pair(24, QT_TRANSLATE_NOOP("ConfigureUI", "Small (24x24)")), - std::make_pair(48, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (48x48)")), - std::make_pair(72, QT_TRANSLATE_NOOP("ConfigureUI", "Large (72x72)")), -}; + constexpr std::array default_folder_icon_sizes{ + std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")), + std::make_pair(24, QT_TRANSLATE_NOOP("ConfigureUI", "Small (24x24)")), + std::make_pair(48, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (48x48)")), + std::make_pair(72, QT_TRANSLATE_NOOP("ConfigureUI", "Large (72x72)")), + }; -// clang-format off -constexpr std::array row_text_names{ - QT_TRANSLATE_NOOP("ConfigureUI", "Filename"), - QT_TRANSLATE_NOOP("ConfigureUI", "Filetype"), - QT_TRANSLATE_NOOP("ConfigureUI", "Title ID"), - QT_TRANSLATE_NOOP("ConfigureUI", "Title Name"), - QT_TRANSLATE_NOOP("ConfigureUI", "None"), -}; -// clang-format on + // clang-format off + constexpr std::array row_text_names{ + QT_TRANSLATE_NOOP("ConfigureUI", "Filename"), + QT_TRANSLATE_NOOP("ConfigureUI", "Filetype"), + QT_TRANSLATE_NOOP("ConfigureUI", "Title ID"), + QT_TRANSLATE_NOOP("ConfigureUI", "Title Name"), + QT_TRANSLATE_NOOP("ConfigureUI", "None"), + }; + // clang-format on -QString GetTranslatedGameIconSize(size_t index) { - return QCoreApplication::translate("ConfigureUI", default_game_icon_sizes[index].second); -} + QString GetTranslatedGameIconSize(size_t index) { + return QCoreApplication::translate("ConfigureUI", default_game_icon_sizes[index].second); + } -QString GetTranslatedFolderIconSize(size_t index) { - return QCoreApplication::translate("ConfigureUI", default_folder_icon_sizes[index].second); -} + QString GetTranslatedFolderIconSize(size_t index) { + return QCoreApplication::translate("ConfigureUI", default_folder_icon_sizes[index].second); + } -QString GetTranslatedRowTextName(size_t index) { - return QCoreApplication::translate("ConfigureUI", row_text_names[index]); -} + QString GetTranslatedRowTextName(size_t index) { + return QCoreApplication::translate("ConfigureUI", row_text_names[index]); + } } // Anonymous namespace static float GetUpFactor(Settings::ResolutionSetup res_setup) { @@ -81,7 +82,7 @@ static void PopulateResolutionComboBox(QComboBox* screenshot_height, QWidget* pa screenshot_height->clear(); const auto& enumeration = - Settings::EnumMetadata::Canonicalizations(); + Settings::EnumMetadata::Canonicalizations(); std::set resolutions{}; for (const auto& [name, value] : enumeration) { const float up_factor = GetUpFactor(value); @@ -102,9 +103,9 @@ static u32 ScreenshotDimensionToInt(const QString& height) { } ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent) - : QWidget(parent), ui{std::make_unique()}, - ratio{Settings::values.aspect_ratio.GetValue()}, - resolution_setting{Settings::values.resolution_setup.GetValue()}, system{system_} { +: QWidget(parent), ui{std::make_unique()}, +ratio{Settings::values.aspect_ratio.GetValue()}, +resolution_setting{Settings::values.resolution_setup.GetValue()}, system{system_} { ui->setupUi(this); InitializeLanguageComboBox(); @@ -121,34 +122,39 @@ ConfigureUi::ConfigureUi(Core::System& system_, QWidget* parent) SetConfiguration(); + connect(ui->accentColorButton, &QPushButton::clicked, this, &ConfigureUi::OnAccentColorButtonPressed); + connect(ui->rainbowModeCheckBox, &QCheckBox::checkStateChanged, this, [this](int state) { + emit themeChanged(); + }); + // Force game list reload if any of the relevant settings are changed. - connect(ui->show_add_ons, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->show_compat, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->show_size, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->show_types, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->show_play_time, &QCheckBox::stateChanged, this, + connect(ui->show_add_ons, &QCheckBox::checkStateChanged, this, &ConfigureUi::RequestGameListUpdate); + connect(ui->show_compat, &QCheckBox::checkStateChanged, this, &ConfigureUi::RequestGameListUpdate); + connect(ui->show_size, &QCheckBox::checkStateChanged, this, &ConfigureUi::RequestGameListUpdate); + connect(ui->show_types, &QCheckBox::checkStateChanged, this, &ConfigureUi::RequestGameListUpdate); + connect(ui->show_play_time, &QCheckBox::checkStateChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->game_icon_size_combobox, QOverload::of(&QComboBox::currentIndexChanged), this, + connect(ui->game_icon_size_combobox, &QComboBox::currentIndexChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->folder_icon_size_combobox, QOverload::of(&QComboBox::currentIndexChanged), + connect(ui->folder_icon_size_combobox, &QComboBox::currentIndexChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->row_1_text_combobox, QOverload::of(&QComboBox::currentIndexChanged), this, + connect(ui->row_1_text_combobox, &QComboBox::currentIndexChanged, this, &ConfigureUi::RequestGameListUpdate); - connect(ui->row_2_text_combobox, QOverload::of(&QComboBox::currentIndexChanged), this, + connect(ui->row_2_text_combobox, &QComboBox::currentIndexChanged, this, &ConfigureUi::RequestGameListUpdate); // Update text ComboBoxes after user interaction. - connect(ui->row_1_text_combobox, QOverload::of(&QComboBox::activated), + connect(ui->row_1_text_combobox, &QComboBox::activated, [this] { ConfigureUi::UpdateSecondRowComboBox(); }); - connect(ui->row_2_text_combobox, QOverload::of(&QComboBox::activated), + connect(ui->row_2_text_combobox, &QComboBox::activated, [this] { ConfigureUi::UpdateFirstRowComboBox(); }); // Set screenshot path to user specification. connect(ui->screenshot_path_button, &QToolButton::pressed, this, [this] { auto dir = - QFileDialog::getExistingDirectory(this, tr("Select Screenshots Path..."), - QString::fromStdString(Common::FS::GetCitronPathString( - Common::FS::CitronPath::ScreenshotsDir))); + QFileDialog::getExistingDirectory(this, tr("Select Screenshots Path..."), + QString::fromStdString(Common::FS::GetCitronPathString( + Common::FS::CitronPath::ScreenshotsDir))); if (!dir.isEmpty()) { if (dir.back() != QChar::fromLatin1('/')) { dir.append(QChar::fromLatin1('/')); @@ -167,7 +173,8 @@ ConfigureUi::~ConfigureUi() = default; void ConfigureUi::ApplyConfiguration() { UISettings::values.theme = - ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString(); + ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString().toStdString(); + UISettings::values.enable_rainbow_mode = ui->rainbowModeCheckBox->isChecked(); UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); UISettings::values.show_compat = ui->show_compat->isChecked(); UISettings::values.show_size = ui->show_size->isChecked(); @@ -180,7 +187,7 @@ void ConfigureUi::ApplyConfiguration() { UISettings::values.enable_screenshot_save_as = ui->enable_screenshot_save_as->isChecked(); Common::FS::SetCitronPath(Common::FS::CitronPath::ScreenshotsDir, - ui->screenshot_path_edit->text().toStdString()); + ui->screenshot_path_edit->text().toStdString()); const u32 height = ScreenshotDimensionToInt(ui->screenshot_height->currentText()); UISettings::values.screenshot_height.SetValue(height); @@ -198,6 +205,7 @@ void ConfigureUi::SetConfiguration() { ui->theme_combobox->findData(QString::fromStdString(UISettings::values.theme))); ui->language_combobox->setCurrentIndex(ui->language_combobox->findData( QString::fromStdString(UISettings::values.language.GetValue()))); + ui->rainbowModeCheckBox->setChecked(UISettings::values.enable_rainbow_mode.GetValue()); ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); ui->show_compat->setChecked(UISettings::values.show_compat.GetValue()); ui->show_size->setChecked(UISettings::values.show_size.GetValue()); @@ -221,6 +229,18 @@ void ConfigureUi::SetConfiguration() { } } +void ConfigureUi::OnAccentColorButtonPressed() { + const QColor current_color(QString::fromStdString(UISettings::values.accent_color.GetValue())); + QColorDialog dialog(current_color, this); + if (dialog.exec() == QDialog::Accepted) { + const QColor color = dialog.selectedColor(); + if (color.isValid()) { + UISettings::values.accent_color.SetValue(color.name().toStdString()); + emit themeChanged(); + } + } +} + void ConfigureUi::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { RetranslateUI(); @@ -263,10 +283,7 @@ void ConfigureUi::InitializeLanguageComboBox() { ui->language_combobox->addItem(QStringLiteral("%1 (%2)").arg(lang, country), locale); } - // Unlike other configuration changes, interface language changes need to be reflected on the - // interface immediately. This is done by passing a signal to the main window, and then - // retranslating when passing back. - connect(ui->language_combobox, qOverload(&QComboBox::currentIndexChanged), this, + connect(ui->language_combobox, &QComboBox::currentIndexChanged, this, &ConfigureUi::OnLanguageChanged); } @@ -288,8 +305,8 @@ void ConfigureUi::InitializeRowComboBoxes() { void ConfigureUi::UpdateFirstRowComboBox(bool init) { const int currentIndex = - init ? UISettings::values.row_1_text_id.GetValue() - : ui->row_1_text_combobox->findData(ui->row_1_text_combobox->currentData()); + init ? UISettings::values.row_1_text_id.GetValue() + : ui->row_1_text_combobox->findData(ui->row_1_text_combobox->currentData()); ui->row_1_text_combobox->clear(); @@ -307,8 +324,8 @@ void ConfigureUi::UpdateFirstRowComboBox(bool init) { void ConfigureUi::UpdateSecondRowComboBox(bool init) { const int currentIndex = - init ? UISettings::values.row_2_text_id.GetValue() - : ui->row_2_text_combobox->findData(ui->row_2_text_combobox->currentData()); + init ? UISettings::values.row_2_text_id.GetValue() + : ui->row_2_text_combobox->findData(ui->row_2_text_combobox->currentData()); ui->row_2_text_combobox->clear(); @@ -340,10 +357,10 @@ void ConfigureUi::UpdateWidthText() { const u32 height_undocked = Layout::ScreenUndocked::Height * up_factor; const u32 width_undocked = UISettings::CalculateWidth(height_undocked, ratio); ui->screenshot_width->setText(tr("Auto (%1 x %2, %3 x %4)", "Screenshot width value") - .arg(width_undocked) - .arg(height_undocked) - .arg(width_docked) - .arg(height_docked)); + .arg(width_undocked) + .arg(height_undocked) + .arg(width_docked) + .arg(height_docked)); } else { ui->screenshot_width->setText(QStringLiteral("%1 x").arg(width)); } From c5260f07871484b2a25bfa0ccb10563e1ff08e8a Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:37:46 +0000 Subject: [PATCH 08/10] Edit configure_dialog.h --- src/citron/configuration/configure_dialog.h | 63 +++++++++++---------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/citron/configuration/configure_dialog.h b/src/citron/configuration/configure_dialog.h index b074541e4..a7e678acf 100644 --- a/src/citron/configuration/configure_dialog.h +++ b/src/citron/configuration/configure_dialog.h @@ -7,16 +7,25 @@ #include #include #include -#include -#include "configuration/shared_widget.h" -#include "citron/configuration/configuration_shared.h" -#include "citron/configuration/shared_translation.h" -#include "citron/vk_device_info.h" +#include "common/settings_enums.h" +#include "citron/configuration/shared_widget.h" // <-- Correct header for Builder -namespace Core { -class System; +// Forward declarations for other types +class HotkeyRegistry; +class QButtonGroup; +class QTimer; +namespace InputCommon { + class InputSubsystem; +} +namespace Core { + class System; +} +namespace VkDeviceInfo { + struct Record; +} +namespace Ui { + class ConfigureDialog; } - class ConfigureApplets; class ConfigureAudio; class ConfigureCpu; @@ -27,56 +36,45 @@ class ConfigureGraphics; class ConfigureGraphicsAdvanced; class ConfigureHotkeys; class ConfigureInput; +class ConfigureNetwork; class ConfigureProfileManager; class ConfigureSystem; -class ConfigureNetwork; class ConfigureUi; class ConfigureWeb; -class HotkeyRegistry; - -namespace InputCommon { -class InputSubsystem; -} - -namespace Ui { -class ConfigureDialog; -} - -class ConfigureDialog : public QDialog { +class ConfigureDialog final : public QDialog { Q_OBJECT public: - explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, + explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, InputCommon::InputSubsystem* input_subsystem, std::vector& vk_device_records, - Core::System& system_, bool enable_web_config = true); + Core::System& system, bool enable_web_config); + ~ConfigureDialog() override; void ApplyConfiguration(); -private slots: - void OnLanguageChanged(const QString& locale); +public slots: + void UpdateTheme(); signals: void LanguageChanged(const QString& locale); private: + void SetConfiguration(); + void HandleApplyButtonClicked(); + void changeEvent(QEvent* event) override; void RetranslateUI(); - void HandleApplyButtonClicked(); - - void SetConfiguration(); + void OnLanguageChanged(const QString& locale); + // All members are now in the EXACT correct order to match the constructor std::unique_ptr ui; HotkeyRegistry& registry; - Core::System& system; std::unique_ptr builder; - std::vector tab_group; - std::unique_ptr tab_button_group; - std::unique_ptr applets_tab; std::unique_ptr audio_tab; std::unique_ptr cpu_tab; @@ -92,4 +90,7 @@ private: std::unique_ptr profile_tab; std::unique_ptr system_tab; std::unique_ptr web_tab; + std::unique_ptr tab_button_group; + QTimer* rainbow_timer; + float rainbow_hue = 0.0f; }; From 25859593580eca6f5d5b811a5839fb771c59b770 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:38:16 +0000 Subject: [PATCH 09/10] Edit configure_dialog.cpp --- src/citron/configuration/configure_dialog.cpp | 214 ++++++++---------- 1 file changed, 91 insertions(+), 123 deletions(-) diff --git a/src/citron/configuration/configure_dialog.cpp b/src/citron/configuration/configure_dialog.cpp index df97c42a3..85f4d66cd 100644 --- a/src/citron/configuration/configure_dialog.cpp +++ b/src/citron/configuration/configure_dialog.cpp @@ -2,24 +2,27 @@ // SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "citron/configuration/configure_dialog.h" #include +#include +#include #include #include #include -#include -#include #include +#include +#include #include "common/logging/log.h" #include "common/settings.h" #include "common/settings_enums.h" #include "core/core.h" #include "ui_configure.h" #include "vk_device_info.h" +#include "citron/configuration/configuration_shared.h" // <-- Full definition included here #include "citron/configuration/configure_applets.h" #include "citron/configuration/configure_audio.h" #include "citron/configuration/configure_cpu.h" #include "citron/configuration/configure_debug_tab.h" -#include "citron/configuration/configure_dialog.h" #include "citron/configuration/configure_filesystem.h" #include "citron/configuration/configure_general.h" #include "citron/configuration/configure_graphics.h" @@ -33,9 +36,9 @@ #include "citron/configuration/configure_ui.h" #include "citron/configuration/configure_web.h" #include "citron/hotkeys.h" +#include "citron/theme.h" #include "citron/uisettings.h" -// Helper function to create a scroll area for a widget static QScrollArea* CreateScrollArea(QWidget* widget) { auto* scroll_area = new QScrollArea(); scroll_area->setWidget(widget); @@ -43,60 +46,6 @@ static QScrollArea* CreateScrollArea(QWidget* widget) { scroll_area->setFrameShape(QFrame::NoFrame); scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - - // High DPI support: Scroll area will inherit scaling from parent - - // Set style with high DPI aware styling - scroll_area->setStyleSheet(QLatin1String( - "QScrollArea { " - "border: none; " - "background-color: #2b2b2b; " - "}" - "QScrollArea > QWidget > QWidget { " - "background-color: #2b2b2b; " - "}" - "QScrollBar:vertical { " - "background-color: #3d3d3d; " - "width: 14px; " - "border-radius: 7px; " - "margin: 2px; " - "}" - "QScrollBar::handle:vertical { " - "background-color: #5d5d5d; " - "border-radius: 6px; " - "min-height: 30px; " - "margin: 1px; " - "}" - "QScrollBar::handle:vertical:hover { " - "background-color: #4a9eff; " - "}" - "QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { " - "border: none; " - "background: none; " - "height: 0px; " - "}" - "QScrollBar:horizontal { " - "background-color: #3d3d3d; " - "height: 14px; " - "border-radius: 7px; " - "margin: 2px; " - "}" - "QScrollBar::handle:horizontal { " - "background-color: #5d5d5d; " - "border-radius: 6px; " - "min-width: 30px; " - "margin: 1px; " - "}" - "QScrollBar::handle:horizontal:hover { " - "background-color: #4a9eff; " - "}" - "QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal { " - "border: none; " - "background: none; " - "width: 0px; " - "}" - )); - return scroll_area; } @@ -104,66 +53,60 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, InputCommon::InputSubsystem* input_subsystem, std::vector& vk_device_records, Core::System& system_, bool enable_web_config) - : QDialog(parent), ui{std::make_unique()}, - registry(registry_), system{system_}, builder{std::make_unique( - this, !system_.IsPoweredOn())}, - applets_tab{std::make_unique(system_, nullptr, *builder, this)}, - audio_tab{std::make_unique(system_, nullptr, *builder, this)}, - cpu_tab{std::make_unique(system_, nullptr, *builder, this)}, - debug_tab_tab{std::make_unique(system_, this)}, - filesystem_tab{std::make_unique(this)}, - general_tab{std::make_unique(system_, nullptr, *builder, this)}, - graphics_advanced_tab{ - std::make_unique(system_, nullptr, *builder, this)}, - ui_tab{std::make_unique(system_, this)}, - graphics_tab{std::make_unique( - system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, - [this](Settings::AspectRatio ratio, Settings::ResolutionSetup setup) { - ui_tab->UpdateScreenshotInfo(ratio, setup); - }, - nullptr, *builder, this)}, - hotkeys_tab{std::make_unique(system_.HIDCore(), this)}, - input_tab{std::make_unique(system_, this)}, - network_tab{std::make_unique(system_, this)}, - profile_tab{std::make_unique(system_, this)}, - system_tab{std::make_unique(system_, nullptr, *builder, this)}, - web_tab{std::make_unique(this)} { +: QDialog(parent), ui{std::make_unique()}, +registry(registry_), system{system_}, builder{std::make_unique( + this, !system_.IsPoweredOn())}, + applets_tab{std::make_unique(system_, nullptr, *builder, this)}, + audio_tab{std::make_unique(system_, nullptr, *builder, this)}, + cpu_tab{std::make_unique(system_, nullptr, *builder, this)}, + debug_tab_tab{std::make_unique(system_, this)}, + filesystem_tab{std::make_unique(this)}, + general_tab{std::make_unique(system_, nullptr, *builder, this)}, + graphics_advanced_tab{ + std::make_unique(system_, nullptr, *builder, this)}, + ui_tab{std::make_unique(system_, this)}, + graphics_tab{std::make_unique( + system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, + [this](Settings::AspectRatio ratio, Settings::ResolutionSetup setup) { + ui_tab->UpdateScreenshotInfo(ratio, setup); + }, + nullptr, *builder, this)}, +hotkeys_tab{std::make_unique(system_.HIDCore(), this)}, +input_tab{std::make_unique(system_, this)}, +network_tab{std::make_unique(system_, this)}, +profile_tab{std::make_unique(system_, this)}, +system_tab{std::make_unique(system_, nullptr, *builder, this)}, +web_tab{std::make_unique(this)}, +rainbow_timer{new QTimer(this)} { + Settings::SetConfiguringGlobal(true); - // Set window flags to include maximize button and make it resizable setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | - Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); + Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint); - // High DPI support: Set proper attributes for scaling setAttribute(Qt::WA_TranslucentBackground, false); setAttribute(Qt::WA_NoSystemBackground, false); setAttribute(Qt::WA_DontShowOnScreen, false); ui->setupUi(this); - // Set size policy and enable resizing + UpdateTheme(); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - // Get screen geometry and set to fullscreen with high DPI awareness QScreen* screen = QApplication::primaryScreen(); if (screen) { QRect screenGeometry = screen->availableGeometry(); - - // Calculate logical size based on device pixel ratio for high DPI support qreal devicePixelRatio = screen->devicePixelRatio(); int logicalWidth = static_cast(screenGeometry.width() / devicePixelRatio); int logicalHeight = static_cast(screenGeometry.height() / devicePixelRatio); - - // Set geometry using logical units setGeometry(0, 0, logicalWidth, logicalHeight); - showMaximized(); // Start maximized/fullscreen + showMaximized(); } - // Create button group for exclusive tab selection tab_button_group = std::make_unique(this); tab_button_group->setExclusive(true); - // Add tab buttons to the button group and connect to stacked widget tab_button_group->addButton(ui->generalTabButton, 0); tab_button_group->addButton(ui->uiTabButton, 1); tab_button_group->addButton(ui->systemTabButton, 2); @@ -180,31 +123,31 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, tab_button_group->addButton(ui->appletsTabButton, 13); tab_button_group->addButton(ui->loggingTabButton, 14); - // Add pages to stacked widget wrapped in scroll areas in the same order as button group - ui->stackedWidget->addWidget(CreateScrollArea(general_tab.get())); // 0 - ui->stackedWidget->addWidget(CreateScrollArea(ui_tab.get())); // 1 - ui->stackedWidget->addWidget(CreateScrollArea(system_tab.get())); // 2 - ui->stackedWidget->addWidget(CreateScrollArea(cpu_tab.get())); // 3 - ui->stackedWidget->addWidget(CreateScrollArea(graphics_tab.get())); // 4 - ui->stackedWidget->addWidget(CreateScrollArea(graphics_advanced_tab.get())); // 5 - ui->stackedWidget->addWidget(CreateScrollArea(audio_tab.get())); // 6 - ui->stackedWidget->addWidget(CreateScrollArea(input_tab.get())); // 7 - ui->stackedWidget->addWidget(CreateScrollArea(hotkeys_tab.get())); // 8 - ui->stackedWidget->addWidget(CreateScrollArea(network_tab.get())); // 9 - ui->stackedWidget->addWidget(CreateScrollArea(web_tab.get())); // 10 - ui->stackedWidget->addWidget(CreateScrollArea(filesystem_tab.get()));// 11 - ui->stackedWidget->addWidget(CreateScrollArea(profile_tab.get())); // 12 - ui->stackedWidget->addWidget(CreateScrollArea(applets_tab.get())); // 13 - ui->stackedWidget->addWidget(CreateScrollArea(debug_tab_tab.get())); // 14 + ui->stackedWidget->addWidget(CreateScrollArea(general_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(ui_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(system_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(cpu_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(graphics_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(graphics_advanced_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(audio_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(input_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(hotkeys_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(network_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(web_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(filesystem_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(profile_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(applets_tab.get())); + ui->stackedWidget->addWidget(CreateScrollArea(debug_tab_tab.get())); - // Connect button group to stacked widget - connect(tab_button_group.get(), QOverload::of(&QButtonGroup::idClicked), - [this](int id) { - ui->stackedWidget->setCurrentIndex(id); - if (id == 14) { // Logging tab - debug_tab_tab->SetCurrentIndex(0); - } - }); + connect(tab_button_group.get(), qOverload(&QButtonGroup::idClicked), this, [this](int id) { + ui->stackedWidget->setCurrentIndex(id); + if (id == 14) { + debug_tab_tab->SetCurrentIndex(0); + } + }); + + connect(ui_tab.get(), &ConfigureUi::themeChanged, this, &ConfigureDialog::UpdateTheme); + connect(rainbow_timer, &QTimer::timeout, this, &ConfigureDialog::UpdateTheme); web_tab->SetWebServiceConfigEnabled(enable_web_config); hotkeys_tab->Populate(registry); @@ -225,16 +168,43 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, } } - // Set initial tab to General (index 0) ui->stackedWidget->setCurrentIndex(0); ui->generalTabButton->setChecked(true); - - // Focus on the OK button by default ui->buttonBox->setFocus(); } +// This line defines the destructor, completing the type for std::unique_ptr ConfigureDialog::~ConfigureDialog() = default; +void ConfigureDialog::UpdateTheme() { + QString accent_color_str; + if (UISettings::values.enable_rainbow_mode.GetValue()) { + rainbow_hue += 0.005f; + if (rainbow_hue > 1.0f) { + rainbow_hue = 0.0f; + } + accent_color_str = QColor::fromHsvF(rainbow_hue, 0.8, 1.0).name(); + if (!rainbow_timer->isActive()) { + rainbow_timer->start(16); // ~60 FPS + } + } else { + if (rainbow_timer->isActive()) { + rainbow_timer->stop(); + } + accent_color_str = Theme::GetAccentColor(); + } + + QColor accent_color(accent_color_str); + QString accent_color_hover = accent_color.lighter(115).name(); + QString accent_color_pressed = accent_color.darker(120).name(); + + QString style_sheet = property("templateStyleSheet").toString(); + style_sheet.replace(QStringLiteral("%%ACCENT_COLOR%%"), accent_color_str); + style_sheet.replace(QStringLiteral("%%ACCENT_COLOR_HOVER%%"), accent_color_hover); + style_sheet.replace(QStringLiteral("%%ACCENT_COLOR_PRESSED%%"), accent_color_pressed); + setStyleSheet(style_sheet); +} + void ConfigureDialog::SetConfiguration() {} void ConfigureDialog::ApplyConfiguration() { @@ -281,9 +251,7 @@ void ConfigureDialog::HandleApplyButtonClicked() { void ConfigureDialog::OnLanguageChanged(const QString& locale) { emit LanguageChanged(locale); - // Reloading the game list is needed to force retranslation. UISettings::values.is_game_list_reload_pending = true; - // first apply the configuration, and then restore the display ApplyConfiguration(); RetranslateUI(); SetConfiguration(); From db1d69ece41db6db00944b55fd11d4d008663b90 Mon Sep 17 00:00:00 2001 From: collecting Date: Sat, 4 Oct 2025 00:39:13 +0000 Subject: [PATCH 10/10] Edit uisettings.cpp --- src/citron/uisettings.cpp | 156 +++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/src/citron/uisettings.cpp b/src/citron/uisettings.cpp index 2ac580d0d..f4db1824d 100644 --- a/src/citron/uisettings.cpp +++ b/src/citron/uisettings.cpp @@ -1,5 +1,5 @@ // SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project +// SPDX-FileCopyrightText: 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -9,13 +9,13 @@ #ifndef CANNOT_EXPLICITLY_INSTANTIATE namespace Settings { -template class Setting; -template class Setting; -template class Setting; -template class Setting; -template class Setting; -template class Setting; -template class Setting; + template class Setting; + template class Setting; + template class Setting; + template class Setting; + template class Setting; + template class Setting; + template class Setting; } // namespace Settings #endif @@ -23,93 +23,93 @@ namespace FS = Common::FS; namespace UISettings { -const Themes themes{{ - {"Default", "default"}, - {"Default Colorful", "colorful"}, - {"Dark", "qdarkstyle"}, - {"Dark Colorful", "colorful_dark"}, - {"Midnight Blue", "qdarkstyle_midnight_blue"}, - {"Midnight Blue Colorful", "colorful_midnight_blue"}, -}}; + const Themes themes{{ + {"Default", "default"}, + {"Default Colorful", "colorful"}, + {"Dark", "qdarkstyle"}, + {"Dark Colorful", "colorful_dark"}, + {"Midnight Blue", "qdarkstyle_midnight_blue"}, + {"Midnight Blue Colorful", "colorful_midnight_blue"}, + }}; -bool IsDarkTheme() { - const auto& theme = UISettings::values.theme; - return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || - theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); -} - -Values values = {}; - -u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) { - switch (ratio) { - case Settings::AspectRatio::R4_3: - return height * 4 / 3; - case Settings::AspectRatio::R21_9: - return height * 21 / 9; - case Settings::AspectRatio::R16_10: - return height * 16 / 10; - case Settings::AspectRatio::R32_9: - return height * 32 / 9; - case Settings::AspectRatio::R16_9: - case Settings::AspectRatio::Stretch: - // TODO: Move this function wherever appropriate to implement Stretched aspect - break; + bool IsDarkTheme() { + const auto& theme = UISettings::values.theme; + return theme == std::string("qdarkstyle") || theme == std::string("qdarkstyle_midnight_blue") || + theme == std::string("colorful_dark") || theme == std::string("colorful_midnight_blue"); } - return height * 16 / 9; -} -void SaveWindowState() { - const auto window_state_config_loc = + Values values = {}; + + u32 CalculateWidth(u32 height, Settings::AspectRatio ratio) { + switch (ratio) { + case Settings::AspectRatio::R4_3: + return height * 4 / 3; + case Settings::AspectRatio::R21_9: + return height * 21 / 9; + case Settings::AspectRatio::R16_10: + return height * 16 / 10; + case Settings::AspectRatio::R32_9: + return height * 32 / 9; + case Settings::AspectRatio::R16_9: + case Settings::AspectRatio::Stretch: + // TODO: Move this function wherever appropriate to implement Stretched aspect + break; + } + return height * 16 / 9; + } + + void SaveWindowState() { + const auto window_state_config_loc = FS::PathToUTF8String(FS::GetCitronPath(FS::CitronPath::ConfigDir) / "window_state.ini"); - void(FS::CreateParentDir(window_state_config_loc)); - QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); + void(FS::CreateParentDir(window_state_config_loc)); + QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); - config.setValue(QStringLiteral("geometry"), values.geometry); - config.setValue(QStringLiteral("state"), values.state); - config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry); - config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state); - config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry); + config.setValue(QStringLiteral("geometry"), values.geometry); + config.setValue(QStringLiteral("state"), values.state); + config.setValue(QStringLiteral("geometryRenderWindow"), values.renderwindow_geometry); + config.setValue(QStringLiteral("gameListHeaderState"), values.gamelist_header_state); + config.setValue(QStringLiteral("microProfileDialogGeometry"), values.microprofile_geometry); - config.sync(); -} + config.sync(); + } -void RestoreWindowState(std::unique_ptr& qtConfig) { - const auto window_state_config_loc = + void RestoreWindowState(std::unique_ptr& qtConfig) { + const auto window_state_config_loc = FS::PathToUTF8String(FS::GetCitronPath(FS::CitronPath::ConfigDir) / "window_state.ini"); - // Migrate window state from old location - if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) { - const auto config_loc = + // Migrate window state from old location + if (!FS::Exists(window_state_config_loc) && qtConfig->Exists("UI", "UILayout\\geometry")) { + const auto config_loc = FS::PathToUTF8String(FS::GetCitronPath(FS::CitronPath::ConfigDir) / "qt-config.ini"); - QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat); + QSettings config(QString::fromStdString(config_loc), QSettings::IniFormat); + + config.beginGroup(QStringLiteral("UI")); + config.beginGroup(QStringLiteral("UILayout")); + values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); + values.state = config.value(QStringLiteral("state")).toByteArray(); + values.renderwindow_geometry = + config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); + values.gamelist_header_state = + config.value(QStringLiteral("gameListHeaderState")).toByteArray(); + values.microprofile_geometry = + config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); + config.endGroup(); + config.endGroup(); + return; + } + + void(FS::CreateParentDir(window_state_config_loc)); + const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); - config.beginGroup(QStringLiteral("UI")); - config.beginGroup(QStringLiteral("UILayout")); values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); values.state = config.value(QStringLiteral("state")).toByteArray(); values.renderwindow_geometry = - config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); + config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); values.gamelist_header_state = - config.value(QStringLiteral("gameListHeaderState")).toByteArray(); + config.value(QStringLiteral("gameListHeaderState")).toByteArray(); values.microprofile_geometry = - config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); - config.endGroup(); - config.endGroup(); - return; + config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); } - void(FS::CreateParentDir(window_state_config_loc)); - const QSettings config(QString::fromStdString(window_state_config_loc), QSettings::IniFormat); - - values.geometry = config.value(QStringLiteral("geometry")).toByteArray(); - values.state = config.value(QStringLiteral("state")).toByteArray(); - values.renderwindow_geometry = - config.value(QStringLiteral("geometryRenderWindow")).toByteArray(); - values.gamelist_header_state = - config.value(QStringLiteral("gameListHeaderState")).toByteArray(); - values.microprofile_geometry = - config.value(QStringLiteral("microProfileDialogGeometry")).toByteArray(); -} - } // namespace UISettings