diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index d6630b8659..252bac4a2b 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -174,10 +174,12 @@ void emu_settings::LoadSettings(const std::string& title_id) } } -void emu_settings::ValidateSettings() +bool emu_settings::ValidateSettings(bool cleanup) { - std::function&, cfg::_base*)> search_level; - search_level = [&search_level](int level, const YAML::Node& yml_node, std::vector& keys, cfg::_base* cfg_base) + bool is_clean = true; + + std::function&, cfg::_base*)> search_level; + search_level = [&search_level, &is_clean, &cleanup, this](int level, YAML::Node& yml_node, std::vector& keys, cfg::_base* cfg_base) { if (!yml_node || !yml_node.IsMap()) { @@ -208,30 +210,59 @@ void emu_settings::ValidateSettings() if (cfg_node) { - search_level(next_level, yml_node[key], keys, cfg_node); + YAML::Node next_node = yml_node[key]; + search_level(next_level, next_node, keys, cfg_node); } else { - std::string key; - for (usz i = 0; i < keys.size(); i++) + const auto get_full_key = [&keys](const std::string& seperator) -> std::string { - key += keys[i]; - if (i < keys.size() - 1) key += ": "; + std::string full_key; + for (usz i = 0; i < keys.size(); i++) + { + full_key += keys[i]; + if (i < keys.size() - 1) full_key += seperator; + } + return full_key; + }; + + is_clean = false; + + if (cleanup) + { + if (!yml_node.remove(key)) + { + cfg_log.error("Could not remove config entry: %s", get_full_key(": ")); + is_clean = true; // abort + return; + } + + // Let's only remove one entry at a time. I got some weird issues when doing all at once. + return; + } + else + { + cfg_log.warning("Unknown config entry found: %s", get_full_key(": ")); } - cfg_log.warning("Unknown config entry found: %s", key); } } }; cfg_root root; std::vector keys; - search_level(0, m_current_settings, keys, &root); + + do + { + is_clean = true; + search_level(0, m_current_settings, keys, &root); + } + while (cleanup && !is_clean); + + return is_clean; } void emu_settings::SaveSettings() { - ValidateSettings(); - YAML::Emitter out; emit_data(out, m_current_settings); diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index 4163497ee4..bebacb2e67 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -90,12 +90,13 @@ public: /** Get a localized and therefore freely adjustable version of the string used in config.yml.*/ QString GetLocalizedSetting(const QString& original, emu_settings_type type, int index) const; + /** Validates the settings and logs unused entries or cleans up the yaml*/ + bool ValidateSettings(bool cleanup); + public Q_SLOTS: /** Writes the unsaved settings to file. Used in settings dialog on accept.*/ void SaveSettings(); private: - void ValidateSettings(); - YAML::Node m_default_settings; // The default settings as a YAML node. YAML::Node m_current_settings; // The current settings as a YAML node. std::string m_title_id; diff --git a/rpcs3/rpcs3qt/gui_settings.h b/rpcs3/rpcs3qt/gui_settings.h index 1632ed4c60..8e56c82342 100644 --- a/rpcs3/rpcs3qt/gui_settings.h +++ b/rpcs3/rpcs3qt/gui_settings.h @@ -121,6 +121,7 @@ namespace gui const gui_save ib_show_welcome = gui_save(main_window, "infoBoxEnabledWelcome", true); const gui_save ib_confirm_exit = gui_save(main_window, "confirmationBoxExitGame", true); const gui_save ib_confirm_boot = gui_save(main_window, "confirmationBoxBootGame", true); + const gui_save ib_obsolete_cfg = gui_save(main_window, "confirmationObsoleteCfg", true); const gui_save fd_install_pkg = gui_save(main_window, "lastExplorePathPKG", ""); const gui_save fd_install_pup = gui_save(main_window, "lastExplorePathPUP", ""); diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 654b0e6238..446f393cf4 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1494,6 +1494,8 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std SubscribeTooltip(ui->cb_show_pup_install, tooltips.settings.show_pup_install); + SubscribeTooltip(ui->cb_show_obsolete_cfg_dialog, tooltips.settings.show_obsolete_cfg); + SubscribeTooltip(ui->gb_updates, tooltips.settings.check_update_start); SubscribeTooltip(ui->useRichPresence, tooltips.settings.use_rich_presence); @@ -1572,6 +1574,7 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std ui->cb_show_boot_game->setChecked(m_gui_settings->GetValue(gui::ib_confirm_boot).toBool()); ui->cb_show_pkg_install->setChecked(m_gui_settings->GetValue(gui::ib_pkg_success).toBool()); ui->cb_show_pup_install->setChecked(m_gui_settings->GetValue(gui::ib_pup_success).toBool()); + ui->cb_show_obsolete_cfg_dialog->setChecked(m_gui_settings->GetValue(gui::ib_obsolete_cfg).toBool()); const QString updates_yes = tr("Yes", "Updates"); const QString updates_background = tr("Background", "Updates"); @@ -1659,6 +1662,10 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std { m_gui_settings->SetValue(gui::ib_pup_success, val); }); + connect(ui->cb_show_obsolete_cfg_dialog, &QCheckBox::clicked, [this](bool val) + { + m_gui_settings->SetValue(gui::ib_obsolete_cfg, val); + }); connect(ui->cb_custom_colors, &QCheckBox::clicked, [this](bool val) { @@ -1963,7 +1970,29 @@ int settings_dialog::exec() QTimer::singleShot(0, [this]{ ui->tab_widget_settings->setCurrentIndex(m_tab_index); }); // Open a dialog if your config file contained invalid entries - QTimer::singleShot(10, [this] { m_emu_settings->OpenCorrectionDialog(this); }); + QTimer::singleShot(10, [this] + { + m_emu_settings->OpenCorrectionDialog(this); + + if (!m_emu_settings->ValidateSettings(false)) + { + int result = QMessageBox::No; + m_gui_settings->ShowConfirmationBox( + tr("Remove obsolete settings?"), + tr( + "Your config file contains one or more obsolete entries.\n" + "Consider that a removal might render them invalid for other versions of RPCS3.\n" + "\n" + "Do you wish to let the program remove them for you now?\n" + "This change will only be final when you save the config." + ), gui::ib_obsolete_cfg, &result, this); + + if (result == QMessageBox::Yes) + { + m_emu_settings->ValidateSettings(true); + } + } + }); return QDialog::exec(); } diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 03f4397aa6..64de9bd45f 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -39,7 +39,7 @@ - 6 + 0 @@ -2068,8 +2068,8 @@ - - + + 0 @@ -2081,12 +2081,11 @@ - - + - + @@ -3303,6 +3302,13 @@ + + + + Show Obsolete Settings Dialog + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 1f99bf2df5..9220f1f90e 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -173,6 +173,7 @@ public: const QString show_boot_game = tr("Shows a confirmation dialog when a game was booted while another game is running."); const QString show_pkg_install = tr("Shows a dialog when packages were installed successfully."); const QString show_pup_install = tr("Shows a dialog when firmware was installed successfully."); + const QString show_obsolete_cfg = tr("Shows a dialog when obsolete settings were found."); const QString check_update_start = tr("Checks if an update is available on startup and asks if you want to update.\nIf \"Background\" is selected, the check is done silently in the background and a new download option is shown in the top right corner of the menu if a new version was found."); const QString use_rich_presence = tr("Enables use of Discord Rich Presence to show what game you are playing on Discord.\nRequires a restart of RPCS3 to completely close the connection."); const QString discord_state = tr("Tell your friends what you are doing.");