Merge branch 'refs/heads/schnacke' into linuxero

This commit is contained in:
2025-05-23 14:04:36 +02:00
182 changed files with 45973 additions and 26906 deletions

61
TeroStyle/BarButton.qml Normal file
View File

@@ -0,0 +1,61 @@
import QtQuick
import QtQuick.Controls.impl
import QtQuick.Controls
import QtQuick.Templates as T
T.ToolButton {
id: control
property string target
checkable: true
icon.color: Colors.foreground
icon.height: 36
icon.width: 36
implicitHeight: 90
implicitWidth: 100
topPadding: 20
contentItem: Column {
readonly property color color: control.checked ? Colors.primaryShade : control.hovered ? Colors.primary : Colors.foreground
IconLabel {
color: parent.color
icon.color: parent.color
icon.height: control.icon.height
icon.source: control.icon.source
icon.width: control.icon.width
x: parent.width * .5 - width * .5
}
Label {
color: parent.color
font: Typography.smaller
text: control.text
x: parent.width * .5 - width * .5
}
}
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
color: control.checked ? Colors.primaryShade : Colors.primary
implicitWidth: 6
visible: control.checked || control.hovered
}
MouseArea {
id: mouseArea
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: mouse => mouse.accepted = false
}
onClicked: {
if(!target) {
return
}
contentStack.replace(target)
}
}

View File

@@ -1,37 +1,69 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls.impl as I
import QtQuick.Templates as T
T.Button
{
id: tsBut
property int tsWidth: tsButtonText.width + 10
property int tsHeight: tsButtonText.height + 8
height: tsHeight
width: tsWidth
T.Button {
id: control
background: Rectangle
{
id: tsButton
/**
* Set true when the button is supposed to be displayed in e.g. a TextField.
* You want to do this when this button is directly related to the TextField
* and the primary and only action for the TextField.
* Usually, you'd only want to display an icon in this button.
* If true, automatically sets height, width and position.
*
* ```qml
* TextField {
* placeholderText: "Search..."
* Button {
* icon.source: "qrc:/images/MagnifyingGlass.svg"
* isFieldButton: true
* }
* }
* ```
*/
property bool isFieldButton: false
height: isFieldButton ? parent.height : null
icon.color: Colors.primaryContrast
icon.height: 21
icon.width: 21
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding)
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, implicitContentWidth + leftPadding + rightPadding)
/**
* Icon is slightly larger than Text, so we need to reduce the padding a
* tiny bit to make sure all Buttons are still the same height.
*/
padding: Dimensions.m - (icon.source.toString() === "" ? 0 : 1)
x: isFieldButton ? parent.x + parent.width - width : null
background: Rectangle {
anchors.fill: parent
radius: 50
color: "red"
border.color: Colors.interactive
border.width: isFieldButton ? 1 : 0
bottomLeftRadius: topLeftRadius
color: !control.enabled ? Colors.disabled : !control.hovered ? Colors.primary : Colors.primaryLighter
radius: Dimensions.radius
topLeftRadius: isFieldButton ? 0 : radius
}
contentItem: I.IconLabel {
color: !control.enabled ? Colors.disabledForeground : Colors.primaryContrast
display: control.display
font: control.font
icon: control.icon
mirrored: control.mirrored
spacing: Dimensions.s
text: control.text
}
MouseArea
{
id: mouseArea
anchors.fill: parent
onClicked: tsBut.clicked()
}
MouseArea {
id: mouseArea
Text
{
id: tsButtonText
anchors.centerIn: parent
color: "indigo"
//font.pixelSize: 13
font: tsBut.font
text: tsBut.text
}
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: mouse => mouse.accepted = false
}
}

26
TeroStyle/Colors.qml Normal file
View File

@@ -0,0 +1,26 @@
pragma Singleton
import QtQuick
QtObject {
readonly property int dark: 0
readonly property int light: 1
property int theme: Application.styleHints.colorScheme === Qt.ColorScheme.Light ? light : dark
readonly property color primary: "#b81a34"
readonly property color primaryContrast: "#fdfdfd"
readonly property color primaryLighter: Qt.lighter(primary, 1.5)
readonly property color primaryShade: theme === dark ? primaryLighter : Qt.darker(primary, 1.5)
readonly property color primaryHighlight: theme === dark ? Qt.darker(primary, 2- Colors.highlightOpacity) : Qt.lighter(primary, 2- Colors.highlightOpacity)
readonly property color foreground: theme === dark ? "#fdfdfd" : "#110b0c"
readonly property color background: theme === dark ? "#303136" : "#eff1f5"
readonly property color mantle: theme === dark ? "#1E1E23" : "#e7e9ef"
readonly property color interactive: theme === dark ? "#878b97" : "#d9d9da"
readonly property color error: theme === dark ? "#ff2264" : "#ff004b"
readonly property color disabled: theme === dark ? Qt.darker(interactive, 1.9) : Qt.darker(interactive, 1.3)
readonly property color disabledForeground: theme === dark ? Qt.darker(foreground, 1.4) : Qt.lighter(foreground, 1.9)
readonly property color transparent: "transparent"
readonly property double highlightOpacity: .3
}

108
TeroStyle/ComboBox.qml Normal file
View File

@@ -0,0 +1,108 @@
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls
import QtQuick.Controls.impl
T.ComboBox {
id: control
font: Typography.body
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
contentItem: T.TextField {
id: test
autoScroll: control.editable
color: Colors.foreground
enabled: control.editable
font: Typography.body
implicitHeight: Typography.body.pixelSize + topPadding + bottomPadding
inputMethodHints: control.inputMethodHints
padding: Dimensions.m
readOnly: control.down
selectByMouse: control.selectTextByMouse
text: control.editable ? control.editText : control.displayText
validator: control.validator
width: control.width - indicator.width
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
border.color: Colors.interactive
border.width: 1
color: Colors.mantle
radius: Dimensions.radius
width: parent.width
}
delegate: ItemDelegate {
required property var model
required property int index
width: ListView.view.width
text: model[control.textRole]
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
}
indicator: Rectangle {
id: indicator
border.color: Colors.interactive
bottomRightRadius: Dimensions.radius
color: Colors.primary
height: control.height
topRightRadius: Dimensions.radius
width: 20 + Dimensions.s * 2
x: control.width - width
y: 0
z: 2
IconLabel {
anchors.fill: parent
bottomPadding: Dimensions.s
icon.color: Colors.foreground
icon.source: "qrc:/images/ChevronDown.svg"
leftPadding: Dimensions.s
rightPadding: Dimensions.s
topPadding: Dimensions.s
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: () => {
control.popup.visible = true;
control.popup.forceActiveFocus()
}
}
}
popup: T.Popup {
bottomMargin: 6
height: Math.min(contentItem.implicitHeight + 2, control.Window.height - topMargin - bottomMargin)
padding: 1
topMargin: 6
width: control.width
y: control.height
background: Rectangle {
border.color: Colors.interactive
color: Colors.mantle
radius: Dimensions.radius
}
contentItem: ListView {
clip: true
currentIndex: control.highlightedIndex
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
T.ScrollBar.vertical: ScrollBar {
}
highlight: Rectangle {
color: Colors.primary
opacity: Colors.highlightOpacity
}
}
}
}

26
TeroStyle/Dimensions.qml Normal file
View File

@@ -0,0 +1,26 @@
pragma Singleton
import QtQuick
QtObject
{
/**
* Distance for objects that are tied to each other,
* e.g. a field and its label.
*/
readonly property int s: 9
/**
* Distance for objects that are grouped together, e.g. radio buttons of the
* same radio group.
*/
readonly property int m: 15
/**
* Distance for objects that are not related to each other, or to objects
* and their container.
*/
readonly property int l: 30
readonly property int radius: 4
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /([\+!#$%&\*\\/\=?\^_`\.{|}\~\-\_0-9A-Za-z]{1,185})@([0-9A-Za-z\.\-\_]{1,64})\.([a-zA-z]{2,5})/
}

20
TeroStyle/Field.qml Normal file
View File

@@ -0,0 +1,20 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ColumnLayout
{
required property string label
/**
* Adds an asterisk after the label, informing the user that this field
* is mandatory.
*/
property bool mandatory: false
spacing: Dimensions.s
Label
{
text: label + (mandatory ? "*" : "")
font: Typography.body
}
}

5
TeroStyle/H1.qml Normal file
View File

@@ -0,0 +1,5 @@
import QtQuick
Text {
font: Typography.h1
}

5
TeroStyle/H2.qml Normal file
View File

@@ -0,0 +1,5 @@
import QtQuick
Text {
font: Typography.h2
}

5
TeroStyle/Label.qml Normal file
View File

@@ -0,0 +1,5 @@
import QtQuick.Controls
Label {
color: Colors.foreground
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /^\S+.*\S+$/
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /^$|([\+!#$%&\*\\/\=?\^_`\.{|}\~\-\_0-9A-Za-z]{1,185})@([0-9A-Za-z\.\-\_]{1,64})\.([a-zA-z]{2,5})/
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /^$|([+0-9])([0-9\s]{1,17})/
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /([+0-9])([0-9\s]{1,17})/
}

View File

@@ -0,0 +1,5 @@
import QtQuick
RegularExpressionValidator {
regularExpression: /([^$][0-9]{1,4})/
}

64
TeroStyle/QuickFilter.qml Normal file
View File

@@ -0,0 +1,64 @@
import QtQuick
import QtCore
import QtQuick.Layouts
RowLayout {
id: root
required property ListModel model
signal selectedChanged(string name)
spacing: Dimensions.m
Repeater {
model: root.model
Item {
id: item
required property int index
required property var modelData
property bool hovered: false
property real padding: Dimensions.m
height: text.height + padding * 2
width: text.width + padding * 2
Rectangle {
anchors.fill: parent
border.color: modelData.selected ? Colors.transparent : Colors.foreground
border.width: 2
color: modelData.selected || mouseArea.containsMouse ? Colors.primary : Colors.transparent
radius: parent.height
}
Text {
id: text
color: Colors.foreground
font: Typography.body
text: modelData.text
x: parent.padding
y: parent.padding
}
MouseArea {
id: mouseArea
hoverEnabled: true
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onPressed: {
if (item.modelData.selected)
return;
const model = root.model;
for (let i = 0; i < model.count; i++) {
model.setProperty(i, "selected", false);
}
model.setProperty(item.index, "selected", true);
selectedChanged(item.modelData.name)
}
}
}
}
}

14
TeroStyle/SearchBar.qml Normal file
View File

@@ -0,0 +1,14 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
TextField {
Layout.preferredWidth: 300
placeholderText: qsTr("Suche")
Button {
icon.source: "qrc:/images/MagnifyingGlass.svg"
isFieldButton: true
}
}

47
TeroStyle/TextField.qml Normal file
View File

@@ -0,0 +1,47 @@
import QtQuick
import QtQuick.Templates as T
T.TextField
{
id: control
background: Rectangle
{
id: background
color: Colors.mantle
radius: Dimensions.radius
border.width: !control.focus ? 1 : 2
border.color: Colors.interactive
height: control.implicitHeight
}
color: Colors.foreground
implicitHeight: Typography.body.pixelSize + topPadding + bottomPadding
placeholderTextColor: Colors.interactive
font: Typography.body
padding: Dimensions.m
verticalAlignment: Text.AlignVCenter
/**
* Placeholder
*/
Text {
x: control.leftPadding
y: control.topPadding
width: control.width - (control.leftPadding + control.rightPadding)
height: control.height - (control.topPadding + control.bottomPadding)
font: control.font
text: control.placeholderText
color: control.placeholderTextColor
verticalAlignment: control.verticalAlignment
visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
elide: Text.ElideRight
renderType: control.renderType
}
}

56
TeroStyle/Typography.qml Normal file
View File

@@ -0,0 +1,56 @@
pragma Singleton
import QtCore
import QtQuick
Item {
readonly property font body: ({
family: robotoCondensed.font,
pointSize: 16,
weight: Font.Medium,
letterSpacing: 0,
kerning: true
})
readonly property font small: ({
family: body.family,
pointSize: 14,
weight: Font.Medium,
letterSpacing: body.letterSpacing,
kerning: body.kerning
})
readonly property font smallBold: ({
family: small.family,
pointSize: small.pointSize,
weight: Font.Bold,
letterSpacing: small.letterSpacing,
kerning: small.kerning
})
readonly property font smaller: ({
family: body.family,
pointSize: 11,
weight: Font.DemiBold,
letterSpacing: body.letterSpacing,
kerning: body.kerning
})
readonly property font h1: ({
family: body.family,
pointSize: 38,
weight: body.weight,
letterSpacing: body.letterSpacing,
kerning: body.kerning
})
readonly property font h2: ({
family: body.family,
pointSize: 28,
weight: body.weight,
letterSpacing: body.letterSpacing,
kerning: body.kerning,
})
readonly property FontLoader robotoCondensed: FontLoader {
source: "qrc:/fonts/RobotoCondensed.otf"
}
}

5
TeroStyle/pushtest.qml Normal file
View File

@@ -0,0 +1,5 @@
import QtQuick
Item {
}

View File

@@ -1,3 +1,20 @@
module TeroStyle
TeroStyle 1.0 TeroStyle.qml
Button 1.0 Button.qml
singleton Colors Colors.qml
singleton Dimensions Dimensions.qml
singleton Typography Typography.qml
BarButton BarButton.qml
Button Button.qml
ComboBox ComboBox.qml
EmailAddressValidator EmailAddressValidator.qml
Field Field.qml
H1 H1.qml
H2 H2.qml
Label Label.qml
NotEmptyValidator NotEmptyValidator.qml
OptionalEmailAddressValidator OptionalEmailAddressValidator.qml
PhoneNumberValidator PhoneNumberValidator.qml
OptionalPhoneNumberValidator OptionalPhoneNumberValidator.qml
PostcodeValidator PostcodeValidator.qml
QuickFilter QuickFilter.qml
SearchBar SearchBar.qml
TextField TextField.qml