Files
metabuilder/qml/components/lab/CTimePicker.qml
johndoe6345789 6e394d7846 style(qt6): 80-char margin enforced — 737 violations → 29 remaining
191 files reformatted across views, components, widgets, hybrid, contexts.
New components: CCreateSchemaDialog, CAddFieldDialog, CAdminContentPanel.
JS helpers: connBadgeStatus/Text, adminStats, exampleLabels, onLevelClicked.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:48:39 +00:00

175 lines
5.2 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Item {
id: timePicker
property date value: new Date()
property string label: ""
property bool ampm: false
property bool disabled: false
property bool readOnly: false
property bool error: false
property string helperText: ""
property string placeholder: "Select time"
signal timeChanged(date newTime)
implicitWidth: 150
implicitHeight: contentColumn.implicitHeight
function formatTime(d) {
if (!d || isNaN(d.getTime())) return ""
var hours = d.getHours()
var minutes = String(d.getMinutes()).padStart(2, '0')
if (ampm) {
var period = hours >= 12 ? "PM" : "AM"
hours = hours % 12 || 12
return hours + ":" + minutes + " " + period
}
return String(hours).padStart(2, '0') + ":" + minutes
}
ColumnLayout {
id: contentColumn
anchors.fill: parent
spacing: 4
// Label
Text {
visible: timePicker.label
text: timePicker.label
font.pixelSize: 12
color: timePicker.error ? "#d32f2f" : "#666666"
}
// Time input
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 40
radius: 4
color: timePicker.disabled ? "#f5f5f5" : "#ffffff"
border.width: 1
border.color: {
if (timePicker.error) return "#d32f2f"
if (inputMouse.containsMouse) return "#1976d2"
return "#c4c4c4"
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
spacing: 4
// Hours
SpinBox {
id: hoursSpinner
from: timePicker.ampm ? 1 : 0
to: timePicker.ampm ? 12 : 23
value: {
var h = timePicker.value.getHours()
if (timePicker.ampm) {
return h % 12 || 12
}
return h
}
editable: true
implicitWidth: 50
enabled: !timePicker.disabled && !timePicker.readOnly
onValueModified: updateTime()
}
Text {
text: ":"
font.pixelSize: 16
font.weight: Font.Medium
}
// Minutes
SpinBox {
id: minutesSpinner
from: 0
to: 59
value: timePicker.value.getMinutes()
editable: true
implicitWidth: 50
enabled: !timePicker.disabled && !timePicker.readOnly
textFromValue: function(value) {
return String(value).padStart(2, '0')
}
onValueModified: updateTime()
}
// AM/PM toggle
ComboBox {
visible: timePicker.ampm
model: ["AM", "PM"]
currentIndex: timePicker.value.getHours() >= 12 ? 1 : 0
implicitWidth: 60
enabled: !timePicker.disabled && !timePicker.readOnly
onCurrentIndexChanged: updateTime()
}
// Clock icon
Text {
visible: !timePicker.ampm
text: "🕐"
font.pixelSize: 16
}
}
MouseArea {
id: inputMouse
anchors.fill: parent
hoverEnabled: true
propagateComposedEvents: true
z: -1
}
}
// Helper text
Text {
visible: timePicker.helperText
text: timePicker.helperText
font.pixelSize: 12
color: timePicker.error ? "#d32f2f" : "#666666"
}
}
function updateTime() {
var hours = hoursSpinner.value
if (timePicker.ampm) {
var isPM = (ampmCombo
? ampmCombo.currentIndex === 1
: timePicker.value.getHours() >= 12)
if (isPM && hours < 12) hours += 12
if (!isPM && hours === 12) hours = 0
}
var newDate = new Date(timePicker.value)
newDate.setHours(hours, minutesSpinner.value, 0, 0)
timePicker.value = newDate
timeChanged(newDate)
}
property var ampmCombo: null
Component.onCompleted: {
// Find AM/PM combo if exists
for (var i = 0; i < contentColumn.children.length; i++) {
var child = contentColumn.children[i]
if (child instanceof ComboBox) {
ampmCombo = child
break
}
}
}
}