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
23 changed files with 247 additions and 47 deletions

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;