diff --git a/headers/apptheme.h b/headers/apptheme.h new file mode 100644 index 0000000..2e4bbf9 --- /dev/null +++ b/headers/apptheme.h @@ -0,0 +1,30 @@ +#ifndef APPTHEME_H +#define APPTHEME_H + +#include +#include +#include "appsettings.h" + +class AppTheme : public QObject +{ + Q_OBJECT + Q_PROPERTY(QVariant style READ getStyle NOTIFY styleChanged) +public: + explicit AppTheme(QObject *parent = nullptr); + +private: + QVariant lightTheme; + QVariant darkTheme; + + QVariant * currentTheme; + + +signals: + void styleChanged(); + +public slots: + QVariant getStyle(); + Q_INVOKABLE bool changeTheme(); +}; + +#endif // APPTHEME_H diff --git a/qml/ErrorDialog.qml b/qml/ErrorDialog.qml index fe78f43..944c942 100644 --- a/qml/ErrorDialog.qml +++ b/qml/ErrorDialog.qml @@ -42,15 +42,15 @@ Popup { background: Rectangle { radius: width * 0.5 - color: StyleSettings.viewColor - border.color: StyleSettings.lineColor + color: appTheme.style.viewColor + border.color: appTheme.style.lineColor border.width: 1 Label { id: head_text text: "error" font.pixelSize: headlineUnderline.width * 0.1 - color: enabled ? StyleSettings.textColor:StyleSettings.disabledTextColor + color: enabled ? appTheme.style.textColor:appTheme.style.disabledTextColor anchors { horizontalCenter: parent.horizontalCenter top: parent.top @@ -62,7 +62,7 @@ Popup { id: headlineUnderline height: 1 width: parent.width - color: StyleSettings.lineColor + color: appTheme.style.lineColor anchors { top: parent.top left: parent.left diff --git a/qml/SettingsDialog.qml b/qml/SettingsDialog.qml index 1d38580..bf06faa 100644 --- a/qml/SettingsDialog.qml +++ b/qml/SettingsDialog.qml @@ -66,8 +66,8 @@ Popup { background: Rectangle { radius: width * 0.5 - color: StyleSettings.viewColor - border.color: StyleSettings.lineColor + color: appTheme.style.viewColor + border.color: appTheme.style.lineColor border.width: 0 RectangularGlow { @@ -95,7 +95,7 @@ Popup { height: header.height width: header.width - property color color: StyleSettings.viewColor + property color color: appTheme.style.viewColor onColorChanged: { requestPaint() @@ -131,7 +131,7 @@ Popup { id: head_text text: options_stack.currentItem.title font.pixelSize: headlineUnderline.width * 0.05 - color: enabled ? StyleSettings.textColor:StyleSettings.disabledTextColor + color: enabled ? appTheme.style.textColor:appTheme.style.disabledTextColor anchors { horizontalCenter: parent.horizontalCenter top: parent.top @@ -144,7 +144,7 @@ Popup { id: headlineUnderline height: 1 width: parent.width - color: StyleSettings.lineColor + color: appTheme.style.lineColor visible: false anchors { top: parent.top @@ -172,8 +172,8 @@ Popup { glowOpacity: Math.pow( root.opacity, 100 ) - backgroundColor: StyleSettings.buttonColor - image: StyleSettings.backIcon + backgroundColor: appTheme.style.buttonColor + image: appTheme.style.backIcon onClicked: { options_stack.depth > 1 ? options_stack.pop():root.close() @@ -245,12 +245,12 @@ Popup { contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } onClicked: { - StyleSettings.setTheme() + appTheme.changeTheme() } } @@ -262,7 +262,7 @@ Popup { contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } @@ -335,7 +335,7 @@ Popup { text: qsTr("say 'ready'") contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } @@ -358,7 +358,7 @@ Popup { text: qsTr("delay (ms)") contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } @@ -389,7 +389,7 @@ Popup { text: qsTr("say\n'at your marks'") contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } @@ -411,7 +411,7 @@ Popup { text: qsTr("delay (ms)") contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } diff --git a/qml/SpeedTimer.qml b/qml/SpeedTimer.qml index a9d0025..36b930d 100644 --- a/qml/SpeedTimer.qml +++ b/qml/SpeedTimer.qml @@ -39,7 +39,7 @@ Item { anchors.centerIn: parent font.pixelSize: parent.pixelSize elide: parent.elide - color: StyleSettings.textColor + color: appTheme.style.textColor Behavior on text { enabled: timerBackend.state !== "RUNNING" FadeAnimation { diff --git a/qml/components/ConnectionDelegate.qml b/qml/components/ConnectionDelegate.qml index 3d63ed8..28962c7 100644 --- a/qml/components/ConnectionDelegate.qml +++ b/qml/components/ConnectionDelegate.qml @@ -21,7 +21,7 @@ ItemDelegate { contentItem: Text { text: parent.text - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: options_stack.text_pixelSize } diff --git a/qml/components/NextPageDelegate.qml b/qml/components/NextPageDelegate.qml index 2fe84af..f6b4423 100644 --- a/qml/components/NextPageDelegate.qml +++ b/qml/components/NextPageDelegate.qml @@ -6,7 +6,7 @@ ItemDelegate { id: control text: "" font.pixelSize: options_stack.text_pixelSize - property color textColor: StyleSettings.textColor + property color textColor: appTheme.style.textColor contentItem: Text { text: parent.text @@ -18,7 +18,7 @@ ItemDelegate { Image { id: forwardImage - source: StyleSettings.backIcon + source: appTheme.style.backIcon rotation: 180 height: control.font.pixelSize width: height diff --git a/qml/main.qml b/qml/main.qml index f80c3c4..195a132 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -35,10 +35,6 @@ Window { property date currentTime: new Date() property int millis: 0 - onBeforeRendering: { - StyleSettings.refreshTheme() - } - Page { id:root anchors.fill: parent @@ -53,7 +49,7 @@ Window { Rectangle { id: backgroundRect anchors.fill: parent - color: StyleSettings.backgroundColor + color: appTheme.style.backgroundColor } SpeedBackend { @@ -81,6 +77,10 @@ Window { } } + AppTheme { + id: appTheme + } + /*------------------------ Timer text an upper line ------------------------*/ @@ -107,14 +107,14 @@ Window { Rectangle { anchors.fill: parent - color: StyleSettings.menuColor + color: appTheme.style.menuColor } Label { id: timer_1 anchors.centerIn: parent elide: "ElideRight" - color: StyleSettings.textColor + color: appTheme.style.textColor font.pixelSize: 100 @@ -133,7 +133,7 @@ Window { property int rtime: speedBackend.timers[0]["reacttime"] text: qsTr("reaction time (ms): ") + Math.round(rtime) opacity: (root.state === "RUNNING" || root.state === "STOPPED") && rtime !== 0 ? 1:0 - color: StyleSettings.textColor + color: appTheme.style.textColor anchors { horizontalCenter: parent.horizontalCenter top: timer_1.bottom @@ -146,7 +146,7 @@ Window { id: upper_line width: root.landscape() ? 1:parent.width height: root.landscape() ? parent.height:1 - color: StyleSettings.lineColor + color: appTheme.style.lineColor anchors.left: root.landscape() ? time_container.right:parent.left anchors.top: root.landscape() ? parent.top:time_container.bottom anchors.bottom: root.landscape() ? parent.bottom:undefined @@ -179,11 +179,10 @@ Window { anchors.centerIn: parent font.pixelSize: parent.height * 0.16 font.family: "Helvetica" - color: enabled ? StyleSettings.textColor:StyleSettings.disabledTextColor + color: enabled ? appTheme.style.textColor:appTheme.style.disabledTextColor } - - backgroundColor: StyleSettings.buttonColor + backgroundColor: appTheme.style.buttonColor Behavior on text { //animate a text change @@ -267,10 +266,10 @@ Window { anchors.centerIn: parent font.pixelSize: parent.height * 0.16 font.family: "Helvetica" - color: StyleSettings.textColor + color: appTheme.style.textColor } - backgroundColor: StyleSettings.buttonColor + backgroundColor: appTheme.style.buttonColor } /*------ @@ -310,7 +309,7 @@ Window { id: lowerLine width: root.landscape() ? 1:parent.width height: root.landscape() ? parent.height:1 - color: StyleSettings.lineColor + color: appTheme.style.lineColor anchors.right: root.landscape() ? menu_container.left:parent.right anchors.bottom: root.landscape() ? parent.bottom:menu_container.top anchors.top: root.landscape() ? parent.top:undefined @@ -341,7 +340,7 @@ Window { Rectangle { id: lowerMenuBackground anchors.fill: parent - color: StyleSettings.menuColor + color: appTheme.style.menuColor } FancyButton { @@ -369,9 +368,9 @@ Window { settingsDialog.open() } - image: StyleSettings.settIcon + image: appTheme.style.settIcon - backgroundColor: parent.pressed ? StyleSettings.buttonPressedColor:StyleSettings.buttonColor + backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor } diff --git a/qml/qml.qrc b/qml/qml.qrc index b006d3e..8aec386 100644 --- a/qml/qml.qrc +++ b/qml/qml.qrc @@ -7,10 +7,6 @@ components/SimpleIndicator.qml components/ConnectionDelegate.qml components/FadeAnimation.qml - styles/StyleSettings.qml - styles/qmldir - styles/Dark.js - styles/Light.js components/ConnectionIcon.qml SpeedTimer.qml components/NextPageDelegate.qml diff --git a/qml/styles/Dark.js b/qml/styles/Dark.js deleted file mode 100644 index 7205113..0000000 --- a/qml/styles/Dark.js +++ /dev/null @@ -1,31 +0,0 @@ -// Colors -var backgroundColor = "#2d3037" - -// buttons -var buttonColor = "#202227" -var buttonPressedColor = "#6ccaf2" -var buttonBorderColor = Qt.darker("grey", 2) -var disabledButtonColor = "#555555" - -var viewColor = "#202227" -var menuColor = Qt.darker("#2d3037", 1.1) - -//delegates -var delegate1Color = Qt.darker(viewColor, 1.2) -var delegate2Color = Qt.lighter(viewColor, 1.2) - -//text -var textColor = "#ffffff" -var textDarkColor = "#232323" -var disabledTextColor = "#777777" - -var sliderColor = "#6ccaf2" - -var errorColor = "#ba3f62" -var infoColor = "#3fba62" - -var lineColor = "grey" - -// Icons -var backIcon = "qrc:/graphics/icons/back.png" -var settIcon = "qrc:/graphics/icons/settings.png" diff --git a/qml/styles/Light.js b/qml/styles/Light.js deleted file mode 100644 index fc58b41..0000000 --- a/qml/styles/Light.js +++ /dev/null @@ -1,31 +0,0 @@ -// Colors -var backgroundColor = "white" - -// buttons -var buttonColor = "white" -var buttonPressedColor = "lightgrey" -var buttonBorderColor = "grey" -var disabledButtonColor = Qt.darker("white", 1.2) - -var viewColor = "white" -var menuColor = Qt.darker("white", 1.03) - -//delegates -var delegate1Color = Qt.darker(viewColor, 1.2) -var delegate2Color = Qt.lighter(viewColor, 1.2) - -//text -var textColor = "black" -var textDarkColor = "#232323" -var disabledTextColor = "grey" - -var sliderColor = "#6ccaf2" - -var errorColor = "#ba3f62" -var infoColor = "#3fba62" - -var lineColor = "grey" - -// Icons -var backIcon = "qrc:/graphics/icons/back_black.png" -var settIcon = "qrc:/graphics/icons/settings_black.png" diff --git a/qml/styles/StyleSettings.qml b/qml/styles/StyleSettings.qml deleted file mode 100644 index 329346a..0000000 --- a/qml/styles/StyleSettings.qml +++ /dev/null @@ -1,155 +0,0 @@ -/*************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of the QtBluetooth module of the Qt Toolkit. -** -**$QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -pragma Singleton -import QtQuick 2.5 -import "./Dark.js" as Dark -import "./Light.js" as Light - -Item { - property int wHeight - property int wWidth - property var theme: _cppAppSettings.loadSetting("theme") === "Light" ? Light: - _cppAppSettings.loadSetting("theme") === "Dark" ? Dark:null - // Colors - readonly property color backgroundColor: theme.backgroundColor - - // buttons - readonly property color buttonColor: theme.buttonColor - readonly property color buttonPressedColor: theme.buttonPressedColor - readonly property color buttonBorderColor: theme.buttonBorderColor - readonly property color disabledButtonColor: theme.disabledButtonColor - - readonly property color viewColor: theme.viewColor - readonly property color menuColor: theme.menuColor - - //delegates - readonly property color delegate1Color: theme.delegate1Color - readonly property color delegate2Color: theme.delegate2Color - - //text - readonly property color textColor: theme.textColor - readonly property color textDarkColor: theme.textDarkColor - readonly property color disabledTextColor: theme.disabledTextColor - - readonly property color sliderColor: theme.sliderColor - - readonly property color errorColor: theme.errorColor - readonly property color infoColor: theme.infoColor - - readonly property color lineColor: theme.lineColor - - // Icons - readonly property string backIcon: theme.backIcon - readonly property string settIcon: theme.settIcon - - // Font sizes - property real microFontSize: hugeFontSize * 0.2 - property real tinyFontSize: hugeFontSize * 0.4 - property real smallTinyFontSize: hugeFontSize * 0.5 - property real smallFontSize: hugeFontSize * 0.6 - property real mediumFontSize: hugeFontSize * 0.7 - property real bigFontSize: hugeFontSize * 0.8 - property real largeFontSize: hugeFontSize * 0.9 - property real hugeFontSize: (wWidth + wHeight) * 0.03 - property real giganticFontSize: (wWidth + wHeight) * 0.04 - - // Some other values - property real fieldHeight: wHeight * 0.08 - property real fieldMargin: fieldHeight * 0.5 - property real buttonHeight: wHeight * 0.08 - property real buttonRadius: buttonHeight * 0.1 - - function refreshTheme(){ - switch(_cppAppSettings.loadSetting("theme")){ - case "Dark": - theme = Light - break - case "Light": - theme = Dark - break - default: - theme = Light - break - } - } - - - - // Some help functions - function widthForHeight(h, ss) - { - return h/ss.height * ss.width; - } - - function heightForWidth(w, ss) - { - return w/ss.width * ss.height; - } - - function setTheme() - { - switch(_cppAppSettings.loadSetting("theme")){ - case "Dark": - _cppAppSettings.writeSetting("theme", "Light") - theme = Light - break - case "Light": - _cppAppSettings.writeSetting("theme", "Dark") - theme = Dark - break - default: - _cppAppSettings.writeSetting("theme", "Light") - theme = Light - break - } - } - -} diff --git a/qml/styles/qmldir b/qml/styles/qmldir deleted file mode 100644 index 8cc5d4d..0000000 --- a/qml/styles/qmldir +++ /dev/null @@ -1 +0,0 @@ -singleton StyleSettings 1.0 StyleSettings.qml diff --git a/sources/apptheme.cpp b/sources/apptheme.cpp new file mode 100644 index 0000000..ae45771 --- /dev/null +++ b/sources/apptheme.cpp @@ -0,0 +1,105 @@ +#include "headers/apptheme.h" + +AppTheme::AppTheme(QObject *parent) : QObject(parent) +{ + + QVariantMap tmpDarkTheme = { + {"backgroundColor", "#2d3037"}, + + {"buttonColor", "#202227"}, + {"buttonPressedColor", "#6ccaf2"}, + {"buttonBorderColor", "grey"}, + {"disabledButtonColor", "#555555"}, + + {"viewColor", "#202227"}, + {"menuColor", "#292b32"}, + + {"delegate1Color", "#202227"}, + {"delegate2Color", "#202227"}, + + {"textColor", "#ffffff"}, + {"textDarkColor", "#232323"}, + {"disabledTextColor", "#777777"}, + + {"sliderColor", "#6ccaf2"}, + + {"errorColor", "#ba3f62"}, + {"infoColor", "#3fba62"}, + + {"lineColor", "grey"}, + + {"backIcon", "qrc:/graphics/icons/back.png"}, + {"settIcon", "qrc:/graphics/icons/settings.png"} + + }; + this->darkTheme = tmpDarkTheme; + + QVariantMap tmpLightTheme = { + {"backgroundColor", "white"}, + + {"buttonColor", "white"}, + {"buttonPressedColor", "lightgrey"}, + {"buttonBorderColor", "grey"}, + {"disabledButtonColor", "#d5d5d5"}, + + {"viewColor", "white"}, + {"menuColor", "#f8f8f8"}, + + {"delegate1Color", "#202227"}, + {"delegate2Color", "#202227"}, + + {"textColor", "black"}, + {"textDarkColor", "#232323"}, + {"disabledTextColor", "grey"}, + + {"sliderColor", "#6ccaf2"}, + + {"errorColor", "#ba3f62"}, + {"infoColor", "#3fba62"}, + + {"lineColor", "grey"}, + + {"backIcon", "qrc:/graphics/icons/back_black.png"}, + {"settIcon", "qrc:/graphics/icons/settings_black.png"} + + }; + this->lightTheme = tmpLightTheme; + + QString currentThemeString = pGlobalAppSettings->loadSetting("theme"); + + if(currentThemeString == "Light"){ + this->currentTheme = &this->lightTheme; + } + else if (currentThemeString == "Dark") { + this->currentTheme = &this->darkTheme; + } + else { + this->currentTheme = &this->lightTheme; + } +} + +QVariant AppTheme::getStyle() { + return *this->currentTheme; +} + +bool AppTheme::changeTheme() { + QString currentThemeString = pGlobalAppSettings->loadSetting("theme"); + QString newThemeString = "Light"; + + if(currentThemeString == "Light"){ + this->currentTheme = &this->darkTheme; + newThemeString = "Dark"; + + } + else if (currentThemeString == "Dark") { + this->currentTheme = &this->lightTheme; + newThemeString = "Light"; + } + else { + this->currentTheme = &this->lightTheme; + } + + pGlobalAppSettings->writeSetting("theme", newThemeString); + + emit this->styleChanged(); +} diff --git a/sources/main.cpp b/sources/main.cpp index 4b74b85..5e51af7 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -54,6 +54,7 @@ #include "headers/baseconn.h" #include "headers/speedtimer.h" #include "headers/climbingrace.h" +#include "headers/apptheme.h" #include static void connectToDatabase() @@ -121,6 +122,7 @@ int main(int argc, char *argv[]) //qmlRegisterType("com.itsblue.speedclimbingstopwatch", 1, 0, "SpeedTimerBackend"); qmlRegisterType("com.itsblue.speedclimbingstopwatch", 2, 0, "SpeedBackend"); + qmlRegisterType("com.itsblue.speedclimbingstopwatch", 2, 0, "AppTheme"); //setup translation engine //to the language of the system diff --git a/speedclimbing_stopwatch.pro b/speedclimbing_stopwatch.pro index fe90887..f7d5756 100644 --- a/speedclimbing_stopwatch.pro +++ b/speedclimbing_stopwatch.pro @@ -26,7 +26,8 @@ SOURCES += \ sources/appsettings.cpp \ sources/baseconn.cpp \ sources/speedtimer.cpp \ - sources/climbingrace.cpp + sources/climbingrace.cpp \ + sources/apptheme.cpp HEADERS += \ headers/sqlstoragemodel.h \ @@ -34,7 +35,8 @@ HEADERS += \ headers/appsettings.h \ headers/baseconn.h \ headers/speedtimer.h \ - headers/climbingrace.h + headers/climbingrace.h \ + headers/apptheme.h RESOURCES += \ shared.qrc \