mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-30 16:54:57 +00:00
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>
175 lines
5.2 KiB
QML
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
|
|
}
|
|
}
|
|
}
|
|
}
|