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; };