Dark theme setting

This commit is contained in:
Ada 2025-04-19 03:44:24 +10:00 committed by Ada
parent 4cbde7e3f0
commit d4b0318fe6
6 changed files with 82 additions and 0 deletions

View file

@ -21,6 +21,7 @@
#include <QtNetwork/QLocalServer>
#include <QtQuick/QQuickWindow>
#include <QWidget>
#include <QStyle>
#include <AccountManager.h>
#include <AddressManager.h>
@ -231,6 +232,7 @@ Application::Application(
_constrainToolbarPosition("toolbar/constrainToolbarToCenterX", true),
_awayStateWhenFocusLostInVREnabled("awayStateWhenFocusLostInVREnabled", DEFAULT_AWAY_STATE_WHEN_FOCUS_LOST_IN_VR_ENABLED),
_preferredCursor("preferredCursor", DEFAULT_CURSOR_NAME),
_darkTheme("darkTheme", false),
_miniTabletEnabledSetting("miniTabletEnabled", DEFAULT_MINI_TABLET_ENABLED),
// Entities
_maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS),
@ -246,6 +248,9 @@ Application::Application(
qInstallMessageHandler(messageHandler);
DependencyManager::set<PathUtils>();
_startupThemeStyleName = qApp->style()->objectName();
_startupThemePalette = qApp->palette();
}
Application::~Application() {
@ -1260,6 +1265,9 @@ void Application::loadSettings(const QCommandLineParser& parser) {
externalResource->setBase(bucket, url.get());
}
// the setter function isn't called, so update the theme colors now
updateThemeColors();
_settingsLoaded = true;
}

View file

@ -386,6 +386,8 @@ signals:
void miniTabletEnabledChanged(bool enabled);
void awayStateWhenFocusLostInVRChanged(bool enabled);
void darkThemePreferenceChanged(bool useDarkTheme);
public slots:
void updateThreadPoolCount() const;
@ -460,6 +462,9 @@ public slots:
const QString getPreferredCursor() const { return _preferredCursor.get(); }
void setPreferredCursor(const QString& cursor);
bool getDarkThemePreference() const { return _darkTheme.get(); }
void setDarkThemePreference(bool value);
/**
* @brief Shows/hides VR keyboard input for Overlay windows
*
@ -799,9 +804,17 @@ private:
Setting::Handle<bool> _constrainToolbarPosition;
Setting::Handle<bool> _awayStateWhenFocusLostInVREnabled;
Setting::Handle<QString> _preferredCursor;
// TODO Qt6: Qt5 doesn't have anything for system theme preferences, Qt6.5+ does
Setting::Handle<bool> _darkTheme;
Setting::Handle<bool> _miniTabletEnabledSetting;
Setting::Handle<bool> _keepLogWindowOnTop { "keepLogWindowOnTop", false };
// to allow switching between system/light and dark theme without needing a restart
QString _startupThemeStyleName;
QPalette _startupThemePalette;
void updateThemeColors();
// Plugins
DisplayPluginPointer _displayPlugin;

View file

@ -16,6 +16,7 @@
#include "Application.h"
#include <QtQml/QQmlContext>
#include <QStyleFactory>
#include <AddressManager.h>
#include <AnimationCacheScriptingInterface.h>
@ -792,6 +793,39 @@ void Application::setPreferredCursor(const QString& cursorName) {
showCursor(Cursor::Manager::lookupIcon(_preferredCursor.get()));
}
void Application::updateThemeColors() {
if (_darkTheme.get()) {
qApp->setStyle(QStyleFactory::create("Fusion")); // builtin style that always exists
auto palette = QPalette(
QColor(224, 224, 244), // windowText
QColor(48, 48, 48), // button
QColor(72, 72, 72), // light
QColor(24, 24, 24), // dark
QColor(48, 48, 48), // mid
QColor(244, 224, 224), // text
QColor(255, 255, 255), // brightText
QColor(48, 48, 48), // base
QColor(48, 48, 48) // window
);
qApp->setPalette(palette);
qApp->getPrimaryMenu()->setPalette(palette); // weird Qt bug workaround
} else {
qApp->setStyle(QStyleFactory::create(_startupThemeStyleName));
qApp->setPalette(_startupThemePalette);
qApp->getPrimaryMenu()->setPalette(_startupThemePalette); // weird Qt bug workaround
}
}
void Application::setDarkThemePreference(bool value) {
bool previousValue = _darkTheme.get();
if (value == previousValue) { return; }
_darkTheme.set(value);
updateThemeColors();
emit darkThemePreferenceChanged(value);
}
void Application::showVRKeyboardForHudUI(bool show) {
if (show) {
DependencyManager::get<Keyboard>()->setRaised(true, true);

View file

@ -62,6 +62,10 @@ WindowScriptingInterface::WindowScriptingInterface() {
connect(qApp, &Application::interstitialModeChanged, [this] (bool interstitialMode) {
emit interstitialModeChanged(interstitialMode);
});
connect(qApp, &Application::darkThemePreferenceChanged, [this](bool useDarkTheme) {
emit darkThemePreferenceChanged(useDarkTheme);
});
}
WindowScriptingInterface::~WindowScriptingInterface() {
@ -672,3 +676,7 @@ void WindowScriptingInterface::openWebBrowser(const QString& url) {
}
});
}
bool WindowScriptingInterface::getDarkThemePreference() {
return qApp->getDarkThemePreference();
}

View file

@ -626,6 +626,13 @@ public slots:
*/
void openWebBrowser(const QString& url = "");
/*@jsdoc
* Returns true if the user prefers a dark UI theme.
* @function Window.getDarkThemePreference
* @returns {boolean}
*/
bool getDarkThemePreference();
private slots:
void onWindowGeometryChanged(const QRect& geometry);
@ -841,6 +848,12 @@ signals:
*/
void minimizedChanged(bool isMinimized);
/*@jsdoc
* @function Window.darkThemePreferenceChanged
* @returns {boolean}
*/
void darkThemePreferenceChanged(bool useDarkTheme);
private:
QString getPreviousBrowseLocation() const;
void setPreviousBrowseLocation(const QString& location);

View file

@ -138,6 +138,12 @@ void setupPreferences() {
// UI
static const QString UI_CATEGORY { "User Interface" };
{
auto getter = []()->bool { return qApp->getDarkThemePreference(); };
auto setter = [](bool value) { qApp->setDarkThemePreference(value); };
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use dark theme", getter, setter));
}
{
auto getter = []()->bool { return qApp->getSettingConstrainToolbarPosition(); };
auto setter = [](bool value) { qApp->setSettingConstrainToolbarPosition(value); };