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() state: "IDLE" Timer { //timer that updates the currTime variable running: true repeat: true interval: 1 onTriggered: { root.currTime = new Date().getTime() } } 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 ----------------------*/ Rectangle { id: startButt property string text: "start" property int size: root.landscape() ? parent.width * 0.5:parent.height * 0.5 anchors { bottom: parent.bottom bottomMargin: parent.height * 0.5 - height * 0.5 right: parent.right rightMargin: parent.width * 0.5 - width * 0.5 } 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 color: "white" border.color: "grey" border.width: 1 radius: width / 2 Label { id: startButt_text text: parent.text anchors.centerIn: parent font.pixelSize: parent.height * 0.16 font.family: "Helvetica" } MouseArea { enabled: startButt.enabled anchors.fill: parent onPressed: parent.color = "lightgrey" onReleased: parent.color = "white" 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 ----------------------*/ Rectangle { id: cancelButt property string text: "cancel" anchors { right: startButt.right bottom: startButt.bottom } height: startButt.height * 0.3 scale: 0 width: height color: "white" border.color: "grey" border.width: 1 radius: width / 2 Label { id: cancelButt_text text: parent.text anchors.centerIn: parent font.pixelSize: parent.height * 0.16 font.family: "Helvetica" } MouseArea { enabled: startSound.playing anchors.fill: parent onPressed: parent.color = "lightgrey" onReleased: parent.color = "white" onClicked: { startSound.stop() root.stoppedTime = 0 time.text = "false start" root.state = "STOPPED" } } Behavior on scale { PropertyAnimation { duration: 200 } } } /*------------------- 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 } Rectangle { id: settingsButt property string text: "cancel" 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 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 } MouseArea { enabled: root.state === "IDLE" anchors.fill: parent onPressed: parent.color = "lightgrey" onReleased: parent.color = "white" onClicked: { } } Behavior on scale { PropertyAnimation { duration: 200 } } } Rectangle { id: profilesButt property string text: "cancel" 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 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 } MouseArea { enabled: root.state === "IDLE" anchors.fill: parent onPressed: parent.color = "lightgrey" onReleased: parent.color = "white" onClicked: { } } Behavior on scale { PropertyAnimation { duration: 200 } } } } /* // 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) } } }