Warning, /libraries/kirigami-addons/src/dateandtime/TimePicker.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2021 Han Young <hanyoung@protonmail.com>
0002 // SPDX-FileCopyrightText: 2022 Carl Schwan <carl@carlschwan.eu>
0003 // SPDX-License-Identifier: LGPL-2.1-or-later
0004 
0005 import QtQuick 2.15
0006 import QtQuick.Controls 2.15
0007 import org.kde.kirigami 2.20 as Kirigami
0008 import QtQuick.Layouts 1.15
0009 import org.kde.kirigamiaddons.dateandtime 1.0
0010 
0011 /**
0012  * A large time picker
0013  * Represented as a clock provides a very visual way for a user
0014  * to set and visulise a time being chosen
0015  */
0016 RowLayout {
0017     id: root
0018 
0019     /**
0020      * This property holds the current hours selected. This is a number between 0 and 23.
0021      */
0022     property int hours
0023 
0024     /**
0025      * This property holds the current minutes selected. This is a number between 0 and 59.
0026      */
0027     property int minutes
0028 
0029     property bool _pm: false
0030 
0031     property bool _init: false
0032 
0033     readonly property bool _isAmPm: Qt.locale().timeFormat().includes("AP")
0034 
0035     implicitHeight: Kirigami.Units.gridUnit * 5
0036     implicitWidth: Kirigami.Units.gridUnit * 10
0037 
0038     Component.onCompleted: {
0039         hoursTumbler.currentIndex = (_isAmPm && hours > 12 ? hours - 12 : hours);
0040         minutesTumbler.currentIndex = minutes;
0041         if (_isAmPm) {
0042             amPmTumbler.currentIndex = hours > 12 ? 1 : 0;
0043         }
0044 
0045         // Avoid initialisation bug where thumbler are by default initialised
0046         // to currentIndex 0
0047         _init = true;
0048     }
0049 
0050     function formatText(count, modelData) {
0051         var data = count === 12 && modelData === 0 ? 12 : modelData;
0052         return data.toString().length < 2 ? "0" + data : data;
0053     }
0054 
0055     FontMetrics {
0056         id: fontMetrics
0057     }
0058 
0059     Component {
0060         id: delegateComponent
0061         Label {
0062             id: delegate
0063 
0064             text: formatText(Tumbler.tumbler.count, modelData)
0065             opacity: 1.0 - Math.abs(Tumbler.displacement) / (Tumbler.tumbler.visibleItemCount / 2)
0066             horizontalAlignment: Text.AlignHCenter
0067             verticalAlignment: Text.AlignVCenter
0068             font.pixelSize: fontMetrics.font.pixelSize * 1.25
0069             Accessible.ignored: true
0070 
0071             Rectangle {
0072                 anchors.fill: parent
0073                 color: 'transparent'
0074                 radius: Kirigami.Units.mediumSpacing
0075                 border {
0076                     width: delegate === Tumbler.tumbler.currentItem ? 1 : 0
0077                     color: Kirigami.Theme.highlightColor
0078                 }
0079             }
0080         }
0081     }
0082 
0083     Item {
0084         Layout.fillWidth: true
0085     }
0086 
0087     Tumbler {
0088         id: hoursTumbler
0089         Layout.preferredHeight: Kirigami.Units.gridUnit * 10
0090         model: _isAmPm ? 12 : 24
0091         delegate: delegateComponent
0092         visibleItemCount: 5
0093         onCurrentIndexChanged: if (_init) {
0094             hours = currentIndex + (_isAmPm && _pm ? 12 : 0)
0095         }
0096         Accessible.name: if (!_isAmPm) {
0097             i18ndc("kirigami-addons6", "time in hour in 24h format", "%1 hours", root.hours)
0098         } else if (_isAmPm && _pm) {
0099             i18ndc("kirigami-addons6", "time in hour (PM)", "%1 PM", currentIndex + 12)
0100         } else {
0101             i18ndc("kirigami-addons6", "time in hour (AM)", "%1 AM", currentIndex)
0102         }
0103         Accessible.role: Accessible.Dial
0104         Accessible.onDecreaseAction: hoursTumbler.currentIndex = (hoursTumbler.currentIndex + hoursTumbler.model - 1) % hoursTumbler.model
0105         Accessible.onIncreaseAction: hoursTumbler.currentIndex = (hoursTumbler.currentIndex + 1) % hoursTumbler.model
0106         focus: true
0107     }
0108 
0109     Label {
0110         Layout.alignment: Qt.AlignCenter
0111         text: i18ndc("kirigami-addons6", "Time separator", ":")
0112         font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.3
0113         Accessible.ignored: true
0114     }
0115 
0116     Tumbler {
0117         id: minutesTumbler
0118         Layout.preferredHeight: Kirigami.Units.gridUnit * 10
0119         model: 60
0120         delegate: delegateComponent
0121         visibleItemCount: 5
0122         onCurrentIndexChanged: if (_init) {
0123             minutes = currentIndex;
0124         }
0125 
0126         Accessible.name: i18ndc("kirigami-addons6", "number of minutes", "%1 minutes", root.minutes)
0127         Accessible.role: Accessible.Dial
0128         Accessible.onDecreaseAction: minutesTumbler.currentIndex = (minutesTumbler.currentIndex + 59) % 60
0129         Accessible.onIncreaseAction: minutesTumbler.currentIndex = (minutesTumbler.currentIndex + 1) % 60
0130     }
0131 
0132     Tumbler {
0133         id: amPmTumbler
0134         visible: _isAmPm
0135         Layout.preferredHeight: Kirigami.Units.gridUnit * 10
0136         model: [Qt.locale().amText, Qt.locale().pmText]
0137         Accessible.name: currentItem.text
0138         Accessible.role: Accessible.CheckBox
0139         Accessible.ignored: !_isAmPm
0140         Accessible.onPressAction: amPmTumbler.currentIndex = (amPmTumbler.currentIndex + 1) % 2
0141         Accessible.onToggleAction: amPmTumbler.currentIndex = (amPmTumbler.currentIndex + 1) % 2
0142         delegate: delegateComponent
0143         visibleItemCount: 5
0144         onCurrentIndexChanged: if (_isAmPm && _init) {
0145             _pm = currentIndex;
0146             hours = (hours + 12) % 24;
0147         }
0148     }
0149 
0150     Item {
0151         Layout.fillWidth: true
0152     }
0153 }