2018-07-17 19:17:25 +02:00
import QtQuick 2.9
import QtMultimedia 5.8
import QtQuick . Window 2.2
import QtQuick . Controls 2.2
2018-07-22 21:08:11 +02:00
//import QtQuick.Layouts 1.11
2018-07-22 16:47:55 +02:00
import com . itsblue . speedclimbingstopwatch 1.0
2018-07-17 19:17:25 +02:00
Window {
visible: true
width: 540
height: 960
2018-07-18 14:06:04 +02:00
title: qsTr ( "Speedclimbing stw" )
2018-07-17 19:17:25 +02:00
property date currentTime: new Date ( )
property int millis: 0
Page {
2018-07-26 20:51:46 +02:00
2018-07-17 19:17:25 +02:00
id:root
anchors.fill: parent
property double startTime: 0
property double stoppedTime: 0
2018-07-26 14:54:11 +02:00
property double currTime
2018-07-17 19:17:25 +02:00
2018-07-25 00:32:20 +02:00
property double buzzer_offset
property double last_button_pressed
2018-07-22 16:47:55 +02:00
state: "IDLE"
2018-07-17 19:17:25 +02:00
Timer {
2018-07-22 16:47:55 +02:00
//timer that updates the currTime variable
2018-07-17 19:17:25 +02:00
running: true
repeat: true
interval: 1
onTriggered: {
root . currTime = new Date ( ) . getTime ( )
2018-07-25 00:32:20 +02:00
}
}
2018-07-26 20:51:46 +02:00
Timer {
//timer that refreshes the connection state to the buzzer
running: false
repeat: true
interval: 500
onTriggered: {
console . log ( _cppBuzzerConn . calcoffset ( ) )
}
}
2018-07-25 00:32:20 +02:00
Timer {
id: running_refresh_timer
running: root . state === "RUNNING"
2018-07-26 14:54:11 +02:00
repeat: false
2018-07-25 00:32:20 +02:00
interval: 1
onTriggered: {
2018-07-26 14:54:11 +02:00
if ( _cppBuzzerConn . buzzer_triggered ( ) ) {
2018-07-26 22:13:43 +02:00
//the buzzer was pushed
2018-07-26 14:54:11 +02:00
root . buzzer_offset = _cppBuzzerConn . get ( "offset" )
root . last_button_pressed = _cppBuzzerConn . get ( "lastpressed" )
2018-07-26 20:51:46 +02:00
root . stoppedTime = ( root . last_button_pressed + root . buzzer_offset ) - root . startTime
2018-07-25 00:32:20 +02:00
root . state = "STOPPED"
2018-07-26 22:13:43 +02:00
//time.text = ( root.stoppedTime / 1000 ).toFixed(3) + " sec"
console . log ( "STOPPED: " + root . stoppedTime )
2018-07-25 00:32:20 +02:00
}
2018-07-26 14:54:11 +02:00
if ( root . state === "RUNNING" ) {
running_refresh_timer . start ( )
}
2018-07-17 19:17:25 +02:00
}
}
2018-07-28 21:17:41 +02:00
Timer {
id: next_actionTimer
property string action
property double started_at
running: false
repeat: false
onRunningChanged: {
if ( ! running ) {
started_at = 0
if ( action == "NONE" ) {
time . text = "0.000 sec"
}
return
}
if ( action === "at_marks" ) {
started_at = new Date ( ) . getTime ( )
time . text = "at your\nmarks"
}
else if ( action === "ready" ) {
started_at = new Date ( ) . getTime ( )
time . text = "ready"
}
}
onTriggered: {
if ( action === "at_marks" ) {
at_marksSound . play ( )
}
else if ( action === "ready" ) {
action = "NONE"
readySound . play ( )
}
}
}
SoundEffect {
id: at_marksSound
source: "qrc:/sounds/at_marks_1.wav"
onPlayingChanged: {
if ( ! playing ) {
if ( _cppAppSettings . loadSetting ( "ready_en" ) === "true" ) {
next_actionTimer . action = "ready"
next_actionTimer . interval = _cppAppSettings . loadSetting ( "ready_delay" )
next_actionTimer . start ( )
//readySound.play()
}
else {
startSound . play ( )
}
}
}
}
SoundEffect {
id: readySound
source: "qrc:/sounds/ready_1.wav"
onPlayingChanged: {
if ( ! playing ) {
startSound . play ( )
}
}
}
2018-07-22 16:47:55 +02:00
SoundEffect {
//start sound
id: startSound
2018-07-28 23:05:26 +02:00
source: "qrc:/sounds/OFFICAL_IFSC_STARTIGNAL.wav"
2018-07-22 16:47:55 +02:00
onPlayingChanged: {
if ( ! playing ) {
2018-07-26 14:54:11 +02:00
root . startTime = _cppBuzzerConn . get ( "currtime" )
_cppBuzzerConn . start ( )
root . currTime = _cppBuzzerConn . get ( "currtime" )
2018-07-22 16:47:55 +02:00
time . text = ( ( root . currTime - root . startTime ) / 1000 ) . toFixed ( 3 ) + " sec"
root . state = "RUNNING"
}
}
}
/ * - - - - - - - - - - - - - - - - - - - - - - - -
Timer text an upper line
-- -- -- -- -- -- -- -- -- -- -- -- * /
2018-07-17 19:17:25 +02:00
Item {
id: time_container
anchors {
top: parent . top
left: parent . left
2018-07-22 16:47:55 +02:00
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
2018-07-17 19:17:25 +02:00
}
2018-07-22 16:47:55 +02:00
//height: root.landscape() ? undefined:parent.height * 0.15
2018-07-17 19:17:25 +02:00
Label {
id: time
text: "Click start to start"
anchors.centerIn: parent
2018-07-22 16:47:55 +02:00
//font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3
elide: "ElideRight"
2018-07-17 19:17:25 +02:00
}
}
Rectangle {
2018-07-22 16:47:55 +02:00
width: root . landscape ( ) ? 1 : parent . width
height: root . landscape ( ) ? parent.height: 1
2018-07-17 19:17:25 +02:00
color: "grey"
2018-07-22 16:47:55 +02:00
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
2018-07-17 19:17:25 +02:00
}
2018-07-22 16:47:55 +02:00
/ * - - - - - - - - - - - - - - - - - - - - - -
Start button
-- -- -- -- -- -- -- -- -- -- -- * /
2018-07-25 00:32:20 +02:00
Button {
id : startButt
2018-07-17 19:17:25 +02:00
2018-07-25 00:32:20 +02:00
text: "start"
2018-07-22 16:47:55 +02:00
property int size: root . landscape ( ) ? parent . width * 0.5 : parent . height * 0.5
2018-07-17 19:17:25 +02:00
anchors {
bottom: parent . bottom
2018-07-25 00:32:20 +02:00
bottomMargin: root . height * 0.5 - height * 0.5
2018-07-22 16:47:55 +02:00
right: parent . right
2018-07-25 00:32:20 +02:00
rightMargin: root . width * 0.5 - width * 0.5
}
contentItem: Text {
//make text disappear
2018-07-17 19:17:25 +02:00
}
2018-07-22 16:47:55 +02:00
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
2018-07-17 19:17:25 +02:00
2018-07-25 00:32:20 +02:00
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"
}
2018-07-17 19:17:25 +02:00
}
2018-07-22 16:47:55 +02:00
2018-07-25 00:32:20 +02:00
onClicked: {
switch ( root . state ) {
case "" :
root . state = "IDLE"
case "IDLE" :
root . state = "STARTING"
2018-07-28 21:17:41 +02:00
if ( _cppAppSettings . loadSetting ( "at_marks_en" ) === "true" ) {
next_actionTimer . action = "at_marks"
next_actionTimer . interval = _cppAppSettings . loadSetting ( "at_marks_delay" )
next_actionTimer . start ( )
return
}
if ( _cppAppSettings . loadSetting ( "ready_en" ) === "true" ) {
next_actionTimer . action = "ready"
next_actionTimer . interval = _cppAppSettings . loadSetting ( "ready_delay" )
next_actionTimer . start ( )
return
}
2018-07-25 00:32:20 +02:00
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
2018-07-22 16:47:55 +02:00
}
}
2018-07-28 21:17:41 +02:00
}
ProgressCircle {
id: prog
anchors.fill: startButt
opacity: next_actionTimer . started_at > 0 ? 1 : 0
lineWidth: 5
2018-07-25 00:32:20 +02:00
2018-07-28 21:17:41 +02:00
arcBegin: 0
arcEnd: 360 * ( ( next_actionTimer . interval - ( new Date ( ) . getTime ( ) - next_actionTimer . started_at ) ) / next_actionTimer . interval )
colorCircle: "grey"
animationDuration: 0
Timer {
id: prog_refresh
running: parent . opacity === 1
interval: 1
repeat: true
onTriggered: {
prog . arcEnd = 360 * ( ( next_actionTimer . interval - ( new Date ( ) . getTime ( ) - next_actionTimer . started_at ) ) / next_actionTimer . interval )
}
}
2018-07-22 16:47:55 +02:00
}
/ * - - - - - - - - - - - - - - - - - - - - - -
Cancel button
-- -- -- -- -- -- -- -- -- -- -- * /
2018-07-25 00:32:20 +02:00
RoundButton {
2018-07-22 16:47:55 +02:00
id: cancelButt
2018-07-25 00:32:20 +02:00
text: "cancel"
2018-07-22 16:47:55 +02:00
anchors {
right: startButt . right
bottom: startButt . bottom
}
2018-07-25 00:32:20 +02:00
contentItem: Text {
//make text disappear
}
2018-07-22 16:47:55 +02:00
height: startButt . height * 0.3
scale: 0
width: height
2018-07-28 21:17:41 +02:00
enabled: root . state === "STARTING"
2018-07-25 00:32:20 +02:00
onPressedChanged: {
if ( pressed ) {
background . color = "lightgrey"
}
else {
background . color = "white"
2018-07-22 16:47:55 +02:00
}
}
2018-07-25 00:32:20 +02:00
onClicked: {
2018-07-28 21:17:41 +02:00
next_actionTimer . stop ( )
at_marksSound . stop ( )
readySound . stop ( )
2018-07-25 00:32:20 +02:00
startSound . stop ( )
root . stoppedTime = 0
time . text = "false start"
root . state = "STOPPED"
}
2018-07-22 16:47:55 +02:00
Behavior on scale {
PropertyAnimation {
duration: 200
}
}
2018-07-25 00:32:20 +02:00
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
2018-07-22 16:47:55 +02:00
}
2018-07-25 00:32:20 +02:00
2018-07-22 16:47:55 +02:00
/ * - - - - - - - - - - - - - - - - - - -
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
}
2018-07-25 00:32:20 +02:00
RoundButton {
2018-07-22 16:47:55 +02:00
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
}
2018-07-25 00:32:20 +02:00
2018-07-22 16:47:55 +02:00
height: root . landscape ( ) ? parent . width * 0.7 : parent . height * 0.7
width: height
2018-07-25 00:32:20 +02:00
onPressedChanged: {
if ( pressed ) {
background . color = "lightgrey"
}
else {
background . color = "white"
}
2018-07-22 16:47:55 +02:00
}
2018-07-25 00:32:20 +02:00
onClicked: {
2018-07-26 22:13:43 +02:00
settingsDialog . open ( )
2018-07-22 16:47:55 +02:00
}
2018-07-25 00:32:20 +02:00
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
2018-07-22 16:47:55 +02:00
}
}
}
2018-07-25 00:32:20 +02:00
RoundButton {
2018-07-22 16:47:55 +02:00
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
}
2018-07-25 00:32:20 +02:00
height: root . landscape ( ) ? parent . width * 0.7 : parent . height * 0.7
2018-07-22 16:47:55 +02:00
width: height
2018-07-25 00:32:20 +02:00
onPressedChanged: {
if ( pressed ) {
background . color = "lightgrey"
}
else {
background . color = "white"
}
2018-07-22 16:47:55 +02:00
}
2018-07-25 00:32:20 +02:00
onClicked: {
2018-07-22 16:47:55 +02:00
}
2018-07-17 19:17:25 +02:00
2018-07-25 00:32:20 +02:00
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
2018-07-22 16:47:55 +02:00
}
2018-07-17 19:17:25 +02:00
}
}
}
2018-07-22 16:47:55 +02:00
/ *
// 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
-- -- -- -- -- -- -- -- -- -- -- * /
2018-07-17 19:17:25 +02:00
states: [
2018-07-22 16:47:55 +02:00
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..." ;
2018-07-29 11:23:32 +02:00
anchors.rightMargin: root . landscape ( ) ? parent . width * 0.05 : parent . width * 0.5 - startButt . width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
anchors.bottomMargin: root . landscape ( ) ? parent . height * 0.5 - startButt . height * 0.5 : parent . height * 0.1 //put the button lower to hide the menu (only in portrait mode)
2018-07-22 16:47:55 +02:00
}
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"
2018-07-29 11:23:32 +02:00
anchors.rightMargin: root . landscape ( ) ? parent . width * 0.05 : parent . width * 0.5 - startButt . width * 0.5 //put the button more to the right to hide the menu (only in landscape mode)
anchors.bottomMargin: root . landscape ( ) ? parent . height * 0.5 - startButt . height * 0.5 : parent . height * 0.1 //put the button lower to hide the menu (only in portrait mode)
2018-07-22 16:47:55 +02:00
}
} ,
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
-- -- -- -- -- -- -- -- -- -- -- * /
2018-07-17 19:17:25 +02:00
transitions: [
Transition {
2018-07-22 16:47:55 +02:00
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize" ; easing.type: Easing . InOutQuad ; duration: 700 }
2018-07-17 19:17:25 +02:00
} ,
Transition {
2018-07-18 14:06:04 +02:00
to: "STOPPED"
2018-07-22 16:47:55 +02:00
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize" ; easing.type: Easing . InOutQuad ; duration: 700 }
2018-07-18 14:06:04 +02:00
} ,
Transition {
to: "IDLE"
2018-07-22 16:47:55 +02:00
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize" ; easing.type: Easing . InOutQuad ; duration: 700 }
2018-07-18 14:06:04 +02:00
FadeAnimation { target: time ; fadeDuration_out: 1000 ; fadeDuration_in: 0 }
} ,
Transition {
to: "RUNNING"
//disable transitions for the RUNNING state
2018-07-17 19:17:25 +02:00
}
]
2018-07-22 16:47:55 +02:00
/ * - - - - - - - - - - - - - - - - - - - - - -
Timer functions
-- -- -- -- -- -- -- -- -- -- -- * /
function landscape ( ) {
return ( root . height < root . width )
}
2018-07-17 19:17:25 +02:00
}
}