Many small and big improvements, see change log for details
This commit is contained in:
parent
121589bf29
commit
f9f6dd7f5d
20 changed files with 1281 additions and 1191 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -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/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# [0.03.1] - UR
|
||||
# [0.05] - UR
|
||||
### Changed
|
||||
- the boulder result rect doesn't have a background if there is no result now
|
||||
- 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
|
||||
### 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
|
||||
|
||||
### 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
|
||||
### Fixed
|
||||
|
|
|
@ -50,9 +50,7 @@ DISTFILES += \
|
|||
android-sources/gradle/wrapper/gradle-wrapper.properties \
|
||||
android-sources/gradlew \
|
||||
android-sources/gradlew.bat \
|
||||
android-sources/res/values/libs.xml \
|
||||
resources/shared/icons/bluerock/index.theme \
|
||||
$$files(resources/shared/icons/*.png, true)
|
||||
android-sources/res/values/libs.xml
|
||||
|
||||
android {
|
||||
QT += androidextras
|
||||
|
|
32
resources/qml/Components/BlueRockBadge.qml
Normal file
32
resources/qml/Components/BlueRockBadge.qml
Normal 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"
|
||||
}
|
||||
}
|
|
@ -32,10 +32,10 @@ Item {
|
|||
property int postRefreshDelay: 1000 // delay after reload funcion has finished
|
||||
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 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 pullIndicatorColor: "black" // color for the pre-defined pull indicator
|
||||
|
|
484
resources/qml/Components/ResultDelegate.qml
Normal file
484
resources/qml/Components/ResultDelegate.qml
Normal 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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
139
resources/qml/Components/SelectorPopup.qml
Normal file
139
resources/qml/Components/SelectorPopup.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,32 +20,24 @@ import QtQuick 2.10
|
|||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Material 2.1
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
ListView {
|
||||
Item {
|
||||
id: control
|
||||
|
||||
property var flowchartData
|
||||
property var allFlowchartData
|
||||
property int rounds: 0
|
||||
property int tileSize: app.height / 8 * 0.8
|
||||
|
||||
property int refreshes: 0
|
||||
property int roundRefreshes: 1
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
|
||||
spacing: app.width * 0.1
|
||||
|
||||
orientation: ListView.LeftToRight
|
||||
boundsBehavior: ListView.StopAtBounds
|
||||
property int roundCount: 0
|
||||
|
||||
onFlowchartDataChanged: {
|
||||
prepareData()
|
||||
}
|
||||
|
||||
model: 0
|
||||
|
||||
function prepareData() {
|
||||
|
||||
if(!control.enabled || control.flowchartData === undefined || control.flowchartData['route_names'] === undefined)
|
||||
|
@ -223,189 +215,273 @@ ListView {
|
|||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
delegate: Column {
|
||||
id: roundCol
|
||||
ListView {
|
||||
id: roundListView
|
||||
|
||||
property int thisIndex: index
|
||||
property int thisRound: thisRoundIsValid ? control.allFlowchartData[roundCol.thisIndex][control.allFlowchartData[roundCol.thisIndex].length-2]:-1
|
||||
property bool thisRoundIsValid: control.allFlowchartData !== undefined && control.allFlowchartData[roundCol.thisIndex] !== undefined && control.allFlowchartData[roundCol.thisIndex].length > 2
|
||||
property bool thisIsLastRound: thisIndex === control.model - 1
|
||||
property int columnWidth: height * 0.3
|
||||
property int columnHeight: height
|
||||
|
||||
width: app.width * 0.5
|
||||
height: control.height
|
||||
|
||||
//spacing: app.width * 0.1
|
||||
|
||||
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] : "-"
|
||||
anchors {
|
||||
top: parent.top
|
||||
bottom: parent.bottom
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: rectRep
|
||||
model: Math.max( Math.pow(2, control.model-1) * Math.pow(0.5, (index)), 2)
|
||||
delegate: Item {
|
||||
id: matchItm
|
||||
width: Math.min((columnWidth + spacing) * model, control.width)
|
||||
|
||||
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
|
||||
property int thisRound: parseInt(roundCol.thisRound) - (thisIsSmallFinal ? 1:0)
|
||||
property var thisMatchData: thisMatchDataIsValid ? matchData:[]
|
||||
model: control.roundCount
|
||||
|
||||
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
|
||||
delegate: Item {
|
||||
id: roundItem
|
||||
|
||||
property bool thisIsFinal: roundCol.thisIsLastRound && thisIndex === rectRep.model - 2
|
||||
property bool thisIsSmallFinal: roundCol.thisIsLastRound && thisIndex === rectRep.model - 1
|
||||
property int thisIndex: index
|
||||
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 )
|
||||
width: parent.width
|
||||
property int tileSize: (roundItem.height / 8 - roundNameLa.height) * 1.45
|
||||
|
||||
onMatchDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
width: roundListView.columnWidth
|
||||
height: roundListView.columnHeight
|
||||
|
||||
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 }
|
||||
}
|
||||
Column {
|
||||
id: roundCol
|
||||
|
||||
Canvas {
|
||||
id: lineCanvas
|
||||
width: app.width; height: app.height
|
||||
contextType: "2d"
|
||||
anchors.fill: parent
|
||||
|
||||
visible: !roundCol.thisIsLastRound
|
||||
|
||||
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
|
||||
Label {
|
||||
id: roundNameLa
|
||||
width: parent.width
|
||||
height: control.tileSize
|
||||
//scale: 0.9
|
||||
color: "white"
|
||||
border.color: "lightgrey"
|
||||
border.width: 1
|
||||
radius: height * 0.2
|
||||
Material.elevation: 10
|
||||
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: roundItem.thisRoundIsValid
|
||||
&& control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] !== undefined ?
|
||||
control.allFlowchartData[roundItem.thisIndex][control.allFlowchartData[roundItem.thisIndex].length-1] :
|
||||
"-"
|
||||
}
|
||||
|
||||
Grid {
|
||||
columns: app.landscape() ? 2:0
|
||||
rows: app.landscape() ? 0:2
|
||||
Repeater {
|
||||
id: rectRep
|
||||
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
|
||||
anchors.margins: matchRect.radius * 0.5
|
||||
property var matchData: roundItem.thisRoundIsValid ?
|
||||
control.allFlowchartData[
|
||||
thisIsSmallFinal ?
|
||||
roundItem.thisIndex+1 :
|
||||
roundItem.thisIndex
|
||||
][ thisIsSmallFinal ? 0:matchItm.thisIndex]:
|
||||
undefined
|
||||
|
||||
Repeater {
|
||||
// for the two athletes
|
||||
model: 2
|
||||
property int thisIndex: index
|
||||
property int thisRound: parseInt(roundItem.thisRound) - (thisIsSmallFinal ? 1:0)
|
||||
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
|
||||
width: app.landscape() ? parent.width / 2 - parent.spacing : parent.width
|
||||
property bool thisIsFinal: roundItem.thisIsLastRound && thisIndex === rectRep.model - 2
|
||||
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 {
|
||||
Layout.preferredHeight: parent.height
|
||||
height: !roundItem.thisIsLastRound ?
|
||||
(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
|
||||
font.pixelSize: height * 0.7
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: 1
|
||||
onMatchDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
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 {
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
height: parent.height
|
||||
|
||||
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'] :"-"
|
||||
PathQuad {
|
||||
relativeX: roundListView.spacing * 0.5
|
||||
relativeY: matchItm.height * 0.25 * lineCanvas.targetYFactor
|
||||
relativeControlX: 0
|
||||
relativeControlY: relativeY
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
Layout.preferredHeight: parent.height
|
||||
onPaint: {
|
||||
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
|
||||
font.pixelSize: app.landscape() ? height * 0.35 : height * 0.5
|
||||
Rectangle {
|
||||
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 ?
|
||||
( parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]) ?
|
||||
(parseFloat(matchItm.thisMatchData[index]['result'+matchItm.thisRound]).toFixed(2))
|
||||
: matchItm.thisMatchData[index]['result'+matchItm.thisRound] )
|
||||
: "-"
|
||||
//anchors.verticalCenterOffset: matchItm.lowerPart ? 10:10
|
||||
width: parent.width
|
||||
height: roundItem.tileSize
|
||||
//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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
101
resources/qml/Components/SpeedFlowChartLocker.qml
Normal file
101
resources/qml/Components/SpeedFlowChartLocker.qml
Normal 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()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
116
resources/qml/Components/SpeedFlowChartPopup.qml
Normal file
116
resources/qml/Components/SpeedFlowChartPopup.qml
Normal 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
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -29,9 +29,8 @@ Page {
|
|||
|
||||
signal headerComponentChanged()
|
||||
|
||||
RowLayout {
|
||||
id: headerLayout
|
||||
|
||||
BlueRockBadge {
|
||||
id: headerBadge
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
top: parent.top
|
||||
|
@ -40,28 +39,6 @@ Page {
|
|||
|
||||
height: menuGr.buttonSize * 0.3
|
||||
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 {
|
||||
|
@ -125,7 +102,7 @@ Page {
|
|||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: headerLayout.anchors.topMargin
|
||||
bottomMargin: headerBadge.anchors.topMargin
|
||||
}
|
||||
|
||||
width: parent.width * 0.9
|
||||
|
@ -161,6 +138,10 @@ Page {
|
|||
|
||||
contentItem: Label {
|
||||
wrapMode: Text.Wrap
|
||||
|
||||
width: ifscDisclaimerDialog.width * 0.8
|
||||
height: implicitHeight
|
||||
|
||||
text:
|
||||
"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>" +
|
||||
|
|
|
@ -245,107 +245,16 @@ Page {
|
|||
|
||||
}
|
||||
|
||||
Dialog {
|
||||
SelectorPopup {
|
||||
id: selectorPu
|
||||
|
||||
property var dataObj
|
||||
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 {
|
||||
contentItem: ListView {
|
||||
id: selectorLv
|
||||
|
||||
property int delegateHeight: 50
|
||||
spacing: 10
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100
|
||||
implicitHeight: model === 0 ? 0:(delegateHeight + spacing) * model
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ DataListView {
|
|||
|
||||
if(endDate.getTime() < new Date().getTime()){
|
||||
// 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!")
|
||||
}
|
||||
}
|
||||
|
@ -400,114 +400,18 @@ DataListView {
|
|||
delegate: CompetitionCalendarDelegate {
|
||||
}
|
||||
|
||||
section.property: "month"
|
||||
section.delegate: ItemDelegate {
|
||||
id: name
|
||||
background: Rectangle {
|
||||
color: "red"
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
text: section
|
||||
}
|
||||
|
||||
Dialog {
|
||||
SelectorPopup {
|
||||
id: filterSelectPu
|
||||
|
||||
property var dataObj
|
||||
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 {
|
||||
contentItem: ListView {
|
||||
id: selectorLv
|
||||
|
||||
property int delegateHeight: 50
|
||||
spacing: 10
|
||||
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100
|
||||
implicitHeight: model === 0 ? 0:(delegateHeight + spacing) * model
|
||||
|
||||
model: filterSelectPu.dataObj !== undefined ? filterSelectPu.dataObj.length:0
|
||||
|
||||
|
@ -520,13 +424,12 @@ DataListView {
|
|||
leftMargin: 3
|
||||
bottom: selectorLv.bottom
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delegate: CheckDelegate {
|
||||
id: catBt
|
||||
|
||||
width: parent.width
|
||||
width: selectorLv.width
|
||||
height: text !== "" ? selectorLv.delegateHeight:0
|
||||
|
||||
//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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.3
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../Components"
|
||||
|
||||
|
@ -43,25 +44,11 @@ Page {
|
|||
id: mainSv
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
anchors.rightMargin: 14
|
||||
anchors.margins: 20
|
||||
|
||||
contentWidth: parent.width - anchors.leftMargin - anchors.rightMargin
|
||||
contentWidth: parent.width - anchors.margins * 2
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
|
||||
anchors {
|
||||
top: mainSv.top
|
||||
left: mainSv.right
|
||||
margins: 10
|
||||
leftMargin: 3
|
||||
bottom: mainSv.bottom
|
||||
}
|
||||
|
||||
width: 8
|
||||
|
||||
active: true
|
||||
}
|
||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||
|
||||
Column {
|
||||
id: mainCol
|
||||
|
@ -72,25 +59,61 @@ Page {
|
|||
height: control.height * 0.3
|
||||
width: parent.width
|
||||
|
||||
Image {
|
||||
id: photo
|
||||
|
||||
property bool ready: false
|
||||
spacing: photoContainerItem.width * 0.1
|
||||
|
||||
Item {
|
||||
id: photoContainerItem
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
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")
|
||||
asynchronous: true
|
||||
Image {
|
||||
id: photo
|
||||
|
||||
property bool ready: photo.status === Image.Ready
|
||||
|
||||
FancyBusyIndicator {
|
||||
height: width
|
||||
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
|
||||
|
||||
height: parent.height * 0.9
|
||||
width: parent.width - photo.width
|
||||
width: parent.width - photoContainerItem.width * 1.1
|
||||
|
||||
Label {
|
||||
|
||||
|
@ -214,7 +237,9 @@ Page {
|
|||
|
||||
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
|
||||
|
||||
height: 1
|
||||
width: parent.width * 0.9
|
||||
width: parent.width
|
||||
|
||||
color: "black"
|
||||
|
||||
|
@ -307,6 +332,7 @@ Page {
|
|||
|
||||
width: parent.width
|
||||
height: 50
|
||||
spacing: 0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
@ -324,11 +350,11 @@ Page {
|
|||
Label {
|
||||
id: bestResultRankLa
|
||||
|
||||
width: parent.width * 0.2
|
||||
width: parent.width * 0.1
|
||||
height: parent.height
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: 1
|
||||
|
@ -341,11 +367,11 @@ Page {
|
|||
Label {
|
||||
id: bestResultCompLa
|
||||
|
||||
width: parent.width * 0.6
|
||||
width: parent.width * 0.7
|
||||
height: parent.height
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: height * 0.3
|
||||
|
@ -370,7 +396,7 @@ Page {
|
|||
scale: 0.8
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
horizontalAlignment: Text.AlignRight
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: 1
|
||||
|
|
|
@ -35,7 +35,7 @@ DataListView {
|
|||
|
||||
Connections {
|
||||
target: selector
|
||||
onSelectionFinished: {
|
||||
function onSelectionFinished(index, data) {
|
||||
if(data.cat !== undefined){
|
||||
updateData({cat: data.cat}, true)
|
||||
}
|
||||
|
@ -64,12 +64,12 @@ DataListView {
|
|||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property int ind: index
|
||||
property int thisIndex: index
|
||||
property var thisData: widgetData[ "participants" ][index]
|
||||
|
||||
state: "closed"
|
||||
|
||||
width: parent.width
|
||||
width: control.width
|
||||
height: 70
|
||||
|
||||
opacity: 0
|
||||
|
@ -105,7 +105,7 @@ DataListView {
|
|||
|
||||
Connections {
|
||||
target: control
|
||||
onCloseAll: {
|
||||
function onCloseAll() {
|
||||
partDel.state = "closed"
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ DataListView {
|
|||
|
||||
width: partDel.width
|
||||
|
||||
color: partDel.ind % 2 == 0 ? "white":"lightgrey"
|
||||
color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
|
||||
|
||||
opacity: 0.2
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ DataListView {
|
|||
font.pixelSize: Math.abs( height * 0.6 )
|
||||
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) {
|
||||
// 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", " - ")])
|
||||
//console.log("found " + obj[prop] + " at index " + prop)
|
||||
}
|
||||
|
@ -382,7 +382,7 @@ DataListView {
|
|||
horizontalAlignment: Text.AlignLeft
|
||||
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 {
|
||||
|
|
|
@ -31,13 +31,13 @@ DataListView {
|
|||
property bool titleIsPageTitle: true
|
||||
|
||||
property Component headerComponent: ToolButton {
|
||||
id: moreToolBt
|
||||
id: moreToolBt
|
||||
|
||||
onClicked: {
|
||||
control.changeCat()
|
||||
}
|
||||
onClicked: {
|
||||
control.changeCat()
|
||||
}
|
||||
|
||||
icon.name: "menu"
|
||||
icon.name: "menu"
|
||||
}
|
||||
|
||||
property var widgetData: currentWidgetData
|
||||
|
@ -111,7 +111,7 @@ DataListView {
|
|||
|
||||
Connections {
|
||||
target: selector
|
||||
onSelectionFinished: {
|
||||
function onSelectionFinished(index, data) {
|
||||
if(data.cat !== undefined){
|
||||
updateData({cat: data.cat}, true)
|
||||
}
|
||||
|
@ -140,10 +140,11 @@ DataListView {
|
|||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property int thisIndex: index
|
||||
property var thisData: widgetData[ "athletes" ][index]
|
||||
|
||||
width: parent.width
|
||||
height: parseInt(thisData.cat) === parseInt(params.cat) ? undefined:0
|
||||
height: parseInt(thisData.cat) === parseInt(params.cat) ? 50:0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
@ -164,16 +165,24 @@ DataListView {
|
|||
|
||||
text: ""
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
width: partDel.width
|
||||
|
||||
color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
|
||||
|
||||
opacity: 0.2
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: parent.width * 0.05
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: true
|
||||
font.pixelSize: Math.abs( height * 0.35 )
|
||||
minimumPixelSize: height * 0.3
|
||||
font.pixelSize: Math.abs( height * 0.3 )
|
||||
|
||||
elide: "ElideRight"
|
||||
|
||||
|
|
|
@ -21,9 +21,7 @@ import QtQuick.Controls 2.4
|
|||
import QtQuick.Layouts 1.3
|
||||
import QtGraphicalEffects 1.0
|
||||
import QtQuick.Controls.Material 2.3
|
||||
//import QtLocation 5.13
|
||||
|
||||
import QtPurchasing 1.12
|
||||
import QtPurchasing 1.12
|
||||
|
||||
import "../Components"
|
||||
|
||||
|
@ -46,9 +44,7 @@ DataListView {
|
|||
ToolButton {
|
||||
id: moreToolBt
|
||||
|
||||
onClicked: {
|
||||
control.changeCat()
|
||||
}
|
||||
onClicked: control.changeCat()
|
||||
|
||||
icon.name: "menu"
|
||||
}
|
||||
|
@ -56,11 +52,15 @@ DataListView {
|
|||
ToolButton {
|
||||
id: flowToolBt
|
||||
|
||||
visible: speedFlowChart.enabled
|
||||
visible: speedFlowChartPopup.enabled
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
@ -94,21 +94,21 @@ DataListView {
|
|||
console.log("widget data changed")
|
||||
|
||||
if(control.widgetData['discipline'] === 'speed' && control.widgetData['route_order'] === "-1" && Object.keys(control.widgetData['route_names']).length > 2){
|
||||
speedFlowChart.flowchartData = ({})
|
||||
speedFlowChart.enabled = true
|
||||
speedFlowChart.flowchartData = control.widgetData
|
||||
speedFlowChartPopup.flowchartData = ({})
|
||||
speedFlowChartPopup.flowchartData = control.widgetData
|
||||
speedFlowChartPopup.enabled = true
|
||||
}
|
||||
else {
|
||||
speedFlowChart.enabled = false
|
||||
speedFlowChart.flowchartData = ({})
|
||||
speedFlowChartPopup.flowchartData = ({})
|
||||
speedFlowChartPopup.enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
function onBackRequested() {
|
||||
if(!speedFlowChartBackgroundRect.isVisible())
|
||||
if(!speedFlowChartPopup.isVisible())
|
||||
return true
|
||||
|
||||
speedFlowChartBackgroundRect.toggle()
|
||||
speedFlowChartPopup.toggle()
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -168,484 +168,13 @@ DataListView {
|
|||
}
|
||||
|
||||
onContentYChanged: {
|
||||
if(contentY > 0 && speedFlowChartBackgroundRect.state === "visible"){
|
||||
if(contentY > 0 && speedFlowChartPopup.state === "visible"){
|
||||
control.positionViewAtBeginning()
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate: ResultDelegate {
|
||||
enabled: speedFlowChartPopup.state === "hidden"
|
||||
}
|
||||
|
||||
footer: ItemDelegate {
|
||||
|
@ -667,7 +196,7 @@ DataListView {
|
|||
property var tabs: getTabs()
|
||||
property var tabIndexes: []
|
||||
|
||||
enabled: speedFlowChartBackgroundRect.state === "hidden"
|
||||
enabled: speedFlowChartPopup.state === "hidden"
|
||||
|
||||
anchors {
|
||||
left: parent.left
|
||||
|
@ -747,209 +276,13 @@ DataListView {
|
|||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: speedFlowChartBackgroundRect
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
]
|
||||
SpeedFlowChartPopup {
|
||||
id: speedFlowChartPopup
|
||||
}
|
||||
|
||||
PullRefresher {
|
||||
// has to be placed here again,
|
||||
// to be on top of the speed flowchart
|
||||
target: control
|
||||
|
||||
postRefreshDelay: 0
|
||||
|
@ -962,4 +295,5 @@ DataListView {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ DataListView {
|
|||
|
||||
Connections {
|
||||
target: selector
|
||||
onSelectionFinished: {
|
||||
function onSelectionFinished(index, data) {
|
||||
if(data.cat !== undefined){
|
||||
updateData({cat: data.cat}, true)
|
||||
}
|
||||
|
@ -113,9 +113,11 @@ DataListView {
|
|||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property int thisIndex: index
|
||||
property var thisData: widgetData[ "participants" ][index]
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
@ -136,6 +138,16 @@ DataListView {
|
|||
|
||||
text: ""
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
|
||||
width: partDel.width
|
||||
|
||||
color: partDel.thisIndex % 2 == 0 ? "white":"lightgrey"
|
||||
|
||||
opacity: 0.2
|
||||
}
|
||||
|
||||
Row {
|
||||
id: partDelFirstRow
|
||||
|
||||
|
@ -145,7 +157,7 @@ DataListView {
|
|||
rightMargin: parent.width * 0.05
|
||||
}
|
||||
|
||||
spacing: width * 0.1
|
||||
spacing: width * 0.05
|
||||
|
||||
Label {
|
||||
height: parent.height
|
||||
|
@ -153,7 +165,7 @@ DataListView {
|
|||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: true
|
||||
font.pixelSize: Math.abs( height * 0.6 )
|
||||
font.pixelSize: Math.abs( height * 0.4 )
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
|
@ -162,7 +174,7 @@ DataListView {
|
|||
|
||||
Label {
|
||||
height: parent.height
|
||||
width: parent.width * 0.4
|
||||
width: parent.width * 0.45
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: true
|
||||
|
@ -178,10 +190,8 @@ DataListView {
|
|||
height: parent.height
|
||||
width: parent.width * 0.3
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: false
|
||||
font.pixelSize: Math.abs( height * 0.4 )
|
||||
minimumPixelSize: height * 0.3
|
||||
font.pixelSize: height * 0.3
|
||||
|
||||
elide: "ElideRight"
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import QtQuick 2.9
|
|||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls.Material 2.12
|
||||
import QtPurchasing 1.12
|
||||
|
||||
import com.itsblue.digitalRockRanking 1.0
|
||||
|
@ -39,7 +40,6 @@ Window {
|
|||
property int errorCode: -1
|
||||
|
||||
// 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/sac_calendar.php
|
||||
|
||||
|
@ -120,12 +120,15 @@ Window {
|
|||
|
||||
anchors.fill: parent
|
||||
|
||||
//Material.theme: Material.Dark
|
||||
|
||||
Component.onCompleted: {
|
||||
//loadingDl.open()
|
||||
//app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300
|
||||
//app.openAthlete() // dorian: 53139 , rustam: 6933 , helen: 53300
|
||||
//openWidget({nation:'GER'})
|
||||
//mainStack.push("Pages/AthleteSearchPage.qml")
|
||||
//openWidget({comp: 11651, cat: 25})
|
||||
//openWidget({comp: 11651, cat: 26})
|
||||
//openWidget({person: 6623})
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
|
@ -315,8 +318,10 @@ Window {
|
|||
height: parent.height
|
||||
|
||||
onItemChanged: {
|
||||
if(item === null)
|
||||
if(item === null) {
|
||||
extraComponentLoader.Layout.preferredWidth = 0
|
||||
return
|
||||
}
|
||||
|
||||
extraComponentLoader.item.width = extraComponentLoader.item.implicitWidth
|
||||
extraComponentLoader.Layout.preferredWidth = extraComponentLoader.item.width
|
||||
|
|
|
@ -20,5 +20,10 @@
|
|||
<file>Components/SpeedFlowChart.qml</file>
|
||||
<file>Components/SwipeGallery.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>
|
||||
</RCC>
|
||||
|
|
|
@ -33,7 +33,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
qDebug() << QStyleFactory::keys();
|
||||
QQuickStyle::setStyle("Material");
|
||||
QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << ":/resources/shared/icons");
|
||||
QIcon::setThemeName("bluerock");
|
||||
|
@ -42,6 +41,13 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterType<AppSettings>("com.itsblue.digitalRockRanking", 1, 0, "AppSettings");
|
||||
|
||||
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")));
|
||||
if (engine.rootObjects().isEmpty())
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue