fuzbal/Sidebar.qml

227 lines
7.1 KiB
QML
Raw Normal View History

// SPDX-License-Identifier: Unlicense
import QtQuick 2.12
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.6
import Qt.labs.platform 1.1
import fuzbal 1
Page {
id: control
property bool modified: false
property Video video
EventList {
id: eventList
onDataChanged: modified = true
onRowsInserted: modified = true
onRowsRemoved: modified = true
}
FileDialog {
id: videoDialog
title: qsTr('Open video')
onAccepted: {
video.source = currentFile
const json = JSON.parse(io.read(currentFile+'.events') || '{}')
eventList.load(json)
description.text = json['description'] || ''
modified = false
}
}
FileDialog {
id: tagsDialog
title: qsTr('Load tags')
nameFilters: [qsTr('JSON files (*.json)'), qsTr('All files (*)')]
onAccepted: eventList.load({ 'tags': JSON.parse(io.read(currentFile)) })
}
Keys.forwardTo: [tags, video]
header: ToolBar {
horizontalPadding: 0
RowLayout {
anchors.fill: parent
ToolButton {
action: Action {
icon.name: 'document-open'
shortcut: StandardKey.Open
onTriggered: videoDialog.open()
}
focusPolicy: Qt.NoFocus
}
Label {
text: video.loaded ? video.source : ''
elide: Text.ElideLeft
Layout.fillWidth: true
}
ToolButton {
action: Action {
onTriggered: {
var json = eventList.save()
json['description'] = description.text
json['video'] = video.source
json['version'] = Qt.application.version
io.write(video.source+'.events', JSON.stringify(json))
modified = false
}
shortcut: StandardKey.Save
icon.name: 'document-save'
enabled: video.loaded && control.modified
}
visible: video.loaded
opacity: enabled ? 1 : 0.25
focusPolicy: Qt.NoFocus
}
}
}
ColumnLayout {
anchors.fill: parent
// Description box.
ColumnLayout {
spacing: 0
RowLayout {
Label {
text: qsTr('Description')
Layout.fillWidth: true
}
Label { text: description.enabled ? qsTr('') : qsTr('+') }
TapHandler { onTapped: description.enabled = !description.enabled }
}
ScrollView {
Layout.fillWidth: true
Layout.preferredHeight: 100
contentWidth: parent.availableWidth
padding: 1
visible: description.enabled
background: Frame { }
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
TextArea {
id: description
background: Rectangle { color: palette.base }
leftPadding: padding
selectByMouse: true
wrapMode: Text.Wrap
onTextChanged: modified = true
KeyNavigation.priority: KeyNavigation.BeforeItem
KeyNavigation.tab: events
}
}
}
// Events list.
ColumnLayout {
spacing: 0
Label { text: qsTr('Events') }
Frame {
padding: 1
Layout.fillWidth: true
Layout.fillHeight: true
Events {
id: events
anchors.fill: parent
focus: true
model: eventList
tags: eventList.tags
onEditingChanged: video.pause(editing)
onCurrentItemChanged: {
if (currentItem)
video.seek(currentItem.time)
}
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:
if (editing) {
currentItem.reset()
editing = false
}
break
case Qt.Key_Delete:
editing = false
eventList.removeRows(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
}
}
}
}
// Tag list.
Frame {
Layout.fillWidth: true
Layout.fillHeight: false
padding: 5
ColumnLayout {
width: parent.width
spacing: 0
RowLayout {
Label {
text: qsTr('Tags')
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
ToolButton {
icon.name: 'document-open'
Layout.alignment: Qt.AlignVCenter
onClicked: tagsDialog.open()
focusPolicy:Qt.NoFocus
}
}
Tags {
id: tags
model: eventList.tagsOrder.map(tag => eventList.tags[tag])
enabled: video.loaded && !events.editing
onClicked: {
events.currentIndex = eventList.insert(video.time)
const event = events.currentItem
event.model.tag = tag
if (event.fields.length > 0)
events.editing = true
}
Layout.fillWidth: true
}
}
}
}
}