From 8aa2d31c406d81fe32f43a8abde1b0115795ecdd Mon Sep 17 00:00:00 2001 From: dorian Date: Sun, 23 Jun 2019 10:55:08 +0200 Subject: [PATCH] - changed year select icon - added the ability to filter competitions by type (eg. world cup, youth, etc.) --- CHANGELOG.md | 12 + android-sources/AndroidManifest.xml | 4 +- blueROCK.pro | 2 + headers/appsettings.h | 43 +++ headers/serverconn.h | 3 - resources/qml/Components/PullRefresher.qml | 61 ++-- resources/qml/Pages/AthleteSearchPage.qml | 44 ++- resources/qml/Pages/StartPage.qml | 2 +- resources/qml/Pages/WidgetPage.qml | 95 +++++- resources/qml/Widgets/CalendarWidget.qml | 314 +++++++++++++++++- resources/qml/Widgets/RegistrationWidget.qml | 2 +- resources/qml/Widgets/ResultWidget.qml | 3 +- resources/qml/Widgets/StartlistWidget.qml | 4 +- resources/qml/main.qml | 86 ++++- .../shared/icons/bluerock/20x20/filter.png | Bin 0 -> 309 bytes .../shared/icons/bluerock/20x20/year.png | Bin 0 -> 363 bytes .../shared/icons/bluerock/20x20@2/filter.png | Bin 0 -> 545 bytes .../shared/icons/bluerock/20x20@2/year.png | Bin 0 -> 591 bytes .../shared/icons/bluerock/20x20@3/filter.png | Bin 0 -> 691 bytes .../shared/icons/bluerock/20x20@3/year.png | Bin 0 -> 727 bytes .../shared/icons/bluerock/20x20@4/filter.png | Bin 0 -> 806 bytes .../shared/icons/bluerock/20x20@4/year.png | Bin 0 -> 767 bytes resources/shared/shared.qrc | 8 + sources/appsettings.cpp | 68 ++++ sources/main.cpp | 2 + sources/serverconn.cpp | 75 +---- 26 files changed, 686 insertions(+), 142 deletions(-) create mode 100644 headers/appsettings.h create mode 100644 resources/shared/icons/bluerock/20x20/filter.png create mode 100644 resources/shared/icons/bluerock/20x20/year.png create mode 100644 resources/shared/icons/bluerock/20x20@2/filter.png create mode 100644 resources/shared/icons/bluerock/20x20@2/year.png create mode 100644 resources/shared/icons/bluerock/20x20@3/filter.png create mode 100644 resources/shared/icons/bluerock/20x20@3/year.png create mode 100644 resources/shared/icons/bluerock/20x20@4/filter.png create mode 100644 resources/shared/icons/bluerock/20x20@4/year.png create mode 100644 sources/appsettings.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 06a22c9..daf4515 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ 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.01.6] - 2019-06-15 +### Fixed +- label for IFSC calendar + +# [0.01.5] - 2019-06-15 +### Fixed +- layout fixes +- cat when changing from 'MEN' to 'WOMEN' 'MEN' is not missing anymore + +### Added +- infosheet url is now present in the cat select dialog if available + # [0.01.4b] - 2019-05-31 ### Fixed - fixed some errors that occurred when changing categories diff --git a/android-sources/AndroidManifest.xml b/android-sources/AndroidManifest.xml index 7b7d720..e62c7f4 100644 --- a/android-sources/AndroidManifest.xml +++ b/android-sources/AndroidManifest.xml @@ -1,7 +1,7 @@ - + - + diff --git a/blueROCK.pro b/blueROCK.pro index e49c8e5..cf8bcfc 100644 --- a/blueROCK.pro +++ b/blueROCK.pro @@ -18,6 +18,7 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + sources/appsettings.cpp \ sources/main.cpp \ sources/serverconn.cpp @@ -39,6 +40,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target HEADERS += \ + headers/appsettings.h \ headers/serverconn.h DISTFILES += \ diff --git a/headers/appsettings.h b/headers/appsettings.h new file mode 100644 index 0000000..7c31ddc --- /dev/null +++ b/headers/appsettings.h @@ -0,0 +1,43 @@ +#ifndef APPSETTINGS_H +#define APPSETTINGS_H + +#include +#include +#include +#include + +class AppSettings : public QObject +{ + Q_OBJECT + + Q_PROPERTY(NOTIFY themeChanged) + +public: + explicit AppSettings(QObject *parent = nullptr); + // This is the Constructor of the AppSettings class + + ~AppSettings(); + // This is the Destructor of the AppSettings class + +private: + QSettings *settingsManager; + // QSettings object which cares about our settings.ini file + + QSettings *themeSettingsManager; + // QSettings object which cares about the themes + +signals: + void themeChanged(); + +public slots: + Q_INVOKABLE QString read(const QString &key); + // function to read values from the settings file + + Q_INVOKABLE void write(const QString &key, const QVariant &value); + // function to write values to the settings file + + Q_INVOKABLE void setDefault(const QString &key, const QVariant &defaultValue); + // function to create a key (/ setting) with a default value if it hasnt been ceated yet +}; + +#endif // APPSETTINGS_H diff --git a/headers/serverconn.h b/headers/serverconn.h index e097a58..2630af3 100644 --- a/headers/serverconn.h +++ b/headers/serverconn.h @@ -38,9 +38,6 @@ signals: 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); }; diff --git a/resources/qml/Components/PullRefresher.qml b/resources/qml/Components/PullRefresher.qml index 16d6dc2..8d2fb5c 100644 --- a/resources/qml/Components/PullRefresher.qml +++ b/resources/qml/Components/PullRefresher.qml @@ -15,7 +15,9 @@ Item { property int preRefreshDelay: 1000 // delay before reload funcion is called property int refreshPosition: height * 1.2 // position of the item when refreshing - property int dragOutPosition: height * 1.8 // position of the item when starting to refresh + property int dragOutPosition: height * 1.8 // maximum drag out + + property double dragRefreshPositionMultiplier: 0.5 // 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 @@ -49,6 +51,8 @@ Item { property double drawProgress: control.dragProgress + rotation: drawProgress > control.dragRefreshPositionMultiplier ? 180:0 + onDrawProgressChanged: { requestPaint() } @@ -68,8 +72,7 @@ Item { var lineWidth = 2 - var progress = drawProgress - console.log(progress) + var progress = drawProgress * 1 / control.dragRefreshPositionMultiplier > 1 ? 1 : drawProgress * 1 / control.dragRefreshPositionMultiplier // modify all values to math the progress arrowHeight = arrowHeight * progress @@ -101,6 +104,13 @@ Item { ctx.stroke(); } + + Behavior on rotation { + NumberAnimation { + duration: 100 + } + } + } signal refreshRequested @@ -132,14 +142,13 @@ Item { topMargin: control.position - height } - onUserPositionChanged: { - console.log(userPosition) - if(control.state === "idle" && userPosition >= control.dragOutPosition * 0.9){ - control.state = "ready" - } - else if(control.state === "ready" && userPosition < control.dragOutPosition * 0.9){ - control.state = "refreshing" - preRefreshTimer.start() + Connections { + target: control.target + onDragEnded: { + if(userPosition >= control.dragOutPosition * control.dragRefreshPositionMultiplier){ + control.state = "refreshing" + preRefreshTimer.start() + } } } @@ -177,13 +186,6 @@ Item { sourceComponent: control.busyIndicator } - Behavior on minimumPosition { - enabled: control.state !== "hidden" && control.state !== "idle" - NumberAnimation { - duration: 100 - } - } - Timer { id: preRefreshTimer interval: control.preRefreshDelay <= 0 ? 1:control.preRefreshDelay @@ -204,6 +206,13 @@ Item { } } + Behavior on minimumPosition { + enabled: !control.target.dragging && state !== "idle" + NumberAnimation { + duration: 100 + } + } + states: [ State { name: "idle" @@ -211,7 +220,7 @@ Item { PropertyChanges { target: control minimumPosition: userPosition > maximumPosition ? maximumPosition:userPosition - userPosition: -1 / (Math.abs( target.verticalOvershoot * 0.001 ) + 1 / control.dragOutPosition * 0.001) + control.dragOutPosition // Math.abs( target.verticalOvershoot ) + userPosition: -1 / (Math.abs( target.verticalOvershoot * 0.001 + 0.003 ) + 1 / control.dragOutPosition * 0.001) + control.dragOutPosition // Math.abs( target.verticalOvershoot ) maximumPosition: control.dragOutPosition } @@ -220,20 +229,6 @@ Item { rotation: 0 } }, - State { - name: "ready" - PropertyChanges { - target: control - maximumPosition: control.dragOutPosition - userPosition: -1 / (Math.abs( target.verticalOvershoot * 0.001 ) + 1 / control.dragOutPosition * 0.001) + control.dragOutPosition // Math.abs( target.verticalOvershoot ) - minimumPosition: userPosition > maximumPosition - 1 ? maximumPosition - 1:userPosition - } - - PropertyChanges { - target: pullIndicatorLd - rotation: 180 - } - }, State { name: "refreshing" PropertyChanges { diff --git a/resources/qml/Pages/AthleteSearchPage.qml b/resources/qml/Pages/AthleteSearchPage.qml index b40bee4..7f8ec87 100644 --- a/resources/qml/Pages/AthleteSearchPage.qml +++ b/resources/qml/Pages/AthleteSearchPage.qml @@ -18,13 +18,55 @@ import QtQuick 2.0 import QtQuick.Controls 2.4 +import "../Components" Page { id: root - title: "start" + title: "search athlete" property Component headerComponent: null + property var searchResults: ({}) + + function search(term){ + loadingDl.open() + root.searchResults = serverConn.getWidgetData({term:term}).data + loadingDl.close() + } + + ListView { + + anchors.fill: parent + anchors.topMargin: searchTf.height + anchors.margins: 10 + + clip: true + + model: root.searchResults.length + + delegate: ItemDelegate { + width: parent.width + text: root.searchResults[index]['label'] + onClicked: app.openWidget({person: root.searchResults[index]['value']}) + } + + + } + + TextField { + id: searchTf + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 10 + } + Keys.onReturnPressed: { + console.warn(searchTf.text) + root.search("*" + searchTf.text + "*") + } + } + } diff --git a/resources/qml/Pages/StartPage.qml b/resources/qml/Pages/StartPage.qml index 97ca5be..58779c4 100644 --- a/resources/qml/Pages/StartPage.qml +++ b/resources/qml/Pages/StartPage.qml @@ -61,7 +61,7 @@ Page { image: "qrc:/icons/ifsc.png" onClicked: { - app.openWidget({nation:""}) + app.openWidget({nation:"ICC"}) } } diff --git a/resources/qml/Pages/WidgetPage.qml b/resources/qml/Pages/WidgetPage.qml index ce2bbb4..e5aba07 100644 --- a/resources/qml/Pages/WidgetPage.qml +++ b/resources/qml/Pages/WidgetPage.qml @@ -18,7 +18,10 @@ import QtQuick 2.9 import QtQuick.Controls 2.4 -import QtGraphicalEffects 1.0 +//import QtGraphicalEffects 1.0 +//import QtQuick.Templates 2.04 as T +//import QtQuick.Controls.impl 2.04 +import QtQuick.Controls.Material 2.3 import "../Components" @@ -97,7 +100,12 @@ Page { // update all the given values for(var prop in params){ if(params.hasOwnProperty(prop)){ + if(params[prop] === null){ + delete root.params[prop] + } + else { root.params[prop] = params[prop] + } } } @@ -244,11 +252,14 @@ Page { id: selectorPu property var dataObj + property string subTitle: "" signal selectionFinished(int index, var data) x: 0 //root.width / 2 - width / 2 - y: root.height - height //root.height / 2 - height / 2 + y: root.height - selectorPu.height * 0.7//root.height - height //root.height / 2 - height / 2 + + opacity: 0 width: root.width height: selectorLv.implicitHeight @@ -258,10 +269,69 @@ Page { title: "" - function appear(dataObj, 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 selectorPu.title = title + selectorPu.subTitle = subTitle === undefined ? "":subTitle selectorPu.open() } } @@ -274,7 +344,7 @@ Page { anchors.fill: parent implicitWidth: parent.width - implicitHeight: root.height * 0.6 < ( (delegateHeight + spacing) * model ) ? root.height * 0.6 : (delegateHeight + spacing) * model + 75 + implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100 model: selectorPu.dataObj !== undefined ? selectorPu.dataObj.length:0 @@ -308,21 +378,30 @@ Page { } enter: Transition { - NumberAnimation { property: "opacity"; from: 0.0; to: 1.0 } + NumberAnimation { + property: "opacity"; + //from: 0.0; + to: 1.0 + } NumberAnimation { property: "y" - from: root.height - selectorPu.height * 0.7 + //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: "opacity"; + //from: 1.0; + to: 0.0 + } NumberAnimation { property: "y" - from: root.height - selectorPu.height + //from: root.height - selectorPu.height to: root.height - selectorPu.height * 0.7 } } } + } diff --git a/resources/qml/Widgets/CalendarWidget.qml b/resources/qml/Widgets/CalendarWidget.qml index c790a52..84f33e1 100644 --- a/resources/qml/Widgets/CalendarWidget.qml +++ b/resources/qml/Widgets/CalendarWidget.qml @@ -27,10 +27,11 @@ DataListView { property bool ready - property string title: (params.nation === "" ? "IFSC":params.nation === "GER" ? "DAV":"SAC") + " " + qsTr("competition calendar") + " " + control.year + property string title: (params.nation === "ICC" ? "IFSC":params.nation === "GER" ? "DAV":"SAC") + " " + qsTr("calendar") + " " + control.year property Component headerComponent: RowLayout { height: parent.height + width: 100//childrenRect.width spacing: 0 @@ -41,7 +42,29 @@ DataListView { control.changeYear() } - icon.name: "calendar" + icon.name: "year" + } + + ToolButton { + id: filterToolBt + + onClicked: { + var obj = app.compCats + var compCats = new Array + + for(var prop in obj) { + // go through the whole array and search for data keys + if (obj.hasOwnProperty(prop) && obj[prop]["nation"] === params.nation) { + //console.log("found cat: " + obj[prop]['label']) + + compCats.push( {"text": obj[prop]['label'], "data": obj[prop]} ) + } + } + + filterSelectPu.appear(compCats, qsTr("Select Filters"), "") + } + + icon.name: "filter" } ToolButton { @@ -59,6 +82,8 @@ DataListView { property int year: new Date().getFullYear() + property var displayedCompCats: [] + anchors.fill: parent //boundsBehavior: Flickable.StopAtBounds @@ -70,6 +95,8 @@ DataListView { } Component.onCompleted: { + initFilters() + if(model > 0){ control.ready = true control.status = 200 @@ -80,9 +107,11 @@ DataListView { } autoScroll() + } + onWidgetDataChanged: { // if the IFSC Calendar is open -> add the worldranking - if(params.nation === ""){ + if(params.nation === "ICC"){ control.widgetData['cups'].unshift({"SerId":"","rkey":"","name":"Worldranking","modified":"2018-10-24 16:11:12","modifier":"","year":"","num_comps":"","cats":["ICC-COA","ICC-HD","ICC-MED","ICC_F","ICC_FB","ICC_FS","ICC_M","ICC_MB","ICC_MS"]}) } } @@ -91,7 +120,7 @@ DataListView { // function to scroll to the next competition that is not already over var compList = control.widgetData["competitions"] - //console.log("scrolling") + console.log("scrolling") if(parseInt(control.year) === new Date().getFullYear()){ for(var i = 0; i < compList.length; i ++){ @@ -146,7 +175,7 @@ DataListView { } } - selector.appear(selectOptions, qsTr("select category")) + selector.appear(selectOptions, control.widgetData["competitions"][compIndex]['name'], getCompInfoUrl(compIndex) !== undefined ? ("infosheet"): "") } function changeYear(){ @@ -223,6 +252,66 @@ DataListView { } + function getCompInfoUrl(compIndex) { + switch(params.nation) { + case "GER": + if(control.widgetData["competitions"][compIndex]['info'] !== undefined){ + return "http://ranking.alpenverein.de/" + control.year + "/GER/" + control.widgetData["competitions"][compIndex]['rkey'] + ".pdf" + } + return + case "SUI": + return + default: + if(control.widgetData["competitions"][compIndex]['info'] === undefined){ + return control.widgetData["competitions"][compIndex]['info2'] + } + else { + return control.widgetData["competitions"][compIndex]['info'] + } + } + } + + function filterCats(display, cats) { + //console.log("filtering cats: " + cats + " displaying: " + display) + for(var i = 0; i < cats.length; i ++){ + if(control.displayedCompCats.indexOf(cats[i]) >= 0 && !display){ + control.displayedCompCats.splice(control.displayedCompCats.indexOf(cats[i]), 1) + } + else if(control.displayedCompCats.indexOf(cats[i]) == -1 && display){ + control.displayedCompCats.push(cats[i]) + + } + } + // trigger 'changed' signal + control.displayedCompCats = control.displayedCompCats + appSettings.write("displayedCompCats"+params.nation, JSON.stringify(displayedCompCats)) + //console.log("new JSON string is: " + JSON.stringify(displayedCompCats)) + //console.log("displayed cats is now: " + control.displayedCompCats) + } + + function initFilters() { + + if(appSettings.read("displayedCompCats"+params.nation) !== "false"){ + //console.log(appSettings.read("displayedCompCats"+params.nation)) + control.displayedCompCats = JSON.parse(appSettings.read("displayedCompCats"+params.nation)) + } + if(control.displayedCompCats.length === 0){ + var obj = app.compCats + var compCats = new Array + + for(var prop in obj) { + // go through the whole array and search for data keys + if (obj.hasOwnProperty(prop) && obj[prop]["nation"] === params.nation) { + //console.log("found cat: " + obj[prop]['label']) + filterCats(true, obj[prop]['cat_id']) + } + } + } + // trigger 'changed' signal + control.displayedCompCats = control.displayedCompCats + //console.log(control.displayedCompCats) + } + Connections { target: parent.selector onSelectionFinished: { @@ -243,6 +332,18 @@ DataListView { } } + header: Item { + id: topSpacerItm + width: parent.width + height: 10 + } + + footer: Item { + id: bottomSpacerItm + width: parent.width + height: 10 + } + delegate: ItemDelegate { id: competitionDel @@ -255,13 +356,22 @@ DataListView { property int catId: thisData["cat_id"] === undefined ? 0:thisData["cat_id"] width: parent.width - height: compDelCol.height + 10 + height: visible ? compDelCol.height + 10 : 0 enabled: thisData["cats"] !== undefined && thisData["cats"].length > 0 + visible: control.displayedCompCats.indexOf(parseInt(thisData['cat_id'])) >= 0 opacity: 0 scale: 0.9 + Connections { + target: control + onDisplayedCompCatsChanged: { + //console.log("filters changed") + competitionDel.visible = control.displayedCompCats.indexOf(parseInt(competitionDel.thisData['cat_id'])) >= 0 + } + } + onThisDataChanged: { fadeInPa.start() } @@ -307,14 +417,6 @@ DataListView { text: name } - /*Label { - id: infola - - width: parent.width - - text: thisData.info - }*/ - Label { id: dateLa @@ -339,4 +441,188 @@ DataListView { } } + + Dialog { + 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 { + id: selectorLv + + property int delegateHeight: 50 + + anchors.fill: parent + + implicitWidth: parent.width + implicitHeight: root.height * 0.7 < ( (delegateHeight + spacing) * model ) ? root.height * 0.7 : (delegateHeight + spacing) * model + 100 + + model: filterSelectPu.dataObj !== undefined ? filterSelectPu.dataObj.length:0 + + ScrollIndicator.vertical: ScrollIndicator { + parent: selectorLv.parent + anchors { + top: selectorLv.top + left: selectorLv.right + margins: 10 + leftMargin: 3 + bottom: selectorLv.bottom + } + + } + + delegate: CheckDelegate { + id: catBt + + width: parent.width + height: text !== "" ? selectorLv.delegateHeight:0 + + //flat: true + + text: filterSelectPu.dataObj[index].text + + Component.onCompleted: { + checked = getCheckedState() + } + + Connections { + target: control + onDisplayedCompCatsChanged: { + //console.log("filters changed") + //competitionDel.visible = control.displayedCompCats.indexOf(parseInt(competitionDel.thisData['cat_id'])) >= 0 + checked = getCheckedState() + } + } + + function getCheckedState() { + for(var i = 0; i < filterSelectPu.dataObj[index].data.cat_id.length; i ++){ + + console.log("checking cat " + filterSelectPu.dataObj[index].data.label ) + if(control.displayedCompCats.indexOf(filterSelectPu.dataObj[index].data.cat_id[i] ) >= 0){ + return true + } + } + return false + } + + + onClicked: { + control.filterCats(checked, filterSelectPu.dataObj[index].data.cat_id) + if(control.displayedCompCats.length == 0){ + control.filterCats(true, filterSelectPu.dataObj[index].data.cat_id) + checked = true + } + } + } + } + + 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 + } + } + } } diff --git a/resources/qml/Widgets/RegistrationWidget.qml b/resources/qml/Widgets/RegistrationWidget.qml index 7486880..4ca9569 100644 --- a/resources/qml/Widgets/RegistrationWidget.qml +++ b/resources/qml/Widgets/RegistrationWidget.qml @@ -172,7 +172,7 @@ DataListView { fontSizeMode: Text.Fit font.bold: true - font.pixelSize: Math.abs( height * 0.4 ) + font.pixelSize: Math.abs( height * 0.35 ) minimumPixelSize: height * 0.3 elide: "ElideRight" diff --git a/resources/qml/Widgets/ResultWidget.qml b/resources/qml/Widgets/ResultWidget.qml index 17c311f..9af83fc 100644 --- a/resources/qml/Widgets/ResultWidget.qml +++ b/resources/qml/Widgets/ResultWidget.qml @@ -194,7 +194,7 @@ DataListView { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft - text: partDel.thisData["firstname"] + " " + partDel.thisData["lastname"] + text: partDel.thisData["firstname"] + " " + partDel.thisData["lastname"] + " (" + partDel.thisData["start_number"] + ")" } Label { @@ -235,7 +235,6 @@ DataListView { Repeater { id: boulderResRep - model: parseInt(widgetData[ "route_num_problems" ]) function getDataForIcon(index){ diff --git a/resources/qml/Widgets/StartlistWidget.qml b/resources/qml/Widgets/StartlistWidget.qml index 94d1208..d1ca712 100644 --- a/resources/qml/Widgets/StartlistWidget.qml +++ b/resources/qml/Widgets/StartlistWidget.qml @@ -166,12 +166,12 @@ DataListView { fontSizeMode: Text.Fit font.bold: true - font.pixelSize: Math.abs( height * 0.45 ) + font.pixelSize: Math.abs( height * 0.35 ) verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignLeft minimumPixelSize: 1 - text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"] + text: widgetData[ "participants" ][index]["firstname"] + " " + widgetData[ "participants" ][index]["lastname"] + " (" + partDel.thisData["start_number"] + ")" } Label { diff --git a/resources/qml/main.qml b/resources/qml/main.qml index 035c5e8..1f4fe6b 100644 --- a/resources/qml/main.qml +++ b/resources/qml/main.qml @@ -43,28 +43,44 @@ Window { // - https://github.com/ralfbecker/ranking/blob/master/sitemgr/digitalrock/sac_calendar.php property var compCats: { - 'int' : { + + // --- ICC --- + + /*'int' : { 'label' : 'International', - 'nation' : '', + 'nation' : 'ICC', 'wettk_reg' : '^[0-9]{2,2}[_^E]{1}[^YJ]{1,1}.*', 'serie_reg' : '^[0-9]{2,2}_(WC|TR){1,1}.*', 'rang_title': 'CUWR continuously updated WORLDRANKING', 'bgcolor' : '#B8C8FF', 'nat_team_ranking' : '', - 'cat_id' : [68,69,70,86,259] + 'cat_id' : [68,86]//[68,69,70,86,259] + },*/ + 'worldcup': { + 'label' : 'World Cups', + 'nation' : 'ICC', + 'bgcolor' : '#B8C8FF', + 'cat_id' : [69] }, 'youth' : { - 'label' : 'Int. Jugend', - 'nation' : '', + 'label' : 'Youth Events', + 'nation' : 'ICC', 'wettk_reg' : '^[0-9]{2,2}(EYC|_J|_Y){1,1}.*', 'serie_reg' : '^[0-9]{2,2}_EYC', 'rang_title': '', 'bgcolor' : '#D8E8FF', 'cat_id' : [71,258] }, + 'champandgames': { + 'label': 'Championships and Games', + 'nation': 'ICC', + 'bgcolor' : '#B8C8FF', + 'cat_id': [68,86] + }, + 'masters' : { - 'label' : 'Masters', - 'nation' : '', + 'label' : 'Masters and Promo Events', + 'nation' : 'ICC', 'wettk_reg' : '^[0-9]{2,2}_[^PWERASL]{1}.*', // 'serie_reg' : '^[0-9]{2,2}_(WC|TR){1,1}.*', // 'rang_title': 'CUWR continuously updated WORLDRANKING', @@ -72,18 +88,27 @@ Window { 'cat_id' : [70] }, 'para' : { - 'label' : 'Paraclimbing', - 'nation' : '', + 'label' : 'Paraclimbing Events', + 'nation' : 'ICC', 'wettk_reg' : '^[0-9]{2,2}_PE.*', 'bgcolor' : '#F0F0F0', 'cat_id' : [256,259] }, - 'ger_boulder' : { + 'cont': { + 'label' : 'Continental Events', + 'nation' : 'ICC', + 'bgcolor' : '#B8C8FF', + 'cat_id' : [262] + }, + + // --- GER --- + + /*'ger_boulder' : { 'label' : 'Bouldern', 'nation' : 'GER', 'wettk_reg' : '^[0-9]{2,2}_B+.*', 'serie_reg' : '^[0-9]{2,2}_BC', - 'bgcolor' : '#FFDBA8', + 'bgcolor' : '#FFDBA8', //'#f59d30' 'cat_id' : [59] }, 'ger' : { @@ -91,7 +116,7 @@ Window { 'nation' : 'GER', 'wettk_reg' : '^[0-9]{2,2}[_J]{1,1}[^WLJ]+.*', 'serie_reg' : '^[0-9]{2,2}_DC', - 'bgcolor' : '#A8F0A8', + 'bgcolor' : '#A8F0A8', //'#69b9a9' 'cat_id' : [57] }, 'ger_speed' : { @@ -100,17 +125,24 @@ Window { 'wettk_reg' : '^[0-9]{2,2}[_J]{1,1}[^WLJ]+.*', 'serie_reg' : '', 'rang_title': '', - 'bgcolor' : '#A8F0A8', + 'bgcolor' : '#A8F0A8', //'#e72e5d' 'cat_id' : [60] + },*/ + 'ger_meisterschaft' : { + 'label' : 'Deutsche Meisterschaft', + 'nation' : 'GER', + 'bgcolor' : '#A8F0A8', + 'cat_id' : [57, 59, 60] }, + 'ger_jugend' : { - 'label' : 'Jugend', + 'label' : 'Deutscher Jugendcup', 'nation' : 'GER', 'wettk_reg' : '^[0-9]{2,2}[_J]{1,1}[^WL]+.*', 'serie_reg' : '^[0-9]{2,2}_JC', // 'rang_title': 'Deutsche Jugend RANGLISTE', 'bgcolor' : '#D8FFD8', - 'cat_id' : [57,58] + 'cat_id' : [58] }, 'ger_state' : { 'label' : 'Landesmeisterschaft', @@ -121,6 +153,9 @@ Window { 'bgcolor' : '#F0F0F0', 'cat_id' : [61,56] }, + + // --- SUI --- + 'sui' : { 'label' : 'Erwachsene', 'nation' : 'SUI', @@ -162,6 +197,7 @@ Window { Component.onCompleted: { //app.openAthlete(53139) // dorian: 53139 , rustam: 6933 , helen: 53300 //openWidget({nation:'GER'}) + //mainStack.push("Pages/AthleteSearchPage.qml") } Shortcut { @@ -178,6 +214,10 @@ Window { id: serverConn } + AppSettings { + id: appSettings + } + StackView { id: mainStack @@ -357,8 +397,20 @@ Window { height: parent.height - onItemChanged: { - width = status === Loader.Ready ? item.width:0 + onStatusChanged: { + //console.log("loader status changed: " + status) + + if(status == 0){ + extraComponentLoader.Layout.preferredWidth = 0 + } + else { + extraComponentLoader.item.width = extraComponentLoader.item.implicitWidth + extraComponentLoader.Layout.preferredWidth = extraComponentLoader.item.width + } + + + + //console.log("set loader width to: " + extraComponentLoader.Layout.preferredWidth + " for a item width of: " + extraComponentLoader.item.implicitWidth) } //sourceComponent: mainStack.currentItem.headerComponent diff --git a/resources/shared/icons/bluerock/20x20/filter.png b/resources/shared/icons/bluerock/20x20/filter.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc1e8a5ae41bcd767db40581c2b43f8649672e6 GIT binary patch literal 309 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VTavfC3&Vd9T(EcfWS|IVfk$L9 z0|Vb-5N14{zaj-F$X?><>&pI^O-#r{>{}N9b)e88PZ!4!i_=#p8S*tbh`7kNwcUui z6cJg#*?)l3BS+VU%~tJJQ~|fP6t~_%-WP8dNKT&0QD-J%buz_#^Jn$l|MmY^F{SSp zuMOzTKhbz@@=tA*5+?lvQWlKn53DL0yZJ1b*dMI96=p>DI$rgy1)=b5i9%crSt zG}{^A`0b(2_q(YtjG! literal 0 HcmV?d00001 diff --git a/resources/shared/icons/bluerock/20x20/year.png b/resources/shared/icons/bluerock/20x20/year.png new file mode 100644 index 0000000000000000000000000000000000000000..26f4edc83264a9d7cab9b9bb38702dae936609ce GIT binary patch literal 363 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 literal 0 HcmV?d00001 diff --git a/resources/shared/shared.qrc b/resources/shared/shared.qrc index c88314b..fc0916f 100644 --- a/resources/shared/shared.qrc +++ b/resources/shared/shared.qrc @@ -34,5 +34,13 @@ icons/bluerock/20x20@2/calendar.png icons/bluerock/20x20@3/calendar.png icons/bluerock/20x20@4/calendar.png + icons/bluerock/20x20/filter.png + icons/bluerock/20x20/year.png + icons/bluerock/20x20@2/filter.png + icons/bluerock/20x20@2/year.png + icons/bluerock/20x20@3/filter.png + icons/bluerock/20x20@3/year.png + icons/bluerock/20x20@4/filter.png + icons/bluerock/20x20@4/year.png diff --git a/sources/appsettings.cpp b/sources/appsettings.cpp new file mode 100644 index 0000000..9d98c94 --- /dev/null +++ b/sources/appsettings.cpp @@ -0,0 +1,68 @@ +#include "headers/appsettings.h" + +AppSettings::AppSettings(QObject* parent) + :QObject(parent) +{ + // This is the Constructor of the AppSettings class + + // get writable path to store the settings.ini file + QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); + + qDebug() << "app settings path: " << path; + + // create or open the settings.ini file + this->settingsManager = new QSettings(path+"/settings.ini", QSettings::IniFormat); + + // set the values to their defaults if they haven't been created yet + + // create or open the settings.ini file + this->themeSettingsManager = new QSettings(":/themes/" + this->read("theme") + ".ini", QSettings::IniFormat); +} + +QString AppSettings::read(const QString &key) +{ + // function to read values from the settings file + + // open the value-group + this->settingsManager->beginGroup("AppSettings"); + // read the value + QString value = this->settingsManager->value(key , false).toString(); + // close the value-group + this->settingsManager->endGroup(); + // return the value + return(value); +} + +void AppSettings::write(const QString &key, const QVariant &value) +{ + // function to write values to the settings file + + // open the value-group + this->settingsManager->beginGroup("AppSettings"); + // write the value + this->settingsManager->setValue(key, value); + // close the value-group + this->settingsManager->endGroup(); +} + +void AppSettings::setDefault(const QString &key, const QVariant &defaultValue) +{ + // function to create a key (/ setting) with a default value if it hasnt been ceated yet + + // read the current value + QString value = this->read(key); + if(value == "false"){ + // if it is nor defined yet, the read function will return "false" (as a string) + // -> if that is the case -> create the key with the default value + this->write(key, defaultValue); + } + +} + +AppSettings::~AppSettings() +{ + // This is the Destructor of the AppSettings class + + // delete the settings manager + delete settingsManager; +} diff --git a/sources/main.cpp b/sources/main.cpp index 6226180..6afdf77 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -23,6 +23,7 @@ #include #include "headers/serverconn.h" +#include "headers/appsettings.h" int main(int argc, char *argv[]) { @@ -36,6 +37,7 @@ int main(int argc, char *argv[]) QIcon::setThemeName("bluerock"); qmlRegisterType("com.itsblue.digitalRockRanking", 1, 0, "ServerConn"); + qmlRegisterType("com.itsblue.digitalRockRanking", 1, 0, "AppSettings"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); diff --git a/sources/serverconn.cpp b/sources/serverconn.cpp index 26595de..5bff901 100644 --- a/sources/serverconn.cpp +++ b/sources/serverconn.cpp @@ -22,70 +22,29 @@ ServerConn::ServerConn(QObject *parent) : QObject(parent) { } -QVariant ServerConn::getCalendar(QString nation, int year){ - 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 - return QVariantMap({{"status", ret["status"]}, {"data", ""}}); - } - - QJsonDocument jsonReply = QJsonDocument::fromJson(ret["text"].toString().toUtf8()); - - QVariantMap rankingData = {{"status", 200}, {"data", jsonReply.toVariant()}}; - - return rankingData; -} - -QVariant ServerConn::getRanking(int competiotionId, int categoryId, bool registrationData, bool rankingData, int routeNumber) { - - QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?" + QString(rankingData ? "cup":"comp") + "=" + QString::number( competiotionId ) + "&cat=" + QString::number( categoryId ) + (registrationData ? "&type=starters":"") + "&route=" + ((routeNumber == -2) ? "":QString::number(routeNumber)); - - 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; -} - -QVariant ServerConn::getAthlete(int perId){ - QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?person=" + QString::number(perId); - - 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; -} - QVariant ServerConn::getWidgetData(QVariantMap params){ - QString requestUrl = "http://egw.ifsc-climbing.org/egw/ranking/json.php?"; + QString requestUrl; + if(params["nation"].toString() == "ICC"){ + requestUrl = "https://ifsc-egw.wavecdn.net/egw/ranking/json.php?"; + params["nation"] = ""; + } + else if (params["nation"].toString() == "GER") { + requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?"; + } + else if (params["nation"].toString() == "SUI") { + requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?"; + } + else { + params.remove("nation"); + requestUrl = "https://www.digitalrock.de/egroupware/ranking/json.php?"; + } for(QVariantMap::const_iterator iter = params.begin(); iter != params.end(); ++iter){ requestUrl += iter.key() + "=" + iter.value().toString() + "&"; } + requestUrl = requestUrl.left(requestUrl.length() - 1); // remove last & + qDebug() << requestUrl; QVariantMap ret = this->senddata(QUrl(requestUrl));