This repository has been archived on 2024-06-03. You can view files and clone it, but cannot push or open issues or pull requests.
monitor/ScStwMonitorSrc/resources/qml/main.qml
Dorian Zedler 759eb60e83
- heavy cleanup
- migrated some stuff to ScStwLibraries
2020-05-26 17:17:33 +02:00

429 lines
14 KiB
QML
Executable file

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import Qt.labs.settings 1.0
import QtQuick.Layouts 1.0
import de.itsblue.ScStw 2.0
import de.itsblue.ScStwMonitor 2.0
import de.itsblue.ScStw.Styling 2.0
import ScStwQmlComponents 1.0
Window {
id: window
visible: true
width: XscreenWidth / 2
height: XscreenHeight / 2
title: qsTr("ScStwMonitor")
//visibility: Window.FullScreen
Page {
id: app
anchors.fill: parent
background: Rectangle {
color: appTheme.theme.colors.background
}
function landscape() {
return app.width > app.height
}
ScStwMonitorBackend {
id: backend
scStwClient.ipAddress: appSettings.baseStationIp
}
ScStwAppThemeManager {
id: appTheme
Component.onCompleted: {
appTheme.setTheme("Light")
}
}
Settings {
id: appSettings
property string baseStationIp: "192.168.4.1"
}
Shortcut {
sequences: ["Ctrl+Q", StandardKey.Back]
onActivated: Qt.quit()
}
Shortcut {
sequences: ["F11", "Esc"]
onActivated: {
if(window.visibility === Window.FullScreen) {
window.visibility = Window.Windowed
}
else {
window.visibility = Window.FullScreen
}
}
}
Loader {
id: mainComponentLoader
anchors.fill: parent
sourceComponent: backend.scStwClient.state === ScStwClient.CONNECTED ? displayComp:loadingComp
}
Component {
id: displayComp
Item {
id: displayItm
anchors.fill: parent
Image {
id: bannerImg
anchors {
top: parent.top
left: parent.left
right: parent.right
margins: app.landscape() ? app.height * 0.01:app.width * 0.1
}
height: app.landscape() ? app.height * 0.25:app.height * 0.2
visible: showControls
fillMode: Image.PreserveAspectFit
mipmap: true
source: "qrc:/Banner.png"
}
TimerColumn {
anchors.fill: parent
timers: backend.race.timers
colors: appTheme.theme.colors
fontName: appTheme.theme.fonts.timers
opacity: !showControls || [ScStwRace.IDLE,ScStwRace.STARTING].indexOf(backend.race.state) < 0 ? 1:0
Behavior on opacity {
NumberAnimation {
duration: 200
}
}
}
Item {
id: controlsItm
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
visible: showControls
Label {
id: clickHintLabel
property string implicitText:[
"tap anywhere\nto start",
"NEXT_START_ACTION",
"please wait...",
"running\ntap anywhere to stop",
"tap anywhere to reset"
][backend.race.state]
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
fontSizeMode: Text.Fit
font.pixelSize: height * 0.3
color: backend.race.state === ScStwRace.STARTING ? appTheme.theme.colors.warning:appTheme.theme.colors.text
text: implicitText === "NEXT_START_ACTION" ? ["", "at your \nmarks", "ready", "starting..."][backend.race.nextStartActionDetails[ScStwRace.NextStartAction]+1]:implicitText
Behavior on text {
FadeAnimation {
target: clickHintLabel
fadeDuration: 150
}
}
}
ProgressBar {
id: nextActiondelayProgressBar
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
}
height: app.landscape() ? app.height * 0.1:app.width * 0.1
opacity: backend.race.nextStartActionDetails[ScStwRace.NextStartAction] < 3 && backend.race.state === ScStwRace.STARTING ? 1:0
value: backend.race.nextStartActionDetails[ScStwRace.NextStartActionDelayProgress]
background: Rectangle {
implicitWidth: 200
implicitHeight: parent.height
color: "lightgrey"
}
contentItem: Item {
implicitWidth: 200
implicitHeight: parent.height
Rectangle {
width: nextActiondelayProgressBar.visualPosition * parent.width
height: parent.height
color: "grey"
}
}
Behavior on opacity {
NumberAnimation {
duration: 200
}
}
}
MouseArea {
parent: app
anchors.fill: parent
visible: controlsItm.visible
enabled: visible
onClicked: {
switch (backend.race.state) {
case ScStwRace.IDLE:
// IDLE
backend.race.start()
break;
case ScStwRace.STARTING:
// STARTING
backend.race.cancel()
break;
case ScStwRace.WAITING:
// WAITING
break;
case ScStwRace.RUNNING:
// RUNNING
backend.race.stop()
break;
case ScStwRace.STOPPED:
// STOPPED
backend.race.reset()
break;
}
}
RowLayout {
id: volumeSliderRow
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
margins: 5
}
height: app.landscape() ? app.height * 0.1:app.width * 0.12
spacing: 0
opacity: backend.race.state === ScStwRace.IDLE ? 1:0
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: 200
}
}
Icon {
Layout.preferredHeight: parent.height * 0.7
Layout.preferredWidth: height * 0.7
Layout.alignment: Layout.Center
fontName: appTheme.theme.fonts.icons
icon: appTheme.theme.icons.volumeDown
color: appTheme.theme.colors.text
}
Slider {
id: volumeSlider
Layout.fillHeight: true
Layout.fillWidth: true
implicitWidth: 200
value: parseFloat(backend.scStwClient.readRemoteSetting(ScStw.SoundVolumeSetting))
onPressedChanged: {
if(!pressed){
volumeSlider.enabled = false
backend.scStwClient.writeRemoteSetting(ScStw.SoundVolumeSetting, value)
volumeSlider.enabled = true
}
}
leftPadding: width * (app.landscape() ? 0.02:0.05)
rightPadding: leftPadding
background: Rectangle {
x: volumeSlider.leftPadding
y: volumeSlider.topPadding + volumeSlider.availableHeight / 2 - height / 2
implicitWidth: 200
implicitHeight: volumeSliderRow.height * 0.1
width: volumeSlider.availableWidth
height: implicitHeight
radius: 2
color: "#bdbebf"
Rectangle {
width: volumeSlider.visualPosition * parent.width
height: parent.height
color: "grey"
radius: 2
}
}
handle: Item {
x: volumeSlider.leftPadding - width * 0.15 + volumeSlider.visualPosition * (volumeSlider.availableWidth - width * 0.55)
y: volumeSlider.topPadding + volumeSlider.availableHeight / 2 - height / 2
implicitWidth: volumeSliderRow.height
implicitHeight: implicitWidth
Image {
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: "qrc:/SpeedHold.png"
}
}
}
Icon {
Layout.preferredHeight: parent.height * 0.7
Layout.preferredWidth: height * 0.7
Layout.alignment: Layout.Center
fontName: appTheme.theme.fonts.icons
icon: appTheme.theme.icons.volumeUp
color: appTheme.theme.colors.text
}
}
}
states: [
State {
when: [ScStwRace.IDLE,ScStwRace.STARTING].indexOf(backend.race.state) >= 0
name: "big"
PropertyChanges {
target: clickHintLabel
anchors.margins: app.landscape() ? app.height * 0.2:app.width * 0.1
width: parent.width * 0.7
height: parent.height * 0.7
}
PropertyChanges {
target: controlsItm
height: app.height
}
},
State {
when: [ScStwRace.IDLE,ScStwRace.STARTING].indexOf(backend.race.state) < 0
name: "small"
PropertyChanges {
target: clickHintLabel
anchors.margins: app.landscape() ? app.height * 0.01:app.width * 0.1
}
PropertyChanges {
target: controlsItm
height: app.landscape() ? app.height * 0.2:app.height * 0.4
}
}
]
transitions: [
Transition {
from: "*"
to: "*"
PauseAnimation {
duration: 150
}
}
]
}
}
}
Component {
id: loadingComp
Item {
id: loadingItm
anchors.fill: parent
BusyIndicator {
id: loadingInd
anchors.centerIn: parent
width: app.landscape() ? parent.height * 0.2 : parent.width *0.2
height: width
}
TextField {
id: ipAddrInputTf
anchors {
bottom: parent.bottom
horizontalCenter: parent.horizontalCenter
}
opacity: backend.scStwClient.state === ScStwClient.CONNECTED ? 0:1
text: appSettings.baseStationIp
onEditingFinished: {
appSettings.baseStationIp = text
backend.scStwClient.ipAddress = text
}
}
}
}
}
}