import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtQuick.Controls.Material 2.15 ColoredItemDelegate { id: partDel property int thisIndex: index property var thisData: widgetData[ "participants" ][partDel.thisIndex] width: control.width height: partDelCol.showSideBySide ? 40:70 text: "" opacity: 0 scale: 0.9 onThisDataChanged: { fadeInPa.start() } onClicked: { app.openWidget({person:thisData["PerId"]}) } highlighted: partDel.thisIndex % 2 == 0 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 } } GridLayout { id: partDelCol property bool showSideBySide: app.landscape() || app.largeScreen() anchors.fill: parent anchors.margins: 5 columns: showSideBySide ? 2:1 rows: showSideBySide ? 1:2 columnSpacing: height * 0.2 rowSpacing: 0 Row { id: partDelFirstRow Layout.fillWidth: true Layout.fillHeight: true 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: partDel.thisData["result_rank"] === undefined ? "":partDel.thisData["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: partDel.thisData["firstname"] + " " + partDel.thisData["lastname"] + (partDel.thisData["start_number"] !== undefined ? (" (" + partDel.thisData["start_number"] + ")"):"") } 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 < 1 ? 1:height * 0.3 elide: "ElideRight" verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter text: "(" + (widgetData[ "display_athlete" ] === "nation" ? partDel.thisData["nation"] : partDel.thisData["federation"]) + ")" onLinkActivated: { Qt.openUrlExternally(link) } } } Row { id: partDelSecondRow Layout.preferredWidth: partDelCol.showSideBySide ? parent.width * 0.5 : parent.width Layout.preferredHeight: partDelCol.showSideBySide ? parent.height : parent.height * 0.5 visible: multiResRow.active || multiGenResRow.active || resultLa.acitve Row { id: multiResRow property bool active: parseInt(widgetData[ "route_order" ]) > -1 && boulderResRep.model > 0 height: parent.height width: active ? 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){ // TODO: clean var resultString = widgetData[ "participants" ][partDel.thisIndex]["boulder"+(index+1)] var numTrys = widgetData[ "participants" ][partDel.thisIndex]["try"+(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) } } else { resultList = [-1,-1] } if (numTrys !== undefined) { resultList.push(numTrys) } else { resultList.push(-1) } 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"); // clear all remainings from other routes context.clearRect(0, 0, width, height); 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 if(resultData[0] !== -1 || resultData[2] !== -1) { // if there is a result available -> draw background context.fillStyle = "#b7b7b7"; } else { context.fillStyle = "transparent"; } context.fill(); // outline context.lineWidth = 1; context.strokeStyle = Material.primaryTextColor; 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 = Material.primaryTextColor; 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 = Material.primaryTextColor; context.stroke(); } } } Label { id: boulderResTrysLa anchors.centerIn: parent height: parent.height / 2 width: parent.width / 2 visible: !boulderResZoneLa.visible && boulderResCv.resultData[2] > 0 fontSizeMode: Text.Fit font.pixelSize: height minimumPixelSize: 1 verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: "#dd000000" text: boulderResCv.resultData[2] } Label { id: boulderResZoneLa anchors { right: parent.right bottom: parent.bottom margins: boulderResCv.height * 0.05 } height: parent.height / 2 width: parent.width / 2 visible: parseInt(text) > 0 fontSizeMode: Text.Fit font.pixelSize: height minimumPixelSize: 1 verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: "#dd000000" 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: parseInt(text) > 0 fontSizeMode: Text.Fit font.pixelSize: height minimumPixelSize: 1 verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter color: "#dd000000" text: boulderResCv.resultData[0] } } } } } Row { id: multiGenResRow property bool active: ((parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0)) ? true:false height: parent.height width: active ? 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: multiGenResRow.active Rectangle { anchors { left: parent.left } width: 1 height: parent.height visible: index === 0 color: Material.primaryTextColor } Rectangle { anchors { right: parent.right } width: 1 height: parent.height color: Material.primaryTextColor } 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.thisIndex]["result"+(generalResRep.routes[index][0])] === undefined ? "": widgetData[ "participants" ][partDel.thisIndex]["result"+(generalResRep.routes[index][0])] } } } } Label { id: resultLa property bool acitve: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 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.thisIndex]["result"] === undefined ? "":widgetData[ "participants" ][partDel.thisIndex]["result"] } } } }