diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.cpp b/Source/Core/DolphinQt/Config/SettingsWindow.cpp index 8efae30cee2..04b1f2d0210 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt/Config/SettingsWindow.cpp @@ -3,9 +3,13 @@ #include "DolphinQt/Config/SettingsWindow.h" +#include +#include #include +#include #include #include +#include #include #include #include @@ -17,6 +21,7 @@ #include "DolphinQt/MainWindow.h" #include "DolphinQt/QtUtils/QtUtils.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" +#include "DolphinQt/Settings.h" #include "DolphinQt/Settings/AdvancedPane.h" #include "DolphinQt/Settings/AudioPane.h" #include "DolphinQt/Settings/GameCubePane.h" @@ -34,7 +39,7 @@ StackedSettingsWindow::StackedSettingsWindow(QWidget* parent) : QDialog{parent} auto* const layout = new QHBoxLayout{this}; // Calculated value for the padding in our list items. - const int list_item_padding = layout->contentsMargins().left() / 2; + m_list_item_padding = layout->contentsMargins().left() / 2; // Eliminate padding around layouts. layout->setContentsMargins(QMargins{}); @@ -46,33 +51,7 @@ StackedSettingsWindow::StackedSettingsWindow(QWidget* parent) : QDialog{parent} m_navigation_list->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); m_navigation_list->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); - // FYI: "base" is the window color on Windows and "alternate-base" is very high contrast on macOS. - const auto* const list_background = -#if !defined(__APPLE__) - "palette(alternate-base)"; -#else - "palette(base)"; -#endif - - m_navigation_list->setStyleSheet( - QString::fromUtf8( - // Remove border around entire widget and adjust background color. - "QListWidget { border: 0; background: %1; } " - // Note: padding-left is broken unless border is set, which then breaks colors. - // see: https://bugreports.qt.io/browse/QTBUG-122698 - "QListWidget::item { padding-top: %2px; padding-bottom: %2px; } " - // Maintain selected item color when unfocused. - "QListWidget::item:selected { background: palette(highlight); " -#if !defined(__APPLE__) - // Prevent text color change on focus loss. - // This seems to breaks the nice white text on macOS. - "color: palette(highlighted-text); " -#endif - "} " - // Remove ugly dotted outline on selected row (Windows and GNOME). - "* { outline: none; } ") - .arg(QString::fromUtf8(list_background)) - .arg(list_item_padding)); + UpdateNavigationListStyle(); layout->addWidget(m_navigation_list); @@ -104,6 +83,90 @@ void StackedSettingsWindow::OnDoneCreatingPanes() QtUtils::AdjustSizeWithinScreen(this); } +void StackedSettingsWindow::changeEvent(QEvent* event) +{ + QDialog::changeEvent(event); + + const auto type = event->type(); + + const bool palette_changed = type == QEvent::PaletteChange; + const bool application_palette_changed = type == QEvent::ApplicationPaletteChange; + const bool style_changed = type == QEvent::StyleChange; + const bool theme_event = type == QEvent::ThemeChange; + + const bool theme_changed = application_palette_changed || theme_event; + + if (theme_changed && !m_handling_theme_change) + { + m_handling_theme_change = true; + Settings::Instance().ApplyStyle(); + // Ensure the dialog and its children adopt the new system palette. + setPalette(qApp->palette()); + Settings::Instance().TriggerThemeChanged(); + m_handling_theme_change = false; + } + + if (palette_changed || application_palette_changed || style_changed || theme_event) + UpdateNavigationListStyle(); +} + +void StackedSettingsWindow::UpdateNavigationListStyle() +{ + if (!m_navigation_list) + return; + + // FYI: "base" is the window color on Windows and "alternate-base" is very high contrast on macOS. + const auto* const list_background = +#if !defined(__APPLE__) + "palette(alternate-base)"; +#else + "palette(base)"; +#endif + + m_navigation_list->setStyleSheet( + QString::fromUtf8( + // Remove border around entire widget and adjust background color. + "QListWidget { border: 0; background: %1; } " + // Note: padding-left is broken unless border is set, which then breaks colors. + // see: https://bugreports.qt.io/browse/QTBUG-122698 + "QListWidget::item { padding-top: %2px; padding-bottom: %2px; } " + // Maintain selected item color when unfocused. + "QListWidget::item:selected { background: palette(highlight); " + // Prevent text color change on focus loss. + "color: palette(highlighted-text); " + "} " + // Remove ugly dotted outline on selected row (Windows and GNOME). + "* { outline: none; } ") + .arg(QString::fromUtf8(list_background)) + .arg(m_list_item_padding)); + QPalette list_palette = m_navigation_list->palette(); + const QPalette app_palette = qApp->palette(); + + QColor highlight_color = app_palette.color(QPalette::Active, QPalette::Highlight); + QColor highlighted_text = app_palette.color(QPalette::Active, QPalette::HighlightedText); + +#if defined(__APPLE__) + const bool is_dark_theme = Settings::Instance().IsThemeDark(); + // The default macOS accent is quite light in our list; darken it for readability in light mode. + if (!is_dark_theme) + { + highlight_color = highlight_color.darker(130); + highlighted_text = QColor(Qt::white); + } +#endif + + for (const QPalette::ColorGroup group : {QPalette::Active, QPalette::Inactive}) + { + list_palette.setColor(group, QPalette::Base, app_palette.color(group, QPalette::Base)); + list_palette.setColor(group, QPalette::AlternateBase, + app_palette.color(group, QPalette::AlternateBase)); + list_palette.setColor(group, QPalette::Highlight, highlight_color); + list_palette.setColor(group, QPalette::HighlightedText, highlighted_text); + } + + m_navigation_list->setPalette(list_palette); +} + void StackedSettingsWindow::AddPane(QWidget* widget, const QString& name) { m_stacked_panes->addWidget(widget); diff --git a/Source/Core/DolphinQt/Config/SettingsWindow.h b/Source/Core/DolphinQt/Config/SettingsWindow.h index be8a85d1037..3fd646e7862 100644 --- a/Source/Core/DolphinQt/Config/SettingsWindow.h +++ b/Source/Core/DolphinQt/Config/SettingsWindow.h @@ -8,6 +8,7 @@ class QStackedWidget; class QListWidget; class MainWindow; +class QEvent; // A settings window with a QListWidget to switch between panes of a QStackedWidget. class StackedSettingsWindow : public QDialog @@ -27,9 +28,15 @@ protected: // For derived classes to call after they create their settings panes. void OnDoneCreatingPanes(); + void changeEvent(QEvent* event) override; + private: - QStackedWidget* m_stacked_panes; - QListWidget* m_navigation_list; + void UpdateNavigationListStyle(); + + QStackedWidget* m_stacked_panes = nullptr; + QListWidget* m_navigation_list = nullptr; + int m_list_item_padding = 0; + bool m_handling_theme_change = false; }; enum class SettingsWindowPaneIndex : int