fix(StatusDateRangePicker): use StatusDatePicker for the range selection
- exchange the direct input with a calendar popup - extend the validation of the range (so that from < to === true, etc) - remove direct input components (Status[Base]DateInput.qml) Fixes #10900
This commit is contained in:
parent
a0146014d1
commit
274fc98839
|
@ -16,23 +16,17 @@ SplitView {
|
||||||
SplitView.fillWidth: true
|
SplitView.fillWidth: true
|
||||||
SplitView.fillHeight: true
|
SplitView.fillHeight: true
|
||||||
|
|
||||||
|
|
||||||
StatusButton {
|
StatusButton {
|
||||||
anchors.top: parent.top
|
anchors.centerIn: parent
|
||||||
anchors.topMargin: 100
|
text: "Launch popup"
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
text: "Launch popoup"
|
|
||||||
onClicked: dialog.open()
|
onClicked: dialog.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusDateRangePicker {
|
StatusDateRangePicker {
|
||||||
id: dialog
|
id: dialog
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
width: 440
|
destroyOnClose: false
|
||||||
height: 300
|
fromTimestamp: new Date().setDate(new Date().getDate() - 7) // 7 days ago
|
||||||
fromTimestamp: new Date().setDate(new Date().getDate() - 7)
|
|
||||||
toTimestamp: Date.now()
|
|
||||||
supportedStartYear: 1900
|
|
||||||
onNewRangeSet: {
|
onNewRangeSet: {
|
||||||
console.warn(" from timeStamp = ", new Date(fromTimestamp).toISOString())
|
console.warn(" from timeStamp = ", new Date(fromTimestamp).toISOString())
|
||||||
console.warn(" to timeStamp = ", new Date(toTimestamp).toISOString())
|
console.warn(" to timeStamp = ", new Date(toTimestamp).toISOString())
|
||||||
|
@ -40,6 +34,5 @@ SplitView {
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: dialog.open()
|
Component.onCompleted: dialog.open()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,313 +0,0 @@
|
||||||
import QtQuick 2.15
|
|
||||||
import QtQuick.Layouts 1.12
|
|
||||||
import QtQuick.Controls 2.15
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
|
|
||||||
import "./private/dateInput"
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmltype StatusDateInput
|
|
||||||
\inherits Control
|
|
||||||
\inqmlmodule StatusQ.Components
|
|
||||||
\since StatusQ.Components 0.1
|
|
||||||
\brief It allows entering a date string in dd/mm/yyyy format
|
|
||||||
|
|
||||||
Example of how to use it:
|
|
||||||
|
|
||||||
\qml
|
|
||||||
StatusDateInput {
|
|
||||||
datePlaceholderText: qsTr("dd")
|
|
||||||
monthPlaceholderText: qsTr("mm")
|
|
||||||
yearPlaceholderText: qsTr("yyyy")
|
|
||||||
presetTimestamp: fromTimestamp
|
|
||||||
}
|
|
||||||
\endqml
|
|
||||||
|
|
||||||
For a list of components available see StatusQ.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Control {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmlproperty string StatusDateInput::datePlaceholderText
|
|
||||||
This property sets the placeholder text for the date input
|
|
||||||
*/
|
|
||||||
property string datePlaceholderText
|
|
||||||
/*!
|
|
||||||
\qmlproperty string StatusDateInput::monthPlaceholderText
|
|
||||||
This property sets the placeholder text for the month input
|
|
||||||
*/
|
|
||||||
property string monthPlaceholderText
|
|
||||||
/*!
|
|
||||||
\qmlproperty string StatusDateInput::yearPlaceholderText
|
|
||||||
This property sets the placeholder text for the year input
|
|
||||||
*/
|
|
||||||
property string yearPlaceholderText
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmlproperty string StatusDateInput::nowText
|
|
||||||
This property holds the now text to be shown on the widget
|
|
||||||
*/
|
|
||||||
property string nowText
|
|
||||||
/*!
|
|
||||||
\qmlproperty double StatusDateInput::presetTimestamp
|
|
||||||
This property holds the timestamp chosen before entering the popup
|
|
||||||
*/
|
|
||||||
property double presetTimestamp: Date.now()
|
|
||||||
/*!
|
|
||||||
\qmlproperty bool StatusDateInput::isEditMode
|
|
||||||
This property can turn and off the edit mode for the input
|
|
||||||
*/
|
|
||||||
property bool isEditMode: false
|
|
||||||
/*!
|
|
||||||
\qmlproperty bool StatusDateInput::showBackground
|
|
||||||
This property helps turning of the background of the input
|
|
||||||
*/
|
|
||||||
property bool showBackground: true
|
|
||||||
/*!
|
|
||||||
\qmlproperty var StatusDateInput::newDate
|
|
||||||
Represents the newly set date in the input
|
|
||||||
*/
|
|
||||||
property var newDate
|
|
||||||
/*!
|
|
||||||
\qmlproperty string StatusDateInput::errorMessage
|
|
||||||
This property to assign errorMessage for the date input
|
|
||||||
*/
|
|
||||||
property string errorMessage
|
|
||||||
/*!
|
|
||||||
\qmlproperty bool StatusDateInput::valid
|
|
||||||
This property exposes if the input has a valid date
|
|
||||||
*/
|
|
||||||
readonly property bool valid: inputLoader1.item.acceptableInput && inputLoader2.item.acceptableInput && inputLoader3.item.acceptableInput
|
|
||||||
/*!
|
|
||||||
\qmlproperty bool StatusDateInput::hasChange
|
|
||||||
This property exposes if the input has been modified by user
|
|
||||||
*/
|
|
||||||
readonly property bool hasChange: d.presetDate.valueOf() !== newDate.valueOf()
|
|
||||||
/*!
|
|
||||||
\qmlproperty bool StatusDateInput::supportedStartYear
|
|
||||||
This property helps set the sypported start year for the input
|
|
||||||
*/
|
|
||||||
property int supportedStartYear: 0
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmlmethod
|
|
||||||
This function resets the input's text
|
|
||||||
*/
|
|
||||||
function reset() {
|
|
||||||
d.presetDate = d.getDateWithoutTime(presetTimestamp)
|
|
||||||
}
|
|
||||||
/*!
|
|
||||||
\qmlmethod
|
|
||||||
This function sets the active focus to edit date
|
|
||||||
*/
|
|
||||||
function forceActiveFocus() {
|
|
||||||
inputLoader1.item.forceActiveFocus()
|
|
||||||
inputLoader1.item.cursorPosition = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
id: d
|
|
||||||
readonly property string separator: "/"
|
|
||||||
readonly property string space: " "
|
|
||||||
readonly property string dateId: "d"
|
|
||||||
readonly property string monthId: "m"
|
|
||||||
readonly property string yearId: "y"
|
|
||||||
readonly property bool hasActiveFocus: inputLoader1.item.activeFocus || inputLoader2.item.activeFocus || inputLoader3.item.activeFocus
|
|
||||||
readonly property bool isCurrentTimestamp: getDateWithoutTime(Date.now().valueOf()).valueOf() === newDate.valueOf()
|
|
||||||
property var presetDate: d.getDateWithoutTime(presetTimestamp)
|
|
||||||
readonly property bool showError: (!inputLoader1.item.acceptableInput && !!inputLoader1.item.text) || (!inputLoader2.item.acceptableInput && !!inputLoader2.item.text) || (!inputLoader3.item.acceptableInput && !!inputLoader3.item.text)
|
|
||||||
readonly property var dateTimeFormat: Qt.locale().dateTimeFormat(Locale.ShortFormat).split(space)[0].toLowerCase().split(separator)
|
|
||||||
|
|
||||||
function setNewDate() {
|
|
||||||
if (!!inputLoader1.item && !!inputLoader2.item && !!inputLoader3.item) {
|
|
||||||
newDate = new Date(getDateString(yearId), getDateString(monthId), getDateString(dateId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDateWithoutTime(timeStamp) {
|
|
||||||
let d = new Date(timeStamp)
|
|
||||||
d.setHours(0, 0, 0, 0)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearAll() {
|
|
||||||
if(!!inputLoader1.item.selectedText)
|
|
||||||
inputLoader1.item.clear()
|
|
||||||
if(!!inputLoader2.item.selectedText)
|
|
||||||
inputLoader2.item.clear()
|
|
||||||
if(!!inputLoader3.item.selectedText)
|
|
||||||
inputLoader3.item.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectAll() {
|
|
||||||
inputLoader1.item.selectAll()
|
|
||||||
inputLoader2.item.selectAll()
|
|
||||||
inputLoader3.item.selectAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getComponent(itemPos) {
|
|
||||||
return d.dateTimeFormat[(itemPos)].startsWith(yearId) ? editYear : d.dateTimeFormat[(itemPos)].startsWith(monthId) ? editMonth: editDate
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDateString(identifier) {
|
|
||||||
return dateTimeFormat[0].startsWith(identifier) ? inputLoader1.item.text : dateTimeFormat[1].startsWith(identifier) ? inputLoader2.item.text: inputLoader3.item.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
implicitHeight: 44
|
|
||||||
implicitWidth: 135
|
|
||||||
leftPadding: 12
|
|
||||||
rightPadding: 12
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
color: root.showBackground ? Theme.palette.baseColor2: Theme.palette.transparent
|
|
||||||
radius: 8
|
|
||||||
clip: true
|
|
||||||
border.width: 1
|
|
||||||
border.color: {
|
|
||||||
if (!root.showBackground) {
|
|
||||||
return Theme.palette.transparent
|
|
||||||
}
|
|
||||||
if (d.showError) {
|
|
||||||
return Theme.palette.dangerColor1
|
|
||||||
}
|
|
||||||
if (d.hasActiveFocus) {
|
|
||||||
return Theme.palette.primaryColor1
|
|
||||||
}
|
|
||||||
return hoverHandler.hovered ? Theme.palette.primaryColor2 : Theme.palette.transparent
|
|
||||||
}
|
|
||||||
HoverHandler { id: hoverHandler }
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: ColumnLayout {
|
|
||||||
id: mainLayout
|
|
||||||
spacing: 11
|
|
||||||
RowLayout {
|
|
||||||
spacing: 3
|
|
||||||
StatusBaseText {
|
|
||||||
id: nowInput
|
|
||||||
Layout.fillWidth: true
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
font.pixelSize: 15
|
|
||||||
text: nowText
|
|
||||||
visible: d.isCurrentTimestamp && !isEditMode && !!nowInput.text
|
|
||||||
}
|
|
||||||
Loader {
|
|
||||||
id: inputLoader1
|
|
||||||
Layout.preferredWidth: Math.max(item.contentWidth, item.placeholder.contentWidth)
|
|
||||||
Layout.preferredHeight: root.height
|
|
||||||
sourceComponent: d.getComponent(0)
|
|
||||||
onLoaded: {
|
|
||||||
d.setNewDate()
|
|
||||||
item.tabNavItem = inputLoader2.item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
lineHeightMode: Text.FixedHeight
|
|
||||||
lineHeight: 22
|
|
||||||
text: d.separator
|
|
||||||
visible: !nowInput.visible
|
|
||||||
}
|
|
||||||
Loader {
|
|
||||||
id: inputLoader2
|
|
||||||
Layout.preferredWidth: Math.max(item.contentWidth, item.placeholder.contentWidth)
|
|
||||||
Layout.preferredHeight: root.height
|
|
||||||
sourceComponent: d.getComponent(1)
|
|
||||||
onLoaded: {
|
|
||||||
d.setNewDate()
|
|
||||||
item.tabNavItem = inputLoader3.item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
lineHeightMode: Text.FixedHeight
|
|
||||||
lineHeight: 22
|
|
||||||
text: d.separator
|
|
||||||
visible: !nowInput.visible
|
|
||||||
}
|
|
||||||
Loader {
|
|
||||||
id: inputLoader3
|
|
||||||
Layout.preferredWidth: Math.max(item.contentWidth, item.placeholder.contentWidth)
|
|
||||||
Layout.preferredHeight: root.height
|
|
||||||
sourceComponent: d.getComponent(2)
|
|
||||||
onLoaded: {
|
|
||||||
d.setNewDate()
|
|
||||||
item.tabNavItem = inputLoader1.item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StatusBaseText {
|
|
||||||
Layout.maximumWidth: root.width
|
|
||||||
Layout.rightMargin: -root.rightPadding
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
font.pixelSize: 12
|
|
||||||
color: Theme.palette.dangerColor1
|
|
||||||
lineHeightMode: Text.FixedHeight
|
|
||||||
lineHeight: 16
|
|
||||||
elide: Text.ElideRight
|
|
||||||
text: errorMessage
|
|
||||||
visible: d.showError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: editDate
|
|
||||||
StatusBaseDateInput {
|
|
||||||
maximumLength: 2
|
|
||||||
placeholderText: root.datePlaceholderText
|
|
||||||
text: ('0' + d.presetDate.getDate()).slice(-2)
|
|
||||||
onTextChanged: d.setNewDate()
|
|
||||||
visible: !nowInput.visible
|
|
||||||
|
|
||||||
validator: IntValidator { bottom: 1; top: {
|
|
||||||
let tempDate = newDate
|
|
||||||
tempDate.setDate(0)
|
|
||||||
return tempDate.getDate() }
|
|
||||||
}
|
|
||||||
|
|
||||||
onTrippleTap: d.selectAll()
|
|
||||||
onClearEvent: d.clearAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: editMonth
|
|
||||||
StatusBaseDateInput {
|
|
||||||
maximumLength: 2
|
|
||||||
placeholderText: root.monthPlaceholderText
|
|
||||||
text: ('0' + d.presetDate.getMonth()).slice(-2)
|
|
||||||
onTextChanged: d.setNewDate()
|
|
||||||
visible: !nowInput.visible
|
|
||||||
|
|
||||||
validator: IntValidator { bottom: 1; top: 12 }
|
|
||||||
|
|
||||||
onTrippleTap: d.selectAll()
|
|
||||||
onClearEvent: d.clearAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: editYear
|
|
||||||
StatusBaseDateInput {
|
|
||||||
maximumLength: 4
|
|
||||||
placeholderText: root.yearPlaceholderText
|
|
||||||
text: d.presetDate.getFullYear()
|
|
||||||
onTextChanged: d.setNewDate()
|
|
||||||
visible: !nowInput.visible
|
|
||||||
|
|
||||||
validator: IntValidator { bottom: supportedStartYear; top: new Date().getFullYear() }
|
|
||||||
|
|
||||||
onTrippleTap: d.selectAll()
|
|
||||||
onClearEvent: d.clearAll()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -54,6 +54,8 @@ StatusComboBox {
|
||||||
*/
|
*/
|
||||||
property string customTodayText: qsTr("Today")
|
property string customTodayText: qsTr("Today")
|
||||||
|
|
||||||
|
readonly property alias isTodaySelected: d.isTodaySelected
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: d
|
id: d
|
||||||
property date selectedDate: new Date()
|
property date selectedDate: new Date()
|
||||||
|
@ -71,12 +73,13 @@ StatusComboBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitHeight: 44
|
|
||||||
|
|
||||||
indicatorIcon: "calendar"
|
indicatorIcon: "calendar"
|
||||||
control.delegate: null
|
control.delegate: null
|
||||||
control.displayText: d.isTodaySelected && root.customTodayText ? root.customTodayText
|
control.displayText: d.isTodaySelected && root.customTodayText ? root.customTodayText
|
||||||
: LocaleUtils.formatDate(d.selectedDate, root.dateFormat)
|
: LocaleUtils.formatDate(d.selectedDate, root.dateFormat)
|
||||||
|
control.implicitHeight: 44
|
||||||
|
control.padding: 12
|
||||||
|
control.leftPadding: 16
|
||||||
control.popup.horizontalPadding: 16
|
control.popup.horizontalPadding: 16
|
||||||
control.popup.verticalPadding: 16
|
control.popup.verticalPadding: 16
|
||||||
control.popup.width: 340
|
control.popup.width: 340
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
import QtQuick 2.15
|
|
||||||
|
|
||||||
import StatusQ.Core 0.1
|
|
||||||
import StatusQ.Core.Theme 0.1
|
|
||||||
import StatusQ.Components 0.1
|
|
||||||
|
|
||||||
TextInput {
|
|
||||||
id: root
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmlproperty var StatusBaseDateInput::placeholderText
|
|
||||||
This property sets the placeholderText for input
|
|
||||||
*/
|
|
||||||
property alias placeholderText: placeholder.text
|
|
||||||
/*!
|
|
||||||
\qmlproperty var StatusBaseDateInput::placeholder
|
|
||||||
This property exposes the placeholder for customisation
|
|
||||||
*/
|
|
||||||
property alias placeholder: placeholder
|
|
||||||
/*!
|
|
||||||
\qmlproperty var StatusBaseDateInput::tabNavItem
|
|
||||||
This property sets the tab key navigation item.
|
|
||||||
*/
|
|
||||||
property var tabNavItem: null
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\qmlsignal
|
|
||||||
This signal when the input is tapped 3 times
|
|
||||||
*/
|
|
||||||
signal trippleTap()
|
|
||||||
/*!
|
|
||||||
\qmlsignal
|
|
||||||
This signal is emitted when backspace is hit
|
|
||||||
*/
|
|
||||||
signal clearEvent()
|
|
||||||
|
|
||||||
verticalAlignment: TextInput.AlignVCenter
|
|
||||||
horizontalAlignment: TextInput.AlignHCenter
|
|
||||||
|
|
||||||
selectByMouse: false
|
|
||||||
activeFocusOnPress: false
|
|
||||||
persistentSelection: true
|
|
||||||
|
|
||||||
font.pixelSize: 15
|
|
||||||
font.family: Theme.palette.baseFont.name
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
selectedTextColor: color
|
|
||||||
selectionColor: Theme.palette.primaryColor2
|
|
||||||
|
|
||||||
KeyNavigation.priority: !!root.tabNavItem ? KeyNavigation.BeforeItem : KeyNavigation.AfterItem
|
|
||||||
KeyNavigation.tab: root.tabNavItem
|
|
||||||
Keys.onPressed: {
|
|
||||||
switch(event.key) {
|
|
||||||
case Qt.Key_Backspace:
|
|
||||||
return root.clearEvent()
|
|
||||||
|
|
||||||
case Qt.Key_Space:
|
|
||||||
return root.tabNavItem.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cursorDelegate: StatusCursorDelegate {
|
|
||||||
cursorVisible: root.cursorVisible
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
id: mouseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.leftMargin: -5
|
|
||||||
anchors.rightMargin: -5
|
|
||||||
drag.target: dragItem
|
|
||||||
drag.axis: Drag.XAxis
|
|
||||||
onClicked: {
|
|
||||||
root.forceActiveFocus()
|
|
||||||
root.cursorPosition = root.positionAt(mouse.x,mouse.y)
|
|
||||||
}
|
|
||||||
onDoubleClicked: root.selectAll()
|
|
||||||
TapHandler {
|
|
||||||
acceptedButtons: Qt.AllButtons
|
|
||||||
onTapped: if (tapCount == 3) { root.trippleTap() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusBaseText {
|
|
||||||
id: placeholder
|
|
||||||
anchors.centerIn: parent
|
|
||||||
verticalAlignment: parent.verticalAlignment
|
|
||||||
horizontalAlignment: parent.horizontalAlignment
|
|
||||||
font.pixelSize: 15
|
|
||||||
text: root.placeholderText
|
|
||||||
wrapMode: Text.NoWrap
|
|
||||||
elide: Text.ElideRight
|
|
||||||
color: Theme.palette.baseColor1
|
|
||||||
visible: (root.length === 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
DropArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onEntered: {
|
|
||||||
root.forceActiveFocus()
|
|
||||||
root.cursorPosition = root.positionAt(drag.x,drag.y)
|
|
||||||
}
|
|
||||||
drag.onXChanged: {
|
|
||||||
root.moveCursorSelection(root.positionAt(drag.x,drag.y), root.mouseSelectionMode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: dragItem
|
|
||||||
width: 1
|
|
||||||
height: 5
|
|
||||||
Drag.active: mouseArea.drag.active
|
|
||||||
Drag.hotSpot.x: dragItem.width / 2
|
|
||||||
Drag.hotSpot.y: dragItem.height / 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -63,4 +63,3 @@ StatusSyncDeviceDelegate 0.1 StatusSyncDeviceDelegate.qml
|
||||||
StatusOnlineBadge 0.1 StatusOnlineBadge.qml
|
StatusOnlineBadge 0.1 StatusOnlineBadge.qml
|
||||||
StatusGroupBox 0.1 StatusGroupBox.qml
|
StatusGroupBox 0.1 StatusGroupBox.qml
|
||||||
StatusPageIndicator 0.1 StatusPageIndicator.qml
|
StatusPageIndicator 0.1 StatusPageIndicator.qml
|
||||||
StatusDateInput 0.1 StatusDateInput.qml
|
|
||||||
|
|
|
@ -219,7 +219,5 @@
|
||||||
<file>StatusQ/Core/Utils/ModelChangeGuard.qml</file>
|
<file>StatusQ/Core/Utils/ModelChangeGuard.qml</file>
|
||||||
<file>StatusQ/Core/Utils/StackViewStates.qml</file>
|
<file>StatusQ/Core/Utils/StackViewStates.qml</file>
|
||||||
<file>StatusQ/Controls/StatusBlockProgressBar.qml</file>
|
<file>StatusQ/Controls/StatusBlockProgressBar.qml</file>
|
||||||
<file>StatusQ/Components/StatusDateInput.qml</file>
|
|
||||||
<file>StatusQ/Components/private/dateInput/StatusBaseDateInput.qml</file>
|
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.15
|
||||||
import QtQml.Models 2.15
|
import QtQml.Models 2.15
|
||||||
import QtQuick.Controls 2.15
|
|
||||||
|
|
||||||
import StatusQ.Core.Theme 0.1
|
import StatusQ.Core.Theme 0.1
|
||||||
import StatusQ.Core 0.1
|
import StatusQ.Core 0.1
|
||||||
|
@ -14,94 +13,95 @@ StatusDialog {
|
||||||
|
|
||||||
property double fromTimestamp: Date.now()
|
property double fromTimestamp: Date.now()
|
||||||
property double toTimestamp: Date.now()
|
property double toTimestamp: Date.now()
|
||||||
property int supportedStartYear
|
|
||||||
|
|
||||||
signal newRangeSet(double fromTimestamp, double toTimestamp)
|
signal newRangeSet(double fromTimestamp, double toTimestamp)
|
||||||
|
|
||||||
onOpened: fromInput.forceActiveFocus()
|
|
||||||
|
|
||||||
topPadding: 0
|
|
||||||
title: qsTr("Filter activity by period")
|
title: qsTr("Filter activity by period")
|
||||||
|
|
||||||
contentItem: RowLayout {
|
QtObject {
|
||||||
spacing: 20
|
id: d
|
||||||
|
|
||||||
// From Date
|
function getFromTimestampUTC(date) {
|
||||||
ColumnLayout {
|
date.setHours(0, 0, 0, 0)
|
||||||
spacing: 8
|
return date.valueOf()
|
||||||
StatusBaseText {
|
|
||||||
height: visible ? contentHeight : 0
|
|
||||||
elide: Text.ElideRight
|
|
||||||
text: qsTr("From")
|
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
}
|
|
||||||
StatusDateInput {
|
|
||||||
id: fromInput
|
|
||||||
datePlaceholderText: qsTr("dd")
|
|
||||||
monthPlaceholderText: qsTr("mm")
|
|
||||||
yearPlaceholderText: qsTr("yyyy")
|
|
||||||
presetTimestamp: fromTimestamp
|
|
||||||
errorMessage: qsTr("Invalid range")
|
|
||||||
supportedStartYear: root.supportedStartYear
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// To Date
|
function getToTimestampUTC(date) {
|
||||||
ColumnLayout {
|
date.setDate(date.getDate() + 1) // next day...
|
||||||
Layout.preferredWidth: toInput.width
|
date.setHours(0, 0, 0, -1) // ... but just 1ms before midnight -> whole day included
|
||||||
spacing: 8
|
return date.valueOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Item {
|
||||||
|
GridLayout {
|
||||||
|
width: parent.width
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
columns: 3
|
||||||
|
columnSpacing: 16
|
||||||
|
rowSpacing: 8
|
||||||
|
|
||||||
|
StatusBaseText {
|
||||||
|
text: qsTr("From")
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.preferredWidth: parent.width
|
Layout.fillWidth: true
|
||||||
StatusBaseText {
|
StatusBaseText {
|
||||||
Layout.alignment: Qt.AlignLeft
|
|
||||||
height: visible ? contentHeight : 0
|
|
||||||
elide: Text.ElideRight
|
|
||||||
text: qsTr("To")
|
text: qsTr("To")
|
||||||
font.pixelSize: 15
|
|
||||||
color: Theme.palette.directColor1
|
|
||||||
}
|
}
|
||||||
StatusButton {
|
Item { Layout.fillWidth: true }
|
||||||
Layout.alignment: Qt.AlignRight
|
StatusFlatButton {
|
||||||
horizontalPadding: 0
|
horizontalPadding: 0
|
||||||
verticalPadding: 0
|
verticalPadding: 0
|
||||||
spacing: 0
|
|
||||||
normalColor: Theme.palette.transparent
|
|
||||||
hoverColor: Theme.palette.transparent
|
hoverColor: Theme.palette.transparent
|
||||||
font.weight: Font.Normal
|
text: qsTr("Now")
|
||||||
text: toInput.isEditMode ? qsTr("Now") : qsTr("Edit")
|
enabled: !toInput.isTodaySelected
|
||||||
onClicked: {
|
onClicked: toInput.selectedDate = new Date()
|
||||||
if(toInput.isEditMode)
|
|
||||||
root.toTimestamp = Date.now()
|
|
||||||
toInput.isEditMode = !toInput.isEditMode
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StatusDateInput {
|
|
||||||
id: toInput
|
|
||||||
datePlaceholderText: qsTr("dd")
|
|
||||||
monthPlaceholderText: qsTr("mm")
|
|
||||||
yearPlaceholderText: qsTr("yyyy")
|
|
||||||
presetTimestamp: toTimestamp
|
|
||||||
nowText: qsTr("Now")
|
|
||||||
errorMessage: qsTr("Invalid range")
|
|
||||||
supportedStartYear: root.supportedStartYear
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusButton {
|
StatusDatePicker {
|
||||||
Layout.preferredHeight: fromInput.height
|
Layout.alignment: Qt.AlignTop
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.row: 1
|
||||||
Layout.topMargin: 28
|
Layout.preferredWidth: 168
|
||||||
text: qsTr("Reset")
|
readonly property bool hasChange: selectedDate.valueOf() !== root.fromTimestamp
|
||||||
enabled: fromInput.hasChange || toInput.hasChange
|
id: fromInput
|
||||||
normalColor: Theme.palette.transparent
|
selectedDate: new Date(fromTimestamp)
|
||||||
borderColor: Theme.palette.baseColor2
|
customTodayText: qsTr("Now")
|
||||||
hoverColor: Theme.palette.primaryColor3
|
validationError: {
|
||||||
onClicked: {
|
if (selectedDate.valueOf() > toInput.selectedDate.valueOf() && !toInput.isTodaySelected) // from > to; today in both is fine
|
||||||
toInput.isEditMode = false
|
return qsTr("'From' can't be later than 'To'")
|
||||||
fromInput.reset()
|
|
||||||
toInput.reset()
|
if (selectedDate.valueOf() > new Date()) // from > now
|
||||||
|
return qsTr("Can't set date to future")
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusDatePicker {
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.preferredWidth: 168
|
||||||
|
readonly property bool hasChange: selectedDate.valueOf() !== root.toTimestamp
|
||||||
|
id: toInput
|
||||||
|
selectedDate: new Date(toTimestamp)
|
||||||
|
customTodayText: qsTr("Now")
|
||||||
|
validationError: selectedDate.valueOf() > new Date() // to > now
|
||||||
|
? qsTr("Can't set date to future") : ""
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusButton {
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.preferredHeight: toInput.control.height
|
||||||
|
text: qsTr("Reset")
|
||||||
|
enabled: fromInput.hasChange || toInput.hasChange
|
||||||
|
normalColor: Theme.palette.transparent
|
||||||
|
borderColor: Theme.palette.baseColor2
|
||||||
|
onClicked: {
|
||||||
|
fromInput.selectedDate = new Date(root.fromTimestamp)
|
||||||
|
toInput.selectedDate = new Date(root.toTimestamp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,11 @@ StatusDialog {
|
||||||
rightButtons: ObjectModel {
|
rightButtons: ObjectModel {
|
||||||
StatusButton {
|
StatusButton {
|
||||||
text: qsTr("Apply")
|
text: qsTr("Apply")
|
||||||
enabled: fromInput.valid && toInput.valid && (fromInput.hasChange || toInput.hasChange)
|
enabled: !fromInput.validationError && !toInput.validationError && (fromInput.hasChange || toInput.hasChange)
|
||||||
onClicked: {
|
onClicked: {
|
||||||
root.newRangeSet(fromInput.newDate.valueOf(), toInput.newDate.valueOf())
|
root.newRangeSet(d.getFromTimestampUTC(fromInput.selectedDate),
|
||||||
|
toInput.isTodaySelected ? new Date().valueOf() // now means now, including the time today
|
||||||
|
: d.getToTimestampUTC(toInput.selectedDate))
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue