diff --git a/Event.qml b/Event.qml
deleted file mode 100644
index da5c194..0000000
--- a/Event.qml
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: Unlicense
-
-import QtQuick 2.12
-import QtQuick.Controls 2.13
-import QtQuick.Layouts 1.6
-
-import 'util.js' as Util
-
-// This is the delegate for event list items.
-ItemDelegate {
- id: control
-
- required property var model
- required property int index
- required property int time
-
- property alias fields: inputs.model // field definitions
- property bool editing: false
-
- clip: true
- padding: 2
-
- background: Rectangle {
- anchors.fill: parent
- color: highlighted ? Util.alphize(border.color, 0.1) :
- (index % 2 === 0 ? palette.base : palette.alternateBase)
- border {
- color: editing ? palette.highlight : palette.dark
- width: highlighted ? 1 : 0
- }
- radius: border.width
- }
-
- // Store current inputs in model.
- function store() {
- var values = {}
- for (var i = 0; i < fields.length; i++)
- values[fields[i].name] = inputs.itemAt(i).item.value
- model.values = values
- }
-
- onEditingChanged: {
- if (editing)
- forceActiveFocus()
- }
-
- // Try passing key to each field input in order.
- Keys.forwardTo: Array.from({ length: inputs.count }, (_, i) => inputs.itemAt(i).item)
-
- contentItem: ColumnLayout {
- anchors { left: parent.left; right: parent.right; margins: 5 }
-
- // Event time, tag and summary.
- RowLayout {
- Label {
- text: new Date(model.time).toISOString().substr(12, 9)
- font.pixelSize: 10
- Layout.alignment: Qt.AlignBaseline
- }
- Label {
- text: model.tag
- font.weight: Font.DemiBold
- Layout.alignment: Qt.AlignBaseline
- }
- Label {
- text: {
- var str = ''
- for (var i = 0; i < inputs.count; i++) {
- const field = inputs.model[i]
- const value = model.values[field.name]
- if (value && field.type !== 'TextArea')
- str += (field.type === 'Bool' ? field.name : value) + ' '
- }
- return str
- }
- elide: Text.ElideRight
- textFormat: Text.PlainText
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignBaseline
- }
- }
-
- // Inputs for event‐specific fields.
- GridLayout {
- flow: GridLayout.TopToBottom
- rows: inputs.count
-
- columnSpacing: 10
- visible: editing
-
- // Labels.
- Repeater {
- model: inputs.model
- delegate: Label {
- text: Util.addShortcut(modelData.name, modelData.key)
- Layout.alignment: Qt.AlignRight
- }
- }
-
- // Inputs.
- Repeater {
- id: inputs
- delegate: Loader {
- source: 'qrc:/Fields/' + modelData.type + '.qml'
-
- Layout.fillHeight: true
- Layout.fillWidth: true
-
- // Set input value to what is in the model each time the control is expanded.
- onVisibleChanged: {
- if (item && visible)
- item.set(control.model.values[modelData.name])
- }
-
- Binding {
- target: item; property: 'model'
- value: modelData
- }
- }
- }
- }
- }
-}
diff --git a/Events.qml b/Events.qml
index 218884a..bce1aac 100644
--- a/Events.qml
+++ b/Events.qml
@@ -4,6 +4,8 @@ import QtQuick 2.12
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.6
+import 'util.js' as Util
+
ListView {
id: control
@@ -12,37 +14,176 @@ ListView {
clip: true
focus: true
- keyNavigationEnabled: true
highlightMoveDuration: 0
highlightResizeDuration: 0
onCurrentIndexChanged: editing = false
+ Keys.onPressed: {
+ switch (event.key) {
+ case Qt.Key_Home:
+ currentIndex = 0
+ break
+ case Qt.Key_End:
+ currentIndex = count - 1
+ break
+ case Qt.Key_Enter:
+ case Qt.Key_Return:
+ if (editing) {
+ currentItem.store()
+ editing = false
+ } else {
+ if (currentItem.fields.length > 0)
+ editing = true
+ }
+ break
+ case Qt.Key_Escape:
+ editing = false
+ break
+ case Qt.Key_Delete:
+ editing = false
+ model.remove(currentIndex)
+ break
+ case Qt.Key_Tab:
+ case Qt.Key_Backtab:
+ // swallow tabs so we don’t lose focus when editing
+ break
+ default:
+ return
+ }
+ event.accepted = true
+ }
+
ScrollBar.vertical: ScrollBar { anchors.right: parent.right }
- delegate: Event {
- // If field definitions are missing for this event’s tag, use
- // Text for all field types unless where the value is bool.
- fields: tags[model.tag] ? tags[model.tag].fields :
- Object.entries(model.values).map(value => ({
- 'name': value[0],
- 'type': typeof(value[1]) === 'boolean' ? 'Bool' : 'Text',
- }))
+ delegate: ItemDelegate {
+ id: event
+
+ required property var model
+ required property int index
+ required property int time
+ required property string tag
+
+ property alias fields: inputs.model // field definitions
+ property bool editing: control.editing && ListView.isCurrentItem
width: control.width
- editing: control.editing && ListView.isCurrentItem
highlighted: ListView.isCurrentItem
- Connections {
- enabled: ListView.currentIndex === index
- function onHeightChanged() {
- control.positionViewAtIndex(index, ListView.Contain)
+ clip: true
+ padding: 2
+
+ background: Rectangle {
+ anchors.fill: parent
+ color: highlighted ? Util.alphize(border.color, 0.1) :
+ (index % 2 === 0 ? palette.base : palette.alternateBase)
+ border {
+ color: editing ? palette.highlight : palette.dark
+ width: highlighted ? 1 : 0
}
+ radius: border.width
}
+ // Store current inputs in model.
+ function store() {
+ var values = {}
+ for (var i = 0; i < inputs.model.length; i++)
+ values[inputs.model[i].name] = inputs.items[i].value
+ model.values = values
+ }
+
+ // Try passing key to each field input in order. If none can
+ // handle it, pass it to control.
+ Keys.forwardTo: Array.prototype.concat(control, editing ? inputs.items : [])
+
onClicked: {
- control.currentIndex = index
- control.forceActiveFocus()
+ control.currentIndex = index
+ control.forceActiveFocus()
+ }
+
+ contentItem: ColumnLayout {
+ anchors { left: parent.left; right: parent.right; margins: 5 }
+
+ // Event time, tag and summary.
+ RowLayout {
+ Label {
+ text: new Date(model.time).toISOString().substr(12, 9)
+ font.pixelSize: 10
+ Layout.alignment: Qt.AlignBaseline
+ }
+ Label {
+ text: tag
+ font.weight: Font.DemiBold
+ Layout.alignment: Qt.AlignBaseline
+ }
+ Label {
+ text: {
+ var str = ''
+ for (var i = 0; i < inputs.count; i++) {
+ const field = inputs.model[i]
+ const value = model.values[field.name]
+ if (value && field.type !== 'TextArea')
+ str += (field.type === 'Bool' ? field.name : value) + ' '
+ }
+ return str
+ }
+ elide: Text.ElideRight
+ textFormat: Text.PlainText
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignBaseline
+ }
+ }
+
+ // Inputs for event‐specific fields.
+ GridLayout {
+ flow: GridLayout.TopToBottom
+ rows: inputs.count
+
+ columnSpacing: 10
+ visible: editing
+
+ // Labels.
+ Repeater {
+ model: inputs.model
+ delegate: Label {
+ text: Util.addShortcut(modelData.name, modelData.key)
+ Layout.alignment: Qt.AlignRight
+ }
+ }
+
+ // Inputs.
+ Repeater {
+ id: inputs
+
+ readonly property var items: Array.from({ length: count }, (_, i) => itemAt(i).item)
+
+ // If field definitions are missing for this event’s tag, use
+ // Text for all field types unless where the value is bool.
+ model: tags[tag] ? tags[tag].fields :
+ Object.entries(event.model.values).map(value => ({
+ 'name': value[0],
+ 'type': typeof(value[1]) === 'boolean' ? 'Bool' : 'Text',
+ }))
+
+ delegate: Loader {
+ source: 'qrc:/Fields/' + modelData.type + '.qml'
+
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ // Set input value to what is in the model each time the control is expanded.
+ onVisibleChanged: {
+ if (item && visible)
+ item.set(event.model.values[modelData.name])
+ }
+
+ Binding {
+ target: item; property: 'model'
+ value: modelData
+ }
+ }
+ }
+ }
}
}
}
diff --git a/Sidebar.qml b/Sidebar.qml
index 3645b2e..4583c0d 100644
--- a/Sidebar.qml
+++ b/Sidebar.qml
@@ -47,7 +47,7 @@ Page {
}
}
- Keys.forwardTo: [tags, video]
+ Keys.forwardTo: [video, tags]
// Save / load buttons.
header: ToolBar {
@@ -151,6 +151,7 @@ Page {
if (currentItem)
video.seek(currentItem.time)
}
+ Keys.forwardTo: control
Rectangle {
anchors { left: parent.left; right: parent.right; top: parent.top }
@@ -163,41 +164,6 @@ Page {
implicitHeight: 1
color: palette.mid
}
-
- Keys.onPressed: {
- switch (event.key) {
- case Qt.Key_Home:
- currentIndex = 0
- break
- case Qt.Key_End:
- currentIndex = count-1
- break
- case Qt.Key_Enter:
- case Qt.Key_Return:
- if (editing) {
- currentItem.store()
- editing = false
- } else {
- if (currentItem.fields.length > 0)
- editing = true
- }
- break
- case Qt.Key_Escape:
- editing = false
- break
- case Qt.Key_Delete:
- editing = false
- eventFilter.remove(currentIndex)
- break
- case Qt.Key_Tab:
- case Qt.Key_Backtab:
- // swallow tabs so we don’t lose focus when editing
- break
- default:
- return
- }
- event.accepted = true
- }
}
Flow {
diff --git a/main.qrc b/main.qrc
index 1ed3196..2eaccc8 100644
--- a/main.qrc
+++ b/main.qrc
@@ -5,7 +5,6 @@
qtquickcontrols2.conf
tags.json
util.js
- Event.qml
Events.qml
Fields/Bool.qml
Fields/Enum.qml