mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 07:05:40 +00:00
Qt: Clean and remove empty game settings
This commit is contained in:
parent
d6ffdb0242
commit
1cdfca155d
|
@ -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(
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
void PostProcessingSettingsWidget::connectUi()
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue