First commit

This commit is contained in:
Stefano Moretti
2021-12-18 19:11:48 +01:00
commit 32a567a950
38 changed files with 2620 additions and 0 deletions

28
qml/BaseUI/App.qml Normal file
View File

@ -0,0 +1,28 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
ApplicationWindow {
property alias pageStack: stackView
property alias initialPage: stackView.initialItem
visible: true
locale: Qt.locale("en_US")
header: stackView.currentItem ? stackView.currentItem.appToolBar : null
StackView {
id: stackView
anchors.fill: parent
onCurrentItemChanged: {
// make sure that the phone physical back button will get key events
currentItem.forceActiveFocus()
}
}
Material.primary: Style.primaryColor
Material.accent: Style.accentColor
Material.theme: Style.isDarkTheme ? Material.Dark : Material.Light
}

View File

@ -0,0 +1,45 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import BaseUI 1.0
Page {
id: root
property StackView stack: StackView.view
property alias appToolBar: appToolBar
property alias leftButton: appToolBar.leftButton
property alias rightButtons: appToolBar.rightButtons
function pop(item, operation) {
if (stack.currentItem != root)
return false
return stack.pop(item, operation)
}
function back() {
pop()
}
Keys.onBackPressed: function(event) {
if (stack.depth > 1) {
event.accepted = true
back()
} else {
Qt.quit()
}
}
Action {
id: backAction
icon.source: Icons.arrow_back
onTriggered: root.back()
}
AppToolBar {
id: appToolBar
title: root.title
leftButton: stack && stack.depth > 1 ? backAction : null
}
}

42
qml/BaseUI/AppToolBar.qml Normal file
View File

@ -0,0 +1,42 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
ToolBar {
property Action leftButton
property list<Action> rightButtons
property alias title: titleLabel.text
RowLayout {
focus: false
spacing: 0
anchors { fill: parent; leftMargin: 4; rightMargin: 4 }
ToolButton {
icon.source: leftButton ? leftButton.icon.source : ""
icon.color: Style.textOnPrimary
focusPolicy: Qt.NoFocus
opacity: Style.opacityTitle
enabled: leftButton && leftButton.enabled
onClicked: leftButton.trigger()
}
LabelTitle {
id: titleLabel
elide: Label.ElideRight
color: Style.textOnPrimary
Layout.fillWidth: true
}
Repeater {
model: rightButtons.length
delegate: ToolButton {
icon.source: rightButtons[index].icon.source
icon.color: Style.textOnPrimary
focusPolicy: Qt.NoFocus
opacity: Style.opacityTitle
enabled: rightButtons[index].enabled
onClicked: rightButtons[index].trigger()
}
}
}
}

36
qml/BaseUI/ButtonFlat.qml Normal file
View File

@ -0,0 +1,36 @@
// ekke (Ekkehard Gentz) @ekkescorner
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Button {
id: button
property alias textColor: buttonText.color
focusPolicy: Qt.NoFocus
leftPadding: 6
rightPadding: 6
Layout.minimumWidth: 88
contentItem: Text {
id: buttonText
text: button.text
opacity: enabled ? 1.0 : 0.3
color: Style.flatButtonTextColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
font.capitalization: Font.AllUppercase
font.weight: Font.Medium
}
background: Rectangle {
id: buttonBackground
implicitHeight: 48
color: button.pressed ? buttonText.color : "transparent"
radius: 2
opacity: button.pressed ? 0.12 : 1.0
}
}

View File

@ -0,0 +1,45 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Button {
id: button
property alias textColor: buttonText.color
property alias buttonColor: buttonBackground.color
focusPolicy: Qt.NoFocus
leftPadding: 6
rightPadding: 6
Layout.minimumWidth: 80
contentItem: Text {
id: buttonText
text: button.text
opacity: enabled ? 1.0 : 0.3
color: Style.textOnPrimary
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
font.capitalization: Font.AllUppercase
}
background: Rectangle {
id: buttonBackground
implicitHeight: 48
color: Style.primaryColor
radius: 2
opacity: button.pressed ? 0.75 : 1.0
/*
layer.enabled: true
layer.effect: DropShadow {
verticalOffset: 2
horizontalOffset: 1
color: dropShadow
samples: button.pressed ? 20 : 10
spread: 0.5
}
*/
}
}

View File

@ -0,0 +1,19 @@
// ekke (Ekkehard Gentz) @ekkescorner
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Item {
height: 8
Layout.fillWidth: true
// anchors.left: parent.left
// anchors.right: parent.right
// anchors.margins: 6
// https://www.google.com/design/spec/components/dividers.html#dividers-types-of-dividers
Rectangle {
anchors.centerIn: parent
width: parent.width
height: 1
opacity: Style.dividerOpacity
color: Style.dividerColor
}
}

9
qml/BaseUI/LabelBody.qml Normal file
View File

@ -0,0 +1,9 @@
// ekke (Ekkehard Gentz) @ekkescorner
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Label {
Layout.fillWidth: true
opacity: Style.opacityBodyAndButton
}

View File

@ -0,0 +1,10 @@
// ekke (Ekkehard Gentz) @ekkescorner
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Label {
Layout.fillWidth: true
font.pixelSize: Style.fontSizeSubheading
opacity: Style.opacitySubheading
}

10
qml/BaseUI/LabelTitle.qml Normal file
View File

@ -0,0 +1,10 @@
// ekke (Ekkehard Gentz) @ekkescorner
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Label {
Layout.fillWidth: true
font.pixelSize: Style.fontSizeTitle
opacity: Style.opacityTitle
}

View File

@ -0,0 +1,84 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
import QtQuick.Layouts 1.12
PopupModalBase {
property bool selectAccentColor: false
property color currentColor: Material.primary
property string currentColorName: colorModel.get(currentIndex).title
property int currentIndex: 0
signal colorSelected(color c)
implicitWidth: parent.width * 0.9
implicitHeight: Math.min(colorsList.contentHeight, parent.height * 0.9)
ListView {
id: colorsList
anchors.fill: parent
clip: true
delegate: ItemDelegate {
width: colorsList.width
contentItem: RowLayout {
spacing: 0
Rectangle {
visible: selectAccentColor
color: Material.primary
Layout.margins: 0
Layout.minimumHeight: 32
Layout.minimumWidth: 48
}
Rectangle {
color: Material.color(model.bg)
Layout.margins: 0
Layout.minimumHeight: 32
Layout.minimumWidth: 32
}
LabelBody {
text: model.title
Layout.leftMargin: 6
Layout.fillWidth: true
}
}
onClicked: {
colorSelected(Material.color(model.bg))
currentIndex = index
close()
}
}
model: ListModel {
id: colorModel
ListElement { title: "Material Red"; bg: Material.Red }
ListElement { title: "Material Pink"; bg: Material.Pink }
ListElement { title: "Material Purple"; bg: Material.Purple }
ListElement { title: "Material DeepPurple"; bg: Material.DeepPurple }
ListElement { title: "Material Indigo"; bg: Material.Indigo }
ListElement { title: "Material Blue"; bg: Material.Blue }
ListElement { title: "Material LightBlue"; bg: Material.LightBlue }
ListElement { title: "Material Cyan"; bg: Material.Cyan }
ListElement { title: "Material Teal"; bg: Material.Teal }
ListElement { title: "Material Green"; bg: Material.Green }
ListElement { title: "Material LightGreen"; bg: Material.LightGreen }
ListElement { title: "Material Lime"; bg: Material.Lime }
ListElement { title: "Material Yellow"; bg: Material.Yellow }
ListElement { title: "Material Amber"; bg: Material.Amber }
ListElement { title: "Material Orange"; bg: Material.Orange }
ListElement { title: "Material DeepOrange"; bg: Material.DeepOrange }
ListElement { title: "Material Brown"; bg: Material.Brown }
ListElement { title: "Material Grey"; bg: Material.Grey }
ListElement { title: "Material BlueGrey"; bg: Material.BlueGrey }
}
}
Component.onCompleted: {
for (var i = 0; i < colorModel.count; ++i) {
var tmp = colorModel.get(i)
if (Material.color(tmp.bg) === currentColor) {
currentIndex = i
return
}
}
}
}

69
qml/BaseUI/PopupError.qml Normal file
View File

@ -0,0 +1,69 @@
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
import QtQuick.Layouts 1.12
import BaseUI 1.0
Popup {
id: root
function start(errorText) {
errorLabel.text = errorText
if (!errorTimer.running)
open()
else
errorTimer.restart()
}
closePolicy: Popup.CloseOnPressOutside
bottomMargin: Screen.primaryOrientation === Qt.LandscapeOrientation ? 24 : 80
implicitWidth: Screen.primaryOrientation === Qt.LandscapeOrientation ? parent.width * 0.50 : parent.width * 0.80
x: (parent.width - implicitWidth) / 2
y: (parent.height - height)
background: Rectangle {
color: Material.color(Material.Red, Style.isDarkTheme ? Material.Shade500 : Material.Shade800)
radius: 24
opacity: Style.toastOpacity
}
onAboutToShow: errorTimer.start()
onAboutToHide: errorTimer.stop()
Timer {
id: errorTimer
interval: 3000
repeat: false
onTriggered: root.close()
}
RowLayout {
width: parent.width
Image {
id: alarmIcon
smooth: true
source: Icons.error + "color=white"
sourceSize.width: 36
sourceSize.height: 36
}
Label {
id: errorLabel
Layout.fillWidth: true
Layout.preferredWidth: 1
rightPadding: 24
font.pixelSize: 16
color: "white"
wrapMode: Label.WordWrap
}
}
}

