Skip to content

Commit 925a7a3

Browse files
authored
Theme switch (#543)
* initial implementation of runtime theme switching * switch to using setColorScheme * address changing to fusion on mac, move the dropdown
1 parent 15aea97 commit 925a7a3

File tree

4 files changed

+144
-16
lines changed

4 files changed

+144
-16
lines changed

gui/qt/mainwindow.cpp

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#include <QtCore/QProcess>
2727
#include <QtCore/QRegularExpression>
2828
#include <QtGui/QFont>
29+
#include <QtGui/QPalette>
30+
#include <QtGui/QColor>
2931
#include <QtGui/QWindow>
3032
#include <QtGui/QDesktopServices>
3133
#include <QtGui/QClipboard>
@@ -36,11 +38,15 @@
3638
#include <QtWidgets/QComboBox>
3739
#include <QtWidgets/QScrollBar>
3840
#include <QtWidgets/QMessageBox>
41+
#include <QtWidgets/QStyle>
42+
#include <QtGui/QStyleHints>
43+
#include <QtWidgets/QStyleFactory>
3944
#include <QtNetwork/QNetworkReply>
45+
#include <QtCore/QSignalBlocker>
46+
#include <QtCore/QScopedValueRollback>
4047
#include <fstream>
4148
#include <iostream>
4249
#include <cmath>
43-
4450
#ifdef Q_OS_MACOS
4551
# include "os/mac/kdmactouchbar.h"
4652
#endif
@@ -56,6 +62,8 @@ Q_DECLARE_METATYPE(emu_data_t)
5662
# include <unistd.h>
5763
#endif
5864

65+
using namespace Qt::StringLiterals;
66+
5967
MainWindow::MainWindow(CEmuOpts &cliOpts, QWidget *p) : QMainWindow(p), ui(new Ui::MainWindow), opts(cliOpts) {
6068
keypadBridge = new QtKeypadBridge(this); // This must be before setupUi for some reason >.>
6169

@@ -70,8 +78,13 @@ MainWindow::MainWindow(CEmuOpts &cliOpts, QWidget *p) : QMainWindow(p), ui(new U
7078

7179
ui->setupUi(this);
7280

73-
m_styleForMode[0] = m_styleForMode[1] = QApplication::style()->name();
74-
darkModeSwitch(isSystemInDarkMode());
81+
{
82+
QSignalBlocker blocker(ui->comboTheme);
83+
ui->comboTheme->setCurrentIndex(static_cast<int>(m_themePreference));
84+
}
85+
connect(ui->comboTheme, &QComboBox::currentIndexChanged, this, &MainWindow::setThemePreference);
86+
87+
applyThemeFromPreference();
7588

7689
setStyleSheet(QStringLiteral("QMainWindow::separator{ width: 0px; height: 0px; }"));
7790

@@ -597,6 +610,7 @@ MainWindow::MainWindow(CEmuOpts &cliOpts, QWidget *p) : QMainWindow(p), ui(new U
597610
}
598611

599612
setAutoUpdates(m_config->value(SETTING_AUTOUPDATE, CEMU_RELEASE).toBool());
613+
setThemePreference(m_config->value(SETTING_UI_THEME, static_cast<int>(ThemePreference::System)).toInt());
600614
checkVersion();
601615

602616
#ifdef Q_OS_WIN
@@ -1129,14 +1143,52 @@ void MainWindow::translateExtras(int init) {
11291143
}
11301144
}
11311145

1132-
void MainWindow::darkModeSwitch(bool darkMode) {
1133-
QApplication::setStyle(m_styleForMode[darkMode]);
1134-
if (darkMode != isRunningInDarkMode()) {
1135-
m_styleForMode[darkMode] = QStringLiteral("fusion");
1136-
QApplication::setStyle(m_styleForMode[darkMode]);
1137-
darkMode = isRunningInDarkMode();
1146+
void MainWindow::applyThemeFromPreference() {
1147+
Qt::ColorScheme scheme = Qt::ColorScheme::Unknown;
1148+
bool explicitScheme = false;
1149+
switch (m_themePreference) {
1150+
case ThemePreference::System:
1151+
scheme = Qt::ColorScheme::Unknown;
1152+
break;
1153+
case ThemePreference::Light:
1154+
scheme = Qt::ColorScheme::Light;
1155+
explicitScheme = true;
1156+
break;
1157+
case ThemePreference::Dark:
1158+
scheme = Qt::ColorScheme::Dark;
1159+
explicitScheme = true;
1160+
break;
1161+
}
1162+
qApp->styleHints()->setColorScheme(scheme);
1163+
1164+
#if defined(Q_OS_WIN)
1165+
if (explicitScheme) {
1166+
if (QStyle *fusion = QStyleFactory::create("Fusion"_L1)) {
1167+
QApplication::setStyle(fusion);
1168+
}
1169+
} else {
1170+
const auto available = QStyleFactory::keys();
1171+
if (available.contains("WindowsVista"_L1, Qt::CaseInsensitive)) {
1172+
if (QStyle *vista = QStyleFactory::create("WindowsVista"_L1)) {
1173+
QApplication::setStyle(vista);
1174+
}
1175+
}
1176+
}
1177+
#elif defined(Q_OS_MACOS)
1178+
Q_UNUSED(explicitScheme);
1179+
#else
1180+
if (explicitScheme) {
1181+
if (QStyle *fusion = QStyleFactory::create("Fusion"_L1)) {
1182+
QApplication::setStyle(fusion);
1183+
}
11381184
}
1185+
#endif
1186+
1187+
const bool dark = (qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark);
1188+
darkModeSwitch(dark);
1189+
}
11391190

1191+
void MainWindow::darkModeSwitch(bool darkMode) {
11401192
m_isInDarkMode = darkMode;
11411193
if (darkMode) {
11421194
m_cBack.setColor(QPalette::Base, QColor(Qt::blue).lighter(180));
@@ -1160,12 +1212,29 @@ void MainWindow::changeEvent(QEvent* event) {
11601212
translateSwitch(QLocale::system());
11611213
}
11621214
QMainWindow::changeEvent(event);
1163-
if (eventType == QEvent::ThemeChange) {
1164-
bool darkMode = isSystemInDarkMode();
1165-
if (darkMode != m_isInDarkMode) {
1166-
darkModeSwitch(darkMode);
1167-
}
1215+
if (eventType == QEvent::ThemeChange ||
1216+
eventType == QEvent::ApplicationPaletteChange ||
1217+
eventType == QEvent::PaletteChange) {
1218+
const bool dark = (qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark);
1219+
darkModeSwitch(dark);
1220+
}
1221+
}
1222+
1223+
void MainWindow::setThemePreference(int index) {
1224+
const auto pref = static_cast<ThemePreference>(index);
1225+
1226+
if (ui && ui->comboTheme && ui->comboTheme->currentIndex() != index) {
1227+
QSignalBlocker blocker(ui->comboTheme);
1228+
ui->comboTheme->setCurrentIndex(index);
11681229
}
1230+
1231+
m_themePreference = pref;
1232+
1233+
if (m_config && opts.useSettings) {
1234+
m_config->setValue(SETTING_UI_THEME, index);
1235+
}
1236+
1237+
applyThemeFromPreference();
11691238
}
11701239

11711240
void MainWindow::showEvent(QShowEvent *e) {
@@ -1485,6 +1554,7 @@ void MainWindow::resetGui() {
14851554
m_config->remove(SETTING_WINDOW_STATUSBAR);
14861555
m_config->remove(SETTING_WINDOW_SEPARATOR);
14871556
m_config->remove(SETTING_UI_EDIT_MODE);
1557+
m_config->remove(SETTING_UI_THEME);
14881558
m_needReload = true;
14891559
close();
14901560
}

gui/qt/mainwindow.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <QtCore/QTimer>
3030
#include <QtCore/QPointer>
3131
#include <QtGui/QShortcut>
32+
#include <QtGui/QPalette>
3233
#include <QtGui/QTextCursor>
3334
#include <QtCore/QTranslator>
3435
#include <QtCore/QStandardPaths>
@@ -39,6 +40,9 @@
3940
QT_BEGIN_NAMESPACE
4041
class QButtonGroup;
4142
class QLocale;
43+
class QEvent;
44+
class QCloseEvent;
45+
class QObject;
4246
QT_END_NAMESPACE
4347

4448
#ifdef LIBUSB_SUPPORT
@@ -100,6 +104,7 @@ private slots:
100104
#ifdef LIBUSB_SUPPORT
101105
void usbConnectPhysical(QVariant userData);
102106
#endif
107+
void setThemePreference(int index);
103108

104109
protected:
105110
virtual void changeEvent(QEvent* event) override;
@@ -228,6 +233,12 @@ private slots:
228233
FULLSCREEN_LCD
229234
};
230235

236+
enum class ThemePreference {
237+
System = 0,
238+
Light = 1,
239+
Dark = 2
240+
};
241+
231242
// emu keypresses
232243
void sendEmuKey(uint16_t key);
233244
void sendEmuLetterKey(char letter);
@@ -258,6 +269,7 @@ private slots:
258269
void translateExtras(int init);
259270
void translateSwitch(const QLocale &locale);
260271

272+
void applyThemeFromPreference();
261273
// dark mode
262274
void darkModeSwitch(bool darkMode);
263275

@@ -769,6 +781,8 @@ private slots:
769781
int m_fullscreen = FULLSCREEN_NONE;
770782
uint32_t m_runUntilAddr;
771783

784+
ThemePreference m_themePreference = ThemePreference::System;
785+
772786
QPushButton *m_btnCancelTranser;
773787
QProgressBar *m_progressBar;
774788
QStringList m_docksMemory;
@@ -790,7 +804,7 @@ private slots:
790804
bool m_timerEmuTriggered = false;
791805
bool m_timerFpsTriggered = false;
792806

793-
QString m_styleForMode[2];
807+
794808

795809
static const char *m_varExtensions[];
796810

@@ -856,6 +870,7 @@ private slots:
856870
static const QString SETTING_STATUS_INTERVAL;
857871
static const QString SETTING_FIRST_RUN;
858872
static const QString SETTING_UI_EDIT_MODE;
873+
static const QString SETTING_UI_THEME;
859874
static const QString SETTING_PAUSE_FOCUS;
860875
static const QString SETTING_SAVE_ON_CLOSE;
861876
static const QString SETTING_RESTORE_ON_OPEN;

gui/qt/mainwindow.ui

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7682,7 +7682,7 @@
76827682
</item>
76837683
</widget>
76847684
</item>
7685-
<item row="0" column="8">
7685+
<item row="0" column="10">
76867686
<spacer name="horizontalSpacer_7">
76877687
<property name="orientation">
76887688
<enum>Qt::Horizontal</enum>
@@ -7771,6 +7771,47 @@
77717771
</property>
77727772
</spacer>
77737773
</item>
7774+
<item row="0" column="8">
7775+
<widget class="QLabel" name="labelTheme">
7776+
<property name="text">
7777+
<string>Theme:</string>
7778+
</property>
7779+
</widget>
7780+
</item>
7781+
<item row="0" column="9">
7782+
<widget class="QComboBox" name="comboTheme">
7783+
<property name="sizePolicy">
7784+
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
7785+
<horstretch>0</horstretch>
7786+
<verstretch>0</verstretch>
7787+
</sizepolicy>
7788+
</property>
7789+
<property name="sizeAdjustPolicy">
7790+
<enum>QComboBox::AdjustToContents</enum>
7791+
</property>
7792+
<property name="maximumSize">
7793+
<size>
7794+
<width>200</width>
7795+
<height>16777215</height>
7796+
</size>
7797+
</property>
7798+
<item>
7799+
<property name="text">
7800+
<string>System Default</string>
7801+
</property>
7802+
</item>
7803+
<item>
7804+
<property name="text">
7805+
<string>Light</string>
7806+
</property>
7807+
</item>
7808+
<item>
7809+
<property name="text">
7810+
<string>Dark</string>
7811+
</property>
7812+
</item>
7813+
</widget>
7814+
</item>
77747815
</layout>
77757816
</widget>
77767817
</item>

gui/qt/settings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ const QString MainWindow::SETTING_ROM_PATH = QStringLiteral("ro
9494
const QString MainWindow::SETTING_STATUS_INTERVAL = QStringLiteral("status_interval");
9595
const QString MainWindow::SETTING_FIRST_RUN = QStringLiteral("first_run");
9696
const QString MainWindow::SETTING_UI_EDIT_MODE = QStringLiteral("ui_edit_mode");
97+
const QString MainWindow::SETTING_UI_THEME = QStringLiteral("ui_theme");
9798
const QString MainWindow::SETTING_PAUSE_FOCUS = QStringLiteral("pause_on_focus_change");
9899
const QString MainWindow::SETTING_SAVE_ON_CLOSE = QStringLiteral("save_on_close");
99100
const QString MainWindow::SETTING_RESTORE_ON_OPEN = QStringLiteral("restore_on_open");
@@ -1277,6 +1278,7 @@ void MainWindow::saveSettings() {
12771278
m_config->setValue(SETTING_WINDOW_VISUALIZER_CONFIG, m_docksVisualizerConfig);
12781279
m_config->setValue(SETTING_WINDOW_KEYHISTORY_DOCKS, m_docksKeyHistory);
12791280
m_config->setValue(SETTING_WINDOW_KEYHISTORY_CONFIG, QVariant::fromValue(m_docksKeyHistorySize));
1281+
m_config->setValue(SETTING_UI_THEME, static_cast<int>(m_themePreference));
12801282

12811283
// Disassembly Goto history
12821284
{

0 commit comments

Comments
 (0)