Many small and big improvements, see change log for details

This commit is contained in:
Dorian Zedler 2021-06-06 18:34:27 +02:00
parent 121589bf29
commit f9f6dd7f5d
Signed by: dorian
GPG key ID: 989DE36109AFA354
20 changed files with 1281 additions and 1191 deletions

View file

@ -4,10 +4,19 @@ 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/) 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). and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
# [0.03.1] - UR # [0.05] - UR
### Changed ### Changed
- the boulder result rect doesn't have a background if there is no result now - the boulder result rect doesn't have a background if there is no result now
- the selected route is kept when changing cats - the selected route is kept when changing cats
- the boulder result rect now shows the number of tries when there is not zone or top yet
- the speed flowchart now blocks the back key from closing the competition and instead closes itself
- redesigned start page
- added disclaimer regarding IFSC results
- some internal refactoring
- the calendar now scrolls less far down
- improoved layout in landscape mode
- some design changes in profile page and speed flowchart
- added second link for "further infos" in calendar
# [0.03.0] - 2019-07-11 # [0.03.0] - 2019-07-11
### Added ### Added
@ -21,7 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- event website url is now present in the cat select dialog if available - event website url is now present in the cat select dialog if available
### Changed ### Changed
- competitons are clickable if there is a infosheet or event website url available event when they don't have any categories - competitons are clickable if there is a infosheet or event website url available even when they don't have any categories
# [0.01.6] - 2019-06-15 # [0.01.6] - 2019-06-15
### Fixed ### Fixed

View file

