mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-06 10:18:42 +02:00
[ui] GraphEditor: Added Loader for Node Delegate
The Loader allows loading Backdrop Component for backdrop nodes and Standard Node component for other nodes
This commit is contained in:
parent
fce662b7f0
commit
ce25d0087b
1 changed files with 276 additions and 114 deletions
|
@ -827,141 +827,303 @@ Item {
|
||||||
property bool updateSelectionOnClick: false
|
property bool updateSelectionOnClick: false
|
||||||
property var temporaryEdgeAboutToBeRemoved: undefined
|
property var temporaryEdgeAboutToBeRemoved: undefined
|
||||||
|
|
||||||
delegate: Node {
|
delegate: Loader {
|
||||||
id: nodeDelegate
|
id: nodeLoader
|
||||||
|
Component {
|
||||||
|
id: nodeComponent
|
||||||
|
Node {
|
||||||
|
id: nodeDelegate
|
||||||
|
|
||||||
node: object
|
node: object
|
||||||
width: uigraph.layout.nodeWidth
|
width: uigraph.layout.nodeWidth
|
||||||
|
|
||||||
mainSelected: uigraph.selectedNode === node
|
mainSelected: uigraph.selectedNode === node
|
||||||
hovered: uigraph.hoveredNode === node
|
hovered: uigraph.hoveredNode === node
|
||||||
|
|
||||||
// ItemSelectionModel.hasSelection triggers updates anytime the selectionChanged() signal is emitted.
|
// ItemSelectionModel.hasSelection triggers updates anytime the selectionChanged() signal is emitted.
|
||||||
selected: uigraph.nodeSelection.hasSelection ? uigraph.nodeSelection.isRowSelected(index) : false
|
selected: uigraph.nodeSelection.hasSelection ? uigraph.nodeSelection.isRowSelected(index) : false
|
||||||
|
|
||||||
onAttributePinCreated: function(attribute, pin) { registerAttributePin(attribute, pin) }
|
onAttributePinCreated: function(attribute, pin) { registerAttributePin(attribute, pin) }
|
||||||
onAttributePinDeleted: function(attribute, pin) { unregisterAttributePin(attribute, pin) }
|
onAttributePinDeleted: function(attribute, pin) { unregisterAttributePin(attribute, pin) }
|
||||||
|
|
||||||
onPressed: function(mouse) {
|
onPressed: function(mouse) {
|
||||||
nodeRepeater.updateSelectionOnClick = true;
|
nodeRepeater.updateSelectionOnClick = true;
|
||||||
nodeRepeater.ongoingDrag = true;
|
nodeRepeater.ongoingDrag = true;
|
||||||
|
|
||||||
let selectionMode = ItemSelectionModel.NoUpdate;
|
let selectionMode = ItemSelectionModel.NoUpdate;
|
||||||
|
|
||||||
if(!selected) {
|
if(!selected) {
|
||||||
selectionMode = ItemSelectionModel.ClearAndSelect;
|
selectionMode = ItemSelectionModel.ClearAndSelect;
|
||||||
}
|
|
||||||
|
|
||||||
if (mouse.button === Qt.LeftButton) {
|
|
||||||
if(mouse.modifiers & Qt.ShiftModifier) {
|
|
||||||
selectionMode = ItemSelectionModel.Select;
|
|
||||||
}
|
|
||||||
if(mouse.modifiers & Qt.ControlModifier) {
|
|
||||||
selectionMode = ItemSelectionModel.Toggle;
|
|
||||||
}
|
|
||||||
if(mouse.modifiers & Qt.AltModifier) {
|
|
||||||
let selectFollowingMode = ItemSelectionModel.ClearAndSelect;
|
|
||||||
if(mouse.modifiers & Qt.ShiftModifier) {
|
|
||||||
selectFollowingMode = ItemSelectionModel.Select;
|
|
||||||
}
|
}
|
||||||
uigraph.selectFollowing(node, selectFollowingMode);
|
|
||||||
// Indicate selection has been dealt with by setting conservative Select mode.
|
if (mouse.button === Qt.LeftButton) {
|
||||||
selectionMode = ItemSelectionModel.Select;
|
if(mouse.modifiers & Qt.ShiftModifier) {
|
||||||
|
selectionMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
if(mouse.modifiers & Qt.ControlModifier) {
|
||||||
|
selectionMode = ItemSelectionModel.Toggle;
|
||||||
|
}
|
||||||
|
if(mouse.modifiers & Qt.AltModifier) {
|
||||||
|
let selectFollowingMode = ItemSelectionModel.ClearAndSelect;
|
||||||
|
if(mouse.modifiers & Qt.ShiftModifier) {
|
||||||
|
selectFollowingMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
uigraph.selectFollowing(node, selectFollowingMode);
|
||||||
|
// Indicate selection has been dealt with by setting conservative Select mode.
|
||||||
|
selectionMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mouse.button === Qt.RightButton) {
|
||||||
|
if(selected) {
|
||||||
|
// Keep the full selection when right-clicking on an already selected node.
|
||||||
|
nodeRepeater.updateSelectionOnClick = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selectionMode != ItemSelectionModel.NoUpdate) {
|
||||||
|
nodeRepeater.updateSelectionOnClick = false;
|
||||||
|
uigraph.selectNodeByIndex(index, selectionMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the node is selected after this, make it the active selected node.
|
||||||
|
if(selected) {
|
||||||
|
uigraph.selectedNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the node context menu once selection has been updated.
|
||||||
|
if(mouse.button == Qt.RightButton) {
|
||||||
|
nodeMenuLoader.load(node)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (mouse.button === Qt.RightButton) {
|
onReleased: function(mouse, wasDragged) {
|
||||||
if(selected) {
|
nodeRepeater.ongoingDrag = false;
|
||||||
// Keep the full selection when right-clicking on an already selected node.
|
|
||||||
nodeRepeater.updateSelectionOnClick = false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(selectionMode != ItemSelectionModel.NoUpdate) {
|
// Only called when the node has not been dragged.
|
||||||
nodeRepeater.updateSelectionOnClick = false;
|
onClicked: function(mouse) {
|
||||||
uigraph.selectNodeByIndex(index, selectionMode);
|
if(!nodeRepeater.updateSelectionOnClick) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
// If the node is selected after this, make it the active selected node.
|
uigraph.selectNodeByIndex(index);
|
||||||
if(selected) {
|
|
||||||
uigraph.selectedNode = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the node context menu once selection has been updated.
|
|
||||||
if(mouse.button == Qt.RightButton) {
|
|
||||||
nodeMenuLoader.load(node)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onReleased: function(mouse, wasDragged) {
|
|
||||||
nodeRepeater.ongoingDrag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only called when the node has not been dragged.
|
|
||||||
onClicked: function(mouse) {
|
|
||||||
if(!nodeRepeater.updateSelectionOnClick) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uigraph.selectNodeByIndex(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDoubleClicked: function(mouse) { root.nodeDoubleClicked(mouse, node) }
|
|
||||||
|
|
||||||
onEntered: uigraph.hoveredNode = node
|
|
||||||
onExited: uigraph.hoveredNode = null
|
|
||||||
|
|
||||||
onEdgeAboutToBeRemoved: function(input) {
|
|
||||||
/*
|
|
||||||
* Sometimes the signals are not in the right order because of weird Qt/QML update order
|
|
||||||
* (next DropArea entered signal before previous DropArea exited signal) so edgeAboutToBeRemoved
|
|
||||||
* must be set to undefined before it can be set to another attribute object.
|
|
||||||
*/
|
|
||||||
if (input === undefined) {
|
|
||||||
if (nodeRepeater.temporaryEdgeAboutToBeRemoved === undefined) {
|
|
||||||
root.edgeAboutToBeRemoved = input
|
|
||||||
} else {
|
|
||||||
root.edgeAboutToBeRemoved = nodeRepeater.temporaryEdgeAboutToBeRemoved
|
|
||||||
nodeRepeater.temporaryEdgeAboutToBeRemoved = undefined
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (root.edgeAboutToBeRemoved === undefined) {
|
onDoubleClicked: function(mouse) { root.nodeDoubleClicked(mouse, node) }
|
||||||
root.edgeAboutToBeRemoved = input
|
|
||||||
} else {
|
onEntered: uigraph.hoveredNode = node
|
||||||
nodeRepeater.temporaryEdgeAboutToBeRemoved = input
|
onExited: uigraph.hoveredNode = null
|
||||||
|
|
||||||
|
onEdgeAboutToBeRemoved: function(input) {
|
||||||
|
/*
|
||||||
|
* Sometimes the signals are not in the right order because of weird Qt/QML update order
|
||||||
|
* (next DropArea entered signal before previous DropArea exited signal) so edgeAboutToBeRemoved
|
||||||
|
* must be set to undefined before it can be set to another attribute object.
|
||||||
|
*/
|
||||||
|
if (input === undefined) {
|
||||||
|
if (nodeRepeater.temporaryEdgeAboutToBeRemoved === undefined) {
|
||||||
|
root.edgeAboutToBeRemoved = input
|
||||||
|
} else {
|
||||||
|
root.edgeAboutToBeRemoved = nodeRepeater.temporaryEdgeAboutToBeRemoved
|
||||||
|
nodeRepeater.temporaryEdgeAboutToBeRemoved = undefined
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (root.edgeAboutToBeRemoved === undefined) {
|
||||||
|
root.edgeAboutToBeRemoved = input
|
||||||
|
} else {
|
||||||
|
nodeRepeater.temporaryEdgeAboutToBeRemoved = input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interactive dragging: move the visual delegates
|
||||||
|
onPositionChanged: {
|
||||||
|
if(!selected || !dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Compute offset between the delegate and the stored node position.
|
||||||
|
const offset = Qt.point(x - node.x, y - node.y);
|
||||||
|
|
||||||
|
uigraph.nodeSelection.selectedIndexes.forEach(function(idx) {
|
||||||
|
if(idx != index) {
|
||||||
|
const delegate = nodeRepeater.itemAt(idx.row).item;
|
||||||
|
delegate.x = delegate.node.x + offset.x;
|
||||||
|
delegate.y = delegate.node.y + offset.y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// After drag: apply the final offset to all selected nodes
|
||||||
|
onMoved: function(position) {
|
||||||
|
const offset = Qt.point(position.x - node.x, position.y - node.y);
|
||||||
|
uigraph.moveSelectedNodesBy(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on x {
|
||||||
|
enabled: !nodeRepeater.ongoingDrag
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
Behavior on y {
|
||||||
|
enabled: !nodeRepeater.ongoingDrag
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interactive dragging: move the visual delegates
|
Component {
|
||||||
onPositionChanged: {
|
id: backdropComponent
|
||||||
if(!selected || !dragging) {
|
Backdrop {
|
||||||
return;
|
id: backdropDelegate
|
||||||
}
|
|
||||||
// Compute offset between the delegate and the stored node position.
|
|
||||||
const offset = Qt.point(x - node.x, y - node.y);
|
|
||||||
|
|
||||||
uigraph.nodeSelection.selectedIndexes.forEach(function(idx) {
|
node: object
|
||||||
if(idx != index) {
|
// The Item instantiating the delegates.
|
||||||
const delegate = nodeRepeater.itemAt(idx.row);
|
modelInstantiator: nodeRepeater
|
||||||
delegate.x = delegate.node.x + offset.x;
|
|
||||||
delegate.y = delegate.node.y + offset.y;
|
property var nodes: []
|
||||||
|
|
||||||
|
width: uigraph.layout.nodeWidth
|
||||||
|
|
||||||
|
mainSelected: uigraph.selectedNode === node
|
||||||
|
hovered: uigraph.hoveredNode === node
|
||||||
|
|
||||||
|
// ItemSelectionModel.hasSelection triggers updates anytime the selectionChanged() signal is emitted.
|
||||||
|
selected: uigraph.nodeSelection.hasSelection ? uigraph.nodeSelection.isRowSelected(index) : false
|
||||||
|
|
||||||
|
onPressed: function(mouse) {
|
||||||
|
nodeRepeater.updateSelectionOnClick = true;
|
||||||
|
nodeRepeater.ongoingDrag = true;
|
||||||
|
|
||||||
|
let selectionMode = ItemSelectionModel.NoUpdate;
|
||||||
|
|
||||||
|
if(!selected) {
|
||||||
|
selectionMode = ItemSelectionModel.ClearAndSelect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mouse.button === Qt.LeftButton) {
|
||||||
|
if(mouse.modifiers & Qt.ShiftModifier) {
|
||||||
|
selectionMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
if(mouse.modifiers & Qt.ControlModifier) {
|
||||||
|
selectionMode = ItemSelectionModel.Toggle;
|
||||||
|
}
|
||||||
|
if(mouse.modifiers & Qt.AltModifier) {
|
||||||
|
let selectFollowingMode = ItemSelectionModel.ClearAndSelect;
|
||||||
|
if(mouse.modifiers & Qt.ShiftModifier) {
|
||||||
|
selectFollowingMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
uigraph.selectFollowing(node, selectFollowingMode);
|
||||||
|
// Indicate selection has been dealt with by setting conservative Select mode.
|
||||||
|
selectionMode = ItemSelectionModel.Select;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mouse.button === Qt.RightButton) {
|
||||||
|
if(selected) {
|
||||||
|
// Keep the full selection when right-clicking on an already selected node.
|
||||||
|
nodeRepeater.updateSelectionOnClick = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(selectionMode != ItemSelectionModel.NoUpdate) {
|
||||||
|
nodeRepeater.updateSelectionOnClick = false;
|
||||||
|
uigraph.selectNodeByIndex(index, selectionMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the node is selected after this, make it the active selected node.
|
||||||
|
if(selected) {
|
||||||
|
uigraph.selectedNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the node context menu once selection has been updated.
|
||||||
|
if(mouse.button == Qt.RightButton) {
|
||||||
|
nodeMenuLoader.load(node)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
onReleased: function(mouse, wasDragged) {
|
||||||
|
nodeRepeater.ongoingDrag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only called when the node has not been dragged.
|
||||||
|
onClicked: function(mouse) {
|
||||||
|
if(!nodeRepeater.updateSelectionOnClick) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uigraph.selectNodeByIndex(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDoubleClicked: function(mouse) { root.nodeDoubleClicked(mouse, node) }
|
||||||
|
|
||||||
|
onResized: function(width, height) {
|
||||||
|
uigraph.resizeNode(node, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEntered: uigraph.hoveredNode = node
|
||||||
|
onExited: uigraph.hoveredNode = null
|
||||||
|
|
||||||
|
// Interactive dragging: move the visual delegates
|
||||||
|
onPositionChanged: {
|
||||||
|
if(!selected || !dragging) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute offset between the delegate and the stored node position.
|
||||||
|
const offset = Qt.point(x - node.x, y - node.y);
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
// Get all of the current children for the backdrop
|
||||||
|
let children = getChildrenNodes();
|
||||||
|
|
||||||
|
for (var i = 0; i < children.length; i++) {
|
||||||
|
const delegate = children[i];
|
||||||
|
|
||||||
|
// Ignore the selected delegates as they will be iterated upon separately
|
||||||
|
if (delegate.selected)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
delegate.x = delegate.node.x + offset.x;
|
||||||
|
delegate.y = delegate.node.y + offset.y;
|
||||||
|
|
||||||
|
// If the delegate is not the current Node
|
||||||
|
if (delegate !== node)
|
||||||
|
nodes.push(delegate.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
uigraph.nodeSelection.selectedIndexes.forEach(function(idx) {
|
||||||
|
if(idx != index) {
|
||||||
|
const delegate = nodeRepeater.itemAt(idx.row).item;
|
||||||
|
delegate.x = delegate.node.x + offset.x;
|
||||||
|
delegate.y = delegate.node.y + offset.y;
|
||||||
|
|
||||||
|
// If the delegate is not the current Node
|
||||||
|
if (delegate !== node)
|
||||||
|
nodes.push(delegate.node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// After drag: apply the final offset to all selected nodes
|
||||||
|
onMoved: function(position) {
|
||||||
|
const offset = Qt.point(position.x - node.x, position.y - node.y);
|
||||||
|
uigraph.moveNodesBy(nodes, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on x {
|
||||||
|
enabled: !nodeRepeater.ongoingDrag && !resizing
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
Behavior on y {
|
||||||
|
enabled: !nodeRepeater.ongoingDrag
|
||||||
|
NumberAnimation { duration: 100 }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// After drag: apply the final offset to all selected nodes
|
// Source Component for the delegate
|
||||||
onMoved: function(position) {
|
sourceComponent: object.isBackdrop ? backdropComponent : nodeComponent;
|
||||||
const offset = Qt.point(position.x - node.x, position.y - node.y);
|
|
||||||
uigraph.moveSelectedNodesBy(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on x {
|
onLoaded: {
|
||||||
enabled: !nodeRepeater.ongoingDrag
|
// Node's Z-Ordering
|
||||||
NumberAnimation { duration: 100 }
|
nodeLoader.z = nodeLoader.item.z;
|
||||||
}
|
|
||||||
Behavior on y {
|
|
||||||
enabled: !nodeRepeater.ongoingDrag
|
|
||||||
NumberAnimation { duration: 100 }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue