Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DolphinQt: Allow forcing light or dark style on Windows. #12272

Merged
merged 4 commits into from Nov 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DolphinQt/Main.cpp
Expand Up @@ -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<const char*>(options.get("movie"))};
win.Show();
Expand Down
6 changes: 2 additions & 4 deletions Source/Core/DolphinQt/MainWindow.cpp
Expand Up @@ -240,9 +240,7 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> 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,
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Source/Core/DolphinQt/QtUtils/SetWindowDecorations.cpp
Expand Up @@ -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;
Expand Down
41 changes: 31 additions & 10 deletions Source/Core/DolphinQt/Settings.cpp
Expand Up @@ -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();
Expand All @@ -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<QPalette>(qApp->palette());
Expand Down Expand Up @@ -169,12 +174,14 @@ 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 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)));
Expand All @@ -191,7 +198,7 @@ void Settings::SetCurrentUserStyle(const QString& stylesheet_name)
// 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))
Expand Down Expand Up @@ -243,18 +250,32 @@ void Settings::SetCurrentUserStyle(const QString& stylesheet_name)
}

qApp->setStyleSheet(stylesheet_contents);

GetQSettings().setValue(QStringLiteral("userstyle/name"), stylesheet_name);
}

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<int>(StyleType::MinValue) &&
type_int <= static_cast<int>(StyleType::MaxValue))
{
return static_cast<StyleType>(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<int>(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,
Expand Down
23 changes: 19 additions & 4 deletions Source/Core/DolphinQt/Settings.h
Expand Up @@ -57,11 +57,26 @@ class Settings final : public QObject
void SetSystemDark(bool dark);
bool IsSystemDark();
bool IsThemeDark();
void SetCurrentUserStyle(const QString& stylesheet_name);
QString GetCurrentUserStyle() const;

void SetUserStylesEnabled(bool enabled);
bool AreUserStylesEnabled() const;
void SetUserStyleName(const QString& stylesheet_name);
QString GetUserStyleName() 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();

void GetToolTipStyle(QColor& window_color, QColor& text_color, QColor& emphasis_text_color,
QColor& border_color, const QPalette& palette,
Expand Down
43 changes: 22 additions & 21 deletions Source/Core/DolphinQt/Settings/InterfacePane.cpp
Expand Up @@ -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<int>(Settings::StyleType::System));

// TODO: Support forcing light/dark on other OSes too.
#ifdef _WIN32
m_combobox_userstyle->addItem(tr("(Light)"), static_cast<int>(Settings::StyleType::Light));
m_combobox_userstyle->addItem(tr("(Dark)"), static_cast<int>(Settings::StyleType::Dark));
#endif

for (const std::string& path : userstyle_search_results)
{
Expand All @@ -143,15 +149,13 @@ 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"));
m_checkbox_focused_hotkeys = new QCheckBox(tr("Hotkeys Require Window Focus"));
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);
Expand Down Expand Up @@ -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()
Expand All @@ -254,19 +257,15 @@ void InterfacePane::LoadConfig()
->setCurrentIndex(
m_combobox_theme->findText(QString::fromStdString(Config::Get(Config::MAIN_THEME_NAME))));

const QString userstyle = Settings::Instance().GetCurrentUserStyle();
const int index = m_combobox_userstyle->findData(QFileInfo(userstyle).fileName());
const Settings::StyleType style_type = Settings::Instance().GetStyleType();
const QString userstyle = Settings::Instance().GetUserStyleName();
const int index = style_type == Settings::StyleType::User ?
m_combobox_userstyle->findData(userstyle) :
m_combobox_userstyle->findData(static_cast<int>(style_type));

if (index > 0)
SignalBlocking(m_combobox_userstyle)->setCurrentIndex(index);

SignalBlocking(m_checkbox_use_userstyle)->setChecked(Settings::Instance().AreUserStylesEnabled());

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());
Expand Down Expand Up @@ -297,13 +296,15 @@ 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().SetCurrentUserStyle(m_combobox_userstyle->currentData().toString());

const bool visible = m_checkbox_use_userstyle->isChecked();

m_combobox_userstyle->setVisible(visible);
m_label_userstyle->setVisible(visible);
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<Settings::StyleType>(style_type_int) :
Settings::StyleType::User);
if (!is_builtin_type)
Settings::Instance().SetUserStyleName(selected_style.toString());
Settings::Instance().ApplyStyle();

// Render Window Options
Settings::Instance().SetKeepWindowOnTop(m_checkbox_top_window->isChecked());
Expand Down
1 change: 0 additions & 1 deletion Source/Core/DolphinQt/Settings/InterfacePane.h
Expand Up @@ -36,7 +36,6 @@ class InterfacePane final : public QWidget
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;
Expand Down