qt: save gui settings to separate file (#2984)

* initial save classes for gui save file

* fixup

* some more settings passed to the new saving file

* even more variables parsing

* more settings

* fixup

* more settings

* more settings

* clang fix

* fixed wrong setting

* more setting

* more setting

* added ca_ES

* rename to general_settings

* added set-addon-folder in main

* fixup

* fixup2

* added sr_CS

* Update CMakeLists.txt

---------

Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com>
This commit is contained in:
georgemoralis 2025-06-12 13:27:52 +03:00 committed by GitHub
parent 34d0d85c15
commit a1d6cd15f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 383 additions and 370 deletions

View file

@ -1055,6 +1055,10 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
src/qt_gui/settings_dialog.h src/qt_gui/settings_dialog.h
src/qt_gui/settings_dialog.ui src/qt_gui/settings_dialog.ui
src/qt_gui/main.cpp src/qt_gui/main.cpp
src/qt_gui/gui_settings.cpp
src/qt_gui/gui_settings.h
src/qt_gui/settings.cpp
src/qt_gui/settings.h
${EMULATOR} ${EMULATOR}
${RESOURCE_FILES} ${RESOURCE_FILES}
${TRANSLATIONS} ${TRANSLATIONS}

View file

@ -33,9 +33,7 @@ namespace Config {
static bool isNeo = false; static bool isNeo = false;
static bool isDevKit = false; static bool isDevKit = false;
static bool playBGM = false;
static bool isTrophyPopupDisabled = false; static bool isTrophyPopupDisabled = false;
static int BGMvolume = 50;
static bool enableDiscordRPC = false; static bool enableDiscordRPC = false;
static u32 screenWidth = 1280; static u32 screenWidth = 1280;
static u32 screenHeight = 720; static u32 screenHeight = 720;
@ -43,7 +41,6 @@ static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto
static std::string logFilter; static std::string logFilter;
static std::string logType = "sync"; static std::string logType = "sync";
static std::string userName = "shadPS4"; static std::string userName = "shadPS4";
static std::string updateChannel;
static std::string chooseHomeTab; static std::string chooseHomeTab;
static std::string backButtonBehavior = "left"; static std::string backButtonBehavior = "left";
static bool useSpecialPad = false; static bool useSpecialPad = false;
@ -52,8 +49,6 @@ static bool isMotionControlsEnabled = true;
static bool isDebugDump = false; static bool isDebugDump = false;
static bool isShaderDebug = false; static bool isShaderDebug = false;
static bool isShowSplash = false; static bool isShowSplash = false;
static bool isAutoUpdate = false;
static bool isAlwaysShowChangelog = false;
static std::string isSideTrophy = "right"; static std::string isSideTrophy = "right";
static bool isNullGpu = false; static bool isNullGpu = false;
static bool shouldCopyGPUBuffers = false; static bool shouldCopyGPUBuffers = false;
@ -86,27 +81,13 @@ static std::vector<GameInstallDir> settings_install_dirs = {};
std::vector<bool> install_dirs_enabled = {}; std::vector<bool> install_dirs_enabled = {};
std::filesystem::path settings_addon_install_dir = {}; std::filesystem::path settings_addon_install_dir = {};
std::filesystem::path save_data_path = {}; std::filesystem::path save_data_path = {};
u32 main_window_geometry_x = 400;
u32 main_window_geometry_y = 400;
u32 main_window_geometry_w = 1280;
u32 main_window_geometry_h = 720;
u32 mw_themes = 0; u32 mw_themes = 0;
u32 m_icon_size = 36;
u32 m_icon_size_grid = 69;
u32 m_slider_pos = 0;
u32 m_slider_pos_grid = 0;
u32 m_table_mode = 0;
u32 m_window_size_W = 1280;
u32 m_window_size_H = 720;
std::vector<std::string> m_elf_viewer; std::vector<std::string> m_elf_viewer;
std::vector<std::string> m_recent_files; std::vector<std::string> m_recent_files;
std::string emulator_language = "en_US"; std::string emulator_language = "en_US";
static int backgroundImageOpacity = 50;
static bool showBackgroundImage = true;
static bool isFullscreen = false; static bool isFullscreen = false;
static std::string fullscreenMode = "Windowed"; static std::string fullscreenMode = "Windowed";
static bool isHDRAllowed = false; static bool isHDRAllowed = false;
static bool showLabelsUnderIcons = true;
// Language // Language
u32 m_language = 1; // english u32 m_language = 1; // english
@ -176,14 +157,6 @@ bool getIsFullscreen() {
return isFullscreen; return isFullscreen;
} }
bool getShowLabelsUnderIcons() {
return showLabelsUnderIcons;
}
bool setShowLabelsUnderIcons() {
return false;
}
std::string getFullscreenMode() { std::string getFullscreenMode() {
return fullscreenMode; return fullscreenMode;
} }
@ -192,14 +165,6 @@ bool getisTrophyPopupDisabled() {
return isTrophyPopupDisabled; return isTrophyPopupDisabled;
} }
bool getPlayBGM() {
return playBGM;
}
int getBGMvolume() {
return BGMvolume;
}
bool getEnableDiscordRPC() { bool getEnableDiscordRPC() {
return enableDiscordRPC; return enableDiscordRPC;
} }
@ -240,10 +205,6 @@ std::string getUserName() {
return userName; return userName;
} }
std::string getUpdateChannel() {
return updateChannel;
}
std::string getChooseHomeTab() { std::string getChooseHomeTab() {
return chooseHomeTab; return chooseHomeTab;
} }
@ -276,14 +237,6 @@ bool showSplash() {
return isShowSplash; return isShowSplash;
} }
bool autoUpdate() {
return isAutoUpdate;
}
bool alwaysShowChangelog() {
return isAlwaysShowChangelog;
}
std::string sideTrophy() { std::string sideTrophy() {
return isSideTrophy; return isSideTrophy;
} }
@ -384,14 +337,6 @@ void setShowSplash(bool enable) {
isShowSplash = enable; isShowSplash = enable;
} }
void setAutoUpdate(bool enable) {
isAutoUpdate = enable;
}
void setAlwaysShowChangelog(bool enable) {
isAlwaysShowChangelog = enable;
}
void setSideTrophy(std::string side) { void setSideTrophy(std::string side) {
isSideTrophy = side; isSideTrophy = side;
} }
@ -431,9 +376,6 @@ void setVblankDiv(u32 value) {
void setIsFullscreen(bool enable) { void setIsFullscreen(bool enable) {
isFullscreen = enable; isFullscreen = enable;
} }
static void setShowLabelsUnderIcons(bool enable) {
showLabelsUnderIcons = enable;
}
void setFullscreenMode(std::string mode) { void setFullscreenMode(std::string mode) {
fullscreenMode = mode; fullscreenMode = mode;
@ -443,14 +385,6 @@ void setisTrophyPopupDisabled(bool disable) {
isTrophyPopupDisabled = disable; isTrophyPopupDisabled = disable;
} }
void setPlayBGM(bool enable) {
playBGM = enable;
}
void setBGMvolume(int volume) {
BGMvolume = volume;
}
void setEnableDiscordRPC(bool enable) { void setEnableDiscordRPC(bool enable) {
enableDiscordRPC = enable; enableDiscordRPC = enable;
} }
@ -490,9 +424,6 @@ void setUserName(const std::string& type) {
userName = type; userName = type;
} }
void setUpdateChannel(const std::string& type) {
updateChannel = type;
}
void setChooseHomeTab(const std::string& type) { void setChooseHomeTab(const std::string& type) {
chooseHomeTab = type; chooseHomeTab = type;
} }
@ -521,13 +452,6 @@ void setCheckCompatibilityOnStartup(bool use) {
checkCompatibilityOnStartup = use; checkCompatibilityOnStartup = use;
} }
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
main_window_geometry_x = x;
main_window_geometry_y = y;
main_window_geometry_w = w;
main_window_geometry_h = h;
}
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) { bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
for (const auto& install_dir : settings_install_dirs) { for (const auto& install_dir : settings_install_dirs) {
if (install_dir.path == dir) { if (install_dir.path == dir) {
@ -564,34 +488,6 @@ void setMainWindowTheme(u32 theme) {
mw_themes = theme; mw_themes = theme;
} }
void setIconSize(u32 size) {
m_icon_size = size;
}
void setIconSizeGrid(u32 size) {
m_icon_size_grid = size;
}
void setSliderPosition(u32 pos) {
m_slider_pos = pos;
}
void setSliderPositionGrid(u32 pos) {
m_slider_pos_grid = pos;
}
void setTableMode(u32 mode) {
m_table_mode = mode;
}
void setMainWindowWidth(u32 width) {
m_window_size_W = width;
}
void setMainWindowHeight(u32 height) {
m_window_size_H = height;
}
void setElfViewer(const std::vector<std::string>& elfList) { void setElfViewer(const std::vector<std::string>& elfList) {
m_elf_viewer.resize(elfList.size()); m_elf_viewer.resize(elfList.size());
m_elf_viewer = elfList; m_elf_viewer = elfList;
@ -621,22 +517,6 @@ void setSaveDataPath(const std::filesystem::path& path) {
save_data_path = path; save_data_path = path;
} }
u32 getMainWindowGeometryX() {
return main_window_geometry_x;
}
u32 getMainWindowGeometryY() {
return main_window_geometry_y;
}
u32 getMainWindowGeometryW() {
return main_window_geometry_w;
}
u32 getMainWindowGeometryH() {
return main_window_geometry_h;
}
const std::vector<std::filesystem::path> getGameInstallDirs() { const std::vector<std::filesystem::path> getGameInstallDirs() {
std::vector<std::filesystem::path> enabled_dirs; std::vector<std::filesystem::path> enabled_dirs;
for (const auto& dir : settings_install_dirs) { for (const auto& dir : settings_install_dirs) {
@ -667,34 +547,6 @@ u32 getMainWindowTheme() {
return mw_themes; return mw_themes;
} }
u32 getIconSize() {
return m_icon_size;
}
u32 getIconSizeGrid() {
return m_icon_size_grid;
}
u32 getSliderPosition() {
return m_slider_pos;
}
u32 getSliderPositionGrid() {
return m_slider_pos_grid;
}
u32 getTableMode() {
return m_table_mode;
}
u32 getMainWindowWidth() {
return m_window_size_W;
}
u32 getMainWindowHeight() {
return m_window_size_H;
}
std::vector<std::string> getElfViewer() { std::vector<std::string> getElfViewer() {
return m_elf_viewer; return m_elf_viewer;
} }
@ -715,22 +567,6 @@ bool getSeparateLogFilesEnabled() {
return isSeparateLogFilesEnabled; return isSeparateLogFilesEnabled;
} }
int getBackgroundImageOpacity() {
return backgroundImageOpacity;
}
void setBackgroundImageOpacity(int opacity) {
backgroundImageOpacity = std::clamp(opacity, 0, 100);
}
bool getShowBackgroundImage() {
return showBackgroundImage;
}
void setShowBackgroundImage(bool show) {
showBackgroundImage = show;
}
bool getPSNSignedIn() { bool getPSNSignedIn() {
return isPSNSignedIn; return isPSNSignedIn;
} }
@ -764,23 +600,14 @@ void load(const std::filesystem::path& path) {
isNeo = toml::find_or<bool>(general, "isPS4Pro", false); isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
isDevKit = toml::find_or<bool>(general, "isDevKit", false); isDevKit = toml::find_or<bool>(general, "isDevKit", false);
isPSNSignedIn = toml::find_or<bool>(general, "isPSNSignedIn", false); isPSNSignedIn = toml::find_or<bool>(general, "isPSNSignedIn", false);
playBGM = toml::find_or<bool>(general, "playBGM", false);
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false); isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
trophyNotificationDuration = trophyNotificationDuration =
toml::find_or<double>(general, "trophyNotificationDuration", 5.0); toml::find_or<double>(general, "trophyNotificationDuration", 5.0);
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true); enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
logFilter = toml::find_or<std::string>(general, "logFilter", ""); logFilter = toml::find_or<std::string>(general, "logFilter", "");
logType = toml::find_or<std::string>(general, "logType", "sync"); logType = toml::find_or<std::string>(general, "logType", "sync");
userName = toml::find_or<std::string>(general, "userName", "shadPS4"); userName = toml::find_or<std::string>(general, "userName", "shadPS4");
if (Common::g_is_release) {
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Release");
} else {
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Nightly");
}
isShowSplash = toml::find_or<bool>(general, "showSplash", true); isShowSplash = toml::find_or<bool>(general, "showSplash", true);
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right"); isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false); compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
checkCompatibilityOnStartup = checkCompatibilityOnStartup =
@ -841,13 +668,7 @@ void load(const std::filesystem::path& path) {
const toml::value& gui = data.at("GUI"); const toml::value& gui = data.at("GUI");
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true); load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true);
m_icon_size = toml::find_or<int>(gui, "iconSize", 0);
m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0);
m_slider_pos = toml::find_or<int>(gui, "sliderPos", 0);
m_slider_pos_grid = toml::find_or<int>(gui, "sliderPosGrid", 0);
mw_themes = toml::find_or<int>(gui, "theme", 0); mw_themes = toml::find_or<int>(gui, "theme", 0);
m_window_size_W = toml::find_or<int>(gui, "mw_width", 0);
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
const auto install_dir_array = const auto install_dir_array =
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {}); toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
@ -872,16 +693,9 @@ void load(const std::filesystem::path& path) {
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {}); save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
main_window_geometry_h = toml::find_or<int>(gui, "geometry_h", 0);
m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {}); m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {});
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {}); m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0);
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en_US"); emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en_US");
backgroundImageOpacity = toml::find_or<int>(gui, "backgroundImageOpacity", 50);
showBackgroundImage = toml::find_or<bool>(gui, "showBackgroundImage", true);
} }
if (data.contains("Settings")) { if (data.contains("Settings")) {
@ -897,9 +711,10 @@ void load(const std::filesystem::path& path) {
// Check if the loaded language is in the allowed list // Check if the loaded language is in the allowed list
const std::vector<std::string> allowed_languages = { const std::vector<std::string> allowed_languages = {
"ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU", "ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI",
"id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", "nl_NL", "pl_PL", "pt_BR", "pt_PT", "fr_FR", "hu_HU", "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO",
"ro_RO", "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"}; "nl_NL", "pl_PL", "pt_BR", "pt_PT", "ro_RO", "ru_RU", "sq_AL", "sv_SE",
"tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW", "ca_ES", "sr_CS"};
if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) == if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) ==
allowed_languages.end()) { allowed_languages.end()) {
@ -966,17 +781,12 @@ void save(const std::filesystem::path& path) {
data["General"]["isPSNSignedIn"] = isPSNSignedIn; data["General"]["isPSNSignedIn"] = isPSNSignedIn;
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled; data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration; data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
data["General"]["playBGM"] = playBGM;
data["General"]["BGMvolume"] = BGMvolume;
data["General"]["enableDiscordRPC"] = enableDiscordRPC; data["General"]["enableDiscordRPC"] = enableDiscordRPC;
data["General"]["logFilter"] = logFilter; data["General"]["logFilter"] = logFilter;
data["General"]["logType"] = logType; data["General"]["logType"] = logType;
data["General"]["userName"] = userName; data["General"]["userName"] = userName;
data["General"]["updateChannel"] = updateChannel;
data["General"]["chooseHomeTab"] = chooseHomeTab; data["General"]["chooseHomeTab"] = chooseHomeTab;
data["General"]["showSplash"] = isShowSplash; data["General"]["showSplash"] = isShowSplash;
data["General"]["autoUpdate"] = isAutoUpdate;
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
data["General"]["sideTrophy"] = isSideTrophy; data["General"]["sideTrophy"] = isSideTrophy;
data["General"]["compatibilityEnabled"] = compatibilityData; data["General"]["compatibilityEnabled"] = compatibilityData;
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup; data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
@ -1046,8 +856,6 @@ void save(const std::filesystem::path& path) {
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
data["GUI"]["emulatorLanguage"] = emulator_language; data["GUI"]["emulatorLanguage"] = emulator_language;
data["GUI"]["backgroundImageOpacity"] = backgroundImageOpacity;
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
data["Settings"]["consoleLanguage"] = m_language; data["Settings"]["consoleLanguage"] = m_language;
// Sorting of TOML sections // Sorting of TOML sections
@ -1082,18 +890,7 @@ void saveMainWindow(const std::filesystem::path& path) {
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string())); fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
} }
data["GUI"]["mw_width"] = m_window_size_W;
data["GUI"]["mw_height"] = m_window_size_H;
data["GUI"]["theme"] = mw_themes; data["GUI"]["theme"] = mw_themes;
data["GUI"]["iconSize"] = m_icon_size;
data["GUI"]["sliderPos"] = m_slider_pos;
data["GUI"]["iconSizeGrid"] = m_icon_size_grid;
data["GUI"]["sliderPosGrid"] = m_slider_pos_grid;
data["GUI"]["gameTableMode"] = m_table_mode;
data["GUI"]["geometry_x"] = main_window_geometry_x;
data["GUI"]["geometry_y"] = main_window_geometry_y;
data["GUI"]["geometry_w"] = main_window_geometry_w;
data["GUI"]["geometry_h"] = main_window_geometry_h;
data["GUI"]["elfDirs"] = m_elf_viewer; data["GUI"]["elfDirs"] = m_elf_viewer;
data["GUI"]["recentFiles"] = m_recent_files; data["GUI"]["recentFiles"] = m_recent_files;
@ -1112,19 +909,13 @@ void setDefaultValues() {
isPSNSignedIn = false; isPSNSignedIn = false;
isFullscreen = false; isFullscreen = false;
isTrophyPopupDisabled = false; isTrophyPopupDisabled = false;
playBGM = false;
BGMvolume = 50;
enableDiscordRPC = true; enableDiscordRPC = true;
screenWidth = 1280; screenWidth = 1280;
screenHeight = 720; screenHeight = 720;
logFilter = ""; logFilter = "";
logType = "sync"; logType = "sync";
userName = "shadPS4"; userName = "shadPS4";
if (Common::g_is_release) {
updateChannel = "Release";
} else {
updateChannel = "Nightly";
}
chooseHomeTab = "General"; chooseHomeTab = "General";
cursorState = HideCursorState::Idle; cursorState = HideCursorState::Idle;
cursorHideTimeout = 5; cursorHideTimeout = 5;
@ -1135,8 +926,6 @@ void setDefaultValues() {
isDebugDump = false; isDebugDump = false;
isShaderDebug = false; isShaderDebug = false;
isShowSplash = false; isShowSplash = false;
isAutoUpdate = false;
isAlwaysShowChangelog = false;
isSideTrophy = "right"; isSideTrophy = "right";
isNullGpu = false; isNullGpu = false;
shouldDumpShaders = false; shouldDumpShaders = false;
@ -1153,8 +942,6 @@ void setDefaultValues() {
gpuId = -1; gpuId = -1;
compatibilityData = false; compatibilityData = false;
checkCompatibilityOnStartup = false; checkCompatibilityOnStartup = false;
backgroundImageOpacity = 50;
showBackgroundImage = true;
} }
constexpr std::string_view GetDefaultKeyboardConfig() { constexpr std::string_view GetDefaultKeyboardConfig() {

View file

@ -26,25 +26,18 @@ bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath(); std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable); void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen(); bool getIsFullscreen();
bool getShowLabelsUnderIcons();
bool setShowLabelsUnderIcons();
std::string getFullscreenMode(); std::string getFullscreenMode();
bool isNeoModeConsole(); bool isNeoModeConsole();
bool isDevKitConsole(); bool isDevKitConsole();
bool getPlayBGM();
int getBGMvolume();
bool getisTrophyPopupDisabled(); bool getisTrophyPopupDisabled();
bool getEnableDiscordRPC(); bool getEnableDiscordRPC();
bool getCompatibilityEnabled(); bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup(); bool getCheckCompatibilityOnStartup();
int getBackgroundImageOpacity();
bool getShowBackgroundImage();
bool getPSNSignedIn(); bool getPSNSignedIn();
std::string getLogFilter(); std::string getLogFilter();
std::string getLogType(); std::string getLogType();
std::string getUserName(); std::string getUserName();
std::string getUpdateChannel();
std::string getChooseHomeTab(); std::string getChooseHomeTab();
s16 getCursorState(); s16 getCursorState();
@ -69,8 +62,6 @@ bool allowHDR();
bool debugDump(); bool debugDump();
bool collectShadersForDebug(); bool collectShadersForDebug();
bool showSplash(); bool showSplash();
bool autoUpdate();
bool alwaysShowChangelog();
std::string sideTrophy(); std::string sideTrophy();
bool nullGpu(); bool nullGpu();
bool copyGPUCmdBuffers(); bool copyGPUCmdBuffers();
@ -83,8 +74,6 @@ u32 vblankDiv();
void setDebugDump(bool enable); void setDebugDump(bool enable);
void setCollectShaderForDebug(bool enable); void setCollectShaderForDebug(bool enable);
void setShowSplash(bool enable); void setShowSplash(bool enable);
void setAutoUpdate(bool enable);
void setAlwaysShowChangelog(bool enable);
void setSideTrophy(std::string side); void setSideTrophy(std::string side);
void setNullGpu(bool enable); void setNullGpu(bool enable);
void setAllowHDR(bool enable); void setAllowHDR(bool enable);
@ -97,21 +86,16 @@ void setScreenHeight(u32 height);
void setIsFullscreen(bool enable); void setIsFullscreen(bool enable);
void setFullscreenMode(std::string mode); void setFullscreenMode(std::string mode);
void setisTrophyPopupDisabled(bool disable); void setisTrophyPopupDisabled(bool disable);
void setPlayBGM(bool enable);
void setBGMvolume(int volume);
void setEnableDiscordRPC(bool enable); void setEnableDiscordRPC(bool enable);
void setLanguage(u32 language); void setLanguage(u32 language);
void setNeoMode(bool enable); void setNeoMode(bool enable);
void setUserName(const std::string& type); void setUserName(const std::string& type);
void setUpdateChannel(const std::string& type);
void setChooseHomeTab(const std::string& type); void setChooseHomeTab(const std::string& type);
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config); void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config); void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
void setSaveDataPath(const std::filesystem::path& path); void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use); void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);
void setBackgroundImageOpacity(int opacity);
void setShowBackgroundImage(bool show);
void setPSNSignedIn(bool sign); void setPSNSignedIn(bool sign);
void setCursorState(s16 cursorState); void setCursorState(s16 cursorState);
@ -141,38 +125,19 @@ void setVkHostMarkersEnabled(bool enable);
void setVkGuestMarkersEnabled(bool enable); void setVkGuestMarkersEnabled(bool enable);
// Gui // Gui
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true); bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
void removeGameInstallDir(const std::filesystem::path& dir); void removeGameInstallDir(const std::filesystem::path& dir);
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled); void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
void setAddonInstallDir(const std::filesystem::path& dir); void setAddonInstallDir(const std::filesystem::path& dir);
void setMainWindowTheme(u32 theme); void setMainWindowTheme(u32 theme);
void setIconSize(u32 size);
void setIconSizeGrid(u32 size);
void setSliderPosition(u32 pos);
void setSliderPositionGrid(u32 pos);
void setTableMode(u32 mode);
void setMainWindowWidth(u32 width);
void setMainWindowHeight(u32 height);
void setElfViewer(const std::vector<std::string>& elfList); void setElfViewer(const std::vector<std::string>& elfList);
void setRecentFiles(const std::vector<std::string>& recentFiles); void setRecentFiles(const std::vector<std::string>& recentFiles);
void setEmulatorLanguage(std::string language); void setEmulatorLanguage(std::string language);
u32 getMainWindowGeometryX();
u32 getMainWindowGeometryY();
u32 getMainWindowGeometryW();
u32 getMainWindowGeometryH();
const std::vector<std::filesystem::path> getGameInstallDirs(); const std::vector<std::filesystem::path> getGameInstallDirs();
const std::vector<bool> getGameInstallDirsEnabled(); const std::vector<bool> getGameInstallDirsEnabled();
std::filesystem::path getAddonInstallDir(); std::filesystem::path getAddonInstallDir();
u32 getMainWindowTheme(); u32 getMainWindowTheme();
u32 getIconSize();
u32 getIconSizeGrid();
u32 getSliderPosition();
u32 getSliderPositionGrid();
u32 getTableMode();
u32 getMainWindowWidth();
u32 getMainWindowHeight();
std::vector<std::string> getElfViewer(); std::vector<std::string> getElfViewer();
std::vector<std::string> getRecentFiles(); std::vector<std::string> getRecentFiles();
std::string getEmulatorLanguage(); std::string getEmulatorLanguage();

