From d9587e20c0ed7e0999819966d98baee9f31917f7 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 9 Sep 2023 14:42:40 +1000 Subject: [PATCH] Qt: Defer folder update until editing complete Closes #7215. --- pcsx2-qt/SettingWidgetBinder.h | 82 ++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/pcsx2-qt/SettingWidgetBinder.h b/pcsx2-qt/SettingWidgetBinder.h index 7aa0c3516f..f3d38fa2b3 100644 --- a/pcsx2-qt/SettingWidgetBinder.h +++ b/pcsx2-qt/SettingWidgetBinder.h @@ -1,5 +1,5 @@ /* 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 * of the GNU Lesser General Public License as published by the Free Software Found- @@ -29,9 +29,11 @@ #include #include #include +#include #include #include +#include "common/FileSystem.h" #include "common/Path.h" #include "pcsx2/Config.h" @@ -125,9 +127,11 @@ namespace SettingWidgetBinder 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. - widget->insertItem(0, globalValue ? 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]")); + widget->insertItem(0, + globalValue ? + 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(); } @@ -939,9 +943,7 @@ namespace SettingWidgetBinder for (int i = 0; enum_names[i] != nullptr; i++) { - widget->addItem(translation_ctx ? - qApp->translate(translation_ctx, enum_names[i]) : - QString::fromUtf8(enum_names[i])); + widget->addItem(translation_ctx ? qApp->translate(translation_ctx, enum_names[i]) : QString::fromUtf8(enum_names[i])); } int enum_index = -1; @@ -997,12 +999,11 @@ namespace SettingWidgetBinder } } - template - static inline void BindWidgetToFolderSetting(SettingsInterface* sif, WidgetType* widget, QAbstractButton* browse_button, + static inline void BindWidgetToFolderSetting(SettingsInterface* sif, QLineEdit* widget, QAbstractButton* browse_button, QAbstractButton* open_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value, bool use_relative = true) { - using Accessor = SettingAccessor; + using Accessor = SettingAccessor; std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str())); if (current_path.empty()) @@ -1024,39 +1025,60 @@ namespace SettingWidgetBinder 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 (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)); - Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str()); - } - else - { - Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str()); + if (use_relative) + { + const std::string relative_path(Path::MakeRelative(new_value, EmuFolders::DataRoot)); + Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str()); + } + else + { + Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str()); + } + + Host::CommitBaseSettingChanges(); + g_emu_thread->updateEmuFolders(); + return; } } 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(); - g_emu_thread->updateEmuFolders(); - }); + // reset to old value + 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) { - 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), //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))))); if (path.isEmpty()) return; - Accessor::setStringValue(widget, path); + widget->setText(path); + value_changed(); }); } if (open_button) @@ -1069,10 +1091,14 @@ namespace SettingWidgetBinder } if (reset_button) { - QObject::connect(reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value)]() { - Accessor::setStringValue(widget, QString::fromStdString(default_value)); - }); + QObject::connect( + 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,