40
qml/BaseUI/PopupInfo.qml Normal file
View File

@ -0,0 +1,40 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
PopupModalBase {
id: root
property alias text: popupLabel.text
closePolicy: Popup.CloseOnEscape
ColumnLayout {
spacing: 10
width: parent.width
LabelSubheading {
id: popupLabel
Layout.fillWidth: true
topPadding: 20
leftPadding: 8
rightPadding: 8
color: Style.popupTextColor
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
linkColor: Style.isDarkTheme ? "lightblue" : "blue"
onLinkActivated: Qt.openUrlExternally(link)
}
ButtonFlat {
Layout.alignment: Qt.AlignHCenter
text: "OK"
textColor: Style.accentColor
onClicked: root.close()
}
}
}

32
qml/BaseUI/PopupList.qml Normal file
View File

@ -0,0 +1,32 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
PopupModalBase {
id: root
property alias model: internalList.model
property alias currentIndex: internalList.currentIndex
property var delegateFunction
signal clicked(var data, int index)
implicitWidth: parent.width * 0.9
implicitHeight: Math.min(internalList.contentHeight, parent.height * 0.9)
ListView {
id: internalList
anchors.fill: parent
clip: true
highlightMoveDuration: 0
delegate: ItemDelegate {
id: internalDelegate
width: parent.width
implicitHeight: 40
text: delegateFunction(modelData)
onClicked: root.clicked(modelData, index)
}
onCurrentIndexChanged: {
internalList.positionViewAtIndex(currentIndex, ListView.Center)
}
}
}

View File

@ -0,0 +1,14 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
Popup {
id: root
modal: true
dim: true
padding: 0
x: (parent.width - width) / 2
y: (parent.height - height) / 2
implicitWidth: Math.min(contentWidth, parent.width * 0.9)
implicitHeight: Math.min(contentHeight, parent.height * 0.9)
}

51
qml/BaseUI/PopupToast.qml Normal file
View File

@ -0,0 +1,51 @@
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.Material 2.12
Popup {
id: root
function start(toastText) {
toastLabel.text = toastText
if (!toastTimer.running)
open()
else
toastTimer.restart()
}
x: (parent.width - width) / 2
y: (parent.height - height)
closePolicy: Popup.CloseOnPressOutside
bottomMargin: Screen.primaryOrientation === Qt.LandscapeOrientation ? 24 : 80
background: Rectangle {
color: Style.toastColor
radius: 24
opacity: Style.toastOpacity
}
onAboutToShow: toastTimer.start()
onAboutToHide: toastTimer.stop()
Timer {
id: toastTimer
interval: 3000
repeat: false
onTriggered: root.close()
}
Label {
id: toastLabel
width: parent.width
leftPadding: 16
rightPadding: 16
font.pixelSize: 16
color: "white"
wrapMode: Label.WordWrap
}
}

View File

