moved everything to the new widget structure

This commit is contained in:
Dorian Zedler 2019-05-24 14:15:07 +02:00
parent 274ab4f673
commit 42464d5a13
16 changed files with 1050 additions and 2369 deletions

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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 + ")"
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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: "<html>(<a href=\"" + (listData[ "participants" ][index]["fed_url"] === undefined ? "":listData[ "participants" ][index]["fed_url"]).toString() + "\">" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + "</a>)</html>"
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"]
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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: "<html>(<a href=\"" + (listData[ "participants" ][index]["url"] === undefined ? "":listData[ "participants" ][index]["url"]).toString() + "\">" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + "</a>)</html>"
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
}
}

View file

@ -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: "<html><a href='" + perData["fed_url"] + "'>" + perData["federation"] + "</a>"
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: "<html><a href='#'>" + bestResultsRep.bestResults[index]["name"] + "</a></html>"
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"]
}
}
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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
}
}
}
}

View file

@ -61,7 +61,7 @@ Page {
image: "qrc:/icons/ifsc.png" image: "qrc:/icons/ifsc.png"
onClicked: { onClicked: {
app.openCalendar("") app.openWidget({nation:""})
} }
} }
@ -75,7 +75,7 @@ Page {
image: "qrc:/icons/dav.png" image: "qrc:/icons/dav.png"
onClicked: { onClicked: {
app.openCalendar("GER") app.openWidget({nation:"GER"})
} }
} }
@ -89,7 +89,7 @@ Page {
image: "qrc:/icons/sac.png" image: "qrc:/icons/sac.png"
onClicked: { onClicked: {
app.openCalendar("SUI") app.openWidget({nation:"SUI"})
} }
} }

View file

@ -38,8 +38,10 @@ Page {
Aggregated // not yet implemented Aggregated // not yet implemented
} }
title: widgetLd.item === null ? "":widgetLd.item.title title: widgetLd.item !== null && widgetLd.item.hasOwnProperty('title') ? widgetLd.item['title']:""
property Component headerComponent: widgetLd.item === null ? null:widgetLd.item.headerComponent 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 property var params
@ -111,7 +113,7 @@ Page {
// check the type of the requested widget // check the type of the requested widget
if(hasParam(params, 'perId')){ if(hasParam(params, 'person')){
// person profile // person profile
widgetType = WidgetPage.WidgetType.Profile widgetType = WidgetPage.WidgetType.Profile
} }
@ -174,11 +176,31 @@ Page {
case WidgetPage.WidgetType.Registration: case WidgetPage.WidgetType.Registration:
path += "RegistrationWidget" path += "RegistrationWidget"
break break
case WidgetPage.WidgetType.Startlist:
path += "StartlistWidget"
break
case WidgetPage.WidgetType.Result:
path += "ResultWidget"
break
case WidgetPage.WidgetType.Ranking:
path += "RankingWidget"
break
} }
path += ".qml" path += ".qml"
return path return path
} }
function getItemProperty(key, defaultValue) {
if(widgetLd.item !== null && widgetLd.item.hasOwnProperty(key)) {
return key
}
else {
return defaultValue
}
}
} }
Dialog { Dialog {
@ -197,10 +219,11 @@ Page {
modal: true modal: true
focus: true focus: true
title: qsTr("select category") title: ""
function appear(dataObj) { function appear(dataObj, title) {
selectorPu.dataObj = dataObj selectorPu.dataObj = dataObj
selectorPu.title = title
selectorPu.open() selectorPu.open()
} }

View file

@ -105,7 +105,7 @@ DataListView {
width: parent.width * 0.25 width: parent.width * 0.25
onClicked: { onClicked: {
cupSelectPu.open() control.openCup()
} }
onPressed: cupToolBt.scale = 0.9 onPressed: cupToolBt.scale = 0.9
@ -154,6 +154,13 @@ DataListView {
autoScroll() 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() { function autoScroll() {
var compList = control.widgetData["competitions"] var compList = control.widgetData["competitions"]
@ -208,7 +215,7 @@ DataListView {
} }
} }
selector.appear(selectOptions) selector.appear(selectOptions, qsTr("select category"))
} }
function changeYear(){ 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 { Connections {
target: selector target: selector
@ -238,6 +303,12 @@ DataListView {
updateData({year: data.year}, true) updateData({year: data.year}, true)
control.year = data.year 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})
}
} }
} }

