interfacesettingswidget.cpp (9008B)
1 // SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com> 2 // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) 3 4 #include "interfacesettingswidget.h" 5 #include "autoupdaterdialog.h" 6 #include "mainwindow.h" 7 #include "qtutils.h" 8 #include "scmversion/scmversion.h" 9 #include "settingswindow.h" 10 #include "settingwidgetbinder.h" 11 12 const char* InterfaceSettingsWidget::THEME_NAMES[] = { 13 QT_TRANSLATE_NOOP("MainWindow", "Native"), 14 #ifdef _WIN32 15 QT_TRANSLATE_NOOP("MainWindow", "Classic Windows"), 16 #endif 17 QT_TRANSLATE_NOOP("MainWindow", "Fusion"), 18 QT_TRANSLATE_NOOP("MainWindow", "Dark Fusion (Gray)"), 19 QT_TRANSLATE_NOOP("MainWindow", "Dark Fusion (Blue)"), 20 QT_TRANSLATE_NOOP("MainWindow", "Cobalt Sky"), 21 QT_TRANSLATE_NOOP("MainWindow", "Grey Matter"), 22 QT_TRANSLATE_NOOP("MainWindow", "Dark Ruby"), 23 QT_TRANSLATE_NOOP("MainWindow", "Purple Rain"), 24 QT_TRANSLATE_NOOP("MainWindow", "QDarkStyle"), 25 nullptr, 26 }; 27 28 const char* InterfaceSettingsWidget::THEME_VALUES[] = { 29 "", 30 #ifdef _WIN32 31 "windowsvista", 32 #endif 33 "fusion", 34 "darkfusion", 35 "darkfusionblue", 36 "cobaltsky", 37 "greymatter", 38 "darkruby", 39 "purplerain", 40 "qdarkstyle", 41 nullptr, 42 }; 43 44 const char* InterfaceSettingsWidget::DEFAULT_THEME_NAME = "darkfusion"; 45 46 InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget* parent) 47 : QWidget(parent), m_dialog(dialog) 48 { 49 SettingsInterface* sif = dialog->getSettingsInterface(); 50 51 m_ui.setupUi(this); 52 53 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.inhibitScreensaver, "Main", "InhibitScreensaver", true); 54 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnFocusLoss, "Main", "PauseOnFocusLoss", false); 55 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnControllerDisconnection, "Main", 56 "PauseOnControllerDisconnection", false); 57 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnStart, "Main", "StartPaused", false); 58 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.saveStateOnExit, "Main", "SaveStateOnExit", true); 59 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.confirmPowerOff, "Main", "ConfirmPowerOff", true); 60 61 if (!m_dialog->isPerGameSettings()) 62 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.startFullscreen, "Main", "StartFullscreen", false); 63 else 64 SettingWidgetBinder::SetAvailability(m_ui.startFullscreen, false); 65 66 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.doubleClickTogglesFullscreen, "Main", 67 "DoubleClickTogglesFullscreen", true); 68 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.renderToSeparateWindow, "Main", "RenderToSeparateWindow", 69 false); 70 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hideMainWindow, "Main", "HideMainWindowWhenRunning", false); 71 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableWindowResizing, "Main", "DisableWindowResize", false); 72 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hideMouseCursor, "Main", "HideCursorInFullscreen", true); 73 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.createSaveStateBackups, "Main", "CreateSaveStateBackups", 74 Settings::DEFAULT_SAVE_STATE_BACKUPS); 75 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableDiscordPresence, "Main", "EnableDiscordPresence", false); 76 connect(m_ui.renderToSeparateWindow, &QCheckBox::checkStateChanged, this, 77 &InterfaceSettingsWidget::onRenderToSeparateWindowChanged); 78 79 SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES, 80 QtHost::GetDefaultThemeName(), "MainWindow"); 81 connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); }); 82 83 populateLanguageDropdown(m_ui.language); 84 SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.language, "Main", "Language", QtHost::GetDefaultLanguage()); 85 connect(m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), this, 86 &InterfaceSettingsWidget::onLanguageChanged); 87 88 onRenderToSeparateWindowChanged(); 89 90 dialog->registerWidgetHelp( 91 m_ui.confirmPowerOff, tr("Confirm Power Off"), tr("Checked"), 92 tr("Determines whether a prompt will be displayed to confirm shutting down the emulator/game " 93 "when the hotkey is pressed.")); 94 dialog->registerWidgetHelp(m_ui.saveStateOnExit, tr("Save State On Exit"), tr("Checked"), 95 tr("Automatically saves the emulator state when powering down or exiting. You can then " 96 "resume directly from where you left off next time.")); 97 dialog->registerWidgetHelp(m_ui.startFullscreen, tr("Start Fullscreen"), tr("Unchecked"), 98 tr("Automatically switches to fullscreen mode when a game is started.")); 99 dialog->registerWidgetHelp(m_ui.hideMouseCursor, tr("Hide Cursor In Fullscreen"), tr("Checked"), 100 tr("Hides the mouse pointer/cursor when the emulator is in fullscreen mode.")); 101 dialog->registerWidgetHelp( 102 m_ui.inhibitScreensaver, tr("Inhibit Screensaver"), tr("Checked"), 103 tr("Prevents the screen saver from activating and the host from sleeping while emulation is running.")); 104 dialog->registerWidgetHelp( 105 m_ui.renderToSeparateWindow, tr("Render To Separate Window"), tr("Checked"), 106 tr("Renders the display of the simulated console to the main window of the application, over " 107 "the game list. If checked, the display will render in a separate window.")); 108 dialog->registerWidgetHelp(m_ui.pauseOnStart, tr("Pause On Start"), tr("Unchecked"), 109 tr("Pauses the emulator when a game is started.")); 110 dialog->registerWidgetHelp(m_ui.pauseOnFocusLoss, tr("Pause On Focus Loss"), tr("Unchecked"), 111 tr("Pauses the emulator when you minimize the window or switch to another application, " 112 "and unpauses when you switch back.")); 113 dialog->registerWidgetHelp(m_ui.pauseOnControllerDisconnection, tr("Pause On Controller Disconnection"), 114 tr("Unchecked"), 115 tr("Pauses the emulator when a controller with bindings is disconnected.")); 116 dialog->registerWidgetHelp( 117 m_ui.createSaveStateBackups, tr("Create Save State Backups"), tr("Checked"), 118 tr("Backs up any previous save state when creating a new save state, with a .bak extension.")); 119 dialog->registerWidgetHelp(m_ui.enableDiscordPresence, tr("Enable Discord Presence"), tr("Unchecked"), 120 tr("Shows the game you are currently playing as part of your profile in Discord.")); 121 122 dialog->registerWidgetHelp(m_ui.autoUpdateEnabled, tr("Enable Automatic Update Check"), tr("Checked"), 123 tr("Automatically checks for updates to the program on startup. Updates can be deferred " 124 "until later or skipped entirely.")); 125 126 m_ui.autoUpdateCurrentVersion->setText(tr("%1 (%2)").arg(g_scm_tag_str).arg(g_scm_date_str)); 127 128 if (!m_dialog->isPerGameSettings() && AutoUpdaterDialog::isSupported()) 129 { 130 SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true); 131 m_ui.autoUpdateTag->addItems(AutoUpdaterDialog::getTagList()); 132 SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.autoUpdateTag, "AutoUpdater", "UpdateTag", 133 AutoUpdaterDialog::getDefaultTag()); 134 connect(m_ui.checkForUpdates, &QPushButton::clicked, this, []() { g_main_window->checkForUpdates(true); }); 135 } 136 else 137 { 138 m_ui.autoUpdateTag->addItem(tr("Unavailable")); 139 m_ui.autoUpdateEnabled->setEnabled(false); 140 m_ui.autoUpdateTag->setEnabled(false); 141 m_ui.checkForUpdates->setEnabled(false); 142 m_ui.updatesGroup->setEnabled(false); 143 } 144 } 145 146 InterfaceSettingsWidget::~InterfaceSettingsWidget() = default; 147 148 void InterfaceSettingsWidget::populateLanguageDropdown(QComboBox* cb) 149 { 150 for (const auto& [language, code] : Host::GetAvailableLanguageList()) 151 { 152 QString icon_filename(QStringLiteral(":/icons/flags/%1.png").arg(QLatin1StringView(code))); 153 if (!QFile::exists(icon_filename)) 154 { 155 // try without the suffix (e.g. es-es -> es) 156 const char* pos = std::strrchr(code, '-'); 157 if (pos) 158 icon_filename = QStringLiteral(":/icons/flags/%1.png").arg(QLatin1StringView(pos)); 159 } 160 161 cb->addItem(QIcon(icon_filename), QString::fromUtf8(language), QString::fromLatin1(code)); 162 } 163 } 164 165 void InterfaceSettingsWidget::onRenderToSeparateWindowChanged() 166 { 167 m_ui.hideMainWindow->setEnabled(m_ui.renderToSeparateWindow->isChecked()); 168 } 169 170 void InterfaceSettingsWidget::onLanguageChanged() 171 { 172 QtHost::UpdateApplicationLanguage(QtUtils::GetRootWidget(this)); 173 g_main_window->recreate(); 174 }