Commit 102ca6a3 authored by Volker Krause's avatar Volker Krause
Browse files

Add a copy of the Kirigami Addons date and time module

With that still not officially released that seems like the only reliable
way to depend on this for 22.08 unconditionally.
parent 8df0555e
# SPDX-FileCopyrightText: 2019 David Edmundson <kde@davidedmundson.co.uk>
# SPDX-License-Identifier: BSD-2-Clause
if (ANDROID)
add_library(KF5KirigamiDateAndTime)
add_library(KF5::KirigamiDateAndTime ALIAS KF5KirigamiDateAndTime)
target_sources(KF5KirigamiDateAndTime PRIVATE
lib/androidintegration.cpp
)
generate_export_header(KF5KirigamiDateAndTime BASE_NAME KirigamiDateAndTime)
target_link_libraries(KF5KirigamiDateAndTime PUBLIC Qt${QT_MAJOR_VERSION}::Core Qt${QT_MAJOR_VERSION}::AndroidExtras)
add_subdirectory(android)
install(TARGETS KF5KirigamiDateAndTime ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
endif()
ecm_add_qml_module(dateandtimeplugin URI "org.kde.kirigamiaddons.dateandtime" VERSION 0.1)
target_compile_definitions(dateandtimeplugin PRIVATE -DTRANSLATION_DOMAIN=\"kirigami_dateandtime\")
target_sources(dateandtimeplugin PRIVATE
lib/yearmodel.cpp
lib/monthmodel.cpp
lib/plugin.cpp
lib/timeinputvalidator.cpp
lib/qdatetimeparser.cpp
lib/infinitecalendarviewmodel.cpp
)
ecm_target_qml_sources(dateandtimeplugin SOURCES
ClockElement.qml
ClockFace.qml
DateInput.qml
DatePicker.qml
DatePopup.qml
DesktopDateInput.qml
MobileDateInput.qml
Hand.qml
TimeLabel.qml
TimePicker.qml
TimeInput.qml
)
target_link_libraries(dateandtimeplugin
Qt${QT_MAJOR_VERSION}::Quick
Qt${QT_MAJOR_VERSION}::Qml
KF5::I18n
)
if (TARGET KF5KirigamiDateAndTime)
target_link_libraries(dateandtimeplugin KF5KirigamiDateAndTime)
endif()
ecm_finalize_qml_module(dateandtimeplugin DESTINATION ${KDE_INSTALL_QMLDIR})
/*
* SPDX-FileCopyrightText: 2019 Dimitris Kardarakos <dimkard@posteo.net>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.12
import QtQuick.Controls 2.5 as Controls2
import org.kde.kirigami 2.0 as Kirigami
import QtQuick.Layouts 1.11
Controls2.ToolButton {
id: hoursButton
property int selectedValue
property string type
checkable: true
checked: index == selectedValue
autoExclusive: true
text: index == selectedValue ? ( (type == "hours" && index == 0) ? 12 : index )
: ( (type == "hours") ? ( index == 0 ? 12 : ( (index % 3 == 0) ? index : ".") ) : (index % 15 == 0) ? index : ".")
contentItem: Controls2.Label {
text: hoursButton.text
color: index <= parent.selectedValue ? Kirigami.Theme.activeTextColor : Kirigami.Theme.textColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
implicitHeight: Kirigami.Units.gridUnit
implicitWidth: height
radius: width*0.5
color: parent.checked ? Kirigami.Theme.buttonBackgroundColor : "transparent"
}
}
/*
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
Item {
id: clock
property date time
property bool showSecondsHand: false
property int _hours
property int _minutes
property int _seconds
onTimeChanged: {
_hours = time.getHours();
_minutes = time.getMinutes();
_seconds = time.getSeconds();
}
PlasmaCore.Svg {
id: clockSvg
imagePath: "widgets/clock"
}
PlasmaCore.SvgItem {
id: face
anchors.centerIn: parent
width: Math.min(parent.width, parent.height)
height: Math.min(parent.width, parent.height)
svg: clockSvg
elementId: "ClockFace"
}
Hand {
anchors.topMargin: 3
elementId: "HourHandShdow"
rotation: 180 + _hours * 30 + (_minutes/2)
svgScale: face.width / face.naturalSize.width
}
Hand {
elementId: "HourHand"
rotation: 180 + _hours * 30 + (_minutes/2)
svgScale: face.width / face.naturalSize.width
}
Hand {
anchors.topMargin: 3
elementId: "MinuteHandShadow"
rotation: 180 + _minutes * 6
svgScale: face.width / face.naturalSize.width
}
Hand {
elementId: "MinuteHand"
rotation: 180 + _minutes * 6
svgScale: face.width / face.naturalSize.width
}
Hand {
anchors.topMargin: 3
elementId: "SecondHandShadow"
rotation: 180 + _seconds * 6
visible: showSecondsHand
svgScale: face.width / face.naturalSize.width
}
Hand {
elementId: "SecondHand"
rotation: 180 + _seconds * 6
visible: showSecondsHand
svgScale: face.width / face.naturalSize.width
}
PlasmaCore.SvgItem {
id: center
width: naturalSize.width * face.width / face.naturalSize.width
height: naturalSize.height * face.width / face.naturalSize.width
anchors.centerIn: clock
svg: clockSvg
elementId: "HandCenterScrew"
z: 1000
}
PlasmaCore.SvgItem {
anchors.fill: face
svg: clockSvg
elementId: "Glass"
width: naturalSize.width * face.width / face.naturalSize.width
height: naturalSize.height * face.width / face.naturalSize.width
}
}
/*
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.3
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3
import org.kde.kirigami 2.4 as Kirigami
import org.kde.kirigamiaddons.dateandtime 0.1
/**
* A small in-line field to input a date.
*
* Use case is for entering a known date, not for "browsing" dates
* where you want the day of the week.
*/
Loader {
id: root
property date selectedDate: new Date()
//maybe we need something more like QQC2 combox to handle user changed signals separately from the others
source: Kirigami.Settings.tabletMode ? "MobileDateInput.qml" : "DesktopDateInput.qml"
onSelectedDateChanged: {
if (item && root.selectedDate) {
item.selectedDate = root.selectedDate;
}
}
onLoaded: {
item.selectedDate = root.selectedDate
root.selectedDate = Qt.binding(function() {return item.selectedDate});
}
}
This diff is collapsed.
// SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick 2.3
import QtQuick.Window 2.15
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3 as Controls
import org.kde.kirigami 2.8 as Kirigami
/**
* A popup that prompts the user to select a date
*/
Kirigami.OverlaySheet {
id: root
/**
* The year of the selected date
*/
property alias year: datePicker.year
/**
* The month of the selected date
*/
property alias month: datePicker.month
/**
* The selected date
*/
property alias selectedDate: datePicker.selectedDate
/**
* Emitted when the user accepts the dialog.
* The selected date is available from the selectedDate property.
*/
signal accepted()
/**
* Emitted when the user cancells the popup
*/
signal cancelled()
header: RowLayout {
implicitWidth: datePicker.width
Kirigami.Heading {
level: 2
text: datePicker.selectedDate.toLocaleDateString(Qt.locale(), "<b>MMMM</b>")
}
Kirigami.Heading {
level: 3
text: datePicker.selectedDate.getFullYear()
opacity: 0.8
Layout.fillWidth: true
}
Controls.Button {
icon.name: "go-previous"
Controls.ToolTip.text: i18n("Previous")
Controls.ToolTip.visible: hovered
Controls.ToolTip.delay: Kirigami.Units.shortDuration
onClicked: datePicker.prevMonth()
}
Controls.Button {
icon.name: "go-jump-today"
Controls.ToolTip.text: i18n("Today")
Controls.ToolTip.visible: hovered
Controls.ToolTip.delay: Kirigami.Units.shortDuration
onClicked: datePicker.goToday()
}
Controls.Button {
icon.name: "go-next"
Controls.ToolTip.text: i18n("Next")
Controls.ToolTip.visible: hovered
Controls.ToolTip.delay: Kirigami.Units.shortDuration
onClicked: datePicker.nextMonth()
}
}
contentItem: DatePicker {
id: datePicker
implicitWidth: Math.min(Window.width, Kirigami.Units.gridUnit * 25)
implicitHeight: width * 0.8
}
footer: RowLayout {
Controls.Label {
text: datePicker.selectedDate.toLocaleDateString();
Layout.fillWidth: true
}
Controls.Button {
text: i18n("Cancel")
icon.name: "dialog-cancel"
onClicked: {
root.cancelled()
root.close()
}
}
Controls.Button {
text: i18n("Accept")
icon.name: "dialog-ok-apply"
onClicked: {
root.selectedDate = datePicker.selectedDate
root.accepted()
root.close()
}
}
}
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
}
/*
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.3
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3
import org.kde.kirigami 2.4 as Kirigami
import org.kde.kirigamiaddons.dateandtime 0.1
RowLayout {
id: layout
//DAVE - if I'm in an RTL country are my date formats pre-reversed?
//i.e Wikipedia says afghan is d/m/yyyy should year go on the left or the right?
property date value
property alias selectedDate: layout.value
property string dateFormat: Qt.locale().dateFormat(Locale.ShortFormat)
//date formats can be in big endian (china), little endian (Europe), or absolutely ridiculous endian (US)
//separators are also different
Component.onCompleted: {
for (var i in layout.children) {
layout.children[i].destroy();
}
var parse = /([^dMy]*)([dMy]+)([^dMy]*)([dMy]+)([^dMy]*)([dMy]+)([^dMy]*)/
var parts = parse.exec(dateFormat);
for(var i=1; i < parts.length; i++) {
var part = parts[i];
if (!part) {
continue;
}
if (part.startsWith("d")) {
daySelectComponent.createObject(layout);
} else if (part.startsWith("M")) {
monthSelectComponent.createObject(layout);
} else if (part.startsWith("y")) {
yearSelectComponent.createObject(layout);
}
}
}
Component {
id: daySelectComponent
SpinBox {
function daysInMonth (month, year) {
return new Date(year, month, 0).getDate();
}
from: 1
to: {
return daysInMonth(layout.value.getFullYear(),
layout.value.getMonth());
}
editable: true
value: layout.value.getDate();
onValueModified: {
var dt = layout.value;
dt.setDate(value);
layout.value = dt;
}
}
}
Component {
id: monthSelectComponent
ComboBox {
id: combo
// JS Date months start at 0, so we can map directly
currentIndex: layout.value.getMonth() // DAVE should be a binding
textRole: "display"
model: YearModel {
year: layout.value.getFullYear()
}
onActivated: {
var dt = layout.value;
dt.setMonth(currentIndex);
layout.value = dt;
}
}
}
Component {
id: yearSelectComponent
SpinBox {
from: 1970
to: 2100 //I assume we'll have a new LTS release by then
editable: true
//default implementation does toLocaleString which looks super weird adding a comma
textFromValue: function(value) {return value}
value: layout.value.getFullYear();
onValueModified: {
var dt = layout.value;
dt.setFullYear(value);
layout.value = dt;
}
}
}
}
/*
* SPDX-FileCopyrightText: 2012 Viranch Mehta <viranch.mehta@gmail.com>
* SPDX-FileCopyrightText: 2012 Marco Martin <mart@kde.org>
* SPDX-FileCopyrightText: 2013 David Edmundson <davidedmundson@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.0
import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.SvgItem {
id: secondHand
property alias rotation: rotation.angle
property double svgScale
width: Math.round(naturalSize.width * svgScale) + Math.round(naturalSize.width * svgScale) % 2
height: Math.round(naturalSize.height * svgScale) + width % 2
anchors {
top: clock.verticalCenter
topMargin: -width/2
horizontalCenter: clock.horizontalCenter
}
svg: clockSvg
smooth: !anim.running
transform: Rotation {
id: rotation
angle: 0
origin {
x: secondHand.width/2
y: secondHand.width/2
}
Behavior on angle {
RotationAnimation {
id: anim
duration: 200
direction: RotationAnimation.Clockwise
easing.type: Easing.OutElastic
easing.overshoot: 0.5
}
}
}
}
// SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
// SPDX-FileCopyrightText: 2021 Carl Schwan <carlschwan@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.3 as Controls
import org.kde.kirigami 2.8 as Kirigami
import org.kde.kirigamiaddons.dateandtime 0.1 as KDT
Controls.TextField { //inherited for style reasons to show we're interactive
id: root
property date selectedDate
readOnly: true
text: selectedDate.toLocaleDateString(Qt.locale(), Locale.ShortFormat)
MouseArea {
anchors.fill: parent
onClicked: {
if (Qt.platform.os === 'android') {
KDT.AndroidIntegration.showDatePicker(root.selectedDate.getTime());
} else {
popupLoader.active = true
popupLoader.item.year = root.selectedDate.getFullYear()
popupLoader.item.month = root.selectedDate.getMonth() + 1
popupLoader.item.selectedDate = root.selectedDate
popupLoader.item.open();
}
}
Connections {
enabled: Qt.platform.os === 'android'
ignoreUnknownSignals: !enabled
target: enabled ? KDT.AndroidIntegration : null
function onDatePickerFinished(accepted, newDate) {
if (accepted) {
root.selectedDate = newDate;
}
}
}
}
Loader {
id: popupLoader
active: false
sourceComponent: Component {
DatePopup {
onAccepted: {
root.selectedDate = item.selectedDate
active = false
}
onCancelled: {
active = false
}
}
}
}
}
/*
* SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org>
*
* SPDX-License-Identifier: LGPL-2.0-or-later
*/
import QtQuick 2.15
import QtQuick.Controls 2.5
import org.kde.kirigamiaddons.dateandtime 0.1
/**
* TimeInput is a single line time editor.
*/
TextField
{
id: timeInput
/**
* This property holds the desired time format.
*/
property string format: Qt.locale().timeFormat(Locale.ShortFormat)
/**
* This property holds the current time value.
*/
property date value: new Date()
// The text field acts as a time input field.
inputMethodHints: Qt.ImhTime
validator: TimeInputValidator {
id: timeValidator
format: timeInput.format
}
onEditingFinished: textToValue()
onValueChanged: valueToText()
function textToValue() {
const locale = Qt.locale();