View file

@ -16,30 +16,6 @@ Page {
property var widgetData: ({}) 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 { ScrollView {
id: mainSv id: mainSv
@ -215,7 +191,7 @@ Page {
wrapMode: Label.Wrap wrapMode: Label.Wrap
text: widgetData["freetext"] text: widgetData["freetext"] === undefined ? "":widgetData["freetext"]
} }

View file

@ -19,23 +19,39 @@
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import "../Components"
DataListView { DataListView {
id: control 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() signal closeAll()
onListDataChanged: { Connections {
model = listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length 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 { delegate: ItemDelegate {
id: partDel id: partDel
property int ind: index property int ind: index
property var thisData: listData[ "participants" ][index] property var thisData: widgetData[ "participants" ][index]
state: "closed" state: "closed"
@ -50,7 +66,7 @@ DataListView {
} }
onPressAndHold: { onPressAndHold: {
app.openAthlete(thisData["PerId"]) app.openWidget({person:thisData["PerId"]})
} }
ParallelAnimation { ParallelAnimation {
@ -122,7 +138,7 @@ DataListView {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter 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 { Label {
@ -138,7 +154,7 @@ DataListView {
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
minimumPixelSize: 1 minimumPixelSize: 1
text: listData[ "participants" ][index]["firstname"] + " " + listData[ "participants" ][index]["lastname"] text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"]
} }
Label { Label {
@ -157,7 +173,7 @@ DataListView {
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: "<html>(<a href=\"" + (listData[ "participants" ][index]["fed_url"] === undefined ? "":listData[ "participants" ][index]["fed_url"]).toString() + "\">" + (listData[ "display_athlete" ] === "nation" ? listData[ "participants" ][index]["nation"] : listData[ "participants" ][index]["federation"]) + "</a>)</html>" text: "<html>(<a href=\"" + (widgetData[ "participants" ][index]["fed_url"] === undefined ? "":widgetData[ "participants" ][index]["fed_url"]).toString() + "\">" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + "</a>)</html>"
onLinkActivated: { onLinkActivated: {
Qt.openUrlExternally(link) Qt.openUrlExternally(link)
@ -191,7 +207,7 @@ DataListView {
font.pixelSize: Math.abs( height * 0.6 ) font.pixelSize: Math.abs( height * 0.6 )
minimumPixelSize: 1 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() { function getCompResults() {
var obj = control.listData["route_names"] var obj = control.widgetData["route_names"]
var resultData = [] var resultData = []
for(var prop in obj) { for(var prop in obj) {
// go through the whole array and search for data keys // 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", " - ")]) resultData.unshift([prop, obj[prop].replace("\n", " - ")])
//console.log("found " + obj[prop] + " at index " + prop) //console.log("found " + obj[prop] + " at index " + prop)
} }
@ -352,7 +368,7 @@ DataListView {
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
minimumPixelSize: 1 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 { Behavior on height {

View file

@ -24,8 +24,125 @@ import "../Components"
DataListView { DataListView {
id: control 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: ({}) 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 model: widgetData[ 'athletes' ] === undefined ? 0:widgetData[ 'athletes' ].length
onRefresh: { onRefresh: {
@ -48,7 +165,7 @@ DataListView {
} }
onClicked: { onClicked: {
app.openAthlete(thisData["PerId"]) app.openWidget({person:thisData["PerId"]})
} }
ParallelAnimation { 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 + ")"
}
} }

View file

@ -18,23 +18,132 @@
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtGraphicalEffects 1.0
import "../Components" import "../Components"
DataListView { DataListView {
id: control 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: ({}) 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 { delegate: ItemDelegate {
id: partDel id: partDel
property var thisData: widgetData[ "athletes" ][index] property int ind: index
property var thisData: widgetData[ "participants" ][partDel.ind]
width: parent.width width: parent.width
height: parseInt(thisData.cat) === root.catId ? undefined:0 height: 70
text: ""
opacity: 0 opacity: 0
scale: 0.9 scale: 0.9
@ -44,7 +153,7 @@ DataListView {
} }
onClicked: { onClicked: {
app.openAthlete(thisData["PerId"]) app.openWidget({person:thisData["PerId"]})
} }
ParallelAnimation { ParallelAnimation {
@ -53,48 +162,491 @@ DataListView {
NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 } NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
} }
text: ""
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 { Label {
anchors.fill: parent height: parent.height
anchors.leftMargin: parent.width * 0.05 width: text === "" ? parent.width * 0.08:parent.width * 0.1
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
font.bold: true font.bold: true
font.pixelSize: Math.abs( height * 0.4 ) 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 minimumPixelSize: height * 0.3
elide: "ElideRight" elide: "ElideRight"
text: control.getText(index) verticalAlignment: Text.AlignVCenter
} horizontalAlignment: Text.AlignHCenter
}
function getText(index){ text: "<html>(<a href=\"" + (widgetData[ "participants" ][index]["fed_url"] === undefined ? "":widgetData[ "participants" ][index]["fed_url"]).toString() + "\">" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + "</a>)</html>"
// ---------------------------- onLinkActivated: {
// if we have registration data Qt.openUrlExternally(link)
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[ root.listKey ][index]["reg_fed_id"]){
fedName = widgetData["federations"][i]["shortcut"]
} }
} }
} }
else {
// an international competition -> get nation
fedName = widgetData[ root.listKey ][index]["nation"] 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(" ")
} }
return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")"
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"]
}
}
}
}
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(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])
}
}
}
}
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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: "<html>(<a href=\"" + (widgetData[ "participants" ][index]["url"] === undefined ? "":widgetData[ "participants" ][index]["url"]).toString() + "\">" + (widgetData[ "display_athlete" ] === "nation" ? widgetData[ "participants" ][index]["nation"] : widgetData[ "participants" ][index]["federation"]) + "</a>)</html>"
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
}
}

View file

@ -160,7 +160,7 @@ Window {
Component.onCompleted: { Component.onCompleted: {
//app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300 //app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300
openWidget({nation:'GER'}) //openWidget({nation:'GER'})
} }
@ -532,63 +532,6 @@ Window {
loadingDl.close() 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) { function getErrorInfo(errorCode) {
var infoLevel var infoLevel

View file

@ -1,25 +1,20 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>main.qml</file> <file>main.qml</file>
<file>Pages/CompetitionCalendarPage.qml</file>
<file>Pages/RankingPage.qml</file>
<file>Pages/StartPage.qml</file> <file>Pages/StartPage.qml</file>
<file>Components/FancyButton.qml</file> <file>Components/FancyButton.qml</file>
<file>Components/AppToolBar.qml</file> <file>Components/AppToolBar.qml</file>
<file>Components/FancyBusyIndicator.qml</file> <file>Components/FancyBusyIndicator.qml</file>
<file>Components/InfoArea.qml</file> <file>Components/InfoArea.qml</file>
<file>Components/DataListView.qml</file> <file>Components/DataListView.qml</file>
<file>Components/ResultView.qml</file>
<file>Components/RegistrationView.qml</file>
<file>Components/StartlistView.qml</file>
<file>Components/RankingView.qml</file>
<file>Components/PullRefresher.qml</file> <file>Components/PullRefresher.qml</file>
<file>Pages/AthleteProfilePage.qml</file>
<file>Components/FadeAnimation.qml</file> <file>Components/FadeAnimation.qml</file>
<file>Pages/WidgetPage.qml</file> <file>Pages/WidgetPage.qml</file>
<file>Widgets/CalendarWidget.qml</file> <file>Widgets/CalendarWidget.qml</file>
<file>Widgets/ProfileWidget.qml</file> <file>Widgets/ProfileWidget.qml</file>
<file>Widgets/ResultWidget.qml</file> <file>Widgets/ResultWidget.qml</file>
<file>Widgets/RegistrationWidget.qml</file> <file>Widgets/RegistrationWidget.qml</file>
<file>Widgets/StartlistWidget.qml</file>
<file>Widgets/RankingWidget.qml</file>
</qresource> </qresource>
</RCC> </RCC>