mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Qt: handle invalid entries in config files
and improve error handling in enhancements
This commit is contained in:
parent
b0f464d110
commit
525c257c6a
3 changed files with 105 additions and 33 deletions
|
@ -4,6 +4,8 @@
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Utilities/Config.h"
|
#include "Utilities/Config.h"
|
||||||
|
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#undef GetHwnd
|
#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)
|
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)
|
if (is_ranged)
|
||||||
{
|
{
|
||||||
QStringList range = GetSettingOptions(type);
|
QStringList range = GetSettingOptions(type);
|
||||||
|
@ -251,11 +259,15 @@ void emu_settings::EnhanceComboBox(QComboBox* combobox, SettingsType type, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString selected = qstr(GetSetting(type));
|
std::string selected = GetSetting(type);
|
||||||
int index = combobox->findData(selected);
|
int index = combobox->findData(qstr(selected));
|
||||||
|
|
||||||
if (index == -1)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -270,14 +282,33 @@ void emu_settings::EnhanceComboBox(QComboBox* combobox, SettingsType type, bool
|
||||||
|
|
||||||
void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, SettingsType type)
|
void emu_settings::EnhanceCheckBox(QCheckBox* checkbox, SettingsType type)
|
||||||
{
|
{
|
||||||
std::string currSet = GetSetting(type);
|
if (!checkbox)
|
||||||
if (currSet == "true")
|
{
|
||||||
|
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);
|
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)
|
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));
|
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);
|
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);
|
||||||
int min = range.first().toInt();
|
val = def;
|
||||||
int max = range.last().toInt();
|
m_broken_types.insert(type);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slider->setRange(min, max);
|
||||||
|
slider->setValue(val);
|
||||||
|
|
||||||
connect(slider, &QSlider::valueChanged, [=](int value)
|
connect(slider, &QSlider::valueChanged, [=](int value)
|
||||||
{
|
{
|
||||||
SetSetting(type, sstr(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;
|
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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -156,6 +156,8 @@ public:
|
||||||
Render_Creator();
|
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
|
/** 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.
|
* Settings are only written when SaveSettings is called.
|
||||||
*/
|
*/
|
||||||
|
@ -169,7 +171,7 @@ public:
|
||||||
void EnhanceCheckBox(QCheckBox* checkbox, SettingsType type);
|
void EnhanceCheckBox(QCheckBox* checkbox, SettingsType type);
|
||||||
|
|
||||||
/** Connects a slider with the target settings 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();
|
std::vector<std::string> GetLoadedLibraries();
|
||||||
void SaveSelectedLibraries(const std::vector<std::string>& libs);
|
void SaveSelectedLibraries(const std::vector<std::string>& libs);
|
||||||
|
@ -195,6 +197,9 @@ public:
|
||||||
/** Loads the settings from path.*/
|
/** Loads the settings from path.*/
|
||||||
void LoadSettings(const std::string& 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:
|
public Q_SLOTS:
|
||||||
/** Writes the unsaved settings to file. Used in settings dialog on accept.*/
|
/** Writes the unsaved settings to file. Used in settings dialog on accept.*/
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
|
|
|
@ -517,7 +517,7 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> guiSettings, std:
|
||||||
return QLabel(sizer).sizeHint().width();
|
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());
|
SubscribeTooltip(ui->gb_resolutionScale, json_gpu_slid["resolutionScale"].toString());
|
||||||
ui->gb_resolutionScale->setEnabled(!ui->scrictModeRendering->isChecked());
|
ui->gb_resolutionScale->setEnabled(!ui->scrictModeRendering->isChecked());
|
||||||
// rename label texts to fit current state of Resolution Scale
|
// 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);
|
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());
|
SubscribeTooltip(ui->gb_minimumScalableDimension, json_gpu_slid["minimumScalableDimension"].toString());
|
||||||
ui->gb_minimumScalableDimension->setEnabled(!ui->scrictModeRendering->isChecked());
|
ui->gb_minimumScalableDimension->setEnabled(!ui->scrictModeRendering->isChecked());
|
||||||
// rename label texts to fit current state of Minimum Scalable Dimension
|
// 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
|
// 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());
|
SubscribeTooltip(ui->perfOverlayUpdateInterval, json_emu_overlay["perfOverlayUpdateInterval"].toString());
|
||||||
ui->label_update_interval->setText(tr("Update Interval: %0 ms").arg(ui->perfOverlayUpdateInterval->value()));
|
ui->label_update_interval->setText(tr("Update Interval: %0 ms").arg(ui->perfOverlayUpdateInterval->value()));
|
||||||
connect(ui->perfOverlayUpdateInterval, &QSlider::valueChanged, [this](int 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));
|
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());
|
SubscribeTooltip(ui->perfOverlayFontSize, json_emu_overlay["perfOverlayFontSize"].toString());
|
||||||
ui->label_font_size->setText(tr("Font Size: %0 px").arg(ui->perfOverlayFontSize->value()));
|
ui->label_font_size->setText(tr("Font Size: %0 px").arg(ui->perfOverlayFontSize->value()));
|
||||||
connect(ui->perfOverlayFontSize, &QSlider::valueChanged, [this](int 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.
|
// 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);
|
ui->tab_widget_settings->setCurrentIndex(0);
|
||||||
QTimer::singleShot(0, [=]{ ui->tab_widget_settings->setCurrentIndex(m_tab_Index); });
|
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();
|
return QDialog::exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue