156 lines
4 KiB
QML
156 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)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|