[ui] extract NodeEditor from AttributeEditor

* NodeEditor
    * exposes Node parameters: compatibility, attributes and logs
    * provides a placeholder when no active Node
* AttributeEditor
    * only displays the list of Attributes
    * use 'AttributeEditor' for GroupAttributes in AttributeItemDelegate
* Layout
   * move NodeEditor on the same SplitView level as GraphEditor
   * move current node name and menu to the Panel's header
This commit is contained in:
Yann Lanthony 2018-12-14 16:02:04 +01:00
parent b6e4876494
commit 00feb46667
5 changed files with 245 additions and 232 deletions

View file

@ -5,103 +5,30 @@ import MaterialIcons 2.2
import Utils 1.0 import Utils 1.0
/** /**
A component to display and edit a Node's attributes. * A component to display and edit the attributes of a Node.
*/ */
ColumnLayout {
id: root
property variant node: null // the node to edit
property bool readOnly: false
readonly property bool isCompatibilityNode: node.hasOwnProperty("compatibilityIssue")
signal upgradeRequest()
signal attributeDoubleClicked(var attribute)
spacing: 0
Pane {
Layout.fillWidth: true
background: Rectangle { color: Qt.darker(parent.palette.window, 1.15) }
padding: 2
RowLayout {
width: parent.width
Label {
Layout.fillWidth: true
elide: Text.ElideMiddle
text: node.label
horizontalAlignment: Text.AlignHCenter
padding: 6
}
ToolButton {
text: MaterialIcons.settings
font.family: MaterialIcons.fontFamily
onClicked: settingsMenu.popup()
checkable: true
checked: settingsMenu.visible
}
}
Menu {
id: settingsMenu
MenuItem {
text: "Advanced Attributes"
checked: GraphEditorSettings.showAdvancedAttributes
onClicked: GraphEditorSettings.showAdvancedAttributes = !GraphEditorSettings.showAdvancedAttributes
}
MenuItem {
text: "Open Cache Folder"
onClicked: Qt.openUrlExternally(Filepath.stringToUrl(node.internalFolder))
ToolTip.text: node.internalFolder
ToolTip.visible: hovered
ToolTip.delay: 500
}
MenuSeparator {}
MenuItem {
text: "Clear Submitted Status"
onClicked: node.clearSubmittedChunks()
}
}
}
// CompatibilityBadge banner for CompatibilityNode
Loader {
active: isCompatibilityNode
Layout.fillWidth: true
visible: active // for layout update
sourceComponent: CompatibilityBadge {
canUpgrade: root.node.canUpgrade
issueDetails: root.node.issueDetails
onUpgradeRequest: root.upgradeRequest()
sourceComponent: bannerDelegate
}
}
StackLayout {
Layout.fillHeight: true
Layout.fillWidth: true
currentIndex: tabBar.currentIndex
Item {
ListView { ListView {
id: attributesListView id: root
property variant attributes: null
property bool readOnly: false
property int labelWidth: 180
signal upgradeRequest()
signal attributeDoubleClicked(var attribute)
implicitHeight: contentHeight
anchors.fill: parent
anchors.margins: 2
clip: true clip: true
spacing: 2 spacing: 2
ScrollBar.vertical: ScrollBar { id: scrollBar } ScrollBar.vertical: ScrollBar { id: scrollBar }
model: SortFilterDelegateModel { model: SortFilterDelegateModel {
model: node ? node.attributes : null model: attributes
filterRole: GraphEditorSettings.showAdvancedAttributes ? "" : "advanced" filterRole: GraphEditorSettings.showAdvancedAttributes ? "" : "advanced"
filterValue: false filterValue: false
function modelData(item, roleName) { function modelData(item, roleName) {
return item.model.object.desc[roleName] return item.model.object.desc[roleName]
} }
@ -109,9 +36,9 @@ ColumnLayout {
Component { Component {
id: delegateComponent id: delegateComponent
AttributeItemDelegate { AttributeItemDelegate {
width: attributesListView.width - scrollBar.width width: ListView.view.width - scrollBar.width
readOnly: root.isCompatibilityNode readOnly: root.readOnly
labelWidth: 180 labelWidth: root.labelWidth
attribute: object attribute: object
onDoubleClicked: root.attributeDoubleClicked(attr) onDoubleClicked: root.attributeDoubleClicked(attr)
} }
@ -126,35 +53,4 @@ ColumnLayout {
z: -1 z: -1
} }
} }
}
NodeLog {
id: nodeLog
Layout.fillHeight: true
Layout.fillWidth: true
node: root.node
}
}
TabBar {
id: tabBar
Layout.fillWidth: true
width: childrenRect.width
position: TabBar.Footer
TabButton {
text: "Attributes"
width: implicitWidth
padding: 4
leftPadding: 8
rightPadding: leftPadding
}
TabButton {
text: "Log"
width: implicitWidth
leftPadding: 8
rightPadding: leftPadding
}
}
}

View file

@ -348,37 +348,17 @@ RowLayout {
Component { Component {
id: groupAttribute_component id: groupAttribute_component
ListView { ColumnLayout {
id: chilrenListView id: groupItem
implicitWidth: parent.width
implicitHeight: childrenRect.height
onCountChanged: forceLayout()
spacing: 2
model: SortFilterDelegateModel {
model: attribute.value
filterRole: GraphEditorSettings.showAdvancedAttributes ? "" : "advanced"
filterValue: false
function modelData(item, roleName) {
return item.model.object.desc[roleName]
}
delegate: RowLayout {
id: row
width: chilrenListView.width
property var childAttrib: object
Component.onCompleted: { Component.onCompleted: {
var cpt = Qt.createComponent("AttributeItemDelegate.qml") var cpt = Qt.createComponent("AttributeEditor.qml");
var obj = cpt.createObject(row, var obj = cpt.createObject(groupItem,
{'attribute': Qt.binding(function() { return row.childAttrib }), {'attributes': Qt.binding(function() { return attribute.value }),
'readOnly': Qt.binding(function() { return root.readOnly }) 'readOnly': Qt.binding(function() { return root.readOnly }),
'labelWidth': 100, // reduce label width for children (space gain)
}) })
obj.Layout.fillWidth = true obj.Layout.fillWidth = true;
obj.labelWidth = 100 // reduce label width for children (space gain) obj.attributeDoubleClicked.connect(function(attr) {root.doubleClicked(attr)})
obj.doubleClicked.connect(function(attr) {root.doubleClicked(attr)})
}
}
} }
} }
} }

View file

@ -0,0 +1,155 @@
import QtQuick 2.9
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.3
import MaterialIcons 2.2
import Controls 1.0
/**
* NodeEditor allows to visualize and edit the parameters of a Node.
* It mainly provides an attribute editor and a log inspector.
*/
Panel {
id: root
property variant node
property bool readOnly: false
property bool isCompatibilityNode: node && node.compatibilityIssue !== undefined
signal attributeDoubleClicked(var attribute)
signal upgradeRequest()
title: "Node" + (node !== null ? " - <b>" + node.label + "</b>" : "")
icon: MaterialLabel { text: MaterialIcons.tune }
headerBar: RowLayout {
MaterialToolButton {
text: MaterialIcons.more_vert
font.pointSize: 11
padding: 2
onClicked: settingsMenu.open()
checkable: true
checked: settingsMenu.visible
Menu {
id: settingsMenu
y: parent.height
MenuItem {
id: advancedToggle
text: "Advanced Attributes"
MaterialLabel {
anchors.right: parent.right; anchors.rightMargin: parent.padding;
text: MaterialIcons.build
anchors.verticalCenter: parent.verticalCenter
font.pointSize: 8
}
checkable: true
checked: GraphEditorSettings.showAdvancedAttributes
onClicked: GraphEditorSettings.showAdvancedAttributes = !GraphEditorSettings.showAdvancedAttributes
}
MenuItem {
text: "Open Cache Folder"
enabled: root.node !== null
onClicked: Qt.openUrlExternally(Filepath.stringToUrl(root.node.internalFolder))
}
MenuSeparator {}
MenuItem {
enabled: root.node !== null
text: "Clear Submitted Status"
onClicked: node.clearSubmittedChunks()
}
}
}
}
ColumnLayout {
anchors.fill: parent
// CompatibilityBadge banner for CompatibilityNode
Loader {
active: root.isCompatibilityNode
Layout.fillWidth: true
visible: active // for layout update
sourceComponent: CompatibilityBadge {
canUpgrade: root.node.canUpgrade
issueDetails: root.node.issueDetails
onUpgradeRequest: root.upgradeRequest()
sourceComponent: bannerDelegate
}
}
Loader {
Layout.fillHeight: true
Layout.fillWidth: true
sourceComponent: root.node ? editor_component : placeholder_component
Component {
id: placeholder_component
Item {
Column {
anchors.centerIn: parent
MaterialLabel {
text: MaterialIcons.select_all
font.pointSize: 34
color: Qt.lighter(palette.mid, 1.2)
anchors.horizontalCenter: parent.horizontalCenter
}
Label {
color: Qt.lighter(palette.mid, 1.2)
text: "Select a Node to edit its Attributes"
}
}
}
}
Component {
id: editor_component
ColumnLayout {
StackLayout {
Layout.fillHeight: true
Layout.fillWidth: true
currentIndex: tabBar.currentIndex
AttributeEditor {
Layout.fillWidth: true
attributes: root.node.attributes
readOnly: root.isCompatibilityNode
onAttributeDoubleClicked: root.attributeDoubleClicked(attribute)
onUpgradeRequest: root.upgradeRequest()
}
NodeLog {
id: nodeLog
Layout.fillHeight: true
Layout.fillWidth: true
node: root.node
}
}
TabBar {
id: tabBar
Layout.fillWidth: true
width: childrenRect.width
position: TabBar.Footer
TabButton {
text: "Attributes"
width: implicitWidth
padding: 4
leftPadding: 8
rightPadding: leftPadding
}
TabButton {
text: "Log"
width: implicitWidth
leftPadding: 8
rightPadding: leftPadding
}
}
}
}
}
}
}

View file

@ -1,6 +1,7 @@
module GraphEditor module GraphEditor
GraphEditor 1.0 GraphEditor.qml GraphEditor 1.0 GraphEditor.qml
NodeEditor 1.0 NodeEditor.qml
Node 1.0 Node.qml Node 1.0 Node.qml
NodeChunks 1.0 NodeChunks.qml NodeChunks 1.0 NodeChunks.qml
Edge 1.0 Edge.qml Edge 1.0 Edge.qml

View file

@ -507,12 +507,16 @@ ApplicationWindow {
} }
} }
Controls1.SplitView {
orientation: Qt.Horizontal
width: parent.width
height: Math.round(parent.height * 0.3)
visible: settings_UILayout.showGraphEditor
Panel { Panel {
id: graphEditorPanel id: graphEditorPanel
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: false padding: 4
padding: 0
height: Math.round(parent.height * 0.3)
title: "Graph Editor" title: "Graph Editor"
visible: settings_UILayout.showGraphEditor visible: settings_UILayout.showGraphEditor
@ -526,15 +530,6 @@ ApplicationWindow {
return false; return false;
} }
Controls1.SplitView {
orientation: Qt.Horizontal
anchors.fill: parent
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.margins: 2
GraphEditor { GraphEditor {
id: graphEditor id: graphEditor
@ -561,32 +556,18 @@ ApplicationWindow {
} }
} }
} }
Item {
implicitHeight: Math.round(parent.height * 0.2)
implicitWidth: Math.round(parent.width * 0.3)
Loader { NodeEditor {
anchors.fill: parent width: Math.round(parent.width * 0.3)
anchors.margins: 2
active: _reconstruction.selectedNode !== null
sourceComponent: Component {
AttributeEditor {
node: _reconstruction.selectedNode node: _reconstruction.selectedNode
// Make AttributeEditor readOnly when computing // Make NodeEditor readOnly when computing
readOnly: _reconstruction.computing readOnly: _reconstruction.computing
onAttributeDoubleClicked: { onAttributeDoubleClicked: graphEditorPanel.displayAttribute(attribute)
graphEditorPanel.displayAttribute(attribute)
}
onUpgradeRequest: { onUpgradeRequest: {
var n = _reconstruction.upgradeNode(node) var n = _reconstruction.upgradeNode(node);
_reconstruction.selectedNode = n; _reconstruction.selectedNode = n;
} }
} }
} }
} }
} }
}
}
}
}