started to move the internal structure to widgets to make everything more modular
This commit is contained in:
parent
4567e0b568
commit
f2ce94f474
21 changed files with 1535 additions and 26 deletions
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<manifest package="com.itsblue.blueROCKtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.01b" android:versionCode="1" android:installLocation="auto">
|
||||
<manifest package="com.itsblue.blueROCKtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.01.1b" android:versionCode="2" android:installLocation="auto">
|
||||
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="blueROCK" android:icon="@drawable/icon">
|
||||
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="blueROCK (for digitalROCK)" android:screenOrientation="unspecified" android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
|
|
|
@ -41,6 +41,7 @@ public slots:
|
|||
QVariant getCalendar(QString nation, int year);
|
||||
QVariant getRanking(int competitionId, int categoryId, bool registrationData = false, bool rankingData = false, const int routeNumber = -2);
|
||||
QVariant getAthlete(int perId);
|
||||
QVariant getWidgetData(QVariantMap params);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -26,14 +26,13 @@ DataListView {
|
|||
|
||||
model: listData[ root.listKey ] === undefined ? 0:listData[ root.listKey ].length
|
||||
|
||||
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property var thisData: listData[ "athletes" ][index]
|
||||
|
||||
width: parent.width
|
||||
height: parseInt(thisData.cat) === root.catId ? undefined:0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
|
|
@ -209,6 +209,8 @@ Page {
|
|||
Label {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
visible: bestResultsRep.model > 0
|
||||
|
||||
width: parent.width
|
||||
|
||||
wrapMode: Label.Wrap
|
||||
|
@ -229,12 +231,34 @@ Page {
|
|||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: toggleAllResultsBt
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
visible: bestResultsRep.model > 0
|
||||
|
||||
flat: true
|
||||
|
||||
text: bestResultsRep.showAllResults ? qsTr("show best results"):qsTr("show all results")
|
||||
|
||||
onClicked: {
|
||||
bestResultsRep.showAllResults = !bestResultsRep.showAllResults
|
||||
}
|
||||
|
||||
Behavior on text {
|
||||
FadeAnimation {
|
||||
target: toggleAllResultsBt
|
||||
fadeDuration: 150
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: bestResultsRep
|
||||
|
||||
property var bestResults: getBestResults()
|
||||
property var bestResults: showAllResults ? getAllResults() : getBestResults()
|
||||
property bool showAllResults: false
|
||||
|
||||
function getBestResults(){
|
||||
|
||||
|
@ -260,16 +284,44 @@ Page {
|
|||
return bestResults
|
||||
}
|
||||
|
||||
function getAllResults() {
|
||||
var allResults = root.perData["results"]
|
||||
|
||||
allResults.sort(function(a, b) {
|
||||
// sort results by date
|
||||
var aTs = Date.fromLocaleString(Qt.locale(), a["date"], "yyyy-MM-dd").getTime()
|
||||
var bTs = Date.fromLocaleString(Qt.locale(), b["date"], "yyyy-MM-dd").getTime()
|
||||
return bTs - aTs;
|
||||
});
|
||||
|
||||
return allResults
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
|
||||
model: bestResults.length > 12 ? 12:bestResults.length
|
||||
model: bestResults.length
|
||||
|
||||
delegate: Row {
|
||||
id: bestResultRow
|
||||
|
||||
property var thisData: bestResultsRep.bestResults[index]
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: fadeInPa
|
||||
NumberAnimation { target: bestResultRow; property: "opacity"; from: 0; to: 1.0; duration: 400 }
|
||||
NumberAnimation { target: bestResultRow; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
|
||||
}
|
||||
|
||||
Label {
|
||||
id: bestResultRankLa
|
||||
|
||||
|
|
|
@ -298,6 +298,14 @@ Page {
|
|||
|
||||
text: name
|
||||
}
|
||||
/*
|
||||
Label {
|
||||
id: infola
|
||||
|
||||
width: parent.width
|
||||
|
||||
text: calendarList.listData[index].info
|
||||
}*/
|
||||
|
||||
Label {
|
||||
id: dateLa
|
||||
|
@ -323,6 +331,7 @@ Page {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Dialog {
|
||||
|
@ -347,13 +356,21 @@ Page {
|
|||
catSelectPu.cupCat = cupCat
|
||||
catSelectPu.index = index
|
||||
|
||||
var tmpCatObj
|
||||
|
||||
if(cupCat){
|
||||
catSelectPu.catObj = root.calendarData["cups"][index]["cats"]
|
||||
tmpCatObj = root.calendarData["cups"][index]["cats"]
|
||||
}
|
||||
else {
|
||||
catSelectPu.catObj = calendarList.listData[index]["cats"]
|
||||
tmpCatObj = calendarList.listData[index]["cats"]
|
||||
}
|
||||
|
||||
tmpCatObj.sort(function(a, b) {
|
||||
return parseInt(a["GrpId"]) - parseInt(b["GrpId"]);
|
||||
});
|
||||
|
||||
catSelectPu.catObj = tmpCatObj
|
||||
|
||||
catSelectPu.open()
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,52 @@ Page {
|
|||
property string subTitle: getSubtitle()
|
||||
property bool titleIsPageTitle: true
|
||||
|
||||
property Component headerComponent: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
|
||||
Button {
|
||||
id: cupToolBt
|
||||
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: parent.width * 0.1
|
||||
}
|
||||
|
||||
height: parent.height * 0.5
|
||||
width: height
|
||||
|
||||
onClicked: {
|
||||
catSelectPu.appear()
|
||||
}
|
||||
|
||||
onPressed: cupToolBt.scale = 0.9
|
||||
onReleased: cupToolBt.scale = 1.0
|
||||
|
||||
background: Image {
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
source: "qrc:/icons/more_black.png"
|
||||
|
||||
height: parent.height > parent.width ? parent.width : parent.height
|
||||
width: height
|
||||
|
||||
mipmap: true
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
property bool ready
|
||||
property int status: -1
|
||||
|
||||
|
@ -44,6 +90,14 @@ Page {
|
|||
property bool res: catStatus === 0 || catStatus === 1 // result data
|
||||
property bool stl: catStatus === 2 || catStatus === 3 // startlist data
|
||||
|
||||
/*
|
||||
enum DataType {
|
||||
RankingData,
|
||||
RegistrationData,
|
||||
ResultData,
|
||||
StartlistData
|
||||
}*/
|
||||
|
||||
property var rankingData
|
||||
|
||||
property string listKey: root.reg ? "athletes":"participants"
|
||||
|
@ -57,7 +111,9 @@ Page {
|
|||
|
||||
function loadData(comp, cat, reg, rak, route){
|
||||
root.status = 905
|
||||
|
||||
console.log("[info][QML] getting ranking data of comp: " + comp + " , cat: " + cat + " and status: " + root.catStatus)
|
||||
|
||||
if(route === -1){
|
||||
route = -2
|
||||
}
|
||||
|
@ -65,12 +121,13 @@ Page {
|
|||
var ret = serverConn.getRanking(comp, cat, reg, rak, route)
|
||||
|
||||
root.status = ret["status"]
|
||||
console.log(root.status)
|
||||
|
||||
if(parseInt(ret["status"]) === 200){
|
||||
// request was successfull -> prepare data
|
||||
if(root.reg){
|
||||
// if the data is registration data, athletes of other cats need to be removed
|
||||
|
||||
/*
|
||||
var validAthletes = []
|
||||
|
||||
for(var i = 0; i < ret["data"]["athletes"].length; i++){
|
||||
|
@ -79,7 +136,7 @@ Page {
|
|||
validAthletes.push(ret["data"]["athletes"][i])
|
||||
}
|
||||
}
|
||||
ret["data"]["athletes"] = validAthletes
|
||||
ret["data"]["athletes"] = validAthletes*/
|
||||
|
||||
root.rankingData = ret["data"]
|
||||
}
|
||||
|
@ -349,4 +406,109 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: catSelectPu
|
||||
|
||||
property var catObj: undefined
|
||||
|
||||
x: 0 //root.width / 2 - width / 2
|
||||
y: root.height - height //root.height / 2 - height / 2
|
||||
|
||||
width: root.width
|
||||
height: catsLv.implicitHeight
|
||||
|
||||
modal: true
|
||||
focus: true
|
||||
|
||||
title: qsTr("select category")
|
||||
|
||||
function appear() {
|
||||
|
||||
var tmpCatObj
|
||||
|
||||
|
||||
tmpCatObj = root.rankingData["categorys"]
|
||||
|
||||
|
||||
tmpCatObj.sort(function(a, b) {
|
||||
return parseInt(a["GrpId"]) - parseInt(b["GrpId"]);
|
||||
});
|
||||
|
||||
catSelectPu.catObj = tmpCatObj
|
||||
|
||||
catSelectPu.open()
|
||||
|
||||
}
|
||||
|
||||
function getText(index){
|
||||
// ----------------------------
|
||||
// get the text
|
||||
// returns list with [catId, catName]
|
||||
return [catSelectPu.catObj[index]["GrpId"], catSelectPu.catObj[index]["name"]]
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: catsLv
|
||||
|
||||
property int delegateHeight: 50
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75
|
||||
|
||||
model: catSelectPu.catObj !== undefined ? catSelectPu.catObj.length:0
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator {
|
||||
parent: catsLv.parent
|
||||
anchors {
|
||||
top: catsLv.top
|
||||
left: catsLv.right
|
||||
margins: 10
|
||||
leftMargin: 3
|
||||
bottom: catsLv.bottom
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delegate: Button {
|
||||
id: catBt
|
||||
|
||||
property var catData: catSelectPu.getText(index)
|
||||
|
||||
width: parent.width
|
||||
height: text !== "" ? catsLv.delegateHeight:0
|
||||
|
||||
flat: true
|
||||
|
||||
text: catData[1]
|
||||
|
||||
onClicked: {
|
||||
catSelectPu.close()
|
||||
root.catId = catData[0]
|
||||
root.loadData(root.comId, root.catId, root.reg, root.rak, root.routeNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enter: Transition {
|
||||
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 }
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
from: root.height - catSelectPu.height * 0.7
|
||||
to: root.height - catSelectPu.height
|
||||
}
|
||||
}
|
||||
|
||||
exit: Transition {
|
||||
NumberAnimation { property: "opacity"; from: 1.0; to: 0.0 }
|
||||
NumberAnimation {
|
||||
property: "y"
|
||||
from: root.height - catSelectPu.height
|
||||
to: root.height - catSelectPu.height * 0.7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,20 @@ Page {
|
|||
id: root
|
||||
|
||||
title: "start"
|
||||
property Component headerComponent: null
|
||||
|
||||
Label {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
top: parent.top
|
||||
topMargin: root.height * 0.03
|
||||
}
|
||||
|
||||
font.pixelSize: anchors.topMargin
|
||||
font.bold: true
|
||||
|
||||
text: "blueROCK"
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: menuGr
|
||||
|
@ -34,7 +48,7 @@ Page {
|
|||
rows: app.landscape() ? 1:3
|
||||
columns: app.landscape() ? 3:1
|
||||
|
||||
spacing: app.landscape() ? parent.height * 0.1:parent.width * 0.1
|
||||
spacing: !app.landscape() ? parent.height * 0.08:parent.width * 0.1
|
||||
|
||||
property int buttonSize: app.landscape() ? parent.width * 0.2:parent.height * 0.2
|
||||
|
||||
|
@ -82,4 +96,24 @@ Page {
|
|||
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: root.height * 0.03
|
||||
}
|
||||
|
||||
width: parent.width * 0.9
|
||||
height: anchors.bottomMargin
|
||||
|
||||
wrapMode: "Wrap"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: "Resultservice and rankings provided by <a href='http://www.digitalROCK.de'>digital ROCK</a>, (c) 1990-2019 by Ralf Becker."
|
||||
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
266
resources/qml/Pages/WidgetPage.qml
Normal file
266
resources/qml/Pages/WidgetPage.qml
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
blueROCK - for digital rock
|
||||
Copyright (C) 2019 Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import "../Components"
|
||||
|
||||
Page {
|
||||
id: root
|
||||
|
||||
enum WidgetType {
|
||||
Competitions,
|
||||
|
||||
Profile,
|
||||
|
||||
Registration,
|
||||
Startlist,
|
||||
Result,
|
||||
|
||||
Ranking,
|
||||
Aggregated // not yet implemented
|
||||
}
|
||||
|
||||
title: widgetLd.item === null ? "":widgetLd.item.title
|
||||
property Component headerComponent: widgetLd.item === null ? null:widgetLd.item.headerComponent
|
||||
|
||||
property var params
|
||||
|
||||
property int status: -1
|
||||
property bool ready: false
|
||||
|
||||
property var widgetData
|
||||
|
||||
property int widgetType
|
||||
|
||||
Component.onCompleted: {
|
||||
loadData(params)
|
||||
}
|
||||
|
||||
function loadData(params) {
|
||||
// params is an object and can contain: {
|
||||
// comp: competitionId,
|
||||
// person: personId,
|
||||
// cat: categoryId,
|
||||
// nation: nationString ('', 'GER', 'SUI')
|
||||
// type: ('','starters', 'nat_team_ranking', 'sektionenwertung', 'regionalzentren'),
|
||||
//}
|
||||
|
||||
var ret = serverConn.getWidgetData(params)
|
||||
|
||||
if(ret["status"] === 200){
|
||||
root.widgetData = ret["data"]
|
||||
root.widgetType = checkWidgetType(params, root.widgetData)
|
||||
console.log(widgetType)
|
||||
widgetLd.load()
|
||||
root.ready = true
|
||||
}
|
||||
|
||||
root.status = ret["status"]
|
||||
|
||||
}
|
||||
|
||||
function updateData(params, openLoadingDl) {
|
||||
if(openLoadingDl)
|
||||
loadingDl.open()
|
||||
|
||||
|
||||
for(var prop in params){
|
||||
if(params.hasOwnProperty(prop)){
|
||||
root.params[prop] = params[prop]
|
||||
}
|
||||
}
|
||||
|
||||
loadData(root.params)
|
||||
|
||||
if(openLoadingDl)
|
||||
loadingDl.close()
|
||||
|
||||
}
|
||||
|
||||
function checkWidgetType(params, widgetData){
|
||||
|
||||
var widgetType
|
||||
|
||||
function hasParam(object, key, value){
|
||||
if(object[key] !== undefined){
|
||||
if(value !== undefined){
|
||||
return object[key] === value
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// check the type of the requested widget
|
||||
|
||||
if(hasParam(params, 'perId')){
|
||||
// person profile
|
||||
widgetType = WidgetPage.WidgetType.Profile
|
||||
}
|
||||
|
||||
else if(hasParam(params, 'nation')){
|
||||
// competition calendar
|
||||
widgetType = WidgetPage.WidgetType.Competitions
|
||||
}
|
||||
|
||||
else if(hasParam(params, 'comp') && hasParam(params, 'type', 'starters')){
|
||||
// registration
|
||||
widgetType = WidgetPage.WidgetType.Registration
|
||||
}
|
||||
else if(hasParam(params, 'type', 'startlist') || (widgetData.participants !== undefined && widgetData.participants[0] && !widgetData.participants[0].result_rank && widgetData.discipline !== 'ranking')){
|
||||
// startlist
|
||||
widgetType = WidgetPage.WidgetType.Startlist
|
||||
}
|
||||
else if(hasParam(params, 'comp') && hasParam(params, 'cat')){
|
||||
// results
|
||||
widgetType = WidgetPage.WidgetType.Result
|
||||
}
|
||||
|
||||
else if( hasParam(params, 'cat') && hasParam(params, 'cup') && !hasParam(params, 'comp')){
|
||||
// ranking data
|
||||
widgetType = WidgetPage.WidgetType.Ranking
|
||||
}
|
||||
else if(hasParam(params, 'type', 'nat_team_ranking') || hasParam(params, 'type', 'sektionenwertung') || hasParam(params, 'type', 'regionalzentren')){
|
||||
// aggregated
|
||||
widgetType = WidgetPage.WidgetType.Aggregated
|
||||
}
|
||||
|
||||
return widgetType
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: widgetLd
|
||||
|
||||
property alias selector: selectorPu
|
||||
property var updateData: root.updateData
|
||||
property alias params: root.params
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
source: ""
|
||||
|
||||
function load() {
|
||||
widgetLd.source = getFile(root.widgetType)
|
||||
widgetLd.item.widgetData = root.widgetData
|
||||
}
|
||||
|
||||
function getFile(widgetType) {
|
||||
var path = "qrc:/Widgets/"
|
||||
switch(widgetType){
|
||||
case WidgetPage.WidgetType.Competitions:
|
||||
path += "CalendarWidget"
|
||||
break
|
||||
case WidgetPage.WidgetType.Profile:
|
||||
path += "ProfileWidget"
|
||||
break
|
||||
case WidgetPage.WidgetType.Registration:
|
||||
path += "RegistrationWidget"
|
||||
break
|
||||
}
|
||||
|
||||
path += ".qml"
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
Dialog {
|
||||
id: selectorPu
|
||||
|
||||
property var dataObj
|
||||
|
||||
signal selectionFinished(int index, var data)
|
||||
|
||||
x: 0 //root.width / 2 - width / 2
|
||||
y: root.height - height //root.height / 2 - height / 2
|
||||
|
||||
width: root.width
|
||||
height: selectorLv.implicitHeight
|
||||
|
||||
modal: true
|
||||
focus: true
|
||||
|
||||
title: qsTr("select category")
|
||||
|
||||
function appear(dataObj) {
|
||||
selectorPu.dataObj = dataObj
|
||||
selectorPu.open()
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: selectorLv
|
||||
|
||||
property int delegateHeight: 50
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75
|
||||
|
||||
model: selectorPu.dataObj !== undefined ? selectorPu.dataObj.length:0
|
||||
|
||||
ScrollIndicator.vertical: ScrollIndicator {
|
||||
parent: selectorLv.parent
|
||||
anchors {
|
||||
top: selectorLv.top
|
||||
left: selectorLv.right
|
||||
margins: 10
|
||||
leftMargin: 3
|
||||
bottom: selectorLv.bottom
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delegate: Button {
|
||||
id: catBt
|
||||
|
||||
width: parent.width
|
||||
height: text !== "" ? selectorLv.delegateHeight:0
|
||||
|
||||
flat: true
|
||||
|
||||
text: selectorPu.dataObj[index].text
|
||||
|
||||
onClicked: {
|
||||
selectorPu.close()
|
||||
selectorPu.selectionFinished(index, selectorPu.dataObj[index].data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
340
resources/qml/Widgets/CalendarWidget.qml
Normal file
340
resources/qml/Widgets/CalendarWidget.qml
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
blueROCK - for digital rock
|
||||
Copyright (C) 2019 Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
|
||||
import "../Components"
|
||||
|
||||
DataListView {
|
||||
id: control
|
||||
|
||||
property string title: (params.nation === "" ? "IFSC":params.nation === "GER" ? "DAV":"SAC") + " " + qsTr("competition calendar")
|
||||
property Component headerComponent: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 5
|
||||
|
||||
spacing: width * 0.05
|
||||
|
||||
Label {
|
||||
id: yearLa
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
width: parent.width * 0.4
|
||||
height: parent.height * 0.6
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.pixelSize: height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
minimumPixelSize: 1
|
||||
|
||||
text: control.year
|
||||
|
||||
Behavior on text {
|
||||
FadeAnimation {
|
||||
target: yearLa
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id:yearToolBt
|
||||
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
height: parent.height * 0.5
|
||||
width: parent.width * 0.25
|
||||
|
||||
onClicked: {
|
||||
control.changeYear()
|
||||
}
|
||||
|
||||
onPressed: yearToolBt.scale = 0.9
|
||||
onReleased: yearToolBt.scale = 1.0
|
||||
|
||||
background: Image {
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
source: "qrc:/icons/calendar.png"
|
||||
|
||||
height: parent.height > parent.width ? parent.width : parent.height
|
||||
width: height
|
||||
|
||||
mipmap: true
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: cupToolBt
|
||||
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
height: parent.height * 0.5
|
||||
width: parent.width * 0.25
|
||||
|
||||
onClicked: {
|
||||
cupSelectPu.open()
|
||||
}
|
||||
|
||||
onPressed: cupToolBt.scale = 0.9
|
||||
onReleased: cupToolBt.scale = 1.0
|
||||
|
||||
background: Image {
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
source: "qrc:/icons/cup.png"
|
||||
|
||||
height: parent.height > parent.width ? parent.width : parent.height
|
||||
width: height
|
||||
|
||||
mipmap: true
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
property var widgetData
|
||||
|
||||
property int year: new Date().getFullYear()
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
//boundsBehavior: Flickable.StopAtBounds
|
||||
|
||||
model: widgetData["competitions"].length
|
||||
|
||||
status: root.status
|
||||
|
||||
onRefresh: {
|
||||
updateData({}, false)
|
||||
}
|
||||
|
||||
onModelChanged: {
|
||||
autoScroll()
|
||||
}
|
||||
|
||||
function autoScroll() {
|
||||
|
||||
var compList = control.widgetData["competitions"]
|
||||
|
||||
if(parseInt(control.year) === new Date().getFullYear()){
|
||||
for(var i = 0; i < compList.length; i ++){
|
||||
// get the start date pf the competition
|
||||
var startDate = Date.fromLocaleString(Qt.locale(), compList[i]["date"], "yyyy-MM-dd")
|
||||
|
||||
// get the duration of the competition
|
||||
var durationString = compList[i]["duration"] === undefined ? "1":compList[i]["duration"]
|
||||
var days = parseInt(durationString.replace(/\D/g,''))
|
||||
// calculate the end date of the competition
|
||||
var endDate = new Date(startDate.valueOf())
|
||||
endDate.setDate(endDate.getDate() + days);
|
||||
|
||||
//console.log(compList[i]["date"] + ": " + startDate + " to " + endDate)
|
||||
|
||||
if(endDate.getTime() < new Date().getTime()){
|
||||
// end date is already over -> move the list view down!
|
||||
control.positionViewAtIndex(i, ListView.Top)
|
||||
//console.log("moving down!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCompCatData(compCatId) {
|
||||
var obj = app.compCats
|
||||
|
||||
for(var prop in obj) {
|
||||
// go through the whole array and search for data keys
|
||||
if (obj.hasOwnProperty(prop) && obj[prop]["cat_id"].indexOf(compCatId) >= 0) {
|
||||
//console.log("found cat: " + obj[prop]['label'])
|
||||
return obj[prop]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openComp(compIndex){
|
||||
var cats = control.widgetData["competitions"][compIndex]["cats"]
|
||||
|
||||
cats.sort(function(a, b) {
|
||||
return parseInt(a["GrpId"]) - parseInt(b["GrpId"]);
|
||||
});
|
||||
|
||||
var selectOptions = []
|
||||
|
||||
for(var prop in cats){
|
||||
if (cats.hasOwnProperty(prop)) {
|
||||
selectOptions.push({text: cats[prop]["name"], data:{cat: cats[prop]["GrpId"], comp: control.widgetData["competitions"][compIndex]["WetId"], status:cats[prop]["status"]}})
|
||||
}
|
||||
}
|
||||
|
||||
selector.appear(selectOptions)
|
||||
}
|
||||
|
||||
function changeYear(){
|
||||
var years = control.widgetData["years"]
|
||||
|
||||
var selectOptions = []
|
||||
|
||||
for(var prop in years){
|
||||
if (years.hasOwnProperty(prop)) {
|
||||
selectOptions.push({text: years[prop], data:{year: years[prop]}})
|
||||
}
|
||||
}
|
||||
|
||||
selector.appear(selectOptions)
|
||||
}
|
||||
|
||||
|
||||
|
||||
Connections {
|
||||
target: selector
|
||||
onSelectionFinished: {
|
||||
if(data.comp !== undefined){
|
||||
console.log(data.status)
|
||||
app.openWidget({comp: data.comp, cat: data.cat, type:data.status === 4 ? 'starters':''})
|
||||
}
|
||||
else if(data.year !== undefined){
|
||||
updateData({year: data.year}, true)
|
||||
control.year = data.year
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: competitionDel
|
||||
|
||||
property bool over
|
||||
property var thisData: control.widgetData["competitions"][index]
|
||||
|
||||
property string name: thisData["name"]
|
||||
property string date: thisData["date_span"]
|
||||
property var cats: thisData["cats"]
|
||||
property int catId: thisData["cat_id"] === undefined ? 0:thisData["cat_id"]
|
||||
|
||||
width: parent.width
|
||||
height: compDelCol.height + 10
|
||||
|
||||
enabled: thisData["cats"] !== undefined && thisData["cats"].length > 0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
control.openComp(index)
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: fadeInPa
|
||||
NumberAnimation { target: competitionDel; property: "opacity"; from: 0; to: 1.0; duration: 400 }
|
||||
NumberAnimation { target: competitionDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: delBackroundRect
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
opacity: 0.5
|
||||
|
||||
color: control.getCompCatData(catId) === undefined ? "white":control.getCompCatData(catId)["bgcolor"]
|
||||
}
|
||||
|
||||
Column {
|
||||
id: compDelCol
|
||||
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: parent.width * 0.97
|
||||
|
||||
spacing: 10
|
||||
|
||||
Label {
|
||||
id: nameLa
|
||||
|
||||
width: parent.width
|
||||
|
||||
font.bold: true
|
||||
|
||||
wrapMode: Text.WordWrap
|
||||
|
||||
text: name
|
||||
}
|
||||
/*
|
||||
Label {
|
||||
id: infola
|
||||
|
||||
width: parent.width
|
||||
|
||||
text: thisData.info
|
||||
}*/
|
||||
|
||||
Label {
|
||||
id: dateLa
|
||||
|
||||
color: "grey"
|
||||
|
||||
text: date
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: bottomLineRa
|
||||
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
height: 1
|
||||
|
||||
color: "lightgrey"
|
||||
|
||||
}
|
||||
}
|
||||
}
|
388
resources/qml/Widgets/ProfileWidget.qml
Normal file
388
resources/qml/Widgets/ProfileWidget.qml
Normal file
|
@ -0,0 +1,388 @@
|
|||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
import QtQuick.Controls.Material 2.3
|
||||
|
||||
import "../Components"
|
||||
|
||||
Page {
|
||||
id: control
|
||||
|
||||
title: widgetData["firstname"] + " " + widgetData["lastname"]
|
||||
property bool titleIsPageTitle: true
|
||||
property bool ready
|
||||
property int status: -1
|
||||
|
||||
property int perId: -1
|
||||
|
||||
property var widgetData: ({})
|
||||
|
||||
Component.onCompleted: {
|
||||
if(control.loadData(control.perId)){
|
||||
control.ready = true
|
||||
}
|
||||
}
|
||||
|
||||
function loadData(perId) {
|
||||
console.log("loading athlete: ", perId)
|
||||
|
||||
control.status = 905
|
||||
|
||||
var ret = serverConn.getAthlete(perId)
|
||||
|
||||
control.status = ret["status"]
|
||||
|
||||
if(ret["status"] === 200){
|
||||
control.widgetData = ret["data"]
|
||||
return true
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: mainSv
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 10
|
||||
anchors.rightMargin: 14
|
||||
|
||||
contentWidth: parent.width - anchors.leftMargin - anchors.rightMargin
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
|
||||
anchors {
|
||||
top: mainSv.top
|
||||
left: mainSv.right
|
||||
margins: 10
|
||||
leftMargin: 3
|
||||
bottom: mainSv.bottom
|
||||
}
|
||||
|
||||
width: 8
|
||||
|
||||
active: true
|
||||
}
|
||||
|
||||
Column {
|
||||
id: mainCol
|
||||
|
||||
width: parent.width
|
||||
|
||||
Row {
|
||||
height: control.height * 0.3
|
||||
width: parent.width
|
||||
|
||||
Image {
|
||||
id: photo
|
||||
|
||||
property bool ready: false
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
height: parent.height * 0.9
|
||||
width: status === Image.Null || status === Image.Error ? 0:parent.width * 0.5
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
source: widgetData["photo"] === undefined ? "":widgetData["photo"].replace("https", "http").replace("www.digitalrock.de", "egw.ifsc-climbing.org")
|
||||
asynchronous: true
|
||||
|
||||
FancyBusyIndicator {
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
opacity: photo.status === Image.Loading
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
height: parent.height * 0.9
|
||||
width: parent.width - photo.width
|
||||
|
||||
Label {
|
||||
|
||||
height: parent.height * 0.2
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: true
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: widgetData["firstname"] + " " + widgetData["lastname"]
|
||||
}
|
||||
|
||||
Label {
|
||||
height: parent.height * 0.2
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: false
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: widgetData["nation"]
|
||||
}
|
||||
|
||||
Label {
|
||||
height: parent.height * 0.15
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: false
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: "<html><a href='" + widgetData["fed_url"] + "'>" + widgetData["federation"] + "</a>"
|
||||
|
||||
onLinkActivated: {
|
||||
Qt.openUrlExternally(link)
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
height: parent.height * 0.15
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: false
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: qsTr("age") + ": " + widgetData["age"]
|
||||
}
|
||||
|
||||
Label {
|
||||
height: parent.height * 0.15
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: false
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: qsTr("year of birth") + ": " + widgetData["birthdate"]
|
||||
}
|
||||
|
||||
Label {
|
||||
height: parent.height * 0.15
|
||||
width: parent.width
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
font.bold: false
|
||||
minimumPixelSize: 1
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: qsTr("city") + ": " + widgetData["city"]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Label {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
visible: bestResultsRep.model > 0
|
||||
|
||||
width: parent.width
|
||||
|
||||
wrapMode: Label.Wrap
|
||||
|
||||
text: widgetData["freetext"]
|
||||
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: separatorLine
|
||||
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
height: 1
|
||||
width: parent.width * 0.9
|
||||
|
||||
color: "black"
|
||||
|
||||
}
|
||||
|
||||
Button {
|
||||
id: toggleAllResultsBt
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
visible: bestResultsRep.model > 0
|
||||
|
||||
flat: true
|
||||
|
||||
text: bestResultsRep.showAllResults ? qsTr("show best results"):qsTr("show all results")
|
||||
|
||||
onClicked: {
|
||||
bestResultsRep.showAllResults = !bestResultsRep.showAllResults
|
||||
}
|
||||
|
||||
Behavior on text {
|
||||
FadeAnimation {
|
||||
target: toggleAllResultsBt
|
||||
fadeDuration: 150
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: bestResultsRep
|
||||
|
||||
property var bestResults: showAllResults ? getAllResults() : getBestResults()
|
||||
property bool showAllResults: false
|
||||
|
||||
function getBestResults(){
|
||||
|
||||
var allResults = control.widgetData["results"]
|
||||
|
||||
allResults.sort(function(a, b) {
|
||||
// sort results by weight
|
||||
var year = new Date().getFullYear();
|
||||
var weightA = a.rank/2 + (year-parseInt(a.date)) + 4*!a.nation;
|
||||
var weightB = b.rank/2 + (year-parseInt(b.date)) + 4*!b.nation;
|
||||
return weightA - weightB;
|
||||
});
|
||||
|
||||
var bestResults = allResults.slice(0,12)
|
||||
|
||||
bestResults.sort(function(a, b) {
|
||||
// sort results by date
|
||||
var aTs = Date.fromLocaleString(Qt.locale(), a["date"], "yyyy-MM-dd").getTime()
|
||||
var bTs = Date.fromLocaleString(Qt.locale(), b["date"], "yyyy-MM-dd").getTime()
|
||||
return bTs - aTs;
|
||||
});
|
||||
|
||||
return bestResults
|
||||
}
|
||||
|
||||
function getAllResults() {
|
||||
var allResults = control.widgetData["results"]
|
||||
|
||||
allResults.sort(function(a, b) {
|
||||
// sort results by date
|
||||
var aTs = Date.fromLocaleString(Qt.locale(), a["date"], "yyyy-MM-dd").getTime()
|
||||
var bTs = Date.fromLocaleString(Qt.locale(), b["date"], "yyyy-MM-dd").getTime()
|
||||
return bTs - aTs;
|
||||
});
|
||||
|
||||
return allResults
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
|
||||
model: bestResults.length
|
||||
|
||||
delegate: Row {
|
||||
id: bestResultRow
|
||||
|
||||
property var thisData: bestResultsRep.bestResults[index]
|
||||
|
||||
width: parent.width
|
||||
height: 50
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: fadeInPa
|
||||
NumberAnimation { target: bestResultRow; property: "opacity"; from: 0; to: 1.0; duration: 400 }
|
||||
NumberAnimation { target: bestResultRow; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
|
||||
}
|
||||
|
||||
Label {
|
||||
id: bestResultRankLa
|
||||
|
||||
width: parent.width * 0.2
|
||||
height: parent.height
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: 1
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
|
||||
text: bestResultsRep.bestResults[index]["rank"]
|
||||
}
|
||||
|
||||
Label {
|
||||
id: bestResultCompLa
|
||||
|
||||
width: parent.width * 0.6
|
||||
height: parent.height
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: height * 0.3
|
||||
|
||||
font.pixelSize: height * 0.3
|
||||
|
||||
elide: "ElideRight"
|
||||
|
||||
text: "<html><a href='#'>" + bestResultsRep.bestResults[index]["name"] + "</a></html>"
|
||||
|
||||
onLinkActivated: {
|
||||
app.openResults( bestResultsRep.bestResults[index]["WetId"], bestResultsRep.bestResults[index]["GrpId"], 1 )
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: bestResultDateLa
|
||||
|
||||
width: parent.width * 0.2
|
||||
height: parent.height
|
||||
|
||||
scale: 0.8
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: 1
|
||||
|
||||
font.pixelSize: height * 0.6
|
||||
|
||||
text: bestResultsRep.bestResults[index]["date"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
104
resources/qml/Widgets/RegistrationWidget.qml
Normal file
104
resources/qml/Widgets/RegistrationWidget.qml
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
blueROCK - for digital rock
|
||||
Copyright (C) 2019 Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
|
||||
import "../Components"
|
||||
|
||||
DataListView {
|
||||
id: control
|
||||
|
||||
property var widgetData: ({})
|
||||
|
||||
model: widgetData[ 'athletes' ] === undefined ? 0:widgetData[ 'athletes' ].length
|
||||
|
||||
onRefresh: {
|
||||
updateData({}, false)
|
||||
}
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property var thisData: widgetData[ "athletes" ][index]
|
||||
|
||||
width: parent.width
|
||||
height: parseInt(thisData.cat) === parseInt(params.cat) ? undefined:0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
app.openAthlete(thisData["PerId"])
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: fadeInPa
|
||||
NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 }
|
||||
NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
|
||||
}
|
||||
|
||||
text: ""
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: parent.width * 0.05
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: true
|
||||
font.pixelSize: Math.abs( height * 0.4 )
|
||||
minimumPixelSize: height * 0.3
|
||||
|
||||
elide: "ElideRight"
|
||||
|
||||
text: control.getText(index)
|
||||
}
|
||||
}
|
||||
|
||||
function getText(index){
|
||||
|
||||
// ----------------------------
|
||||
// if we have registration data
|
||||
|
||||
var fedName // federation name
|
||||
|
||||
if(widgetData["federations"] !== undefined){
|
||||
// not an international competition -> get name of federation
|
||||
|
||||
for(var i = 0; i < widgetData["federations"].length; i ++ ){
|
||||
//console.log("checking " + i + ": cat: " + parseInt(widgetData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId)
|
||||
if(widgetData["federations"][i]["fed_id"] === widgetData[ 'athletes' ][index]["reg_fed_id"]){
|
||||
fedName = widgetData["federations"][i]["shortcut"]
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// an international competition -> get nation
|
||||
|
||||
fedName = widgetData[ 'athletes' ][index]["nation"]
|
||||
}
|
||||
|
||||
return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")"
|
||||
}
|
||||
}
|
100
resources/qml/Widgets/ResultWidget.qml
Normal file
100
resources/qml/Widgets/ResultWidget.qml
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
blueROCK - for digital rock
|
||||
Copyright (C) 2019 Dorian Zedler
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.9
|
||||
import QtQuick.Controls 2.4
|
||||
|
||||
import "../Components"
|
||||
|
||||
DataListView {
|
||||
id: control
|
||||
|
||||
property var widgetData: ({})
|
||||
|
||||
model: widgetData[ root.listKey ] === undefined ? 0:widgetData[ root.listKey ].length
|
||||
|
||||
delegate: ItemDelegate {
|
||||
id: partDel
|
||||
|
||||
property var thisData: widgetData[ "athletes" ][index]
|
||||
|
||||
width: parent.width
|
||||
height: parseInt(thisData.cat) === root.catId ? undefined:0
|
||||
|
||||
opacity: 0
|
||||
scale: 0.9
|
||||
|
||||
onThisDataChanged: {
|
||||
fadeInPa.start()
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
app.openAthlete(thisData["PerId"])
|
||||
}
|
||||
|
||||
ParallelAnimation {
|
||||
id: fadeInPa
|
||||
NumberAnimation { target: partDel; property: "opacity"; from: 0; to: 1.0; duration: 400 }
|
||||
NumberAnimation { target: partDel; property: "scale"; from: 0.8; to: 1.0; duration: 400 }
|
||||
}
|
||||
|
||||
text: ""
|
||||
|
||||
Label {
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: parent.width * 0.05
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
font.bold: true
|
||||
font.pixelSize: Math.abs( height * 0.4 )
|
||||
minimumPixelSize: height * 0.3
|
||||
|
||||
elide: "ElideRight"
|
||||
|
||||
text: control.getText(index)
|
||||
}
|
||||
}
|
||||
|
||||
function getText(index){
|
||||
|
||||
// ----------------------------
|
||||
// if we have registration data
|
||||
|
||||
var fedName // federation name
|
||||
|
||||
if(widgetData["federations"] !== undefined){
|
||||
// not an international competition -> get name of federation
|
||||
|
||||
for(var i = 0; i < widgetData["federations"].length; i ++ ){
|
||||
//console.log("checking " + i + ": cat: " + parseInt(widgetData["categorys"][i]["GrpId"]) + " searched cat: " + root.catId)
|
||||
if(widgetData["federations"][i]["fed_id"] === widgetData[ root.listKey ][index]["reg_fed_id"]){
|
||||
fedName = widgetData["federations"][i]["shortcut"]
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// an international competition -> get nation
|
||||
|
||||
fedName = widgetData[ root.listKey ][index]["nation"]
|
||||
}
|
||||
|
||||
return widgetData[ "athletes" ][index]["firstname"] + " " + widgetData[ "athletes" ][index]["lastname"] + " (" + fedName + ")"
|
||||
}
|
||||
}
|
|
@ -36,15 +36,10 @@ Window {
|
|||
|
||||
property int errorCode: -1
|
||||
|
||||
property var competitionCategoryColors: {
|
||||
"61": "lightgrey",
|
||||
"58": "lightgreen",
|
||||
|
||||
"69": "#B8C8FF",
|
||||
"70": "#F0F0F0",
|
||||
"71": "#D8E8FF",
|
||||
"256": "#D8E8FF"
|
||||
}
|
||||
// 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
|
||||
|
||||
property var compCats: {
|
||||
'int' : {
|
||||
|
@ -165,8 +160,10 @@ Window {
|
|||
|
||||
Component.onCompleted: {
|
||||
//app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300
|
||||
openWidget({nation:'GER'})
|
||||
}
|
||||
|
||||
|
||||
Shortcut {
|
||||
sequences: ["Esc", "Back"]
|
||||
enabled: mainStack.depth > 1
|
||||
|
@ -179,10 +176,6 @@ Window {
|
|||
|
||||
ServerConn {
|
||||
id: serverConn
|
||||
|
||||
Component.onCompleted: {
|
||||
//serverConn.refreshFoodplan()
|
||||
}
|
||||
}
|
||||
|
||||
StackView {
|
||||
|
@ -524,6 +517,21 @@ Window {
|
|||
return app.height < app.width
|
||||
}
|
||||
|
||||
function openWidget(params){
|
||||
loadingDl.open()
|
||||
|
||||
var calComp = Qt.createComponent("qrc:/Pages/WidgetPage.qml").createObject(null, {"params": params})
|
||||
app.errorCode = calComp.status
|
||||
if(calComp.ready){
|
||||
mainStack.push(calComp)
|
||||
}
|
||||
else {
|
||||
delete(calComp)
|
||||
}
|
||||
|
||||
loadingDl.close()
|
||||
}
|
||||
|
||||
function openCalendar(nation){
|
||||
loadingDl.open()
|
||||
|
||||
|
@ -542,7 +550,7 @@ Window {
|
|||
function openResults(comp, cat, status){
|
||||
// comp: (int) competiotion ID
|
||||
// cat: (int) category ID
|
||||
// reg: (int) 0: result imported into ranking; 1: result-service result available; 2: result-service startlist available; 3: old non result-server startlist (no longer used); 4: starters / registration data
|
||||
// status: (int) 0: result imported into ranking; 1: result-service result available; 2: result-service startlist available; 3: old non result-server startlist (no longer used); 4: starters / registration data
|
||||
|
||||
loadingDl.open()
|
||||
|
||||
|
@ -560,6 +568,11 @@ Window {
|
|||
loadingDl.close()
|
||||
}
|
||||
|
||||
function hasParam(url, param, value){
|
||||
if (typeof value == 'undefined') value = '';
|
||||
return url.indexOf(param+'='+value) !== -1;
|
||||
}
|
||||
|
||||
function openAthlete(perId) {
|
||||
loadingDl.open()
|
||||
|
||||
|
@ -605,7 +618,7 @@ Window {
|
|||
case 500:
|
||||
infoLevel = 2
|
||||
errorString = "Internal server error"
|
||||
errorDescription = "The server was unable to process this request, this is probaply the servers vault. Please try again later."
|
||||
errorDescription = "The server was unable to process this request, this is probaply the servers fault. Please try again later."
|
||||
break
|
||||
case 900:
|
||||
infoLevel = 2
|
||||
|
|
|
@ -16,5 +16,10 @@
|
|||
<file>Components/PullRefresher.qml</file>
|
||||
<file>Pages/AthleteProfilePage.qml</file>
|
||||
<file>Components/FadeAnimation.qml</file>
|
||||
<file>Pages/WidgetPage.qml</file>
|
||||
<file>Widgets/CalendarWidget.qml</file>
|
||||
<file>Widgets/ProfileWidget.qml</file>
|
||||
<file>Widgets/ResultWidget.qml</file>
|
||||
<file>Widgets/RegistrationWidget.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
BIN
resources/shared/faviconNoBackground.png
Normal file
BIN
resources/shared/faviconNoBackground.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 85 KiB |
BIN
resources/shared/icons/more_black.png
Normal file
BIN
resources/shared/icons/more_black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 457 B |
Binary file not shown.
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 67 KiB |
|
@ -7,5 +7,7 @@
|
|||
<file>icons/backDark.png</file>
|
||||
<file>icons/calendar.png</file>
|
||||
<file>icons/cup.png</file>
|
||||
<file>Banner.png</file>
|
||||
<file>icons/more_black.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -23,7 +23,10 @@ ServerConn::ServerConn(QObject *parent) : QObject(parent)
|
|||
}
|
||||
|
||||
QVariant ServerConn::getCalendar(QString nation, int year){
|
||||
QVariantMap ret = this->senddata(QUrl("http://egw.ifsc-climbing.org/egw/ranking/json.php?year=" + QString::number(year) + "&nation=" + nation));
|
||||
QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?year=" + (year == 0 ? "":QString::number(year)) + "&nation=" + nation;
|
||||
qDebug() << requestUrl;
|
||||
|
||||
QVariantMap ret = this->senddata(QUrl(requestUrl));
|
||||
|
||||
if(ret["status"] != 200){
|
||||
// request was a failure
|
||||
|
@ -76,6 +79,29 @@ QVariant ServerConn::getAthlete(int perId){
|
|||
return data;
|
||||
}
|
||||
|
||||
QVariant ServerConn::getWidgetData(QVariantMap params){
|
||||
QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?";
|
||||
|
||||
for(QVariantMap::const_iterator iter = params.begin(); iter != params.end(); ++iter){
|
||||
requestUrl += iter.key() + "=" + iter.value().toString() + "&";
|
||||
}
|
||||
|
||||
qDebug() << requestUrl;
|
||||
|
||||
QVariantMap ret = this->senddata(QUrl(requestUrl));
|
||||
|
||||
if(ret["status"] != 200){
|
||||
// request was a failure
|
||||
return QVariantMap({{"status", ret["status"]}, {"data", ""}});
|
||||
}
|
||||
|
||||
QJsonDocument jsonReply = QJsonDocument::fromJson(ret["text"].toString().toUtf8());
|
||||
|
||||
QVariantMap data = {{"status", 200}, {"data", jsonReply.toVariant()}};
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// --- Helper functions ---
|
||||
// ------------------------
|
||||
|
|
Loading…
Reference in a new issue