From 42464d5a13631bf3e311139cf61b6df09b374852 Mon Sep 17 00:00:00 2001 From: dorian Date: Fri, 24 May 2019 14:15:07 +0200 Subject: [PATCH] moved everything to the new widget structure --- resources/qml/Components/RegistrationView.qml | 98 --- resources/qml/Components/ResultView.qml | 458 ------------- resources/qml/Components/StartlistView.qml | 111 --- resources/qml/Pages/AthleteProfilePage.qml | 388 ----------- .../qml/Pages/CompetitionCalendarPage.qml | 630 ------------------ resources/qml/Pages/RankingPage.qml | 514 -------------- resources/qml/Pages/StartPage.qml | 6 +- resources/qml/Pages/WidgetPage.qml | 33 +- resources/qml/Widgets/CalendarWidget.qml | 77 ++- resources/qml/Widgets/ProfileWidget.qml | 26 +- .../RankingWidget.qml} | 42 +- resources/qml/Widgets/RegistrationWidget.qml | 144 +++- resources/qml/Widgets/ResultWidget.qml | 612 ++++++++++++++++- resources/qml/Widgets/StartlistWidget.qml | 212 ++++++ resources/qml/main.qml | 59 +- resources/qml/qml.qrc | 9 +- 16 files changed, 1050 insertions(+), 2369 deletions(-) delete mode 100644 resources/qml/Components/RegistrationView.qml delete mode 100644 resources/qml/Components/ResultView.qml delete mode 100644 resources/qml/Components/StartlistView.qml delete mode 100644 resources/qml/Pages/AthleteProfilePage.qml delete mode 100644 resources/qml/Pages/CompetitionCalendarPage.qml delete mode 100644 resources/qml/Pages/RankingPage.qml rename resources/qml/{Components/RankingView.qml => Widgets/RankingWidget.qml} (82%) create mode 100644 resources/qml/Widgets/StartlistWidget.qml diff --git a/resources/qml/Components/RegistrationView.qml b/resources/qml/Components/RegistrationView.qml deleted file mode 100644 index 56ebad4..0000000 --- a/resources/qml/Components/RegistrationView.qml +++ /dev/null @@ -1,98 +0,0 @@ -/* - blueROCK - for digital rock - Copyright (C) 2019 Dorian Zedler - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import QtQuick 2.9 -import QtQuick.Controls 2.4 - -DataListView { - id: control - - property var listData: ({}) - - model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length - - delegate: ItemDelegate { - id: partDel - - property var thisData: listData[ "athletes" ][index] - - width: parent.width - height: parseInt(thisData.cat) === root.catId ? undefined:0 - - opacity: 0 - scale: 0.9 - - onThisDataChanged: { - fadeInPa.start() - } - - onClicked: { - app.openAthlete(thisData["PerId"]) - } - - ParallelAnimation { - id: fadeInPa - NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 } - NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } - } - - text: "" - - Label { - anchors.fill: parent - anchors.leftMargin: parent.width * 0.05 - - verticalAlignment: Text.AlignVCenter - - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( height * 0.4 ) - minimumPixelSize: height * 0.3 - - elide: "ElideRight" - - text: control.getText(index) - } - } - - function getText(index){ - - // ---------------------------- - // if we have registration data - - var fedName // federation name - - if(listData["federations"] !== undefined){ - // not an international competition -> get name of federation - - for(var i = 0; i < listData["federations"].length; i ++ ){ - //console.log("checking " + i + ": cat: " + parseInt(listData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) - if(listData["federations"][i]["fed_id"] === listData[ root.listKey ][index]["reg_fed_id"]){ - fedName = listData["federations"][i]["shortcut"] - } - } - } - else { - // an international competition -> get nation - - fedName = listData[ root.listKey ][index]["nation"] - } - - return listData[ "athletes" ][index]["firstname"] + " " + listData[ "athletes" ][index]["lastname"] + " (" + fedName + ")" - } -} diff --git a/resources/qml/Components/ResultView.qml b/resources/qml/Components/ResultView.qml deleted file mode 100644 index f3621fe..0000000 --- a/resources/qml/Components/ResultView.qml +++ /dev/null @@ -1,458 +0,0 @@ -/* - blueROCK - for digital rock - Copyright (C) 2019 Dorian Zedler - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import QtQuick 2.9 -import QtQuick.Controls 2.4 - -DataListView { - id: control - - property var listData: ({}) - - onListDataChanged: { - model = listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length - } - - model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length - - delegate: ItemDelegate { - id: partDel - - property int ind: index - property var thisData: listData[ "participants" ][partDel.ind] - - width: parent.width - height: 70 - - text: "" - - opacity: 0 - scale: 0.9 - - onThisDataChanged: { - fadeInPa.start() - } - - onClicked: { - app.openAthlete(thisData["PerId"]) - } - - ParallelAnimation { - id: fadeInPa - NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 } - NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } - } - - - Rectangle { - anchors.fill: parent - - width: partDel.width - - color: partDel.ind % 2 == 0 ? "white":"lightgrey" - - opacity: 0.2 - } - - Column { - id: partDelCol - - anchors.fill: parent - anchors.margins: 5 - - Row { - id: partDelFirstRow - - width: parent.width - height: parent.height - partDelSecondRow.height - - Label { - height: parent.height - width: text === "" ? parent.width * 0.08:parent.width * 0.1 - - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: listData[ "participants" ][index]["result_rank"] === undefined ? "":listData[ "participants" ][index]["result_rank"] - } - - Label { - height: parent.height - width: parent.width * 0.5 - - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - - text: listData[ "participants" ][index]["firstname"] + " " + listData[ "participants" ][index]["lastname"] - } - - Label { - height: parent.height - width: parent.width * 0.4 - - fontSizeMode: Text.Fit - font.bold: false - font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.4:height * 0.3 ) - minimumPixelSize: height * 0.3 - - elide: "ElideRight" - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: "(" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + ")" - - onLinkActivated: { - Qt.openUrlExternally(link) - } - } - } - - Row { - id: partDelSecondRow - - width: parent.width - height: multiResRow.enabled || multiGenResRow.enabled || resultLa.enabled ? parent.height / 2:0 - - Row { - id: multiResRow - - height: parent.height - width: enabled ? parent.width * 0.75:0 - - enabled: parseInt(listData[ "route_order" ]) > -1 && boulderResRep.model > 0 - - Repeater { - id: boulderResRep - - model: parseInt(listData[ "route_num_problems" ]) - - function getDataForIcon(index){ - var resultString = listData[ "participants" ][partDel.ind]["boulder"+(index+1)] - - var resultList = [] - - if( resultString !== undefined){ - resultString = resultString.replace("t", "") - resultString = resultString.replace("z", "") - resultString = resultString.replace("b", "") - resultList = resultString.split(" ") - } - - - while (resultList.length < 2){ - resultList.unshift(0) - } - - return resultList - } - - delegate: Item { - id: boulderResItm - - anchors.verticalCenter: parent.verticalCenter - - width: parent.width / ( boulderResRep.model ) - height: parent.height - - Canvas { - id: boulderResCv - - property var resultData: boulderResRep.getDataForIcon(index) - - onResultDataChanged: { - boulderResCv.requestPaint() - } - - anchors.centerIn: parent - - height: parent.height > parent.width ? parent.width * 0.9:parent.height * 0.9 - width: height - - onPaint: { - var width = 24//boulderResCv.width * 0.9 - var height = width - - var radius = width * 0.3 - - var offsetX = width * 0.05 - var offsetY = height * 0.05 - - //console.log("drawing result rect with width: " + width + " and height: " + height) - - var context = getContext("2d"); - - context.beginPath(); - - context.moveTo(0 + offsetX + radius, 0 + offsetY); - - // top line - context.lineTo(width - radius + offsetX, 0 + offsetY); - // top right corner - context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 0); - // right line - context.lineTo(width + offsetX, height - radius + offsetY); - // bottom right corner - context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI); - // bottom line - context.lineTo(0 + radius + offsetX, height + offsetY); - // bottom left corner - context.arc(radius + offsetY, height - radius + offsetY, radius, 0.5 * Math.PI, Math.PI); - // left line - context.lineTo(0 + offsetX, radius + offsetY); - // top left corner - context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI); - - // fill - context.fillStyle = "#b7b7b7"; - context.fill(); - - // outline - context.lineWidth = 1; - context.strokeStyle = '#424242'; - context.stroke(); - - if(resultData[1] > 0){ - - // the first triangle - context.beginPath(); - - // top right corner - context.arc(width-radius + offsetX, radius + offsetY, radius, 1.75 * Math.PI, 0); - - // right line - context.lineTo(width + offsetX, height - radius + offsetY); - - // bottom right corner - context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI); - - // bottom line - context.lineTo(0 + radius + offsetX, height + offsetY); - // bottom left corner - context.arc(radius + offsetX, height - radius + offsetY, radius, 0.5 * Math.PI, 0.75 * Math.PI); - context.closePath(); - - context.fillStyle = "#44ed38"; - context.fill(); - - // outline - context.lineWidth = 1; - context.strokeStyle = '#424242'; - context.stroke(); - - - if(resultData[0] > 0){ - // the second triangle - context.beginPath(); - // bottom left corner - context.arc(radius + offsetX, height - radius + offsetY, radius, 0.75 * Math.PI, 1 * Math.PI); - // left line - context.lineTo(0 + offsetX, radius + offsetY); - // top left corner - context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI); - // top line - context.lineTo(width - radius + offsetX, 0 + offsetY); - // top right corner - context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 1.75 * Math.PI); - - context.closePath(); - - context.fillStyle = "#44ed38"; - context.fill(); - - // outline - context.lineWidth = 1; - context.strokeStyle = '#424242'; - context.stroke(); - } - } - - } - - Label { - id: boulderResZoneLa - - anchors { - right: parent.right - bottom: parent.bottom - margins: boulderResCv.height * 0.05 - } - - height: parent.height / 2 - width: parent.width / 2 - - visible: text !== "0" - - fontSizeMode: Text.Fit - font.pixelSize: height - minimumPixelSize: 1 - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: boulderResCv.resultData[1] - } - - Label { - id: boulderResTopLa - - anchors { - left: parent.left - top: parent.top - margins: boulderResCv.height * 0.05 - } - - height: parent.height / 2 - width: parent.width / 2 - - visible: text !== "0" - - fontSizeMode: Text.Fit - font.pixelSize: height - minimumPixelSize: 1 - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: boulderResCv.resultData[0] - } - } - - } - - } - - } - - Row { - id: multiGenResRow - - height: parent.height - width: enabled ? parent.width - resultLa.width:0 - - enabled: ((parseInt(listData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false - - Repeater { - id: generalResRep - - property var routes: getRoutes() - model: routes.length - - function getRoutes() { - - var obj = listData["route_names"] - var routes = [] - - for(var prop in obj) { - // go through the whole array and search for data keys - if (obj.hasOwnProperty(prop) && prop > -1) { - routes.push([prop, obj[prop]]) - //console.log("found " + obj[prop] + " at index " + prop) - } - } - - routes.sort(function(a, b) { - return a[0] - b[0]; - }); - - return routes - } - - delegate: Item { - id: boulderGenResItm - - anchors.verticalCenter: parent.verticalCenter - - width: parent.width / ( generalResRep.model ) - height: parent.height - - visible: boulderGenResLa.text != "" - - Rectangle { - - anchors { - left: parent.left - } - - width: 1 - height: parent.height - - visible: index === 0 - - color: "grey" - } - - Rectangle { - anchors { - right: parent.right - } - - width: 1 - height: parent.height - - color: "grey" - } - - Label { - id: boulderGenResLa - anchors.centerIn: parent - - height: parent.height - width: parent.width * 0.9 - - fontSizeMode: Text.Fit - font.pixelSize: Math.abs( height * 0.6 ) - minimumPixelSize: 1 - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: listData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] === undefined ? "":listData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] - } - - } - - } - } - - Label { - id: resultLa - - width: enabled ? parent.width * 0.25:0 - height: enabled ? parent.height:0 - - enabled: ( boulderResRep.model > 0 || listData["discipline"] !== "boulder" ) && parseInt(listData[ "route_order" ]) > -1 - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - fontSizeMode: Text.Fit - font.pixelSize: Math.abs( height * 0.6 ) - minimumPixelSize: 1 - - text: listData[ "participants" ][partDel.ind]["result"] === undefined ? "":listData[ "participants" ][partDel.ind]["result"] - } - } - } - } -} diff --git a/resources/qml/Components/StartlistView.qml b/resources/qml/Components/StartlistView.qml deleted file mode 100644 index ff836db..0000000 --- a/resources/qml/Components/StartlistView.qml +++ /dev/null @@ -1,111 +0,0 @@ -/* - blueROCK - for digital rock - Copyright (C) 2019 Dorian Zedler - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import QtQuick 2.0 -import QtQuick.Controls 2.4 - -DataListView { - id: control - - property var listData: ({}) - - model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length - - delegate: ItemDelegate { - id: partDel - - property var thisData: listData[ "participants" ][index] - - width: parent.width - - opacity: 0 - scale: 0.9 - - onThisDataChanged: { - fadeInPa.start() - } - - onClicked: { - app.openAthlete(thisData["PerId"]) - } - - ParallelAnimation { - id: fadeInPa - NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 } - NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } - } - - text: "" - - Row { - id: partDelFirstRow - - width: parent.width - height: parent.height - - Label { - height: parent.height - width: parent.width * 0.1 - - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( height * 0.6 ) - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: listData[ "participants" ][index]["start_order"] - } - - Label { - height: parent.height - width: parent.width * 0.5 - - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( height * 0.45 ) - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignLeft - minimumPixelSize: 1 - - text: listData[ "participants" ][index]["firstname"] + " " + listData[ "participants" ][index]["lastname"] - } - - Label { - height: parent.height - width: parent.width * 0.3 - - fontSizeMode: Text.Fit - font.bold: false - font.pixelSize: Math.abs( height * 0.4 ) - minimumPixelSize: height * 0.3 - - elide: "ElideRight" - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: "(" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + ")" - - onLinkActivated: { - Qt.openUrlExternally(link) - } - } - } - - } -} diff --git a/resources/qml/Pages/AthleteProfilePage.qml b/resources/qml/Pages/AthleteProfilePage.qml deleted file mode 100644 index 6acde5b..0000000 --- a/resources/qml/Pages/AthleteProfilePage.qml +++ /dev/null @@ -1,388 +0,0 @@ -import QtQuick 2.9 -import QtQuick.Controls 2.4 -import QtQuick.Controls.Material 2.3 - -import "../Components" - -Page { - id: root - - title: perData["firstname"] + " " + perData["lastname"] - property bool titleIsPageTitle: true - property bool ready - property int status: -1 - - property int perId: -1 - - property var perData: ({}) - - Component.onCompleted: { - if(root.loadData(root.perId)){ - root.ready = true - } - } - - function loadData(perId) { - console.log("loading athlete: ", perId) - - root.status = 905 - - var ret = serverConn.getAthlete(perId) - - root.status = ret["status"] - - if(ret["status"] === 200){ - root.perData = ret["data"] - return true - } - else { - return false - } - } - - ScrollView { - id: mainSv - - anchors.fill: parent - anchors.margins: 10 - anchors.rightMargin: 14 - - contentWidth: parent.width - anchors.leftMargin - anchors.rightMargin - - ScrollBar.vertical: ScrollBar { - - anchors { - top: mainSv.top - left: mainSv.right - margins: 10 - leftMargin: 3 - bottom: mainSv.bottom - } - - width: 8 - - active: true - } - - Column { - id: mainCol - - width: parent.width - - Row { - height: root.height * 0.3 - width: parent.width - - Image { - id: photo - - property bool ready: false - - anchors.verticalCenter: parent.verticalCenter - - height: parent.height * 0.9 - width: status === Image.Null || status === Image.Error ? 0:parent.width * 0.5 - - fillMode: Image.PreserveAspectFit - - source: perData["photo"] === undefined ? "":perData["photo"].replace("https", "http").replace("www.digitalrock.de", "egw.ifsc-climbing.org") - asynchronous: true - - FancyBusyIndicator { - height: width - anchors.centerIn: parent - opacity: photo.status === Image.Loading - } - } - - Column { - - anchors.verticalCenter: parent.verticalCenter - - height: parent.height * 0.9 - width: parent.width - photo.width - - Label { - - height: parent.height * 0.2 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: true - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: perData["firstname"] + " " + perData["lastname"] - } - - Label { - height: parent.height * 0.2 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: false - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: perData["nation"] - } - - Label { - height: parent.height * 0.15 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: false - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: "" + perData["federation"] + "" - - onLinkActivated: { - Qt.openUrlExternally(link) - } - } - - Label { - height: parent.height * 0.15 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: false - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: qsTr("age") + ": " + perData["age"] - } - - Label { - height: parent.height * 0.15 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: false - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: qsTr("year of birth") + ": " + perData["birthdate"] - } - - Label { - height: parent.height * 0.15 - width: parent.width - - font.pixelSize: height * 0.6 - font.bold: false - minimumPixelSize: 1 - - fontSizeMode: Text.Fit - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - text: qsTr("city") + ": " + perData["city"] - } - } - - } - - Label { - anchors.horizontalCenter: parent.horizontalCenter - - visible: bestResultsRep.model > 0 - - width: parent.width - - wrapMode: Label.Wrap - - text: perData["freetext"] - - } - - Rectangle { - id: separatorLine - - anchors.horizontalCenter: parent.horizontalCenter - - height: 1 - width: parent.width * 0.9 - - color: "black" - - } - - Button { - id: toggleAllResultsBt - anchors.horizontalCenter: parent.horizontalCenter - - visible: bestResultsRep.model > 0 - - flat: true - - text: bestResultsRep.showAllResults ? qsTr("show best results"):qsTr("show all results") - - onClicked: { - bestResultsRep.showAllResults = !bestResultsRep.showAllResults - } - - Behavior on text { - FadeAnimation { - target: toggleAllResultsBt - fadeDuration: 150 - } - } - - } - - Repeater { - id: bestResultsRep - - property var bestResults: showAllResults ? getAllResults() : getBestResults() - property bool showAllResults: false - - function getBestResults(){ - - var allResults = root.perData["results"] - - allResults.sort(function(a, b) { - // sort results by weight - var year = new Date().getFullYear(); - var weightA = a.rank/2 + (year-parseInt(a.date)) + 4*!a.nation; - var weightB = b.rank/2 + (year-parseInt(b.date)) + 4*!b.nation; - return weightA - weightB; - }); - - var bestResults = allResults.slice(0,12) - - bestResults.sort(function(a, b) { - // sort results by date - var aTs = Date.fromLocaleString(Qt.locale(), a["date"], "yyyy-MM-dd").getTime() - var bTs = Date.fromLocaleString(Qt.locale(), b["date"], "yyyy-MM-dd").getTime() - return bTs - aTs; - }); - - return bestResults - } - - function getAllResults() { - var allResults = root.perData["results"] - - allResults.sort(function(a, b) { - // sort results by date - var aTs = Date.fromLocaleString(Qt.locale(), a["date"], "yyyy-MM-dd").getTime() - var bTs = Date.fromLocaleString(Qt.locale(), b["date"], "yyyy-MM-dd").getTime() - return bTs - aTs; - }); - - return allResults - } - - width: parent.width - - model: bestResults.length - - delegate: Row { - id: bestResultRow - - property var thisData: bestResultsRep.bestResults[index] - - width: parent.width - height: 50 - - opacity: 0 - scale: 0.9 - - onThisDataChanged: { - fadeInPa.start() - } - - ParallelAnimation { - id: fadeInPa - NumberAnimation { target: bestResultRow; property: "opacity"; from: 0; to: 1.0; duration: 400 } - NumberAnimation { target: bestResultRow; property: "scale"; from: 0.8; to: 1.0; duration: 400 } - } - - Label { - id: bestResultRankLa - - width: parent.width * 0.2 - height: parent.height - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - fontSizeMode: Text.Fit - minimumPixelSize: 1 - - font.pixelSize: height * 0.6 - - text: bestResultsRep.bestResults[index]["rank"] - } - - Label { - id: bestResultCompLa - - width: parent.width * 0.6 - height: parent.height - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - fontSizeMode: Text.Fit - minimumPixelSize: height * 0.3 - - font.pixelSize: height * 0.3 - - elide: "ElideRight" - - text: "" + bestResultsRep.bestResults[index]["name"] + "" - - onLinkActivated: { - app.openResults( bestResultsRep.bestResults[index]["WetId"], bestResultsRep.bestResults[index]["GrpId"], 1 ) - } - } - - Label { - id: bestResultDateLa - - width: parent.width * 0.2 - height: parent.height - - scale: 0.8 - - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - - fontSizeMode: Text.Fit - minimumPixelSize: 1 - - font.pixelSize: height * 0.6 - - text: bestResultsRep.bestResults[index]["date"] - } - } - } - - } - } -} diff --git a/resources/qml/Pages/CompetitionCalendarPage.qml b/resources/qml/Pages/CompetitionCalendarPage.qml deleted file mode 100644 index 2bb6e11..0000000 --- a/resources/qml/Pages/CompetitionCalendarPage.qml +++ /dev/null @@ -1,630 +0,0 @@ -/* - blueROCK - for digital rock - Copyright (C) 2019 Dorian Zedler - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import QtQuick 2.9 -import QtQuick.Controls 2.4 -import QtQuick.Controls.Material 2.3 - -import "../Components" - -Page { - id: root - - title: (nation === "" ? "IFSC":nation === "GER" ? "DAV":"SAC") + " " + qsTr("competition calendar") - - property bool ready - - property Component headerComponent: Item { - anchors.fill: parent - - Row { - anchors.fill: parent - anchors.rightMargin: 5 - - spacing: width * 0.05 - - Label { - anchors.verticalCenter: parent.verticalCenter - - width: parent.width * 0.4 - height: parent.height * 0.6 - - fontSizeMode: Text.Fit - font.pixelSize: height - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignHCenter - minimumPixelSize: 1 - - text: root.year - - } - - Button { - id:yearToolBt - - anchors { - verticalCenter: parent.verticalCenter - } - - height: parent.height * 0.5 - width: parent.width * 0.25 - - onClicked: { - yearSelectPu.open() - } - - onPressed: yearToolBt.scale = 0.9 - onReleased: yearToolBt.scale = 1.0 - - background: Image { - - anchors.centerIn: parent - - source: "qrc:/icons/calendar.png" - - height: parent.height > parent.width ? parent.width : parent.height - width: height - - mipmap: true - - fillMode: Image.PreserveAspectFit - Behavior on scale { - PropertyAnimation { - duration: 100 - } - } - } - } - - Button { - id: cupToolBt - - anchors { - verticalCenter: parent.verticalCenter - } - - height: parent.height * 0.5 - width: parent.width * 0.25 - - onClicked: { - cupSelectPu.open() - } - - onPressed: cupToolBt.scale = 0.9 - onReleased: cupToolBt.scale = 1.0 - - background: Image { - - anchors.centerIn: parent - - source: "qrc:/icons/cup.png" - - height: parent.height > parent.width ? parent.width : parent.height - width: height - - mipmap: true - - fillMode: Image.PreserveAspectFit - Behavior on scale { - PropertyAnimation { - duration: 100 - } - } - } - } - - } - } - - property string nation: "" - property int year: new Date().getFullYear() - property int status: -1 - property var calendarData - - Component.onCompleted: { - root.ready = loadData(root.nation, root.year) - } - - function loadData(nation, year) { - //loadingDl.open() - - //console.log("loading calendar data and old data is: " + (root.calendarData !== undefined) + " because of: " + root.calendarData + " and: ") - - root.status = 905 - - var ret = serverConn.getCalendar(nation, year) - - if(ret["status"] === 200){ - root.status = 200 - root.calendarData = ret["data"] - calendarList.listData = ret["data"]["competitions"] - - - - } - else if (root.calendarData !== undefined ){ - // there is still old data available - root.status = 902 - //console.log("old data") - } - else { - root.status = parseInt(ret["status"]) - app.errorCode = parseInt(ret["status"]) - root.calendarData = ({}) - calendarList.listData = ({}) - //console.log("error: " + root.status) - loadingDl.close() - app.errorCode = root.status - return false - } - - //loadingDl.close() - app.errorCode = root.status - - return true - } - - function getCompCatData(compCatId) { - var obj = app.compCats - - for(var prop in obj) { - // go through the whole array and search for data keys - if (obj.hasOwnProperty(prop) && obj[prop]["cat_id"].indexOf(compCatId) >= 0) { - //console.log("found cat: " + obj[prop]['label']) - return obj[prop] - } - } - } - - DataListView { - id: calendarList - - property var listData - - anchors.fill: parent - - //boundsBehavior: Flickable.StopAtBounds - - model: listData.length - - status: root.status - - onRefresh: { - root.loadData(root.nation, root.year) - } - - onModelChanged: { - autoScroll() - } - - function autoScroll() { - if(parseInt(root.year) === new Date().getFullYear()){ - for(var i = 0; i < listData.length; i ++){ - // get the start date pf the competition - var startDate = Date.fromLocaleString(Qt.locale(), calendarList.listData[i]["date"], "yyyy-MM-dd") - - // get the duration of the competition - var durationString = calendarList.listData[i]["duration"] === undefined ? "1":calendarList.listData[i]["duration"] - var days = parseInt(durationString.replace(/\D/g,'')) - // calculate the end date of the competition - var endDate = new Date(startDate.valueOf()) - endDate.setDate(endDate.getDate() + days); - - //console.log(calendarList.listData[i]["date"] + ": " + startDate + " to " + endDate) - - if(endDate.getTime() < new Date().getTime()){ - // end date is already over -> move the list view down! - calendarList.positionViewAtIndex(i, ListView.Top) - //console.log("moving down!") - } - } - } - } - - delegate: ItemDelegate { - id: competitionDel - - property string name: calendarList.listData[index]["name"] - property string date: calendarList.listData[index]["date_span"] - property var cats: calendarList.listData[index]["cats"] - property int catId: calendarList.listData[index]["cat_id"] === undefined ? 0:calendarList.listData[index]["cat_id"] - property bool over - property var thisData: calendarList.listData[index] - - width: parent.width - height: compDelCol.height + 10 - - enabled: calendarList.listData[index]["cats"] !== undefined && calendarList.listData[index]["cats"].length > 0 - - opacity: 0 - scale: 0.9 - - onThisDataChanged: { - fadeInPa.start() - } - - onClicked: { - catSelectPu.appear(index, false) - } - - ParallelAnimation { - id: fadeInPa - NumberAnimation { target: competitionDel; property: "opacity"; from: 0; to: 1.0; duration: 400 } - NumberAnimation { target: competitionDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } - } - - Rectangle { - id: delBackroundRect - - anchors.fill: parent - - opacity: 0.5 - - color: root.getCompCatData(catId) === undefined ? "white":root.getCompCatData(catId)["bgcolor"] - } - - Column { - id: compDelCol - - anchors.centerIn: parent - - width: parent.width * 0.97 - - spacing: 10 - - Label { - id: nameLa - - width: parent.width - - font.bold: true - - wrapMode: Text.WordWrap - - text: name - } -/* - Label { - id: infola - - width: parent.width - - text: calendarList.listData[index].info - }*/ - - Label { - id: dateLa - - color: "grey" - - text: date - } - } - - Rectangle { - id: bottomLineRa - - anchors { - bottom: parent.bottom - left: parent.left - right: parent.right - } - - height: 1 - - color: "lightgrey" - - } - } - - } - - Dialog { - id: catSelectPu - - property int index: -1 - property bool cupCat: false - property var catObj: undefined - - x: 0 //root.width / 2 - width / 2 - y: root.height - height //root.height / 2 - height / 2 - - width: root.width - height: catsLv.implicitHeight - - modal: true - focus: true - - title: qsTr("select category") - - function appear(index, cupCat) { - catSelectPu.cupCat = cupCat - catSelectPu.index = index - - var tmpCatObj - - if(cupCat){ - tmpCatObj = root.calendarData["cups"][index]["cats"] - } - else { - tmpCatObj = calendarList.listData[index]["cats"] - } - - tmpCatObj.sort(function(a, b) { - return parseInt(a["GrpId"]) - parseInt(b["GrpId"]); - }); - - catSelectPu.catObj = tmpCatObj - - catSelectPu.open() - - } - - function getText(index){ - // ---------------------------- - // get the text - // returns list with [catId, catName] - - if(catSelectPu.cupCat){ - var catName // category name - var catId // category id - - for(var i = 0; i < root.calendarData["cats"].length; i ++ ){ - //console.log("checking " + i + ": cat: " + parseInt(listData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) - if(root.calendarData["cats"][i]["rkey"] === root.calendarData["cups"][catSelectPu.index]["cats"][index] && root.calendarData["cats"][i]["sex"] !== undefined){ - catName = root.calendarData["cats"][i]["name"] - catId = root.calendarData["cats"][i]["GrpId"] - } - } - - return [catId, catName] - } - else { - return [catSelectPu.catObj[index]["GrpId"], catSelectPu.catObj[index]["name"]] - } - - - } - - ListView { - id: catsLv - - property int delegateHeight: 50 - - anchors.fill: parent - - implicitWidth: parent.width - implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75 - - model: catSelectPu.catObj !== undefined ? catSelectPu.catObj.length:0 - - ScrollIndicator.vertical: ScrollIndicator { - parent: catsLv.parent - anchors { - top: catsLv.top - left: catsLv.right - margins: 10 - leftMargin: 3 - bottom: catsLv.bottom - } - - } - - delegate: Button { - id: catBt - - property var catData: catSelectPu.getText(index) - - width: parent.width - height: text !== "" ? catsLv.delegateHeight:0 - - flat: true - - text: catData[1] - - onClicked: { - catSelectPu.close() - app.openResults( catSelectPu.cupCat ? root.calendarData["cups"][catSelectPu.index]["SerId"]:calendarList.listData[catSelectPu.index]["WetId"], catData[0], catSelectPu.cupCat ? -1:catSelectPu.catObj[index]["status"] ) - } - } - } - - enter: Transition { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } - NumberAnimation { - property: "y" - from: root.height - catSelectPu.height * 0.7 - to: root.height - catSelectPu.height - } - } - - exit: Transition { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { - property: "y" - from: root.height - catSelectPu.height - to: root.height - catSelectPu.height * 0.7 - } - } - } - - Dialog { - id: yearSelectPu - - property var yearList: root.calendarData["years"] - - x: 0 //root.width / 2 - width / 2 - y: root.height - height //root.height / 2 - height / 2 - - width: root.width - height: yearsLv.implicitHeight - - modal: true - focus: true - - title: qsTr("select year") - - contentItem: ListView { - id: yearsLv - - implicitWidth: parent.width - implicitHeight: root.height * 0.6 - - model: yearSelectPu.yearList !== undefined ? yearSelectPu.yearList.length:0 - - clip: true - - ScrollIndicator.vertical: ScrollIndicator { - parent: yearsLv.parent - anchors { - top: yearsLv.top - left: yearsLv.right - margins: 10 - leftMargin: 3 - bottom: yearsLv.bottom - } - - } - - delegate: Button { - id: yearBt - - width: parent.width - - flat: true - - text: yearSelectPu.yearList[index] - - onClicked: { - yearSelectPu.close() - root.year = yearSelectPu.yearList[index] - loadingDl.open() - root.loadData(root.nation, root.year) - loadingDl.close() - } - } - } - - enter: Transition { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } - NumberAnimation { - property: "y" - from: root.height - yearSelectPu.height * 0.7 - to: root.height - yearSelectPu.height - } - } - - exit: Transition { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { - property: "y" - from: root.height - yearSelectPu.height - to: root.height - yearSelectPu.height * 0.7 - } - } - } - - Dialog { - id: cupSelectPu - - property var cupList: getCupList() - - function getCupList() { - if(root.nation === "") { - root.calendarData["cups"].unshift({"SerId":"","rkey":"","name":"Worldranking","modified":"2018-10-24 16:11:12","modifier":"","year":"","num_comps":"","cats":["ICC-COA","ICC-HD","ICC-MED","ICC_F","ICC_FB","ICC_FS","ICC_M","ICC_MB","ICC_MS"]}) - } - return root.calendarData["cups"] - } - - x: 0 //root.width / 2 - width / 2 - y: root.height - height //root.height / 2 - height / 2 - - width: root.width - height: cupsLv.implicitHeight - - modal: true - focus: true - - title: qsTr("select cup") - - ListView { - id: cupsLv - - property int delegateHeight: 50 - - anchors { - top: parent.top - left: parent.left - right: parent.right - } - - implicitWidth: parent.width - implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75 - - model: cupSelectPu.cupList !== undefined ? cupSelectPu.cupList.length:0 - - ScrollIndicator.vertical: ScrollIndicator { - parent: cupsLv.parent - anchors { - top: cupsLv.top - left: cupsLv.right - margins: 10 - leftMargin: 3 - bottom: cupsLv.bottom - } - - } - - delegate: Button { - id: cupBt - - width: parent.width - height: cupsLv.delegateHeight - - flat: true - - text: cupSelectPu.cupList[index]["name"] - - onClicked: { - cupSelectPu.close() - catSelectPu.appear(index, true) - } - } - } - - enter: Transition { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } - NumberAnimation { - property: "y" - from: root.height - cupSelectPu.height * 0.7 - to: root.height - cupSelectPu.height - } - } - - exit: Transition { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { - property: "y" - from: root.height - cupSelectPu.height - to: root.height - cupSelectPu.height * 0.7 - } - } - - } - -} diff --git a/resources/qml/Pages/RankingPage.qml b/resources/qml/Pages/RankingPage.qml deleted file mode 100644 index 207e0bf..0000000 --- a/resources/qml/Pages/RankingPage.qml +++ /dev/null @@ -1,514 +0,0 @@ -/* - blueROCK - for digital rock - Copyright (C) 2019 Dorian Zedler - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import QtQuick 2.9 -import QtQuick.Controls 2.4 -import QtGraphicalEffects 1.0 - -import "../Components" - -Page { - id: root - - title: root.rankingData[compNameKey] - property string subTitle: getSubtitle() - property bool titleIsPageTitle: true - - property Component headerComponent: Item { - anchors.fill: parent - - - Button { - id: cupToolBt - - anchors { - verticalCenter: parent.verticalCenter - right: parent.right - rightMargin: parent.width * 0.1 - } - - height: parent.height * 0.5 - width: height - - onClicked: { - catSelectPu.appear() - } - - onPressed: cupToolBt.scale = 0.9 - onReleased: cupToolBt.scale = 1.0 - - background: Image { - - anchors.centerIn: parent - - source: "qrc:/icons/more_black.png" - - height: parent.height > parent.width ? parent.width : parent.height - width: height - - mipmap: true - - fillMode: Image.PreserveAspectFit - Behavior on scale { - PropertyAnimation { - duration: 100 - } - } - } - } - - - } - - property bool ready - property int status: -1 - - property bool debug: true - - property int comId: -1 - property int catId: -1 - property int catStatus: undefined - property int routeNumber: -2 - - property bool rak: catStatus === -1 // ranking (cup) data - property bool reg: catStatus === 4 || catStatus === undefined // registration data - property bool res: catStatus === 0 || catStatus === 1 // result data - property bool stl: catStatus === 2 || catStatus === 3 // startlist data - - /* - enum DataType { - RankingData, - RegistrationData, - ResultData, - StartlistData - }*/ - - property var rankingData - - property string listKey: root.reg ? "athletes":"participants" - property string compNameKey: root.reg ? "name":"comp_name" - - Component.onCompleted: { - loadingDl.open() - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - loadingDl.close() - } - - function loadData(comp, cat, reg, rak, route){ - root.status = 905 - - console.log("[info][QML] getting ranking data of comp: " + comp + " , cat: " + cat + " and status: " + root.catStatus) - - if(route === -1){ - route = -2 - } - - var ret = serverConn.getRanking(comp, cat, reg, rak, route) - - root.status = ret["status"] - console.log(root.status) - - if(parseInt(ret["status"]) === 200){ - // request was successfull -> prepare data - if(root.reg){ - // if the data is registration data, athletes of other cats need to be removed -/* - var validAthletes = [] - - for(var i = 0; i < ret["data"]["athletes"].length; i++){ - if(parseInt(ret["data"]["athletes"][i]["cat"]) === cat){ - //console.log("found matching athlete at " + i) - validAthletes.push(ret["data"]["athletes"][i]) - } - } - ret["data"]["athletes"] = validAthletes*/ - - root.rankingData = ret["data"] - } - else if(root.rak){ - root.rankingData = ret["data"] - root.routeNumber = root.rankingData["route_order"] === undefined ? -2:root.rankingData["route_order"] - } - else { - root.rankingData = ret["data"] - root.routeNumber = root.rankingData["route_order"] === undefined ? -2:root.rankingData["route_order"] - } - } - else if(root.rankingData !== undefined){ - root.status = 902 - app.errorCode = 902 - } - - else if(root.status !== 200) { - root.ready = false - root.rankingData = {} - return false - } - - if((ret["data"][ root.listKey ] === undefined || ret["data"][ root.listKey ].length < 1) && ( root.status === 200 || root.status === 404 ) ){ - root.status = 901 - root.ready = false - return false - } - - console.log("done! status: " + root.status) - root.ready = true - return true - } - - function getSubtitle() { - var titleString - - //console.log("getting title, reg: " + root.reg) - - if(reg){ - for(var i = 0; i < root.rankingData["categorys"].length; i ++ ){ - //console.log("checking " + i + ": cat: " + parseInt(root.rankingData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) - if(parseInt(root.rankingData["categorys"][i]["GrpId"]) === root.catId){ - titleString = root.rankingData["categorys"][i]["name"] - } - } - } - else { - titleString = root.rankingData["route_name"] - } - - var addition = "" - - if(root.reg) { - addition = "(Registration) " - } - else if(root.res) { - addition = "(Results) " - } - else if(root.stl) { - addition = "(Startlist) " - } - else if(root.rak) { - addition = "(Ranking) " - } - - return addition + titleString - - } - - Item { - id: regItm - // item for registration view - - anchors.fill: parent - - visible: root.reg - - RegistrationView { - id: regViewRv - - anchors.fill: parent - - status: root.status - - listData: root.reg ? root.rankingData:({}) - - onRefresh: { - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - } - } - } - - Item { - id: rankItm - // item for ranking data - - anchors.fill: parent - - visible: root.res - - ResultView { - id: rankViewRv - - anchors { - left: parent.left - right: parent.right - top: parent.top - bottom: routeSelectTb.top - } - - height: root.height - routeSelectTb.height - - status: root.status - - listData: root.res ? root.rankingData:({}) - - onRefresh: { - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - } - } - - RectangularGlow { - id: toolBarEffect - glowRadius: 3 - spread: 0.2 - color: "black" - opacity: 0.3 - anchors.fill: routeSelectTb - } - - TabBar { - id: routeSelectTb - - property var tabs: getTabs() - property var tabIndexes: [] - - anchors { - left: parent.left - right: parent.right - bottom: parent.bottom - } - - height: tabs.length > 0 ? 50:0 - - position: TabBar.Footer - - Component.onCompleted: { - //currentIndex = getIndex(root.routeNumber) - setCurrentIndex(getIndex(root.routeNumber)) - } - - function getTabs() { - - var obj = root.rankingData["route_names"] - var buttonData = [] - - for(var prop in obj) { - // go through the whole array and search for data keys - if (obj.hasOwnProperty(prop)) { - buttonData.push([prop, obj[prop]]) - console.log("found " + obj[prop] + " at index " + prop) - } - } - - buttonData.sort(function(a, b) { - return a[0] - b[0]; - }); - - return buttonData - } - - function getIndex(routeNumber) { - console.log("getting index for route number: " + routeNumber) - - for(var i = 0; i < tabs.length; i++){ - //console.log(tabs[i]) - if(parseInt(tabs[i][0]) === routeNumber){ - console.log("found index: " + i) - return i - } - } - - - return 0 - } - - Repeater { - id: routeSelectButtonRep - - model: routeSelectTb.tabs.length - - onModelChanged: { - routeSelectTb.setCurrentIndex(routeSelectTb.getIndex(root.routeNumber)) - } - - delegate: TabButton { - text: routeSelectTb.tabs[index][1] - - width: Math.max(150, routeSelectTb.width / routeSelectButtonRep.model) //text.length * font.pixelSize - - - - onClicked: { - console.log("changing to index: " + index + " (" + routeSelectTb.tabs[index][0] + ", " + routeSelectTb.tabs[index][1] + ")") - if(root.routeNumber !== parseInt(routeSelectTb.tabs[index][0])){ - loadingDl.open() - if(root.loadData(root.comId, root.catId, root.reg, root.rak, routeSelectTb.tabs[index][0]) && root.status === 200){ - root.routeNumber = routeSelectTb.tabs[index][0] - } - else { - routeSelectTb.setCurrentIndex(routeSelectTb.getIndex(root.routeNumber)) - } - - loadingDl.close() - - } - } - } - } - } - } - - Item { - id: startlItm - // item for startlist data - - anchors.fill: parent - - visible: root.stl - - StartlistView { - id: stlViewRv - - anchors.fill: parent - - status: root.status - - listData: root.stl ? root.rankingData:({}) - - onRefresh: { - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - } - } - } - - Item { - id: rankinglItm - // item for startlist data - - anchors.fill: parent - - visible: root.rak - - RankingView { - id: rankingRv - - anchors.fill: parent - - status: root.status - - listData: root.rak ? root.rankingData:({}) - - onRefresh: { - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - } - } - } - - Dialog { - id: catSelectPu - - property var catObj: undefined - - x: 0 //root.width / 2 - width / 2 - y: root.height - height //root.height / 2 - height / 2 - - width: root.width - height: catsLv.implicitHeight - - modal: true - focus: true - - title: qsTr("select category") - - function appear() { - - var tmpCatObj - - - tmpCatObj = root.rankingData["categorys"] - - - tmpCatObj.sort(function(a, b) { - return parseInt(a["GrpId"]) - parseInt(b["GrpId"]); - }); - - catSelectPu.catObj = tmpCatObj - - catSelectPu.open() - - } - - function getText(index){ - // ---------------------------- - // get the text - // returns list with [catId, catName] - return [catSelectPu.catObj[index]["GrpId"], catSelectPu.catObj[index]["name"]] - } - - ListView { - id: catsLv - - property int delegateHeight: 50 - - anchors.fill: parent - - implicitWidth: parent.width - implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75 - - model: catSelectPu.catObj !== undefined ? catSelectPu.catObj.length:0 - - ScrollIndicator.vertical: ScrollIndicator { - parent: catsLv.parent - anchors { - top: catsLv.top - left: catsLv.right - margins: 10 - leftMargin: 3 - bottom: catsLv.bottom - } - - } - - delegate: Button { - id: catBt - - property var catData: catSelectPu.getText(index) - - width: parent.width - height: text !== "" ? catsLv.delegateHeight:0 - - flat: true - - text: catData[1] - - onClicked: { - catSelectPu.close() - root.catId = catData[0] - root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber) - } - } - } - - enter: Transition { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } - NumberAnimation { - property: "y" - from: root.height - catSelectPu.height * 0.7 - to: root.height - catSelectPu.height - } - } - - exit: Transition { - NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 } - NumberAnimation { - property: "y" - from: root.height - catSelectPu.height - to: root.height - catSelectPu.height * 0.7 - } - } - } - - -} diff --git a/resources/qml/Pages/StartPage.qml b/resources/qml/Pages/StartPage.qml index 5939dd9..fbb4d10 100644 --- a/resources/qml/Pages/StartPage.qml +++ b/resources/qml/Pages/StartPage.qml @@ -61,7 +61,7 @@ Page { image: "qrc:/icons/ifsc.png" onClicked: { - app.openCalendar("") + app.openWidget({nation:""}) } } @@ -75,7 +75,7 @@ Page { image: "qrc:/icons/dav.png" onClicked: { - app.openCalendar("GER") + app.openWidget({nation:"GER"}) } } @@ -89,7 +89,7 @@ Page { image: "qrc:/icons/sac.png" onClicked: { - app.openCalendar("SUI") + app.openWidget({nation:"SUI"}) } } diff --git a/resources/qml/Pages/WidgetPage.qml b/resources/qml/Pages/WidgetPage.qml index 00e97c5..c791d01 100644 --- a/resources/qml/Pages/WidgetPage.qml +++ b/resources/qml/Pages/WidgetPage.qml @@ -38,8 +38,10 @@ Page { Aggregated // not yet implemented } - title: widgetLd.item === null ? "":widgetLd.item.title - property Component headerComponent: widgetLd.item === null ? null:widgetLd.item.headerComponent + title: widgetLd.item !== null && widgetLd.item.hasOwnProperty('title') ? widgetLd.item['title']:"" + property string subTitle: widgetLd.item !== null && widgetLd.item.hasOwnProperty('subTitle') ? widgetLd.item['subTitle']:"" + property bool titleIsPageTitle: widgetLd.item !== null && widgetLd.item.hasOwnProperty('titleIsPageTitle') ? widgetLd.item['titleIsPageTitle']:false + property Component headerComponent: widgetLd.item !== null && widgetLd.item.hasOwnProperty('headerComponent') ? widgetLd.item['headerComponent']:null property var params @@ -111,7 +113,7 @@ Page { // check the type of the requested widget - if(hasParam(params, 'perId')){ + if(hasParam(params, 'person')){ // person profile widgetType = WidgetPage.WidgetType.Profile } @@ -174,11 +176,31 @@ Page { case WidgetPage.WidgetType.Registration: path += "RegistrationWidget" break + case WidgetPage.WidgetType.Startlist: + path += "StartlistWidget" + break + case WidgetPage.WidgetType.Result: + path += "ResultWidget" + break + case WidgetPage.WidgetType.Ranking: + path += "RankingWidget" + break + } path += ".qml" return path } + + function getItemProperty(key, defaultValue) { + if(widgetLd.item !== null && widgetLd.item.hasOwnProperty(key)) { + return key + } + else { + return defaultValue + } + } + } Dialog { @@ -197,10 +219,11 @@ Page { modal: true focus: true - title: qsTr("select category") + title: "" - function appear(dataObj) { + function appear(dataObj, title) { selectorPu.dataObj = dataObj + selectorPu.title = title selectorPu.open() } diff --git a/resources/qml/Widgets/CalendarWidget.qml b/resources/qml/Widgets/CalendarWidget.qml index d435950..03e8a47 100644 --- a/resources/qml/Widgets/CalendarWidget.qml +++ b/resources/qml/Widgets/CalendarWidget.qml @@ -105,7 +105,7 @@ DataListView { width: parent.width * 0.25 onClicked: { - cupSelectPu.open() + control.openCup() } onPressed: cupToolBt.scale = 0.9 @@ -154,6 +154,13 @@ DataListView { autoScroll() } + onWidgetDataChanged: { + // if the IFSC Calendar is open -> add the worldranking + if(params.nation === ""){ + control.widgetData['cups'].unshift({"SerId":"","rkey":"","name":"Worldranking","modified":"2018-10-24 16:11:12","modifier":"","year":"","num_comps":"","cats":["ICC-COA","ICC-HD","ICC-MED","ICC_F","ICC_FB","ICC_FS","ICC_M","ICC_MB","ICC_MS"]}) + } + } + function autoScroll() { var compList = control.widgetData["competitions"] @@ -208,7 +215,7 @@ DataListView { } } - selector.appear(selectOptions) + selector.appear(selectOptions, qsTr("select category")) } function changeYear(){ @@ -222,10 +229,68 @@ DataListView { } } - selector.appear(selectOptions) + selector.appear(selectOptions, qsTr("select Year")) } + function openCup(state, data) { + var cups = control.widgetData["cups"] + var prop + var selectOptions = [] + var selectTitle = "" + + if(state === undefined){ + // opened for the first time -> select cup + selectTitle = qsTr("select cup") + + cups.sort(function(a, b) { + return parseInt(b["SerId"]) - parseInt(a["SerId"]); + }); + + for(prop in cups){ + if (cups.hasOwnProperty(prop)) { + selectOptions.push({text: cups[prop]["name"], data:{cup: cups[prop]["SerId"]}}) + } + } + } + else if(state === 1){ + // opened for the second time -> select cat + var cup + + // find the selected cup + for(prop in cups){ + if (cups.hasOwnProperty(prop) && cups[prop]['SerId'] === data.cup) { + cup = cups[prop] + } + } + + if(cup === undefined){ + // cup was not found + return + } + + selectTitle = cup['name'] + ": " + qsTr("select category") + + // build a list with all cat in the cup out of the cat keys (rkey) given in the cup.cats + for(prop in cup['cats']){ + if (cup['cats'].hasOwnProperty(prop)) { + + // search the rkey in the cat list + for(var i = 0; i < control.widgetData["cats"].length; i ++ ){ + if(control.widgetData["cats"][i]["rkey"] === cup["cats"][prop] && control.widgetData["cats"][i]["sex"] !== undefined){ + // found it -> append it to the select list + var catName = control.widgetData["cats"][i]["name"] // name of cat + var catId = control.widgetData["cats"][i]["GrpId"] // id of cat + selectOptions.push({text: catName, data:{cup: data.cup, cat: catId}}) + } + } + } + } + } + + selector.appear(selectOptions, selectTitle) + + } Connections { target: selector @@ -238,6 +303,12 @@ DataListView { updateData({year: data.year}, true) control.year = data.year } + else if(data.cup !== undefined && data.cat === undefined){ + control.openCup(1,data) + } + else if(data.cup !== undefined && data.cat !== undefined){ + app.openWidget({cup: data.cup, cat: data.cat}) + } } } diff --git a/resources/qml/Widgets/ProfileWidget.qml b/resources/qml/Widgets/ProfileWidget.qml index fd8c71c..db77f0b 100644 --- a/resources/qml/Widgets/ProfileWidget.qml +++ b/resources/qml/Widgets/ProfileWidget.qml @@ -16,30 +16,6 @@ Page { property var widgetData: ({}) - Component.onCompleted: { - if(control.loadData(control.perId)){ - control.ready = true - } - } - - function loadData(perId) { - console.log("loading athlete: ", perId) - - control.status = 905 - - var ret = serverConn.getAthlete(perId) - - control.status = ret["status"] - - if(ret["status"] === 200){ - control.widgetData = ret["data"] - return true - } - else { - return false - } - } - ScrollView { id: mainSv @@ -215,7 +191,7 @@ Page { wrapMode: Label.Wrap - text: widgetData["freetext"] + text: widgetData["freetext"] === undefined ? "":widgetData["freetext"] } diff --git a/resources/qml/Components/RankingView.qml b/resources/qml/Widgets/RankingWidget.qml similarity index 82% rename from resources/qml/Components/RankingView.qml rename to resources/qml/Widgets/RankingWidget.qml index a3f8a8b..5a3cc1e 100644 --- a/resources/qml/Components/RankingView.qml +++ b/resources/qml/Widgets/RankingWidget.qml @@ -19,23 +19,39 @@ import QtQuick 2.9 import QtQuick.Controls 2.4 +import "../Components" + DataListView { id: control - property var listData: ({}) + property string title: control.widgetData['comp_name'] + property string subTitle: qsTr("(Ranking)") + " after " + control.widgetData['route_name'] + property bool titleIsPageTitle: true + + property var widgetData: ({}) signal closeAll() - onListDataChanged: { - model = listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length + Connections { + target: selector + onSelectionFinished: { + if(data.cat !== undefined){ + updateData({cat: data.cat}, true) + } + } } - model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length + + onWidgetDataChanged: { + model = widgetData[ "participants" ] === undefined ? 0:widgetData[ "participants" ].length + } + + model: widgetData[ "participants" ] === undefined ? 0:widgetData[ "participants" ].length delegate: ItemDelegate { id: partDel property int ind: index - property var thisData: listData[ "participants" ][index] + property var thisData: widgetData[ "participants" ][index] state: "closed" @@ -50,7 +66,7 @@ DataListView { } onPressAndHold: { - app.openAthlete(thisData["PerId"]) + app.openWidget({person:thisData["PerId"]}) } ParallelAnimation { @@ -122,7 +138,7 @@ DataListView { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text: listData[ "participants" ][index]["result_rank"] === undefined ? "":listData[ "participants" ][index]["result_rank"] + text: widgetData[ "participants" ][index]["result_rank"] === undefined ? "":widgetData[ "participants" ][index]["result_rank"] } Label { @@ -138,7 +154,7 @@ DataListView { horizontalAlignment: Text.AlignLeft minimumPixelSize: 1 - text: listData[ "participants" ][index]["firstname"] + " " + listData[ "participants" ][index]["lastname"] + text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"] } Label { @@ -157,7 +173,7 @@ DataListView { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter - text: "(" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + ")" + text: "(" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + ")" onLinkActivated: { Qt.openUrlExternally(link) @@ -191,7 +207,7 @@ DataListView { font.pixelSize: Math.abs( height * 0.6 ) minimumPixelSize: 1 - text: listData[ "participants" ][partDel.ind]["points"] === undefined ? "":"points: "+listData[ "participants" ][partDel.ind]["points"] + text: widgetData[ "participants" ][partDel.ind]["points"] === undefined ? "":"points: "+widgetData[ "participants" ][partDel.ind]["points"] } } } @@ -298,12 +314,12 @@ DataListView { function getCompResults() { - var obj = control.listData["route_names"] + var obj = control.widgetData["route_names"] var resultData = [] for(var prop in obj) { // go through the whole array and search for data keys - if (obj.hasOwnProperty(prop) && control.listData["participants"][partDel.ind]["result" + prop.replace(" ", "")] !== undefined ) { + if (obj.hasOwnProperty(prop) && control.widgetData["participants"][partDel.ind]["result" + prop.replace(" ", "")] !== undefined ) { resultData.unshift([prop, obj[prop].replace("\n", " - ")]) //console.log("found " + obj[prop] + " at index " + prop) } @@ -352,7 +368,7 @@ DataListView { horizontalAlignment: Text.AlignLeft minimumPixelSize: 1 - text: control.listData["participants"][partDel.ind]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")] === undefined ? "":control.listData["participants"][partDel.ind]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")].replace("\n", " ") + text: control.widgetData["participants"][partDel.ind]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")] === undefined ? "":control.widgetData["participants"][partDel.ind]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")].replace("\n", " ") } Behavior on height { diff --git a/resources/qml/Widgets/RegistrationWidget.qml b/resources/qml/Widgets/RegistrationWidget.qml index 70b66a1..2395e9b 100644 --- a/resources/qml/Widgets/RegistrationWidget.qml +++ b/resources/qml/Widgets/RegistrationWidget.qml @@ -24,8 +24,125 @@ import "../Components" DataListView { id: control + property string title: control.widgetData['name'] + property string subTitle: getSubtitle() + property bool titleIsPageTitle: true + + property Component headerComponent: Item { + anchors.fill: parent + + + Button { + id: cupToolBt + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: parent.width * 0.1 + } + + height: parent.height * 0.5 + width: height + + onClicked: { + control.changeCat() + } + + onPressed: cupToolBt.scale = 0.9 + onReleased: cupToolBt.scale = 1.0 + + background: Image { + + anchors.centerIn: parent + + source: "qrc:/icons/more_black.png" + + height: parent.height > parent.width ? parent.width : parent.height + width: height + + mipmap: true + + fillMode: Image.PreserveAspectFit + Behavior on scale { + PropertyAnimation { + duration: 100 + } + } + } + } + + + } + property var widgetData: ({}) + function getSubtitle() { + var titleString + + for(var i = 0; i < control.widgetData["categorys"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(control.widgetData["categorys"][i]["GrpId"]) + " searched cat: " + params.cat) + if(parseInt(control.widgetData["categorys"][i]["GrpId"]) === parseInt(params.cat)){ + titleString = control.widgetData["categorys"][i]["name"] + } + } + + + var addition = "(Registration) " + return addition + titleString + + } + + function getText(index){ + + var fedName // federation name + + if(widgetData["federations"] !== undefined){ + // not an international competition -> get name of federation + + for(var i = 0; i < widgetData["federations"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(widgetData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) + if(widgetData["federations"][i]["fed_id"] === widgetData[ 'athletes' ][index]["reg_fed_id"]){ + fedName = widgetData["federations"][i]["shortcut"] + } + } + } + else { + // an international competition -> get nation + + fedName = widgetData[ 'athletes' ][index]["nation"] + } + + return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")" + } + + function changeCat(){ + var cats = control.widgetData["categorys"] + + cats.sort(function(a, b) { + return parseInt(a["GrpId"]) - parseInt(b["GrpId"]); + }); + + var selectOptions = [] + + for(var prop in cats){ + if (cats.hasOwnProperty(prop) && !control.subTitle.includes(cats[prop]['name'])) { + // append all cats and ignore the current one + selectOptions.push({text: cats[prop]['name'], data:{cat: cats[prop]['GrpId']}}) + } + } + + selector.appear(selectOptions, qsTr("select cat")) + } + + Connections { + target: selector + onSelectionFinished: { + if(data.cat !== undefined){ + updateData({cat: data.cat}, true) + } + } + } + model: widgetData[ 'athletes' ] === undefined ? 0:widgetData[ 'athletes' ].length onRefresh: { @@ -48,7 +165,7 @@ DataListView { } onClicked: { - app.openAthlete(thisData["PerId"]) + app.openWidget({person:thisData["PerId"]}) } ParallelAnimation { @@ -76,29 +193,4 @@ DataListView { } } - function getText(index){ - - // ---------------------------- - // if we have registration data - - var fedName // federation name - - if(widgetData["federations"] !== undefined){ - // not an international competition -> get name of federation - - for(var i = 0; i < widgetData["federations"].length; i ++ ){ - //console.log("checking " + i + ": cat: " + parseInt(widgetData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) - if(widgetData["federations"][i]["fed_id"] === widgetData[ 'athletes' ][index]["reg_fed_id"]){ - fedName = widgetData["federations"][i]["shortcut"] - } - } - } - else { - // an international competition -> get nation - - fedName = widgetData[ 'athletes' ][index]["nation"] - } - - return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")" - } } diff --git a/resources/qml/Widgets/ResultWidget.qml b/resources/qml/Widgets/ResultWidget.qml index d354ba9..65bd747 100644 --- a/resources/qml/Widgets/ResultWidget.qml +++ b/resources/qml/Widgets/ResultWidget.qml @@ -18,23 +18,132 @@ import QtQuick 2.9 import QtQuick.Controls 2.4 +import QtGraphicalEffects 1.0 import "../Components" DataListView { id: control + property string title: control.widgetData['comp_name'] + property string subTitle: getSubtitle() + property bool titleIsPageTitle: true + + property Component headerComponent: Item { + anchors.fill: parent + + + Button { + id: cupToolBt + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: parent.width * 0.1 + } + + height: parent.height * 0.5 + width: height + + onClicked: { + control.changeCat() + } + + onPressed: cupToolBt.scale = 0.9 + onReleased: cupToolBt.scale = 1.0 + + background: Image { + + anchors.centerIn: parent + + source: "qrc:/icons/more_black.png" + + height: parent.height > parent.width ? parent.width : parent.height + width: height + + mipmap: true + + fillMode: Image.PreserveAspectFit + Behavior on scale { + PropertyAnimation { + duration: 100 + } + } + } + } + + + } + property var widgetData: ({}) - model: widgetData[ root.listKey ] === undefined ? 0:widgetData[ root.listKey ].length + onWidgetDataChanged: { + model = widgetData[ "participants" ] === undefined ? 0:widgetData[ "participants" ].length + } + + model: widgetData[ "participants" ] === undefined ? 0:widgetData[ "participants" ].length + + onRefresh: { + updateData({}, false) + } + + function getSubtitle() { + var titleString + + for(var i = 0; i < control.widgetData["categorys"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(control.widgetData["categorys"][i]["GrpId"]) + " searched cat: " + params.cat) + if(parseInt(control.widgetData["categorys"][i]["GrpId"]) === parseInt(params.cat)){ + titleString = control.widgetData["categorys"][i]["name"] + } + } + + var addition = qsTr("(Results)") + return addition + " " + titleString + + } + + function changeRoute(route) { + updateData({route:route}, true) + } + + function changeCat(){ + var cats = control.widgetData["categorys"] + + cats.sort(function(a, b) { + return parseInt(a["GrpId"]) - parseInt(b["GrpId"]); + }); + + var selectOptions = [] + + for(var prop in cats){ + if (cats.hasOwnProperty(prop) && !control.subTitle.includes(cats[prop]['name'])) { + // append all cats and ignore the current one + selectOptions.push({text: cats[prop]['name'], data:{cat: cats[prop]['GrpId']}}) + } + } + + selector.appear(selectOptions, qsTr("select cat")) + } + + Connections { + target: selector + onSelectionFinished: { + if(data.cat !== undefined){ + updateData({cat: data.cat}, true) + } + } + } delegate: ItemDelegate { id: partDel - property var thisData: widgetData[ "athletes" ][index] + property int ind: index + property var thisData: widgetData[ "participants" ][partDel.ind] width: parent.width - height: parseInt(thisData.cat) === root.catId ? undefined:0 + height: 70 + + text: "" opacity: 0 scale: 0.9 @@ -44,7 +153,7 @@ DataListView { } onClicked: { - app.openAthlete(thisData["PerId"]) + app.openWidget({person:thisData["PerId"]}) } ParallelAnimation { @@ -53,48 +162,491 @@ DataListView { NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } } - text: "" - Label { + Rectangle { anchors.fill: parent - anchors.leftMargin: parent.width * 0.05 - verticalAlignment: Text.AlignVCenter + width: partDel.width - fontSizeMode: Text.Fit - font.bold: true - font.pixelSize: Math.abs( height * 0.4 ) - minimumPixelSize: height * 0.3 + color: partDel.ind % 2 == 0 ? "white":"lightgrey" - elide: "ElideRight" - - text: control.getText(index) + opacity: 0.2 } - } - function getText(index){ + Column { + id: partDelCol - // ---------------------------- - // if we have registration data + anchors.fill: parent + anchors.margins: 5 - var fedName // federation name + Row { + id: partDelFirstRow - if(widgetData["federations"] !== undefined){ - // not an international competition -> get name of federation + width: parent.width + height: parent.height - partDelSecondRow.height - for(var i = 0; i < widgetData["federations"].length; i ++ ){ - //console.log("checking " + i + ": cat: " + parseInt(widgetData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId) - if(widgetData["federations"][i]["fed_id"] === widgetData[ root.listKey ][index]["reg_fed_id"]){ - fedName = widgetData["federations"][i]["shortcut"] + Label { + height: parent.height + width: text === "" ? parent.width * 0.08:parent.width * 0.1 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: widgetData[ "participants" ][index]["result_rank"] === undefined ? "":widgetData[ "participants" ][index]["result_rank"] + } + + Label { + height: parent.height + width: parent.width * 0.5 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.6:height * 0.4 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + + text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"] + } + + Label { + height: parent.height + width: parent.width * 0.4 + + fontSizeMode: Text.Fit + font.bold: false + font.pixelSize: Math.abs( partDelSecondRow.height > 0 ? height * 0.4:height * 0.3 ) + minimumPixelSize: height * 0.3 + + elide: "ElideRight" + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: "(" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + ")" + + onLinkActivated: { + Qt.openUrlExternally(link) + } + } + } + + Row { + id: partDelSecondRow + + width: parent.width + height: multiResRow.enabled || multiGenResRow.enabled || resultLa.enabled ? parent.height / 2:0 + + Row { + id: multiResRow + + height: parent.height + width: enabled ? parent.width * 0.75:0 + + enabled: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0 + + Repeater { + id: boulderResRep + + model: parseInt(widgetData[ "route_num_problems" ]) + + function getDataForIcon(index){ + var resultString = widgetData[ "participants" ][partDel.ind]["boulder"+(index+1)] + + var resultList = [] + + if( resultString !== undefined){ + resultString = resultString.replace("t", "") + resultString = resultString.replace("z", "") + resultString = resultString.replace("b", "") + resultList = resultString.split(" ") + } + + + while (resultList.length < 2){ + resultList.unshift(0) + } + + return resultList + } + + delegate: Item { + id: boulderResItm + + anchors.verticalCenter: parent.verticalCenter + + width: parent.width / ( boulderResRep.model ) + height: parent.height + + Canvas { + id: boulderResCv + + property var resultData: boulderResRep.getDataForIcon(index) + + onResultDataChanged: { + boulderResCv.requestPaint() + } + + anchors.centerIn: parent + + height: parent.height > parent.width ? parent.width * 0.9:parent.height * 0.9 + width: height + + onPaint: { + var width = 24//boulderResCv.width * 0.9 + var height = width + + var radius = width * 0.3 + + var offsetX = width * 0.05 + var offsetY = height * 0.05 + + //console.log("drawing result rect with width: " + width + " and height: " + height) + + var context = getContext("2d"); + + context.beginPath(); + + context.moveTo(0 + offsetX + radius, 0 + offsetY); + + // top line + context.lineTo(width - radius + offsetX, 0 + offsetY); + // top right corner + context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 0); + // right line + context.lineTo(width + offsetX, height - radius + offsetY); + // bottom right corner + context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI); + // bottom line + context.lineTo(0 + radius + offsetX, height + offsetY); + // bottom left corner + context.arc(radius + offsetY, height - radius + offsetY, radius, 0.5 * Math.PI, Math.PI); + // left line + context.lineTo(0 + offsetX, radius + offsetY); + // top left corner + context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI); + + // fill + context.fillStyle = "#b7b7b7"; + context.fill(); + + // outline + context.lineWidth = 1; + context.strokeStyle = '#424242'; + context.stroke(); + + if(resultData[1] > 0){ + + // the first triangle + context.beginPath(); + + // top right corner + context.arc(width-radius + offsetX, radius + offsetY, radius, 1.75 * Math.PI, 0); + + // right line + context.lineTo(width + offsetX, height - radius + offsetY); + + // bottom right corner + context.arc(width-radius + offsetX, height - radius + offsetY, radius, 0, 0.5 * Math.PI); + + // bottom line + context.lineTo(0 + radius + offsetX, height + offsetY); + // bottom left corner + context.arc(radius + offsetX, height - radius + offsetY, radius, 0.5 * Math.PI, 0.75 * Math.PI); + context.closePath(); + + context.fillStyle = "#44ed38"; + context.fill(); + + // outline + context.lineWidth = 1; + context.strokeStyle = '#424242'; + context.stroke(); + + + if(resultData[0] > 0){ + // the second triangle + context.beginPath(); + // bottom left corner + context.arc(radius + offsetX, height - radius + offsetY, radius, 0.75 * Math.PI, 1 * Math.PI); + // left line + context.lineTo(0 + offsetX, radius + offsetY); + // top left corner + context.arc(radius + offsetX, radius + offsetY, radius, Math.PI, 1.5 * Math.PI); + // top line + context.lineTo(width - radius + offsetX, 0 + offsetY); + // top right corner + context.arc(width-radius + offsetX, radius + offsetY, radius, 1.5 * Math.PI, 1.75 * Math.PI); + + context.closePath(); + + context.fillStyle = "#44ed38"; + context.fill(); + + // outline + context.lineWidth = 1; + context.strokeStyle = '#424242'; + context.stroke(); + } + } + + } + + Label { + id: boulderResZoneLa + + anchors { + right: parent.right + bottom: parent.bottom + margins: boulderResCv.height * 0.05 + } + + height: parent.height / 2 + width: parent.width / 2 + + visible: text !== "0" + + fontSizeMode: Text.Fit + font.pixelSize: height + minimumPixelSize: 1 + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: boulderResCv.resultData[1] + } + + Label { + id: boulderResTopLa + + anchors { + left: parent.left + top: parent.top + margins: boulderResCv.height * 0.05 + } + + height: parent.height / 2 + width: parent.width / 2 + + visible: text !== "0" + + fontSizeMode: Text.Fit + font.pixelSize: height + minimumPixelSize: 1 + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: boulderResCv.resultData[0] + } + } + + } + + } + + } + + Row { + id: multiGenResRow + + height: parent.height + width: enabled ? parent.width - resultLa.width:0 + + enabled: ((parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false + + Repeater { + id: generalResRep + + property var routes: getRoutes() + model: routes.length + + function getRoutes() { + + var obj = widgetData["route_names"] + var routes = [] + + for(var prop in obj) { + // go through the whole array and search for data keys + if (obj.hasOwnProperty(prop) && prop > -1) { + routes.push([prop, obj[prop]]) + //console.log("found " + obj[prop] + " at index " + prop) + } + } + + routes.sort(function(a, b) { + return a[0] - b[0]; + }); + + return routes + } + + delegate: Item { + id: boulderGenResItm + + anchors.verticalCenter: parent.verticalCenter + + width: parent.width / ( generalResRep.model ) + height: parent.height + + visible: boulderGenResLa.text != "" + + Rectangle { + + anchors { + left: parent.left + } + + width: 1 + height: parent.height + + visible: index === 0 + + color: "grey" + } + + Rectangle { + anchors { + right: parent.right + } + + width: 1 + height: parent.height + + color: "grey" + } + + Label { + id: boulderGenResLa + anchors.centerIn: parent + + height: parent.height + width: parent.width * 0.9 + + fontSizeMode: Text.Fit + font.pixelSize: Math.abs( height * 0.6 ) + minimumPixelSize: 1 + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: widgetData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] === undefined ? "":widgetData[ "participants" ][partDel.ind]["result"+(generalResRep.routes[index][0])] + } + + } + + } + } + + Label { + id: resultLa + + width: enabled ? parent.width * 0.25:0 + height: enabled ? parent.height:0 + + enabled: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + fontSizeMode: Text.Fit + font.pixelSize: Math.abs( height * 0.6 ) + minimumPixelSize: 1 + + text: widgetData[ "participants" ][partDel.ind]["result"] === undefined ? "":widgetData[ "participants" ][partDel.ind]["result"] } } } - else { - // an international competition -> get nation + } - fedName = widgetData[ root.listKey ][index]["nation"] + RectangularGlow { + id: toolBarEffect + glowRadius: 3 + spread: 0.2 + color: "black" + opacity: 0.3 + anchors.fill: routeSelectTb + } + + TabBar { + id: routeSelectTb + + property var tabs: getTabs() + property var tabIndexes: [] + + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom } - return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")" + height: tabs.length > 0 ? 50:0 + + position: TabBar.Footer + + Component.onCompleted: { + //currentIndex = getIndex(params.route) + setCurrentIndex(getIndex(props.route)) + } + + function getTabs() { + + var obj = control.widgetData["route_names"] + var buttonData = [] + + for(var prop in obj) { + // go through the whole array and search for data keys + if (obj.hasOwnProperty(prop)) { + buttonData.push([prop, obj[prop]]) + console.log("found " + obj[prop] + " at index " + prop) + } + } + + buttonData.sort(function(a, b) { + return a[0] - b[0]; + }); + + return buttonData + } + + function getIndex(routeNumber) { + console.log("getting index for route number: " + routeNumber) + + for(var i = 0; i < tabs.length; i++){ + //console.log(tabs[i]) + if(parseInt(tabs[i][0]) === routeNumber){ + console.log("found index: " + i) + return i + } + } + + + return 0 + } + + Repeater { + id: routeSelectButtonRep + + model: routeSelectTb.tabs.length + + onModelChanged: { + routeSelectTb.setCurrentIndex(routeSelectTb.getIndex(params.route)) + } + + delegate: TabButton { + text: routeSelectTb.tabs[index][1] + + width: Math.max(150, routeSelectTb.width / routeSelectButtonRep.model) //text.length * font.pixelSize + + onClicked: { + //console.log("changing to index: " + index + " (" + routeSelectTb.tabs[index][0] + ", " + routeSelectTb.tabs[index][1] + ")") + + control.changeRoute(routeSelectTb.tabs[index][0]) + } + } + } } + + } diff --git a/resources/qml/Widgets/StartlistWidget.qml b/resources/qml/Widgets/StartlistWidget.qml new file mode 100644 index 0000000..602cb36 --- /dev/null +++ b/resources/qml/Widgets/StartlistWidget.qml @@ -0,0 +1,212 @@ +/* + blueROCK - for digital rock + Copyright (C) 2019 Dorian Zedler + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +import QtQuick 2.9 +import QtQuick.Controls 2.4 + +import "../Components" + +DataListView { + id: control + + property string title: control.widgetData['comp_name'] + property string subTitle: getSubtitle() + property bool titleIsPageTitle: true + + property Component headerComponent: Item { + anchors.fill: parent + + + Button { + id: cupToolBt + + anchors { + verticalCenter: parent.verticalCenter + right: parent.right + rightMargin: parent.width * 0.1 + } + + height: parent.height * 0.5 + width: height + + onClicked: { + control.changeCat() + } + + onPressed: cupToolBt.scale = 0.9 + onReleased: cupToolBt.scale = 1.0 + + background: Image { + + anchors.centerIn: parent + + source: "qrc:/icons/more_black.png" + + height: parent.height > parent.width ? parent.width : parent.height + width: height + + mipmap: true + + fillMode: Image.PreserveAspectFit + Behavior on scale { + PropertyAnimation { + duration: 100 + } + } + } + } + + + } + + function getSubtitle() { + var titleString + + for(var i = 0; i < control.widgetData["categorys"].length; i ++ ){ + //console.log("checking " + i + ": cat: " + parseInt(control.widgetData["categorys"][i]["GrpId"]) + " searched cat: " + params.cat) + if(parseInt(control.widgetData["categorys"][i]["GrpId"]) === parseInt(params.cat)){ + titleString = control.widgetData["categorys"][i]["name"] + } + } + + var addition = qsTr("(Startlist)") + return addition + " " + titleString + + } + + + function changeCat(){ + var cats = control.widgetData["categorys"] + + cats.sort(function(a, b) { + return parseInt(a["GrpId"]) - parseInt(b["GrpId"]); + }); + + var selectOptions = [] + + for(var prop in cats){ + if (cats.hasOwnProperty(prop) && !control.subTitle.includes(cats[prop]['name'])) { + // append all cats and ignore the current one + selectOptions.push({text: cats[prop]['name'], data:{cat: cats[prop]['GrpId']}}) + } + } + + selector.appear(selectOptions, qsTr("select cat")) + } + + Connections { + target: selector + onSelectionFinished: { + if(data.cat !== undefined){ + updateData({cat: data.cat}, true) + } + } + } + + + property var widgetData: ({}) + + model: widgetData[ "participants" ] === undefined ? 0:widgetData[ "participants" ].length + + onRefresh: { + updateData({}, false) + } + + delegate: ItemDelegate { + id: partDel + + property var thisData: widgetData[ "participants" ][index] + + width: parent.width + + opacity: 0 + scale: 0.9 + + onThisDataChanged: { + fadeInPa.start() + } + + onClicked: { + app.openWidget({person:thisData["PerId"]}) + } + + ParallelAnimation { + id: fadeInPa + NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 } + NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } + } + + text: "" + + Row { + id: partDelFirstRow + + width: parent.width + height: parent.height + + Label { + height: parent.height + width: parent.width * 0.1 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( height * 0.6 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: widgetData[ "participants" ][index]["start_order"] + } + + Label { + height: parent.height + width: parent.width * 0.5 + + fontSizeMode: Text.Fit + font.bold: true + font.pixelSize: Math.abs( height * 0.45 ) + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + minimumPixelSize: 1 + + text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"] + } + + Label { + height: parent.height + width: parent.width * 0.3 + + fontSizeMode: Text.Fit + font.bold: false + font.pixelSize: Math.abs( height * 0.4 ) + minimumPixelSize: height * 0.3 + + elide: "ElideRight" + + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + + text: "(" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + ")" + + onLinkActivated: { + Qt.openUrlExternally(link) + } + } + } + + } +} diff --git a/resources/qml/main.qml b/resources/qml/main.qml index 1cb0a31..227c10b 100644 --- a/resources/qml/main.qml +++ b/resources/qml/main.qml @@ -160,7 +160,7 @@ Window { Component.onCompleted: { //app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300 - openWidget({nation:'GER'}) + //openWidget({nation:'GER'}) } @@ -532,63 +532,6 @@ Window { loadingDl.close() } - function openCalendar(nation){ - loadingDl.open() - - var calComp = Qt.createComponent("qrc:/Pages/CompetitionCalendarPage.qml").createObject(null, {"nation": nation}) - app.errorCode = calComp.status - if(calComp.ready){ - mainStack.push(calComp) - } - else { - delete(calComp) - } - - loadingDl.close() - } - - function openResults(comp, cat, status){ - // comp: (int) competiotion ID - // cat: (int) category ID - // status: (int) 0: result imported into ranking; 1: result-service result available; 2: result-service startlist available; 3: old non result-server startlist (no longer used); 4: starters / registration data - - loadingDl.open() - - var rankComp = Qt.createComponent("qrc:/Pages/RankingPage.qml").createObject(null, {"comId": comp, "catId": cat, "catStatus": status}) - app.errorCode = rankComp.status - - if(rankComp.ready){ - mainStack.push(rankComp) - } - else { - delete(rankComp) - } - - - loadingDl.close() - } - - function hasParam(url, param, value){ - if (typeof value == 'undefined') value = ''; - return url.indexOf(param+'='+value) !== -1; - } - - function openAthlete(perId) { - loadingDl.open() - - var athleteComp = Qt.createComponent("qrc:/Pages/AthleteProfilePage.qml").createObject(null, {"perId": perId}) - app.errorCode = athleteComp.status - - if(athleteComp.ready){ - mainStack.push(athleteComp) - } - else { - delete(athleteComp) - } - - loadingDl.close() - } - function getErrorInfo(errorCode) { var infoLevel diff --git a/resources/qml/qml.qrc b/resources/qml/qml.qrc index eb0a96d..411879b 100644 --- a/resources/qml/qml.qrc +++ b/resources/qml/qml.qrc @@ -1,25 +1,20 @@ main.qml - Pages/CompetitionCalendarPage.qml - Pages/RankingPage.qml Pages/StartPage.qml Components/FancyButton.qml Components/AppToolBar.qml Components/FancyBusyIndicator.qml Components/InfoArea.qml Components/DataListView.qml - Components/ResultView.qml - Components/RegistrationView.qml - Components/StartlistView.qml - Components/RankingView.qml Components/PullRefresher.qml - Pages/AthleteProfilePage.qml Components/FadeAnimation.qml Pages/WidgetPage.qml Widgets/CalendarWidget.qml Widgets/ProfileWidget.qml Widgets/ResultWidget.qml Widgets/RegistrationWidget.qml + Widgets/StartlistWidget.qml + Widgets/RankingWidget.qml