Skip to content

Commit

Permalink
qml: introduce ThemeManager
Browse files Browse the repository at this point in the history
  • Loading branch information
jarolrod committed May 31, 2023
1 parent af0ddf6 commit 9918383
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ QT_MOC_CPP = \
qml/models/moc_options_model.cpp \
qml/models/moc_peerlistsortproxy.cpp \
qml/moc_appmode.cpp \
qml/moc_thememanager.cpp \
qt/moc_addressbookpage.cpp \
qt/moc_addresstablemodel.cpp \
qt/moc_askpassphrasedialog.cpp \
Expand Down Expand Up @@ -124,6 +125,7 @@ BITCOIN_QT_H = \
qml/appmode.h \
qml/bitcoin.h \
qml/imageprovider.h \
qml/thememanager.h \
qml/util.h \
qt/addressbookpage.h \
qt/addresstablemodel.h \
Expand Down Expand Up @@ -309,6 +311,7 @@ BITCOIN_QML_BASE_CPP = \
qml/models/options_model.cpp \
qml/models/peerlistsortproxy.cpp \
qml/imageprovider.cpp \
qml/thememanager.cpp \
qml/util.cpp

QML_RES_FONTS = \
Expand Down
3 changes: 3 additions & 0 deletions src/qml/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <qml/models/options_model.h>
#include <qml/models/peerlistsortproxy.h>
#include <qml/imageprovider.h>
#include <qml/thememanager.h>
#include <qml/util.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
Expand Down Expand Up @@ -232,6 +233,7 @@ int QmlGuiMain(int argc, char* argv[])
QObject::connect(&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
// QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException);

ThemeManager theme_manager{};
NetworkTrafficTower network_traffic_tower{node_model};

ChainModel chain_model{*chain};
Expand Down Expand Up @@ -264,6 +266,7 @@ int QmlGuiMain(int argc, char* argv[])
engine.rootContext()->setContextProperty("chainModel", &chain_model);
engine.rootContext()->setContextProperty("peerTableModel", &peer_model);
engine.rootContext()->setContextProperty("peerListModelProxy", &peer_model_sort_proxy);
engine.rootContext()->setContextProperty("themeManager", &theme_manager);

OptionsQmlModel options_model{*node};
engine.rootContext()->setContextProperty("optionsModel", &options_model);
Expand Down
40 changes: 36 additions & 4 deletions src/qml/components/ThemeSettings.qml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ ColumnLayout {
header: qsTr("Light")
actionItem: Button {
anchors.centerIn: parent
visible: !Theme.dark
visible: !Theme.manualDark && Theme.manualTheme
icon.source: "image://images/check"
icon.color: Theme.color.neutral9
icon.height: 24
Expand All @@ -33,7 +33,8 @@ ColumnLayout {
}
}
onClicked: {
Theme.dark = false
Theme.manualTheme = true;
Theme.manualDark = false;
}
}
Separator { Layout.fillWidth: true }
Expand All @@ -42,7 +43,7 @@ ColumnLayout {
header: qsTr("Dark")
actionItem: Button {
anchors.centerIn: parent
visible: Theme.dark
visible: Theme.manualDark && Theme.manualTheme
icon.source: "image://images/check"
icon.color: Theme.color.neutral9
icon.height: 24
Expand All @@ -54,7 +55,38 @@ ColumnLayout {
}
}
onClicked: {
Theme.dark = true;
Theme.manualTheme = true;
Theme.manualDark = true;
}
}
Separator { Layout.fillWidth: true }
Setting {
id: systemThemeSetting
property bool systemThemeAvailable: Theme.systemThemeAvailable
Layout.fillWidth: true
header: qsTr("System")
actionItem: Button {
anchors.centerIn: parent
visible: !Theme.manualTheme
icon.source: "image://images/check"
icon.color: Theme.color.neutral9
icon.height: 24
icon.width: 24
background: null

Behavior on icon.color {
ColorAnimation { duration: 150 }
}
}
Component.onCompleted: {
if (systemThemeAvailable) {
systemThemeSetting.state = "FILLED"
} else {
systemThemeSetting.state = "DISABLED"
}
}
onClicked: {
Theme.manualTheme = false
}
}
}
21 changes: 20 additions & 1 deletion src/qml/controls/Theme.qml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,38 @@ import QtQuick 2.15
import QtQuick.Controls 2.15
import Qt.labs.settings 1.0

