552 lines
20 KiB
QML
552 lines
20 KiB
QML
import QtQuick 2.9
|
|
import QtMultimedia 5.8
|
|
import QtQuick.Window 2.2
|
|
import QtQuick.Controls 2.2
|
|
//import QtQuick.Layouts 1.11
|
|
|
|
import com.itsblue.speedclimbingstopwatch 1.0
|
|
|
|
Window {
|
|
visible: true
|
|
width: 540
|
|
height: 960
|
|
title: qsTr("Speedclimbing stw")
|
|
property date currentTime: new Date()
|
|
property int millis: 0
|
|
|
|
|
|
Page {
|
|
id:root
|
|
anchors.fill: parent
|
|
|
|
property double startTime: 0
|
|
property double stoppedTime: 0
|
|
property double currTime: new Date().getTime()
|
|
|
|
property double buzzer_offset
|
|
property double last_button_pressed
|
|
|
|
|
|
state: "IDLE"
|
|
|
|
Timer {
|
|
//timer that updates the currTime variable
|
|
running: true
|
|
repeat: true
|
|
interval: 1
|
|
onTriggered: {
|
|
root.currTime = new Date().getTime()
|
|
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: running_refresh_timer
|
|
running: root.state === "RUNNING"
|
|
repeat: true
|
|
interval: 1
|
|
|
|
onTriggered: {
|
|
var theUrl = "http://192.168.4.1";
|
|
var xmlHttp = null;
|
|
|
|
xmlHttp = new XMLHttpRequest();
|
|
xmlHttp.open( "GET", theUrl, false );
|
|
xmlHttp.send( null );
|
|
var response = xmlHttp.responseText
|
|
var res = response.split("<br>");
|
|
startButt.text = res[0]
|
|
if(res[1]>root.last_button_pressed){
|
|
root.last_button_pressed = res[1]
|
|
root.stoppedTime = (root.last_button_pressed + root.buzzer_offset) - root.startTime
|
|
console.log("STOPPED: "+root.stoppedTime)
|
|
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
|
|
root.state = "STOPPED"
|
|
}
|
|
}
|
|
}
|
|
|
|
SoundEffect {
|
|
//start sound
|
|
id: startSound
|
|
source: "OFFICAL_IFSC_STARTIGNAL.wav"
|
|
|
|
onPlayingChanged: {
|
|
if(!playing){
|
|
root.startTime = new Date().getTime()
|
|
root.currTime = new Date().getTime()
|
|
time.text = ( ( root.currTime - root.startTime ) / 1000 ).toFixed(3) + " sec"
|
|
root.state = "RUNNING"
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------------------------
|
|
Timer text an upper line
|
|
------------------------*/
|
|
Item {
|
|
id: time_container
|
|
anchors {
|
|
top: parent.top
|
|
left: parent.left
|
|
right: root.landscape() ? startButt.left:parent.right
|
|
bottom: root.landscape() ? parent.bottom:startButt.top
|
|
bottomMargin: root.landscape() ? undefined:parent.height * 0.1
|
|
rightMargin: root.landscape() ? parent.width * 0.05:0
|
|
}
|
|
//height: root.landscape() ? undefined:parent.height * 0.15
|
|
Label {
|
|
id: time
|
|
text: "Click start to start"
|
|
|
|
anchors.centerIn: parent
|
|
//font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3
|
|
elide: "ElideRight"
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
width: root.landscape() ? 1:parent.width
|
|
height: root.landscape() ? parent.height:1
|
|
color: "grey"
|
|
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
|
|
}
|
|
|
|
/*----------------------
|
|
Start button
|
|
----------------------*/
|
|
Button {
|
|
id : startButt
|
|
|
|
text: "start"
|
|
property int size: root.landscape() ? parent.width * 0.5:parent.height * 0.5
|
|
anchors {
|
|
bottom: parent.bottom
|
|
bottomMargin: root.height * 0.5 - height * 0.5
|
|
right: parent.right
|
|
rightMargin: root.width * 0.5 - width * 0.5
|
|
}
|
|
contentItem: Text {
|
|
//make text disappear
|
|
}
|
|
height: root.landscape() ? size > parent.height * 0.9 ? parent.height * 0.9:size : size
|
|
width: root.landscape() ? size : size > parent.width * 0.9 ? parent.width * 0.9:size
|
|
|
|
onPressedChanged: {
|
|
if(pressed){
|
|
background.color = "lightgrey"
|
|
}
|
|
else {
|
|
background.color = "white"
|
|
}
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: "white"
|
|
border.color: "grey"
|
|
border.width: 1
|
|
radius: width / 2
|
|
Label {
|
|
id: startButt_text
|
|
text: startButt.text
|
|
anchors.centerIn: parent
|
|
font.pixelSize: parent.height * 0.16
|
|
font.family: "Helvetica"
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
switch(root.state) {
|
|
case "":
|
|
root.state = "IDLE"
|
|
case "IDLE":
|
|
root.state = "STARTING"
|
|
startSound.play()
|
|
break
|
|
case "RUNNING":
|
|
root.stoppedTime = new Date().getTime() - root.startTime
|
|
time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
|
|
root.state = "STOPPED"
|
|
break
|
|
case "STOPPED":
|
|
root.state = "IDLE"
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*----------------------
|
|
Cancel button
|
|
----------------------*/
|
|
RoundButton {
|
|
id: cancelButt
|
|
|
|
text: "cancel"
|
|
anchors {
|
|
right: startButt.right
|
|
bottom: startButt.bottom
|
|
}
|
|
contentItem: Text {
|
|
//make text disappear
|
|
}
|
|
height: startButt.height * 0.3
|
|
scale: 0
|
|
width: height
|
|
|
|
enabled: startSound.playing
|
|
onPressedChanged: {
|
|
if(pressed){
|
|
background.color = "lightgrey"
|
|
}
|
|
else {
|
|
background.color = "white"
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
startSound.stop()
|
|
root.stoppedTime = 0
|
|
time.text = "false start"
|
|
root.state = "STOPPED"
|
|
}
|
|
|
|
Behavior on scale {
|
|
PropertyAnimation {
|
|
duration: 200
|
|
}
|
|
}
|
|
background: Rectangle {
|
|
color: "white"
|
|
border.color: "grey"
|
|
border.width: 1
|
|
radius: width / 2
|
|
Label {
|
|
id: cancelButt_text
|
|
text: cancelButt.text
|
|
anchors.centerIn: parent
|
|
font.pixelSize: parent.height * 0.16
|
|
font.family: "Helvetica"
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------
|
|
Popups
|
|
------*/
|
|
SettingsDialog{
|
|
id:settingsDialog
|
|
}
|
|
|
|
|
|
/*-------------------
|
|
lower line and menu
|
|
-------------------*/
|
|
Rectangle {
|
|
width: root.landscape() ? 1:parent.width
|
|
height: root.landscape() ? parent.height:1
|
|
color: "grey"
|
|
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
|
|
}
|
|
|
|
Item {
|
|
id: menu_container
|
|
anchors {
|
|
bottom: parent.bottom
|
|
right: parent.right
|
|
left: root.landscape() ? startButt.right:parent.left
|
|
top: root.landscape() ? parent.top:startButt.bottom
|
|
topMargin: root.landscape() ? undefined:parent.height * 0.1
|
|
leftMargin: root.landscape() ? parent.width * 0.05:0
|
|
}
|
|
|
|
RoundButton {
|
|
id: settingsButt
|
|
|
|
anchors {
|
|
//center
|
|
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
|
|
horizontalCenter: root.landscape() ? parent.horizontalCenter:undefined
|
|
//set anchors
|
|
left: root.landscape() ? undefined:parent.left
|
|
top: root.landscape() ? parent.top:undefined
|
|
//align in landscape mode
|
|
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
|
|
//align in portrait mode
|
|
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
|
|
}
|
|
|
|
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
|
|
width: height
|
|
|
|
onPressedChanged: {
|
|
if(pressed){
|
|
background.color = "lightgrey"
|
|
}
|
|
else {
|
|
background.color = "white"
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
if(settingsDialog.enabled === false){
|
|
settingsDialog.open()
|
|
settingsDialog.enabled = true
|
|
}
|
|
else {
|
|
settingsDialog.enabled = false
|
|
settingsDialog.close()
|
|
}
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: "white"
|
|
border.color: "grey"
|
|
border.width: 1
|
|
radius: width / 2
|
|
|
|
|
|
Image {
|
|
id: settungsButt_Image
|
|
source: "qrc:/graphics/icons/settings.png"
|
|
anchors.centerIn: parent
|
|
height: parent.height * 0.7
|
|
width: parent.width * 0.7
|
|
mipmap: true
|
|
}
|
|
}
|
|
}
|
|
|
|
RoundButton {
|
|
id: profilesButt
|
|
|
|
anchors {
|
|
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
|
|
horizontalCenter: root.landscape() ? parent.horizontalCenter:undefined
|
|
left: root.landscape() ? undefined:settingsButt.right
|
|
top: root.landscape() ? settingsButt.bottom:undefined
|
|
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
|
|
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
|
|
}
|
|
|
|
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
|
|
width: height
|
|
|
|
onPressedChanged: {
|
|
if(pressed){
|
|
background.color = "lightgrey"
|
|
}
|
|
else {
|
|
background.color = "white"
|
|
}
|
|
}
|
|
|
|
onClicked: {
|
|
var theUrl = "http://192.168.4.1";
|
|
var xmlHttp = null;
|
|
|
|
xmlHttp = new XMLHttpRequest();
|
|
xmlHttp.open( "GET", theUrl, false );
|
|
xmlHttp.send( null );
|
|
console.log(xmlHttp.responseText)
|
|
}
|
|
|
|
background: Rectangle {
|
|
color: "white"
|
|
border.color: "grey"
|
|
border.width: 1
|
|
radius: width / 2
|
|
|
|
Image {
|
|
id: profilesButt_Image
|
|
source: "qrc:/graphics/icons/user.png"
|
|
anchors.centerIn: parent
|
|
height: parent.height * 0.5
|
|
width: parent.width * 0.5
|
|
mipmap: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
// ComboBox {
|
|
// id: profileBox
|
|
// property int profileIndex: -1
|
|
// model: SqlProfileModel{}
|
|
// textRole: "name"
|
|
// width: parent.width
|
|
// anchors {
|
|
// bottom: parent.bottom
|
|
// horizontalCenter: parent.horizontalCenter
|
|
// }
|
|
// height: parent.height * 0.05
|
|
// background: Rectangle {
|
|
// color: profileBox.down ? "lightgrey":"white"
|
|
// border.width: 1
|
|
// border.color: "grey"
|
|
// }
|
|
// popup: Popup {
|
|
// id: profileBox_popup
|
|
// property bool popup_open: false
|
|
// y: profileBox.height - 1
|
|
// width: profileBox.width
|
|
// implicitHeight: contentItem.implicitHeight
|
|
// padding: 1
|
|
|
|
// contentItem: ListView {
|
|
// clip: true
|
|
// implicitHeight: contentHeight
|
|
// model: profileBox.popup.visible ? profileBox.delegateModel : null
|
|
// currentIndex: profileBox.highlightedIndex
|
|
|
|
// ScrollIndicator.vertical: ScrollIndicator { }
|
|
// }
|
|
// onVisibleChanged: {
|
|
// if(visible){
|
|
// if(popup_open){
|
|
// popup_open = false
|
|
// return
|
|
// }
|
|
// popup_open = true
|
|
// height=implicitHeight
|
|
// }
|
|
// else {
|
|
// height = 0
|
|
// visible = true
|
|
// }
|
|
// }
|
|
|
|
// background: Rectangle {
|
|
// border.color: "grey"
|
|
// radius: 2
|
|
// }
|
|
|
|
// Behavior on height {
|
|
// NumberAnimation
|
|
// {
|
|
// onRunningChanged: {
|
|
// if(!running && !profileBox_popup.popup_pen){
|
|
// profileBox_popup.popup_open = false
|
|
// profileBox_popup.visible = false
|
|
// }
|
|
// }
|
|
|
|
// duration: 200
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// onDownChanged: {
|
|
// if(profileIndex !== currentIndex)
|
|
// profileIndex = currentIndex
|
|
// }
|
|
// }
|
|
*/
|
|
|
|
|
|
/*----------------------
|
|
Timer states
|
|
----------------------*/
|
|
states: [
|
|
State {
|
|
name: "IDLE"
|
|
//state for the start page
|
|
PropertyChanges { target: time; text: "Click start to start"; font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 }
|
|
PropertyChanges {
|
|
target: time_container;
|
|
anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1;
|
|
anchors.rightMargin: root.landscape() ? parent.height * 0.05:0
|
|
}
|
|
|
|
PropertyChanges {
|
|
target: startButt;
|
|
enabled: true; text: "start";
|
|
size: root.landscape() ? parent.width * 0.5:parent.height * 0.5
|
|
anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5
|
|
anchors.rightMargin: parent.width * 0.5 - startButt.width * 0.5
|
|
}
|
|
|
|
},
|
|
State {
|
|
name: "STARTING"
|
|
//state for the start sequence
|
|
PropertyChanges { target: startButt; enabled: false; text: "starting...";
|
|
anchors.rightMargin: root.landscape() ? parent.width * 0.05:none //put the button more to the right to hide the menu (only in landscape mode)
|
|
anchors.bottomMargin: root.landscape() ? none:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
|
}
|
|
PropertyChanges { target: time; text: "0.000 sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
|
PropertyChanges { target: cancelButt; scale: 1}
|
|
PropertyChanges { target: menu_container; }
|
|
},
|
|
State {
|
|
name: "RUNNING"
|
|
//state when the timer is running
|
|
PropertyChanges { target: time; text: ( ( root.currTime - root.startTime ) / 1000 ).toFixed(3) + " sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
|
PropertyChanges { target: startButt; enabled: true;
|
|
text: "stop"
|
|
anchors.rightMargin: root.landscape() ? parent.width * 0.05:none //put the button more to the right to hide the menu (only in landscape mode)
|
|
anchors.bottomMargin: root.landscape() ? none:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
|
}
|
|
|
|
},
|
|
|
|
State {
|
|
name: "STOPPED"
|
|
//state when the meassuring is over
|
|
PropertyChanges {
|
|
target: time; text: root.stoppedTime > 0 ? ( root.stoppedTime / 1000 ).toFixed(3) + " sec":"false start";
|
|
font.pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1;
|
|
scale: 1
|
|
}
|
|
PropertyChanges {
|
|
target: startButt;
|
|
enabled: true; text: "reset";
|
|
size: root.landscape() ? parent.height * 0.35:parent.height * 0.2;
|
|
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.2 - startButt.height * 0.5
|
|
anchors.rightMargin: root.landscape() ? parent.height * 0.2 - startButt.height * 0.5:parent.width * 0.5 - startButt.width * 0.5
|
|
}
|
|
PropertyChanges {
|
|
target: time_container;
|
|
anchors.rightMargin: root.landscape() ? 0-startButt.width/2:undefined
|
|
anchors.bottomMargin: root.landscape() ? undefined:0-startButt.height/2
|
|
}
|
|
}
|
|
]
|
|
|
|
/*----------------------
|
|
Timer animations
|
|
----------------------*/
|
|
transitions: [
|
|
Transition {
|
|
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
|
},
|
|
Transition {
|
|
to: "STOPPED"
|
|
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
|
},
|
|
Transition {
|
|
to: "IDLE"
|
|
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
|
FadeAnimation { target: time; fadeDuration_out: 1000; fadeDuration_in: 0}
|
|
},
|
|
|
|
Transition {
|
|
to: "RUNNING"
|
|
//disable transitions for the RUNNING state
|
|
}
|
|
]
|
|
|
|
/*----------------------
|
|
Timer functions
|
|
----------------------*/
|
|
function landscape(){
|
|
return(root.height < root.width)
|
|
}
|
|
}
|
|
}
|