// 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) } } }