From 33fd06d7f334f904d9b9742f7d1fb6f51f3b2a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Tue, 12 Aug 2025 15:04:19 +0200 Subject: [PATCH 1/6] AdvancedPane: Add a button to restore default settings --- Source/Core/Common/FileUtil.cpp | 2 + Source/Core/Common/FileUtil.h | 2 + Source/Core/Core/ConfigManager.cpp | 23 ++++++++++ Source/Core/Core/ConfigManager.h | 2 + Source/Core/DolphinQt/CMakeLists.txt | 2 + Source/Core/DolphinQt/DolphinQt.vcxproj | 2 + Source/Core/DolphinQt/Main.cpp | 41 ++++-------------- .../DolphinQt/QtUtils/AnalyticsPrompt.cpp | 41 ++++++++++++++++++ .../Core/DolphinQt/QtUtils/AnalyticsPrompt.h | 8 ++++ .../Core/DolphinQt/Settings/AdvancedPane.cpp | 43 +++++++++++++++++++ Source/Core/DolphinQt/Settings/AdvancedPane.h | 7 ++- 11 files changed, 139 insertions(+), 34 deletions(-) create mode 100644 Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.cpp create mode 100644 Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.h diff --git a/Source/Core/Common/FileUtil.cpp b/Source/Core/Common/FileUtil.cpp index 4521be00be6..bcfd74256d9 100644 --- a/Source/Core/Common/FileUtil.cpp +++ b/Source/Core/Common/FileUtil.cpp @@ -882,6 +882,7 @@ static void RebuildUserDirectories(unsigned int dir_index) s_user_paths[D_GRAPHICSMOD_IDX] = s_user_paths[D_LOAD_IDX] + GRAPHICSMOD_DIR DIR_SEP; s_user_paths[D_BANNERS_WIIROOT_IDX] = s_user_paths[D_LOAD_IDX] + WIIBANNERS_DIR DIR_SEP; s_user_paths[D_FIRMWARE_IDX] = s_user_paths[D_LOAD_IDX] + FIRMWARE_DIR DIR_SEP; + s_user_paths[D_WIISYSCONF_IDX] = s_user_paths[D_WIIROOT_IDX] + WII_SYSCONF_DIR DIR_SEP; s_user_paths[D_WIISDCARDSYNCFOLDER_IDX] = s_user_paths[D_LOAD_IDX] + WIISDSYNC_DIR DIR_SEP; s_user_paths[F_DOLPHINCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + DOLPHIN_CONFIG; s_user_paths[F_GCPADCONFIG_IDX] = s_user_paths[D_CONFIG_IDX] + GCPAD_CONFIG; @@ -901,6 +902,7 @@ static void RebuildUserDirectories(unsigned int dir_index) s_user_paths[F_FAKEVMEMDUMP_IDX] = s_user_paths[D_DUMP_IDX] + FAKEVMEM_DUMP; s_user_paths[F_GCSRAM_IDX] = s_user_paths[D_GCUSER_IDX] + GC_SRAM; s_user_paths[F_WIISDCARDIMAGE_IDX] = s_user_paths[D_LOAD_IDX] + WII_SD_CARD_IMAGE; + s_user_paths[F_WIISYSCONF_IDX] = s_user_paths[D_WIISYSCONF_IDX] + WII_SYSCONF; s_user_paths[D_MEMORYWATCHER_IDX] = s_user_paths[D_USER_IDX] + MEMORYWATCHER_DIR DIR_SEP; s_user_paths[F_MEMORYWATCHERLOCATIONS_IDX] = diff --git a/Source/Core/Common/FileUtil.h b/Source/Core/Common/FileUtil.h index eb6473e5099..37548acfed0 100644 --- a/Source/Core/Common/FileUtil.h +++ b/Source/Core/Common/FileUtil.h @@ -71,6 +71,7 @@ enum D_GBAUSER_IDX, D_GBASAVES_IDX, D_WIISDCARDSYNCFOLDER_IDX, + D_WIISYSCONF_IDX, D_GPU_DRIVERS_EXTRACTED, D_GPU_DRIVERS_TMP, D_GPU_DRIVERS_HOOKS, @@ -93,6 +94,7 @@ enum F_MEMORYWATCHERLOCATIONS_IDX, F_MEMORYWATCHERSOCKET_IDX, F_WIISDCARDIMAGE_IDX, + F_WIISYSCONF_IDX, F_DUALSHOCKUDPCLIENTCONFIG_IDX, F_FREELOOKCONFIG_IDX, F_GBABIOS_IDX, diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 4e0b7dd3ac8..a2c2ac1f0f7 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -102,6 +102,29 @@ void SConfig::LoadSettings() Config::Load(); } +void SConfig::ResetAllSettings() +{ + Config::ConfigChangeCallbackGuard config_guard; + + File::Delete(File::GetUserPath(F_DOLPHINCONFIG_IDX)); + File::Delete(File::GetUserPath(F_GFXCONFIG_IDX)); + File::Delete(File::GetUserPath(F_LOGGERCONFIG_IDX)); + File::Delete(File::GetUserPath(F_DUALSHOCKUDPCLIENTCONFIG_IDX)); + File::Delete(File::GetUserPath(F_FREELOOKCONFIG_IDX)); + File::Delete(File::GetUserPath(F_RETROACHIEVEMENTSCONFIG_IDX)); + File::Delete(File::GetUserPath(F_WIISYSCONF_IDX)); + + for (Config::LayerType layer_type : Config::SEARCH_ORDER) + { + const std::shared_ptr layer = Config::GetLayer(layer_type); + if (!layer) + continue; + layer->DeleteAllKeys(); + } + + Config::OnConfigChanged(); +} + const std::string SConfig::GetGameID() const { std::lock_guard lock(m_metadata_lock); diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index f441cd888b9..e255974d8b2 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -110,6 +110,8 @@ struct SConfig // Load settings void LoadSettings(); + static void ResetAllSettings(); + // Return the permanent and somewhat globally used instance of this struct static SConfig& GetInstance() { return (*m_Instance); } static void Init(); diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 93c85a39972..a371fb16933 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -307,6 +307,8 @@ add_executable(dolphin-emu NANDRepairDialog.h NKitWarningDialog.cpp NKitWarningDialog.h + QtUtils/AnalyticsPrompt.cpp + QtUtils/AnalyticsPrompt.h QtUtils/AspectRatioWidget.cpp QtUtils/AspectRatioWidget.h QtUtils/BlockUserInputFilter.cpp diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index eb548ae0ad8..2084db0e32f 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -189,6 +189,7 @@ Create + @@ -408,6 +409,7 @@ + diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp index a69c5af22e8..49436475ae9 100644 --- a/Source/Core/DolphinQt/Main.cpp +++ b/Source/Core/DolphinQt/Main.cpp @@ -33,6 +33,7 @@ #include "DolphinQt/Host.h" #include "DolphinQt/MainWindow.h" +#include "DolphinQt/QtUtils/AnalyticsPrompt.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/RunOnObject.h" #include "DolphinQt/QtUtils/SetWindowDecorations.h" @@ -269,40 +270,16 @@ int main(int argc, char* argv[]) // the dialog is only shown after the application is ready, as only then it is guaranteed that // the main window has been placed in its final position. auto* const connection_context = new QObject(&win); - QObject::connect( - qApp, &QGuiApplication::applicationStateChanged, connection_context, - [connection_context, &win](const Qt::ApplicationState state) { - if (state != Qt::ApplicationState::ApplicationActive) - return; + QObject::connect(qApp, &QGuiApplication::applicationStateChanged, connection_context, + [connection_context, &win](const Qt::ApplicationState state) { + if (state != Qt::ApplicationState::ApplicationActive) + return; - // Severe the connection after the first run. - delete connection_context; + // Severe the connection after the first run. + delete connection_context; - ModalMessageBox analytics_prompt(&win); - - analytics_prompt.setIcon(QMessageBox::Question); - analytics_prompt.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - analytics_prompt.setWindowTitle(QObject::tr("Allow Usage Statistics Reporting")); - analytics_prompt.setText(QObject::tr( - "Do you authorize Dolphin to report information to Dolphin's developers?")); - analytics_prompt.setInformativeText( - QObject::tr("If authorized, Dolphin can collect data on its performance, " - "feature usage, and configuration, as well as data on your system's " - "hardware and operating system.\n\n" - "No private data is ever collected. This data helps us understand " - "how people and emulated games use Dolphin and prioritize our " - "efforts. It also helps us identify rare configurations that are " - "causing bugs, performance and stability issues.\n" - "This authorization can be revoked at any time through Dolphin's " - "settings.")); - - const int answer = analytics_prompt.exec(); - - Config::SetBase(Config::MAIN_ANALYTICS_PERMISSION_ASKED, true); - Settings::Instance().SetAnalyticsEnabled(answer == QMessageBox::Yes); - - DolphinAnalytics::Instance().ReloadConfig(); - }); + ShowAnalyticsPrompt(&win); + }); } #endif diff --git a/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.cpp b/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.cpp new file mode 100644 index 00000000000..f9a4b6379cd --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.cpp @@ -0,0 +1,41 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/QtUtils/AnalyticsPrompt.h" + +#include +#include +#include + +#include "Core/Config/MainSettings.h" +#include "Core/DolphinAnalytics.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/Settings.h" + +void ShowAnalyticsPrompt(QWidget* parent) +{ + ModalMessageBox analytics_prompt(parent); + + analytics_prompt.setIcon(QMessageBox::Question); + analytics_prompt.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + analytics_prompt.setWindowTitle(QObject::tr("Allow Usage Statistics Reporting")); + analytics_prompt.setText( + QObject::tr("Do you authorize Dolphin to report information to Dolphin's developers?")); + analytics_prompt.setInformativeText( + QObject::tr("If authorized, Dolphin can collect data on its performance, " + "feature usage, and configuration, as well as data on your system's " + "hardware and operating system.\n\n" + "No private data is ever collected. This data helps us understand " + "how people and emulated games use Dolphin and prioritize our " + "efforts. It also helps us identify rare configurations that are " + "causing bugs, performance and stability issues.\n" + "This authorization can be revoked at any time through Dolphin's " + "settings.")); + + const int answer = analytics_prompt.exec(); + + Config::SetBase(Config::MAIN_ANALYTICS_PERMISSION_ASKED, true); + Settings::Instance().SetAnalyticsEnabled(answer == QMessageBox::Yes); + + DolphinAnalytics::Instance().ReloadConfig(); +} diff --git a/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.h b/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.h new file mode 100644 index 00000000000..563d6ae3a61 --- /dev/null +++ b/Source/Core/DolphinQt/QtUtils/AnalyticsPrompt.h @@ -0,0 +1,8 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +void ShowAnalyticsPrompt(QWidget* parent); diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp index e6abd0921e1..4f5d4bfa7d5 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp @@ -17,6 +17,9 @@ #include #include +#include "Common/Config/Config.h" +#include "Common/Config/Enums.h" +#include "Common/FileUtil.h" #include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" @@ -28,10 +31,15 @@ #include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include "DolphinQt/QtUtils/AnalyticsPrompt.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/SignalBlocking.h" #include "DolphinQt/Settings.h" +#include "UICommon/UICommon.h" + static const std::map CPU_CORE_NAMES = { {PowerPC::CPUCore::Interpreter, QT_TR_NOOP("Interpreter (slowest)")}, {PowerPC::CPUCore::CachedInterpreter, QT_TR_NOOP("Cached Interpreter (slower)")}, @@ -284,6 +292,15 @@ void AdvancedPane::CreateLayout() "your current system time." "

If unsure, leave this unchecked.")); + auto* reset_group = new QGroupBox(tr("Reset Dolphin Settings")); + reset_group->setLayout(new QVBoxLayout()); + main_layout->addWidget(reset_group); + + m_reset_button = new NonDefaultQPushButton(tr("Reset All Settings")); + connect(m_reset_button, &QPushButton::clicked, this, &AdvancedPane::OnResetButtonClicked); + + reset_group->layout()->addWidget(m_reset_button); + main_layout->addStretch(1); } @@ -366,4 +383,30 @@ void AdvancedPane::Update() initial_date_time.setSecsSinceEpoch(Config::Get(Config::MAIN_CUSTOM_RTC_VALUE)); m_custom_rtc_datetime->setEnabled(enable_custom_rtc_widgets); SignalBlocking(m_custom_rtc_datetime)->setDateTime(initial_date_time); + + m_reset_button->setEnabled(is_uninitialized); +} + +void AdvancedPane::OnResetButtonClicked() +{ + if (ModalMessageBox::question( + this, tr("Reset Dolphin Settings"), + tr("Are you sure you want to restore all Dolphin settings to their default " + "values? This action cannot be undone!\n" + "All customizations or changes you have made will be lost.\n\n" + "Do you want to proceed?"), + ModalMessageBox::StandardButtons(ModalMessageBox::Yes | ModalMessageBox::No), + ModalMessageBox::No, Qt::WindowModality::WindowModal) == ModalMessageBox::No) + { + return; + } + + SConfig::ResetAllSettings(); + UICommon::SetUserDirectory(File::GetUserPath(D_USER_IDX)); + + emit Settings::Instance().ConfigChanged(); + +#if defined(USE_ANALYTICS) && USE_ANALYTICS + ShowAnalyticsPrompt(this); +#endif } diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.h b/Source/Core/DolphinQt/Settings/AdvancedPane.h index 0d70b817cc2..f3a8c831983 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.h +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.h @@ -3,8 +3,7 @@ #pragma once -#include - +#include #include class ConfigBool; @@ -34,6 +33,8 @@ private: void ConnectLayout(); void Update(); + void OnResetButtonClicked(); + QComboBox* m_cpu_emulation_engine_combobox; ConfigBool* m_enable_mmu_checkbox; ConfigBool* m_pause_on_panic_checkbox; @@ -54,4 +55,6 @@ private: QLabel* m_mem1_label; ConfigSliderU32* m_mem2_override_slider; QLabel* m_mem2_label; + + QPushButton* m_reset_button; }; From 1e227bd736b4343f7fac807ac3540d4824e85a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Tue, 12 Aug 2025 16:43:50 +0200 Subject: [PATCH 2/6] FreeLookWidget: Use ConfigControls where applicable --- .../Core/DolphinQt/Config/FreeLookWidget.cpp | 24 ++++--------------- Source/Core/DolphinQt/Config/FreeLookWidget.h | 3 ++- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/Source/Core/DolphinQt/Config/FreeLookWidget.cpp b/Source/Core/DolphinQt/Config/FreeLookWidget.cpp index 781773a74ea..a28091f61fc 100644 --- a/Source/Core/DolphinQt/Config/FreeLookWidget.cpp +++ b/Source/Core/DolphinQt/Config/FreeLookWidget.cpp @@ -3,7 +3,6 @@ #include "DolphinQt/Config/FreeLookWidget.h" -#include #include #include #include @@ -15,9 +14,9 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" #include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" -#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/Settings.h" @@ -32,8 +31,7 @@ void FreeLookWidget::CreateLayout() { auto* layout = new QVBoxLayout(); - m_enable_freelook = new ToolTipCheckBox(tr("Enable")); - m_enable_freelook->setChecked(Config::Get(Config::FREE_LOOK_ENABLED)); + m_enable_freelook = new ConfigBool(tr("Enable"), Config::FREE_LOOK_ENABLED); m_enable_freelook->SetDescription( tr("Allows manipulation of the in-game camera.

If unsure, " "leave this unchecked.")); @@ -67,8 +65,8 @@ void FreeLookWidget::CreateLayout() description->setTextInteractionFlags(Qt::TextBrowserInteraction); description->setOpenExternalLinks(true); - m_freelook_background_input = new QCheckBox(tr("Background Input")); - m_freelook_background_input->setChecked(Config::Get(Config::FREE_LOOK_BACKGROUND_INPUT)); + m_freelook_background_input = + new ConfigBool(tr("Background Input"), Config::FREE_LOOK_BACKGROUND_INPUT); auto* hlayout = new QHBoxLayout(); hlayout->addWidget(new QLabel(tr("Camera 1"))); @@ -87,8 +85,6 @@ void FreeLookWidget::ConnectWidgets() { connect(m_freelook_controller_configure_button, &QPushButton::clicked, this, &FreeLookWidget::OnFreeLookControllerConfigured); - connect(m_enable_freelook, &QCheckBox::clicked, this, &FreeLookWidget::SaveSettings); - connect(m_freelook_background_input, &QCheckBox::clicked, this, &FreeLookWidget::SaveSettings); connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] { const QSignalBlocker blocker(this); LoadSettings(); @@ -109,7 +105,6 @@ void FreeLookWidget::OnFreeLookControllerConfigured() void FreeLookWidget::LoadSettings() { const bool checked = Config::Get(Config::FREE_LOOK_ENABLED); - m_enable_freelook->setChecked(checked); #ifdef USE_RETRO_ACHIEVEMENTS const bool hardcore = AchievementManager::GetInstance().IsHardcoreModeActive(); m_enable_freelook->setEnabled(!hardcore); @@ -118,14 +113,3 @@ void FreeLookWidget::LoadSettings() m_freelook_controller_configure_button->setEnabled(checked); m_freelook_background_input->setEnabled(checked); } - -void FreeLookWidget::SaveSettings() -{ - const bool checked = m_enable_freelook->isChecked(); - Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, checked); - Config::SetBaseOrCurrent(Config::FREE_LOOK_BACKGROUND_INPUT, - m_freelook_background_input->isChecked()); - m_freelook_control_type->setEnabled(checked); - m_freelook_controller_configure_button->setEnabled(checked); - m_freelook_background_input->setEnabled(checked); -} diff --git a/Source/Core/DolphinQt/Config/FreeLookWidget.h b/Source/Core/DolphinQt/Config/FreeLookWidget.h index 3d04bbd6c6b..f2ebcb0527c 100644 --- a/Source/Core/DolphinQt/Config/FreeLookWidget.h +++ b/Source/Core/DolphinQt/Config/FreeLookWidget.h @@ -5,6 +5,7 @@ #include +class ConfigBool; class ConfigChoice; class QCheckBox; class QPushButton; @@ -24,7 +25,7 @@ private: void LoadSettings(); void SaveSettings(); - ToolTipCheckBox* m_enable_freelook; + ConfigBool* m_enable_freelook; ConfigChoice* m_freelook_control_type; QPushButton* m_freelook_controller_configure_button; QCheckBox* m_freelook_background_input; From b6766e1ca0146de939e6645b743634bda717b719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Wed, 13 Aug 2025 00:33:52 +0200 Subject: [PATCH 3/6] GameCubePane: Use ConfigControls where applicable --- Source/Core/DolphinQt/CMakeLists.txt | 4 + .../Config/ConfigControls/ConfigText.cpp | 39 +++++++ .../Config/ConfigControls/ConfigText.h | 28 +++++ .../Config/ConfigControls/ConfigUserPath.cpp | 59 ++++++++++ .../Config/ConfigControls/ConfigUserPath.h | 28 +++++ Source/Core/DolphinQt/DolphinQt.vcxproj | 4 + .../Core/DolphinQt/Settings/GameCubePane.cpp | 102 ++++-------------- Source/Core/DolphinQt/Settings/GameCubePane.h | 19 ++-- Source/Core/UICommon/UICommon.cpp | 2 - 9 files changed, 194 insertions(+), 91 deletions(-) create mode 100644 Source/Core/DolphinQt/Config/ConfigControls/ConfigText.cpp create mode 100644 Source/Core/DolphinQt/Config/ConfigControls/ConfigText.h create mode 100644 Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.cpp create mode 100644 Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index a371fb16933..ba2e5522a42 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -68,6 +68,10 @@ add_executable(dolphin-emu Config/ConfigControls/ConfigFloatSlider.h Config/ConfigControls/ConfigSlider.cpp Config/ConfigControls/ConfigSlider.h + Config/ConfigControls/ConfigText.cpp + Config/ConfigControls/ConfigText.h + Config/ConfigControls/ConfigUserPath.cpp + Config/ConfigControls/ConfigUserPath.h Config/ControllerInterface/ControllerInterfaceWindow.cpp Config/ControllerInterface/ControllerInterfaceWindow.h Config/ControllerInterface/DualShockUDPClientAddServerDialog.cpp diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.cpp new file mode 100644 index 00000000000..41e4d2166ed --- /dev/null +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.cpp @@ -0,0 +1,39 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/Config/ConfigControls/ConfigText.h" + +#include + +ConfigText::ConfigText(const Config::Info& setting) : ConfigText(setting, nullptr) +{ +} + +ConfigText::ConfigText(const Config::Info& setting, Config::Layer* layer) + : ConfigControl(setting.GetLocation(), layer), m_setting(setting) +{ + setText(QString::fromStdString(ReadValue(setting))); + + connect(this, &QLineEdit::editingFinished, this, &ConfigText::Update); +} + +void ConfigText::SetTextAndUpdate(const QString& text) +{ + if (text == this->text()) + return; + + setText(text); + Update(); +} + +void ConfigText::Update() +{ + const std::string value = text().toStdString(); + + SaveValue(m_setting, value); +} + +void ConfigText::OnConfigChanged() +{ + setText(QString::fromStdString(ReadValue(m_setting))); +} diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.h new file mode 100644 index 00000000000..51cd8b2179c --- /dev/null +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigText.h @@ -0,0 +1,28 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "DolphinQt/Config/ConfigControls/ConfigControl.h" + +#include "Common/Config/ConfigInfo.h" + +class ConfigText : public ConfigControl +{ + Q_OBJECT +public: + ConfigText(const Config::Info& setting); + ConfigText(const Config::Info& setting, Config::Layer* layer); + + void SetTextAndUpdate(const QString& text); + +protected: + void OnConfigChanged() override; + + const Config::Info m_setting; + +private: + void Update(); +}; diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.cpp new file mode 100644 index 00000000000..1b6c03f915d --- /dev/null +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.cpp @@ -0,0 +1,59 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/Config/ConfigControls/ConfigUserPath.h" + +#include +#include + +#include "Common/FileUtil.h" + +#include "DolphinQt/Config/ConfigControls/ConfigText.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" + +ConfigUserPath::ConfigUserPath(const unsigned int dir_index, + const Config::Info& setting) + : ConfigUserPath(dir_index, setting, nullptr) +{ +} + +ConfigUserPath::ConfigUserPath(const unsigned int dir_index, + const Config::Info& setting, Config::Layer* layer) + : ConfigText(setting, layer), m_dir_index(dir_index) +{ + OnConfigChanged(); + + connect(this, &QLineEdit::editingFinished, this, &ConfigUserPath::Update); +} + +// Display the effective path: if Config has a value, use it; otherwise fall back to UserPath. +// Config values only serve to initialize UserPath at startup, an empty config meaning "use the +// current UserPath". +void ConfigUserPath::RefreshText() +{ + const std::string config_value = ReadValue(m_setting); + const std::string userpath_value = File::GetUserPath(m_dir_index); + const QString text = QString::fromStdString(config_value.empty() ? userpath_value : config_value); + setText(text); +} + +void ConfigUserPath::Update() +{ + const QString new_text = text().trimmed(); + if (new_text.isEmpty()) + { + ModalMessageBox::warning(this, tr("Empty Value"), + tr("This field cannot be left empty. Please enter a value.")); + RefreshText(); + return; + } + + const std::string value = new_text.toStdString(); + File::SetUserPath(m_dir_index, value); + SaveValue(m_setting, value); +} + +void ConfigUserPath::OnConfigChanged() +{ + RefreshText(); +} diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.h new file mode 100644 index 00000000000..40fea637092 --- /dev/null +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigUserPath.h @@ -0,0 +1,28 @@ +// Copyright 2025 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "Common/Config/ConfigInfo.h" + +#include "DolphinQt/Config/ConfigControls/ConfigText.h" + +class ConfigUserPath final : public ConfigText +{ + Q_OBJECT +public: + ConfigUserPath(const unsigned int dir_index, const Config::Info& setting); + ConfigUserPath(const unsigned int dir_index, const Config::Info& setting, + Config::Layer* layer); + +protected: + void OnConfigChanged() override; + +private: + void RefreshText(); + void Update(); + + const unsigned int m_dir_index; +}; diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 2084db0e32f..fe5a2dda4a7 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -64,6 +64,8 @@ + + @@ -295,6 +297,8 @@ + + diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 1cd5dc5a2fc..c84475600e4 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -34,6 +34,10 @@ #include "Core/NetPlayServer.h" #include "Core/System.h" +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigChoice.h" +#include "DolphinQt/Config/ConfigControls/ConfigText.h" +#include "DolphinQt/Config/ConfigControls/ConfigUserPath.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" #include "DolphinQt/GCMemcardManager.h" #include "DolphinQt/QtUtils/DolphinFileDialog.h" @@ -64,7 +68,7 @@ void GameCubePane::CreateWidgets() QVBoxLayout* ipl_box_layout = new QVBoxLayout(ipl_box); ipl_box->setLayout(ipl_box_layout); - m_skip_main_menu = new QCheckBox(tr("Skip Main Menu"), ipl_box); + m_skip_main_menu = new ConfigBool(tr("Skip Main Menu"), Config::MAIN_SKIP_IPL); ipl_box_layout->addWidget(m_skip_main_menu); QFormLayout* ipl_language_layout = new QFormLayout; @@ -72,17 +76,11 @@ void GameCubePane::CreateWidgets() ipl_language_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); ipl_box_layout->addLayout(ipl_language_layout); - m_language_combo = new QComboBox(ipl_box); - m_language_combo->setCurrentIndex(-1); - ipl_language_layout->addRow(tr("System Language:"), m_language_combo); + const QStringList language_list{tr("English"), tr("German"), tr("French"), + tr("Spanish"), tr("Italian"), tr("Dutch")}; - // Add languages - for (const auto& entry : {std::make_pair(tr("English"), 0), std::make_pair(tr("German"), 1), - std::make_pair(tr("French"), 2), std::make_pair(tr("Spanish"), 3), - std::make_pair(tr("Italian"), 4), std::make_pair(tr("Dutch"), 5)}) - { - m_language_combo->addItem(entry.first, entry.second); - } + m_language_combo = new ConfigChoice(language_list, Config::MAIN_GC_LANGUAGE); + ipl_language_layout->addRow(tr("System Language:"), m_language_combo); // Device Settings QGroupBox* device_box = new QGroupBox(tr("Device Settings"), this); @@ -194,11 +192,12 @@ void GameCubePane::CreateWidgets() gba_box->setLayout(gba_layout); int gba_row = 0; - m_gba_threads = new QCheckBox(tr("Run GBA Cores in Dedicated Threads")); + m_gba_threads = + new ConfigBool(tr("Run GBA Cores in Dedicated Threads"), Config::MAIN_GBA_THREADS); gba_layout->addWidget(m_gba_threads, gba_row, 0, 1, -1); gba_row++; - m_gba_bios_edit = new QLineEdit(); + m_gba_bios_edit = new ConfigUserPath(F_GBABIOS_IDX, Config::MAIN_GBA_BIOS_PATH); m_gba_browse_bios = new NonDefaultQPushButton(QStringLiteral("...")); gba_layout->addWidget(new QLabel(tr("BIOS:")), gba_row, 0); gba_layout->addWidget(m_gba_bios_edit, gba_row, 1); @@ -207,7 +206,7 @@ void GameCubePane::CreateWidgets() for (size_t i = 0; i < m_gba_rom_edits.size(); ++i) { - m_gba_rom_edits[i] = new QLineEdit(); + m_gba_rom_edits[i] = new ConfigText(Config::MAIN_GBA_ROM_PATHS[i]); m_gba_browse_roms[i] = new NonDefaultQPushButton(QStringLiteral("...")); gba_layout->addWidget(new QLabel(tr("Port %1 ROM:").arg(i + 1)), gba_row, 0); gba_layout->addWidget(m_gba_rom_edits[i], gba_row, 1); @@ -215,11 +214,12 @@ void GameCubePane::CreateWidgets() gba_row++; } - m_gba_save_rom_path = new QCheckBox(tr("Save in Same Directory as the ROM")); + m_gba_save_rom_path = + new ConfigBool(tr("Save in Same Directory as the ROM"), Config::MAIN_GBA_SAVES_IN_ROM_PATH); gba_layout->addWidget(m_gba_save_rom_path, gba_row, 0, 1, -1); gba_row++; - m_gba_saves_edit = new QLineEdit(); + m_gba_saves_edit = new ConfigUserPath(D_GBASAVES_IDX, Config::MAIN_GBA_SAVES_PATH); m_gba_browse_saves = new NonDefaultQPushButton(QStringLiteral("...")); gba_layout->addWidget(new QLabel(tr("Saves:")), gba_row, 0); gba_layout->addWidget(m_gba_saves_edit, gba_row, 1); @@ -240,14 +240,6 @@ void GameCubePane::CreateWidgets() void GameCubePane::ConnectWidgets() { - // IPL Settings -#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) - connect(m_skip_main_menu, &QCheckBox::checkStateChanged, this, &GameCubePane::SaveSettings); -#else - connect(m_skip_main_menu, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); -#endif - connect(m_language_combo, &QComboBox::currentIndexChanged, this, &GameCubePane::SaveSettings); - // Device Settings for (ExpansionInterface::Slot slot : GUI_SLOTS) { @@ -276,13 +268,6 @@ void GameCubePane::ConnectWidgets() #ifdef HAS_LIBMGBA // GBA Settings - -#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) - connect(m_gba_threads, &QCheckBox::checkStateChanged, this, &GameCubePane::SaveSettings); -#else - connect(m_gba_threads, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); -#endif - connect(m_gba_bios_edit, &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings); connect(m_gba_browse_bios, &QPushButton::clicked, this, &GameCubePane::BrowseGBABios); #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0) connect(m_gba_save_rom_path, &QCheckBox::checkStateChanged, this, @@ -290,11 +275,9 @@ void GameCubePane::ConnectWidgets() #else connect(m_gba_save_rom_path, &QCheckBox::stateChanged, this, &GameCubePane::SaveRomPathChanged); #endif - connect(m_gba_saves_edit, &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings); connect(m_gba_browse_saves, &QPushButton::clicked, this, &GameCubePane::BrowseGBASaves); for (size_t i = 0; i < m_gba_browse_roms.size(); ++i) { - connect(m_gba_rom_edits[i], &QLineEdit::editingFinished, this, &GameCubePane::SaveSettings); connect(m_gba_browse_roms[i], &QPushButton::clicked, this, [this, i] { BrowseGBARom(i); }); } #endif @@ -682,37 +665,30 @@ void GameCubePane::SetAGPRom(ExpansionInterface::Slot slot, const QString& filen void GameCubePane::BrowseGBABios() { QString file = QDir::toNativeSeparators(DolphinFileDialog::getOpenFileName( - this, tr("Select GBA BIOS"), QString::fromStdString(File::GetUserPath(F_GBABIOS_IDX)), + this, tr("Select GBA BIOS"), QString::fromStdString(Config::Get(Config::MAIN_GBA_BIOS_PATH)), tr("All Files (*)"))); if (!file.isEmpty()) - { - m_gba_bios_edit->setText(file); - SaveSettings(); - } + m_gba_bios_edit->SetTextAndUpdate(file); } void GameCubePane::BrowseGBARom(size_t index) { QString file = QString::fromStdString(GetOpenGBARom({})); if (!file.isEmpty()) - { - m_gba_rom_edits[index]->setText(file); - SaveSettings(); - } + m_gba_rom_edits[index]->SetTextAndUpdate(file); } void GameCubePane::SaveRomPathChanged() { m_gba_saves_edit->setEnabled(!m_gba_save_rom_path->isChecked()); m_gba_browse_saves->setEnabled(!m_gba_save_rom_path->isChecked()); - SaveSettings(); } void GameCubePane::BrowseGBASaves() { QString dir = QDir::toNativeSeparators(DolphinFileDialog::getExistingDirectory( this, tr("Select GBA Saves Path"), - QString::fromStdString(File::GetUserPath(D_GBASAVES_IDX)))); + QString::fromStdString(Config::Get(Config::MAIN_GBA_SAVES_PATH)))); if (!dir.isEmpty()) { m_gba_saves_edit->setText(dir); @@ -722,11 +698,6 @@ void GameCubePane::BrowseGBASaves() void GameCubePane::LoadSettings() { - // IPL Settings - SignalBlocking(m_skip_main_menu)->setChecked(Config::Get(Config::MAIN_SKIP_IPL)); - SignalBlocking(m_language_combo) - ->setCurrentIndex(m_language_combo->findData(Config::Get(Config::MAIN_GC_LANGUAGE))); - bool have_menu = false; for (const std::string dir : {USA_DIR, JAP_DIR, EUR_DIR}) @@ -741,7 +712,7 @@ void GameCubePane::LoadSettings() } m_skip_main_menu->setEnabled(have_menu || !m_skip_main_menu->isChecked()); - m_skip_main_menu->setToolTip(have_menu ? QString{} : tr("Put IPL ROMs in User/GC/.")); + m_skip_main_menu->SetDescription(have_menu ? QString{} : tr("Put IPL ROMs in User/GC/.")); // Device Settings for (ExpansionInterface::Slot slot : GUI_SLOTS) @@ -762,31 +733,12 @@ void GameCubePane::LoadSettings() SignalBlocking(m_gci_paths[slot]) ->setText(QString::fromStdString(Config::GetGCIFolderPath(slot, std::nullopt))); } - -#ifdef HAS_LIBMGBA - // GBA Settings - SignalBlocking(m_gba_threads)->setChecked(Config::Get(Config::MAIN_GBA_THREADS)); - SignalBlocking(m_gba_bios_edit) - ->setText(QString::fromStdString(File::GetUserPath(F_GBABIOS_IDX))); - SignalBlocking(m_gba_save_rom_path)->setChecked(Config::Get(Config::MAIN_GBA_SAVES_IN_ROM_PATH)); - SignalBlocking(m_gba_saves_edit) - ->setText(QString::fromStdString(File::GetUserPath(D_GBASAVES_IDX))); - for (size_t i = 0; i < m_gba_rom_edits.size(); ++i) - { - SignalBlocking(m_gba_rom_edits[i]) - ->setText(QString::fromStdString(Config::Get(Config::MAIN_GBA_ROM_PATHS[i]))); - } -#endif } void GameCubePane::SaveSettings() { Config::ConfigChangeCallbackGuard config_guard; - // IPL Settings - Config::SetBaseOrCurrent(Config::MAIN_SKIP_IPL, m_skip_main_menu->isChecked()); - Config::SetBaseOrCurrent(Config::MAIN_GC_LANGUAGE, m_language_combo->currentData().toInt()); - auto& system = Core::System::GetInstance(); // Device Settings for (ExpansionInterface::Slot slot : GUI_SLOTS) @@ -808,18 +760,6 @@ void GameCubePane::SaveSettings() // GBA Settings if (!NetPlay::IsNetPlayRunning()) { - Config::SetBaseOrCurrent(Config::MAIN_GBA_THREADS, m_gba_threads->isChecked()); - Config::SetBaseOrCurrent(Config::MAIN_GBA_BIOS_PATH, m_gba_bios_edit->text().toStdString()); - Config::SetBaseOrCurrent(Config::MAIN_GBA_SAVES_IN_ROM_PATH, m_gba_save_rom_path->isChecked()); - Config::SetBaseOrCurrent(Config::MAIN_GBA_SAVES_PATH, m_gba_saves_edit->text().toStdString()); - File::SetUserPath(F_GBABIOS_IDX, Config::Get(Config::MAIN_GBA_BIOS_PATH)); - File::SetUserPath(D_GBASAVES_IDX, Config::Get(Config::MAIN_GBA_SAVES_PATH)); - for (size_t i = 0; i < m_gba_rom_edits.size(); ++i) - { - Config::SetBaseOrCurrent(Config::MAIN_GBA_ROM_PATHS[i], - m_gba_rom_edits[i]->text().toStdString()); - } - auto server = Settings::Instance().GetNetPlayServer(); if (server) server->SetGBAConfig(server->GetGBAConfig(), true); diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.h b/Source/Core/DolphinQt/Settings/GameCubePane.h index 05186f81aaf..010da7325d9 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.h +++ b/Source/Core/DolphinQt/Settings/GameCubePane.h @@ -12,7 +12,10 @@ #include "Common/EnumMap.h" #include "Core/HW/EXI/EXI.h" -class QCheckBox; +class ConfigBool; +class ConfigChoice; +class ConfigText; +class ConfigUserPath; class QComboBox; class QHBoxLayout; class QLabel; @@ -52,8 +55,8 @@ private: void SaveRomPathChanged(); void BrowseGBASaves(); - QCheckBox* m_skip_main_menu; - QComboBox* m_language_combo; + ConfigBool* m_skip_main_menu; + ConfigChoice* m_language_combo; Common::EnumMap m_slot_buttons; Common::EnumMap m_slot_combos; @@ -71,12 +74,12 @@ private: Common::EnumMap m_gci_override_labels; Common::EnumMap m_gci_paths; - QCheckBox* m_gba_threads; - QCheckBox* m_gba_save_rom_path; + ConfigBool* m_gba_threads; + ConfigBool* m_gba_save_rom_path; QPushButton* m_gba_browse_bios; - QLineEdit* m_gba_bios_edit; + ConfigUserPath* m_gba_bios_edit; std::array m_gba_browse_roms; - std::array m_gba_rom_edits; + std::array m_gba_rom_edits; QPushButton* m_gba_browse_saves; - QLineEdit* m_gba_saves_edit; + ConfigUserPath* m_gba_saves_edit; }; diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 40f31a231da..19de3dc612b 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -114,8 +114,6 @@ static void InitCustomPaths() Config::Get(Config::MAIN_WII_SD_CARD_SYNC_FOLDER_PATH)); File::CreateFullPath(File::GetUserPath(D_WIISDCARDSYNCFOLDER_IDX)); #ifdef HAS_LIBMGBA - File::SetUserPath(F_GBABIOS_IDX, Config::Get(Config::MAIN_GBA_BIOS_PATH)); - File::SetUserPath(D_GBASAVES_IDX, Config::Get(Config::MAIN_GBA_SAVES_PATH)); File::CreateFullPath(File::GetUserPath(D_GBASAVES_IDX)); #endif } From 02d84ddc7808afa64fe467af913bbf5f89681070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Wed, 13 Aug 2025 00:39:46 +0200 Subject: [PATCH 4/6] WiiPane: Use ConfigControls where applicable --- .../Config/ConfigControls/ConfigChoice.cpp | 20 ++ .../Config/ConfigControls/ConfigChoice.h | 53 ++++ Source/Core/DolphinQt/Settings.cpp | 6 - Source/Core/DolphinQt/Settings.h | 2 - Source/Core/DolphinQt/Settings/WiiPane.cpp | 232 +++++------------- Source/Core/DolphinQt/Settings/WiiPane.h | 50 ++-- Source/Core/UICommon/UICommon.cpp | 3 - 7 files changed, 154 insertions(+), 212 deletions(-) diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp index 3c77b2bc3a2..bdc95185870 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.cpp @@ -25,6 +25,26 @@ void ConfigChoice::OnConfigChanged() setCurrentIndex(ReadValue(m_setting)); } +ConfigChoiceU32::ConfigChoiceU32(const QStringList& options, const Config::Info& setting, + Config::Layer* layer) + : ConfigControl(setting.GetLocation(), layer), m_setting(setting) +{ + addItems(options); + setCurrentIndex(ReadValue(setting)); + + connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoiceU32::Update); +} + +void ConfigChoiceU32::Update(int choice) +{ + SaveValue(m_setting, (u32)choice); +} + +void ConfigChoiceU32::OnConfigChanged() +{ + setCurrentIndex(ReadValue(m_setting)); +} + ConfigStringChoice::ConfigStringChoice(const std::vector& options, const Config::Info& setting, Config::Layer* layer) diff --git a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h index 4ef02ab5695..40f7bdccbef 100644 --- a/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h +++ b/Source/Core/DolphinQt/Config/ConfigControls/ConfigChoice.h @@ -28,6 +28,59 @@ private: Config::Info m_setting; }; +class ConfigChoiceU32 final : public ConfigControl +{ + Q_OBJECT +public: + ConfigChoiceU32(const QStringList& options, const Config::Info& setting, + Config::Layer* layer = nullptr); + +protected: + void OnConfigChanged() override; + +private: + void Update(int choice); + + Config::Info m_setting; +}; + +template +class ConfigChoiceMap final : public ConfigControl +{ +public: + ConfigChoiceMap(const std::vector>& options, const Config::Info& setting, + Config::Layer* layer = nullptr) + : ConfigControl(setting.GetLocation(), layer), m_setting(setting), + m_options(options) + { + for (const auto& [option_text, option_data] : options) + addItem(option_text); + + OnConfigChanged(); + connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoiceMap::Update); + } + +protected: + void OnConfigChanged() override + { + const T value = ReadValue(m_setting); + const auto it = std::find_if(m_options.begin(), m_options.end(), + [&value](const auto& pair) { return pair.second == value; }); + + int index = + (it != m_options.end()) ? static_cast(std::distance(m_options.begin(), it)) : -1; + + const QSignalBlocker blocker(this); + setCurrentIndex(index); + } + +private: + void Update(int choice) { SaveValue(m_setting, m_options[choice].second); } + + const Config::Info m_setting; + const std::vector> m_options; +}; + class ConfigStringChoice final : public ConfigControl { Q_OBJECT diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index cb76f0f5bfa..acc65525126 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -773,10 +773,7 @@ bool Settings::IsSDCardInserted() const void Settings::SetSDCardInserted(bool inserted) { if (IsSDCardInserted() != inserted) - { Config::SetBaseOrCurrent(Config::MAIN_WII_SD_CARD, inserted); - emit SDCardInsertionChanged(inserted); - } } bool Settings::IsUSBKeyboardConnected() const @@ -787,10 +784,7 @@ bool Settings::IsUSBKeyboardConnected() const void Settings::SetUSBKeyboardConnected(bool connected) { if (IsUSBKeyboardConnected() != connected) - { Config::SetBaseOrCurrent(Config::MAIN_WII_KEYBOARD, connected); - emit USBKeyboardConnectionChanged(connected); - } } bool Settings::IsWiiSpeakMuted() const diff --git a/Source/Core/DolphinQt/Settings.h b/Source/Core/DolphinQt/Settings.h index a109c37ae60..cb78e9e5c00 100644 --- a/Source/Core/DolphinQt/Settings.h +++ b/Source/Core/DolphinQt/Settings.h @@ -223,8 +223,6 @@ signals: void AnalyticsToggled(bool enabled); void ReleaseDevices(); void DevicesChanged(); - void SDCardInsertionChanged(bool inserted); - void USBKeyboardConnectionChanged(bool connected); void WiiSpeakMuteChanged(bool muted); void EnableGfxModsChanged(bool enabled); diff --git a/Source/Core/DolphinQt/Settings/WiiPane.cpp b/Source/Core/DolphinQt/Settings/WiiPane.cpp index cf532d41cd9..19d54ca50c1 100644 --- a/Source/Core/DolphinQt/Settings/WiiPane.cpp +++ b/Source/Core/DolphinQt/Settings/WiiPane.cpp @@ -8,19 +8,14 @@ #include #include -#include -#include #include #include #include #include #include -#include #include #include -#include #include -#include #include "Common/Config/Config.h" #include "Common/FatFsUtil.h" @@ -33,29 +28,18 @@ #include "Core/System.h" #include "Core/USBUtils.h" +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigChoice.h" +#include "DolphinQt/Config/ConfigControls/ConfigSlider.h" +#include "DolphinQt/Config/ConfigControls/ConfigUserPath.h" #include "DolphinQt/QtUtils/DolphinFileDialog.h" #include "DolphinQt/QtUtils/ModalMessageBox.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/QtUtils/ParallelProgressDialog.h" #include "DolphinQt/QtUtils/QtUtils.h" -#include "DolphinQt/QtUtils/SignalBlocking.h" #include "DolphinQt/Settings.h" #include "DolphinQt/Settings/USBDevicePicker.h" -// SYSCONF uses 0 for bottom and 1 for top, but we place them in -// the other order in the GUI so that Top will be above Bottom, -// matching the respective physical placements of the sensor bar. -// This also matches the layout of the settings in the Wii Menu. -static int TranslateSensorBarPosition(int position) -{ - if (position == 0) - return 1; - if (position == 1) - return 0; - - return position; -} - namespace { struct SDSizeComboEntry @@ -89,7 +73,7 @@ constexpr std::array sd_size_combo_entries{ WiiPane::WiiPane(QWidget* parent) : QWidget(parent) { CreateLayout(); - LoadConfig(); + PopulateUSBPassthroughListWidget(); ConnectLayout(); ValidateSelectionState(); OnEmulationStateChanged(!Core::IsUninitialized(Core::System::GetInstance())); @@ -106,39 +90,15 @@ void WiiPane::CreateLayout() void WiiPane::ConnectLayout() { - // Misc Settings - connect(m_aspect_ratio_choice, &QComboBox::currentIndexChanged, this, &WiiPane::OnSaveConfig); - connect(m_system_language_choice, &QComboBox::currentIndexChanged, this, &WiiPane::OnSaveConfig); - connect(m_sound_mode_choice, &QComboBox::currentIndexChanged, this, &WiiPane::OnSaveConfig); - connect(m_screensaver_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(m_pal60_mode_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(m_connect_keyboard_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(&Settings::Instance(), &Settings::SDCardInsertionChanged, m_sd_card_checkbox, - &QCheckBox::setChecked); - connect(&Settings::Instance(), &Settings::USBKeyboardConnectionChanged, - m_connect_keyboard_checkbox, &QCheckBox::setChecked); - connect(m_wiilink_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - - // SD Card Settings - connect(m_sd_card_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(m_allow_sd_writes_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(m_sync_sd_folder_checkbox, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - connect(m_sd_card_size_combo, &QComboBox::currentIndexChanged, this, &WiiPane::OnSaveConfig); - // Whitelisted USB Passthrough Devices + connect(&Settings::Instance(), &Settings::ConfigChanged, this, + &WiiPane::PopulateUSBPassthroughListWidget); connect(m_whitelist_usb_list, &QListWidget::itemClicked, this, &WiiPane::ValidateSelectionState); connect(m_whitelist_usb_add_button, &QPushButton::clicked, this, &WiiPane::OnUSBWhitelistAddButton); connect(m_whitelist_usb_remove_button, &QPushButton::clicked, this, &WiiPane::OnUSBWhitelistRemoveButton); - // Wii Remote Settings - connect(m_wiimote_ir_sensor_position, &QComboBox::currentIndexChanged, this, - &WiiPane::OnSaveConfig); - connect(m_wiimote_ir_sensitivity, &QSlider::valueChanged, this, &WiiPane::OnSaveConfig); - connect(m_wiimote_speaker_volume, &QSlider::valueChanged, this, &WiiPane::OnSaveConfig); - connect(m_wiimote_motor, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig); - // Emulation State connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); @@ -151,45 +111,44 @@ void WiiPane::CreateMisc() auto* misc_settings_group_layout = new QGridLayout(); misc_settings_group->setLayout(misc_settings_group_layout); m_main_layout->addWidget(misc_settings_group); - m_pal60_mode_checkbox = new QCheckBox(tr("Use PAL60 Mode (EuRGB60)")); - m_screensaver_checkbox = new QCheckBox(tr("Enable Screen Saver")); - m_wiilink_checkbox = new QCheckBox(tr("Enable WiiConnect24 via WiiLink")); - m_connect_keyboard_checkbox = new QCheckBox(tr("Connect USB Keyboard")); + m_pal60_mode_checkbox = new ConfigBool(tr("Use PAL60 Mode (EuRGB60)"), Config::SYSCONF_PAL60); + m_screensaver_checkbox = new ConfigBool(tr("Enable Screen Saver"), Config::SYSCONF_SCREENSAVER); + m_wiilink_checkbox = + new ConfigBool(tr("Enable WiiConnect24 via WiiLink"), Config::MAIN_WII_WIILINK_ENABLE); + m_connect_keyboard_checkbox = + new ConfigBool(tr("Connect USB Keyboard"), Config::MAIN_WII_KEYBOARD); m_aspect_ratio_choice_label = new QLabel(tr("Aspect Ratio:")); - m_aspect_ratio_choice = new QComboBox(); - m_aspect_ratio_choice->addItem(tr("4:3")); - m_aspect_ratio_choice->addItem(tr("16:9")); + m_aspect_ratio_choice = new ConfigChoiceMap({{tr("4:3"), false}, {tr("16:9"), true}}, + Config::SYSCONF_WIDESCREEN); m_system_language_choice_label = new QLabel(tr("System Language:")); - m_system_language_choice = new QComboBox(); - m_system_language_choice->addItem(tr("Japanese")); - m_system_language_choice->addItem(tr("English")); - m_system_language_choice->addItem(tr("German")); - m_system_language_choice->addItem(tr("French")); - m_system_language_choice->addItem(tr("Spanish")); - m_system_language_choice->addItem(tr("Italian")); - m_system_language_choice->addItem(tr("Dutch")); - m_system_language_choice->addItem(tr("Simplified Chinese")); - m_system_language_choice->addItem(tr("Traditional Chinese")); - m_system_language_choice->addItem(tr("Korean")); + m_system_language_choice = new ConfigChoiceU32( + {tr("Japanese"), tr("English"), tr("German"), tr("French"), tr("Spanish"), tr("Italian"), + tr("Dutch"), tr("Simplified Chinese"), tr("Traditional Chinese"), tr("Korean")}, + Config::SYSCONF_LANGUAGE); m_sound_mode_choice_label = new QLabel(tr("Sound:")); - m_sound_mode_choice = new QComboBox(); - m_sound_mode_choice->addItem(tr("Mono")); - m_sound_mode_choice->addItem(tr("Stereo")); - // i18n: Surround audio (Dolby Pro Logic II) - m_sound_mode_choice->addItem(tr("Surround")); + m_sound_mode_choice = new ConfigChoiceU32( + {// i18n: Mono audio + tr("Mono"), + // i18n: Stereo audio + tr("Stereo"), + // i18n: Surround audio (Dolby Pro Logic II) + tr("Surround")}, + Config::SYSCONF_SOUND_MODE); - m_pal60_mode_checkbox->setToolTip(tr("Sets the Wii display mode to 60Hz (480i) instead of 50Hz " - "(576i) for PAL games.\nMay not work for all games.")); - m_screensaver_checkbox->setToolTip(tr("Dims the screen after five minutes of inactivity.")); - m_wiilink_checkbox->setToolTip(tr( + m_pal60_mode_checkbox->SetDescription( + tr("Sets the Wii display mode to 60Hz (480i) instead of 50Hz " + "(576i) for PAL games.\nMay not work for all games.")); + m_screensaver_checkbox->SetDescription(tr("Dims the screen after five minutes of inactivity.")); + m_wiilink_checkbox->SetDescription(tr( "Enables the WiiLink service for WiiConnect24 channels.\nWiiLink is an alternate provider " "for the discontinued WiiConnect24 Channels such as the Forecast and Nintendo Channels\nRead " "the Terms of Service at: https://www.wiilink24.com/tos")); - m_system_language_choice->setToolTip(tr("Sets the Wii system language.")); - m_connect_keyboard_checkbox->setToolTip(tr("May cause slow down in Wii Menu and some games.")); + m_system_language_choice->SetDescription(tr("Sets the Wii system language.")); + m_connect_keyboard_checkbox->SetDescription( + tr("May cause slow down in Wii Menu and some games.")); misc_settings_group_layout->addWidget(m_pal60_mode_checkbox, 0, 0, 1, 1); misc_settings_group_layout->addWidget(m_connect_keyboard_checkbox, 0, 1, 1, 1); @@ -211,18 +170,17 @@ void WiiPane::CreateSDCard() m_main_layout->addWidget(sd_settings_group); int row = 0; - m_sd_card_checkbox = new QCheckBox(tr("Insert SD Card")); - m_sd_card_checkbox->setToolTip(tr("Supports SD and SDHC. Default size is 128 MB.")); - m_allow_sd_writes_checkbox = new QCheckBox(tr("Allow Writes to SD Card")); + m_sd_card_checkbox = new ConfigBool(tr("Insert SD Card"), Config::MAIN_WII_SD_CARD); + m_sd_card_checkbox->SetDescription(tr("Supports SD and SDHC. Default size is 128 MB.")); + m_allow_sd_writes_checkbox = + new ConfigBool(tr("Allow Writes to SD Card"), Config::MAIN_ALLOW_SD_WRITES); sd_settings_group_layout->addWidget(m_sd_card_checkbox, row, 0, 1, 1); sd_settings_group_layout->addWidget(m_allow_sd_writes_checkbox, row, 1, 1, 1); ++row; { QHBoxLayout* hlayout = new QHBoxLayout; - m_sd_raw_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(F_WIISDCARDIMAGE_IDX))); - connect(m_sd_raw_edit, &QLineEdit::editingFinished, - [this] { SetSDRaw(m_sd_raw_edit->text()); }); + m_sd_raw_edit = new ConfigUserPath(F_WIISDCARDIMAGE_IDX, Config::MAIN_WII_SD_CARD_IMAGE_PATH); QPushButton* sdcard_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(sdcard_open, &QPushButton::clicked, this, &WiiPane::BrowseSDRaw); hlayout->addWidget(new QLabel(tr("SD Card Path:"))); @@ -233,8 +191,9 @@ void WiiPane::CreateSDCard() ++row; } - m_sync_sd_folder_checkbox = new QCheckBox(tr("Automatically Sync with Folder")); - m_sync_sd_folder_checkbox->setToolTip( + m_sync_sd_folder_checkbox = new ConfigBool(tr("Automatically Sync with Folder"), + Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC); + m_sync_sd_folder_checkbox->SetDescription( tr("Synchronizes the SD Card with the SD Sync Folder when starting and ending emulation.")); sd_settings_group_layout->addWidget(m_sync_sd_folder_checkbox, row, 0, 1, 2); ++row; @@ -242,9 +201,7 @@ void WiiPane::CreateSDCard() { QHBoxLayout* hlayout = new QHBoxLayout; m_sd_sync_folder_edit = - new QLineEdit(QString::fromStdString(File::GetUserPath(D_WIISDCARDSYNCFOLDER_IDX))); - connect(m_sd_sync_folder_edit, &QLineEdit::editingFinished, - [this] { SetSDSyncFolder(m_sd_sync_folder_edit->text()); }); + new ConfigUserPath(D_WIISDCARDSYNCFOLDER_IDX, Config::MAIN_WII_SD_CARD_SYNC_FOLDER_PATH); QPushButton* sdcard_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(sdcard_open, &QPushButton::clicked, this, &WiiPane::BrowseSDSyncFolder); hlayout->addWidget(new QLabel(tr("SD Sync Folder:"))); @@ -255,9 +212,11 @@ void WiiPane::CreateSDCard() ++row; } - m_sd_card_size_combo = new QComboBox(); - for (size_t i = 0; i < sd_size_combo_entries.size(); ++i) - m_sd_card_size_combo->addItem(tr(sd_size_combo_entries[i].name)); + std::vector> sd_size_choices; + for (const auto& entry : sd_size_combo_entries) + sd_size_choices.emplace_back(tr(entry.name), entry.size); + + m_sd_card_size_combo = new ConfigChoiceMap(sd_size_choices, Config::MAIN_WII_SD_CARD_FILESIZE); sd_settings_group_layout->addWidget(new QLabel(tr("SD Card File Size:")), row, 0); sd_settings_group_layout->addWidget(m_sd_card_size_combo, row, 1); ++row; @@ -346,26 +305,21 @@ void WiiPane::CreateWiiRemoteSettings() auto* wii_remote_settings_group_layout = new QGridLayout(); wii_remote_settings_group->setLayout(wii_remote_settings_group_layout); m_main_layout->addWidget(wii_remote_settings_group); - m_wiimote_motor = new QCheckBox(tr("Enable Rumble")); + m_wiimote_motor = new ConfigBool(tr("Enable Rumble"), Config::SYSCONF_WIIMOTE_MOTOR); m_wiimote_sensor_position_label = new QLabel(tr("Sensor Bar Position:")); - m_wiimote_ir_sensor_position = new QComboBox(); - m_wiimote_ir_sensor_position->addItem(tr("Top")); - m_wiimote_ir_sensor_position->addItem(tr("Bottom")); + m_wiimote_ir_sensor_position = new ConfigChoiceMap({{tr("Top"), 1}, {tr("Bottom"), 0}}, + Config::SYSCONF_SENSOR_BAR_POSITION); // IR Sensitivity Slider // i18n: IR stands for infrared and refers to the pointer functionality of Wii Remotes m_wiimote_ir_sensitivity_label = new QLabel(tr("IR Sensitivity:")); - m_wiimote_ir_sensitivity = new QSlider(Qt::Horizontal); // Wii menu saves values from 1 to 5. - m_wiimote_ir_sensitivity->setMinimum(1); - m_wiimote_ir_sensitivity->setMaximum(5); + m_wiimote_ir_sensitivity = new ConfigSliderU32(1, 5, Config::SYSCONF_SENSOR_BAR_SENSITIVITY, 1); // Speaker Volume Slider m_wiimote_speaker_volume_label = new QLabel(tr("Speaker Volume:")); - m_wiimote_speaker_volume = new QSlider(Qt::Horizontal); - m_wiimote_speaker_volume->setMinimum(0); - m_wiimote_speaker_volume->setMaximum(127); + m_wiimote_speaker_volume = new ConfigSliderU32(0, 127, Config::SYSCONF_SPEAKER_VOLUME, 1); wii_remote_settings_group_layout->addWidget(m_wiimote_sensor_position_label, 0, 0); wii_remote_settings_group_layout->addWidget(m_wiimote_ir_sensor_position, 0, 1); @@ -392,68 +346,6 @@ void WiiPane::OnEmulationStateChanged(bool running) m_wiilink_checkbox->setEnabled(!running); } -void WiiPane::LoadConfig() -{ - m_screensaver_checkbox->setChecked(Config::Get(Config::SYSCONF_SCREENSAVER)); - m_pal60_mode_checkbox->setChecked(Config::Get(Config::SYSCONF_PAL60)); - m_connect_keyboard_checkbox->setChecked(Settings::Instance().IsUSBKeyboardConnected()); - m_aspect_ratio_choice->setCurrentIndex(Config::Get(Config::SYSCONF_WIDESCREEN)); - m_system_language_choice->setCurrentIndex(Config::Get(Config::SYSCONF_LANGUAGE)); - m_sound_mode_choice->setCurrentIndex(Config::Get(Config::SYSCONF_SOUND_MODE)); - m_wiilink_checkbox->setChecked(Config::Get(Config::MAIN_WII_WIILINK_ENABLE)); - - m_sd_card_checkbox->setChecked(Settings::Instance().IsSDCardInserted()); - m_allow_sd_writes_checkbox->setChecked(Config::Get(Config::MAIN_ALLOW_SD_WRITES)); - m_sync_sd_folder_checkbox->setChecked(Config::Get(Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC)); - - const u64 sd_card_size = Config::Get(Config::MAIN_WII_SD_CARD_FILESIZE); - for (size_t i = 0; i < sd_size_combo_entries.size(); ++i) - { - if (sd_size_combo_entries[i].size == sd_card_size) - m_sd_card_size_combo->setCurrentIndex(static_cast(i)); - } - - PopulateUSBPassthroughListWidget(); - - m_wiimote_ir_sensor_position->setCurrentIndex( - TranslateSensorBarPosition(Config::Get(Config::SYSCONF_SENSOR_BAR_POSITION))); - m_wiimote_ir_sensitivity->setValue(Config::Get(Config::SYSCONF_SENSOR_BAR_SENSITIVITY)); - m_wiimote_speaker_volume->setValue(Config::Get(Config::SYSCONF_SPEAKER_VOLUME)); - m_wiimote_motor->setChecked(Config::Get(Config::SYSCONF_WIIMOTE_MOTOR)); -} - -void WiiPane::OnSaveConfig() -{ - Config::ConfigChangeCallbackGuard config_guard; - - Config::SetBase(Config::SYSCONF_SCREENSAVER, m_screensaver_checkbox->isChecked()); - Config::SetBase(Config::SYSCONF_PAL60, m_pal60_mode_checkbox->isChecked()); - Settings::Instance().SetUSBKeyboardConnected(m_connect_keyboard_checkbox->isChecked()); - - Config::SetBase(Config::SYSCONF_SENSOR_BAR_POSITION, - TranslateSensorBarPosition(m_wiimote_ir_sensor_position->currentIndex())); - Config::SetBase(Config::SYSCONF_SENSOR_BAR_SENSITIVITY, m_wiimote_ir_sensitivity->value()); - Config::SetBase(Config::SYSCONF_SPEAKER_VOLUME, m_wiimote_speaker_volume->value()); - Config::SetBase(Config::SYSCONF_LANGUAGE, m_system_language_choice->currentIndex()); - Config::SetBase(Config::SYSCONF_WIDESCREEN, m_aspect_ratio_choice->currentIndex()); - Config::SetBase(Config::SYSCONF_SOUND_MODE, m_sound_mode_choice->currentIndex()); - Config::SetBase(Config::SYSCONF_WIIMOTE_MOTOR, m_wiimote_motor->isChecked()); - Config::SetBase(Config::MAIN_WII_WIILINK_ENABLE, m_wiilink_checkbox->isChecked()); - - Settings::Instance().SetSDCardInserted(m_sd_card_checkbox->isChecked()); - Config::SetBase(Config::MAIN_ALLOW_SD_WRITES, m_allow_sd_writes_checkbox->isChecked()); - Config::SetBase(Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC, - m_sync_sd_folder_checkbox->isChecked()); - - const int sd_card_size_index = m_sd_card_size_combo->currentIndex(); - if (sd_card_size_index >= 0 && - static_cast(sd_card_size_index) < sd_size_combo_entries.size()) - { - Config::SetBase(Config::MAIN_WII_SD_CARD_FILESIZE, - sd_size_combo_entries[sd_card_size_index].size); - } -} - void WiiPane::ValidateSelectionState() { m_whitelist_usb_remove_button->setEnabled(m_whitelist_usb_list->currentIndex().isValid()); @@ -518,13 +410,7 @@ void WiiPane::BrowseSDRaw() tr("SD Card Image (*.raw);;" "All Files (*)"))); if (!file.isEmpty()) - SetSDRaw(file); -} - -void WiiPane::SetSDRaw(const QString& path) -{ - Config::SetBase(Config::MAIN_WII_SD_CARD_IMAGE_PATH, path.toStdString()); - SignalBlocking(m_sd_raw_edit)->setText(path); + m_sd_raw_edit->SetTextAndUpdate(file); } void WiiPane::BrowseSDSyncFolder() @@ -533,11 +419,5 @@ void WiiPane::BrowseSDSyncFolder() this, tr("Select a Folder to Sync with the SD Card Image"), QString::fromStdString(File::GetUserPath(D_WIISDCARDSYNCFOLDER_IDX)))); if (!file.isEmpty()) - SetSDSyncFolder(file); -} - -void WiiPane::SetSDSyncFolder(const QString& path) -{ - Config::SetBase(Config::MAIN_WII_SD_CARD_SYNC_FOLDER_PATH, path.toStdString()); - SignalBlocking(m_sd_sync_folder_edit)->setText(path); + m_sd_sync_folder_edit->SetTextAndUpdate(file); } diff --git a/Source/Core/DolphinQt/Settings/WiiPane.h b/Source/Core/DolphinQt/Settings/WiiPane.h index 206ec1f731a..ce53f81a0aa 100644 --- a/Source/Core/DolphinQt/Settings/WiiPane.h +++ b/Source/Core/DolphinQt/Settings/WiiPane.h @@ -5,13 +5,17 @@ #include -class QCheckBox; -class QComboBox; +#include "Common/CommonTypes.h" + +class ConfigBool; +template +class ConfigChoiceMap; +class ConfigChoiceU32; +class ConfigSliderU32; +class ConfigUserPath; class QLabel; -class QLineEdit; class QListWidget; class QPushButton; -class QSlider; class QString; class QVBoxLayout; @@ -30,8 +34,6 @@ private: void CreateWhitelistedUSBPassthroughDevices(); void CreateWiiRemoteSettings(); - void LoadConfig(); - void OnSaveConfig(); void OnEmulationStateChanged(bool running); void ValidateSelectionState(); @@ -40,32 +42,30 @@ private: void OnUSBWhitelistRemoveButton(); void BrowseSDRaw(); - void SetSDRaw(const QString& path); void BrowseSDSyncFolder(); - void SetSDSyncFolder(const QString& path); // Widgets QVBoxLayout* m_main_layout; // Misc Settings - QCheckBox* m_screensaver_checkbox; - QCheckBox* m_pal60_mode_checkbox; - QCheckBox* m_connect_keyboard_checkbox; - QCheckBox* m_wiilink_checkbox; - QComboBox* m_system_language_choice; + ConfigBool* m_screensaver_checkbox; + ConfigBool* m_pal60_mode_checkbox; + ConfigBool* m_connect_keyboard_checkbox; + ConfigBool* m_wiilink_checkbox; + ConfigChoiceU32* m_system_language_choice; QLabel* m_system_language_choice_label; - QComboBox* m_aspect_ratio_choice; + ConfigChoiceMap* m_aspect_ratio_choice; QLabel* m_aspect_ratio_choice_label; - QComboBox* m_sound_mode_choice; + ConfigChoiceU32* m_sound_mode_choice; QLabel* m_sound_mode_choice_label; // SD Card Settings - QCheckBox* m_sd_card_checkbox; - QCheckBox* m_allow_sd_writes_checkbox; - QCheckBox* m_sync_sd_folder_checkbox; - QComboBox* m_sd_card_size_combo; - QLineEdit* m_sd_raw_edit; - QLineEdit* m_sd_sync_folder_edit; + ConfigBool* m_sd_card_checkbox; + ConfigBool* m_allow_sd_writes_checkbox; + ConfigBool* m_sync_sd_folder_checkbox; + ConfigChoiceMap* m_sd_card_size_combo; + ConfigUserPath* m_sd_raw_edit; + ConfigUserPath* m_sd_sync_folder_edit; QPushButton* m_sd_pack_button; QPushButton* m_sd_unpack_button; @@ -76,10 +76,10 @@ private: // Wii Remote Settings QLabel* m_wiimote_sensor_position_label; - QComboBox* m_wiimote_ir_sensor_position; - QSlider* m_wiimote_ir_sensitivity; + ConfigChoiceMap* m_wiimote_ir_sensor_position; + ConfigSliderU32* m_wiimote_ir_sensitivity; QLabel* m_wiimote_ir_sensitivity_label; - QSlider* m_wiimote_speaker_volume; + ConfigSliderU32* m_wiimote_speaker_volume; QLabel* m_wiimote_speaker_volume_label; - QCheckBox* m_wiimote_motor; + ConfigBool* m_wiimote_motor; }; diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 19de3dc612b..59806556317 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -109,9 +109,6 @@ static void InitCustomPaths() CreateDumpPath(Config::Get(Config::MAIN_DUMP_PATH)); CreateResourcePackPath(Config::Get(Config::MAIN_RESOURCEPACK_PATH)); CreateWFSPath(Config::Get(Config::MAIN_WFS_PATH)); - File::SetUserPath(F_WIISDCARDIMAGE_IDX, Config::Get(Config::MAIN_WII_SD_CARD_IMAGE_PATH)); - File::SetUserPath(D_WIISDCARDSYNCFOLDER_IDX, - Config::Get(Config::MAIN_WII_SD_CARD_SYNC_FOLDER_PATH)); File::CreateFullPath(File::GetUserPath(D_WIISDCARDSYNCFOLDER_IDX)); #ifdef HAS_LIBMGBA File::CreateFullPath(File::GetUserPath(D_GBASAVES_IDX)); From 3cf4b02a9102c231144414a67f272dc28690e1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Wed, 13 Aug 2025 00:45:51 +0200 Subject: [PATCH 5/6] PathPane: Use ConfigControls where applicable --- Source/Core/DolphinQt/Settings/PathPane.cpp | 54 ++++++--------------- Source/Core/DolphinQt/Settings/PathPane.h | 16 +++--- Source/Core/UICommon/UICommon.cpp | 12 ----- 3 files changed, 22 insertions(+), 60 deletions(-) diff --git a/Source/Core/DolphinQt/Settings/PathPane.cpp b/Source/Core/DolphinQt/Settings/PathPane.cpp index ce0d47bc90a..24ea8555702 100644 --- a/Source/Core/DolphinQt/Settings/PathPane.cpp +++ b/Source/Core/DolphinQt/Settings/PathPane.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -18,6 +17,9 @@ #include "Core/Config/MainSettings.h" #include "Core/Config/UISettings.h" +#include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigText.h" +#include "DolphinQt/Config/ConfigControls/ConfigUserPath.h" #include "DolphinQt/QtUtils/DolphinFileDialog.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #include "DolphinQt/Settings.h" @@ -59,10 +61,7 @@ void PathPane::BrowseWiiNAND() QString dir = QDir::toNativeSeparators(DolphinFileDialog::getExistingDirectory( this, tr("Select Wii NAND Root"), QString::fromStdString(File::GetUserPath(D_WIIROOT_IDX)))); if (!dir.isEmpty()) - { - m_nand_edit->setText(dir); - OnNANDPathChanged(); - } + m_nand_edit->SetTextAndUpdate(dir); } void PathPane::BrowseDump() @@ -70,10 +69,7 @@ void PathPane::BrowseDump() QString dir = QDir::toNativeSeparators(DolphinFileDialog::getExistingDirectory( this, tr("Select Dump Path"), QString::fromStdString(File::GetUserPath(D_DUMP_IDX)))); if (!dir.isEmpty()) - { - m_dump_edit->setText(dir); - Config::SetBase(Config::MAIN_DUMP_PATH, dir.toStdString()); - } + m_dump_edit->SetTextAndUpdate(dir); } void PathPane::BrowseLoad() @@ -110,11 +106,6 @@ void PathPane::BrowseWFS() } } -void PathPane::OnNANDPathChanged() -{ - Config::SetBase(Config::MAIN_FS_PATH, m_nand_edit->text().toStdString()); -} - QGroupBox* PathPane::MakeGameFolderBox() { QGroupBox* game_box = new QGroupBox(tr("Game Folders")); @@ -143,8 +134,8 @@ QGroupBox* PathPane::MakeGameFolderBox() m_remove_path->setEnabled(false); - auto* recursive_checkbox = new QCheckBox(tr("Search Subfolders")); - recursive_checkbox->setChecked(Config::Get(Config::MAIN_RECURSIVE_ISO_PATHS)); + auto* recursive_checkbox = + new ConfigBool(tr("Search Subfolders"), Config::MAIN_RECURSIVE_ISO_PATHS); auto* auto_checkbox = new QCheckBox(tr("Check for Game List Changes in the Background")); auto_checkbox->setChecked(Settings::Instance().IsAutoRefreshEnabled()); @@ -155,10 +146,8 @@ QGroupBox* PathPane::MakeGameFolderBox() vlayout->addWidget(recursive_checkbox); vlayout->addWidget(auto_checkbox); - connect(recursive_checkbox, &QCheckBox::toggled, [](bool checked) { - Config::SetBase(Config::MAIN_RECURSIVE_ISO_PATHS, checked); - Settings::Instance().RefreshGameList(); - }); + connect(recursive_checkbox, &QCheckBox::toggled, + [](bool checked) { Settings::Instance().RefreshGameList(); }); connect(auto_checkbox, &QCheckBox::toggled, &Settings::Instance(), &Settings::SetAutoRefreshEnabled); @@ -175,9 +164,7 @@ QGridLayout* PathPane::MakePathsLayout() QGridLayout* layout = new QGridLayout; layout->setColumnStretch(1, 1); - m_game_edit = new QLineEdit(Settings::Instance().GetDefaultGame()); - connect(m_game_edit, &QLineEdit::editingFinished, - [this] { Settings::Instance().SetDefaultGame(m_game_edit->text()); }); + m_game_edit = new ConfigText(Config::MAIN_DEFAULT_ISO); connect(&Settings::Instance(), &Settings::DefaultGameChanged, this, [this](const QString& path) { m_game_edit->setText(path); }); QPushButton* game_open = new NonDefaultQPushButton(QStringLiteral("...")); @@ -186,46 +173,35 @@ QGridLayout* PathPane::MakePathsLayout() layout->addWidget(m_game_edit, 0, 1); layout->addWidget(game_open, 0, 2); - m_nand_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_WIIROOT_IDX))); - connect(m_nand_edit, &QLineEdit::editingFinished, this, &PathPane::OnNANDPathChanged); + m_nand_edit = new ConfigUserPath(D_WIIROOT_IDX, Config::MAIN_FS_PATH); QPushButton* nand_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(nand_open, &QPushButton::clicked, this, &PathPane::BrowseWiiNAND); layout->addWidget(new QLabel(tr("Wii NAND Root:")), 1, 0); layout->addWidget(m_nand_edit, 1, 1); layout->addWidget(nand_open, 1, 2); - m_dump_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_DUMP_IDX))); - connect(m_dump_edit, &QLineEdit::editingFinished, - [this] { Config::SetBase(Config::MAIN_DUMP_PATH, m_dump_edit->text().toStdString()); }); + m_dump_edit = new ConfigUserPath(D_DUMP_IDX, Config::MAIN_DUMP_PATH); QPushButton* dump_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(dump_open, &QPushButton::clicked, this, &PathPane::BrowseDump); layout->addWidget(new QLabel(tr("Dump Path:")), 2, 0); layout->addWidget(m_dump_edit, 2, 1); layout->addWidget(dump_open, 2, 2); - m_load_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_LOAD_IDX))); - connect(m_load_edit, &QLineEdit::editingFinished, - [this] { Config::SetBase(Config::MAIN_LOAD_PATH, m_load_edit->text().toStdString()); }); + m_load_edit = new ConfigUserPath(D_LOAD_IDX, Config::MAIN_LOAD_PATH); QPushButton* load_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(load_open, &QPushButton::clicked, this, &PathPane::BrowseLoad); layout->addWidget(new QLabel(tr("Load Path:")), 3, 0); layout->addWidget(m_load_edit, 3, 1); layout->addWidget(load_open, 3, 2); - m_resource_pack_edit = - new QLineEdit(QString::fromStdString(File::GetUserPath(D_RESOURCEPACK_IDX))); - connect(m_resource_pack_edit, &QLineEdit::editingFinished, [this] { - Config::SetBase(Config::MAIN_RESOURCEPACK_PATH, m_resource_pack_edit->text().toStdString()); - }); + m_resource_pack_edit = new ConfigUserPath(D_RESOURCEPACK_IDX, Config::MAIN_RESOURCEPACK_PATH); QPushButton* resource_pack_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(resource_pack_open, &QPushButton::clicked, this, &PathPane::BrowseResourcePack); layout->addWidget(new QLabel(tr("Resource Pack Path:")), 4, 0); layout->addWidget(m_resource_pack_edit, 4, 1); layout->addWidget(resource_pack_open, 4, 2); - m_wfs_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_WFSROOT_IDX))); - connect(m_load_edit, &QLineEdit::editingFinished, - [this] { Config::SetBase(Config::MAIN_WFS_PATH, m_wfs_edit->text().toStdString()); }); + m_wfs_edit = new ConfigUserPath(D_WFSROOT_IDX, Config::MAIN_WFS_PATH); QPushButton* wfs_open = new NonDefaultQPushButton(QStringLiteral("...")); connect(wfs_open, &QPushButton::clicked, this, &PathPane::BrowseWFS); layout->addWidget(new QLabel(tr("WFS Path:")), 5, 0); diff --git a/Source/Core/DolphinQt/Settings/PathPane.h b/Source/Core/DolphinQt/Settings/PathPane.h index e9253846227..bf07dd3ee62 100644 --- a/Source/Core/DolphinQt/Settings/PathPane.h +++ b/Source/Core/DolphinQt/Settings/PathPane.h @@ -5,9 +5,9 @@ #include +class ConfigText; class QGridLayout; class QGroupBox; -class QLineEdit; class QListWidget; class QPushButton; @@ -29,15 +29,13 @@ private: QGridLayout* MakePathsLayout(); void RemovePath(); - void OnNANDPathChanged(); - QListWidget* m_path_list; - QLineEdit* m_game_edit; - QLineEdit* m_nand_edit; - QLineEdit* m_dump_edit; - QLineEdit* m_load_edit; - QLineEdit* m_resource_pack_edit; - QLineEdit* m_wfs_edit; + ConfigText* m_game_edit; + ConfigText* m_nand_edit; + ConfigText* m_dump_edit; + ConfigText* m_load_edit; + ConfigText* m_resource_pack_edit; + ConfigText* m_wfs_edit; QPushButton* m_remove_path; }; diff --git a/Source/Core/UICommon/UICommon.cpp b/Source/Core/UICommon/UICommon.cpp index 59806556317..fcaa45d651d 100644 --- a/Source/Core/UICommon/UICommon.cpp +++ b/Source/Core/UICommon/UICommon.cpp @@ -67,8 +67,6 @@ static Config::ConfigChangedCallbackID s_config_changed_callback_id; static void CreateDumpPath(std::string path) { - if (!path.empty()) - File::SetUserPath(D_DUMP_IDX, std::move(path)); File::CreateFullPath(File::GetUserPath(D_DUMPAUDIO_IDX)); File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX)); File::CreateFullPath(File::GetUserPath(D_DUMPSSL_IDX)); @@ -82,20 +80,12 @@ static void CreateDumpPath(std::string path) static void CreateLoadPath(std::string path) { - if (!path.empty()) - File::SetUserPath(D_LOAD_IDX, std::move(path)); File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX)); File::CreateFullPath(File::GetUserPath(D_RIIVOLUTION_IDX)); File::CreateFullPath(File::GetUserPath(D_GRAPHICSMOD_IDX)); File::CreateFullPath(File::GetUserPath(D_DYNAMICINPUT_IDX)); } -static void CreateResourcePackPath(std::string path) -{ - if (!path.empty()) - File::SetUserPath(D_RESOURCEPACK_IDX, std::move(path)); -} - static void CreateWFSPath(const std::string& path) { if (!path.empty()) @@ -104,10 +94,8 @@ static void CreateWFSPath(const std::string& path) static void InitCustomPaths() { - File::SetUserPath(D_WIIROOT_IDX, Config::Get(Config::MAIN_FS_PATH)); CreateLoadPath(Config::Get(Config::MAIN_LOAD_PATH)); CreateDumpPath(Config::Get(Config::MAIN_DUMP_PATH)); - CreateResourcePackPath(Config::Get(Config::MAIN_RESOURCEPACK_PATH)); CreateWFSPath(Config::Get(Config::MAIN_WFS_PATH)); File::CreateFullPath(File::GetUserPath(D_WIISDCARDSYNCFOLDER_IDX)); #ifdef HAS_LIBMGBA From e1088659b1e9e4ba271ac66fb07e77c58891703e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joshua=20Vanda=C3=ABle?= Date: Wed, 13 Aug 2025 01:09:01 +0200 Subject: [PATCH 6/6] AdvancedPane: Use ConfigControls where applicable --- .../Core/DolphinQt/Settings/AdvancedPane.cpp | 25 +++++-------------- Source/Core/DolphinQt/Settings/AdvancedPane.h | 7 ++++-- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp index 4f5d4bfa7d5..399c46c486a 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.cpp +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.cpp @@ -4,7 +4,6 @@ #include "DolphinQt/Settings/AdvancedPane.h" #include -#include #include #include #include @@ -29,6 +28,7 @@ #include "Core/System.h" #include "DolphinQt/Config/ConfigControls/ConfigBool.h" +#include "DolphinQt/Config/ConfigControls/ConfigChoice.h" #include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h" #include "DolphinQt/Config/ConfigControls/ConfigSlider.h" #include "DolphinQt/QtUtils/AnalyticsPrompt.h" @@ -72,12 +72,12 @@ void AdvancedPane::CreateLayout() cpu_emulation_engine_layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); cpu_options_group_layout->addLayout(cpu_emulation_engine_layout); - m_cpu_emulation_engine_combobox = new QComboBox(this); - cpu_emulation_engine_layout->addRow(tr("CPU Emulation Engine:"), m_cpu_emulation_engine_combobox); + std::vector> emulation_engine_choices; for (PowerPC::CPUCore cpu_core : PowerPC::AvailableCPUCores()) - { - m_cpu_emulation_engine_combobox->addItem(tr(CPU_CORE_NAMES.at(cpu_core))); - } + emulation_engine_choices.emplace_back(tr(CPU_CORE_NAMES.at(cpu_core)), cpu_core); + m_cpu_emulation_engine_combobox = + new ConfigChoiceMap(emulation_engine_choices, Config::MAIN_CPU_CORE); + cpu_emulation_engine_layout->addRow(tr("CPU Emulation Engine:"), m_cpu_emulation_engine_combobox); m_enable_mmu_checkbox = new ConfigBool(tr("Enable MMU"), Config::MAIN_MMU); m_enable_mmu_checkbox->SetDescription( @@ -306,12 +306,6 @@ void AdvancedPane::CreateLayout() void AdvancedPane::ConnectLayout() { - connect(m_cpu_emulation_engine_combobox, &QComboBox::currentIndexChanged, [](int index) { - const auto cpu_cores = PowerPC::AvailableCPUCores(); - if (index >= 0 && static_cast(index) < cpu_cores.size()) - Config::SetBaseOrCurrent(Config::MAIN_CPU_CORE, cpu_cores[index]); - }); - m_ram_override_checkbox->setChecked(Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE)); connect(m_ram_override_checkbox, &QCheckBox::toggled, [this](bool enable_ram_override) { Config::SetBaseOrCurrent(Config::MAIN_RAM_OVERRIDE_ENABLE, enable_ram_override); @@ -334,13 +328,6 @@ void AdvancedPane::Update() const bool enable_custom_rtc_widgets = Config::Get(Config::MAIN_CUSTOM_RTC_ENABLE) && is_uninitialized; - const auto available_cpu_cores = PowerPC::AvailableCPUCores(); - const auto cpu_core = Config::Get(Config::MAIN_CPU_CORE); - for (size_t i = 0; i < available_cpu_cores.size(); ++i) - { - if (available_cpu_cores[i] == cpu_core) - m_cpu_emulation_engine_combobox->setCurrentIndex(int(i)); - } m_cpu_emulation_engine_combobox->setEnabled(is_uninitialized); m_enable_mmu_checkbox->setEnabled(is_uninitialized); m_pause_on_panic_checkbox->setEnabled(is_uninitialized); diff --git a/Source/Core/DolphinQt/Settings/AdvancedPane.h b/Source/Core/DolphinQt/Settings/AdvancedPane.h index f3a8c831983..7f7cf6b755b 100644 --- a/Source/Core/DolphinQt/Settings/AdvancedPane.h +++ b/Source/Core/DolphinQt/Settings/AdvancedPane.h @@ -6,12 +6,15 @@ #include #include +#include "Core/PowerPC/PowerPC.h" + class ConfigBool; +template +class ConfigChoiceMap; class ConfigFloatSlider; class ConfigSlider; class ConfigSliderU32; class QCheckBox; -class QComboBox; class QLabel; class QRadioButton; class QSlider; @@ -35,7 +38,7 @@ private: void OnResetButtonClicked(); - QComboBox* m_cpu_emulation_engine_combobox; + ConfigChoiceMap* m_cpu_emulation_engine_combobox; ConfigBool* m_enable_mmu_checkbox; ConfigBool* m_pause_on_panic_checkbox; ConfigBool* m_accurate_cpu_cache_checkbox;