155 lines
4 KiB
QML
155 lines
4 KiB
QML
// SPDX-License-Identifier: Unlicense
|
||
|
||
import QtQuick 2.12
|
||
import QtQuick.Controls 2.13
|
||
import QtQuick.Layouts 1.6
|
||
import QtQml.Models 2.1
|
||
|
||
import 'util.js' as Util
|
||
|
||
ListView {
|
||
id: control
|
||
|
||
property bool editing: false
|
||
property var tags: []
|
||
|
||
signal changed
|
||
|
||
clip: true
|
||
focus: true
|
||
keyNavigationEnabled: true
|
||
highlightMoveDuration: 0
|
||
highlightResizeDuration: 0
|
||
ScrollBar.vertical: ScrollBar { anchors.right: parent.right }
|
||
|
||
// Create a new blank event, insert it and start editing.
|
||
function create(time, tag, fields) {
|
||
const index = Util.find(list, 'time', time)
|
||
list.insert(index, {
|
||
'time': time,
|
||
'tag': tag,
|
||
'fields': fields,
|
||
})
|
||
currentIndex = index
|
||
if (fields.length > 0)
|
||
editing = true
|
||
changed()
|
||
}
|
||
|
||
function clear() {
|
||
list.clear()
|
||
}
|
||
|
||
function load(json) {
|
||
// Return list of fields for the given tag.
|
||
function getFields(name) {
|
||
for (var i = 0; i < tags.length; i++)
|
||
if (tags[i].tag === name)
|
||
return tags[i].fields
|
||
return []
|
||
}
|
||
|
||
for (var i = 0; i < json.length; i++) {
|
||
const event = json[i]
|
||
var fields = getFields(event.tag)
|
||
for (var j = 0; j < fields.length; j++)
|
||
fields[j].value = event.fields[fields[j].name]
|
||
list.append({ 'time': event.time, 'tag': event.tag, 'fields': fields })
|
||
}
|
||
forceActiveFocus()
|
||
}
|
||
|
||
function save() {
|
||
var data = []
|
||
for (var i = 0; i < list.count; i++) {
|
||
const event = list.get(i)
|
||
var fields = {}
|
||
for (var j = 0; j < event.fields.count; j++) {
|
||
const field = event.fields.get(j)
|
||
fields[field.name] = field.value
|
||
}
|
||
data.push({ 'time': event.time, 'tag': event.tag, 'fields': fields })
|
||
}
|
||
return data
|
||
}
|
||
|
||
onCurrentIndexChanged: editing = false
|
||
|
||
Keys.onPressed: {
|
||
switch (event.key) {
|
||
case Qt.Key_Enter:
|
||
case Qt.Key_Return:
|
||
if (editing) {
|
||
currentItem.store()
|
||
changed()
|
||
editing = false
|
||
} else {
|
||
if (currentItem.fields.count > 0)
|
||
editing = true
|
||
}
|
||
break
|
||
case Qt.Key_Escape:
|
||
if (editing) {
|
||
currentItem.reset()
|
||
editing = false
|
||
}
|
||
break
|
||
case Qt.Key_Delete:
|
||
editing = false
|
||
if (currentIndex >= 0 && currentIndex < list.count) {
|
||
list.remove(currentIndex)
|
||
changed()
|
||
}
|
||
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
|
||
}
|
||
|
||
model: ListModel {
|
||
id: list
|
||
dynamicRoles: true
|
||
}
|
||
|
||
delegate: Event {
|
||
id: item
|
||
|
||
time: model.time
|
||
tag: model.tag
|
||
fields: model.fields
|
||
|
||
width: control.width
|
||
editing: control.editing && ListView.isCurrentItem
|
||
|
||
background: Rectangle {
|
||
anchors.fill: parent
|
||
color: border.width > 0 ? Util.alphize(border.color, 0.1) :
|
||
(index % 2 === 0 ? palette.base : palette.alternateBase)
|
||
border {
|
||
color: editing ? palette.highlight : palette.dark
|
||
width: item.ListView.isCurrentItem ? 1 : 0
|
||
}
|
||
radius: border.width
|
||
}
|
||
|
||
Connections {
|
||
enabled: ListView.currentIndex === index
|
||
function onHeightChanged() {
|
||
control.positionViewAtIndex(index, ListView.Contain)
|
||
}
|
||
}
|
||
onEditingChanged: {
|
||
reset()
|
||
if (editing)
|
||
forceActiveFocus()
|
||
}
|
||
onRemove: {
|
||
list.remove(ObjectModel.index)
|
||
}
|
||
}
|
||
}
|