diff --git a/rpcs3/rpcs3qt/emu_settings.cpp b/rpcs3/rpcs3qt/emu_settings.cpp index 377113838a..5b1de8e187 100644 --- a/rpcs3/rpcs3qt/emu_settings.cpp +++ b/rpcs3/rpcs3qt/emu_settings.cpp @@ -4,6 +4,8 @@ #include "Emu/System.h" #include "Utilities/Config.h" +#include + #ifdef _MSC_VER #include #undef GetHwnd @@ -232,6 +234,12 @@ void emu_settings::SaveSettings() void emu_settings::EnhanceComboBox(QComboBox* combobox, SettingsType type, bool is_ranged, bool use_max, int max) { + if (!combobox) + { + LOG_FATAL(GENERAL, "EnhanceComboBox '%s' was used with an invalid object", GetSettingName(type)); + return; + } + if (is_ranged) { QStringList range = GetSettingOptions(type); @@ -251,11 +259,15 @@ void emu_settings::EnhanceComboBox(QComboBox* combobox, SettingsType type, bool } } - QString selected = qstr(GetSetting(type)); - int index = combobox->findData(selected); + std::string selected = GetSetting(type); + int index = combobox->findData(qstr(selected)); + if (index == -1) { - LOG_WARNING(GENERAL, "Current setting not found while creating combobox"); + std::string def = GetSettingDefault(type); + LOG_ERROR(GENERAL, "EnhanceComboBox '%s' tried to set an invalid value: %s. Setting to default: %s", GetSettingName(type), selected, def); + combobox->setCurrentIndex(combobox->findData(qstr(def))); + m_broken_types.insert(type); } else { @@ -270,14 +282,33 @@ void emu_settings::EnhanceComboBox(QComboBox* combobox, SettingsType type, bool void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, SettingsType type) { - std::string currSet = GetSetting(type); - if (currSet == "true") + if (!checkbox) + { + LOG_FATAL(GENERAL, "EnhanceCheckBox '%s' was used with an invalid object", GetSettingName(type)); + return; + } + + std::string def = GetSettingDefault(type); + std::transform(def.begin(), def.end(), def.begin(), ::tolower); + + if (def != "true" && def != "false") + { + LOG_FATAL(GENERAL, "EnhanceCheckBox '%s' was used with an invalid SettingsType", GetSettingName(type)); + return; + } + + std::string selected = GetSetting(type); + std::transform(selected.begin(), selected.end(), selected.begin(), ::tolower); + + if (selected == "true") { checkbox->setChecked(true); } - else if (currSet != "false") + else if (selected != "false") { - LOG_WARNING(GENERAL, "Passed in an invalid setting for creating enhanced checkbox"); + LOG_ERROR(GENERAL, "EnhanceCheckBox '%s' tried to set an invalid value: %s. Setting to default: %s", GetSettingName(type), selected, def); + checkbox->setChecked(def == "true"); + m_broken_types.insert(type); } connect(checkbox, &QCheckBox::stateChanged, [=](int val) @@ -287,33 +318,40 @@ void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, SettingsType type) }); } -void emu_settings::EnhanceSlider(QSlider* slider, SettingsType type, bool is_ranged) +void emu_settings::EnhanceSlider(QSlider* slider, SettingsType type) { + if (!slider) + { + LOG_FATAL(GENERAL, "EnhanceSlider '%s' was used with an invalid object", GetSettingName(type)); + return; + } + + QStringList range = GetSettingOptions(type); + bool ok_def, ok_sel, ok_min, ok_max; + + int def = qstr(GetSettingDefault(type)).toInt(&ok_def); + int min = range.first().toInt(&ok_min); + int max = range.last().toInt(&ok_max); + + if (!ok_def || !ok_min || !ok_max) + { + LOG_FATAL(GENERAL, "EnhanceSlider '%s' was used with an invalid SettingsType", GetSettingName(type)); + return; + } + QString selected = qstr(GetSetting(type)); + int val = selected.toInt(&ok_sel); - if (is_ranged) + if (!ok_sel || val < min || val > max) { - QStringList range = GetSettingOptions(type); - int min = range.first().toInt(); - int max = range.last().toInt(); - int val = selected.toInt(); - - if (val < min || val > max) - { - LOG_ERROR(GENERAL, "Passed in an invalid setting for creating enhanced slider"); - val = min; - } - - slider->setMinimum(min); - slider->setMaximum(max); - slider->setValue(val); - } - else - { - //TODO ? - LOG_ERROR(GENERAL, "TODO: implement unranged enhanced slider"); + LOG_ERROR(GENERAL, "EnhanceSlider '%s' tried to set an invalid value: %d. Setting to default: %d. Allowed range: [%d, %d]", GetSettingName(type), val, def, min, max); + val = def; + m_broken_types.insert(type); } + slider->setRange(min, max); + slider->setValue(val); + connect(slider, &QSlider::valueChanged, [=](int value) { SetSetting(type, sstr(value)); @@ -355,3 +393,28 @@ void emu_settings::SetSetting(SettingsType type, const std::string& val) { cfg_adapter::get_node(m_currentSettings, SettingsLoc[type]) = val; } + +void emu_settings::OpenCorrectionDialog(QWidget* parent) +{ + if (m_broken_types.size() && QMessageBox::question(parent, tr("Fix invalid settings?"), + tr( + "Your config file contained one or more unrecognized settings.\n" + "Their default value will be used until they are corrected.\n" + "Consider that a correction might render them invalid for other versions of RPCS3.\n" + "\n" + "Do you wish to let the program correct them for you?\n" + "This change will only be final when you save the config." + ), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::Yes) + { + for (const auto& type : m_broken_types) + { + std::string def = GetSettingDefault(type); + SetSetting(type, def); + LOG_SUCCESS(GENERAL, "The config entry '%s' was corrected from '%s' to '%s'", GetSettingName(type), GetSetting(type), def); + } + + m_broken_types.clear(); + LOG_SUCCESS(GENERAL, "You need to save the settings in order to make these changes permanent!"); + } +} diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index 39c490c273..a387a7cc1f 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -156,6 +156,8 @@ public: Render_Creator(); }; + std::set m_broken_types; // list of broken settings + /** Creates a settings object which reads in the config.yml file at rpcs3/bin/%path%/config.yml * Settings are only written when SaveSettings is called. */ @@ -169,7 +171,7 @@ public: void EnhanceCheckBox(QCheckBox* checkbox, SettingsType type); /** Connects a slider with the target settings type*/ - void EnhanceSlider(QSlider* slider, SettingsType type, bool is_ranged = false); + void EnhanceSlider(QSlider* slider, SettingsType type); std::vector GetLoadedLibraries(); void SaveSelectedLibraries(const std::vector& libs); @@ -195,6 +197,9 @@ public: /** Loads the settings from path.*/ void LoadSettings(const std::string& path = ""); + /** Fixes all registered invalid settings after asking the user for permission.*/ + void OpenCorrectionDialog(QWidget* parent = Q_NULLPTR); + public Q_SLOTS: /** Writes the unsaved settings to file. Used in settings dialog on accept.*/ void SaveSettings(); diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index d9806c4b6c..226e077ffe 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -517,7 +517,7 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: return QLabel(sizer).sizeHint().width(); }; - xemu_settings->EnhanceSlider(ui->resolutionScale, emu_settings::ResolutionScale, true); + xemu_settings->EnhanceSlider(ui->resolutionScale, emu_settings::ResolutionScale); SubscribeTooltip(ui->gb_resolutionScale, json_gpu_slid["resolutionScale"].toString()); ui->gb_resolutionScale->setEnabled(!ui->scrictModeRendering->isChecked()); // rename label texts to fit current state of Resolution Scale @@ -542,7 +542,7 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: ui->resolutionScale->setValue(resolutionScaleDef); }); - xemu_settings->EnhanceSlider(ui->minimumScalableDimension, emu_settings::MinimumScalableDimension, true); + xemu_settings->EnhanceSlider(ui->minimumScalableDimension, emu_settings::MinimumScalableDimension); SubscribeTooltip(ui->gb_minimumScalableDimension, json_gpu_slid["minimumScalableDimension"].toString()); ui->gb_minimumScalableDimension->setEnabled(!ui->scrictModeRendering->isChecked()); // rename label texts to fit current state of Minimum Scalable Dimension @@ -829,7 +829,7 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: // Sliders - xemu_settings->EnhanceSlider(ui->perfOverlayUpdateInterval, emu_settings::PerfOverlayUpdateInterval, true); + xemu_settings->EnhanceSlider(ui->perfOverlayUpdateInterval, emu_settings::PerfOverlayUpdateInterval); SubscribeTooltip(ui->perfOverlayUpdateInterval, json_emu_overlay["perfOverlayUpdateInterval"].toString()); ui->label_update_interval->setText(tr("Update Interval: %0 ms").arg(ui->perfOverlayUpdateInterval->value())); connect(ui->perfOverlayUpdateInterval, &QSlider::valueChanged, [this](int value) @@ -837,7 +837,7 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: ui->label_update_interval->setText(tr("Update Interval: %0 ms").arg(value)); }); - xemu_settings->EnhanceSlider(ui->perfOverlayFontSize, emu_settings::PerfOverlayFontSize, true); + xemu_settings->EnhanceSlider(ui->perfOverlayFontSize, emu_settings::PerfOverlayFontSize); SubscribeTooltip(ui->perfOverlayFontSize, json_emu_overlay["perfOverlayFontSize"].toString()); ui->label_font_size->setText(tr("Font Size: %0 px").arg(ui->perfOverlayFontSize->value())); connect(ui->perfOverlayFontSize, &QSlider::valueChanged, [this](int value) @@ -1246,6 +1246,10 @@ int settings_dialog::exec() // Weirdly enough this won't happen if we change the tab order so that anything else is at index 0. ui->tab_widget_settings->setCurrentIndex(0); QTimer::singleShot(0, [=]{ ui->tab_widget_settings->setCurrentIndex(m_tab_Index); }); + + // Open a dialog if your config file contained invalid entries + QTimer::singleShot(10, [this] { xemu_settings->OpenCorrectionDialog(this); }); + return QDialog::exec(); }