started to implement athlete management (remote, database on basestation)

This commit is contained in:
Dorian Zedler 2019-04-30 23:44:04 +02:00
parent fea01cf503
commit 271e98f8ec
9 changed files with 301 additions and 245 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -95,6 +95,7 @@ public slots:
Q_INVOKABLE void disconnectBaseStation(); Q_INVOKABLE void disconnectBaseStation();
Q_INVOKABLE QString getBaseStationState(); Q_INVOKABLE QString getBaseStationState();
Q_INVOKABLE QVariant getBaseStationConnections(); Q_INVOKABLE QVariant getBaseStationConnections();
Q_INVOKABLE QVariant getAthletes();
Q_INVOKABLE bool reloadBaseStationIpAdress(); Q_INVOKABLE bool reloadBaseStationIpAdress();
}; };

View file

@ -20,183 +20,50 @@ import QtMultimedia 5.8
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import QtQuick.Controls 2.2 import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import com.itsblue.speedclimbingstopwatch 1.0 import com.itsblue.speedclimbingstopwatch 1.0
import "./components/ProgressCircle.qml" import "./components"
Popup { Popup {
id: root id: root
x: startButt.x
y: startButt.y
width: startButt.width
height: startButt.height
modal: true modal: true
dim: false dim: false
opacity: 0
enter: Transition { enter: Transition {
NumberAnimation { properties: "scale"; from: 0; to: 1; duration: 300; easing.type: Easing.Linear } NumberAnimation { properties: "opacity"; to: 1; duration: 300; easing.type: Easing.InOutQuad }
NumberAnimation { properties: "scale"; from: 0.9; to: 1; duration: 300; easing.type: Easing.InOutQuad }
} }
exit: Transition { exit: Transition {
NumberAnimation { properties: "scale"; from: 1; to: 0; duration: 300; easing.type: Easing.Linear } NumberAnimation { properties: "opacity"; to: 0; duration: 300; easing.type: Easing.InOutQuad }
NumberAnimation { properties: "scale"; from: 1; to: 0.9; duration: 300; easing.type: Easing.InOutQuad }
} }
background: Rectangle { background: Item {
radius: width * 0.5
color: "white"
border.color: "grey"
border.width: 1
Label { RectangularGlow {
id: head_text id: backgroundEffect
text: profiles_stack.currentItem.title glowRadius: 7
font.pixelSize: headlineUnderline.width * 0.1 spread: 0.02
anchors { color: "black"
horizontalCenter: parent.horizontalCenter opacity: 0.18
top: parent.top anchors.fill: backgroundRect
topMargin: headlineUnderline.anchors.topMargin / 2 - height / 2 cornerRadius: backgroundRect.radius
} scale: 1
} }
Rectangle { Rectangle {
id: headlineUnderline id: backgroundRect
height: 1
width: parent.width
color: "grey"
anchors {
top: parent.top
left: parent.left
right: parent.right
topMargin: parent.height * 0.15
rightMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
leftMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
}
}
ProgressCircle {
id: prog
property string text: "connecting.."
anchors.fill: parent anchors.fill: parent
opacity: 0 radius: width * 0.1
lineWidth: 5 color: appTheme.style.viewColor
arcBegin: 0
arcEnd: 0
Timer {
id: prog_refresh
running: false
interval: 1
repeat: true
onTriggered: {
prog.arcEnd = 360 * ( _cppBuzzerConn.get("connection_progress") / 100 )
} }
} }
Label {
id: content
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.width * 0.1
}
}
Button {
id: head_back
anchors {
left: parent.left
leftMargin: parent.width * 0.17
top:parent.top
topMargin: parent.height * 0.01
}
height: parent.height * 0.13
width:height
background: Rectangle {
radius: width * 0.5
color: head_back.pressed ? "lightgrey":"white"
border.color: "grey"
border.width: 1
Image {
anchors.fill: parent
anchors.margins: parent.width * 0.2
source: "qrc:/graphics/icons/back_black.png"
}
}
onClicked: profiles_stack.depth > 1 ? profiles_stack.pop():root.close()
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
}
Button {
id: head_add
anchors {
right: parent.right
rightMargin: parent.width * 0.17
top:parent.top
topMargin: parent.height * 0.01
}
height: parent.height * 0.13
width:height
background: Rectangle {
radius: width * 0.5
color: parent.pressed ? "lightgrey":"white"
border.color: "grey"
border.width: 1
Label {
anchors {
top: parent.top
topMargin: parent.height/2 - height*0.55
left: parent.left
leftMargin: parent.width/2 - width/2
}
opacity: profiles_stack.currentItem.secondButt === "add" ? 1:0
text: "+"
font.pixelSize: parent.height
}
Image {
anchors.fill: parent
anchors.margins: parent.width * 0.2
source: "qrc:/graphics/icons/ok_black.png"
opacity: profiles_stack.currentItem.secondButt === "ok" ? 1:0
}
}
onClicked: {
switch(profiles_stack.currentItem.secondButt){
case "add":
profiles_stack.push(addProfileComp)
break
case "ok":
if(profileModel.model.append(profiles_stack.currentItem.newProfileName)){
profiles_stack.pop()
}
}
}
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
}
}
ListView {
id: profileModel
model: SqlProfileModel{}
}
StackView { StackView {
id: profiles_stack id: profiles_stack
@ -205,10 +72,10 @@ Popup {
width: headlineUnderline.width width: headlineUnderline.width
anchors { anchors {
top: parent.top top: topContainerItm.bottom
left: parent.left left: parent.left
leftMargin: ( parent.width - headlineUnderline.width ) / 2 leftMargin: ( parent.width - headlineUnderline.width ) / 2
topMargin: headlineUnderline.anchors.topMargin * 1.2 //topMargin: headlineUnderline.anchors.topMargin * 1.2
bottom: parent.bottom bottom: parent.bottom
bottomMargin: headlineUnderline.anchors.topMargin bottomMargin: headlineUnderline.anchors.topMargin
} }
@ -220,27 +87,23 @@ Popup {
/*-----List of all profiles-----*/ /*-----List of all profiles-----*/
Component { Component {
id: profileListComp id: profileListComp
Tumbler {
id: control
property string title: "profiles"
property string secondButt: "add"
model: SqlProfileModel{}
delegate: Text {
text: model.name
color: control.visualFocus ? control.palette.highlight : control.palette.text
font: control.font
opacity: 1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2)
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
/*
ListView { ListView {
id: profileList id: profileList
model: profileModel.model
property string title: "profiles" property string title: "profiles"
property string secondButt: "add" property string secondButt: "add"
property var listData: speedBackend.getAthletes()
model: listData.length
Connections {
target: root
onOpened: {
listData = speedBackend.getAthletes()
}
}
Label { Label {
opacity: profileList.count <= 0 ? 1:0 opacity: profileList.count <= 0 ? 1:0
@ -257,7 +120,7 @@ Popup {
delegate: SwipeDelegate { delegate: SwipeDelegate {
id: swipeDelegate id: swipeDelegate
text: model.name text: profileList.listData[index]["fullName"]
width: profileList.width width: profileList.width
font.pixelSize: profiles_stack.text_pixelSize font.pixelSize: profiles_stack.text_pixelSize
@ -357,7 +220,7 @@ Popup {
} }
ScrollIndicator.vertical: ScrollIndicator { } ScrollIndicator.vertical: ScrollIndicator { }
} }
*/
} }
/*-----Option to add a profile-----*/ /*-----Option to add a profile-----*/
@ -422,4 +285,163 @@ Popup {
} }
} }
} }
Item {
id: topContainerItm
anchors {
top: parent.top
horizontalCenter: parent.horizontalCenter
}
height: parent.height * 0.15
width: backgroundRect.width
RectangularGlow {
id: headerUnderlineEffect
glowRadius: 7
spread: 0.02
color: "black"
opacity: 0.18
anchors.fill: headlineUnderline
scale: 1
}
Rectangle {
id: headlineUnderline
height: 1
width: parent.width
color: "grey"
anchors {
bottom: parent.bottom
left: parent.left
right: parent.right
}
}
Canvas {
id: headerBackground
anchors.fill: parent
property color color: appTheme.style.viewColor
onPaint: {
var ctx = getContext("2d");
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.lineTo(width, height);
ctx.lineTo(0, height);
ctx.lineTo(0, 0);
ctx.fill();
}
}
Label {
id: head_text
anchors {
centerIn: parent
}
width: parent.width * 0.8
height: parent.height * 0.8
fontSizeMode: Text.Fit
font.pixelSize: headlineUnderline.width * 0.1
minimumPixelSize: 0
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: profiles_stack.currentItem.title
}
}
FancyButton {
id: head_back
anchors {
left: parent.left
leftMargin: -parent.width * 0.03
top:parent.top
topMargin: -parent.height * 0.03
}
height: parent.height * 0.1
width: height
glowOpacity: Math.pow( root.opacity, 100 )
backgroundColor: appTheme.style.buttonColor
image: "qrc:/graphics/icons/back_black.png"
onClicked: profiles_stack.depth > 1 ? profiles_stack.pop():root.close()
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
}
FancyButton {
id: head_add
anchors {
right: parent.right
rightMargin: -parent.width * 0.03
top:parent.top
topMargin: -parent.height * 0.03
}
height: parent.height * 0.1
width:height
glowOpacity: Math.pow( root.opacity, 100 )
backgroundColor: appTheme.style.buttonColor
image: "qrc:/graphics/icons/ok_black.png"
imageScale: profiles_stack.currentItem.secondButt === "ok" ? 1:0
Label {
anchors {
top: parent.top
topMargin: parent.height/2 - height*0.55
left: parent.left
leftMargin: parent.width/2 - width/2
}
opacity: profiles_stack.currentItem.secondButt === "add" ? 1:0
text: "+"
font.pixelSize: parent.height
}
onClicked: {
switch(profiles_stack.currentItem.secondButt){
case "add":
profiles_stack.push(addProfileComp)
break
case "ok":
if(profileModel.model.append(profiles_stack.currentItem.newProfileName)){
profiles_stack.pop()
}
}
}
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
}
} }

