From 2b1de6278dca5a62f4d7e5897a1872f5adf27a1d Mon Sep 17 00:00:00 2001 From: Stenzek Date: Mon, 6 Jul 2026 12:31:59 +1000 Subject: [PATCH] Qt: Fix empty gamesettings ini being saved on close --- src/core/fullscreenui_settings.cpp | 6 +++++- src/duckstation-qt/qthost.cpp | 3 +++ src/duckstation-qt/settingswindow.cpp | 3 +++ src/util/ini_settings_interface.cpp | 5 +++++ src/util/ini_settings_interface.h | 1 + 5 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/core/fullscreenui_settings.cpp b/src/core/fullscreenui_settings.cpp index d96a9134d..5649caf28 100644 --- a/src/core/fullscreenui_settings.cpp +++ b/src/core/fullscreenui_settings.cpp @@ -2114,10 +2114,12 @@ void FullscreenUI::DrawSettingsWindow() if (s_settings_locals.game_settings_interface) { Error error; - s_settings_locals.game_settings_interface->RemoveEmptySections(); if (s_settings_locals.game_settings_interface->IsEmpty()) { + // prevent empty ini from being saved if it was modified and transitioned back to empty + s_settings_locals.game_settings_interface->SetDirty(false); + if (FileSystem::FileExists(s_settings_locals.game_settings_interface->GetPath().c_str())) { INFO_LOG("Removing empty game settings {}", s_settings_locals.game_settings_interface->GetPath()); @@ -2131,6 +2133,8 @@ void FullscreenUI::DrawSettingsWindow() } else { + s_settings_locals.game_settings_interface->RemoveEmptySections(); + if (!s_settings_locals.game_settings_interface->Save(&error)) { OpenInfoMessageDialog( diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index 02342722a..40e051aed 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -683,6 +683,9 @@ bool QtHost::SaveGameSettings(SettingsInterface* sif, bool delete_if_empty) { INFO_LOG("Removing empty gamesettings ini {}", Path::GetFileName(ini->GetPath())); + // prevent empty ini from being saved if it was modified and transitioned back to empty + ini->SetDirty(false); + // grab the settings lock while we're writing the file, that way the CPU thread doesn't try // to read it at the same time. const auto lock = Core::GetSettingsLock(); diff --git a/src/duckstation-qt/settingswindow.cpp b/src/duckstation-qt/settingswindow.cpp index b6f359691..39ced207c 100644 --- a/src/duckstation-qt/settingswindow.cpp +++ b/src/duckstation-qt/settingswindow.cpp @@ -77,6 +77,9 @@ SettingsWindow::SettingsWindow(const GameList::Entry* entry, std::unique_ptrIsDirty()) [[unlikely]] + WARNING_LOG("File {} was dirty when SettingsWindow was closed", Path::GetFileName(m_sif->GetPath())); + if (isPerGameSettings()) s_open_game_properties_dialogs.removeOne(this); } diff --git a/src/util/ini_settings_interface.cpp b/src/util/ini_settings_interface.cpp index 7c5f3298e..95df6ff1d 100644 --- a/src/util/ini_settings_interface.cpp +++ b/src/util/ini_settings_interface.cpp @@ -31,6 +31,11 @@ INISettingsInterface::~INISettingsInterface() Save(); } +void INISettingsInterface::SetDirty(bool dirty) +{ + m_dirty = dirty; +} + void INISettingsInterface::SetPath(std::string path) { m_dirty |= (path != m_path); diff --git a/src/util/ini_settings_interface.h b/src/util/ini_settings_interface.h index c120af023..56afac7b0 100644 --- a/src/util/ini_settings_interface.h +++ b/src/util/ini_settings_interface.h @@ -41,6 +41,7 @@ public: ALWAYS_INLINE bool IsDirty() const { return m_dirty; } ALWAYS_INLINE const std::string& GetPath() const { return m_path; } + void SetDirty(bool dirty); void SetPath(std::string path); bool Load(Error* error = nullptr);