summaryrefslogtreecommitdiff
path: root/Events.qml
blob: 8853f900caba86f26ebc34013e5b9f9723a0264d (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
// 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)
        }
    }
}