Skip to content

Commit

Permalink
FEAT(client): Automatically sync theme with OS color scheme
Browse files Browse the repository at this point in the history
This update introduces an automatic theme switch that changes based on the OS color scheme at startup and during runtime. This feature is implemented for Qt 6.2 and includes compatibility for Qt 6.5 once Mumble upgrades.

Implements mumble-voip#6515
  • Loading branch information
jakub2682-tuke committed Oct 28, 2024
1 parent 70dea60 commit be5a104
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 2 deletions.
91 changes: 90 additions & 1 deletion src/mumble/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@
# include <dbt.h>
#endif


#include <QFile>
#include <QGuiApplication>
#include <QPalette>
#include <QSettings>
#include <QStyleHints>
#include <QTextStream>



#include <algorithm>

MessageBoxEvent::MessageBoxEvent(QString m) : QEvent(static_cast< QEvent::Type >(MB_QEVENT)) {
Expand Down Expand Up @@ -117,7 +127,9 @@ MainWindow::MainWindow(QWidget *p)
else
SvgIcon::addSvgPixmapsToIcon(qiIcon, QLatin1String("skin:mumble.svg"));
#else
{ SvgIcon::addSvgPixmapsToIcon(qiIcon, QLatin1String("skin:mumble.svg")); }
{
SvgIcon::addSvgPixmapsToIcon(qiIcon, QLatin1String("skin:mumble.svg"));
}

// Set application icon except on MacOSX, where the window-icon
// shown in the title-bar usually serves as a draggable version of the
Expand Down Expand Up @@ -198,8 +210,81 @@ MainWindow::MainWindow(QWidget *p)
&PluginManager::on_serverSynchronized);

QAccessible::installFactory(AccessibleSlider::semanticSliderFactory);

// Theme application
applyTheme(); // Apply the light or dark theme during initialization
}

void MainWindow::applyTheme() {
boost::optional< ThemeInfo::StyleInfo > configuredStyle = Themes::getConfiguredStyle(Global::get().s);

QString lightThemePath = ":/themes/Default/Lite.qss"; // Default light theme path
QString darkThemePath = ":/themes/Default/Dark.qss"; // Default dark theme path

if (configuredStyle) {
if (configuredStyle->name == "Auto") {
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
auto colorScheme = QGuiApplication::styleHints()->colorScheme();
if (colorScheme == Qt::ColorScheme::Dark) {
setStyleSheet(loadStyleSheet(darkThemePath)); // Apply dark theme
} else {
setStyleSheet(loadStyleSheet(lightThemePath)); // Apply light theme
}
#else
bool isDarkTheme = detectSystemTheme();
if (isDarkTheme) {
setStyleSheet(loadStyleSheet(darkThemePath)); // Apply dark theme
} else {
setStyleSheet(loadStyleSheet(lightThemePath)); // Apply light theme
}
#endif
} else if (configuredStyle->themeName == "none") {
setStyleSheet(""); // Clear the stylesheet if "None" is selected
} else {
QString themePath =
QString(":/themes/%1/%2.qss").arg(configuredStyle->themeName).arg(configuredStyle->name);
setStyleSheet(loadStyleSheet(themePath)); // Apply the selected theme and style
}
} else {
// Handle the case where no theme is configured (fallback to default behavior)
setStyleSheet(loadStyleSheet(lightThemePath)); // Default to light theme
}
}

bool MainWindow::detectSystemTheme() {
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
return false; // This should not be called for Qt 6.5 and above
#else
// Custom method to detect dark theme for Qt 6.2 and below
# ifdef Q_OS_WIN
QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
QSettings::NativeFormat);
return settings.value("AppsUseLightTheme", 1).toInt() == 0; // 0 means dark mode
# else
// Fallback for other OSes
QByteArray platform = qgetenv("QT_QPA_PLATFORM");
if (platform.contains("darkmode=2")) {
return true;
} else if (platform.contains("darkmode=1")) {
QPalette defaultPalette;
return defaultPalette.color(QPalette::WindowText).lightness()
> defaultPalette.color(QPalette::Window).lightness();
}
return false;
# endif
#endif
}

QString MainWindow::loadStyleSheet(const QString &path) {
QFile file(path);
if (file.open(QFile::ReadOnly | QFile::Text)) {
QTextStream stream(&file);
return stream.readAll(); // Return the stylesheet content
}
return QString(); // Return empty if the file cannot be loaded
}


void MainWindow::createActions() {
gsPushTalk = new GlobalShortcut(this, GlobalShortcutType::PushToTalk, tr("Push-to-Talk", "Global Shortcut"));
gsPushTalk->setObjectName(QLatin1String("PushToTalk"));
Expand Down Expand Up @@ -756,6 +841,10 @@ void MainWindow::changeEvent(QEvent *e) {
QTimer::singleShot(0, this, SLOT(hide()));
}
#endif

if (e->type() == QEvent::ThemeChange) {
applyTheme();
}
}

void MainWindow::keyPressEvent(QKeyEvent *e) {
Expand Down
4 changes: 4 additions & 0 deletions src/mumble/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ class MainWindow : public QMainWindow, public Ui::MainWindow {

void autocompleteUsername();

void applyTheme();
bool detectSystemTheme();
QString loadStyleSheet(const QString &path);

public slots:
void on_qmServer_aboutToShow();
void on_qaServerConnect_triggered(bool autoconnect = false);
Expand Down
6 changes: 5 additions & 1 deletion themes/Default/theme.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[theme]
name=Mumble
styles=dark,lite
styles=dark,lite,auto
[dark]
name=Dark
qss=Dark.qss
Expand All @@ -9,3 +9,7 @@ qss_MAC=OSX Dark.qss
name=Lite
qss=Lite.qss
qss_MAC=OSX Lite.qss
[auto]
name=Auto
qss=Lite.qss
qss_MAC=OSX Lite.qss

0 comments on commit be5a104

Please sign in to comment.