// Copyright (c) 2020 Proton Technologies AG // // This file is part of ProtonMail Bridge. // // ProtonMail Bridge 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. // // ProtonMail Bridge 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 ProtonMail Bridge. If not, see . // input for date import QtQuick 2.8 import QtQuick.Controls 2.2 import ProtonUI 1.0 import ImportExportUI 1.0 Rectangle { id: root width : row.width + (root.label == "" ? 0 : textlabel.width) height : row.height color : Style.transparent property alias label : textlabel.text property string metricsLabel : root.label property var dropDownStyle : Style.dropDownLight // dates property date currentDate : new Date() // default now property date minDate : new Date(0) // default epoch start property date maxDate : new Date() // default now property bool isMaxDateToday : false property int unix : Math.floor(currentDate.getTime()/1000) onMinDateChanged: { if (isNaN(minDate.getTime()) || minDate.getTime() > maxDate.getTime()) { minDate = new Date(0) } //console.log(" minDate changed:", root.label, minDate.toDateString()) updateRange() } onMaxDateChanged: { if (isNaN(maxDate.getTime()) || minDate.getTime() > maxDate.getTime()) { maxDate = new Date() } //console.log(" maxDate changed:", root.label, maxDate.toDateString()) updateRange() } RoundedRectangle { id: background anchors.fill : row strokeColor : dropDownStyle.line strokeWidth : Style.dialog.borderInput fillColor : dropDownStyle.background radiusTopLeft : row.children[0].down && !row.children[0].below ? 0 : Style.dialog.radiusButton radiusBottomLeft : row.children[0].down && row.children[0].below ? 0 : Style.dialog.radiusButton radiusTopRight : row.children[row.children.length-1].down && !row.children[row.children.length-1].below ? 0 : Style.dialog.radiusButton radiusBottomRight : row.children[row.children.length-1].down && row.children[row.children.length-1].below ? 0 : Style.dialog.radiusButton } TextMetrics { id: textMetrics text: root.metricsLabel+"M" font: textlabel.font } Text { id: textlabel anchors { left : root.left verticalCenter : root.verticalCenter } font { pointSize: Style.dialog.fontSize * Style.pt bold: dropDownStyle.labelBold } color: dropDownStyle.text width: textMetrics.width verticalAlignment: Text.AlignVCenter } Row { id: row anchors { left : root.label=="" ? root.left : textlabel.right bottom : root.bottom } padding : Style.dialog.borderInput DateBox { id: monthInput placeholderText: qsTr("Month") enabled: !allDates model: gui.allMonths onActivated: updateRange() anchors.verticalCenter: parent.verticalCenter dropDownStyle: root.dropDownStyle onDownChanged: { if (root.isMaxDateToday){ root.maxDate = new Date() } } } Rectangle { width: Style.dialog.borderInput height: monthInput.height color: dropDownStyle.line anchors.verticalCenter: parent.verticalCenter } DateBox { id: dayInput placeholderText: qsTr("Day") enabled: !allDates model: gui.allDays onActivated: updateRange() anchors.verticalCenter: parent.verticalCenter dropDownStyle: root.dropDownStyle onDownChanged: { if (root.isMaxDateToday){ root.maxDate = new Date() } } } Rectangle { width: Style.dialog.borderInput height: monthInput.height color: dropDownStyle.line } DateBox { id: yearInput placeholderText: qsTr("Year") enabled: !allDates model: gui.allYears onActivated: updateRange() anchors.verticalCenter: parent.verticalCenter dropDownStyle: root.dropDownStyle onDownChanged: { if (root.isMaxDateToday){ root.maxDate = new Date() } } } } function setDate(d) { //console.trace() //console.log( " setDate ", label, d) if (isNaN(d = parseInt(d))) return var newUnix = Math.min(maxDate.getTime(), d*1000) // seconds to ms newUnix = Math.max(minDate.getTime(), newUnix) root.updateRange(new Date(newUnix)) //console.log( " set ", currentDate.getTime()) } function updateRange(curr) { if (curr === undefined || isNaN(curr.getTime())) curr = root.getCurrentDate() //console.log( " update", label, curr, curr.getTime()) //console.trace() if (isNaN(curr.getTime())) return // shouldn't happen // full system date range var firstYear = parseInt(gui.allYears[0]) var firstDay = parseInt(gui.allDays[0]) if ( isNaN(firstYear) || isNaN(firstDay) ) return // get minimal and maximal available year, month, day // NOTE: The order is important!!! var minYear = minDate.getFullYear() var maxYear = maxDate.getFullYear() var minMonth = (curr.getFullYear() == minYear ? minDate.getMonth() : 0 ) var maxMonth = (curr.getFullYear() == maxYear ? maxDate.getMonth() : 11 ) var minDay = ( curr.getFullYear() == minYear && curr.getMonth() == minMonth ? minDate.getDate() : firstDay ) var maxDay = ( curr.getFullYear() == maxYear && curr.getMonth() == maxMonth ? maxDate.getDate() : gui.daysInMonth(curr.getFullYear(), curr.getMonth()+1) ) //console.log("update ranges: ", root.label, minYear, maxYear, minMonth+1, maxMonth+1, minDay, maxDay) //console.log("update indexes: ", root.label, firstYear-minYear, firstYear-maxYear, minMonth, maxMonth, minDay-firstDay, maxDay-firstDay) yearInput.filterItems(firstYear-maxYear, firstYear-minYear) monthInput.filterItems(minMonth,maxMonth) // getMonth() is index not a month (i.e. Jan==0) dayInput.filterItems(minDay-1,maxDay-1) // keep ordering from model not from filter yearInput .currentIndex = firstYear - curr.getFullYear() monthInput .currentIndex = curr.getMonth() // getMonth() is index not a month (i.e. Jan==0) dayInput .currentIndex = curr.getDate()-firstDay /* console.log( "update current indexes: ", root.label, curr.getFullYear() , '->' , yearInput.currentIndex , gui.allMonths[curr.getMonth()] , '->' , monthInput.currentIndex , curr.getDate() , '->' , dayInput.currentIndex ) */ // test if current date changed if ( yearInput.currentText == root.currentDate.getFullYear() && monthInput.currentText == root.currentDate.toLocaleString(gui.locale, "MMM") && dayInput.currentText == gui.prependZeros(root.currentDate.getDate(),2) ) { //console.log(" currentDate NOT changed", label, root.currentDate.toDateString()) return } root.currentDate = root.getCurrentDate() // console.log(" currentDate changed", label, root.currentDate.toDateString()) } // get current date from selected function getCurrentDate() { if (isNaN(root.currentDate.getTime())) { // wrong current ? console.log("!WARNING! Wrong current date format", root.currentDate) root.currentDate = new Date(0) } var currentString = "" var currentUnix = root.currentDate.getTime() if ( yearInput.currentText != "" && yearInput.currentText != yearInput.placeholderText && monthInput.currentText != "" && monthInput.currentText != monthInput.placeholderText ) { var day = gui.daysInMonth(yearInput.currentText, monthInput.currentText) if (!isNaN(parseInt(dayInput.currentText))) { day = Math.min(day, parseInt(dayInput.currentText)) } var month = gui.allMonths.indexOf(monthInput.currentText) var year = parseInt(yearInput.currentText) var pickedDate = new Date(year, month, day) // Compensate automatic DST in windows if (pickedDate.getDate() != day) { pickedDate.setTime(pickedDate.getTime() + 60*60*1000) // add hour } currentUnix = pickedDate.getTime() } return new Date(Math.max( minDate.getTime(), Math.min(maxDate.getTime(), currentUnix) )) } }