View file

@ -58,10 +58,12 @@ Popup {
enter: Transition { enter: Transition {
NumberAnimation { properties: "opacity"; to: 1; duration: 300; easing.type: Easing.InOutQuad } NumberAnimation { properties: "opacity"; to: 1; duration: 300; easing.type: Easing.InOutQuad }
NumberAnimation { properties: "scale"; from: 0.9; to: 1; duration: 300; easing.type: Easing.InOutQuad }
} }
exit: Transition { exit: Transition {
NumberAnimation { properties: "opacity"; to: 0; duration: 300; easing.type: Easing.InOutQuad } NumberAnimation { properties: "opacity"; to: 0; duration: 300; easing.type: Easing.InOutQuad }
NumberAnimation { properties: "scale"; from: 1; to: 0.9; duration: 300; easing.type: Easing.InOutQuad }
} }
background: Rectangle { background: Rectangle {

View file

@ -481,9 +481,18 @@ Window {
} }
} }
// ProfilesDialog { ProfilesDialog {
// id: profilesDialog id: profilesDialog
// }
property int margin: root.landscape() ? root.height * 0.05:root.width * 0.05
x: root.landscape() ? topContainerItm.width + margin:topContainerItm.x + margin
y: !root.landscape() ? topContainerItm.height + margin:topContainerItm.x + margin
width: root.landscape() ? root.width - topContainerItm.width - menu_container.width - margin * 2 : root.width - margin * 2
height: !root.landscape() ? root.height - topContainerItm.height - menu_container.height - margin * 2 : root.height - margin * 2
}
/*------------------- /*-------------------
lower line and menu lower line and menu
@ -512,6 +521,7 @@ Window {
Item { Item {
id: menu_container id: menu_container
anchors { anchors {
bottom: parent.bottom bottom: parent.bottom
right: parent.right right: parent.right
@ -533,25 +543,44 @@ Window {
} }
} }
Grid {
id: loweMenuGrd
property int spacingMultiplier: 200 * (getActiveChildren() - 1)
property int activeChildren: getActiveChildren()
function getActiveChildren() {
var childrenCount = 0
for (var i = 0; i < children.length; i++)
{
if(children[i].enabled){
childrenCount ++
}
}
return childrenCount
}
anchors.centerIn: parent
height: childrenRect.height
width: childrenRect.width
rows: root.landscape() ? activeChildren:1
columns: root.landscape() ? 1:activeChildren
spacing: 0// root.landscape() ? parent.height * spacingMultiplier * 0.001:parent.width * spacingMultiplier * 0.001
Behavior on spacingMultiplier {
NumberAnimation {
duration: 200
}
}
FancyButton { FancyButton {
id: settingsButt id: settingsButt
anchors { height: root.landscape() ? menu_container.width * 0.7:menu_container.height * 0.7
//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
//for two buttons: topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
topMargin: root.landscape() ? (parent.height * 0.5 - (height * 0.5)):undefined
//align in portrait mode
//for two buttons: leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
leftMargin: root.landscape() ? undefined:(parent.width * 0.5 - width * 0.5)
}
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
width: height width: height
onClicked: { onClicked: {
@ -564,52 +593,35 @@ Window {
} }
/* Item {
RoundButton { height: profilesButt.height
width: profilesButt.height
}
FancyButton {
id: profilesButt id: profilesButt
anchors { enabled: height > 0
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 height: speedBackend.baseStationState === "connected" ? root.landscape() ? menu_container.width * 0.7:menu_container.height * 0.7:0
width: height width: height
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
onClicked: { onClicked: {
profilesDialog.open() profilesDialog.open()
} }
background: Rectangle { image: appTheme.style.profilesIcon
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Image { backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
id: profilesButt_Image
source: "qrc:/graphics/icons/user.png" Behavior on height {
anchors.centerIn: parent NumberAnimation {
height: parent.height * 0.5 duration: 200
width: parent.width * 0.5
mipmap: true
} }
} }
} }
*/ }
} }

