Qt: Defer folder update until editing complete

Closes #7215.
This commit is contained in:
Stenzek 2023-09-09 14:42:40 +10:00 committed by Connor McLaughlin
parent f5684c43dd
commit d9587e20c0
1 changed files with 54 additions and 28 deletions

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs /* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team * Copyright (C) 2002-2023 PCSX2 Dev Team
* *
* PCSX2 is free software: you can redistribute it and/or modify it under the terms * PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found- * of the GNU Lesser General Public License as published by the Free Software Found-
@ -29,9 +29,11 @@
#include <QtWidgets/QLabel> #include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit> #include <QtWidgets/QLineEdit>
#include <QtWidgets/QMenu> #include <QtWidgets/QMenu>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QSlider> #include <QtWidgets/QSlider>
#include <QtWidgets/QSpinBox> #include <QtWidgets/QSpinBox>
#include "common/FileSystem.h"
#include "common/Path.h" #include "common/Path.h"
#include "pcsx2/Config.h" #include "pcsx2/Config.h"
@ -125,9 +127,11 @@ namespace SettingWidgetBinder
static void makeNullableBool(QComboBox* widget, bool globalValue) static void makeNullableBool(QComboBox* widget, bool globalValue)
{ {
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Enabled]: the text must be translated. //: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Enabled]: the text must be translated.
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") : widget->insertItem(0,
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Disabled]: the text must be translated. globalValue ?
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]")); qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Disabled]: the text must be translated.
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
} }
static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); } static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); }
@ -939,9 +943,7 @@ namespace SettingWidgetBinder
for (int i = 0; enum_names[i] != nullptr; i++) for (int i = 0; enum_names[i] != nullptr; i++)
{ {
widget->addItem(translation_ctx ? widget->addItem(translation_ctx ? qApp->translate(translation_ctx, enum_names[i]) : QString::fromUtf8(enum_names[i]));
qApp->translate(translation_ctx, enum_names[i]) :
QString::fromUtf8(enum_names[i]));
} }
int enum_index = -1; int enum_index = -1;
@ -997,12 +999,11 @@ namespace SettingWidgetBinder
} }
} }
template <typename WidgetType> static inline void BindWidgetToFolderSetting(SettingsInterface* sif, QLineEdit* widget, QAbstractButton* browse_button,
static inline void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget, QAbstractButton* browse_button,
QAbstractButton* open_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value, QAbstractButton* open_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value,
bool use_relative = true) bool use_relative = true)
{ {
using Accessor = SettingAccessor<WidgetType>; using Accessor = SettingAccessor<QLineEdit>;
std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str())); std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
if (current_path.empty()) if (current_path.empty())
@ -1024,39 +1025,60 @@ namespace SettingWidgetBinder
return; return;
} }
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), use_relative]() {
const std::string new_value(Accessor::getStringValue(widget).toStdString()); auto value_changed = [widget, section = std::move(section), key = std::move(key), default_value, use_relative]() {
const std::string new_value(widget->text().toStdString());
if (!new_value.empty()) if (!new_value.empty())
{ {
if (use_relative) if (FileSystem::DirectoryExists(new_value.c_str()) ||
QMessageBox::question(QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Confirm Folder"),
qApp->translate("SettingWidgetBinder",
"The chosen directory does not currently exist:\n\n%1\n\nDo you want to create this directory?")
.arg(QString::fromStdString(new_value)),
QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
{ {
const std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot)); if (use_relative)
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str()); {
} const std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot));
else Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str());
{ }
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str()); else
{
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str());
}
Host::CommitBaseSettingChanges();
g_emu_thread->updateEmuFolders();
return;
} }
} }
else else
{ {
Host::RemoveBaseSettingValue(section.c_str(), key.c_str()); QMessageBox::critical(QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Error"),
qApp->translate("SettingWidgetBinder", "Folder path cannot be empty."));
} }
Host::CommitBaseSettingChanges(); // reset to old value
g_emu_thread->updateEmuFolders(); std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
}); if (current_path.empty())
current_path = default_value;
else if (use_relative && !Path::IsAbsolute(current_path))
current_path = Path::Canonicalize(Path::Combine(EmuFolders::DataRoot, current_path));
widget->setText(QString::fromStdString(current_path));
};
if (browse_button) if (browse_button)
{ {
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key]() { QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key, value_changed]() {
const QString path(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(widget), const QString path(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(widget),
//It seems that the latter half should show the types of folders that can be selected within Settings -> Folders, but right now it's broken. It would be best for localization purposes to duplicate this into multiple lines, each per type of folder. //It seems that the latter half should show the types of folders that can be selected within Settings -> Folders, but right now it's broken. It would be best for localization purposes to duplicate this into multiple lines, each per type of folder.
qApp->translate("SettingWidgetBinder", "Select folder for %1").arg(QString::fromStdString(key))))); qApp->translate("SettingWidgetBinder", "Select folder for %1").arg(QString::fromStdString(key)))));
if (path.isEmpty()) if (path.isEmpty())
return; return;
Accessor::setStringValue(widget, path); widget->setText(path);
value_changed();
}); });
} }
if (open_button) if (open_button)
@ -1069,10 +1091,14 @@ namespace SettingWidgetBinder
} }
if (reset_button) if (reset_button)
{ {
QObject::connect(reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value)]() { QObject::connect(
Accessor::setStringValue(widget, QString::fromStdString(default_value)); reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value), value_changed]() {
}); widget->setText(QString::fromStdString(default_value));
value_changed();
});
} }
widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed));
} }
static inline void BindSliderToIntSetting(SettingsInterface* sif, QSlider* slider, QLabel* label, const QString& label_suffix, static inline void BindSliderToIntSetting(SettingsInterface* sif, QSlider* slider, QLabel* label, const QString& label_suffix,