diff --git a/CHANGELOG.md b/CHANGELOG.md index af1ee6f..c456520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +# [0.8.0] - 2023-06-05 +### Added +- Show both results in speed quali + # [0.7.3] - 2023-05-02 ### Removed - Im-App purchase on android diff --git a/blueROCK.pro b/blueROCK.pro index a412723..44d5b65 100644 --- a/blueROCK.pro +++ b/blueROCK.pro @@ -1,7 +1,7 @@ QT += quick qml quickcontrols2 CONFIG += c++11 -VERSION = 0.7.4 +VERSION = 0.8.0 TARGET = blueROCK # The following define makes your compiler emit warnings if you use diff --git a/qzxing b/qzxing index cfc7285..6ea2b31 160000 --- a/qzxing +++ b/qzxing @@ -1 +1 @@ -Subproject commit cfc728583b867e157bd27e8b7c239c05a081e562 +Subproject commit 6ea2b31e26db9d43db027ba207f5c73dc9d759fc diff --git a/resources/qml/Components/BoulderResultRow.qml b/resources/qml/Components/BoulderResultRow.qml new file mode 100644 index 0000000..831f424 --- /dev/null +++ b/resources/qml/Components/BoulderResultRow.qml @@ -0,0 +1,262 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Material 2.15 + +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] + } + } + + } + + } + +} diff --git a/resources/qml/Components/GeneralResultRow.qml b/resources/qml/Components/GeneralResultRow.qml new file mode 100644 index 0000000..4050b0b --- /dev/null +++ b/resources/qml/Components/GeneralResultRow.qml @@ -0,0 +1,97 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Material 2.15 + +Row { + id: multiGenResRow + + property bool active: (parseInt(widgetData[ "route_order" ]) === -1) && (generalResRep.model > 0) + + height: parent.height + width: active ? parent.width - resultLa.width:0 + + enabled: active + + 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])] + } + + } + + } +} diff --git a/resources/qml/Components/ResultDelegate.qml b/resources/qml/Components/ResultDelegate.qml index e0d4df3..8531c13 100644 --- a/resources/qml/Components/ResultDelegate.qml +++ b/resources/qml/Components/ResultDelegate.qml @@ -107,370 +107,29 @@ ColoredItemDelegate { 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] - } - } - - } - - } + visible: boulderResRow.active || generalResRow.active || speedQualificationResRow.active || resultLa.active + BoulderResultRow { + id: boulderResRow } - Row { - id: multiGenResRow + GeneralResultRow { + id: generalResRow + } - 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])] - } - - } - - } + SpeedQualificationResultRow { + id: speedQualificationResRow } Label { id: resultLa - property bool acitve: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 + property bool active: ( parseInt(widgetData[ "route_num_problems" ]) > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 && !speedQualificationResRow.active width: enabled ? parent.width * 0.25:0 height: enabled ? parent.height:0 - enabled: ( boulderResRep.model > 0 || widgetData["discipline"] !== "boulder" ) && parseInt(widgetData[ "route_order" ]) > -1 + enabled: active verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter diff --git a/resources/qml/Components/SharePopup.qml b/resources/qml/Components/SharePopup.qml index 4a512df..9c15247 100644 --- a/resources/qml/Components/SharePopup.qml +++ b/resources/qml/Components/SharePopup.qml @@ -1,7 +1,7 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import QZXing 3.1 +import QZXing 3.3 import QtGraphicalEffects 1.0 Dialog { diff --git a/resources/qml/Components/SpeedQualificationResultRow.qml b/resources/qml/Components/SpeedQualificationResultRow.qml new file mode 100644 index 0000000..5a09ed0 --- /dev/null +++ b/resources/qml/Components/SpeedQualificationResultRow.qml @@ -0,0 +1,79 @@ +import QtQuick 2.10 +import QtQuick.Controls 2.15 +import QtQuick.Controls.Material 2.15 + +Row { + id: control + + property bool active: (parseInt(widgetData[ "route_order" ]) === 0) && (widgetData["discipline"] === "speed") && (thisData["result_l"] !== undefined || thisData["result_r"] !== undefined) + property var thisData: widgetData["participants"][partDel.thisIndex] + + height: parent.height + width: active ? parent.width - resultLa.width:0 + + enabled: active + + Repeater { + id: generalResRep + + model: 2 + + delegate: Item { + id: boulderGenResItm + + anchors.verticalCenter: parent.verticalCenter + + width: parent.width / ( generalResRep.model ) + height: parent.height + + visible: control.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 + + property string thisKey: "result_"+(["l", "r"][index]) + + 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 + font.bold: thisData["result_l"] !== undefined && thisData["result_r"] !== undefined && thisData[thisKey] === thisData["result"] + + text: control.thisData[thisKey] ?? "" + } + + } + + } +} diff --git a/resources/qml/Pages/QrCodeScanPage.qml b/resources/qml/Pages/QrCodeScanPage.qml index 7474d1c..1dc1612 100644 --- a/resources/qml/Pages/QrCodeScanPage.qml +++ b/resources/qml/Pages/QrCodeScanPage.qml @@ -1,7 +1,7 @@ import QtQuick 2.0 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import QZXing 3.1 +import QZXing 3.3 import QtMultimedia 5.12 import QtQuick.Shapes 1.12 import QtQuick.Controls.Material 2.12 diff --git a/resources/qml/qml.qrc b/resources/qml/qml.qrc index be351c6..9bec943 100644 --- a/resources/qml/qml.qrc +++ b/resources/qml/qml.qrc @@ -32,5 +32,8 @@ Pages/QrCodeScanPage.qml Components/MovingLabel.qml Components/SpeedFlowChart.js + Components/BoulderResultRow.qml + Components/GeneralResultRow.qml + Components/SpeedQualificationResultRow.qml