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 QString getBaseStationState();
Q_INVOKABLE QVariant getBaseStationConnections();
Q_INVOKABLE QVariant getAthletes();
Q_INVOKABLE bool reloadBaseStationIpAdress();
};

View file

@ -20,183 +20,50 @@ import QtMultimedia 5.8
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import com.itsblue.speedclimbingstopwatch 1.0
import "./components/ProgressCircle.qml"
import "./components"
Popup {
id: root
x: startButt.x
y: startButt.y
width: startButt.width
height: startButt.height
modal: true
dim: false
opacity: 0
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 {
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 {
radius: width * 0.5
color: "white"
border.color: "grey"
border.width: 1
background: Item {
Label {
id: head_text
text: profiles_stack.currentItem.title
font.pixelSize: headlineUnderline.width * 0.1
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: headlineUnderline.anchors.topMargin / 2 - height / 2
}
RectangularGlow {
id: backgroundEffect
glowRadius: 7
spread: 0.02
color: "black"
opacity: 0.18
anchors.fill: backgroundRect
cornerRadius: backgroundRect.radius
scale: 1
}
Rectangle {
id: headlineUnderline
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.."
id: backgroundRect
anchors.fill: parent
opacity: 0
lineWidth: 5
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
}
}
radius: width * 0.1
color: appTheme.style.viewColor
}
}
ListView {
id: profileModel
model: SqlProfileModel{}
}
StackView {
id: profiles_stack
@ -205,10 +72,10 @@ Popup {
width: headlineUnderline.width
anchors {
top: parent.top
top: topContainerItm.bottom
left: parent.left
leftMargin: ( parent.width - headlineUnderline.width ) / 2
topMargin: headlineUnderline.anchors.topMargin * 1.2
//topMargin: headlineUnderline.anchors.topMargin * 1.2
bottom: parent.bottom
bottomMargin: headlineUnderline.anchors.topMargin
}
@ -220,27 +87,23 @@ Popup {
/*-----List of all profiles-----*/
Component {
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 {
id: profileList
model: profileModel.model
property string title: "profiles"
property string secondButt: "add"
property var listData: speedBackend.getAthletes()
model: listData.length
Connections {
target: root
onOpened: {
listData = speedBackend.getAthletes()
}
}
Label {
opacity: profileList.count <= 0 ? 1:0
@ -257,7 +120,7 @@ Popup {
delegate: SwipeDelegate {
id: swipeDelegate
text: model.name
text: profileList.listData[index]["fullName"]
width: profileList.width
font.pixelSize: profiles_stack.text_pixelSize
@ -357,7 +220,7 @@ Popup {
}
ScrollIndicator.vertical: ScrollIndicator { }
}
*/
}
/*-----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 {
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 {
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 {

View file

@ -481,9 +481,18 @@ Window {
}
}
// ProfilesDialog {
// id: profilesDialog
// }
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
@ -512,6 +521,7 @@ Window {
Item {
id: menu_container
anchors {
bottom: parent.bottom
right: parent.right
@ -533,83 +543,85 @@ Window {
}
}
FancyButton {
id: settingsButt
Grid {
id: loweMenuGrd
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
//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)
}
property int spacingMultiplier: 200 * (getActiveChildren() - 1)
property int activeChildren: getActiveChildren()
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
width: height
onClicked: {
settingsDialog.open()
}
image: appTheme.style.settIcon
backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
}
/*
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"
function getActiveChildren() {
var childrenCount = 0
for (var i = 0; i < children.length; i++)
{
if(children[i].enabled){
childrenCount ++
}
}
else {
background.color = "white"
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
}
}
onClicked: {
profilesDialog.open()
FancyButton {
id: settingsButt
height: root.landscape() ? menu_container.width * 0.7:menu_container.height * 0.7
width: height
onClicked: {
settingsDialog.open()
}
image: appTheme.style.settIcon
backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
}
background: Rectangle {
color: "white"
border.color: "grey"
border.width: 1
radius: width / 2
Item {
height: profilesButt.height
width: profilesButt.height
}
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
FancyButton {
id: profilesButt
enabled: height > 0
height: speedBackend.baseStationState === "connected" ? root.landscape() ? menu_container.width * 0.7:menu_container.height * 0.7:0
width: height
onClicked: {
profilesDialog.open()
}
image: appTheme.style.profilesIcon
backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
Behavior on height {
NumberAnimation {
duration: 200
}
}
}
}
*/
}

View file

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

View file

@ -34,7 +34,8 @@ AppTheme::AppTheme(QObject *parent) : QObject(parent)
{"settIcon", "qrc:/graphics/icons/settings.png"},
{"buzzerIcon", "qrc:/graphics/icons/buzzer.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;
@ -70,7 +71,8 @@ AppTheme::AppTheme(QObject *parent) : QObject(parent)
{"settIcon", "qrc:/graphics/icons/settings_black.png"},
{"buzzerIcon", "qrc:/graphics/icons/buzzer_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;

View file

@ -515,6 +515,22 @@ QVariant ClimbingRace::getBaseStationConnections() {
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() {
if(this->baseConn->state == "disconnected"){
this->baseConn->setIP(pGlobalAppSettings->loadSetting("baseStationIpAdress"));