import org.bitcoincore.qt 1.0

Control {
id: root
property bool dark: true
property bool dark: manualTheme ? manualDark : themeManager.darkMode
property bool systemThemeAvailable: themeManager.systemThemeAvailable
property bool manualTheme: false
property bool manualDark: true
property real blockclocksize: (5/12)
readonly property ColorSet color: dark ? darkColorSet : lightColorSet
readonly property ImageSet image: dark ? darkImageSet : lightImageSet

Settings {
id: settings
property alias dark: root.dark
property alias manualTheme: root.manualTheme
property alias manualDark: root.manualDark
property alias blockclocksize: root.blockclocksize
}

SystemPalette {
id: systemColor

onBaseChanged: {
themeManager.systemBaseColor = systemColor.base
}
}

Component.onCompleted: {
themeManager.systemBaseColor = systemColor.base
}

component ColorSet: QtObject {
required property color white
required property color background
Expand Down
48 changes: 48 additions & 0 deletions src/qml/thememanager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <qml/thememanager.h>

ThemeManager::ThemeManager(QObject* parent)
: QObject(parent)
{
}

void ThemeManager::setSystemBaseColor(QColor base_color)
{
// Convert QColor's 8-bit RGB values to linear RGB values
double linearR = base_color.redF();
double linearG = base_color.greenF();
double linearB = base_color.blueF();

// Constants for the luminance formula
const double RED_FACTOR = 0.2126;
const double GREEN_FACTOR = 0.7152;
const double BLUE_FACTOR = 0.0722;

// Calculate luminance using the formula
double luminance = RED_FACTOR * linearR + GREEN_FACTOR * linearG + BLUE_FACTOR * linearB;

if (luminance <= 0.5) {
m_dark_mode = true;
} else {
m_dark_mode = false;
}

m_system_base_color = base_color;

#ifdef Q_OS_MAC
setSystemThemeAvailable(true);
#endif

Q_EMIT darkModeChanged();
}

void ThemeManager::setSystemThemeAvailable(bool available)
{
if (m_system_theme_available != available) {
m_system_theme_available = available;
Q_EMIT systemThemeAvailableChanged();
}
}
41 changes: 41 additions & 0 deletions src/qml/thememanager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2023 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_QML_THEMEMANAGER_H
#define BITCOIN_QML_THEMEMANAGER_H

#include <QObject>
#include <QColor>
#include <QProcess>


class ThemeManager : public QObject
{
Q_OBJECT
Q_PROPERTY(bool darkMode READ darkMode NOTIFY darkModeChanged)
Q_PROPERTY(QColor systemBaseColor READ systemBaseColor WRITE setSystemBaseColor)
Q_PROPERTY(bool systemThemeAvailable READ systemThemeAvailable WRITE setSystemThemeAvailable NOTIFY systemThemeAvailableChanged)

public:
explicit ThemeManager(QObject* parent = nullptr);

bool darkMode() const { return m_dark_mode; };
QColor systemBaseColor() const { return m_system_base_color; };
bool systemThemeAvailable() const { return m_system_theme_available; };

public Q_SLOTS:
void setSystemBaseColor(QColor base_color);
void setSystemThemeAvailable(bool available);

Q_SIGNALS:
void darkModeChanged();
void systemThemeAvailableChanged();

private:
bool m_dark_mode{ true };
QColor m_system_base_color;
bool m_system_theme_available{ false };
};

#endif // BITCOIN_QML_THEMEMANAGER_H

0 comments on commit 9918383

Please sign in to comment.