View file

@ -47,6 +47,7 @@ int main(int argc, char* argv[]) {
" -f, --fullscreen <true|false> Specify window initial fullscreen " " -f, --fullscreen <true|false> Specify window initial fullscreen "
"state. Does not overwrite the config file.\n" "state. Does not overwrite the config file.\n"
" --add-game-folder <folder> Adds a new game folder to the config.\n" " --add-game-folder <folder> Adds a new game folder to the config.\n"
" --set-addon-folder <folder> Sets the addon folder to the config.\n"
" -h, --help Display this help message\n"; " -h, --help Display this help message\n";
exit(0); exit(0);
}}, }},
@ -116,7 +117,24 @@ int main(int argc, char* argv[]) {
std::cout << "Game folder successfully saved.\n"; std::cout << "Game folder successfully saved.\n";
exit(0); exit(0);
}}, }},
}; {"--set-addon-folder", [&](int& i) {
if (++i >= argc) {
std::cerr << "Error: Missing argument for --add-addon-folder\n";
exit(1);
}
std::string config_dir(argv[i]);
std::filesystem::path config_path = std::filesystem::path(config_dir);
std::error_code discard;
if (!std::filesystem::exists(config_path, discard)) {
std::cerr << "Error: File does not exist: " << config_path << "\n";
exit(1);
}
Config::setAddonInstallDir(config_path);
Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml");
std::cout << "Addon folder successfully saved.\n";
exit(0);
}}};
if (argc == 1) { if (argc == 1) {
int dummy = 0; // one does not simply pass 0 directly int dummy = 0; // one does not simply pass 0 directly

View file

@ -28,8 +28,10 @@
using namespace Common::FS; using namespace Common::FS;
CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent) CheckUpdate::CheckUpdate(std::shared_ptr<gui_settings> gui_settings, const bool showMessage,
: QDialog(parent), networkManager(new QNetworkAccessManager(this)) { QWidget* parent)
: QDialog(parent), m_gui_settings(std::move(gui_settings)),
networkManager(new QNetworkAccessManager(this)) {
setWindowTitle(tr("Auto Updater")); setWindowTitle(tr("Auto Updater"));
setFixedSize(0, 0); setFixedSize(0, 0);
CheckForUpdates(showMessage); CheckForUpdates(showMessage);
@ -43,7 +45,7 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) {
bool checkName = true; bool checkName = true;
while (checkName) { while (checkName) {
updateChannel = QString::fromStdString(Config::getUpdateChannel()); updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString();
if (updateChannel == "Nightly") { if (updateChannel == "Nightly") {
url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases"); url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases");
checkName = false; checkName = false;
@ -52,12 +54,10 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) {
checkName = false; checkName = false;
} else { } else {
if (Common::g_is_release) { if (Common::g_is_release) {
Config::setUpdateChannel("Release"); m_gui_settings->SetValue(gui::gen_updateChannel, "Release");
} else { } else {
Config::setUpdateChannel("Nightly"); m_gui_settings->SetValue(gui::gen_updateChannel, "Nightly");
} }
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::save(config_dir / "config.toml");
} }
} }
@ -198,7 +198,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
titleLayout->addWidget(titleLabel); titleLayout->addWidget(titleLabel);
layout->addLayout(titleLayout); layout->addLayout(titleLayout);
QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); QString updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString();
QString updateText = QString("<p><b>" + tr("Update Channel") + ": </b>" + updateChannel + QString updateText = QString("<p><b>" + tr("Update Channel") + ": </b>" + updateChannel +
"<br>" "<br>"
@ -273,7 +273,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
} }
}); });
if (Config::alwaysShowChangelog()) { if (m_gui_settings->GetValue(gui::gen_showChangeLog).toBool()) {
requestChangelog(currentRev, latestRev, downloadUrl, latestDate, currentDate); requestChangelog(currentRev, latestRev, downloadUrl, latestDate, currentDate);
textField->setVisible(true); textField->setVisible(true);
toggleButton->setText(tr("Hide Changelog")); toggleButton->setText(tr("Hide Changelog"));
@ -290,14 +290,14 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
connect(noButton, &QPushButton::clicked, this, [this]() { close(); }); connect(noButton, &QPushButton::clicked, this, [this]() { close(); });
autoUpdateCheckBox->setChecked(Config::autoUpdate()); autoUpdateCheckBox->setChecked(m_gui_settings->GetValue(gui::gen_checkForUpdates).toBool());
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) { connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
#else #else
connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [](Qt::CheckState state) { connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) {
#endif #endif
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
Config::setAutoUpdate(state == Qt::Checked); m_gui_settings->SetValue(gui::gen_checkForUpdates, (state == Qt::Checked));
Config::save(user_dir / "config.toml"); Config::save(user_dir / "config.toml");
}); });