@ -50,9 +50,7 @@ DISTFILES += \
android-sources/gradle/wrapper/gradle-wrapper.properties \ android-sources/gradle/wrapper/gradle-wrapper.properties \
android-sources/gradlew \ android-sources/gradlew \
android-sources/gradlew.bat \ android-sources/gradlew.bat \
android-sources/res/values/libs.xml \ android-sources/res/values/libs.xml
resources/shared/icons/bluerock/index.theme \
$$files(resources/shared/icons/*.png, true)
android { android {
QT += androidextras QT += androidextras

View file

@ -0,0 +1,32 @@
import QtQuick 2.9
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.0
RowLayout {
id: control
Image {
Layout.preferredHeight: parent.height
Layout.preferredWidth: height
Layout.alignment: Layout.Center
fillMode: Image.PreserveAspectFit
mipmap: true
source: "qrc:/icons/blueRockHold.png"
}
Label {
Layout.preferredHeight: parent.height
Layout.fillWidth: true
Layout.alignment: Layout.Center
fontSizeMode: Text.Fit
font.pixelSize: parent.height * 0.6
font.bold: true
verticalAlignment: Text.AlignVCenter
text: "blueROCK"
}
}

View file

@ -32,10 +32,10 @@ Item {
property int postRefreshDelay: 1000 // delay after reload funcion has finished property int postRefreshDelay: 1000 // delay after reload funcion has finished
property int preRefreshDelay: 1000 // delay before reload funcion is called property int preRefreshDelay: 1000 // delay before reload funcion is called
property int refreshPosition: height * 1.2 // position of the item when refreshing property int refreshPosition: height * 1.7 // position of the item when refreshing
property int dragOutPosition: height * 1.8 // maximum drag out property int dragOutPosition: height * 1.8 // maximum drag out
property double dragRefreshPositionMultiplier: 0.5 // position of the item when starting to refresh property double dragRefreshPositionMultiplier: 0.6 // position of the item when starting to refresh
property color backgroundColor: "white" // color for the pre-defined background property color backgroundColor: "white" // color for the pre-defined background
property color pullIndicatorColor: "black" // color for the pre-defined pull indicator property color pullIndicatorColor: "black" // color for the pre-defined pull indicator

View file

@ -0,0 +1,484 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
ItemDelegate {
id: partDel
property int ind: index
property var thisData: widgetData[ "participants" ][partDel.ind]
width: control.width
height: app.landscape() ? 40:70
text: ""
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 }
}
Rectangle {
id: partDelBackgroundRect
anchors.fill: parent
width: partDel.width
color: partDel.ind % 2 == 0 ? "white":"lightgrey"
opacity: 0.2
}
GridLayout {
id: partDelCol
anchors.fill: parent
anchors.margins: 5
columns: app.landscape() ? 2:1
rows: app.landscape()? 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: "<html>(<a href=\"" + (partDel.thisData["fed_url"] === undefined ? "":partDel.thisData["fed_url"]).toString() + "\">" + (widgetData[ "display_athlete" ] === "nation" ? partDel.thisData["nation"] : partDel.thisData["federation"]) + "</a>)</html>"
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
Row {
id: partDelSecondRow
Layout.preferredWidth: app.landscape() ? parent.width * 0.5 : parent.width
Layout.preferredHeight: app.landscape() ? 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.ind]["boulder"+(index+1)]
var numTrys = widgetData[ "participants" ][partDel.ind]["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) {
// if there is a result available -> draw background
context.fillStyle = "#b7b7b7";
}
else {
context.fillStyle = "transparent";
}
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: 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
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
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
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: "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
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.ind]["result"] === undefined ? "":widgetData[ "participants" ][partDel.ind]["result"]
}
}
}
}

View file

@ -0,0 +1,139 @@
import QtQuick 2.9
import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.3
Dialog {
id: control
property var dataObj
property string subTitle: ""
property int implicitY: parent.height - implicitHeight
signal selectionFinished(int index, var data)
parent: Overlay.overlay
x: 0
y: parent.height - implicitHeight
opacity: 1
width: parent.width
implicitWidth: width
contentHeight: Math.min(parent.height * 0.7, implicitContentHeight)
implicitHeight: contentHeight + topPadding + bottomPadding + header.height
padding: 30
modal: true
focus: true
title: ""
header: Column {
id: selectorPuHeaderCol
width: control.width
height: headerSubLa.text !== "" && headerLa.text !== "" ? 73 : 40
Label {
id: headerLa
visible: control.title
width: selectorPuHeaderCol.width
elide: "ElideRight"
padding: control.padding
bottomPadding: 0
font.bold: true
font.pixelSize: 16
text: control.title
onLinkActivated: {
console.log("Opening " + link)
Qt.openUrlExternally(link)
}
}
Label {
id: headerSubLa
visible: control.subTitle
width: selectorPuHeaderCol.width
elide: "ElideRight"
padding: control.padding
topPadding: 5
bottomPadding: 0
font.bold: true
font.pixelSize: 16
text: control.subTitle
onLinkActivated: {
console.log("Opening " + link)
Qt.openUrlExternally(link)
}
}
}
background: Item {
Rectangle {
id: backgroundRect
anchors {
fill: parent
bottomMargin: -radius
}
radius: control.leftPadding
color: control.Material.dialogColor
}
}
function appear(dataObj, title, subTitle) {
if(dataObj.length > 0){
control.dataObj = dataObj
}
else {
control.dataObj = undefined
}
control.title = title
control.subTitle = subTitle === undefined ? "":subTitle
control.open()
}
enter: Transition {
NumberAnimation {
property: "opacity";
from: 0
to: 1.0
easing.type: Easing.Linear
}
NumberAnimation {
property: "y"
from: control.parent.height - control.implicitHeight * 0.7
to: control.parent.height - control.implicitHeight
}
}
exit: Transition {
NumberAnimation {
property: "opacity";
from: 1
to: 0
}
NumberAnimation {
property: "y"
from: control.parent.height - control.implicitHeight
to: control.parent.height - control.implicitHeight * 0.7
}
}
}

View file

@ -20,32 +20,24 @@ import QtQuick 2.10
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.1 import QtQuick.Controls.Material 2.1
import QtGraphicalEffects 1.0
ListView { Item {
id: control id: control
property var flowchartData property var flowchartData
property var allFlowchartData property var allFlowchartData
property int rounds: 0 property int rounds: 0
property int tileSize: app.height / 8 * 0.8
property int refreshes: 0 property int refreshes: 0
property int roundRefreshes: 1 property int roundRefreshes: 1
anchors.fill: parent property int roundCount: 0
anchors.margins: 10
spacing: app.width * 0.1
orientation: ListView.LeftToRight
boundsBehavior: ListView.StopAtBounds
onFlowchartDataChanged: { onFlowchartDataChanged: {
prepareData() prepareData()
} }
model: 0
function prepareData() { function prepareData() {
if(!control.enabled || control.flowchartData === undefined || control.flowchartData['route_names'] === undefined) if(!control.enabled || control.flowchartData === undefined || control.flowchartData['route_names'] === undefined)
@ -223,189 +215,273 @@ ListView {
} }
control.allFlowchartData = allData control.allFlowchartData = allData
control.model = (parseInt(Object.keys(control.flowchartData['route_names']).length > 2 ? control.flowchartData['route_names']["2"].includes("8") ? 2:1 : 0) + 2) control.roundCount = (parseInt(Object.keys(control.flowchartData['route_names']).length > 2 ? control.flowchartData['route_names']["2"].includes("8") ? 2:1 : 0) + 2)
//console.log(JSON.stringify(allData)) //console.log(JSON.stringify(allData))
} }
delegate: Column { ListView {
id: roundCol id: roundListView
property int thisIndex: index property int columnWidth: height * 0.3
property int thisRound: thisRoundIsValid ? control.allFlowchartData[roundCol.thisIndex][control.allFlowchartData[roundCol.thisIndex].length-2]:-1 property int columnHeight: height
property bool thisRoundIsValid: control.allFlowchartData !== undefined && control.allFlowchartData[roundCol.thisIndex] !== undefined && control.allFlowchartData[roundCol.thisIndex].length > 2
property bool thisIsLastRound: thisIndex === control.model - 1
width: app.width * 0.5 anchors {
height: control.height top: parent.top
bottom: parent.bottom
//spacing: app.width * 0.1 horizontalCenter: parent.horizontalCenter
Label {
id: roundNameLa
width: parent.width
height: control.height * 0.05
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
font.pixelSize: height * 0.6
minimumPixelSize: 1
font.bold: true
text: roundCol.thisRoundIsValid && control.allFlowchartData[roundCol.thisIndex][control.allFlowchartData[roundCol.thisIndex].length-1] !== undefined ? control.allFlowchartData[roundCol.thisIndex][control.allFlowchartData[roundCol.thisIndex].length-1] : "-"
} }
Repeater { width: Math.min((columnWidth + spacing) * model, control.width)
id: rectRep
model: Math.max( Math.pow(2, control.model-1) * Math.pow(0.5, (index)), 2)
delegate: Item {
id: matchItm
property bool lowerPart: (index%2 > 0) spacing: app.height * 0.05
property var matchData: roundCol.thisRoundIsValid ? control.allFlowchartData[ thisIsSmallFinal ? roundCol.thisIndex+1 : roundCol.thisIndex][ thisIsSmallFinal ? 0:matchItm.thisIndex]:undefined orientation: ListView.LeftToRight
boundsBehavior: ListView.StopAtBounds
property int thisIndex: index model: control.roundCount
property int thisRound: parseInt(roundCol.thisRound) - (thisIsSmallFinal ? 1:0)
property var thisMatchData: thisMatchDataIsValid ? matchData:[]
property bool thisMatchDataIsValid: (matchData !== undefined && matchData !== null && typeof matchData === "object" && matchData.length > 0) delegate: Item {
property bool thisMatchIsOver: thisMatchDataIsValid && thisMatchData[0]['result_rank'+thisRound] !== undefined && thisMatchData[1]['result_rank'+thisRound] !== undefined id: roundItem
property bool thisIsFinal: roundCol.thisIsLastRound && thisIndex === rectRep.model - 2 property int thisIndex: index
property bool thisIsSmallFinal: roundCol.thisIsLastRound && thisIndex === rectRep.model - 1 property int thisRound: thisRoundIsValid ? control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-2]:-1
property bool thisRoundIsValid: control.allFlowchartData !== undefined
&& control.allFlowchartData[roundItem.thisIndex] !== undefined
&& control.allFlowchartData[roundItem.thisIndex].length > 2
property int winnerIndex: thisMatchIsOver ? (parseInt(thisMatchData[0]['result_rank'+thisRound]) < parseInt(thisMatchData[1]['result_rank'+thisRound]) ? 0:1) : -1 property bool thisIsLastRound: thisIndex === control.roundCount - 1
property bool thisIsSemiFinal: thisIndex === control.roundCount - 2 && rectRep.model === 2
height: !roundCol.thisIsLastRound ? (roundCol.height - roundNameLa.height) / rectRep.model - roundCol.spacing : (thisIsFinal ? (roundCol.height - roundNameLa.height) * 0.5 + control.tileSize * 0.5 : (roundCol.height - roundNameLa.height) - (roundCol.height - roundNameLa.height) * 0.5 + control.tileSize * 0.5 ) property int tileSize: (roundItem.height / 8 - roundNameLa.height) * 1.45
width: parent.width
onMatchDataChanged: { width: roundListView.columnWidth
fadeInPa.start() height: roundListView.columnHeight
}
ParallelAnimation { Column {
id: fadeInPa id: roundCol
NumberAnimation { target: matchItm; property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { target: matchItm; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
}
Canvas { anchors.fill: parent
id: lineCanvas
width: app.width; height: app.height
contextType: "2d"
visible: !roundCol.thisIsLastRound Label {
id: roundNameLa
property int targetX: matchItm.width + control.spacing
property int targetY: matchItm.lowerPart ? 0:matchItm.height
Path {
id: myPath
startX: matchRect.x + matchRect.width * matchRect.scale ; startY: matchRect.y + matchRect.height * 0.5
PathCurve { x: lineCanvas.targetX ; y: lineCanvas.targetY }
}
onPaint: {
context.strokeStyle = Qt.rgba(.4,.6,.8);
context.path = myPath;
context.stroke();
}
}
Rectangle {
id: matchRect
anchors {
centerIn: !matchItm.thisIsFinal ? parent:undefined
bottom: matchItm.thisIsFinal ? parent.bottom:undefined
}
//anchors.verticalCenterOffset: matchItm.lowerPart ? 10:10
width: parent.width width: parent.width
height: control.tileSize height: control.height * 0.05
//scale: 0.9 horizontalAlignment: Text.AlignHCenter
color: "white" verticalAlignment: Text.AlignVCenter
border.color: "lightgrey" fontSizeMode: Text.Fit
border.width: 1 font.pixelSize: height * 0.6
radius: height * 0.2 minimumPixelSize: 1
Material.elevation: 10 font.bold: true
text: roundItem.thisRoundIsValid
&& control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] !== undefined ?
control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] :
"-"
}
Grid { Repeater {
columns: app.landscape() ? 2:0 id: rectRep
rows: app.landscape() ? 0:2 model: Math.max( Math.pow(2, control.roundCount-1) * Math.pow(0.5, (roundItem.thisIndex)), 2)
delegate: Item {
id: matchItm
spacing: app.landscape() ? height * 0.4:0 property bool lowerPart: (index%2 > 0)
anchors.fill: parent property var matchData: roundItem.thisRoundIsValid ?
anchors.margins: matchRect.radius * 0.5 control.allFlowchartData[
thisIsSmallFinal ?
roundItem.thisIndex+1 :
roundItem.thisIndex
][ thisIsSmallFinal ? 0:matchItm.thisIndex]:
undefined
Repeater { property int thisIndex: index
// for the two athletes property int thisRound: parseInt(roundItem.thisRound) - (thisIsSmallFinal ? 1:0)
model: 2 property var thisMatchData: thisMatchDataIsValid ? matchData:[]
delegate: RowLayout { property bool thisMatchDataIsValid: (matchData !== undefined && matchData !== null && typeof matchData === "object" && matchData.length > 0)
property bool thisMatchIsOver: thisMatchDataIsValid && thisMatchData[0]['result_rank'+thisRound] !== undefined && thisMatchData[1]['result_rank'+thisRound] !== undefined
height: app.landscape() ? parent.height:parent.height / 2 - parent.spacing property bool thisIsFinal: roundItem.thisIsLastRound && thisIndex === rectRep.model - 2
width: app.landscape() ? parent.width / 2 - parent.spacing : parent.width property bool thisIsSmallFinal: roundItem.thisIsLastRound && thisIndex === rectRep.model - 1
spacing: app.landscape() ? height * 0.1:height * 0.1 property int winnerIndex: thisMatchIsOver ? (parseInt(thisMatchData[0]['result_rank'+thisRound]) < parseInt(thisMatchData[1]['result_rank'+thisRound]) ? 0:1) : -1
Label { height: !roundItem.thisIsLastRound ?
Layout.preferredHeight: parent.height (roundItem.height - roundNameLa.height) / rectRep.model - roundCol.spacing :
(thisIsFinal ?
(roundItem.height - roundNameLa.height) * 0.5 + roundItem.tileSize * 0.5 :
(roundItem.height - roundNameLa.height) - (roundItem.height - roundNameLa.height) * 0.5 + roundItem.tileSize * 0.5
)
height: parent.height width: roundItem.width
verticalAlignment: Text.AlignVCenter onMatchDataChanged: {
font.pixelSize: height * 0.7 fadeInPa.start()
fontSizeMode: Text.Fit }
minimumPixelSize: 1
Layout.alignment: Layout.Left ParallelAnimation {
id: fadeInPa
NumberAnimation { target: matchItm; property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { target: matchItm; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
}
text: matchItm.thisMatchData[index] !== undefined ? (parseInt(matchItm.thisMatchData[index]['result_rank0']) < 10 ?matchItm.thisMatchData[index]['result_rank0'] + " ":matchItm.thisMatchData[index]['result_rank0']): "" Canvas {
id: lineCanvas
width: app.width; height: app.height
contextType: "2d"
visible: !roundItem.thisIsLastRound
property int targetYFactor: matchItm.lowerPart ? -1:1
Path {
id: firstPartPath
startX: matchItm.width
startY: matchItm.height * 0.5
PathQuad {
id: firstPartPathQuad
relativeX: roundListView.spacing * 0.5
relativeY: matchItm.height * 0.25 * lineCanvas.targetYFactor
relativeControlX: relativeX
relativeControlY: 0
} }
Label { PathQuad {
Layout.preferredHeight: parent.height relativeX: roundListView.spacing * 0.5
relativeY: matchItm.height * 0.25 * lineCanvas.targetYFactor
height: parent.height relativeControlX: 0
relativeControlY: relativeY
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
//horizontalAlignment: app.landscape() ? Text.AlignLeft : Text.AlignLeft
font.pixelSize: app.landscape() ? height * 0.4 : height * 0.6
minimumPixelSize: (app.landscape() ? height * 0.35 : height * 0.5) < 1 ? 1 : (app.landscape() ? height * 0.35 : height * 0.5)
fontSizeMode: Text.Fit
font.bold: matchItm.winnerIndex === index
elide: "ElideRight"
Layout.fillWidth: true
color: matchItm.winnerIndex === index ? "green":"black"
text: matchItm.thisMatchData[index] !== undefined ? matchItm.thisMatchData[index]['firstname'] + " " + matchItm.thisMatchData[index]['lastname'] :"-"
} }
}
Label { onPaint: {
Layout.preferredHeight: parent.height context.strokeStyle = "lightgrey"
context.lineWidth = matchRect.height * 0.05
context.path = firstPartPath;
context.stroke();
}
}
height: parent.height RectangularGlow {
id: effect
anchors.fill: matchRect
glowRadius: 0
spread: 0
opacity: 0.3
color: "black"
cornerRadius: matchRect.radius
}
verticalAlignment: Text.AlignVCenter Rectangle {
font.pixelSize: app.landscape() ? height * 0.35 : height * 0.5 id: matchRect
Layout.alignment: Layout.Right anchors {
centerIn: !matchItm.thisIsFinal ? parent:undefined
bottom: matchItm.thisIsFinal ? parent.bottom:undefined
}
text: matchItm.thisMatchData[index] !== undefined && matchItm.thisMatchData[index]['result'+matchItm.thisRound] !== undefined ? //anchors.verticalCenterOffset: matchItm.lowerPart ? 10:10
( parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]) ? width: parent.width
(parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]).toFixed(2)) height: roundItem.tileSize
: matchItm.thisMatchData[index]['result'+matchItm.thisRound] ) //scale: 0.9
: "-" color: "white"
border.color: "lightgrey"
border.width: 0
radius: height * 0.2
Column {
spacing: 0
anchors.fill: parent
anchors.margins: matchRect.radius * 0.5
Repeater {
// for the two athletes
model: 2
delegate: RowLayout {
height: parent.height / 2 - parent.spacing
width: parent.width
spacing: height * 0.1
Label {
Layout.preferredHeight: parent.height
Layout.preferredWidth: parent.width * 0.15
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
font.pixelSize: height * 0.7
fontSizeMode: Text.Fit
minimumPixelSize: 1
text: matchItm.thisMatchData[index] !== undefined ?
(
parseInt(matchItm.thisMatchData[index]['result_rank0']) < 10 ?
matchItm.thisMatchData[index]['result_rank0'] + " ":
matchItm.thisMatchData[index]['result_rank0']
):
""
}
Label {
Layout.preferredHeight: parent.height
Layout.fillWidth: true
height: parent.height
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
font.pixelSize: height * 0.5
font.bold: matchItm.winnerIndex === index
elide: "ElideRight"
color: matchItm.winnerIndex === index ? "green":"black"
text: matchItm.thisMatchData[index] !== undefined ? matchItm.thisMatchData[index]['firstname'] + " " + matchItm.thisMatchData[index]['lastname'] :"-"
}
Label {
Layout.preferredHeight: parent.height
height: parent.height
verticalAlignment: Text.AlignVCenter
font.pixelSize: height * 0.5
text: matchItm.thisMatchData[index] !== undefined && matchItm.thisMatchData[index]['result'+matchItm.thisRound] !== undefined ?
( parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]) ?
(parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]).toFixed(2))
: matchItm.thisMatchData[index]['result'+matchItm.thisRound] )
: "-"
}
}
} }
} }
} }
} }
} }
}
Loader {
id: blueRockBadgeLoader
x: (parent.width - width) / 2
y: (parent.height - roundNameLa.height - height) / 2 + roundNameLa.height
sourceComponent: roundItem.thisIsSemiFinal ? blueRockBadgeComponent:undefined
Component {
id: blueRockBadgeComponent
BlueRockBadge {
width: roundItem.width
height: width * 0.25
}
}
} }
} }
} }

View file

@ -0,0 +1,101 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtPurchasing 1.12
Rectangle {
id: speedFlowChartLockedOverlay
anchors.fill: parent
anchors.margins: -20
color: "white"
Connections {
target: speedFlowChartProduct
function onPurchaseFailed() {
purchaseBt.text = qsTr("Purchase failed")
purchaseBt.enabled = false
buttonTextResetTimer.start()
}
}
Timer {
id: buttonTextResetTimer
interval: 2000
running: false
repeat: false
onTriggered: {
purchaseBt.text = (speedFlowChartProduct.status === Product.Registered
? "Buy now for " + speedFlowChartProduct.price
: qsTr("this item is currently unavailable"))
purchaseBt.enabled = true
}
}
ColumnLayout {
id: lockedLayout
anchors {
fill: parent
topMargin: parent.height * 0.05
bottomMargin: parent.height * 0.1
rightMargin: parent.width * 0.1 + 20
leftMargin: parent.width * 0.1 + 20
}
//spacing: parent.height * 0.05
Image {
id: name
Layout.alignment: Layout.Center
Layout.preferredHeight: height
Layout.preferredWidth: width
width: lockedLayout.height * 0.1
height: width
mipmap: true
source: "qrc:/icons/lock.png"
}
Text {
Layout.fillWidth: true
height: parent.height * 0.05
text: qsTr("This is a premium feature.")
font.bold: true
font.pixelSize: parent.height * 0.05
fontSizeMode: Text.Fit
minimumPixelSize: 1
horizontalAlignment: Text.AlignHCenter
}
SwipeGallery {
Layout.fillHeight: true
Layout.fillWidth: true
images: ["qrc:/screenshots/SpeedFlowchartDemo/1.png","qrc:/screenshots/SpeedFlowchartDemo/2.png","qrc:/screenshots/SpeedFlowchartDemo/3.png"]
}
Button {
id: purchaseBt
Layout.alignment: Layout.Center
enabled: speedFlowChartProduct.status === Product.Registered
text: speedFlowChartProduct.status === Product.Registered
? "Buy now for " + speedFlowChartProduct.price
: qsTr("this item is currently unavailable")
icon.name: "buy"
onClicked: speedFlowChartProduct.purchase()
}
}
}

View file

@ -0,0 +1,116 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
Rectangle {
id: control
property var flowchartData: ({})
// always unlock in debug mode
property bool unlocked: appSettings.read("speedBackendPurchase") === "1" || QT_DEBUG
state: "hidden"
anchors {
top: parent.top
bottom: parent.bottom
left: parent.right
}
width: parent.width
height: parent.height
color: Material.background
onStateChanged: {
if(state === "visible" && unlocked) {
speedFlowChartLoader.sourceComponent = speedFlowChartComponent
}
else if(state === "visible" && !unlocked) {
speedFlowChartLoader.sourceComponent = speedFlowChartLockerComponent
}
else {
speedFlowChartLoader.sourceComponent = undefined
}
}
function toggle() {
if(control.state === "hidden"){
control.state = "visible"
}
else {
control.state = "hidden"
}
}
function isVisible() {
return control.state === "visible"
}
Connections {
target: speedFlowChartProduct
function onPurchaseRestored() {
control.unlocked = appSettings.read("speedBackendPurchase") === "1" ? "unlocked":"locked"
}
function onPurchaseSucceeded() {
control.unlocked = appSettings.read("speedBackendPurchase") === "1" ? "unlocked":"locked"
}
}
Loader {
id: speedFlowChartLoader
anchors.fill: parent
Component {
id: speedFlowChartComponent
SpeedFlowChart {
anchors.fill: parent
anchors.margins: 10
flowchartData: control.flowchartData
}
}
Component {
id: speedFlowChartLockerComponent
SpeedFlowChartLocker {
}
}
}
states: [
State {
name: "hidden"
PropertyChanges {
target: control
opacity: 0
anchors.leftMargin: 0
}
},
State {
name: "visible"
PropertyChanges {
target: control
opacity: 1
anchors.leftMargin: -parent.width
}
}
]
transitions: [
Transition {
NumberAnimation {
properties: "opacity,scale,anchors.leftMargin"
duration: 200
easing.type: Easing.InOutQuad
}
}
]
}

View file

@ -29,9 +29,8 @@ Page {
signal headerComponentChanged() signal headerComponentChanged()
RowLayout { BlueRockBadge {
id: headerLayout id: headerBadge
anchors { anchors {
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
top: parent.top top: parent.top
@ -40,28 +39,6 @@ Page {
height: menuGr.buttonSize * 0.3 height: menuGr.buttonSize * 0.3
spacing: anchors.topMargin * 0.5 spacing: anchors.topMargin * 0.5
Image {
Layout.preferredHeight: parent.height
Layout.preferredWidth: height
fillMode: Image.PreserveAspectFit
mipmap: true
source: "qrc:/icons/blueRockHold.png"
}
Label {
Layout.preferredHeight: parent.height
Layout.fillWidth: true
font.pixelSize: parent.height * 0.6
font.bold: true
verticalAlignment: Text.AlignVCenter
text: "blueROCK"
}
} }
Grid { Grid {
@ -125,7 +102,7 @@ Page {
anchors { anchors {
horizontalCenter: parent.horizontalCenter horizontalCenter: parent.horizontalCenter
bottom: parent.bottom bottom: parent.bottom
bottomMargin: headerLayout.anchors.topMargin bottomMargin: headerBadge.anchors.topMargin
} }
width: parent.width * 0.9 width: parent.width * 0.9
@ -161,6 +138,10 @@ Page {
contentItem: Label { contentItem: Label {
wrapMode: Text.Wrap wrapMode: Text.Wrap
width: ifscDisclaimerDialog.width * 0.8
height: implicitHeight
text: text:
"Unfortunately, the IFSC has restricted the access to their data and <b>is not willing to share results with blueROCK anymore</b>. " + "Unfortunately, the IFSC has restricted the access to their data and <b>is not willing to share results with blueROCK anymore</b>. " +
"Because of this, blueROCK is no longer able to access and display IFSC results.<br><br>" + "Because of this, blueROCK is no longer able to access and display IFSC results.<br><br>" +

View file

@ -245,107 +245,16 @@ Page {
} }
Dialog { SelectorPopup {
id: selectorPu id: selectorPu
property var dataObj contentItem: ListView {
property string subTitle: ""
signal selectionFinished(int index, var data)
x: 0 //root.width / 2 - width / 2
y: root.height - selectorPu.height * 0.7//root.height - height //root.height / 2 - height / 2
opacity: 0
width: root.width
height: selectorLv.implicitHeight
modal: true
focus: true
title: ""
header: Column {
id: selectorPuHeaderCol
width: parent.width
Label {
id: headerLa
visible: selectorPu.title
width: parent.width
elide: "ElideRight"
padding: 24
bottomPadding: 0
font.bold: true
font.pixelSize: 16
background: Rectangle {
radius: 2
color: selectorPu.Material.dialogColor
clip: true
}
text: selectorPu.title
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
Label {
id: headerSubLa
visible: selectorPu.subTitle
width: parent.width
elide: "ElideRight"
padding: 24
topPadding: 5
bottomPadding: 0
font.bold: true
font.pixelSize: 16
background: Rectangle {
radius: 2
color: selectorPu.Material.dialogColor
clip: true
}
text: selectorPu.subTitle
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
function appear(dataObj, title, subTitle) {
if(dataObj.length > 0){
selectorPu.dataObj = dataObj
}
else {
selectorPu.dataObj = undefined
}
selectorPu.title = title
selectorPu.subTitle = subTitle === undefined ? "":subTitle
selectorPu.open()
}
ListView {
id: selectorLv id: selectorLv
property int delegateHeight: 50 property int delegateHeight: 50
spacing: 10
anchors.fill: parent implicitHeight: model === 0 ? 0:(delegateHeight + spacing) * model
implicitWidth: parent.width
implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100
model: selectorPu.dataObj !== undefined ? selectorPu.dataObj.length:0 model: selectorPu.dataObj !== undefined ? selectorPu.dataObj.length:0
@ -377,32 +286,5 @@ Page {
} }
} }
} }
enter: Transition {
NumberAnimation {
property: "opacity";
//from: 0.0;
to: 1.0
}
NumberAnimation {
property: "y"
//from: root.height - selectorPu.height * 0.7
to: root.height - selectorPu.height
}
}
exit: Transition {
NumberAnimation {
property: "opacity";
//from: 1.0;
to: 0.0
}
NumberAnimation {
property: "y"
//from: root.height - selectorPu.height
to: root.height - selectorPu.height * 0.7
}
}
} }
} }

View file

@ -150,7 +150,7 @@ DataListView {
if(endDate.getTime() < new Date().getTime()){ if(endDate.getTime() < new Date().getTime()){
// end date is already over -> move the list view down! // end date is already over -> move the list view down!
control.positionViewAtIndex(i, ListView.Top) control.positionViewAtIndex(i - 2, ListView.Top)
//console.log("moving down!") //console.log("moving down!")
} }
} }
@ -400,114 +400,18 @@ DataListView {
delegate: CompetitionCalendarDelegate { delegate: CompetitionCalendarDelegate {
} }
section.property: "month" SelectorPopup {
section.delegate: ItemDelegate {
id: name
background: Rectangle {
color: "red"
}
width: parent.width
text: section
}
Dialog {
id: filterSelectPu id: filterSelectPu
property var dataObj contentItem: ListView {
property string subTitle: ""
signal selectionFinished(int index, var data)
x: 0 - control.anchors.leftMargin //root.width / 2 - width / 2
y: root.height - filterSelectPu.height * 0.7//root.height - height //root.height / 2 - height / 2
opacity: 0
width: control.width + control.anchors.leftMargin + control.anchors.rightMargin
height: selectorLv.implicitHeight
modal: true
focus: true
title: ""
function appear(dataObj, title, subTitle) {
if(dataObj.length > 0){
filterSelectPu.dataObj = dataObj
filterSelectPu.title = title
filterSelectPu.subTitle = subTitle === undefined ? "":subTitle
filterSelectPu.open()
}
}
header: Column {
id: filterSelectPuHeaderCol
width: parent.width
Label {
id: headerLa
visible: filterSelectPu.title
width: parent.width
elide: "ElideRight"
padding: 24
bottomPadding: 0
font.bold: true
font.pixelSize: 16
background: Rectangle {
radius: 2
//color: filterSelectPu.Material.dialogColor
clip: true
}
text: filterSelectPu.title
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
Label {
id: headerSubLa
visible: filterSelectPu.subTitle
width: parent.width
elide: "ElideRight"
padding: 24
topPadding: 5
bottomPadding: 0
font.bold: true
font.pixelSize: 16
background: Rectangle {
radius: 2
//color: filterSelectPu.Material.dialogColor
clip: true
}
text: filterSelectPu.subTitle
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
ListView {
id: selectorLv id: selectorLv
property int delegateHeight: 50 property int delegateHeight: 50
spacing: 10
anchors.fill: parent clip: true
implicitWidth: parent.width implicitHeight: model === 0 ? 0:(delegateHeight + spacing) * model
implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100
model: filterSelectPu.dataObj !== undefined ? filterSelectPu.dataObj.length:0 model: filterSelectPu.dataObj !== undefined ? filterSelectPu.dataObj.length:0
@ -520,13 +424,12 @@ DataListView {
leftMargin: 3 leftMargin: 3
bottom: selectorLv.bottom bottom: selectorLv.bottom
} }
} }
delegate: CheckDelegate { delegate: CheckDelegate {
id: catBt id: catBt
width: parent.width width: selectorLv.width
height: text !== "" ? selectorLv.delegateHeight:0 height: text !== "" ? selectorLv.delegateHeight:0
//flat: true //flat: true
@ -567,31 +470,5 @@ DataListView {
} }
} }
} }
enter: Transition {
NumberAnimation {
property: "opacity";
//from: 0.0;
to: 1.0
}
NumberAnimation {
property: "y"
//from: root.height - filterSelectPu.height * 0.7
to: root.height - filterSelectPu.height
}
}
exit: Transition {
NumberAnimation {
property: "opacity";
//from: 1.0;
to: 0.0
}
NumberAnimation {
property: "y"
//from: root.height - filterSelectPu.height
to: root.height - filterSelectPu.height * 0.7
}
}
} }
} }

View file

@ -19,6 +19,7 @@
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtQuick.Controls.Material 2.3 import QtQuick.Controls.Material 2.3
import QtGraphicalEffects 1.0
import "../Components" import "../Components"
@ -43,25 +44,11 @@ Page {
id: mainSv id: mainSv
anchors.fill: parent anchors.fill: parent
anchors.margins: 10 anchors.margins: 20
anchors.rightMargin: 14
contentWidth: parent.width - anchors.leftMargin - anchors.rightMargin contentWidth: parent.width - anchors.margins * 2
ScrollBar.vertical: ScrollBar { ScrollBar.vertical.policy: ScrollBar.AlwaysOff
anchors {
top: mainSv.top
left: mainSv.right
margins: 10
leftMargin: 3
bottom: mainSv.bottom
}
width: 8
active: true
}
Column { Column {
id: mainCol id: mainCol
@ -72,25 +59,61 @@ Page {
height: control.height * 0.3 height: control.height * 0.3
width: parent.width width: parent.width
Image { spacing: photoContainerItem.width * 0.1
id: photo
property bool ready: false
Item {
id: photoContainerItem
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
height: parent.height * 0.9 height: parent.height * 0.9
width: status === Image.Null || status === Image.Error ? 0:parent.width * 0.5 width: photo.status === Image.Null || photo.status === Image.Error ? 0:parent.width * 0.4
fillMode: Image.PreserveAspectFit RectangularGlow {
id: effect
visible: photo.ready
anchors.fill: photo
glowRadius: 1
opacity: 0.4
color: "black"
cornerRadius: photo.width * 0.2
}
source: widgetData["photo"] === undefined ? "":widgetData["photo"].replace("https", "http").replace("www.digitalrock.de", "egw.ifsc-climbing.org") Image {
asynchronous: true id: photo
property bool ready: photo.status === Image.Ready
FancyBusyIndicator {
height: width
anchors.centerIn: parent anchors.centerIn: parent
opacity: photo.status === Image.Loading height: parent.height * 0.9
width: height * 0.7
fillMode: Image.PreserveAspectCrop
mipmap: true
source: widgetData["photo"] === undefined ?
"":
widgetData["photo"].replace("https", "http")
asynchronous: true
FancyBusyIndicator {
height: width
anchors.centerIn: parent
opacity: photo.status === Image.Loading
}
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Item {
width: photo.width
height: photo.height
Rectangle {
anchors.centerIn: parent
width: photo.width
height: photo.height
radius: photo.width * 0.2
}
}
}
} }
} }
@ -99,7 +122,7 @@ Page {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
height: parent.height * 0.9 height: parent.height * 0.9
width: parent.width - photo.width width: parent.width - photoContainerItem.width * 1.1
Label { Label {
@ -214,7 +237,9 @@ Page {
wrapMode: Label.Wrap wrapMode: Label.Wrap
text: widgetData["freetext"] === undefined ? "":widgetData["freetext"] text: widgetData["freetext"] === undefined ?
"":
(widgetData["freetext"] + "<br>")
} }
@ -224,7 +249,7 @@ Page {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
height: 1 height: 1
width: parent.width * 0.9 width: parent.width
color: "black" color: "black"
@ -307,6 +332,7 @@ Page {
width: parent.width width: parent.width
height: 50 height: 50
spacing: 0
opacity: 0 opacity: 0
scale: 0.9 scale: 0.9
@ -324,11 +350,11 @@ Page {
Label { Label {
id: bestResultRankLa id: bestResultRankLa
width: parent.width * 0.2 width: parent.width * 0.1
height: parent.height height: parent.height
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignLeft
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
minimumPixelSize: 1 minimumPixelSize: 1
@ -341,11 +367,11 @@ Page {
Label { Label {
id: bestResultCompLa id: bestResultCompLa
width: parent.width * 0.6 width: parent.width * 0.7
height: parent.height height: parent.height
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignLeft
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
minimumPixelSize: height * 0.3 minimumPixelSize: height * 0.3
@ -370,7 +396,7 @@ Page {
scale: 0.8 scale: 0.8
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignRight
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
minimumPixelSize: 1 minimumPixelSize: 1

View file

@ -35,7 +35,7 @@ DataListView {
Connections { Connections {
target: selector target: selector
onSelectionFinished: { function onSelectionFinished(index, data) {
if(data.cat !== undefined){ if(data.cat !== undefined){
updateData({cat: data.cat}, true) updateData({cat: data.cat}, true)
} }
@ -64,12 +64,12 @@ DataListView {
delegate: ItemDelegate { delegate: ItemDelegate {
id: partDel id: partDel
property int ind: index property int thisIndex: index
property var thisData: widgetData[ "participants" ][index] property var thisData: widgetData[ "participants" ][index]
state: "closed" state: "closed"
width: parent.width width: control.width
height: 70 height: 70
opacity: 0 opacity: 0
@ -105,7 +105,7 @@ DataListView {
Connections { Connections {
target: control target: control
onCloseAll: { function onCloseAll() {
partDel.state = "closed" partDel.state = "closed"
} }
} }
@ -115,7 +115,7 @@ DataListView {
width: partDel.width width: partDel.width
color: partDel.ind % 2 == 0 ? "white":"lightgrey" color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
opacity: 0.2 opacity: 0.2
} }
@ -221,7 +221,7 @@ DataListView {
font.pixelSize: Math.abs( height * 0.6 ) font.pixelSize: Math.abs( height * 0.6 )
minimumPixelSize: 1 minimumPixelSize: 1
text: widgetData[ "participants" ][partDel.ind]["points"] === undefined ? "":"points: "+widgetData[ "participants" ][partDel.ind]["points"] text: widgetData[ "participants" ][partDel.thisIndex]["points"] === undefined ? "":"points: "+widgetData[ "participants" ][partDel.thisIndex]["points"]
} }
} }
} }
@ -333,7 +333,7 @@ DataListView {
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.widgetData["participants"][partDel.ind]["result" + prop.replace(" ", "")] !== undefined ) { if (obj.hasOwnProperty(prop) && control.widgetData["participants"][partDel.thisIndex]["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)
} }
@ -382,7 +382,7 @@ DataListView {
horizontalAlignment: Text.AlignLeft horizontalAlignment: Text.AlignLeft
minimumPixelSize: 1 minimumPixelSize: 1
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", " ") text: control.widgetData["participants"][partDel.thisIndex]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")] === undefined ? "":control.widgetData["participants"][partDel.thisIndex]["result"+detailResultRowRep.compResults[index][0].replace(" ", "")].replace("\n", " ")
} }
Behavior on height { Behavior on height {

View file

@ -31,13 +31,13 @@ DataListView {
property bool titleIsPageTitle: true property bool titleIsPageTitle: true
property Component headerComponent: ToolButton { property Component headerComponent: ToolButton {
id: moreToolBt id: moreToolBt
onClicked: { onClicked: {
control.changeCat() control.changeCat()
} }
icon.name: "menu" icon.name: "menu"
} }
property var widgetData: currentWidgetData property var widgetData: currentWidgetData
@ -111,7 +111,7 @@ DataListView {
Connections { Connections {
target: selector target: selector
onSelectionFinished: { function onSelectionFinished(index, data) {
if(data.cat !== undefined){ if(data.cat !== undefined){
updateData({cat: data.cat}, true) updateData({cat: data.cat}, true)
} }
@ -140,10 +140,11 @@ DataListView {
delegate: ItemDelegate { delegate: ItemDelegate {
id: partDel id: partDel
property int thisIndex: index
property var thisData: widgetData[ "athletes" ][index] property var thisData: widgetData[ "athletes" ][index]
width: parent.width width: parent.width
height: parseInt(thisData.cat) === parseInt(params.cat) ? undefined:0 height: parseInt(thisData.cat) === parseInt(params.cat) ? 50:0
opacity: 0 opacity: 0
scale: 0.9 scale: 0.9
@ -164,16 +165,24 @@ DataListView {
text: "" text: ""
Rectangle {
anchors.fill: parent
width: partDel.width
color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
opacity: 0.2
}
Label { Label {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: parent.width * 0.05 anchors.leftMargin: parent.width * 0.05
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
fontSizeMode: Text.Fit
font.bold: true font.bold: true
font.pixelSize: Math.abs( height * 0.35 ) font.pixelSize: Math.abs( height * 0.3 )
minimumPixelSize: height * 0.3
elide: "ElideRight" elide: "ElideRight"

View file

@ -21,9 +21,7 @@ import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import QtQuick.Controls.Material 2.3 import QtQuick.Controls.Material 2.3
//import QtLocation 5.13 import QtPurchasing 1.12
import QtPurchasing 1.12
import "../Components" import "../Components"
@ -46,9 +44,7 @@ DataListView {
ToolButton { ToolButton {
id: moreToolBt id: moreToolBt
onClicked: { onClicked: control.changeCat()
control.changeCat()
}
icon.name: "menu" icon.name: "menu"
} }
@ -56,11 +52,15 @@ DataListView {
ToolButton { ToolButton {
id: flowToolBt id: flowToolBt
visible: speedFlowChart.enabled visible: speedFlowChartPopup.enabled
enabled: control.widgetData['route_order'] === "-1" && Object.keys(control.widgetData['route_names']).length > 2 enabled: control.widgetData['route_order'] === "-1" && Object.keys(control.widgetData['route_names']).length > 2
onClicked: speedFlowChartBackgroundRect.toggle() onClicked: {
control.positionViewAtBeginning()
speedFlowChartPopup.toggle()
}
icon.name: "flowchart" icon.name: "flowchart"
} }
} }
@ -94,21 +94,21 @@ DataListView {
console.log("widget data changed") console.log("widget data changed")
if(control.widgetData['discipline'] === 'speed' && control.widgetData['route_order'] === "-1" && Object.keys(control.widgetData['route_names']).length > 2){ if(control.widgetData['discipline'] === 'speed' && control.widgetData['route_order'] === "-1" && Object.keys(control.widgetData['route_names']).length > 2){
speedFlowChart.flowchartData = ({}) speedFlowChartPopup.flowchartData = ({})
speedFlowChart.enabled = true speedFlowChartPopup.flowchartData = control.widgetData
speedFlowChart.flowchartData = control.widgetData speedFlowChartPopup.enabled = true
} }
else { else {
speedFlowChart.enabled = false speedFlowChartPopup.flowchartData = ({})
speedFlowChart.flowchartData = ({}) speedFlowChartPopup.enabled = false
} }
} }
function onBackRequested() { function onBackRequested() {
if(!speedFlowChartBackgroundRect.isVisible()) if(!speedFlowChartPopup.isVisible())
return true return true
speedFlowChartBackgroundRect.toggle() speedFlowChartPopup.toggle()
return false return false
} }
@ -168,484 +168,13 @@ DataListView {
} }
onContentYChanged: { onContentYChanged: {
if(contentY > 0 && speedFlowChartBackgroundRect.state === "visible"){ if(contentY > 0 && speedFlowChartPopup.state === "visible"){
control.positionViewAtBeginning() control.positionViewAtBeginning()
} }
} }
delegate: ItemDelegate { delegate: ResultDelegate {
id: partDel enabled: speedFlowChartPopup.state === "hidden"
property int ind: index
property var thisData: widgetData[ "participants" ][partDel.ind]
enabled: speedFlowChartBackgroundRect.state === "hidden"
width: control.width
height: 70
text: ""
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 }
}
Rectangle {
id: partDelBackgroundRect
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: 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: "<html>(<a href=\"" + (partDel.thisData["fed_url"] === undefined ? "":partDel.thisData["fed_url"]).toString() + "\">" + (widgetData[ "display_athlete" ] === "nation" ? partDel.thisData["nation"] : partDel.thisData["federation"]) + "</a>)</html>"
onLinkActivated: {
Qt.openUrlExternally(link)
}
}
}
Row {
id: partDelSecondRow
width: parent.width
height: multiResRow.active || multiGenResRow.active || resultLa.acitve ? parent.height / 2 : 0
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.ind]["boulder"+(index+1)]
var numTrys = widgetData[ "participants" ][partDel.ind]["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) {
// if there is a result available -> draw background
context.fillStyle = "#b7b7b7";
}
else {
context.fillStyle = "transparent";
}
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: boulderResTrysLa
anchors.centerIn: parent
height: parent.height / 2
width: parent.width / 2
visible: !boulderResZoneLa.visible
fontSizeMode: Text.Fit
font.pixelSize: height
minimumPixelSize: 1
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
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
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
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: "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
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.ind]["result"] === undefined ? "":widgetData[ "participants" ][partDel.ind]["result"]
}
}
}
} }
footer: ItemDelegate { footer: ItemDelegate {
@ -667,7 +196,7 @@ DataListView {
property var tabs: getTabs() property var tabs: getTabs()
property var tabIndexes: [] property var tabIndexes: []
enabled: speedFlowChartBackgroundRect.state === "hidden" enabled: speedFlowChartPopup.state === "hidden"
anchors { anchors {
left: parent.left left: parent.left
@ -747,209 +276,13 @@ DataListView {
} }
Rectangle { SpeedFlowChartPopup {
id: speedFlowChartBackgroundRect id: speedFlowChartPopup
state: "hidden"
anchors {
top: parent.top
bottom: parent.bottom
left: parent.right
}
width: parent.width
height: parent.height
color: Material.background
function toggle() {
if(speedFlowChartBackgroundRect.state === "hidden"){
speedFlowChartBackgroundRect.state = "visible"
control.positionViewAtBeginning()
}
else {
speedFlowChartBackgroundRect.state = "hidden"
}
}
function isVisible() {
return speedFlowChartBackgroundRect.state === "visible"
}
SpeedFlowChart {
id: speedFlowChart
anchors.fill: parent
enabled: false
flowchartData: ({})
onEnabledChanged: {
if(!enabled){
speedFlowChartBackgroundRect.state = 'hidden'
}
}
Rectangle {
id: speedFlowChartLockedOverlay
state: appSettings.read("speedBackendPurchase") === "1" ? "unlocked":"locked"
anchors.fill: parent
anchors.margins: -20
color: "white"
Connections {
target: speedFlowChartProduct
function onPurchaseRestored() {
speedFlowChartLockedOverlay.state = appSettings.read("speedBackendPurchase") === "1" ? "unlocked":"locked"
}
function onPurchaseSucceeded() {
speedFlowChartLockedOverlay.state = appSettings.read("speedBackendPurchase") === "1" ? "unlocked":"locked"
}
function onPurchaseFailed() {
purchaseBt.text = qsTr("Purchase failed")
purchaseBt.enabled = false
buttonTextResetTimer.start()
}
}
Timer {
id: buttonTextResetTimer
interval: 2000
running: false
repeat: false
onTriggered: {
purchaseBt.text = (speedFlowChartProduct.status === Product.Registered
? "Buy now for " + speedFlowChartProduct.price
: qsTr("this item is currently unavailable"))
purchaseBt.enabled = true
}
}
ColumnLayout {
id: lockedLayout
anchors {
fill: parent
topMargin: parent.height * 0.05
bottomMargin: parent.height * 0.1
rightMargin: parent.width * 0.1 + 20
leftMargin: parent.width * 0.1 + 20
}
//spacing: parent.height * 0.05
Image {
id: name
Layout.alignment: Layout.Center
Layout.preferredHeight: height
Layout.preferredWidth: width
width: lockedLayout.height * 0.1
height: width
mipmap: true
source: "qrc:/icons/lock.png"
}
Text {
Layout.fillWidth: true
height: parent.height * 0.05
text: qsTr("This is a premium feature.")
font.bold: true
font.pixelSize: parent.height * 0.05
fontSizeMode: Text.Fit
minimumPixelSize: 1
horizontalAlignment: Text.AlignHCenter
}
SwipeGallery {
Layout.fillHeight: true
Layout.fillWidth: true
images: ["qrc:/screenshots/SpeedFlowchartDemo/1.png","qrc:/screenshots/SpeedFlowchartDemo/2.png","qrc:/screenshots/SpeedFlowchartDemo/3.png"]
}
Button {
id: purchaseBt
Layout.alignment: Layout.Center
enabled: speedFlowChartProduct.status === Product.Registered
text: speedFlowChartProduct.status === Product.Registered
? "Buy now for " + speedFlowChartProduct.price
: qsTr("this item is currently unavailable")
icon.name: "buy"
//display: AbstractButton.TextBesideIcon
onClicked: speedFlowChartProduct.purchase()
}
}
states: [
State {
name: "unlocked"
PropertyChanges {
target: speedFlowChartLockedOverlay
visible: false
}
},
State {
name: "locked"
PropertyChanges {
target: speedFlowChartLockedOverlay
visible: true
}
}
]
}
}
states: [
State {
name: "hidden"
PropertyChanges {
target: speedFlowChartBackgroundRect
opacity: 0
anchors.leftMargin: 0
}
},
State {
name: "visible"
PropertyChanges {
target: speedFlowChartBackgroundRect
opacity: 1
anchors.leftMargin: -parent.width
}
}
]
transitions: [
Transition {
NumberAnimation {
properties: "opacity,scale,anchors.leftMargin"
duration: 200
easing.type: Easing.InOutQuad
}
}
]
} }
PullRefresher { PullRefresher {
// has to be placed here again,
// to be on top of the speed flowchart
target: control target: control
postRefreshDelay: 0 postRefreshDelay: 0
@ -962,4 +295,5 @@ DataListView {
} }
} }
} }

View file

@ -82,7 +82,7 @@ DataListView {
Connections { Connections {
target: selector target: selector
onSelectionFinished: { function onSelectionFinished(index, data) {
if(data.cat !== undefined){ if(data.cat !== undefined){
updateData({cat: data.cat}, true) updateData({cat: data.cat}, true)
} }
@ -113,9 +113,11 @@ DataListView {
delegate: ItemDelegate { delegate: ItemDelegate {
id: partDel id: partDel
property int thisIndex: index
property var thisData: widgetData[ "participants" ][index] property var thisData: widgetData[ "participants" ][index]
width: parent.width width: parent.width
height: 50
opacity: 0 opacity: 0
scale: 0.9 scale: 0.9
@ -136,6 +138,16 @@ DataListView {
text: "" text: ""
Rectangle {
anchors.fill: parent
width: partDel.width
color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
opacity: 0.2
}
Row { Row {
id: partDelFirstRow id: partDelFirstRow
@ -145,7 +157,7 @@ DataListView {
rightMargin: parent.width * 0.05 rightMargin: parent.width * 0.05
} }
spacing: width * 0.1 spacing: width * 0.05
Label { Label {
height: parent.height height: parent.height
@ -153,7 +165,7 @@ DataListView {
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
font.bold: true font.bold: true
font.pixelSize: Math.abs( height * 0.6 ) font.pixelSize: Math.abs( height * 0.4 )
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
@ -162,7 +174,7 @@ DataListView {
Label { Label {
height: parent.height height: parent.height
width: parent.width * 0.4 width: parent.width * 0.45
fontSizeMode: Text.Fit fontSizeMode: Text.Fit
font.bold: true font.bold: true
@ -178,10 +190,8 @@ DataListView {
height: parent.height height: parent.height
width: parent.width * 0.3 width: parent.width * 0.3
fontSizeMode: Text.Fit
font.bold: false font.bold: false
font.pixelSize: Math.abs( height * 0.4 ) font.pixelSize: height * 0.3
minimumPixelSize: height * 0.3
elide: "ElideRight" elide: "ElideRight"

View file

@ -20,6 +20,7 @@ import QtQuick 2.9
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Controls.Material 2.12
import QtPurchasing 1.12 import QtPurchasing 1.12
import com.itsblue.digitalRockRanking 1.0 import com.itsblue.digitalRockRanking 1.0
@ -39,7 +40,6 @@ Window {
property int errorCode: -1 property int errorCode: -1
// comp cats source: // comp cats source:
// - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/icc_calendar.php
// - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/dav_calendar.php // - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/dav_calendar.php
// - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/sac_calendar.php // - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/sac_calendar.php
@ -120,12 +120,15 @@ Window {
anchors.fill: parent anchors.fill: parent
//Material.theme: Material.Dark
Component.onCompleted: { Component.onCompleted: {
//loadingDl.open() //loadingDl.open()
//app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300 //app.openAthlete() // dorian: 53139 , rustam: 6933 , helen: 53300
//openWidget({nation:'GER'}) //openWidget({nation:'GER'})
//mainStack.push("Pages/AthleteSearchPage.qml") //mainStack.push("Pages/AthleteSearchPage.qml")
//openWidget({comp: 11651, cat: 25}) //openWidget({comp: 11651, cat: 26})
//openWidget({person: 6623})
} }
Shortcut { Shortcut {
@ -315,8 +318,10 @@ Window {
height: parent.height height: parent.height
onItemChanged: { onItemChanged: {
if(item === null) if(item === null) {
extraComponentLoader.Layout.preferredWidth = 0
return return
}
extraComponentLoader.item.width = extraComponentLoader.item.implicitWidth extraComponentLoader.item.width = extraComponentLoader.item.implicitWidth
extraComponentLoader.Layout.preferredWidth = extraComponentLoader.item.width extraComponentLoader.Layout.preferredWidth = extraComponentLoader.item.width

View file

@ -20,5 +20,10 @@
<file>Components/SpeedFlowChart.qml</file> <file>Components/SpeedFlowChart.qml</file>
<file>Components/SwipeGallery.qml</file> <file>Components/SwipeGallery.qml</file>
<file>Components/CompetitionCalendarDelegate.qml</file> <file>Components/CompetitionCalendarDelegate.qml</file>
<file>Components/SelectorPopup.qml</file>
<file>Components/ResultDelegate.qml</file>
<file>Components/SpeedFlowChartLocker.qml</file>
<file>Components/SpeedFlowChartPopup.qml</file>
<file>Components/BlueRockBadge.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -33,7 +33,6 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
qDebug() << QStyleFactory::keys();
QQuickStyle::setStyle("Material"); QQuickStyle::setStyle("Material");
QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << ":/resources/shared/icons"); QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << ":/resources/shared/icons");
QIcon::setThemeName("bluerock"); QIcon::setThemeName("bluerock");
@ -42,6 +41,13 @@ int main(int argc, char *argv[])
qmlRegisterType<AppSettings>("com.itsblue.digitalRockRanking", 1, 0, "AppSettings"); qmlRegisterType<AppSettings>("com.itsblue.digitalRockRanking", 1, 0, "AppSettings");
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
#ifdef QT_DEBUG
engine.rootContext()->setContextProperty("QT_DEBUG", true);
#else
engine.rootContext()->setContextProperty("QT_DEBUG", false);
#endif
engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty()) if (engine.rootObjects().isEmpty())
return -1; return -1;