diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d89524cc..12ff0b53a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1055,6 +1055,10 @@ set(QT_GUI src/qt_gui/about_dialog.cpp src/qt_gui/settings_dialog.h src/qt_gui/settings_dialog.ui 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} ${RESOURCE_FILES} ${TRANSLATIONS} diff --git a/src/common/config.cpp b/src/common/config.cpp index 6565ab82a..d8f46a17d 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -33,9 +33,7 @@ namespace Config { static bool isNeo = false; static bool isDevKit = false; -static bool playBGM = false; static bool isTrophyPopupDisabled = false; -static int BGMvolume = 50; static bool enableDiscordRPC = false; static u32 screenWidth = 1280; 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 logType = "sync"; static std::string userName = "shadPS4"; -static std::string updateChannel; static std::string chooseHomeTab; static std::string backButtonBehavior = "left"; static bool useSpecialPad = false; @@ -52,8 +49,6 @@ static bool isMotionControlsEnabled = true; static bool isDebugDump = false; static bool isShaderDebug = false; static bool isShowSplash = false; -static bool isAutoUpdate = false; -static bool isAlwaysShowChangelog = false; static std::string isSideTrophy = "right"; static bool isNullGpu = false; static bool shouldCopyGPUBuffers = false; @@ -86,27 +81,13 @@ static std::vector settings_install_dirs = {}; std::vector install_dirs_enabled = {}; std::filesystem::path settings_addon_install_dir = {}; 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 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 m_elf_viewer; std::vector m_recent_files; std::string emulator_language = "en_US"; -static int backgroundImageOpacity = 50; -static bool showBackgroundImage = true; static bool isFullscreen = false; static std::string fullscreenMode = "Windowed"; static bool isHDRAllowed = false; -static bool showLabelsUnderIcons = true; // Language u32 m_language = 1; // english @@ -176,14 +157,6 @@ bool getIsFullscreen() { return isFullscreen; } -bool getShowLabelsUnderIcons() { - return showLabelsUnderIcons; -} - -bool setShowLabelsUnderIcons() { - return false; -} - std::string getFullscreenMode() { return fullscreenMode; } @@ -192,14 +165,6 @@ bool getisTrophyPopupDisabled() { return isTrophyPopupDisabled; } -bool getPlayBGM() { - return playBGM; -} - -int getBGMvolume() { - return BGMvolume; -} - bool getEnableDiscordRPC() { return enableDiscordRPC; } @@ -240,10 +205,6 @@ std::string getUserName() { return userName; } -std::string getUpdateChannel() { - return updateChannel; -} - std::string getChooseHomeTab() { return chooseHomeTab; } @@ -276,14 +237,6 @@ bool showSplash() { return isShowSplash; } -bool autoUpdate() { - return isAutoUpdate; -} - -bool alwaysShowChangelog() { - return isAlwaysShowChangelog; -} - std::string sideTrophy() { return isSideTrophy; } @@ -384,14 +337,6 @@ void setShowSplash(bool enable) { isShowSplash = enable; } -void setAutoUpdate(bool enable) { - isAutoUpdate = enable; -} - -void setAlwaysShowChangelog(bool enable) { - isAlwaysShowChangelog = enable; -} - void setSideTrophy(std::string side) { isSideTrophy = side; } @@ -431,9 +376,6 @@ void setVblankDiv(u32 value) { void setIsFullscreen(bool enable) { isFullscreen = enable; } -static void setShowLabelsUnderIcons(bool enable) { - showLabelsUnderIcons = enable; -} void setFullscreenMode(std::string mode) { fullscreenMode = mode; @@ -443,14 +385,6 @@ void setisTrophyPopupDisabled(bool disable) { isTrophyPopupDisabled = disable; } -void setPlayBGM(bool enable) { - playBGM = enable; -} - -void setBGMvolume(int volume) { - BGMvolume = volume; -} - void setEnableDiscordRPC(bool enable) { enableDiscordRPC = enable; } @@ -490,9 +424,6 @@ void setUserName(const std::string& type) { userName = type; } -void setUpdateChannel(const std::string& type) { - updateChannel = type; -} void setChooseHomeTab(const std::string& type) { chooseHomeTab = type; } @@ -521,13 +452,6 @@ void setCheckCompatibilityOnStartup(bool 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) { for (const auto& install_dir : settings_install_dirs) { if (install_dir.path == dir) { @@ -564,34 +488,6 @@ void setMainWindowTheme(u32 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& elfList) { m_elf_viewer.resize(elfList.size()); m_elf_viewer = elfList; @@ -621,22 +517,6 @@ void setSaveDataPath(const std::filesystem::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 getGameInstallDirs() { std::vector enabled_dirs; for (const auto& dir : settings_install_dirs) { @@ -667,34 +547,6 @@ u32 getMainWindowTheme() { 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 getElfViewer() { return m_elf_viewer; } @@ -715,22 +567,6 @@ bool getSeparateLogFilesEnabled() { 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() { return isPSNSignedIn; } @@ -764,23 +600,14 @@ void load(const std::filesystem::path& path) { isNeo = toml::find_or(general, "isPS4Pro", false); isDevKit = toml::find_or(general, "isDevKit", false); isPSNSignedIn = toml::find_or(general, "isPSNSignedIn", false); - playBGM = toml::find_or(general, "playBGM", false); isTrophyPopupDisabled = toml::find_or(general, "isTrophyPopupDisabled", false); trophyNotificationDuration = toml::find_or(general, "trophyNotificationDuration", 5.0); - BGMvolume = toml::find_or(general, "BGMvolume", 50); enableDiscordRPC = toml::find_or(general, "enableDiscordRPC", true); logFilter = toml::find_or(general, "logFilter", ""); logType = toml::find_or(general, "logType", "sync"); userName = toml::find_or(general, "userName", "shadPS4"); - if (Common::g_is_release) { - updateChannel = toml::find_or(general, "updateChannel", "Release"); - } else { - updateChannel = toml::find_or(general, "updateChannel", "Nightly"); - } isShowSplash = toml::find_or(general, "showSplash", true); - isAutoUpdate = toml::find_or(general, "autoUpdate", false); - isAlwaysShowChangelog = toml::find_or(general, "alwaysShowChangelog", false); isSideTrophy = toml::find_or(general, "sideTrophy", "right"); compatibilityData = toml::find_or(general, "compatibilityEnabled", false); checkCompatibilityOnStartup = @@ -841,13 +668,7 @@ void load(const std::filesystem::path& path) { const toml::value& gui = data.at("GUI"); load_game_size = toml::find_or(gui, "loadGameSizeEnabled", true); - m_icon_size = toml::find_or(gui, "iconSize", 0); - m_icon_size_grid = toml::find_or(gui, "iconSizeGrid", 0); - m_slider_pos = toml::find_or(gui, "sliderPos", 0); - m_slider_pos_grid = toml::find_or(gui, "sliderPosGrid", 0); mw_themes = toml::find_or(gui, "theme", 0); - m_window_size_W = toml::find_or(gui, "mw_width", 0); - m_window_size_H = toml::find_or(gui, "mw_height", 0); const auto install_dir_array = toml::find_or>(gui, "installDirs", {}); @@ -872,16 +693,9 @@ void load(const std::filesystem::path& path) { save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); - main_window_geometry_x = toml::find_or(gui, "geometry_x", 0); - main_window_geometry_y = toml::find_or(gui, "geometry_y", 0); - main_window_geometry_w = toml::find_or(gui, "geometry_w", 0); - main_window_geometry_h = toml::find_or(gui, "geometry_h", 0); m_elf_viewer = toml::find_or>(gui, "elfDirs", {}); m_recent_files = toml::find_or>(gui, "recentFiles", {}); - m_table_mode = toml::find_or(gui, "gameTableMode", 0); emulator_language = toml::find_or(gui, "emulatorLanguage", "en_US"); - backgroundImageOpacity = toml::find_or(gui, "backgroundImageOpacity", 50); - showBackgroundImage = toml::find_or(gui, "showBackgroundImage", true); } 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 const std::vector allowed_languages = { - "ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU", - "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", "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"}; + "ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", + "fr_FR", "hu_HU", "id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", + "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) == allowed_languages.end()) { @@ -966,17 +781,12 @@ void save(const std::filesystem::path& path) { data["General"]["isPSNSignedIn"] = isPSNSignedIn; data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled; data["General"]["trophyNotificationDuration"] = trophyNotificationDuration; - data["General"]["playBGM"] = playBGM; - data["General"]["BGMvolume"] = BGMvolume; data["General"]["enableDiscordRPC"] = enableDiscordRPC; data["General"]["logFilter"] = logFilter; data["General"]["logType"] = logType; data["General"]["userName"] = userName; - data["General"]["updateChannel"] = updateChannel; data["General"]["chooseHomeTab"] = chooseHomeTab; data["General"]["showSplash"] = isShowSplash; - data["General"]["autoUpdate"] = isAutoUpdate; - data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog; data["General"]["sideTrophy"] = isSideTrophy; data["General"]["compatibilityEnabled"] = compatibilityData; data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup; @@ -1046,8 +856,6 @@ void save(const std::filesystem::path& path) { data["GUI"]["addonInstallDir"] = std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; data["GUI"]["emulatorLanguage"] = emulator_language; - data["GUI"]["backgroundImageOpacity"] = backgroundImageOpacity; - data["GUI"]["showBackgroundImage"] = showBackgroundImage; data["Settings"]["consoleLanguage"] = m_language; // 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())); } - data["GUI"]["mw_width"] = m_window_size_W; - data["GUI"]["mw_height"] = m_window_size_H; 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"]["recentFiles"] = m_recent_files; @@ -1112,19 +909,13 @@ void setDefaultValues() { isPSNSignedIn = false; isFullscreen = false; isTrophyPopupDisabled = false; - playBGM = false; - BGMvolume = 50; enableDiscordRPC = true; screenWidth = 1280; screenHeight = 720; logFilter = ""; logType = "sync"; userName = "shadPS4"; - if (Common::g_is_release) { - updateChannel = "Release"; - } else { - updateChannel = "Nightly"; - } + chooseHomeTab = "General"; cursorState = HideCursorState::Idle; cursorHideTimeout = 5; @@ -1135,8 +926,6 @@ void setDefaultValues() { isDebugDump = false; isShaderDebug = false; isShowSplash = false; - isAutoUpdate = false; - isAlwaysShowChangelog = false; isSideTrophy = "right"; isNullGpu = false; shouldDumpShaders = false; @@ -1153,8 +942,6 @@ void setDefaultValues() { gpuId = -1; compatibilityData = false; checkCompatibilityOnStartup = false; - backgroundImageOpacity = 50; - showBackgroundImage = true; } constexpr std::string_view GetDefaultKeyboardConfig() { diff --git a/src/common/config.h b/src/common/config.h index 404854ae2..414bc122e 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -26,25 +26,18 @@ bool GetLoadGameSizeEnabled(); std::filesystem::path GetSaveDataPath(); void setLoadGameSizeEnabled(bool enable); bool getIsFullscreen(); -bool getShowLabelsUnderIcons(); -bool setShowLabelsUnderIcons(); std::string getFullscreenMode(); bool isNeoModeConsole(); bool isDevKitConsole(); -bool getPlayBGM(); -int getBGMvolume(); bool getisTrophyPopupDisabled(); bool getEnableDiscordRPC(); bool getCompatibilityEnabled(); bool getCheckCompatibilityOnStartup(); -int getBackgroundImageOpacity(); -bool getShowBackgroundImage(); bool getPSNSignedIn(); std::string getLogFilter(); std::string getLogType(); std::string getUserName(); -std::string getUpdateChannel(); std::string getChooseHomeTab(); s16 getCursorState(); @@ -69,8 +62,6 @@ bool allowHDR(); bool debugDump(); bool collectShadersForDebug(); bool showSplash(); -bool autoUpdate(); -bool alwaysShowChangelog(); std::string sideTrophy(); bool nullGpu(); bool copyGPUCmdBuffers(); @@ -83,8 +74,6 @@ u32 vblankDiv(); void setDebugDump(bool enable); void setCollectShaderForDebug(bool enable); void setShowSplash(bool enable); -void setAutoUpdate(bool enable); -void setAlwaysShowChangelog(bool enable); void setSideTrophy(std::string side); void setNullGpu(bool enable); void setAllowHDR(bool enable); @@ -97,21 +86,16 @@ void setScreenHeight(u32 height); void setIsFullscreen(bool enable); void setFullscreenMode(std::string mode); void setisTrophyPopupDisabled(bool disable); -void setPlayBGM(bool enable); -void setBGMvolume(int volume); void setEnableDiscordRPC(bool enable); void setLanguage(u32 language); void setNeoMode(bool enable); void setUserName(const std::string& type); -void setUpdateChannel(const std::string& type); void setChooseHomeTab(const std::string& type); void setGameInstallDirs(const std::vector& dirs_config); void setAllGameInstallDirs(const std::vector& dirs_config); void setSaveDataPath(const std::filesystem::path& path); void setCompatibilityEnabled(bool use); void setCheckCompatibilityOnStartup(bool use); -void setBackgroundImageOpacity(int opacity); -void setShowBackgroundImage(bool show); void setPSNSignedIn(bool sign); void setCursorState(s16 cursorState); @@ -141,38 +125,19 @@ void setVkHostMarkersEnabled(bool enable); void setVkGuestMarkersEnabled(bool enable); // Gui -void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h); bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true); void removeGameInstallDir(const std::filesystem::path& dir); void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled); void setAddonInstallDir(const std::filesystem::path& dir); 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& elfList); void setRecentFiles(const std::vector& recentFiles); void setEmulatorLanguage(std::string language); -u32 getMainWindowGeometryX(); -u32 getMainWindowGeometryY(); -u32 getMainWindowGeometryW(); -u32 getMainWindowGeometryH(); const std::vector getGameInstallDirs(); const std::vector getGameInstallDirsEnabled(); std::filesystem::path getAddonInstallDir(); u32 getMainWindowTheme(); -u32 getIconSize(); -u32 getIconSizeGrid(); -u32 getSliderPosition(); -u32 getSliderPositionGrid(); -u32 getTableMode(); -u32 getMainWindowWidth(); -u32 getMainWindowHeight(); std::vector getElfViewer(); std::vector getRecentFiles(); std::string getEmulatorLanguage(); diff --git a/src/main.cpp b/src/main.cpp index 8a251c55a..fe245d104 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,7 @@ int main(int argc, char* argv[]) { " -f, --fullscreen Specify window initial fullscreen " "state. Does not overwrite the config file.\n" " --add-game-folder Adds a new game folder to the config.\n" + " --set-addon-folder Sets the addon folder to the config.\n" " -h, --help Display this help message\n"; exit(0); }}, @@ -116,7 +117,24 @@ int main(int argc, char* argv[]) { std::cout << "Game folder successfully saved.\n"; 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) { int dummy = 0; // one does not simply pass 0 directly diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp index b0858840a..10c986411 100644 --- a/src/qt_gui/check_update.cpp +++ b/src/qt_gui/check_update.cpp @@ -28,8 +28,10 @@ using namespace Common::FS; -CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent) - : QDialog(parent), networkManager(new QNetworkAccessManager(this)) { +CheckUpdate::CheckUpdate(std::shared_ptr gui_settings, const bool showMessage, + QWidget* parent) + : QDialog(parent), m_gui_settings(std::move(gui_settings)), + networkManager(new QNetworkAccessManager(this)) { setWindowTitle(tr("Auto Updater")); setFixedSize(0, 0); CheckForUpdates(showMessage); @@ -43,7 +45,7 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) { bool checkName = true; while (checkName) { - updateChannel = QString::fromStdString(Config::getUpdateChannel()); + updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString(); if (updateChannel == "Nightly") { url = QUrl("https://api.github.com/repos/shadps4-emu/shadPS4/releases"); checkName = false; @@ -52,12 +54,10 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) { checkName = false; } else { if (Common::g_is_release) { - Config::setUpdateChannel("Release"); + m_gui_settings->SetValue(gui::gen_updateChannel, "Release"); } 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); layout->addLayout(titleLayout); - QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); + QString updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString(); QString updateText = QString("

" + tr("Update Channel") + ": " + updateChannel + "
" @@ -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); textField->setVisible(true); 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(); }); - autoUpdateCheckBox->setChecked(Config::autoUpdate()); + autoUpdateCheckBox->setChecked(m_gui_settings->GetValue(gui::gen_checkForUpdates).toBool()); #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 - connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [](Qt::CheckState state) { + connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [this](Qt::CheckState state) { #endif 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"); }); diff --git a/src/qt_gui/check_update.h b/src/qt_gui/check_update.h index dfeb95e73..139059c41 100644 --- a/src/qt_gui/check_update.h +++ b/src/qt_gui/check_update.h @@ -8,12 +8,14 @@ #include #include #include +#include "gui_settings.h" class CheckUpdate : public QDialog { Q_OBJECT public: - explicit CheckUpdate(const bool showMessage, QWidget* parent = nullptr); + explicit CheckUpdate(std::shared_ptr gui_settings, const bool showMessage, + QWidget* parent = nullptr); ~CheckUpdate(); private slots: @@ -35,6 +37,7 @@ private: QString updateDownloadUrl; QNetworkAccessManager* networkManager; + std::shared_ptr m_gui_settings; }; #endif // CHECKUPDATE_H diff --git a/src/qt_gui/game_grid_frame.cpp b/src/qt_gui/game_grid_frame.cpp index e06fea090..66679dc71 100644 --- a/src/qt_gui/game_grid_frame.cpp +++ b/src/qt_gui/game_grid_frame.cpp @@ -5,11 +5,13 @@ #include "game_grid_frame.h" #include "qt_gui/compatibility_info.h" -GameGridFrame::GameGridFrame(std::shared_ptr game_info_get, +GameGridFrame::GameGridFrame(std::shared_ptr gui_settings, + std::shared_ptr game_info_get, std::shared_ptr compat_info_get, QWidget* parent) - : QTableWidget(parent), m_game_info(game_info_get), m_compat_info(compat_info_get) { - icon_size = Config::getIconSizeGrid(); + : QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get), + m_compat_info(compat_info_get) { + icon_size = m_gui_settings->GetValue(gui::gg_icon_size).toInt(); windowWidth = parent->width(); this->setShowGrid(false); this->setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -74,7 +76,7 @@ void GameGridFrame::onCurrentCellChanged(int currentRow, int currentColumn, int } void GameGridFrame::PlayBackgroundMusic(QString path) { - if (path.isEmpty() || !Config::getPlayBGM()) { + if (path.isEmpty() || !m_gui_settings->GetValue(gui::gl_playBackgroundMusic).toBool()) { BackgroundMusicPlayer::getInstance().stopMusic(); return; } @@ -91,7 +93,8 @@ void GameGridFrame::PopulateGameGrid(QVector m_games_search, bool from else m_games_ = m_game_info->m_games; m_games_shared = std::make_shared>(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 row = 0; @@ -118,7 +121,7 @@ void GameGridFrame::PopulateGameGrid(QVector m_games_search, bool from layout->addWidget(name_label); // 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("color: white; font-weight: bold; font-size: %1px;").arg(fontSize); 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 (!Config::getShowBackgroundImage()) { + if (!m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) { backgroundImage = QImage(); m_last_opacity = -1; // Reset opacity tracking when disabled 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 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 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() { QPalette palette; - if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { + if (!backgroundImage.isNull() && + m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) { QSize widgetSize = size(); QPixmap scaledPixmap = QPixmap::fromImage(backgroundImage) diff --git a/src/qt_gui/game_grid_frame.h b/src/qt_gui/game_grid_frame.h index 14596f8e1..22d278a21 100644 --- a/src/qt_gui/game_grid_frame.h +++ b/src/qt_gui/game_grid_frame.h @@ -11,6 +11,7 @@ #include "game_info.h" #include "game_list_utils.h" #include "gui_context_menus.h" +#include "gui_settings.h" #include "qt_gui/compatibility_info.h" class GameGridFrame : public QTableWidget { @@ -37,9 +38,11 @@ private: bool validCellSelected = false; 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::shared_ptr m_gui_settings; public: - explicit GameGridFrame(std::shared_ptr game_info_get, + explicit GameGridFrame(std::shared_ptr gui_settings, + std::shared_ptr game_info_get, std::shared_ptr compat_info_get, QWidget* parent = nullptr); void PopulateGameGrid(QVector m_games, bool fromSearch); diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index 170215f3d..dd10e0f8b 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -9,11 +9,13 @@ #include "game_list_frame.h" #include "game_list_utils.h" -GameListFrame::GameListFrame(std::shared_ptr game_info_get, +GameListFrame::GameListFrame(std::shared_ptr gui_settings, + std::shared_ptr game_info_get, std::shared_ptr compat_info_get, QWidget* parent) - : QTableWidget(parent), m_game_info(game_info_get), m_compat_info(compat_info_get) { - icon_size = Config::getIconSize(); + : QTableWidget(parent), m_gui_settings(std::move(gui_settings)), m_game_info(game_info_get), + m_compat_info(compat_info_get) { + icon_size = m_gui_settings->GetValue(gui::gl_icon_size).toInt(); this->setShowGrid(false); this->setEditTriggers(QAbstractItemView::NoEditTriggers); this->setSelectionBehavior(QAbstractItemView::SelectRows); @@ -97,7 +99,7 @@ void GameListFrame::onCurrentCellChanged(int currentRow, int currentColumn, int } void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) { - if (!item || !Config::getPlayBGM()) { + if (!item || !m_gui_settings->GetValue(gui::gl_playBackgroundMusic).toBool()) { BackgroundMusicPlayer::getInstance().stopMusic(); return; } @@ -172,7 +174,7 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { } // If background images are hidden, clear the background image - if (!Config::getShowBackgroundImage()) { + if (!m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) { backgroundImage = QImage(); m_last_opacity = -1; // Reset opacity tracking when disabled 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 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 if (opacity != m_last_opacity || game.pic_path != m_current_game_path) { @@ -200,7 +202,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) { void GameListFrame::RefreshListBackgroundImage() { QPalette palette; - if (!backgroundImage.isNull() && Config::getShowBackgroundImage()) { + if (!backgroundImage.isNull() && + m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()) { QSize widgetSize = size(); QPixmap scaledPixmap = QPixmap::fromImage(backgroundImage) diff --git a/src/qt_gui/game_list_frame.h b/src/qt_gui/game_list_frame.h index 782db6bae..f70d73054 100644 --- a/src/qt_gui/game_list_frame.h +++ b/src/qt_gui/game_list_frame.h @@ -17,11 +17,13 @@ #include "game_info.h" #include "game_list_utils.h" #include "gui_context_menus.h" +#include "gui_settings.h" class GameListFrame : public QTableWidget { Q_OBJECT public: - explicit GameListFrame(std::shared_ptr game_info_get, + explicit GameListFrame(std::shared_ptr gui_settings, + std::shared_ptr game_info_get, std::shared_ptr compat_info_get, QWidget* parent = nullptr); Q_SIGNALS: @@ -48,6 +50,7 @@ private: QTableWidgetItem* m_current_item = nullptr; 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::shared_ptr m_gui_settings; public: void PopulateGameList(bool isInitialPopulation = true); diff --git a/src/qt_gui/gui_settings.cpp b/src/qt_gui/gui_settings.cpp new file mode 100644 index 000000000..4de6b7f19 --- /dev/null +++ b/src/qt_gui/gui_settings.cpp @@ -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(ComputeSettingsDir() + "qt_ui.ini", + QSettings::Format::IniFormat, parent); +} diff --git a/src/qt_gui/gui_settings.h b/src/qt_gui/gui_settings.h new file mode 100644 index 000000000..da5542956 --- /dev/null +++ b/src/qt_gui/gui_settings.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#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; +}; diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 906a3066e..c6da49182 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -32,6 +32,9 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi ui->setupUi(this); installEventFilter(this); setAttribute(Qt::WA_DeleteOnClose); + m_gui_settings = std::make_shared(); + ui->toggleLabelsAct->setChecked( + m_gui_settings->GetValue(gui::mw_showLabelsUnderIcons).toBool()); } MainWindow::~MainWindow() { @@ -139,7 +142,7 @@ void MainWindow::PauseGame() { void MainWindow::toggleLabelsUnderIcons() { bool showLabels = ui->toggleLabelsAct->isChecked(); - Config::setShowLabelsUnderIcons(); + m_gui_settings->SetValue(gui::mw_showLabelsUnderIcons, showLabels); UpdateToolbarLabels(); if (isGameRunning) { UpdateToolbarButtons(); @@ -290,21 +293,21 @@ void MainWindow::CreateDockWindows() { setCentralWidget(phCentralWidget); 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_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_elf_viewer.reset(new ElfViewer(this)); 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; if (table_mode == 0) { // List m_game_grid_frame->hide(); m_elf_viewer->hide(); m_game_list_frame->show(); 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; isTableList = true; } else if (table_mode == 1) { // Grid @@ -312,7 +315,7 @@ void MainWindow::CreateDockWindows() { m_elf_viewer->hide(); m_game_grid_frame->show(); 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; isTableList = false; } else { @@ -356,11 +359,11 @@ void MainWindow::LoadGameLists() { #ifdef ENABLE_UPDATER void MainWindow::CheckUpdateMain(bool checkSave) { if (checkSave) { - if (!Config::autoUpdate()) { + if (!m_gui_settings->GetValue(gui::gen_checkForUpdates).toBool()) { return; } } - auto checkUpdate = new CheckUpdate(false); + auto checkUpdate = new CheckUpdate(m_gui_settings, false); checkUpdate->exec(); } #endif @@ -380,13 +383,13 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 48 + value; // 48 is the minimum icon size to use due to text disappearing. m_game_list_frame->ResizeIcons(48 + value); - Config::setIconSize(48 + value); - Config::setSliderPosition(value); + m_gui_settings->SetValue(gui::gl_icon_size, 48 + value); + m_gui_settings->SetValue(gui::gl_slider_pos, value); } else { m_game_grid_frame->icon_size = 69 + value; m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); - Config::setIconSizeGrid(69 + value); - Config::setSliderPositionGrid(value); + m_gui_settings->SetValue(gui::gg_icon_size, 69 + value); + m_gui_settings->SetValue(gui::gg_slider_pos, value); } }); @@ -404,7 +407,7 @@ void MainWindow::CreateConnects() { &MainWindow::StartGame); 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, &MainWindow::OnLanguageChanged); @@ -418,7 +421,8 @@ void MainWindow::CreateConnects() { connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this, [this](int opacity) { - Config::setBackgroundImageOpacity(opacity); + m_gui_settings->SetValue(gui::gl_backgroundImageOpacity, + std::clamp(opacity, 0, 100)); if (m_game_list_frame) { QTableWidgetItem* current = m_game_list_frame->GetCurrentItem(); if (current) { @@ -437,7 +441,7 @@ void MainWindow::CreateConnects() { }); 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, &MainWindow::OnLanguageChanged); @@ -451,7 +455,8 @@ void MainWindow::CreateConnects() { connect(settingsDialog, &SettingsDialog::BackgroundOpacityChanged, this, [this](int opacity) { - Config::setBackgroundImageOpacity(opacity); + m_gui_settings->SetValue(gui::gl_backgroundImageOpacity, + std::clamp(opacity, 0, 100)); if (m_game_list_frame) { QTableWidgetItem* current = m_game_list_frame->GetCurrentItem(); if (current) { @@ -481,7 +486,7 @@ void MainWindow::CreateConnects() { #ifdef ENABLE_UPDATER connect(ui->updaterAct, &QAction::triggered, this, [this]() { - auto checkUpdate = new CheckUpdate(true); + auto checkUpdate = new CheckUpdate(m_gui_settings, true); checkUpdate->exec(); }); #endif @@ -496,13 +501,13 @@ void MainWindow::CreateConnects() { m_game_list_frame->icon_size = 36; // 36 is the minimum icon size to use due to text disappearing. ui->sizeSlider->setValue(0); // icone_size - 36 - Config::setIconSize(36); - Config::setSliderPosition(0); + m_gui_settings->SetValue(gui::gl_icon_size, 36); + m_gui_settings->SetValue(gui::gl_slider_pos, 0); } else { m_game_grid_frame->icon_size = 69; ui->sizeSlider->setValue(0); // icone_size - 36 - Config::setIconSizeGrid(69); - Config::setSliderPositionGrid(0); + m_gui_settings->SetValue(gui::gg_icon_size, 69); + m_gui_settings->SetValue(gui::gg_slider_pos, 9); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); } }); @@ -511,13 +516,13 @@ void MainWindow::CreateConnects() { if (isTableList) { m_game_list_frame->icon_size = 64; ui->sizeSlider->setValue(28); - Config::setIconSize(64); - Config::setSliderPosition(28); + m_gui_settings->SetValue(gui::gl_icon_size, 64); + m_gui_settings->SetValue(gui::gl_slider_pos, 28); } else { m_game_grid_frame->icon_size = 97; ui->sizeSlider->setValue(28); - Config::setIconSizeGrid(97); - Config::setSliderPositionGrid(28); + m_gui_settings->SetValue(gui::gg_icon_size, 97); + m_gui_settings->SetValue(gui::gg_slider_pos, 28); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); } }); @@ -526,13 +531,13 @@ void MainWindow::CreateConnects() { if (isTableList) { m_game_list_frame->icon_size = 128; ui->sizeSlider->setValue(92); - Config::setIconSize(128); - Config::setSliderPosition(92); + m_gui_settings->SetValue(gui::gl_icon_size, 128); + m_gui_settings->SetValue(gui::gl_slider_pos, 92); } else { m_game_grid_frame->icon_size = 161; ui->sizeSlider->setValue(92); - Config::setIconSizeGrid(161); - Config::setSliderPositionGrid(92); + m_gui_settings->SetValue(gui::gg_icon_size, 161); + m_gui_settings->SetValue(gui::gg_slider_pos, 92); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); } }); @@ -541,13 +546,13 @@ void MainWindow::CreateConnects() { if (isTableList) { m_game_list_frame->icon_size = 256; ui->sizeSlider->setValue(220); - Config::setIconSize(256); - Config::setSliderPosition(220); + m_gui_settings->SetValue(gui::gl_icon_size, 256); + m_gui_settings->SetValue(gui::gl_slider_pos, 220); } else { m_game_grid_frame->icon_size = 256; ui->sizeSlider->setValue(220); - Config::setIconSizeGrid(256); - Config::setSliderPositionGrid(220); + m_gui_settings->SetValue(gui::gg_icon_size, 256); + m_gui_settings->SetValue(gui::gg_slider_pos, 220); m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); } }); @@ -563,8 +568,8 @@ void MainWindow::CreateConnects() { m_game_list_frame->PopulateGameList(); } isTableList = true; - Config::setTableMode(0); - int slider_pos = Config::getSliderPosition(); + m_gui_settings->SetValue(gui::gl_mode, 0); + int slider_pos = m_gui_settings->GetValue(gui::gl_slider_pos).toInt(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos); ui->mw_searchbar->setText(""); @@ -582,8 +587,8 @@ void MainWindow::CreateConnects() { m_game_grid_frame->PopulateGameGrid(m_game_info->m_games, false); } isTableList = false; - Config::setTableMode(1); - int slider_pos_grid = Config::getSliderPositionGrid(); + m_gui_settings->SetValue(gui::gl_mode, 1); + int slider_pos_grid = m_gui_settings->GetValue(gui::gg_slider_pos).toInt(); ui->sizeSlider->setEnabled(true); ui->sizeSlider->setSliderPosition(slider_pos_grid); ui->mw_searchbar->setText(""); @@ -598,7 +603,7 @@ void MainWindow::CreateConnects() { m_elf_viewer->show(); isTableList = false; ui->sizeSlider->setDisabled(true); - Config::setTableMode(2); + m_gui_settings->SetValue(gui::gl_mode, 2); SetLastIconSizeBullet(); }); @@ -840,7 +845,7 @@ void MainWindow::CreateConnects() { void MainWindow::StartGame() { BackgroundMusicPlayer::getInstance().stopMusic(); QString gamePath = ""; - int table_mode = Config::getTableMode(); + int table_mode = m_gui_settings->GetValue(gui::gl_mode).toInt(); if (table_mode == 0) { if (m_game_list_frame->currentItem()) { int itemID = m_game_list_frame->currentItem()->row(); @@ -925,25 +930,25 @@ void MainWindow::RefreshGameTable() { } void MainWindow::ConfigureGuiFromSettings() { - setGeometry(Config::getMainWindowGeometryX(), Config::getMainWindowGeometryY(), - Config::getMainWindowGeometryW(), Config::getMainWindowGeometryH()); - + if (!restoreGeometry(m_gui_settings->GetValue(gui::mw_geometry).toByteArray())) { + // By default, set the window to 70% of the screen + resize(QGuiApplication::primaryScreen()->availableSize() * 0.7); + } 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); - } else if (Config::getTableMode() == 1) { + } else if (table_mode == 1) { ui->setlistModeGridAct->setChecked(true); - } else if (Config::getTableMode() == 2) { + } else if (table_mode == 2) { ui->setlistElfAct->setChecked(true); } - BackgroundMusicPlayer::getInstance().setVolume(Config::getBGMvolume()); + BackgroundMusicPlayer::getInstance().setVolume( + m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt()); } -void MainWindow::SaveWindowState() const { - Config::setMainWindowWidth(this->width()); - Config::setMainWindowHeight(this->height()); - Config::setMainWindowGeometry(this->geometry().x(), this->geometry().y(), - this->geometry().width(), this->geometry().height()); +void MainWindow::SaveWindowState() { + m_gui_settings->SetValue(gui::mw_geometry, saveGeometry(), false); } void MainWindow::BootGame() { @@ -1024,8 +1029,8 @@ void MainWindow::SetLastUsedTheme() { void MainWindow::SetLastIconSizeBullet() { // set QAction bullet point if applicable - int lastSize = Config::getIconSize(); - int lastSizeGrid = Config::getIconSizeGrid(); + int lastSize = m_gui_settings->GetValue(gui::gl_icon_size).toInt(); + int lastSizeGrid = m_gui_settings->GetValue(gui::gg_icon_size).toInt(); if (isTableList) { switch (lastSize) { case 36: @@ -1195,7 +1200,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); 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())) { StartGame(); return true; diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index 97c56433d..7f11f7310 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -20,6 +20,7 @@ #include "game_info.h" #include "game_list_frame.h" #include "game_list_utils.h" +#include "gui_settings.h" #include "main_window_themes.h" #include "main_window_ui.h" @@ -41,7 +42,7 @@ public: private Q_SLOTS: void ConfigureGuiFromSettings(); - void SaveWindowState() const; + void SaveWindowState(); void SearchGameTable(const QString& text); void ShowGameList(); void RefreshGameTable(); @@ -102,6 +103,7 @@ private: std::make_shared(); QTranslator* translator; + std::shared_ptr m_gui_settings; protected: bool eventFilter(QObject* obj, QEvent* event) override; diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 4d3481c07..4ce71013e 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -107,7 +107,6 @@ public: toggleLabelsAct = new QAction(MainWindow); toggleLabelsAct->setObjectName("toggleLabelsAct"); toggleLabelsAct->setCheckable(true); - toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons()); setIconSizeTinyAct = new QAction(MainWindow); setIconSizeTinyAct->setObjectName("setIconSizeTinyAct"); diff --git a/src/qt_gui/settings.cpp b/src/qt_gui/settings.cpp new file mode 100644 index 000000000..44133dac5 --- /dev/null +++ b/src/qt_gui/settings.cpp @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#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(); + } + } +} diff --git a/src/qt_gui/settings.h b/src/qt_gui/settings.h new file mode 100644 index 000000000..da71fe01a --- /dev/null +++ b/src/qt_gui/settings.h @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include +#include + +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 m_settings; + QDir m_settings_dir; +}; diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 914cc5470..fc00c6f75 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -71,9 +71,10 @@ int bgm_volume_backup; static std::vector m_physical_devices; -SettingsDialog::SettingsDialog(std::shared_ptr m_compat_info, +SettingsDialog::SettingsDialog(std::shared_ptr gui_settings, + std::shared_ptr m_compat_info, 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->tabWidgetSettings->setUsesScrollButtons(false); @@ -147,6 +148,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr m_compat_ Config::save(config_dir / "config.toml"); } else if (button == ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)) { Config::setDefaultValues(); + setDefaultValues(); Config::save(config_dir / "config.toml"); LoadValuesFromConfig(); } else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) { @@ -175,28 +177,34 @@ SettingsDialog::SettingsDialog(std::shared_ptr m_compat_ { #ifdef ENABLE_UPDATER #if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) - connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, - [](int state) { Config::setAutoUpdate(state == Qt::Checked); }); + connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, [this](int state) { + m_gui_settings->SetValue(gui::gen_checkForUpdates, state == Qt::Checked); + }); - connect(ui->changelogCheckBox, &QCheckBox::stateChanged, this, - [](int state) { Config::setAlwaysShowChangelog(state == Qt::Checked); }); + connect(ui->changelogCheckBox, &QCheckBox::stateChanged, this, [this](int state) { + m_gui_settings->SetValue(gui::gen_showChangeLog, state == Qt::Checked); + }); #else 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, - [](Qt::CheckState state) { Config::setAlwaysShowChangelog(state == Qt::Checked); }); + [this](Qt::CheckState state) { + m_gui_settings->SetValue(gui::gen_showChangeLog, state == Qt::Checked); + }); #endif connect(ui->updateComboBox, &QComboBox::currentTextChanged, this, [this](const QString& 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, []() { - auto checkUpdate = new CheckUpdate(true); + connect(ui->checkUpdateButton, &QPushButton::clicked, this, [this]() { + auto checkUpdate = new CheckUpdate(m_gui_settings, true); checkUpdate->exec(); }); #else @@ -235,12 +243,12 @@ SettingsDialog::SettingsDialog(std::shared_ptr m_compat_ [](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); }); #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 connect(ui->showBackgroundImageCheckBox, &QCheckBox::checkStateChanged, this, - [](Qt::CheckState state) { + [this](Qt::CheckState state) { #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( toml::find_or(data, "General", "alwaysShowChangelog", false)); - QString updateChannel = QString::fromStdString(Config::getUpdateChannel()); + QString updateChannel = m_gui_settings->GetValue(gui::gen_updateChannel).toString(); ui->updateComboBox->setCurrentText( channelMap.key(updateChannel != "Release" && updateChannel != "Nightly" ? (Common::g_is_release ? "Release" : "Nightly") @@ -536,11 +544,14 @@ void SettingsDialog::LoadValuesFromConfig() { ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); ResetInstallFolders(); - ui->backgroundImageOpacitySlider->setValue(Config::getBackgroundImageOpacity()); - ui->showBackgroundImageCheckBox->setChecked(Config::getShowBackgroundImage()); + ui->backgroundImageOpacitySlider->setValue( + m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt()); + ui->showBackgroundImageCheckBox->setChecked( + m_gui_settings->GetValue(gui::gl_showBackgroundImage).toBool()); - backgroundImageOpacitySlider_backup = Config::getBackgroundImageOpacity(); - bgm_volume_backup = Config::getBGMvolume(); + backgroundImageOpacitySlider_backup = + m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt(); + bgm_volume_backup = m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt(); } void SettingsDialog::InitializeEmulatorLanguages() { @@ -754,8 +765,7 @@ void SettingsDialog::UpdateSettings() { } else if (ui->radioButton_Bottom->isChecked()) { Config::setSideTrophy("bottom"); } - - Config::setPlayBGM(ui->playBGMCheckBox->isChecked()); + m_gui_settings->SetValue(gui::gl_playBackgroundMusic, ui->playBGMCheckBox->isChecked()); Config::setAllowHDR(ui->enableHDRCheckBox->isChecked()); Config::setLogType(logTypeMap.value(ui->logTypeComboBox->currentText()).toStdString()); Config::setLogFilter(ui->logFilterLineEdit->text().toStdString()); @@ -764,7 +774,7 @@ void SettingsDialog::UpdateSettings() { Config::setCursorState(ui->hideCursorComboBox->currentIndex()); Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value()); 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::setEnableDiscordRPC(ui->discordRPCCheckbox->isChecked()); Config::setScreenWidth(ui->widthSpinBox->value()); @@ -784,16 +794,19 @@ void SettingsDialog::UpdateSettings() { Config::setVkCrashDiagnosticEnabled(ui->crashDiagnosticsCheckBox->isChecked()); Config::setCollectShaderForDebug(ui->collectShaderCheckBox->isChecked()); Config::setCopyGPUCmdBuffers(ui->copyGPUBuffersCheckBox->isChecked()); - Config::setAutoUpdate(ui->updateCheckBox->isChecked()); - Config::setAlwaysShowChangelog(ui->changelogCheckBox->isChecked()); - Config::setUpdateChannel(channelMap.value(ui->updateComboBox->currentText()).toStdString()); + m_gui_settings->SetValue(gui::gen_checkForUpdates, ui->updateCheckBox->isChecked()); + m_gui_settings->SetValue(gui::gen_showChangeLog, ui->changelogCheckBox->isChecked()); + m_gui_settings->SetValue(gui::gen_updateChannel, + channelMap.value(ui->updateComboBox->currentText())); Config::setChooseHomeTab( chooseHomeTabMap.value(ui->chooseHomeTabComboBox->currentText()).toStdString()); Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->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()); - Config::setShowBackgroundImage(ui->showBackgroundImageCheckBox->isChecked()); + m_gui_settings->SetValue(gui::gl_showBackgroundImage, + ui->showBackgroundImageCheckBox->isChecked()); std::vector dirs_with_states; for (int i = 0; i < ui->gameFoldersListWidget->count(); i++) { @@ -862,3 +875,16 @@ void SettingsDialog::ResetInstallFolders() { 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"); + } +} \ No newline at end of file diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index cdf9be80e..db1bcf772 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -11,6 +11,7 @@ #include "common/config.h" #include "common/path_util.h" +#include "gui_settings.h" #include "qt_gui/compatibility_info.h" namespace Ui { @@ -20,7 +21,8 @@ class SettingsDialog; class SettingsDialog : public QDialog { Q_OBJECT public: - explicit SettingsDialog(std::shared_ptr m_compat_info, + explicit SettingsDialog(std::shared_ptr gui_settings, + std::shared_ptr m_compat_info, QWidget* parent = nullptr); ~SettingsDialog(); @@ -42,6 +44,7 @@ private: void OnLanguageChanged(int index); void OnCursorStateChanged(s16 index); void closeEvent(QCloseEvent* event) override; + void setDefaultValues(); std::unique_ptr ui; @@ -52,4 +55,5 @@ private: int initialHeight; bool is_saving = false; + std::shared_ptr m_gui_settings; };