From 6d585b6eb6a2248858916f936c5af9e7910e9b56 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 4 Nov 2023 17:56:43 +0100 Subject: [PATCH 1/4] DolphinQt/Settings: Split setting of the user style into two functions. This makes it so that if you just want to reload the current style (eg. on program start, or in response to a system event), you don't need to know the name of the currently selected user style. It's also more consistent with the way the 'userstyle/enabled' flag works. --- .../DolphinQt/Config/ToolTipControls/BalloonTip.cpp | 2 +- Source/Core/DolphinQt/Main.cpp | 2 +- Source/Core/DolphinQt/MainWindow.cpp | 6 ++---- Source/Core/DolphinQt/Settings.cpp | 12 ++++++++---- Source/Core/DolphinQt/Settings.h | 7 +++++-- Source/Core/DolphinQt/Settings/InterfacePane.cpp | 5 +++-- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp b/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp index ccec65c374..435b60e462 100644 --- a/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp +++ b/Source/Core/DolphinQt/Config/ToolTipControls/BalloonTip.cpp @@ -133,7 +133,7 @@ void BalloonTip::UpdateBoundsAndRedraw(const QPoint& pos, ShowArrow show_arrow) const QRect screen_rect = screen->geometry(); QSize sh = sizeHint(); - // The look should resemble the default tooltip style set in Settings::SetCurrentUserStyle() + // The look should resemble the default tooltip style set in Settings::ApplyStyle() const int border = 1; const int arrow_height = 18; const int arrow_width = 18; diff --git a/Source/Core/DolphinQt/Main.cpp b/Source/Core/DolphinQt/Main.cpp index 39aa5c6f1f..30922f1c63 100644 --- a/Source/Core/DolphinQt/Main.cpp +++ b/Source/Core/DolphinQt/Main.cpp @@ -247,7 +247,7 @@ int main(int argc, char* argv[]) Settings::Instance().InitDefaultPalette(); Settings::Instance().UpdateSystemDark(); - Settings::Instance().SetCurrentUserStyle(Settings::Instance().GetCurrentUserStyle()); + Settings::Instance().ApplyStyle(); MainWindow win{std::move(boot), static_cast(options.get("movie"))}; win.Show(); diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 3e9596f72e..7df52cdebf 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -240,9 +240,7 @@ MainWindow::MainWindow(std::unique_ptr boot_parameters, #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, - [](Qt::ColorScheme colorScheme) { - Settings::Instance().SetCurrentUserStyle(Settings::Instance().GetCurrentUserStyle()); - }); + [](Qt::ColorScheme colorScheme) { Settings::Instance().ApplyStyle(); }); #endif connect(m_cheats_manager, &CheatsManager::OpenGeneralSettings, this, @@ -1739,7 +1737,7 @@ bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr settings.UpdateSystemDark(); if (settings.IsSystemDark() != was_dark_before) { - settings.SetCurrentUserStyle(settings.GetCurrentUserStyle()); + settings.ApplyStyle(); // force the colors in the Skylander window to update if (m_skylander_window) diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index ebcf90ee8e..21ab0d62ef 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -123,7 +123,7 @@ void Settings::SetThemeName(const QString& theme_name) emit ThemeChanged(); } -QString Settings::GetCurrentUserStyle() const +QString Settings::GetUserStyleName() const { if (GetQSettings().contains(QStringLiteral("userstyle/name"))) return GetQSettings().value(QStringLiteral("userstyle/name")).toString(); @@ -132,6 +132,11 @@ QString Settings::GetCurrentUserStyle() const return QFileInfo(GetQSettings().value(QStringLiteral("userstyle/path")).toString()).fileName(); } +void Settings::SetUserStyleName(const QString& stylesheet_name) +{ + GetQSettings().setValue(QStringLiteral("userstyle/name"), stylesheet_name); +} + void Settings::InitDefaultPalette() { s_default_palette = std::make_unique(qApp->palette()); @@ -169,8 +174,9 @@ bool Settings::IsThemeDark() } // Calling this before the main window has been created breaks the style of some widgets. -void Settings::SetCurrentUserStyle(const QString& stylesheet_name) +void Settings::ApplyStyle() { + const QString stylesheet_name = GetUserStyleName(); QString stylesheet_contents; // If we haven't found one, we continue with an empty (default) style @@ -243,8 +249,6 @@ void Settings::SetCurrentUserStyle(const QString& stylesheet_name) } qApp->setStyleSheet(stylesheet_contents); - - GetQSettings().setValue(QStringLiteral("userstyle/name"), stylesheet_name); } bool Settings::AreUserStylesEnabled() const diff --git a/Source/Core/DolphinQt/Settings.h b/Source/Core/DolphinQt/Settings.h index 5583ed0628..e13eb0c0da 100644 --- a/Source/Core/DolphinQt/Settings.h +++ b/Source/Core/DolphinQt/Settings.h @@ -57,12 +57,15 @@ public: void SetSystemDark(bool dark); bool IsSystemDark(); bool IsThemeDark(); - void SetCurrentUserStyle(const QString& stylesheet_name); - QString GetCurrentUserStyle() const; + void SetUserStyleName(const QString& stylesheet_name); + QString GetUserStyleName() const; void SetUserStylesEnabled(bool enabled); bool AreUserStylesEnabled() const; + // this evaluates the current stylesheet settings and refreshes the GUI with them + void ApplyStyle(); + void GetToolTipStyle(QColor& window_color, QColor& text_color, QColor& emphasis_text_color, QColor& border_color, const QPalette& palette, const QPalette& high_contrast_palette) const; diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.cpp b/Source/Core/DolphinQt/Settings/InterfacePane.cpp index ef0985bfd4..0aa35054de 100644 --- a/Source/Core/DolphinQt/Settings/InterfacePane.cpp +++ b/Source/Core/DolphinQt/Settings/InterfacePane.cpp @@ -254,7 +254,7 @@ void InterfacePane::LoadConfig() ->setCurrentIndex( m_combobox_theme->findText(QString::fromStdString(Config::Get(Config::MAIN_THEME_NAME)))); - const QString userstyle = Settings::Instance().GetCurrentUserStyle(); + const QString userstyle = Settings::Instance().GetUserStyleName(); const int index = m_combobox_userstyle->findData(QFileInfo(userstyle).fileName()); if (index > 0) @@ -298,7 +298,8 @@ void InterfacePane::OnSaveConfig() m_checkbox_use_builtin_title_database->isChecked()); Settings::Instance().SetDebugModeEnabled(m_checkbox_show_debugging_ui->isChecked()); Settings::Instance().SetUserStylesEnabled(m_checkbox_use_userstyle->isChecked()); - Settings::Instance().SetCurrentUserStyle(m_combobox_userstyle->currentData().toString()); + Settings::Instance().SetUserStyleName(m_combobox_userstyle->currentData().toString()); + Settings::Instance().ApplyStyle(); const bool visible = m_checkbox_use_userstyle->isChecked(); From 8f55c28472801afddc4dc8d595253b9ef529868d Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 4 Nov 2023 18:25:42 +0100 Subject: [PATCH 2/4] DolphinQt/Settings: Add option to force the light or dark style on Windows. --- Source/Core/DolphinQt/Settings.cpp | 29 +++++++++++++++---- Source/Core/DolphinQt/Settings.h | 16 ++++++++-- .../Core/DolphinQt/Settings/InterfacePane.cpp | 7 +++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/Source/Core/DolphinQt/Settings.cpp b/Source/Core/DolphinQt/Settings.cpp index 21ab0d62ef..2e21835b6f 100644 --- a/Source/Core/DolphinQt/Settings.cpp +++ b/Source/Core/DolphinQt/Settings.cpp @@ -176,11 +176,12 @@ bool Settings::IsThemeDark() // Calling this before the main window has been created breaks the style of some widgets. void Settings::ApplyStyle() { + const StyleType style_type = GetStyleType(); const QString stylesheet_name = GetUserStyleName(); QString stylesheet_contents; // If we haven't found one, we continue with an empty (default) style - if (!stylesheet_name.isEmpty() && AreUserStylesEnabled()) + if (!stylesheet_name.isEmpty() && style_type == StyleType::User) { // Load custom user stylesheet QDir directory = QDir(QString::fromStdString(File::GetUserPath(D_STYLES_IDX))); @@ -197,7 +198,7 @@ void Settings::ApplyStyle() // which would select Qt's default theme, but unlike other OSes we don't automatically get a // default dark theme on Windows when the user has selected dark mode in the Windows settings. // So manually check if the user wants dark mode and, if yes, load our embedded dark theme. - if (IsSystemDark()) + if (style_type == StyleType::Dark || (style_type != StyleType::Light && IsSystemDark())) { QFile file(QStringLiteral(":/dolphin_dark_win/dark.qss")); if (file.open(QFile::ReadOnly)) @@ -251,14 +252,30 @@ void Settings::ApplyStyle() qApp->setStyleSheet(stylesheet_contents); } -bool Settings::AreUserStylesEnabled() const +Settings::StyleType Settings::GetStyleType() const { - return GetQSettings().value(QStringLiteral("userstyle/enabled"), false).toBool(); + if (GetQSettings().contains(QStringLiteral("userstyle/styletype"))) + { + bool ok = false; + const int type_int = GetQSettings().value(QStringLiteral("userstyle/styletype")).toInt(&ok); + if (ok && type_int >= static_cast(StyleType::MinValue) && + type_int <= static_cast(StyleType::MaxValue)) + { + return static_cast(type_int); + } + } + + // if the style type is unset or invalid, try the old enabled flag instead + const bool enabled = GetQSettings().value(QStringLiteral("userstyle/enabled"), false).toBool(); + return enabled ? StyleType::User : StyleType::System; } -void Settings::SetUserStylesEnabled(bool enabled) +void Settings::SetStyleType(StyleType type) { - GetQSettings().setValue(QStringLiteral("userstyle/enabled"), enabled); + GetQSettings().setValue(QStringLiteral("userstyle/styletype"), static_cast(type)); + + // also set the old setting so that the config is correctly intepreted by older Dolphin builds + GetQSettings().setValue(QStringLiteral("userstyle/enabled"), type == StyleType::User); } void Settings::GetToolTipStyle(QColor& window_color, QColor& text_color, diff --git a/Source/Core/DolphinQt/Settings.h b/Source/Core/DolphinQt/Settings.h index e13eb0c0da..fdc9f0a940 100644 --- a/Source/Core/DolphinQt/Settings.h +++ b/Source/Core/DolphinQt/Settings.h @@ -60,8 +60,20 @@ public: void SetUserStyleName(const QString& stylesheet_name); QString GetUserStyleName() const; - void SetUserStylesEnabled(bool enabled); - bool AreUserStylesEnabled() const; + + enum class StyleType : int + { + System = 0, + Light = 1, + Dark = 2, + User = 3, + + MinValue = 0, + MaxValue = 3, + }; + + void SetStyleType(StyleType type); + StyleType GetStyleType() const; // this evaluates the current stylesheet settings and refreshes the GUI with them void ApplyStyle(); diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.cpp b/Source/Core/DolphinQt/Settings/InterfacePane.cpp index 0aa35054de..1a5eeee441 100644 --- a/Source/Core/DolphinQt/Settings/InterfacePane.cpp +++ b/Source/Core/DolphinQt/Settings/InterfacePane.cpp @@ -260,7 +260,8 @@ void InterfacePane::LoadConfig() if (index > 0) SignalBlocking(m_combobox_userstyle)->setCurrentIndex(index); - SignalBlocking(m_checkbox_use_userstyle)->setChecked(Settings::Instance().AreUserStylesEnabled()); + SignalBlocking(m_checkbox_use_userstyle) + ->setChecked(Settings::Instance().GetStyleType() == Settings::StyleType::User); const bool visible = m_checkbox_use_userstyle->isChecked(); @@ -297,7 +298,9 @@ void InterfacePane::OnSaveConfig() Config::SetBase(Config::MAIN_USE_BUILT_IN_TITLE_DATABASE, m_checkbox_use_builtin_title_database->isChecked()); Settings::Instance().SetDebugModeEnabled(m_checkbox_show_debugging_ui->isChecked()); - Settings::Instance().SetUserStylesEnabled(m_checkbox_use_userstyle->isChecked()); + Settings::Instance().SetStyleType(m_checkbox_use_userstyle->isChecked() ? + Settings::StyleType::User : + Settings::StyleType::System); Settings::Instance().SetUserStyleName(m_combobox_userstyle->currentData().toString()); Settings::Instance().ApplyStyle(); From ed6014ddb50f1b5f7a877137e4eb5f312d026d23 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sat, 4 Nov 2023 18:41:52 +0100 Subject: [PATCH 3/4] DolphinQt/InterfacePane: Rework style dropdown so the built-in light/dark style can be manually selected. --- .../Core/DolphinQt/Settings/InterfacePane.cpp | 43 +++++++++---------- .../Core/DolphinQt/Settings/InterfacePane.h | 1 - 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.cpp b/Source/Core/DolphinQt/Settings/InterfacePane.cpp index 1a5eeee441..51e09c7fa7 100644 --- a/Source/Core/DolphinQt/Settings/InterfacePane.cpp +++ b/Source/Core/DolphinQt/Settings/InterfacePane.cpp @@ -128,12 +128,18 @@ void InterfacePane::CreateUI() // User Style Combobox m_combobox_userstyle = new QComboBox; - m_label_userstyle = new QLabel(tr("User Style:")); + m_label_userstyle = new QLabel(tr("Style:")); combobox_layout->addRow(m_label_userstyle, m_combobox_userstyle); auto userstyle_search_results = Common::DoFileSearch({File::GetUserPath(D_STYLES_IDX)}); - m_combobox_userstyle->addItem(tr("(None)"), QString{}); + m_combobox_userstyle->addItem(tr("(System)"), static_cast(Settings::StyleType::System)); + + // TODO: Support forcing light/dark on other OSes too. +#ifdef _WIN32 + m_combobox_userstyle->addItem(tr("(Light)"), static_cast(Settings::StyleType::Light)); + m_combobox_userstyle->addItem(tr("(Dark)"), static_cast(Settings::StyleType::Dark)); +#endif for (const std::string& path : userstyle_search_results) { @@ -143,7 +149,6 @@ void InterfacePane::CreateUI() // Checkboxes m_checkbox_use_builtin_title_database = new QCheckBox(tr("Use Built-In Database of Game Names")); - m_checkbox_use_userstyle = new QCheckBox(tr("Use Custom User Style")); m_checkbox_use_covers = new QCheckBox(tr("Download Game Covers from GameTDB.com for Use in Grid Mode")); m_checkbox_show_debugging_ui = new QCheckBox(tr("Enable Debugging UI")); @@ -151,7 +156,6 @@ void InterfacePane::CreateUI() m_checkbox_disable_screensaver = new QCheckBox(tr("Inhibit Screensaver During Emulation")); groupbox_layout->addWidget(m_checkbox_use_builtin_title_database); - groupbox_layout->addWidget(m_checkbox_use_userstyle); groupbox_layout->addWidget(m_checkbox_use_covers); groupbox_layout->addWidget(m_checkbox_show_debugging_ui); groupbox_layout->addWidget(m_checkbox_focused_hotkeys); @@ -238,7 +242,6 @@ void InterfacePane::ConnectLayout() &InterfacePane::OnCursorVisibleAlways); connect(m_checkbox_lock_mouse, &QCheckBox::toggled, &Settings::Instance(), &Settings::SetLockCursor); - connect(m_checkbox_use_userstyle, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig); } void InterfacePane::LoadConfig() @@ -254,20 +257,15 @@ void InterfacePane::LoadConfig() ->setCurrentIndex( m_combobox_theme->findText(QString::fromStdString(Config::Get(Config::MAIN_THEME_NAME)))); + const Settings::StyleType style_type = Settings::Instance().GetStyleType(); const QString userstyle = Settings::Instance().GetUserStyleName(); - const int index = m_combobox_userstyle->findData(QFileInfo(userstyle).fileName()); + const int index = style_type == Settings::StyleType::User ? + m_combobox_userstyle->findData(userstyle) : + m_combobox_userstyle->findData(static_cast(style_type)); if (index > 0) SignalBlocking(m_combobox_userstyle)->setCurrentIndex(index); - SignalBlocking(m_checkbox_use_userstyle) - ->setChecked(Settings::Instance().GetStyleType() == Settings::StyleType::User); - - const bool visible = m_checkbox_use_userstyle->isChecked(); - - m_combobox_userstyle->setVisible(visible); - m_label_userstyle->setVisible(visible); - // Render Window Options SignalBlocking(m_checkbox_top_window) ->setChecked(Settings::Instance().IsKeepWindowOnTopEnabled()); @@ -298,17 +296,16 @@ void InterfacePane::OnSaveConfig() Config::SetBase(Config::MAIN_USE_BUILT_IN_TITLE_DATABASE, m_checkbox_use_builtin_title_database->isChecked()); Settings::Instance().SetDebugModeEnabled(m_checkbox_show_debugging_ui->isChecked()); - Settings::Instance().SetStyleType(m_checkbox_use_userstyle->isChecked() ? - Settings::StyleType::User : - Settings::StyleType::System); - Settings::Instance().SetUserStyleName(m_combobox_userstyle->currentData().toString()); + const auto selected_style = m_combobox_userstyle->currentData(); + bool is_builtin_type = false; + const int style_type_int = selected_style.toInt(&is_builtin_type); + Settings::Instance().SetStyleType(is_builtin_type ? + static_cast(style_type_int) : + Settings::StyleType::User); + if (!is_builtin_type) + Settings::Instance().SetUserStyleName(selected_style.toString()); Settings::Instance().ApplyStyle(); - const bool visible = m_checkbox_use_userstyle->isChecked(); - - m_combobox_userstyle->setVisible(visible); - m_label_userstyle->setVisible(visible); - // Render Window Options Settings::Instance().SetKeepWindowOnTop(m_checkbox_top_window->isChecked()); Config::SetBase(Config::MAIN_CONFIRM_ON_STOP, m_checkbox_confirm_on_stop->isChecked()); diff --git a/Source/Core/DolphinQt/Settings/InterfacePane.h b/Source/Core/DolphinQt/Settings/InterfacePane.h index d751c507c5..ffa09c3f72 100644 --- a/Source/Core/DolphinQt/Settings/InterfacePane.h +++ b/Source/Core/DolphinQt/Settings/InterfacePane.h @@ -36,7 +36,6 @@ private: QLabel* m_label_userstyle; QCheckBox* m_checkbox_top_window; QCheckBox* m_checkbox_use_builtin_title_database; - QCheckBox* m_checkbox_use_userstyle; QCheckBox* m_checkbox_show_debugging_ui; QCheckBox* m_checkbox_focused_hotkeys; QCheckBox* m_checkbox_use_covers; From 2f9e98b77b660d34d74a1b3cf7ba41b501a6a310 Mon Sep 17 00:00:00 2001 From: "Admiral H. Curtiss" Date: Sun, 5 Nov 2023 18:13:00 +0100 Subject: [PATCH 4/4] DolphinQt: Check theme instead of system for when to apply dark title bars on Windows. --- Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp b/Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp index 704e5a8f7f..6c595c0e2d 100644 --- a/Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp +++ b/Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp @@ -14,7 +14,7 @@ void SetQWidgetWindowDecorations(QWidget* widget) { #ifdef _WIN32 - if (!Settings::Instance().IsSystemDark()) + if (!Settings::Instance().IsThemeDark()) return; BOOL use_dark_title_bar = TRUE;