View file

@ -25,5 +25,6 @@
<file>graphics/icons/BaseStation_black.png</file> <file>graphics/icons/BaseStation_black.png</file>
<file>graphics/icons/buzzer.png</file> <file>graphics/icons/buzzer.png</file>
<file>graphics/icons/startpad.png</file> <file>graphics/icons/startpad.png</file>
<file>graphics/icons/user_black.png</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -34,7 +34,8 @@ AppTheme::AppTheme(QObject *parent) : QObject(parent)
{"settIcon", "qrc:/graphics/icons/settings.png"}, {"settIcon", "qrc:/graphics/icons/settings.png"},
{"buzzerIcon", "qrc:/graphics/icons/buzzer.png"}, {"buzzerIcon", "qrc:/graphics/icons/buzzer.png"},
{"startpadIcon", "qrc:/graphics/icons/startpad.png"}, {"startpadIcon", "qrc:/graphics/icons/startpad.png"},
{"baseStationIcon", "qrc:/graphics/icons/BaseStation.png"} {"baseStationIcon", "qrc:/graphics/icons/BaseStation.png"},
{"profilesIcon", "qrc:/graphics/icons/user.png"}
}; };
this->darkTheme = tmpDarkTheme; this->darkTheme = tmpDarkTheme;
@ -70,7 +71,8 @@ AppTheme::AppTheme(QObject *parent) : QObject(parent)
{"settIcon", "qrc:/graphics/icons/settings_black.png"}, {"settIcon", "qrc:/graphics/icons/settings_black.png"},
{"buzzerIcon", "qrc:/graphics/icons/buzzer_black.png"}, {"buzzerIcon", "qrc:/graphics/icons/buzzer_black.png"},
{"startpadIcon", "qrc:/graphics/icons/startpad_black.png"}, {"startpadIcon", "qrc:/graphics/icons/startpad_black.png"},
{"baseStationIcon", "qrc:/graphics/icons/BaseStation_black.png"} {"baseStationIcon", "qrc:/graphics/icons/BaseStation_black.png"},
{"profilesIcon", "qrc:/graphics/icons/user_black.png"}
}; };
this->lightTheme = tmpLightTheme; this->lightTheme = tmpLightTheme;

View file

@ -515,6 +515,22 @@ QVariant ClimbingRace::getBaseStationConnections() {
return baseConn->getConnections(); return baseConn->getConnections();
} }
QVariant ClimbingRace::getAthletes() {
QVariantMap reply = this->baseConn->sendCommand(4003);
if(reply["status"] != 200){
//handle Error!!
qDebug() << "+ --- error getting athletes: " << reply["status"];
return false;
}
QVariantList tmpAthletes = reply["data"].toList();
qDebug() << tmpAthletes;
return tmpAthletes;
}
bool ClimbingRace::reloadBaseStationIpAdress() { bool ClimbingRace::reloadBaseStationIpAdress() {
if(this->baseConn->state == "disconnected"){ if(this->baseConn->state == "disconnected"){
this->baseConn->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress")); this->baseConn->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));