@ -0,0 +1,48 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
ItemDelegate {
id: root
property alias title: titleLabel.text
property string subtitle
property string subtitlePlaceholder
property alias check: settingSwitch
Layout.fillWidth: true
contentItem: RowLayout {
ColumnLayout {
spacing: 2
LabelSubheading {
id: titleLabel
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
LabelBody {
id: subtitleLabel
visible: text.length > 0 || root.subtitlePlaceholder.length > 0
opacity: 0.6
wrapMode: Text.WordWrap
elide: Text.ElideMiddle
text: root.subtitle.length > 0 ? root.subtitle : root.subtitlePlaceholder
Layout.fillWidth: true
}
}
Item {
Layout.fillWidth: true
}
Switch {
id: settingSwitch
visible: false
}
}
}

View File

@ -0,0 +1,18 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
Label {
leftPadding: 16
topPadding: 6
bottomPadding: 6
font.bold: true
font.pixelSize: Style.fontSizeBodyAndButton
color: Style.isDarkTheme ? "white" : "black"
background: Rectangle {
color: Style.isDarkTheme ? Qt.darker("gray") : "lightgray"
}
Layout.fillWidth: true
}

56
qml/BaseUI/Style.qml Normal file
View File

@ -0,0 +1,56 @@
pragma Singleton
import QtQuick 2.12
import QtQuick.Controls.Material 2.12
QtObject {
property bool isDarkTheme: false
property color primaryColor: Material.color(Material.BlueGrey)
property color accentColor: Material.color(Material.Orange)
property color primaryDarkColor: Qt.darker(primaryColor)
// ui constants
property color textOnPrimary: isDarkColor(primaryColor) ? "#FFFFFF" : "#000000"
property color textOnAccent: isDarkColor(accentColor) ? "#FFFFFF" : "#000000"
property color textOnPrimaryDark: textOnPrimary
property color dividerColor: isDarkTheme ? "#FFFFFF" : "#000000"
property real primaryTextOpacity: isDarkTheme ? 1.0 : 0.87
property real secondaryTextOpacity: isDarkTheme ? 0.7 : 0.54
property real dividerOpacity: isDarkTheme ? 0.12 : 0.12
property color flatButtonTextColor: isDarkTheme ? "#FFFFFF" : "#424242"
property color popupTextColor: isDarkTheme ? "#FFFFFF" : "#424242"
property color toastColor: isDarkTheme ? "Darkgrey" : "#323232"
property real toastOpacity: isDarkTheme ? 0.9 : 0.75
// font sizes - defaults from Google Material Design Guide
property int fontSizeDisplay4: 112
property int fontSizeDisplay3: 56
property int fontSizeDisplay2: 45
property int fontSizeDisplay1: 34
property int fontSizeHeadline: 24
property int fontSizeTitle: 20
property int fontSizeSubheading: 16
property int fontSizeBodyAndButton: 14 // is Default
property int fontSizeCaption: 12
// fonts are grouped into primary and secondary with different Opacity
// to make it easier to get the right property,
// here's the opacity per size:
property real opacityDisplay4: secondaryTextOpacity
property real opacityDisplay3: secondaryTextOpacity
property real opacityDisplay2: secondaryTextOpacity
property real opacityDisplay1: secondaryTextOpacity
property real opacityHeadline: primaryTextOpacity
property real opacityTitle: primaryTextOpacity
property real opacitySubheading: primaryTextOpacity
// body can be both: primary or secondary text
property real opacityBodyAndButton: primaryTextOpacity
property real opacityBodySecondary: secondaryTextOpacity
property real opacityCaption: secondaryTextOpacity
function isDarkColor(color) {
var a = 1.0 - (0.299 * color.r + 0.587 * color.g + 0.114 * color.b)
return color.a > 0.0 && a >= 0.3
}
}

23
qml/BaseUI/baseui_qml.qrc Normal file
View File

@ -0,0 +1,23 @@
<RCC>
<qresource prefix="/imports/BaseUI">
<file>qmldir</file>
<file>App.qml</file>
<file>AppStackPage.qml</file>
<file>AppToolBar.qml</file>
<file>ButtonFlat.qml</file>
<file>ButtonRaised.qml</file>
<file>HorizontalDivider.qml</file>
<file>LabelBody.qml</file>
<file>LabelSubheading.qml</file>
<file>LabelTitle.qml</file>
<file>PopupColorSelection.qml</file>
<file>PopupError.qml</file>
<file>PopupInfo.qml</file>
<file>PopupList.qml</file>
<file>PopupModalBase.qml</file>
<file>PopupToast.qml</file>
<file>SettingsItem.qml</file>
<file>SettingsSectionTitle.qml</file>
<file>Style.qml</file>
</qresource>
</RCC>

21
qml/BaseUI/qmldir Normal file
View File

@ -0,0 +1,21 @@
module BaseUI
App 1.0 App.qml
AppStackPage 1.0 AppStackPage.qml
AppToolBar 1.0 AppToolBar.qml
ButtonFlat 1.0 ButtonFlat.qml
ButtonRaised 1.0 ButtonRaised.qml
HorizontalDivider 1.0 HorizontalDivider.qml
LabelBody 1.0 LabelBody.qml
LabelSubheading 1.0 LabelSubheading.qml
LabelTitle 1.0 LabelTitle.qml
PopupColorSelection 1.0 PopupColorSelection.qml
PopupError 1.0 PopupError.qml
PopupInfo 1.0 PopupInfo.qml
PopupList 1.0 PopupList.qml
PopupModalBase 1.0 PopupModalBase.qml
PopupToast 1.0 PopupToast.qml
SettingsItem 1.0 SettingsItem.qml
SettingsSectionTitle 1.0 SettingsSectionTitle.qml
singleton Style 1.0 Style.qml