diff --git a/graphics/icons/user.png b/graphics/icons/user.png index 2255aa9..952e933 100644 Binary files a/graphics/icons/user.png and b/graphics/icons/user.png differ diff --git a/graphics/icons/user_black.png b/graphics/icons/user_black.png new file mode 100644 index 0000000..2255aa9 Binary files /dev/null and b/graphics/icons/user_black.png differ diff --git a/headers/climbingrace.h b/headers/climbingrace.h index 5382646..bac10c7 100644 --- a/headers/climbingrace.h +++ b/headers/climbingrace.h @@ -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(); }; diff --git a/qml/ProfilesDialog.qml b/qml/ProfilesDialog.qml index 203675a..dd17bd4 100644 --- a/qml/ProfilesDialog.qml +++ b/qml/ProfilesDialog.qml @@ -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 + } + } + } + } diff --git a/qml/SettingsDialog.qml b/qml/SettingsDialog.qml index c519723..4affffb 100644 --- a/qml/SettingsDialog.qml +++ b/qml/SettingsDialog.qml @@ -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 { diff --git a/qml/main.qml b/qml/main.qml index 27cf705..b47296d 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -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 + } } } } - */ + } diff --git a/shared.qrc b/shared.qrc index 3485eea..a5e6cc5 100644 --- a/shared.qrc +++ b/shared.qrc @@ -25,5 +25,6 @@ graphics/icons/BaseStation_black.png graphics/icons/buzzer.png graphics/icons/startpad.png + graphics/icons/user_black.png diff --git a/sources/apptheme.cpp b/sources/apptheme.cpp index 81db4fd..74e7ddd 100644 --- a/sources/apptheme.cpp +++ b/sources/apptheme.cpp @@ -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; diff --git a/sources/climbingrace.cpp b/sources/climbingrace.cpp index 50922c1..7afce26 100644 --- a/sources/climbingrace.cpp +++ b/sources/climbingrace.cpp @@ -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"));