fuzbal/Events.qml
Timotej Lazar 09a1c7d57f
Events: inline event delegate
Also key handling. Again allow space to pause/resume video while
editing an event.
2021-09-16 20:33:53 +02:00

189 lines
5.9 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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
clip: true
focus: 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 dont lose focus when editing
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
}
// 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()
}
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 eventspecific 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 events 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
}
}
}
}
}
}
}