Qt: handle invalid entries in config files

and improve error handling in enhancements
This commit is contained in:
Megamouse 2018-06-17 13:34:53 +02:00
parent b0f464d110
commit 525c257c6a
3 changed files with 105 additions and 33 deletions

View file

@ -4,6 +4,8 @@
#include "Emu/System.h"
#include "Utilities/Config.h"
#include <QMessageBox>
#ifdef _MSC_VER
#include <Windows.h>
#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!");
}
}

View file

@ -156,6 +156,8 @@ public:
Render_Creator();
};
std::set<SettingsType> 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<std::string> GetLoadedLibraries();
void SaveSelectedLibraries(const std::vector<std::string>& 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();

View file

@ -517,7 +517,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> 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<gui_settings> 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<gui_settings> 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<gui_settings> 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();
}