View file

@ -8,12 +8,14 @@
#include <QDialog> #include <QDialog>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QPushButton> #include <QPushButton>
#include "gui_settings.h"
class CheckUpdate : public QDialog { class CheckUpdate : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit CheckUpdate(const bool showMessage, QWidget* parent = nullptr); explicit CheckUpdate(std::shared_ptr<gui_settings> gui_settings, const bool showMessage,
QWidget* parent = nullptr);
~CheckUpdate(); ~CheckUpdate();
private slots: private slots:
@ -35,6 +37,7 @@ private:
QString updateDownloadUrl; QString updateDownloadUrl;
QNetworkAccessManager* networkManager; QNetworkAccessManager* networkManager;
std::shared_ptr<gui_settings> m_gui_settings;
}; };
#endif // CHECKUPDATE_H #endif // CHECKUPDATE_H

View file

@ -5,11 +5,13 @@
#include "game_grid_frame.h" #include "game_grid_frame.h"
#include "qt_gui/compatibility_info.h" #include "qt_gui/compatibility_info.h"
GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, GameGridFrame::GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get, std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent) QWidget* parent)
: QTableWidget(parent), m_game_info(game_info_get), m_compat_info(compat_info_get) { : QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get),
icon_size = Config::getIconSizeGrid(); m_compat_info(compat_info_get) {
icon_size = m_gui_settings->GetValue(gui::gg_icon_size).toInt();
windowWidth = parent->width(); windowWidth = parent->width();
this->setShowGrid(false); this->setShowGrid(false);
this->setEditTriggers(QAbstractItemView::NoEditTriggers); this->setEditTriggers(QAbstractItemView::NoEditTriggers);
@ -74,7 +76,7 @@ void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int
} }
void GameGridFrame::PlayBackgroundMusic(QString path) { void GameGridFrame::PlayBackgroundMusic(QString path) {
if (path.isEmpty() || !Config::getPlayBGM()) { if (path.isEmpty() || !m_gui_settings->GetValue(gui::gl_playBackgroundMusic).toBool()) {
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
return; return;
} }
@ -91,7 +93,8 @@ void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool from
else else
m_games_ = m_game_info->m_games; m_games_ = m_game_info->m_games;
m_games_shared = std::make_shared<QVector<GameInfo>>(m_games_); m_games_shared = std::make_shared<QVector<GameInfo>>(m_games_);
icon_size = Config::getIconSizeGrid(); // update icon size for resize event. icon_size =
m_gui_settings->GetValue(gui::gg_icon_size).toInt(); // update icon size for resize event.
int gamesPerRow = windowWidth / (icon_size + 20); // 2 x cell widget border size. int gamesPerRow = windowWidth / (icon_size + 20); // 2 x cell widget border size.
int row = 0; int row = 0;
@ -118,7 +121,7 @@ void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool from
layout->addWidget(name_label); layout->addWidget(name_label);
// Resizing of font-size. // Resizing of font-size.
float fontSize = (Config::getIconSizeGrid() / 5.5f); float fontSize = (m_gui_settings->GetValue(gui::gg_icon_size).toInt() / 5.5f);
QString styleSheet = QString styleSheet =
QString("color: white; font-weight: bold; font-size: %1px;").arg(fontSize); QString("color: white; font-weight: bold; font-size: %1px;").arg(fontSize);
name_label->setStyleSheet(styleSheet); name_label->setStyleSheet(styleSheet);
@ -168,7 +171,7 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) {
} }
// If background images are hidden, clear the background image // If background images are hidden, clear the background image
if (!Config::getShowBackgroundImage()) { if (!m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) {
backgroundImage = QImage(); backgroundImage = QImage();
m_last_opacity = -1; // Reset opacity tracking when disabled m_last_opacity = -1; // Reset opacity tracking when disabled
m_current_game_path.clear(); // Reset current game path m_current_game_path.clear(); // Reset current game path
@ -177,7 +180,7 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) {
} }
const auto& game = (*m_games_shared)[itemID]; const auto& game = (*m_games_shared)[itemID];
const int opacity = Config::getBackgroundImageOpacity(); const int opacity = m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt();
// Recompute if opacity changed or we switched to a different game // Recompute if opacity changed or we switched to a different game
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) { if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
@ -195,7 +198,8 @@ void GameGridFrame::SetGridBackgroundImage(int row, int column) {
void GameGridFrame::RefreshGridBackgroundImage() { void GameGridFrame::RefreshGridBackgroundImage() {
QPalette palette; QPalette palette;
if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { if (!backgroundImage.isNull() &&
m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) {
QSize widgetSize = size(); QSize widgetSize = size();
QPixmap scaledPixmap = QPixmap scaledPixmap =
QPixmap::fromImage(backgroundImage) QPixmap::fromImage(backgroundImage)

View file

@ -11,6 +11,7 @@
#include "game_info.h" #include "game_info.h"
#include "game_list_utils.h" #include "game_list_utils.h"
#include "gui_context_menus.h" #include "gui_context_menus.h"
#include "gui_settings.h"
#include "qt_gui/compatibility_info.h" #include "qt_gui/compatibility_info.h"
class GameGridFrame : public QTableWidget { class GameGridFrame : public QTableWidget {
@ -37,9 +38,11 @@ private:
bool validCellSelected = false; bool validCellSelected = false;
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
std::filesystem::path m_current_game_path; // Track current game path to detect changes std::filesystem::path m_current_game_path; // Track current game path to detect changes
std::shared_ptr<gui_settings> m_gui_settings;
public: public:
explicit GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, explicit GameGridFrame(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get, std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent = nullptr); QWidget* parent = nullptr);
void PopulateGameGrid(QVector<GameInfo> m_games, bool fromSearch); void PopulateGameGrid(QVector<GameInfo> m_games, bool fromSearch);

View file

@ -9,11 +9,13 @@
#include "game_list_frame.h" #include "game_list_frame.h"
#include "game_list_utils.h" #include "game_list_utils.h"
GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, GameListFrame::GameListFrame(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get, std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent) QWidget* parent)
: QTableWidget(parent), m_game_info(game_info_get), m_compat_info(compat_info_get) { : QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get),
icon_size = Config::getIconSize(); m_compat_info(compat_info_get) {
icon_size = m_gui_settings->GetValue(gui::gl_icon_size).toInt();
this->setShowGrid(false); this->setShowGrid(false);
this->setEditTriggers(QAbstractItemView::NoEditTriggers); this->setEditTriggers(QAbstractItemView::NoEditTriggers);
this->setSelectionBehavior(QAbstractItemView::SelectRows); this->setSelectionBehavior(QAbstractItemView::SelectRows);
@ -97,7 +99,7 @@ void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int
} }
void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) { void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
if (!item || !Config::getPlayBGM()) { if (!item || !m_gui_settings->GetValue(gui::gl_playBackgroundMusic).toBool()) {
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
return; return;
} }
@ -172,7 +174,7 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
} }
// If background images are hidden, clear the background image // If background images are hidden, clear the background image
if (!Config::getShowBackgroundImage()) { if (!m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) {
backgroundImage = QImage(); backgroundImage = QImage();
m_last_opacity = -1; // Reset opacity tracking when disabled m_last_opacity = -1; // Reset opacity tracking when disabled
m_current_game_path.clear(); // Reset current game path m_current_game_path.clear(); // Reset current game path
@ -181,7 +183,7 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
} }
const auto& game = m_game_info->m_games[item->row()]; const auto& game = m_game_info->m_games[item->row()];
const int opacity = Config::getBackgroundImageOpacity(); const int opacity = m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt();
// Recompute if opacity changed or we switched to a different game // Recompute if opacity changed or we switched to a different game
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) { if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
@ -200,7 +202,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
void GameListFrame::RefreshListBackgroundImage() { void GameListFrame::RefreshListBackgroundImage() {
QPalette palette; QPalette palette;
if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { if (!backgroundImage.isNull() &&
m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) {
QSize widgetSize = size(); QSize widgetSize = size();
QPixmap scaledPixmap = QPixmap scaledPixmap =
QPixmap::fromImage(backgroundImage) QPixmap::fromImage(backgroundImage)

View file

@ -17,11 +17,13 @@
#include "game_info.h" #include "game_info.h"
#include "game_list_utils.h" #include "game_list_utils.h"
#include "gui_context_menus.h" #include "gui_context_menus.h"
#include "gui_settings.h"
class GameListFrame : public QTableWidget { class GameListFrame : public QTableWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, explicit GameListFrame(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<GameInfoClass> game_info_get,
std::shared_ptr<CompatibilityInfoClass> compat_info_get, std::shared_ptr<CompatibilityInfoClass> compat_info_get,
QWidget* parent = nullptr); QWidget* parent = nullptr);
Q_SIGNALS: Q_SIGNALS:
@ -48,6 +50,7 @@ private:
QTableWidgetItem* m_current_item = nullptr; QTableWidgetItem* m_current_item = nullptr;
int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation int m_last_opacity = -1; // Track last opacity to avoid unnecessary recomputation
std::filesystem::path m_current_game_path; // Track current game path to detect changes std::filesystem::path m_current_game_path; // Track current game path to detect changes
std::shared_ptr<gui_settings> m_gui_settings;
public: public:
void PopulateGameList(bool isInitialPopulation = true); void PopulateGameList(bool isInitialPopulation = true);

View file

@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "gui_settings.h"
gui_settings::gui_settings(QObject* parent) : settings(parent) {
m_settings = std::make_unique<QSettings>(ComputeSettingsDir() + "qt_ui.ini",
QSettings::Format::IniFormat, parent);
}

46
src/qt_gui/gui_settings.h Normal file
View file

@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QWindow>
#include "settings.h"
namespace gui {
// categories
const QString general_settings = "general_settings";
const QString main_window = "main_window";
const QString game_list = "game_list";
const QString game_grid = "game_grid";
// general
const gui_value gen_checkForUpdates = gui_value(general_settings, "checkForUpdates", false);
const gui_value gen_showChangeLog = gui_value(general_settings, "showChangeLog", false);
const gui_value gen_updateChannel = gui_value(general_settings, "updateChannel", "Release");
// main window settings
const gui_value mw_geometry = gui_value(main_window, "geometry", QByteArray());
const gui_value mw_showLabelsUnderIcons = gui_value(main_window, "showLabelsUnderIcons", true);
// game list settings
const gui_value gl_mode = gui_value(game_list, "tableMode", 0);
const gui_value gl_icon_size = gui_value(game_list, "icon_size", 36);
const gui_value gl_slider_pos = gui_value(game_list, "slider_pos", 0);
const gui_value gl_showBackgroundImage = gui_value(game_list, "showBackgroundImage", true);
const gui_value gl_backgroundImageOpacity = gui_value(game_list, "backgroundImageOpacity", 50);
const gui_value gl_playBackgroundMusic = gui_value(game_list, "playBackgroundMusic", true);
const gui_value gl_backgroundMusicVolume = gui_value(game_list, "backgroundMusicVolume", 50);
// game grid settings
const gui_value gg_icon_size = gui_value(game_grid, "icon_size", 69);
const gui_value gg_slider_pos = gui_value(game_grid, "slider_pos", 0);
} // namespace gui
class gui_settings : public settings {
Q_OBJECT
public:
explicit gui_settings(QObject* parent = nullptr);
~gui_settings() override = default;
};

View file

@ -32,6 +32,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi
ui->setupUi(this); ui->setupUi(this);
installEventFilter(this); installEventFilter(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
m_gui_settings = std::make_shared<gui_settings>();
ui->toggleLabelsAct->setChecked(
m_gui_settings->GetValue(gui::mw_showLabelsUnderIcons).toBool());
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
@ -139,7 +142,7 @@ void MainWindow::PauseGame() {
void MainWindow::toggleLabelsUnderIcons() { void MainWindow::toggleLabelsUnderIcons() {
bool showLabels = ui->toggleLabelsAct->isChecked(); bool showLabels = ui->toggleLabelsAct->isChecked();
Config::setShowLabelsUnderIcons(); m_gui_settings->SetValue(gui::mw_showLabelsUnderIcons, showLabels);
UpdateToolbarLabels(); UpdateToolbarLabels();
if (isGameRunning) { if (isGameRunning) {
UpdateToolbarButtons(); UpdateToolbarButtons();
@ -290,21 +293,21 @@ void MainWindow::CreateDockWindows() {
setCentralWidget(phCentralWidget); setCentralWidget(phCentralWidget);
m_dock_widget.reset(new QDockWidget(tr("Game List"), this)); m_dock_widget.reset(new QDockWidget(tr("Game List"), this));
m_game_list_frame.reset(new GameListFrame(m_game_info, m_compat_info, this)); m_game_list_frame.reset(new GameListFrame(m_gui_settings, m_game_info, m_compat_info, this));
m_game_list_frame->setObjectName("gamelist"); m_game_list_frame->setObjectName("gamelist");
m_game_grid_frame.reset(new GameGridFrame(m_game_info, m_compat_info, this)); m_game_grid_frame.reset(new GameGridFrame(m_gui_settings, m_game_info, m_compat_info, this));
m_game_grid_frame->setObjectName("gamegridlist"); m_game_grid_frame->setObjectName("gamegridlist");
m_elf_viewer.reset(new ElfViewer(this)); m_elf_viewer.reset(new ElfViewer(this));
m_elf_viewer->setObjectName("elflist"); m_elf_viewer->setObjectName("elflist");
int table_mode = Config::getTableMode(); int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt();
int slider_pos = 0; int slider_pos = 0;
if (table_mode == 0) { // List if (table_mode == 0) { // List
m_game_grid_frame->hide(); m_game_grid_frame->hide();
m_elf_viewer->hide(); m_elf_viewer->hide();
m_game_list_frame->show(); m_game_list_frame->show();
m_dock_widget->setWidget(m_game_list_frame.data()); m_dock_widget->setWidget(m_game_list_frame.data());
slider_pos = Config::getSliderPosition(); slider_pos = m_gui_settings->GetValue(gui::gl_slider_pos).toInt();
ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start;
isTableList = true; isTableList = true;
} else if (table_mode == 1) { // Grid } else if (table_mode == 1) { // Grid
@ -312,7 +315,7 @@ void MainWindow::CreateDockWindows() {
m_elf_viewer->hide(); m_elf_viewer->hide();
m_game_grid_frame->show(); m_game_grid_frame->show();
m_dock_widget->setWidget(m_game_grid_frame.data()); m_dock_widget->setWidget(m_game_grid_frame.data());
slider_pos = Config::getSliderPositionGrid(); slider_pos = m_gui_settings->GetValue(gui::gg_slider_pos).toInt();
ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start; ui->sizeSlider->setSliderPosition(slider_pos); // set slider pos at start;
isTableList = false; isTableList = false;
} else { } else {
@ -356,11 +359,11 @@ void MainWindow::LoadGameLists() {
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
void MainWindow::CheckUpdateMain(bool checkSave) { void MainWindow::CheckUpdateMain(bool checkSave) {
if (checkSave) { if (checkSave) {
if (!Config::autoUpdate()) { if (!m_gui_settings->GetValue(gui::gen_checkForUpdates).toBool()) {
return; return;
} }
} }
auto checkUpdate = new CheckUpdate(false); auto checkUpdate = new CheckUpdate(m_gui_settings, false);
checkUpdate->exec(); checkUpdate->exec();
} }
#endif #endif
@ -380,13 +383,13 @@ void MainWindow::CreateConnects() {
m_game_list_frame->icon_size = m_game_list_frame->icon_size =
48 + value; // 48 is the minimum icon size to use due to text disappearing. 48 + value; // 48 is the minimum icon size to use due to text disappearing.
m_game_list_frame->ResizeIcons(48 + value); m_game_list_frame->ResizeIcons(48 + value);
Config::setIconSize(48 + value); m_gui_settings->SetValue(gui::gl_icon_size, 48 + value);
Config::setSliderPosition(value); m_gui_settings->SetValue(gui::gl_slider_pos, value);
} else { } else {
m_game_grid_frame->icon_size = 69 + value; m_game_grid_frame->icon_size = 69 + value;
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
Config::setIconSizeGrid(69 + value); m_gui_settings->SetValue(gui::gg_icon_size, 69 + value);
Config::setSliderPositionGrid(value); m_gui_settings->SetValue(gui::gg_slider_pos, value);
} }
}); });
@ -404,7 +407,7 @@ void MainWindow::CreateConnects() {
&MainWindow::StartGame); &MainWindow::StartGame);
connect(ui->configureAct, &QAction::triggered, this, [this]() { connect(ui->configureAct, &QAction::triggered, this, [this]() {
auto settingsDialog = new SettingsDialog(m_compat_info, this); auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, this);
connect(settingsDialog, &SettingsDialog::LanguageChanged, this, connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
&MainWindow::OnLanguageChanged); &MainWindow::OnLanguageChanged);
@ -418,7 +421,8 @@ void MainWindow::CreateConnects() {
connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this, connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this,
[this](int opacity) { [this](int opacity) {
Config::setBackgroundImageOpacity(opacity); m_gui_settings->SetValue(gui::gl_backgroundImageOpacity,
std::clamp(opacity, 0, 100));
if (m_game_list_frame) { if (m_game_list_frame) {
QTableWidgetItem* current = m_game_list_frame->GetCurrentItem(); QTableWidgetItem* current = m_game_list_frame->GetCurrentItem();
if (current) { if (current) {
@ -437,7 +441,7 @@ void MainWindow::CreateConnects() {
}); });
connect(ui->settingsButton, &QPushButton::clicked, this, [this]() { connect(ui->settingsButton, &QPushButton::clicked, this, [this]() {
auto settingsDialog = new SettingsDialog(m_compat_info, this); auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, this);
connect(settingsDialog, &SettingsDialog::LanguageChanged, this, connect(settingsDialog, &SettingsDialog::LanguageChanged, this,
&MainWindow::OnLanguageChanged); &MainWindow::OnLanguageChanged);
@ -451,7 +455,8 @@ void MainWindow::CreateConnects() {
connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this, connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this,
[this](int opacity) { [this](int opacity) {
Config::setBackgroundImageOpacity(opacity); m_gui_settings->SetValue(gui::gl_backgroundImageOpacity,
std::clamp(opacity, 0, 100));
if (m_game_list_frame) { if (m_game_list_frame) {
QTableWidgetItem* current = m_game_list_frame->GetCurrentItem(); QTableWidgetItem* current = m_game_list_frame->GetCurrentItem();
if (current) { if (current) {
@ -481,7 +486,7 @@ void MainWindow::CreateConnects() {
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
connect(ui->updaterAct, &QAction::triggered, this, [this]() { connect(ui->updaterAct, &QAction::triggered, this, [this]() {
auto checkUpdate = new CheckUpdate(true); auto checkUpdate = new CheckUpdate(m_gui_settings, true);
checkUpdate->exec(); checkUpdate->exec();
}); });
#endif #endif
@ -496,13 +501,13 @@ void MainWindow::CreateConnects() {
m_game_list_frame->icon_size = m_game_list_frame->icon_size =
36; // 36 is the minimum icon size to use due to text disappearing. 36; // 36 is the minimum icon size to use due to text disappearing.
ui->sizeSlider->setValue(0); // icone_size - 36 ui->sizeSlider->setValue(0); // icone_size - 36
Config::setIconSize(36); m_gui_settings->SetValue(gui::gl_icon_size, 36);
Config::setSliderPosition(0); m_gui_settings->SetValue(gui::gl_slider_pos, 0);
} else { } else {
m_game_grid_frame->icon_size = 69; m_game_grid_frame->icon_size = 69;
ui->sizeSlider->setValue(0); // icone_size - 36 ui->sizeSlider->setValue(0); // icone_size - 36
Config::setIconSizeGrid(69); m_gui_settings->SetValue(gui::gg_icon_size, 69);
Config::setSliderPositionGrid(0); m_gui_settings->SetValue(gui::gg_slider_pos, 9);
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
} }
}); });
@ -511,13 +516,13 @@ void MainWindow::CreateConnects() {
if (isTableList) { if (isTableList) {
m_game_list_frame->icon_size = 64; m_game_list_frame->icon_size = 64;
ui->sizeSlider->setValue(28); ui->sizeSlider->setValue(28);
Config::setIconSize(64); m_gui_settings->SetValue(gui::gl_icon_size, 64);
Config::setSliderPosition(28); m_gui_settings->SetValue(gui::gl_slider_pos, 28);
} else { } else {
m_game_grid_frame->icon_size = 97; m_game_grid_frame->icon_size = 97;
ui->sizeSlider->setValue(28); ui->sizeSlider->setValue(28);
Config::setIconSizeGrid(97); m_gui_settings->SetValue(gui::gg_icon_size, 97);
Config::setSliderPositionGrid(28); m_gui_settings->SetValue(gui::gg_slider_pos, 28);
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
} }
}); });
@ -526,13 +531,13 @@ void MainWindow::CreateConnects() {
if (isTableList) { if (isTableList) {
m_game_list_frame->icon_size = 128; m_game_list_frame->icon_size = 128;
ui->sizeSlider->setValue(92); ui->sizeSlider->setValue(92);
Config::setIconSize(128); m_gui_settings->SetValue(gui::gl_icon_size, 128);
Config::setSliderPosition(92); m_gui_settings->SetValue(gui::gl_slider_pos, 92);
} else { } else {
m_game_grid_frame->icon_size = 161; m_game_grid_frame->icon_size = 161;
ui->sizeSlider->setValue(92); ui->sizeSlider->setValue(92);
Config::setIconSizeGrid(161); m_gui_settings->SetValue(gui::gg_icon_size, 161);
Config::setSliderPositionGrid(92); m_gui_settings->SetValue(gui::gg_slider_pos, 92);
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
} }
}); });
@ -541,13 +546,13 @@ void MainWindow::CreateConnects() {
if (isTableList) { if (isTableList) {
m_game_list_frame->icon_size = 256; m_game_list_frame->icon_size = 256;
ui->sizeSlider->setValue(220); ui->sizeSlider->setValue(220);
Config::setIconSize(256); m_gui_settings->SetValue(gui::gl_icon_size, 256);
Config::setSliderPosition(220); m_gui_settings->SetValue(gui::gl_slider_pos, 220);
} else { } else {
m_game_grid_frame->icon_size = 256; m_game_grid_frame->icon_size = 256;
ui->sizeSlider->setValue(220); ui->sizeSlider->setValue(220);
Config::setIconSizeGrid(256); m_gui_settings->SetValue(gui::gg_icon_size, 256);
Config::setSliderPositionGrid(220); m_gui_settings->SetValue(gui::gg_slider_pos, 220);
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
} }
}); });
@ -563,8 +568,8 @@ void MainWindow::CreateConnects() {
m_game_list_frame->PopulateGameList(); m_game_list_frame->PopulateGameList();
} }
isTableList = true; isTableList = true;
Config::setTableMode(0); m_gui_settings->SetValue(gui::gl_mode, 0);
int slider_pos = Config::getSliderPosition(); int slider_pos = m_gui_settings->GetValue(gui::gl_slider_pos).toInt();
ui->sizeSlider->setEnabled(true); ui->sizeSlider->setEnabled(true);
ui->sizeSlider->setSliderPosition(slider_pos); ui->sizeSlider->setSliderPosition(slider_pos);
ui->mw_searchbar->setText(""); ui->mw_searchbar->setText("");
@ -582,8 +587,8 @@ void MainWindow::CreateConnects() {
m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false);
} }
isTableList = false; isTableList = false;
Config::setTableMode(1); m_gui_settings->SetValue(gui::gl_mode, 1);
int slider_pos_grid = Config::getSliderPositionGrid(); int slider_pos_grid = m_gui_settings->GetValue(gui::gg_slider_pos).toInt();
ui->sizeSlider->setEnabled(true); ui->sizeSlider->setEnabled(true);
ui->sizeSlider->setSliderPosition(slider_pos_grid); ui->sizeSlider->setSliderPosition(slider_pos_grid);
ui->mw_searchbar->setText(""); ui->mw_searchbar->setText("");
@ -598,7 +603,7 @@ void MainWindow::CreateConnects() {
m_elf_viewer->show(); m_elf_viewer->show();
isTableList = false; isTableList = false;
ui->sizeSlider->setDisabled(true); ui->sizeSlider->setDisabled(true);
Config::setTableMode(2); m_gui_settings->SetValue(gui::gl_mode, 2);
SetLastIconSizeBullet(); SetLastIconSizeBullet();
}); });
@ -840,7 +845,7 @@ void MainWindow::CreateConnects() {
void MainWindow::StartGame() { void MainWindow::StartGame() {
BackgroundMusicPlayer::getInstance().stopMusic(); BackgroundMusicPlayer::getInstance().stopMusic();
QString gamePath = ""; QString gamePath = "";
int table_mode = Config::getTableMode(); int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt();
if (table_mode == 0) { if (table_mode == 0) {
if (m_game_list_frame->currentItem()) { if (m_game_list_frame->currentItem()) {
int itemID = m_game_list_frame->currentItem()->row(); int itemID = m_game_list_frame->currentItem()->row();
@ -925,25 +930,25 @@ void MainWindow::RefreshGameTable() {
} }
void MainWindow::ConfigureGuiFromSettings() { void MainWindow::ConfigureGuiFromSettings() {
setGeometry(Config::getMainWindowGeometryX(), Config::getMainWindowGeometryY(), if (!restoreGeometry(m_gui_settings->GetValue(gui::mw_geometry).toByteArray())) {
Config::getMainWindowGeometryW(), Config::getMainWindowGeometryH()); // By default, set the window to 70% of the screen
resize(QGuiApplication::primaryScreen()->availableSize() * 0.7);
}
ui->showGameListAct->setChecked(true); ui->showGameListAct->setChecked(true);
if (Config::getTableMode() == 0) { int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt();
if (table_mode == 0) {
ui->setlistModeListAct->setChecked(true); ui->setlistModeListAct->setChecked(true);
} else if (Config::getTableMode() == 1) { } else if (table_mode == 1) {
ui->setlistModeGridAct->setChecked(true); ui->setlistModeGridAct->setChecked(true);
} else if (Config::getTableMode() == 2) { } else if (table_mode == 2) {
ui->setlistElfAct->setChecked(true); ui->setlistElfAct->setChecked(true);
} }
BackgroundMusicPlayer::getInstance().setVolume(Config::getBGMvolume()); BackgroundMusicPlayer::getInstance().setVolume(
m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt());
} }
void MainWindow::SaveWindowState() const { void MainWindow::SaveWindowState() {
Config::setMainWindowWidth(this->width()); m_gui_settings->SetValue(gui::mw_geometry, saveGeometry(), false);
Config::setMainWindowHeight(this->height());
Config::setMainWindowGeometry(this->geometry().x(), this->geometry().y(),
this->geometry().width(), this->geometry().height());
} }
void MainWindow::BootGame() { void MainWindow::BootGame() {
@ -1024,8 +1029,8 @@ void MainWindow::SetLastUsedTheme() {
void MainWindow::SetLastIconSizeBullet() { void MainWindow::SetLastIconSizeBullet() {
// set QAction bullet point if applicable // set QAction bullet point if applicable
int lastSize = Config::getIconSize(); int lastSize = m_gui_settings->GetValue(gui::gl_icon_size).toInt();
int lastSizeGrid = Config::getIconSizeGrid(); int lastSizeGrid = m_gui_settings->GetValue(gui::gg_icon_size).toInt();
if (isTableList) { if (isTableList) {
switch (lastSize) { switch (lastSize) {
case 36: case 36:
@ -1195,7 +1200,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::KeyPress) { if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event); QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) { if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
auto tblMode = Config::getTableMode(); auto tblMode = m_gui_settings->GetValue(gui::gl_mode).toInt();
if (tblMode != 2 && (tblMode != 1 || m_game_grid_frame->IsValidCellSelected())) { if (tblMode != 2 && (tblMode != 1 || m_game_grid_frame->IsValidCellSelected())) {
StartGame(); StartGame();
return true; return true;

View file

@ -20,6 +20,7 @@
#include "game_info.h" #include "game_info.h"
#include "game_list_frame.h" #include "game_list_frame.h"
#include "game_list_utils.h" #include "game_list_utils.h"
#include "gui_settings.h"
#include "main_window_themes.h" #include "main_window_themes.h"
#include "main_window_ui.h" #include "main_window_ui.h"
@ -41,7 +42,7 @@ public:
private Q_SLOTS: private Q_SLOTS:
void ConfigureGuiFromSettings(); void ConfigureGuiFromSettings();
void SaveWindowState() const; void SaveWindowState();
void SearchGameTable(const QString& text); void SearchGameTable(const QString& text);
void ShowGameList(); void ShowGameList();
void RefreshGameTable(); void RefreshGameTable();
@ -102,6 +103,7 @@ private:
std::make_shared<CompatibilityInfoClass>(); std::make_shared<CompatibilityInfoClass>();
QTranslator* translator; QTranslator* translator;
std::shared_ptr<gui_settings> m_gui_settings;
protected: protected:
bool eventFilter(QObject* obj, QEvent* event) override; bool eventFilter(QObject* obj, QEvent* event) override;

View file

@ -107,7 +107,6 @@ public:
toggleLabelsAct = new QAction(MainWindow); toggleLabelsAct = new QAction(MainWindow);
toggleLabelsAct->setObjectName("toggleLabelsAct"); toggleLabelsAct->setObjectName("toggleLabelsAct");
toggleLabelsAct->setCheckable(true); toggleLabelsAct->setCheckable(true);
toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons());
setIconSizeTinyAct = new QAction(MainWindow); setIconSizeTinyAct = new QAction(MainWindow);
setIconSizeTinyAct->setObjectName("setIconSizeTinyAct"); setIconSizeTinyAct->setObjectName("setIconSizeTinyAct");

77
src/qt_gui/settings.cpp Normal file
View file

@ -0,0 +1,77 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <common/path_util.h>
#include "settings.h"
settings::settings(QObject* parent) : QObject(parent), m_settings_dir(ComputeSettingsDir()) {}
settings::~settings() {
sync();
}
void settings::sync() {
if (m_settings) {
m_settings->sync();
}
}
QString settings::GetSettingsDir() const {
return m_settings_dir.absolutePath();
}
QString settings::ComputeSettingsDir() {
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
return QString::fromStdString(config_dir.string() + "/");
}
void settings::RemoveValue(const QString& key, const QString& name, bool sync) const {
if (m_settings) {
m_settings->beginGroup(key);
m_settings->remove(name);
m_settings->endGroup();
if (sync) {
m_settings->sync();
}
}
}
void settings::RemoveValue(const gui_value& entry, bool sync) const {
RemoveValue(entry.key, entry.name, sync);
}
QVariant settings::GetValue(const QString& key, const QString& name, const QVariant& def) const {
return m_settings ? m_settings->value(key + "/" + name, def) : def;
}
QVariant settings::GetValue(const gui_value& entry) const {
return GetValue(entry.key, entry.name, entry.def);
}
void settings::SetValue(const gui_value& entry, const QVariant& value, bool sync) const {
SetValue(entry.key, entry.name, value, sync);
}
void settings::SetValue(const QString& key, const QVariant& value, bool sync) const {
if (m_settings) {
m_settings->setValue(key, value);
if (sync) {
m_settings->sync();
}
}
}
void settings::SetValue(const QString& key, const QString& name, const QVariant& value,
bool sync) const {
if (m_settings) {
m_settings->beginGroup(key);
m_settings->setValue(name, value);
m_settings->endGroup();
if (sync) {
m_settings->sync();
}
}
}

55
src/qt_gui/settings.h Normal file
View file

@ -0,0 +1,55 @@
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QDir>
#include <QSettings>
#include <QString>
#include <QVariant>
struct gui_value {
QString key;
QString name;
QVariant def;
gui_value() {}
gui_value(const QString& k, const QString& n, const QVariant& d) : key(k), name(n), def(d) {}
bool operator==(const gui_value& rhs) const noexcept {
return key == rhs.key && name == rhs.name && def == rhs.def;
}
};
class settings : public QObject {
Q_OBJECT
public:
explicit settings(QObject* parent = nullptr);
~settings();
void sync();
QString GetSettingsDir() const;
QVariant GetValue(const QString& key, const QString& name, const QVariant& def) const;
QVariant GetValue(const gui_value& entry) const;
public Q_SLOTS:
/** Remove entry */
void RemoveValue(const QString& key, const QString& name, bool sync = true) const;
void RemoveValue(const gui_value& entry, bool sync = true) const;
/** Write value to entry */
void SetValue(const gui_value& entry, const QVariant& value, bool sync = true) const;
void SetValue(const QString& key, const QVariant& value, bool sync = true) const;
void SetValue(const QString& key, const QString& name, const QVariant& value,
bool sync = true) const;
protected:
static QString ComputeSettingsDir();
std::unique_ptr<QSettings> m_settings;
QDir m_settings_dir;
};

View file

@ -71,9 +71,10 @@ int bgm_volume_backup;
static std::vector<QString> m_physical_devices; static std::vector<QString> m_physical_devices;
SettingsDialog::SettingsDialog(std::shared_ptr<CompatibilityInfoClass> m_compat_info, SettingsDialog::SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QWidget* parent) QWidget* parent)
: QDialog(parent), ui(new Ui::SettingsDialog) { : QDialog(parent), ui(new Ui::SettingsDialog), m_gui_settings(std::move(gui_settings)) {
ui->setupUi(this); ui->setupUi(this);
ui->tabWidgetSettings->setUsesScrollButtons(false); ui->tabWidgetSettings->setUsesScrollButtons(false);
@ -147,6 +148,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr<CompatibilityInfoClass> m_compat_
Config::save(config_dir / "config.toml"); Config::save(config_dir / "config.toml");
} else if (button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) { } else if (button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) {
Config::setDefaultValues(); Config::setDefaultValues();
setDefaultValues();
Config::save(config_dir / "config.toml"); Config::save(config_dir / "config.toml");
LoadValuesFromConfig(); LoadValuesFromConfig();
} else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) { } else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) {
@ -175,28 +177,34 @@ SettingsDialog::SettingsDialog(std::shared_ptr<CompatibilityInfoClass> m_compat_
{ {
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
[](int state) { Config::setAutoUpdate(state == Qt::Checked); }); m_gui_settings->SetValue(gui::gen_checkForUpdates, state == Qt::Checked);
});
connect(ui->changelogCheckBox, &QCheckBox::stateChanged, this, connect(ui->changelogCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
[](int state) { Config::setAlwaysShowChangelog(state == Qt::Checked); }); m_gui_settings->SetValue(gui::gen_showChangeLog, state == Qt::Checked);
});
#else #else
connect(ui->updateCheckBox, &QCheckBox::checkStateChanged, this, connect(ui->updateCheckBox, &QCheckBox::checkStateChanged, this,
[](Qt::CheckState state) { Config::setAutoUpdate(state == Qt::Checked); }); [this](Qt::CheckState state) {
m_gui_settings->SetValue(gui::gen_checkForUpdates, state == Qt::Checked);
});
connect(ui->changelogCheckBox, &QCheckBox::checkStateChanged, this, connect(ui->changelogCheckBox, &QCheckBox::checkStateChanged, this,
[](Qt::CheckState state) { Config::setAlwaysShowChangelog(state == Qt::Checked); }); [this](Qt::CheckState state) {
m_gui_settings->SetValue(gui::gen_showChangeLog, state == Qt::Checked);
});
#endif #endif
connect(ui->updateComboBox, &QComboBox::currentTextChanged, this, connect(ui->updateComboBox, &QComboBox::currentTextChanged, this,
[this](const QString& channel) { [this](const QString& channel) {
if (channelMap.contains(channel)) { if (channelMap.contains(channel)) {
Config::setUpdateChannel(channelMap.value(channel).toStdString()); m_gui_settings->SetValue(gui::gen_updateChannel, channelMap.value(channel));
} }
}); });
connect(ui->checkUpdateButton, &QPushButton::clicked, this, []() { connect(ui->checkUpdateButton, &QPushButton::clicked, this, [this]() {
auto checkUpdate = new CheckUpdate(true); auto checkUpdate = new CheckUpdate(m_gui_settings, true);
checkUpdate->exec(); checkUpdate->exec();
}); });
#else #else
@ -235,12 +243,12 @@ SettingsDialog::SettingsDialog(std::shared_ptr<CompatibilityInfoClass> m_compat_
[](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); }); [](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); });
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) #if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
connect(ui->showBackgroundImageCheckBox, &QCheckBox::stateChanged, this, [](int state) { connect(ui->showBackgroundImageCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
#else #else
connect(ui->showBackgroundImageCheckBox, &QCheckBox::checkStateChanged, this, connect(ui->showBackgroundImageCheckBox, &QCheckBox::checkStateChanged, this,
[](Qt::CheckState state) { [this](Qt::CheckState state) {
#endif #endif
Config::setShowBackgroundImage(state == Qt::Checked); m_gui_settings->SetValue(gui::gl_showBackgroundImage, state == Qt::Checked);
}); });
} }
@ -505,7 +513,7 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->changelogCheckBox->setChecked( ui->changelogCheckBox->setChecked(
toml::find_or<bool>(data, "General", "alwaysShowChangelog", false)); toml::find_or<bool>(data, "General", "alwaysShowChangelog", false));
QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); QString updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString();
ui->updateComboBox->setCurrentText( ui->updateComboBox->setCurrentText(
channelMap.key(updateChannel != "Release" && updateChannel != "Nightly" channelMap.key(updateChannel != "Release" && updateChannel != "Nightly"
? (Common::g_is_release ? "Release" : "Nightly") ? (Common::g_is_release ? "Release" : "Nightly")
@ -536,11 +544,14 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty());
ResetInstallFolders(); ResetInstallFolders();
ui->backgroundImageOpacitySlider->setValue(Config::getBackgroundImageOpacity()); ui->backgroundImageOpacitySlider->setValue(
ui->showBackgroundImageCheckBox->setChecked(Config::getShowBackgroundImage()); m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt());
ui->showBackgroundImageCheckBox->setChecked(
m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool());
backgroundImageOpacitySlider_backup = Config::getBackgroundImageOpacity(); backgroundImageOpacitySlider_backup =
bgm_volume_backup = Config::getBGMvolume(); m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt();
bgm_volume_backup = m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt();
} }
void SettingsDialog::InitializeEmulatorLanguages() { void SettingsDialog::InitializeEmulatorLanguages() {
@ -754,8 +765,7 @@ void SettingsDialog::UpdateSettings() {
} else if (ui->radioButton_Bottom->isChecked()) { } else if (ui->radioButton_Bottom->isChecked()) {
Config::setSideTrophy("bottom"); Config::setSideTrophy("bottom");
} }
m_gui_settings->SetValue(gui::gl_playBackgroundMusic, ui->playBGMCheckBox->isChecked());
Config::setPlayBGM(ui->playBGMCheckBox->isChecked());
Config::setAllowHDR(ui->enableHDRCheckBox->isChecked()); Config::setAllowHDR(ui->enableHDRCheckBox->isChecked());
Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString()); Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString());
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString()); Config::setLogFilter(ui->logFilterLineEdit->text().toStdString());
@ -764,7 +774,7 @@ void SettingsDialog::UpdateSettings() {
Config::setCursorState(ui->hideCursorComboBox->currentIndex()); Config::setCursorState(ui->hideCursorComboBox->currentIndex());
Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value()); Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value());
Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1); Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1);
Config::setBGMvolume(ui->BGMVolumeSlider->value()); m_gui_settings->SetValue(gui::gl_backgroundMusicVolume, ui->BGMVolumeSlider->value());
Config::setLanguage(languageIndexes[ui->consoleLanguageComboBox->currentIndex()]); Config::setLanguage(languageIndexes[ui->consoleLanguageComboBox->currentIndex()]);
Config::setEnableDiscordRPC(ui->discordRPCCheckbox->isChecked()); Config::setEnableDiscordRPC(ui->discordRPCCheckbox->isChecked());
Config::setScreenWidth(ui->widthSpinBox->value()); Config::setScreenWidth(ui->widthSpinBox->value());
@ -784,16 +794,19 @@ void SettingsDialog::UpdateSettings() {
Config::setVkCrashDiagnosticEnabled(ui->crashDiagnosticsCheckBox->isChecked()); Config::setVkCrashDiagnosticEnabled(ui->crashDiagnosticsCheckBox->isChecked());
Config::setCollectShaderForDebug(ui->collectShaderCheckBox->isChecked()); Config::setCollectShaderForDebug(ui->collectShaderCheckBox->isChecked());
Config::setCopyGPUCmdBuffers(ui->copyGPUBuffersCheckBox->isChecked()); Config::setCopyGPUCmdBuffers(ui->copyGPUBuffersCheckBox->isChecked());
Config::setAutoUpdate(ui->updateCheckBox->isChecked()); m_gui_settings->SetValue(gui::gen_checkForUpdates, ui->updateCheckBox->isChecked());
Config::setAlwaysShowChangelog(ui->changelogCheckBox->isChecked()); m_gui_settings->SetValue(gui::gen_showChangeLog, ui->changelogCheckBox->isChecked());
Config::setUpdateChannel(channelMap.value(ui->updateComboBox->currentText()).toStdString()); m_gui_settings->SetValue(gui::gen_updateChannel,
channelMap.value(ui->updateComboBox->currentText()));
Config::setChooseHomeTab( Config::setChooseHomeTab(
chooseHomeTabMap.value(ui->chooseHomeTabComboBox->currentText()).toStdString()); chooseHomeTabMap.value(ui->chooseHomeTabComboBox->currentText()).toStdString());
Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked()); Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked());
Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked()); Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked());
Config::setBackgroundImageOpacity(ui->backgroundImageOpacitySlider->value()); m_gui_settings->SetValue(gui::gl_backgroundImageOpacity,
std::clamp(ui->backgroundImageOpacitySlider->value(), 0, 100));
emit BackgroundOpacityChanged(ui->backgroundImageOpacitySlider->value()); emit BackgroundOpacityChanged(ui->backgroundImageOpacitySlider->value());
Config::setShowBackgroundImage(ui->showBackgroundImageCheckBox->isChecked()); m_gui_settings->SetValue(gui::gl_showBackgroundImage,
ui->showBackgroundImageCheckBox->isChecked());
std::vector<Config::GameInstallDir> dirs_with_states; std::vector<Config::GameInstallDir> dirs_with_states;
for (int i = 0; i < ui->gameFoldersListWidget->count(); i++) { for (int i = 0; i < ui->gameFoldersListWidget->count(); i++) {
@ -862,3 +875,16 @@ void SettingsDialog::ResetInstallFolders() {
Config::setAllGameInstallDirs(settings_install_dirs_config); Config::setAllGameInstallDirs(settings_install_dirs_config);
} }
} }
void SettingsDialog::setDefaultValues() {
m_gui_settings->SetValue(gui::gl_showBackgroundImage, true);
m_gui_settings->SetValue(gui::gl_backgroundImageOpacity, 50);
m_gui_settings->SetValue(gui::gl_playBackgroundMusic, false);
m_gui_settings->SetValue(gui::gl_backgroundMusicVolume, 50);
m_gui_settings->SetValue(gui::gen_checkForUpdates, false);
m_gui_settings->SetValue(gui::gen_showChangeLog, false);
if (Common::g_is_release) {
m_gui_settings->SetValue(gui::gen_updateChannel, "Release");
} else {
m_gui_settings->SetValue(gui::gen_updateChannel, "Nightly");
}
}

View file

@ -11,6 +11,7 @@
#include "common/config.h" #include "common/config.h"
#include "common/path_util.h" #include "common/path_util.h"
#include "gui_settings.h"
#include "qt_gui/compatibility_info.h" #include "qt_gui/compatibility_info.h"
namespace Ui { namespace Ui {
@ -20,7 +21,8 @@ class SettingsDialog;
class SettingsDialog : public QDialog { class SettingsDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
explicit SettingsDialog(std::shared_ptr<CompatibilityInfoClass> m_compat_info, explicit SettingsDialog(std::shared_ptr<gui_settings> gui_settings,
std::shared_ptr<CompatibilityInfoClass> m_compat_info,
QWidget* parent = nullptr); QWidget* parent = nullptr);
~SettingsDialog(); ~SettingsDialog();
@ -42,6 +44,7 @@ private:
void OnLanguageChanged(int index); void OnLanguageChanged(int index);
void OnCursorStateChanged(s16 index); void OnCursorStateChanged(s16 index);
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;
void setDefaultValues();
std::unique_ptr<Ui::SettingsDialog> ui; std::unique_ptr<Ui::SettingsDialog> ui;
@ -52,4 +55,5 @@ private:
int initialHeight; int initialHeight;
bool is_saving = false; bool is_saving = false;
std::shared_ptr<gui_settings> m_gui_settings;
}; };