diff --git a/headers/climbingrace.h b/headers/climbingrace.h
index 19edd77..23f7419 100644
--- a/headers/climbingrace.h
+++ b/headers/climbingrace.h
@@ -101,6 +101,7 @@ public slots:
Q_INVOKABLE bool createAthlete( QString userName, QString fullName );
Q_INVOKABLE bool deleteAthlete( QString userName );
Q_INVOKABLE bool selectAthlete( QString userName );
+ Q_INVOKABLE QVariant getResults( QString userName );
Q_INVOKABLE bool reloadBaseStationIpAdress();
};
diff --git a/qml/ProfilesDialog.qml b/qml/ProfilesDialog.qml
index 3904058..4345c18 100644
--- a/qml/ProfilesDialog.qml
+++ b/qml/ProfilesDialog.qml
@@ -68,7 +68,7 @@ Popup {
StackView {
id: profiles_stack
property int text_pixelSize: headlineUnderline.width * 0.08
- initialItem: profileListComp
+ //initialItem: profileListComp
width: headlineUnderline.width
anchors {
@@ -84,44 +84,48 @@ Popup {
NumberAnimation {duration: 200}
}
+ Connections {
+ target: root
+ onOpened: {
+ profiles_stack.openAthletes()
+ }
+ }
+
+ onCurrentItemChanged: {
+ currentItem.opened()
+ }
+
+ function openAthletes() {
+ var athsComp = profileListComp.createObject(null, {})
+ profiles_stack.push(athsComp)
+ }
+
+ function openResults( userName ){
+ var resComp = resultViewComp.createObject(null, {"userName": userName})
+ profiles_stack.push(resComp)
+ }
+
/*-----List of all profiles-----*/
Component {
id: profileListComp
-
- ListView {
+ RemoteDataListView {
id: profileList
property string title: "profiles"
property string secondButt: "add"
- property var listData: speedBackend.getAthletes()
- function loadData() {
- profileList.enabled = false
+ signal opened()
+
+ onOpened: {
+ loadData()
+ }
+
+ loadData: function () {
+ status = 905
+ listData = {}
listData = speedBackend.getAthletes()
- profileList.enabled = true
- }
-
- model: listData.length
-
- Connections {
- target: root
- onOpened: {
- profileList.loadData()
- }
- }
-
- Label {
- opacity: profileList.count <= 0 ? 1:0
- text: "add a profile by clicking +"
- anchors.centerIn: parent
- font.pixelSize: parent.width*0.06
- Behavior on opacity {
- NumberAnimation {
- duration: 200
- easing.type: Easing.InOutQuad
- }
- }
+ status = listData.lenght !== false ? 200:0
}
delegate: SwipeDelegate {
@@ -141,14 +145,53 @@ Popup {
}
onClicked: {
- if(speedBackend.selectAthlete(profileList.listData[index]["userName"])){
- profileList.loadData()
- }
+ profiles_stack.openResults(profileList.listData[index]["userName"])
}
background: Rectangle {
color: Qt.darker( pressed ? Qt.darker("white", 1.1):"white", swipeDelegate.active ? 1.1:0 )
+ }
+ CheckBox {
+ id: control
+
+ anchors {
+ verticalCenter: parent.verticalCenter
+ right: parent.right
+ }
+
+ height: parent.height * 0.6
+
+ checked: swipeDelegate.active
+
+ onCheckedChanged: {
+ if(checked && !swipeDelegate.active && speedBackend.selectAthlete(profileList.listData[index]["userName"])){
+ profileList.loadData()
+ }
+ }
+
+ indicator: Rectangle {
+ implicitWidth: 26
+ implicitHeight: 26
+
+ height: parent.height
+ width: height
+
+ x: control.leftPadding
+ y: parent.height / 2 - height / 2
+
+ radius: width * 0.2
+ border.color: control.down ? "#17a81a" : "#21be2b"
+
+ Rectangle {
+ width: parent.width * 0.65
+ height: width
+ anchors.centerIn: parent
+ radius: width * 0.2
+ color: control.down ? "#17a81a" : "#21be2b"
+ visible: control.checked
+ }
+ }
}
Rectangle {
@@ -188,9 +231,12 @@ Popup {
height: parent.height
SwipeDelegate.onClicked: {
+ profileList.status = 905
if(speedBackend.deleteAthlete(profileList.listData[index]["userName"])){
profileList.loadData()
+ return
}
+ profileList.status = 200
}
background: Rectangle {
@@ -199,10 +245,7 @@ Popup {
}
}
}
-
- ScrollIndicator.vertical: ScrollIndicator { }
}
-
}
/*-----Option to add a profile-----*/
@@ -220,6 +263,7 @@ Popup {
onClicked: {
if(speedBackend.createAthlete(userNameTf.text, fullNameTf.text)){
+ profiles_stack.get(profiles_stack.depth - 2 ).loadData()
profiles_stack.pop()
}
}
@@ -248,25 +292,99 @@ Popup {
}
}
- /*-----Custom animations-----*/
+ // --- Result View ---
+ Component {
+ id: resultViewComp
+ RemoteDataListView {
+ id: resultView
+ property string userName
+ property string title: userName
+ property string secondButt: "none"
+
+ signal opened()
+
+ onOpened: {
+ loadData()
+ }
+
+ loadData: function () {
+ status = 905
+ listData = {}
+ listData = speedBackend.getResults(userName)
+ status = listData.lenght !== false ? 200:0
+ }
+
+ delegate: ItemDelegate {
+ id: resultDel
+
+ width: parent.width
+
+ font.pixelSize: profiles_stack.text_pixelSize
+
+ text: "result: " + (listData[index]["result"] / 1000).toFixed(3) + " sec \nreaction time: " + listData[index]["reactionTime"].toFixed(0) + " ms"
+
+ Rectangle {
+ color: "grey"
+ height: 1
+ width: parent.width * 0.9
+ visible: index > 0
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ top: parent.top
+ }
+ }
+
+ Label {
+ anchors.top: parent.top
+ anchors.left: parent.left
+
+ font.pixelSize: 10
+
+ text: " " + getText()
+
+ function getText(){
+ var date = new Date(listData[index]["timestamp"]*1000).toLocaleDateString(Qt.locale("de_DE"))
+ return date
+ console.log(date)
+ }
+ }
+ }
+ }
+ }
+
+ /*-----Custom animations-----*/
pushEnter: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1
- duration: 200
+ duration: 300
easing.type: Easing.InOutQuad
}
+
+ NumberAnimation {
+ property: "x"
+ from: width * 0.1
+ to: 0
+ duration: 300
+ }
}
pushExit: Transition {
NumberAnimation {
property: "opacity"
from: 1
to: 0
- duration: 200
+ duration: 300
easing.type: Easing.InOutQuad
}
+
+ NumberAnimation {
+ property: "x"
+ to: -width * 0.1
+ from: 0
+ duration: 300
+ }
}
popExit: Transition {
@@ -274,18 +392,30 @@ Popup {
property: "opacity"
from: 1
to: 0
- duration: 200
+ duration: 300
easing.type: Easing.InOutQuad
}
+ NumberAnimation {
+ property: "x"
+ to: width * 0.1
+ from: 0
+ duration: 300
+ }
}
popEnter: Transition {
NumberAnimation {
property: "opacity"
from: 0
to: 1
- duration: 200
+ duration: 300
easing.type: Easing.InOutQuad
}
+ NumberAnimation {
+ property: "x"
+ from: -width * 0.1
+ to: 0
+ duration: 300
+ }
}
}
@@ -333,14 +463,21 @@ Popup {
onPaint: {
var ctx = getContext("2d");
+ var topMargin = backgroundRect.radius
+
+
ctx.beginPath();
ctx.fillStyle = headerBackground.color
- ctx.moveTo(0, 0);
- //ctx.arc(centreX, centreY, root.width / 2, 1 * Math.PI, 2*Math.PI, false);
- ctx.lineTo(width, 0);
+ ctx.moveTo(width, topMargin);
+ //
+ //ctx.lineTo(width, topMargin);
ctx.lineTo(width, height);
ctx.lineTo(0, height);
- ctx.lineTo(0, 0);
+ ctx.lineTo(0, topMargin)
+
+ ctx.arc(topMargin, topMargin, topMargin, 1 * Math.PI, 1.5*Math.PI, false);
+ ctx.lineTo(width-topMargin, 0)
+ ctx.arc(width-topMargin, topMargin, topMargin, 1.5*Math.PI, 0, false)
ctx.fill();
}
}
@@ -408,6 +545,8 @@ Popup {
height: parent.height * 0.1
width:height
+ opacity: profiles_stack.currentItem.secondButt !== "none" ? 1:0
+
glowOpacity: Math.pow( root.opacity, 100 )
backgroundColor: appTheme.style.buttonColor
diff --git a/qml/SettingsDialog.qml b/qml/SettingsDialog.qml
index 4affffb..4487de4 100644
--- a/qml/SettingsDialog.qml
+++ b/qml/SettingsDialog.qml
@@ -520,6 +520,13 @@ Popup {
duration: 300
easing.type: Easing.InOutQuad
}
+
+ NumberAnimation {
+ property: "x"
+ from: width * 0.1
+ to: 0
+ duration: 300
+ }
}
pushExit: Transition {
NumberAnimation {
@@ -529,6 +536,13 @@ Popup {
duration: 300
easing.type: Easing.InOutQuad
}
+
+ NumberAnimation {
+ property: "x"
+ to: -width * 0.1
+ from: 0
+ duration: 300
+ }
}
popExit: Transition {
@@ -539,6 +553,12 @@ Popup {
duration: 300
easing.type: Easing.InOutQuad
}
+ NumberAnimation {
+ property: "x"
+ to: width * 0.1
+ from: 0
+ duration: 300
+ }
}
popEnter: Transition {
NumberAnimation {
@@ -548,6 +568,12 @@ Popup {
duration: 300
easing.type: Easing.InOutQuad
}
+ NumberAnimation {
+ property: "x"
+ from: -width * 0.1
+ to: 0
+ duration: 300
+ }
}
}
diff --git a/qml/components/FancyBusyIndicator.qml b/qml/components/FancyBusyIndicator.qml
new file mode 100644
index 0000000..32d8421
--- /dev/null
+++ b/qml/components/FancyBusyIndicator.qml
@@ -0,0 +1,95 @@
+import QtQuick 2.3
+import QtQuick.Controls 2.4
+import QtQuick.Controls.Styles 1.2
+
+BusyIndicator {
+ id: control
+
+ property double animationSpeed: 0.5
+
+ contentItem: Item {
+ implicitWidth: 64
+ implicitHeight: 64
+
+ Item {
+ id: item
+
+ x: parent.width / 2 - 32
+ y: parent.height / 2 - 32
+
+ width: 64
+ height: 64
+
+ opacity: control.running ? 1 : 0
+
+ property int currentHeight: 0
+
+ onCurrentHeightChanged: {
+ }
+
+ Behavior on opacity {
+ OpacityAnimator {
+ duration: 250
+ }
+ }
+
+ SequentialAnimation {
+ loops: Animation.Infinite
+
+ running: true
+
+ NumberAnimation {
+ target: item
+
+ duration: 2000 * 1/control.animationSpeed
+
+ to: 1000
+
+ properties: "currentHeight"
+
+ easing.type: Easing.InOutQuad
+
+ }
+
+ NumberAnimation {
+ target: item
+
+ duration: 2000 * 1/control.animationSpeed
+
+ to: 0
+
+ properties: "currentHeight"
+
+ easing.type: Easing.InOutQuad
+
+ }
+ }
+
+ Row {
+
+ anchors.fill: parent
+
+ spacing: item.width / 9
+
+ Repeater {
+ id: repeater
+ model: 5
+
+ Rectangle {
+
+ property double heightMultiplier: Math.abs( Math.sin(( (item.currentHeight + (index*20))*0.01) * (Math.PI/2) ) )
+
+ anchors.verticalCenter: parent.verticalCenter
+
+ width: item.width / 9
+ height: ( heightMultiplier ) * ( item.height - 1 ) + 1
+
+ radius: width * 0.5
+
+ color: "#21be2b"
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/qml/components/RemoteDataListView.qml b/qml/components/RemoteDataListView.qml
new file mode 100644
index 0000000..d9c8ccc
--- /dev/null
+++ b/qml/components/RemoteDataListView.qml
@@ -0,0 +1,77 @@
+import QtQuick 2.9
+import QtQuick.Controls 2.4
+
+Item {
+ id: control
+
+ property var loadData
+ property var listData: ({})
+ property Component delegate
+
+ property int status: -1
+
+ signal refresh()
+
+ Component.onCompleted: {
+
+ }
+
+ ListView {
+ id: listView
+
+ model: control.listData.length
+
+ anchors.fill: parent
+
+
+ enabled: status === 200 || status === 902
+ opacity: enabled ? 1:0
+
+
+ ScrollBar.vertical: ScrollBar {
+ parent: listView.parent
+
+ anchors {
+ top: listView.top
+ left: listView.right
+ margins: 10
+ leftMargin: 3
+ bottom: listView.bottom
+ }
+
+ width: 8
+
+ visible: listView.model > 0
+
+ active: true
+ }
+
+ delegate: control.delegate
+
+ onContentYChanged: {
+/*
+ if(contentY < -listView.height * 0.3 && control.status !== 905){
+ contentY = 0
+ control.refresh()
+ }*/
+ }
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 200
+ }
+ }
+
+ Behavior on contentY {
+ NumberAnimation {
+ duration: 200
+ }
+ }
+
+ }
+
+ FancyBusyIndicator {
+ anchors.centerIn: parent
+ opacity: listView.opacity === 1 ? 0:1
+ }
+}
diff --git a/qml/qml.qrc b/qml/qml.qrc
index 6a1ba34..1043b1e 100644
--- a/qml/qml.qrc
+++ b/qml/qml.qrc
@@ -14,5 +14,7 @@
components/SmoothSwitchDelegate.qml
components/InputDelegate.qml
components/SmoothSliderDelegate.qml
+ components/RemoteDataListView.qml
+ components/FancyBusyIndicator.qml
diff --git a/sources/climbingrace.cpp b/sources/climbingrace.cpp
index bd195be..6e42c0f 100644
--- a/sources/climbingrace.cpp
+++ b/sources/climbingrace.cpp
@@ -459,7 +459,7 @@ QVariant ClimbingRace::getAthletes() {
QVariantList tmpAthletes = reply["data"].toList();
- qDebug() << tmpAthletes;
+ //qDebug() << tmpAthletes;
return tmpAthletes;
}
@@ -503,7 +503,7 @@ bool ClimbingRace::selectAthlete( QString userName){
if(reply["status"] != 200){
//handle Error!!
- qDebug() << "+ --- error deleting athlete: " << reply["status"];
+ qDebug() << "+ --- error selecting athlete: " << reply["status"];
return false;
}
@@ -511,7 +511,21 @@ bool ClimbingRace::selectAthlete( QString userName){
}
+QVariant ClimbingRace::getResults( QString userName ){
+ QVariantMap reply = this->baseConn->sendCommand(4004, userName);
+ if(reply["status"] != 200){
+ //handle Error!!
+ qDebug() << "+ --- error getting results: " << reply["status"];
+ return false;
+ }
+
+ QVariantList tmpAthletes = reply["data"].toList();
+
+ //qDebug() << tmpAthletes;
+
+ return tmpAthletes;
+}
// -------------------------
// --- functions for qml ---