Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt: Clean and remove empty game settings #11190

Merged
merged 4 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions 3rdparty/simpleini/include/SimpleIni.h
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,11 @@ class CSimpleIniTempl
/** @}
@{ @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
Expand Down Expand Up @@ -2274,6 +2279,17 @@ CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSectionSize(
return nCount;
}

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>
const typename CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::TKeyVal *
CSimpleIniTempl<SI_CHAR,SI_STRLESS,SI_CONVERTER>::GetSection(
Expand Down
32 changes: 28 additions & 4 deletions common/FileSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1725,17 +1725,29 @@ bool FileSystem::CreateDirectoryPath(const char* Path, bool Recursive, Error* er
}
}

bool FileSystem::DeleteFilePath(const char* path)
bool FileSystem::DeleteFilePath(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;
}

if (!DeleteFileW(wpath.c_str()))
{
Error::SetWin32(error, "DeleteFileW() failed: ", GetLastError());
return false;
}

return (DeleteFileW(wpath.c_str()) == TRUE);
return true;
}

bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)
Expand Down Expand Up @@ -2213,16 +2225,28 @@ bool FileSystem::CreateDirectoryPath(const char* path, bool recursive, Error* er
}
}

bool FileSystem::DeleteFilePath(const char* path)
bool FileSystem::DeleteFilePath(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;
}

if (unlink(path) != 0)
{
Error::SetErrno(error, "unlink() failed: ", errno);
return false;
}

return (unlink(path) == 0);
return true;
}

bool FileSystem::RenamePath(const char* old_path, const char* new_path, Error* error)
Expand Down
2 changes: 1 addition & 1 deletion common/FileSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace FileSystem
bool DirectoryIsEmpty(const char* path);

/// Delete file
bool DeleteFilePath(const char* path);
bool DeleteFilePath(const char* path, Error* error = nullptr);

/// Rename file
bool RenamePath(const char* OldPath, const char* NewPath, Error* error = nullptr);
Expand Down
6 changes: 5 additions & 1 deletion common/HeapArray.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,11 @@ class DynamicHeapArray

void fill(const_reference value) { std::fill(begin(), end(), value); }

void swap(this_type& move) { std::swap(m_data, move.m_data); }
void swap(this_type& move)
{
std::swap(m_data, move.m_data);
std::swap(m_size, move.m_size);
}

void resize(size_t new_size) { internal_resize(new_size, m_data, m_size); }

Expand Down
28 changes: 28 additions & 0 deletions common/MemorySettingsInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,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);
Expand Down Expand Up @@ -312,3 +317,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);
}
}
4 changes: 4 additions & 0 deletions common/MemorySettingsInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class MemorySettingsInterface final : public SettingsInterface

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;
Expand All @@ -37,6 +39,8 @@ class MemorySettingsInterface final : public SettingsInterface
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;
Expand Down
3 changes: 3 additions & 0 deletions common/SettingsInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class SettingsInterface

virtual bool Save(Error* error = nullptr) = 0;
virtual void Clear() = 0;
virtual bool IsEmpty() = 0;

virtual bool GetIntValue(const char* section, const char* key, int* value) const = 0;
virtual bool GetUIntValue(const char* section, const char* key, uint* value) const = 0;
Expand Down Expand Up @@ -46,6 +47,8 @@ class SettingsInterface
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;

__fi int GetIntValue(const char* section, const char* key, int default_value = 0) const
{
Expand Down
36 changes: 36 additions & 0 deletions pcsx2-qt/QtHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,42 @@ std::string QtHost::GetRuntimeDownloadedResourceURL(std::string_view name)
return fmt::format("{}/{}", RUNTIME_RESOURCES_URL, Path::URLEncode(name));
}

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())
{
INFO_LOG("Removing empty gamesettings ini {}", Path::GetFileName(ini->GetFileName()));
if (FileSystem::FileExists(ini->GetFileName().c_str()) &&
!FileSystem::DeleteFilePath(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;
}

std::optional<bool> QtHost::DownloadFile(QWidget* parent, const QString& title, std::string url, std::vector<u8>* data)
{
static constexpr u32 HTTP_POLL_INTERVAL = 10;
Expand Down
3 changes: 3 additions & 0 deletions pcsx2-qt/QtHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ namespace QtHost
/// Returns the URL to a runtime-downloaded resource.
std::string GetRuntimeDownloadedResourceURL(std::string_view name);

/// 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 std::string& path);

Expand Down
18 changes: 9 additions & 9 deletions pcsx2-qt/SettingWidgetBinder.h
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -723,7 +723,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -797,7 +797,7 @@ namespace SettingWidgetBinder
}
}

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -845,7 +845,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -886,7 +886,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -927,7 +927,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -989,7 +989,7 @@ namespace SettingWidgetBinder
sif->DeleteValue(section.c_str(), key.c_str());
}

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -1055,7 +1055,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down Expand Up @@ -1120,7 +1120,7 @@ namespace SettingWidgetBinder
else
sif->DeleteValue(section.c_str(), key.c_str());

sif->Save();
QtHost::SaveGameSettings(sif, true);
g_emu_thread->reloadGameSettings();
});
}
Expand Down
4 changes: 2 additions & 2 deletions pcsx2-qt/Settings/AudioSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,9 +486,9 @@ void AudioSettingsWidget::resetVolume(bool fast_forward)

if (m_dialog->isPerGameSettings())
{
m_dialog->removeSettingValue("Audio", key);
m_dialog->removeSettingValue("SPU2/Output", key);

const int value = m_dialog->getEffectiveIntValue("Audio", key, 100);
const int value = m_dialog->getEffectiveIntValue("SPU2/Output", key, 100);
QSignalBlocker sb(slider);
slider->setValue(value);
label->setText(QStringLiteral("%1%2").arg(value).arg(tr("%")));
Expand Down
2 changes: 1 addition & 1 deletion pcsx2-qt/Settings/ControllerBindingWidgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ void ControllerBindingWidget::onClearBindingsClicked()
else
{
Pad::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
m_dialog->getProfileSettingsInterface()->Save();
QtHost::SaveGameSettings(m_dialog->getProfileSettingsInterface(), false);
}

// force a refresh after clearing
Expand Down
16 changes: 8 additions & 8 deletions pcsx2-qt/Settings/ControllerGlobalSettingsWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,

SettingsInterface* sif = dialog->getProfileSettingsInterface();

SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
connect(m_ui.enableSDLSource, &QCheckBox::checkStateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
connect(m_ui.ledSettings, &QToolButton::clicked, this, &ControllerGlobalSettingsWidget::ledSettingsClicked);

#ifdef _WIN32
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLRawInput, "InputSources", "SDLRawInput", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLRawInput, "InputSources", "SDLRawInput", false);
#else
m_ui.sdlGridLayout->removeWidget(m_ui.enableSDLRawInput);
m_ui.enableSDLRawInput->deleteLater();
m_ui.enableSDLRawInput = nullptr;
#endif

#ifdef __APPLE__
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLIOKitDriver, "InputSources", "SDLIOKitDriver", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLMFIDriver, "InputSources", "SDLMFIDriver", true);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLIOKitDriver, "InputSources", "SDLIOKitDriver", true);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLMFIDriver, "InputSources", "SDLMFIDriver", true);
#else
m_ui.sdlGridLayout->removeWidget(m_ui.enableSDLIOKitDriver);
m_ui.enableSDLIOKitDriver->deleteLater();
Expand All @@ -50,8 +50,8 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.multitapPort2, "Pad", "MultitapPort2", false);

#ifdef _WIN32
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableXInputSource, "InputSources", "XInput", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableDInputSource, "InputSources", "DInput", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableXInputSource, "InputSources", "XInput", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableDInputSource, "InputSources", "DInput", false);
#else
m_ui.mainLayout->removeWidget(m_ui.xinputGroup);
m_ui.xinputGroup->deleteLater();
Expand Down Expand Up @@ -204,7 +204,7 @@ ControllerMappingSettingsDialog::ControllerMappingSettingsDialog(ControllerSetti

m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("settings-3-line")).pixmap(32, 32));

SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.ignoreInversion, "InputSources", "IgnoreInversion", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.ignoreInversion, "InputSources", "IgnoreInversion", false);

connect(m_ui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::accept);
}
Expand Down
Loading