/* 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 . */ import QtQuick 2.9 import QtQuick.Controls 2.4 import QtQuick.Layouts 1.3 import "../Components" DataListView { id: control property bool ready property string title: (params.nation === "ICC" ? "IFSC":params.nation === "GER" ? "DAV":"SAC") + " " + qsTr("calendar") + " " + control.year property Component headerComponent: RowLayout { height: parent.height //width: 10//childrenRect.width spacing: 0 ToolButton { id:yearToolBt onClicked: { control.changeYear() } 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]} ) } } compCats.push( {"text": qsTr("Pinned"), "data": {"sort_rank":0, "cat_id":[-1]}} ) compCats.sort(function(a, b) { return a['data']['sort_rank'] - b['data']['sort_rank']; }); filterSelectPu.appear(compCats, qsTr("Select Filters"), "") } icon.name: "filter" } ToolButton { id: cupToolBt onClicked: { control.openCup() } icon.name: "cup" } } property var widgetData: currentWidgetData property int year: new Date().getFullYear() property var displayedCompCats: [] property var compFavorites: [] anchors.fill: parent //boundsBehavior: Flickable.StopAtBounds model: widgetData["competitions"].length //listData: widgetData['competitions'] onRefresh: { updateData({}, false) } Component.onCompleted: { initFilters() initFavorites() if(model){ control.status = 200 control.ready = true } else { control.ready = false control.status = 901 return } autoScroll() } onWidgetDataChanged: { // if the IFSC Calendar is open -> add the worldranking 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"]}) } } function autoScroll() { // function to scroll to the next competition that is not already over var compList = control.widgetData["competitions"] //console.log("scrolling") if(parseInt(control.year) === new Date().getFullYear()){ for(var i = 0; i < compList.length; i ++){ // get the start date of the competition var startDate = Date.fromLocaleString(Qt.locale(), compList[i]["date"], "yyyy-MM-dd") //control.widgetData["competitions"][i]["month"] = startDate.getMonth() //console.log("got date: " + startDate + " from string: " + compList[i]["date"] + " -> month is: " + compList[i]["month"]) // 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!") } } //control.widgetData = control.widgetData } else { //console.log("not current year") } } 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"]}}) } } var infosheet = getCompInfoUrl(compIndex) !== undefined ? ("" + qsTr('infosheet') + ""): "" var eventWebsite = control.widgetData["competitions"][compIndex]["homepage"] !== undefined ? ("" + qsTr('Event Website') + ""):"" selector.appear(selectOptions, control.widgetData["competitions"][compIndex]['name'], eventWebsite + ((eventWebsite !== "" && infosheet !== "") ? ", ":"") + infosheet ) } 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, qsTr("select year")) } function openCup(state, data) { var cups = control.widgetData["cups"] var prop var selectOptions = [] var selectTitle = "" if(state === undefined){ // opened for the first time -> select cup selectTitle = qsTr("select cup") cups.sort(function(a, b) { return parseInt(b["SerId"]) - parseInt(a["SerId"]); }); for(prop in cups){ if (cups.hasOwnProperty(prop)) { selectOptions.push({text: cups[prop]["name"], data:{cup: cups[prop]["SerId"]}}) } } } else if(state === 1){ // opened for the second time -> select cat var cup // find the selected cup for(prop in cups){ if (cups.hasOwnProperty(prop) && cups[prop]['SerId'] === data.cup) { cup = cups[prop] } } if(cup === undefined){ // cup was not found return } selectTitle = cup['name'] + ": " + qsTr("select category") // build a list with all cat in the cup out of the cat keys (rkey) given in the cup.cats for(prop in cup['cats']){ if (cup['cats'].hasOwnProperty(prop)) { // search the rkey in the cat list for(var i = 0; i < control.widgetData["cats"].length; i ++ ){ if(control.widgetData["cats"][i]["rkey"] === cup["cats"][prop] && control.widgetData["cats"][i]["sex"] !== undefined){ // found it -> append it to the select list var catName = control.widgetData["cats"][i]["name"] // name of cat var catId = control.widgetData["cats"][i]["GrpId"] // id of cat selectOptions.push({text: catName, data:{cup: data.cup, cat: catId}}) } } } } } selector.appear(selectOptions, selectTitle) } 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) } function editFavorites(favorite, compId) { if(control.compFavorites.indexOf(compId) >= 0 && !favorite) { control.compFavorites.splice( control.compFavorites.indexOf(compId), 1) } else if(control.compFavorites.indexOf(compId) < 0 && favorite) { control.compFavorites.push(compId) } appSettings.write("compFavorites", JSON.stringify(control.compFavorites)) // trigger 'changed' signal control.compFavorites = control.compFavorites } function initFavorites() { if(appSettings.read("compFavorites") !== "false"){ //console.log(appSettings.read("displayedCompCats"+params.nation)) control.compFavorites = JSON.parse(appSettings.read("compFavorites")) } else { control.compFavorites = [] appSettings.write("compFavorites", JSON.stringify(control.compFavorites)) } // trigger 'changed' signal control.compFavorites = control.compFavorites console.log(control.compFavorites) } Connections { target: parent.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 } else if(data.cup !== undefined && data.cat === undefined){ control.openCup(1,data) } else if(data.cup !== undefined && data.cat !== undefined){ app.openWidget({cup: data.cup, cat: data.cat}) } } } header: Item { id: topSpacerItm width: parent.width height: 10 } footer: Item { id: bottomSpacerItm width: parent.width height: 10 } 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"] property bool thisIsFavored: control.compFavorites.indexOf(parseInt(thisData['WetId'])) >= 0 property bool includedByFavorites: control.displayedCompCats.indexOf(-1) >= 0 && thisIsFavored property bool includedByFilter: control.displayedCompCats.indexOf(parseInt(thisData['cat_id'])) >= 0 property bool thisIsVisible: includedByFavorites || includedByFilter function updateVisibility() { competitionDel.includedByFilter = control.displayedCompCats.indexOf(parseInt(competitionDel.thisData['cat_id'])) >= 0 competitionDel.thisIsFavored = control.compFavorites.indexOf(parseInt(thisData['WetId'])) >= 0 competitionDel.includedByFavorites = control.displayedCompCats.indexOf(-1) >= 0 && thisIsFavored } width: parent.width height: thisIsVisible ? compDelCol.height + 10 : 0 enabled: ((thisData["cats"] !== undefined && thisData["cats"].length > 0) || competitionDel.thisData["homepage"] !== undefined || getCompInfoUrl(index) !== undefined) && height > 0 //visible: includedByFilter opacity: 0 scale: 0.9 Connections { target: control onDisplayedCompCatsChanged: { competitionDel.updateVisibility() } onCompFavoritesChanged: { competitionDel.updateVisibility() } } onThisDataChanged: { if(thisIsVisible){ fadeInPa.start() } } onThisIsVisibleChanged: { if(thisIsVisible){ fadeInPa.start() } else { fadeOutPa.start() } } Behavior on height { NumberAnimation { duration: 400 } } 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 } } ParallelAnimation { id: fadeOutPa NumberAnimation { target: competitionDel; property: "opacity"; from: 1; to: 0; duration: 400 } NumberAnimation { target: competitionDel; property: "scale"; from: 1; to: 0.8; 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 RowLayout { width: parent.width Label { id: nameLa width: parent.width font.bold: true wrapMode: Text.WordWrap text: name Layout.fillWidth: true } ToolButton { id: bookmarkTb icon.name: competitionDel.thisIsFavored ? "pinFilled":"pin" onClicked: { control.editFavorites(!competitionDel.thisIsFavored, parseInt(thisData['WetId'])) } Layout.alignment: Layout.Right Behavior on icon.name { SequentialAnimation { NumberAnimation { property: "scale" target: bookmarkTb duration: 75 to: 0.8 } NumberAnimation { property: "scale" target: bookmarkTb duration: 75 to: 1 } } } } } Label { id: dateLa color: "grey" text: date } } Rectangle { id: bottomLineRa anchors { bottom: parent.bottom left: parent.left right: parent.right } height: 1 color: "lightgrey" } } section.property: "month" section.delegate: ItemDelegate { id: name background: Rectangle { color: "red" } width: parent.width text: section } 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 } } } }