monitor/ScStwMonitorSrc/main.qml
2020-05-22 19:32:57 +02:00

418 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
Window {
id: window
visible: true
width: XscreenWidth / 2
height: XscreenHeight / 2
title: qsTr("ScStwMonitor")
//visibility: Window.FullScreen
Page {
id: app
anchors.fill: parent
function landscape() {
return app.width > app.height
}
ScStwMonitorBackend {
id: backend
scStwClient.ipAddress: appSettings.baseStationIp
}
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
}
}
}
FontLoader {
id: timerFont
source:"qrc:///fonts/PTMono-Regular.ttf"
}
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
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 ? "#e0b928":"grey"
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
}
}
Image {
Layout.preferredHeight: parent.height * 0.5
Layout.preferredWidth: height * 0.7
Layout.alignment: Layout.Center
mipmap: true
fillMode: Image.PreserveAspectFit
source: "qrc:/VolumeLow.png"
}
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"
}
}
}
Image {
Layout.preferredHeight: parent.height * 0.5
Layout.preferredWidth: height
Layout.alignment: Layout.Center
mipmap: true
fillMode: Image.PreserveAspectFit
source: "qrc:/VolumeHigh.png"
}
}
}
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
FancyBusyIndicator {
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
}
}
}
}
}
}