Kirigami-addons

TimePicker.qml
1// SPDX-FileCopyrightText: 2021 Han Young <hanyoung@protonmail.com>
2// SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
3// SPDX-License-Identifier: LGPL-2.1-or-later
4
5import QtQuick
6import QtQuick.Controls
7import org.kde.kirigami as Kirigami
8import QtQuick.Layouts
9import org.kde.kirigamiaddons.dateandtime
10
11/**
12 * A large time picker
13 * Represented as a clock provides a very visual way for a user
14 * to set and visulise a time being chosen
15 */
16RowLayout {
17 id: root
18
19 /**
20 * This property holds the current hours selected. This is a number between 0 and 23.
21 */
22 property int hours
24 /**
25 * This property holds the current minutes selected. This is a number between 0 and 59.
26 */
27 property int minutes
28
29 property bool _pm: false
30
31 property bool _init: false
32
33 readonly property bool _isAmPm: Qt.locale().timeFormat().includes("AP")
34
35 implicitHeight: Kirigami.Units.gridUnit * 5
36 implicitWidth: Kirigami.Units.gridUnit * 10
37
38 Component.onCompleted: {
39 hoursTumbler.currentIndex = (_isAmPm && hours > 12 ? hours - 12 : hours);
40 minutesTumbler.currentIndex = minutes;
41 if (_isAmPm) {
42 root._pm = hours > 12 ? 1 : 0;
43 amPmTumbler.currentIndex = _pm;
44 }
45
46 // Avoid initialisation bug where thumbler are by default initialised
47 // to currentIndex 0
48 _init = true;
49 }
50
51 function formatText(count, modelData) {
52 var data = count === 12 && modelData === 0 ? 12 : modelData;
53 return data.toString().length < 2 ? "0" + data : data;
54 }
55
56 FontMetrics {
57 id: fontMetrics
58 }
59
60 Component {
61 id: delegateComponent
62 Label {
63 id: delegate
64
65 text: formatText(Tumbler.tumbler.count, modelData)
66 opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
67 horizontalAlignment: Text.AlignHCenter
68 verticalAlignment: Text.AlignVCenter
69 font.pixelSize: fontMetrics.font.pixelSize * 1.25
70 Accessible.ignored: true
71
72 Rectangle {
73 anchors.fill: parent
74 color: 'transparent'
75 radius: Kirigami.Units.mediumSpacing
76 border {
77 width: delegate === Tumbler.tumbler.currentItem ? 1 : 0
78 color: Kirigami.Theme.highlightColor
79 }
80 }
81 }
82 }
83
84 Item {
85 Layout.fillWidth: true
86 }
87
88 Tumbler {
89 id: hoursTumbler
90 Layout.preferredHeight: Kirigami.Units.gridUnit * 10
91 model: _isAmPm ? 12 : 24
92 delegate: delegateComponent
93 visibleItemCount: 5
94 onCurrentIndexChanged: if (_init) {
95 hours = currentIndex + (_isAmPm && _pm ? 12 : 0)
96 }
97 Accessible.name: i18nd("kirigami-addons6", "Hours")
98 Accessible.role: Accessible.Dial
99 Accessible.onDecreaseAction: hoursTumbler.currentIndex = (hoursTumbler.currentIndex + hoursTumbler.model - 1) % hoursTumbler.model
100 Accessible.onIncreaseAction: hoursTumbler.currentIndex = (hoursTumbler.currentIndex + 1) % hoursTumbler.model
101 // a11y value interface
102 property int minimumValue: root._isAmPm ? 1 : 0
103 property int maximumValue: root._isAmPm ? 12 : 23
104 property int stepSize: 1
105 property int value: root.hours
106 onValueChanged: {
107 if (root._isAmPm && value === 12)
108 hoursTumbler.currentIndex = 0;
109 else
110 hoursTumbler.currentIndex = value;
111 hoursTumbler.value = Qt.binding(function() { return root.hours; });
112 }
113
114 focus: true
115 }
116
117 Label {
118 Layout.alignment: Qt.AlignCenter
119 text: i18ndc("kirigami-addons6", "Time separator", ":")
120 font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.3
121 Accessible.ignored: true
122 }
123
124 Tumbler {
125 id: minutesTumbler
126 Layout.preferredHeight: Kirigami.Units.gridUnit * 10
127 model: 60
128 delegate: delegateComponent
129 visibleItemCount: 5
130 onCurrentIndexChanged: if (_init) {
131 minutes = currentIndex;
132 }
133
134 Accessible.name: i18nd("kirigami-addons6", "Minutes")
135 Accessible.role: Accessible.Dial
136 Accessible.onDecreaseAction: minutesTumbler.currentIndex = (minutesTumbler.currentIndex + 59) % 60
137 Accessible.onIncreaseAction: minutesTumbler.currentIndex = (minutesTumbler.currentIndex + 1) % 60
138 // a11y value interface
139 property int minimumValue: 0
140 property int maximumValue: 59
141 property int stepSize: 1
142 property alias value: minutesTumbler.currentIndex
143 }
144
145 Tumbler {
146 id: amPmTumbler
147 visible: _isAmPm
148 Layout.preferredHeight: Kirigami.Units.gridUnit * 10
149 model: [Qt.locale().amText, Qt.locale().pmText]
150 Accessible.name: currentItem.text
151 Accessible.role: Accessible.CheckBox
152 Accessible.ignored: !_isAmPm
153 Accessible.onPressAction: amPmTumbler.currentIndex = (amPmTumbler.currentIndex + 1) % 2
154 Accessible.onToggleAction: amPmTumbler.currentIndex = (amPmTumbler.currentIndex + 1) % 2
155 delegate: delegateComponent
156 visibleItemCount: 5
157 onCurrentIndexChanged: if (_isAmPm && _init) {
158 _pm = currentIndex;
159 hours = (hours + 12) % 24;
160 }
161 }
162
163 Item {
164 Layout.fillWidth: true
165 }
166}
QString i18ndc(const char *domain, const char *context, const char *text, const TYPE &arg...)
QString i18nd(const char *domain, const char *text, const TYPE &arg...)
AlignHCenter
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:33:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.