blob: 846f2bb5b07c13c4d0810249958bd985510771fb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
// SPDX-License-Identifier: Unlicense
import QtQuick 2.12
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.6
import 'util.js' as Util
ListView {
id: control
required property var tags // tag definitions
property bool editing: false
signal selected(var event)
clip: 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
default:
return
}
event.accepted = true
}
ScrollBar.vertical: ScrollBar { anchors.right: parent.right }
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
highlighted: ListView.isCurrentItem
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
}
// Pass the key to parent first to check if Video handles it.
// If not, try passing it to each field input when editing.
Keys.forwardTo: Array.prototype.concat(control, editing ? inputs.items : [])
onClicked: {
control.currentIndex = index
control.forceActiveFocus()
}
onDoubleClicked: control.selected(event)
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
}
}
}
}
}
}
}
|