Qt: Clean and remove empty game settings

This commit is contained in:
Stenzek 2024-04-25 14:02:16 +10:00
parent d6ffdb0242
commit 1cdfca155d
No known key found for this signature in database
23 changed files with 247 additions and 47 deletions

View file

@ -797,6 +797,11 @@ public:
/** @}
@{ @name Accessing INI Data */
/** Retrieve the number keys across all sections.
@return number of keys currently present.
*/
size_t GetKeyCount() const;
/** Retrieve all section names. The list is returned as an STL vector of
names and can be iterated or searched as necessary. Note that the
sort order of the returned strings is NOT DEFINED. You can sort
@ -2440,6 +2445,17 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSection(
return 0;
}
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
size_t
CSimpleIniTempl<SI_CHAR, SI_STRLESS, SI_CONVERTER>::GetKeyCount() const
{
size_t count = 0;
typename TSection::const_iterator i = m_data.begin();
for (; i != m_data.end(); ++i)
count += i->second.size();
return count;
}
template<class SI_CHAR, class SI_STRLESS, class SI_CONVERTER>
void
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetAllSections(

View file

@ -1736,17 +1736,29 @@ bool FileSystem::CreateDirectory(const char* Path, bool Recursive, Error* error)
}
}
bool FileSystem::DeleteFile(const char* path)
bool FileSystem::DeleteFile(const char* path, Error* error)
{
if (path[0] == '\0')
{
Error::SetStringView(error, "Path is empty.");
return false;
}
const std::wstring wpath = GetWin32Path(path);
const DWORD fileAttributes = GetFileAttributesW(wpath.c_str());
if (fileAttributes == INVALID_FILE_ATTRIBUTES || fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
Error::SetStringView(error, "File does not exist.");
return false;
}
return (DeleteFileW(wpath.c_str()) == TRUE);
if (!DeleteFileW(wpath.c_str()))
{
Error::SetWin32(error, "DeleteFileW() failed: ", GetLastError());
return false;
}
return true;
}
bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)
@ -2241,16 +2253,28 @@ bool FileSystem::CreateDirectory(const char* path, bool recursive, Error* error)
}
}
bool FileSystem::DeleteFile(const char* path)
bool FileSystem::DeleteFile(const char* path, Error* error)
{
if (path[0] == '\0')
{
Error::SetStringView(error, "Path is empty.");
return false;
}
struct stat sysStatData;
if (stat(path, &sysStatData) != 0 || S_ISDIR(sysStatData.st_mode))
{
Error::SetStringView(error, "File does not exist.");
return false;
}
return (unlink(path) == 0);
if (unlink(path) != 0)
{
Error::SetErrno(error, "unlink() failed: ", errno);
return false;
}
return true;
}
bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)

View file

@ -86,7 +86,7 @@ bool DirectoryExists(const char* path);
bool DirectoryIsEmpty(const char* path);
/// Delete file
bool DeleteFile(const char* path);
bool DeleteFile(const char* path, Error* error = nullptr);
/// Rename file
bool RenamePath(const char* OldPath, const char* NewPath, Error* error = nullptr);

View file

@ -19,6 +19,11 @@ void LayeredSettingsInterface::Clear()
Panic("Attempting to clear layered settings interface");
}
bool LayeredSettingsInterface::IsEmpty()
{
return false;
}
bool LayeredSettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
{
for (u32 layer = FIRST_LAYER; layer <= LAST_LAYER; layer++)
@ -170,6 +175,16 @@ void LayeredSettingsInterface::ClearSection(const char* section)
Panic("Attempt to call ClearSection() on layered settings interface");
}
void LayeredSettingsInterface::RemoveSection(const char* section)
{
Panic("Attempt to call RemoveSection() on layered settings interface");
}
void LayeredSettingsInterface::RemoveEmptySections()
{
Panic("Attempt to call RemoveEmptySections() on layered settings interface");
}
std::vector<std::string> LayeredSettingsInterface::GetStringList(const char* section, const char* key) const
{
std::vector<std::string> ret;

View file

@ -27,6 +27,8 @@ public:
void Clear() override;
bool IsEmpty() override;
bool GetIntValue(const char* section, const char* key, s32* value) const override;
bool GetUIntValue(const char* section, const char* key, u32* value) const override;
bool GetFloatValue(const char* section, const char* key, float* value) const override;
@ -44,6 +46,8 @@ public:
bool ContainsValue(const char* section, const char* key) const override;
void DeleteValue(const char* section, const char* key) override;
void ClearSection(const char* section) override;
void RemoveSection(const char* section) override;
void RemoveEmptySections() override;
std::vector<std::string> GetStringList(const char* section, const char* key) const override;
void SetStringList(const char* section, const char* key, const std::vector<std::string>& items) override;

View file

@ -22,6 +22,11 @@ void MemorySettingsInterface::Clear()
m_sections.clear();
}
bool MemorySettingsInterface::IsEmpty()
{
return m_sections.empty();
}
bool MemorySettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
{
const auto sit = m_sections.find(section);
@ -315,3 +320,26 @@ void MemorySettingsInterface::ClearSection(const char* section)
m_sections.erase(sit);
}
void MemorySettingsInterface::RemoveSection(const char* section)
{
auto sit = m_sections.find(section);
if (sit == m_sections.end())
return;
m_sections.erase(sit);
}
void MemorySettingsInterface::RemoveEmptySections()
{
for (auto sit = m_sections.begin(); sit != m_sections.end();)
{
if (sit->second.size() > 0)
{
++sit;
continue;
}
sit = m_sections.erase(sit);
}
}

View file

@ -16,6 +16,8 @@ public:
void Clear() override;
bool IsEmpty() override;
bool GetIntValue(const char* section, const char* key, s32* value) const override;
bool GetUIntValue(const char* section, const char* key, u32* value) const override;
bool GetFloatValue(const char* section, const char* key, float* value) const override;
@ -37,6 +39,8 @@ public:
bool ContainsValue(const char* section, const char* key) const override;
void DeleteValue(const char* section, const char* key) override;
void ClearSection(const char* section) override;
void RemoveSection(const char* section) override;
void RemoveEmptySections();
std::vector<std::string> GetStringList(const char* section, const char* key) const override;
void SetStringList(const char* section, const char* key, const std::vector<std::string>& items) override;

View file

@ -19,6 +19,7 @@ public:
virtual bool Save(Error* error = nullptr) = 0;
virtual void Clear() = 0;
virtual bool IsEmpty() = 0;
virtual bool GetIntValue(const char* section, const char* key, s32* value) const = 0;
virtual bool GetUIntValue(const char* section, const char* key, u32* value) const = 0;
@ -46,6 +47,8 @@ public:
virtual bool ContainsValue(const char* section, const char* key) const = 0;
virtual void DeleteValue(const char* section, const char* key) = 0;
virtual void ClearSection(const char* section) = 0;
virtual void RemoveSection(const char* section) = 0;
virtual void RemoveEmptySections() = 0;
ALWAYS_INLINE s32 GetIntValue(const char* section, const char* key, s32 default_value = 0) const
{

View file

@ -836,7 +836,29 @@ void FullscreenUI::Render()
{
if (s_game_settings_interface)
{
s_game_settings_interface->Save();
Error error;
s_game_settings_interface->RemoveEmptySections();
if (s_game_settings_interface->IsEmpty())
{
if (FileSystem::FileExists(s_game_settings_interface->GetFileName().c_str()) &&
!FileSystem::DeleteFile(s_game_settings_interface->GetFileName().c_str(), &error))
{
ImGuiFullscreen::OpenInfoMessageDialog(
FSUI_STR("Error"), fmt::format(FSUI_FSTR("An error occurred while deleting empty game settings:\n{}"),
error.GetDescription()));
}
}
else
{
if (!s_game_settings_interface->Save(&error))
{
ImGuiFullscreen::OpenInfoMessageDialog(
FSUI_STR("Error"),
fmt::format(FSUI_FSTR("An error occurred while saving game settings:\n{}"), error.GetDescription()));
}
}
if (System::IsValid())
Host::RunOnCPUThread([]() { System::ReloadGameSettings(false); });
}
@ -7052,6 +7074,8 @@ TRANSLATE_NOOP("FullscreenUI", "Advanced Settings");
TRANSLATE_NOOP("FullscreenUI", "All Time: {}");
TRANSLATE_NOOP("FullscreenUI", "Allow Booting Without SBI File");
TRANSLATE_NOOP("FullscreenUI", "Allows loading protected games without subchannel information.");
TRANSLATE_NOOP("FullscreenUI", "An error occurred while deleting empty game settings:\n{}");
TRANSLATE_NOOP("FullscreenUI", "An error occurred while saving game settings:\n{}");
TRANSLATE_NOOP("FullscreenUI", "Applies modern dithering techniques to further smooth out gradients when true color is enabled.");
TRANSLATE_NOOP("FullscreenUI", "Apply Image Patches");
TRANSLATE_NOOP("FullscreenUI", "Apply Per-Game Settings");
@ -7220,6 +7244,7 @@ TRANSLATE_NOOP("FullscreenUI", "Enhancements");
TRANSLATE_NOOP("FullscreenUI", "Ensures every frame generated is displayed for optimal pacing. Enable for variable refresh displays, such as GSync/FreeSync. Disable if you are having speed or sound issues.");
TRANSLATE_NOOP("FullscreenUI", "Enter Value");
TRANSLATE_NOOP("FullscreenUI", "Enter the name of the input profile you wish to create.");
TRANSLATE_NOOP("FullscreenUI", "Error");
TRANSLATE_NOOP("FullscreenUI", "Execution Mode");
TRANSLATE_NOOP("FullscreenUI", "Exit");
TRANSLATE_NOOP("FullscreenUI", "Exit And Save State");
@ -7330,6 +7355,7 @@ TRANSLATE_NOOP("FullscreenUI", "Macro {} Buttons");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Frequency");
TRANSLATE_NOOP("FullscreenUI", "Macro {} Trigger");
TRANSLATE_NOOP("FullscreenUI", "Makes games run closer to their console framerate, at a small cost to performance.");
TRANSLATE_NOOP("FullscreenUI", "Memory Card Busy");
TRANSLATE_NOOP("FullscreenUI", "Memory Card Directory");
TRANSLATE_NOOP("FullscreenUI", "Memory Card Port {}");
TRANSLATE_NOOP("FullscreenUI", "Memory Card Settings");
@ -7351,6 +7377,7 @@ TRANSLATE_NOOP("FullscreenUI", "No input profiles available.");
TRANSLATE_NOOP("FullscreenUI", "No resume save state found.");
TRANSLATE_NOOP("FullscreenUI", "No save present in this slot.");
TRANSLATE_NOOP("FullscreenUI", "No save states found.");
TRANSLATE_NOOP("FullscreenUI", "No, resume the game.");
TRANSLATE_NOOP("FullscreenUI", "None (Double Speed)");
TRANSLATE_NOOP("FullscreenUI", "None (Normal Speed)");
TRANSLATE_NOOP("FullscreenUI", "Not Logged In");
@ -7599,6 +7626,7 @@ TRANSLATE_NOOP("FullscreenUI", "Uses perspective-correct interpolation for textu
TRANSLATE_NOOP("FullscreenUI", "Uses screen positions to resolve PGXP data. May improve visuals in some games.");
TRANSLATE_NOOP("FullscreenUI", "Value: {} | Default: {} | Minimum: {} | Maximum: {}");
TRANSLATE_NOOP("FullscreenUI", "Vertical Sync (VSync)");
TRANSLATE_NOOP("FullscreenUI", "WARNING: Your game is still saving to the memory card. Continuing to {0} may IRREVERSIBLY DESTROY YOUR MEMORY CARD. We recommend resuming your game and waiting 5 seconds for it to finish saving.\n\nDo you want to {0} anyway?");
TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, DuckStation will scan for achievements on startup.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, DuckStation will assume all achievements are locked and not send any unlock notifications to the server.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, DuckStation will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements.");
@ -7611,8 +7639,12 @@ TRANSLATE_NOOP("FullscreenUI", "When this option is chosen, the clock speed set
TRANSLATE_NOOP("FullscreenUI", "Widescreen Hack");
TRANSLATE_NOOP("FullscreenUI", "Wireframe Rendering");
TRANSLATE_NOOP("FullscreenUI", "Writes textures which can be replaced to the dump directory.");
TRANSLATE_NOOP("FullscreenUI", "Yes, {} now and risk memory card corruption.");
TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.");
TRANSLATE_NOOP("FullscreenUI", "\"PlayStation\" and \"PSX\" are registered trademarks of Sony Interactive Entertainment Europe Limited. This software is not affiliated in any way with Sony Interactive Entertainment.");
TRANSLATE_NOOP("FullscreenUI", "change disc");
TRANSLATE_NOOP("FullscreenUI", "reset");
TRANSLATE_NOOP("FullscreenUI", "shut down");
TRANSLATE_NOOP("FullscreenUI", "{:%H:%M}");
TRANSLATE_NOOP("FullscreenUI", "{:%Y-%m-%d %H:%M:%S}");
TRANSLATE_NOOP("FullscreenUI", "{} Frames");

View file

@ -336,7 +336,7 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
else
{
result = InputManager::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
m_dialog->getProfileSettingsInterface()->Save();
QtHost::SaveGameSettings(m_dialog->getProfileSettingsInterface(), false);
g_emu_thread->reloadInputBindings();
}

View file

@ -278,8 +278,7 @@ void ControllerSettingsWindow::setBoolValue(const char* section, const char* key
if (m_profile_interface)
{
m_profile_interface->SetBoolValue(section, key, value);
m_profile_interface->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -294,8 +293,7 @@ void ControllerSettingsWindow::setIntValue(const char* section, const char* key,
if (m_profile_interface)
{
m_profile_interface->SetIntValue(section, key, value);
m_profile_interface->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -310,8 +308,7 @@ void ControllerSettingsWindow::setStringValue(const char* section, const char* k
if (m_profile_interface)
{
m_profile_interface->SetStringValue(section, key, value);
m_profile_interface->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -321,6 +318,13 @@ void ControllerSettingsWindow::setStringValue(const char* section, const char* k
}
}
void ControllerSettingsWindow::saveAndReloadGameSettings()
{
DebugAssert(m_profile_interface);
QtHost::SaveGameSettings(m_profile_interface.get(), false);
g_emu_thread->reloadGameSettings(false);
}
void ControllerSettingsWindow::clearSettingValue(const char* section, const char* key)
{
if (m_profile_interface)

View file

@ -64,6 +64,7 @@ public:
void setIntValue(const char* section, const char* key, s32 value);
void setStringValue(const char* section, const char* key, const char* value);
void clearSettingValue(const char* section, const char* key);
void saveAndReloadGameSettings();
Q_SIGNALS:
void inputProfileSwitched();

View file

@ -37,7 +37,7 @@ static void BindWidgetToInputProfileBool(SettingsInterface* sif, WidgetType* wid
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget);
sif->SetBoolValue(section.c_str(), key.c_str(), new_value);
sif->Save();
QtHost::SaveGameSettings(sif, false);
g_emu_thread->reloadGameSettings();
});
}
@ -70,7 +70,7 @@ static void BindWidgetToInputProfileFloat(SettingsInterface* sif, WidgetType* wi
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget);
sif->SetFloatValue(section.c_str(), key.c_str(), new_value);
sif->Save();
QtHost::SaveGameSettings(sif, false);
g_emu_thread->reloadGameSettings();
});
}
@ -103,7 +103,7 @@ static void BindWidgetToInputProfileNormalized(SettingsInterface* sif, WidgetTyp
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), range]() {
const int new_value = Accessor::getIntValue(widget);
sif->SetFloatValue(section.c_str(), key.c_str(), static_cast<float>(new_value) / range);
sif->Save();
QtHost::SaveGameSettings(sif, false);
g_emu_thread->reloadGameSettings();
});
}
@ -142,7 +142,7 @@ static void BindWidgetToInputProfileString(SettingsInterface* sif, WidgetType* w
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, false);
g_emu_thread->reloadGameSettings();
});
}

View file

@ -234,7 +234,7 @@ void InputBindingDialog::saveListToSettings()
m_sif->SetStringList(m_section_name.c_str(), m_key_name.c_str(), m_bindings);
else
m_sif->DeleteValue(m_section_name.c_str(), m_key_name.c_str());
m_sif->Save();
QtHost::SaveGameSettings(m_sif, false);
g_emu_thread->reloadGameSettings();
}
else

View file

@ -218,7 +218,7 @@ void InputBindingWidget::setNewBinding()
if (m_sif)
{
m_sif->SetStringValue(m_section_name.c_str(), m_key_name.c_str(), new_binding.c_str());
m_sif->Save();
QtHost::SaveGameSettings(m_sif, false);
g_emu_thread->reloadGameSettings();
}
else
@ -239,7 +239,7 @@ void InputBindingWidget::clearBinding()
if (m_sif)
{
m_sif->DeleteValue(m_section_name.c_str(), m_key_name.c_str());
m_sif->Save();
QtHost::SaveGameSettings(m_sif, false);
g_emu_thread->reloadGameSettings();
}
else

View file

@ -41,15 +41,13 @@ void PostProcessingSettingsWidget::commitSettingsUpdate()
{
if (m_dialog->isPerGameSettings())
{
m_dialog->getSettingsInterface()->Save();
g_emu_thread->reloadGameSettings(false);
m_dialog->saveAndReloadGameSettings();
}
else
{
Host::CommitBaseSettingChanges();
g_emu_thread->updatePostProcessingSettings();
}
g_emu_thread->updatePostProcessingSettings();
}
void PostProcessingSettingsWidget::connectUi()

View file

@ -171,6 +171,42 @@ INISettingsInterface* QtHost::GetBaseSettingsInterface()
return s_base_settings_interface.get();
}
bool QtHost::SaveGameSettings(SettingsInterface* sif, bool delete_if_empty)
{
INISettingsInterface* ini = static_cast<INISettingsInterface*>(sif);
Error error;
// if there's no keys, just toss the whole thing out
if (delete_if_empty && ini->IsEmpty())
{
Log_InfoFmt("Removing empty gamesettings ini {}", Path::GetFileName(ini->GetFileName()));
if (FileSystem::FileExists(ini->GetFileName().c_str()) &&
!FileSystem::DeleteFile(ini->GetFileName().c_str(), &error))
{
Host::ReportErrorAsync(
TRANSLATE_SV("QtHost", "Error"),
fmt::format(TRANSLATE_FS("QtHost", "An error occurred while deleting empty game settings:\n{}"),
error.GetDescription()));
return false;
}
return true;
}
// clean unused sections, stops the file being bloated
sif->RemoveEmptySections();
if (!sif->Save(&error))
{
Host::ReportErrorAsync(
TRANSLATE_SV("QtHost", "Error"),
fmt::format(TRANSLATE_FS("QtHost", "An error occurred while saving game settings:\n{}"), error.GetDescription()));
return false;
}
return true;
}
QIcon QtHost::GetAppIcon()
{
return QIcon(QStringLiteral(":/icons/duck.png"));

View file

@ -280,6 +280,9 @@ QString GetResourcesBasePath();
/// Returns the base settings interface. Should lock before manipulating.
INISettingsInterface* GetBaseSettingsInterface();
/// Saves a game settings interface.
bool SaveGameSettings(SettingsInterface* sif, bool delete_if_empty);
/// Downloads the specified URL to the provided path.
bool DownloadFile(QWidget* parent, const QString& title, std::string url, const char* path);

View file

@ -289,8 +289,7 @@ void SettingsWindow::onCopyGlobalSettingsClicked()
temp.Load(*Host::Internal::GetBaseSettingsLayer());
temp.Save(*m_sif.get(), true);
}
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
reloadPages();
@ -311,8 +310,7 @@ void SettingsWindow::onClearSettingsClicked()
}
Settings::Clear(*m_sif.get());
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
reloadPages();
@ -524,8 +522,7 @@ void SettingsWindow::setBoolSettingValue(const char* section, const char* key, s
if (m_sif)
{
value.has_value() ? m_sif->SetBoolValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -541,8 +538,7 @@ void SettingsWindow::setIntSettingValue(const char* section, const char* key, st
if (m_sif)
{
value.has_value() ? m_sif->SetIntValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -558,8 +554,7 @@ void SettingsWindow::setFloatSettingValue(const char* section, const char* key,
if (m_sif)
{
value.has_value() ? m_sif->SetFloatValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -575,8 +570,7 @@ void SettingsWindow::setStringSettingValue(const char* section, const char* key,
if (m_sif)
{
value.has_value() ? m_sif->SetStringValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -600,8 +594,7 @@ void SettingsWindow::removeSettingValue(const char* section, const char* key)
if (m_sif)
{
m_sif->DeleteValue(section, key);
m_sif->Save();
g_emu_thread->reloadGameSettings();
saveAndReloadGameSettings();
}
else
{
@ -611,6 +604,13 @@ void SettingsWindow::removeSettingValue(const char* section, const char* key)
}
}
void SettingsWindow::saveAndReloadGameSettings()
{
DebugAssert(m_sif);
QtHost::SaveGameSettings(m_sif.get(), true);
g_emu_thread->reloadGameSettings(false);
}
void SettingsWindow::openGamePropertiesDialog(const std::string& path, const std::string& serial, DiscRegion region)
{
const GameDatabase::Entry* dentry = nullptr;

View file

@ -88,6 +88,7 @@ public:
void setStringSettingValue(const char* section, const char* key, std::optional<const char*> value);
bool containsSettingValue(const char* section, const char* key) const;
void removeSettingValue(const char* section, const char* key);
void saveAndReloadGameSettings();
Q_SIGNALS:
void settingsResetToDefaults();

View file

@ -710,7 +710,7 @@ static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget,
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -753,7 +753,7 @@ static void BindWidgetToIntSetting(SettingsInterface* sif, WidgetType* widget, s
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -828,7 +828,7 @@ static inline void BindWidgetAndLabelToIntSetting(SettingsInterface* sif, Widget
}
}
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -876,7 +876,7 @@ static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget,
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -917,7 +917,7 @@ static void BindWidgetToNormalizedSetting(SettingsInterface* sif, WidgetType* wi
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -959,7 +959,7 @@ static void BindWidgetToStringSetting(SettingsInterface* sif, WidgetType* widget
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -1024,7 +1024,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
sif->DeleteValue(section.c_str(), key.c_str());
}
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -1092,7 +1092,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
@ -1160,7 +1160,7 @@ static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget,
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}

View file

@ -135,6 +135,11 @@ void INISettingsInterface::Clear()
m_ini.Reset();
}
bool INISettingsInterface::IsEmpty()
{
return (m_ini.GetKeyCount() == 0);
}
bool INISettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
{
const char* str_value = m_ini.GetValue(section, key);
@ -279,6 +284,29 @@ void INISettingsInterface::ClearSection(const char* section)
m_ini.SetValue(section, nullptr, nullptr);
}
void INISettingsInterface::RemoveSection(const char* section)
{
if (!m_ini.GetSection(section))
return;
m_dirty = true;
m_ini.Delete(section, nullptr);
}
void INISettingsInterface::RemoveEmptySections()
{
std::list<CSimpleIniA::Entry> entries;
m_ini.GetAllSections(entries);
for (const CSimpleIniA::Entry& entry : entries)
{
if (m_ini.GetSectionSize(entry.pItem) > 0)
continue;
m_dirty = true;
m_ini.Delete(entry.pItem, nullptr);
}
}
std::vector<std::string> INISettingsInterface::GetStringList(const char* section, const char* key) const
{
std::list<CSimpleIniA::Entry> entries;

View file

@ -22,6 +22,7 @@ public:
bool Save(Error* error = nullptr) override;
void Clear() override;
bool IsEmpty() override;
bool GetIntValue(const char* section, const char* key, s32* value) const override;
bool GetUIntValue(const char* section, const char* key, u32* value) const override;
@ -40,6 +41,8 @@ public:
bool ContainsValue(const char* section, const char* key) const override;
void DeleteValue(const char* section, const char* key) override;
void ClearSection(const char* section) override;
void RemoveSection(const char* section) override;
void RemoveEmptySections() override;
std::vector<std::string> GetStringList(const char* section, const char* key) const override;
void SetStringList(const char* section, const char* key, const std::vector<std::string>& items) override;