mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-06-02 02:42:05 +02:00
[ui] GraphEditor: move node context menu to a Loader
Avoid having the node context menu always evaluating the current state of the selected nodes for its own display, by dynamically creating it on demand with a Loader. Use callbacks for recomputing/resubmitting actions, instead of storing state in the UI components.
This commit is contained in:
parent
686927a92d
commit
b3a8c6a1f2
1 changed files with 95 additions and 72 deletions
|
@ -31,8 +31,6 @@ Item {
|
||||||
signal computeRequest(var nodes)
|
signal computeRequest(var nodes)
|
||||||
signal submitRequest(var nodes)
|
signal submitRequest(var nodes)
|
||||||
|
|
||||||
signal dataDeleted()
|
|
||||||
|
|
||||||
property int nbMeshroomScenes: 0
|
property int nbMeshroomScenes: 0
|
||||||
property int nbDraggedFiles: 0
|
property int nbDraggedFiles: 0
|
||||||
signal filesDropped(var drop, var mousePosition) // Files have been dropped
|
signal filesDropped(var drop, var mousePosition) // Files have been dropped
|
||||||
|
@ -70,17 +68,6 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDataDeleted: {
|
|
||||||
if (computeMenuItem.recompute) {
|
|
||||||
computeRequest(uigraph.selectedNodes)
|
|
||||||
computeMenuItem.recompute = false
|
|
||||||
}
|
|
||||||
else if (submitMenuItem.resubmit) {
|
|
||||||
submitRequest(uigraph.selectedNodes)
|
|
||||||
submitMenuItem.resubmit = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Duplicate a node and optionally all the following ones
|
/// Duplicate a node and optionally all the following ones
|
||||||
function duplicateNode(duplicateFollowingNodes) {
|
function duplicateNode(duplicateFollowingNodes) {
|
||||||
var nodes
|
var nodes
|
||||||
|
@ -549,12 +536,44 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: nodeMenuLoader
|
||||||
|
property var currentNode: null
|
||||||
|
active: currentNode != null
|
||||||
|
sourceComponent: nodeMenuComponent
|
||||||
|
|
||||||
|
function load(node) {
|
||||||
|
currentNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unload() {
|
||||||
|
currentNode = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDataDeletionDialog(deleteFollowing: bool, callback) {
|
||||||
|
uigraph.forceNodesStatusUpdate();
|
||||||
|
const dialog = deleteDataDialog.createObject(
|
||||||
|
root,
|
||||||
|
{
|
||||||
|
"node": currentNode,
|
||||||
|
"deleteFollowing": deleteFollowing
|
||||||
|
}
|
||||||
|
);
|
||||||
|
dialog.open();
|
||||||
|
if(callback)
|
||||||
|
dialog.dataDeleted.connect(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: nodeMenuComponent
|
||||||
Menu {
|
Menu {
|
||||||
id: nodeMenu
|
id: nodeMenu
|
||||||
property var currentNode: null
|
|
||||||
property bool canComputeNode: currentNode != null && uigraph.graph.canComputeTopologically(currentNode)
|
property var currentNode: nodeMenuLoader.currentNode
|
||||||
|
property bool canComputeNode: uigraph.graph.canComputeTopologically(currentNode)
|
||||||
// canSubmitOrCompute: return int n : 0 >= n <= 3 | n=0 cannot submit or compute | n=1 can compute | n=2 can submit | n=3 can compute & submit
|
// canSubmitOrCompute: return int n : 0 >= n <= 3 | n=0 cannot submit or compute | n=1 can compute | n=2 can submit | n=3 can compute & submit
|
||||||
property int canSubmitOrCompute: currentNode != null && uigraph.graph.canSubmitOrCompute(currentNode)
|
property int canSubmitOrCompute: uigraph.graph.canSubmitOrCompute(currentNode)
|
||||||
property bool isComputed: {
|
property bool isComputed: {
|
||||||
var count = 0
|
var count = 0
|
||||||
for (var i = 0; i < uigraph.selectedNodes.count; ++i) {
|
for (var i = 0; i < uigraph.selectedNodes.count; ++i) {
|
||||||
|
@ -567,12 +586,14 @@ Item {
|
||||||
}
|
}
|
||||||
return count > 0
|
return count > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 220
|
width: 220
|
||||||
onClosed: currentNode = null
|
|
||||||
|
Component.onCompleted: popup()
|
||||||
|
onClosed: nodeMenuLoader.unload()
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
id: computeMenuItem
|
id: computeMenuItem
|
||||||
property bool recompute: false
|
|
||||||
text: nodeMenu.isComputed ? "Recompute" : "Compute"
|
text: nodeMenu.isComputed ? "Recompute" : "Compute"
|
||||||
visible: {
|
visible: {
|
||||||
var count = 0
|
var count = 0
|
||||||
|
@ -607,10 +628,14 @@ Item {
|
||||||
|
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (nodeMenu.isComputed) {
|
if (nodeMenu.isComputed) {
|
||||||
recompute = true
|
nodeMenuLoader.showDataDeletionDialog(
|
||||||
deleteDataMenuItem.showConfirmationDialog(false)
|
false,
|
||||||
|
function(request, uigraph) {
|
||||||
|
request(uigraph.selectedNodes);
|
||||||
|
}.bind(null, computeRequest, uigraph)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
computeRequest(uigraph.selectedNodes)
|
computeRequest(uigraph.selectedNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -648,35 +673,39 @@ Item {
|
||||||
}
|
}
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (nodeMenu.isComputed) {
|
if (nodeMenu.isComputed) {
|
||||||
resubmit = true
|
nodeMenuLoader.showDataDeletionDialog(
|
||||||
deleteDataMenuItem.showConfirmationDialog(false)
|
false,
|
||||||
|
function(request, uigraph) {
|
||||||
|
request(uigraph.selectedNodes);
|
||||||
|
}.bind(null, submitRequest, uigraph)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
submitRequest(uigraph.selectedNodes)
|
submitRequest(uigraph.selectedNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Stop Computation"
|
text: "Stop Computation"
|
||||||
enabled: nodeMenu.currentNode ? nodeMenu.currentNode.canBeStopped() : false
|
enabled: nodeMenu.currentNode.canBeStopped()
|
||||||
visible: enabled
|
visible: enabled
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
onTriggered: uigraph.stopNodeComputation(nodeMenu.currentNode)
|
onTriggered: uigraph.stopNodeComputation(nodeMenu.currentNode)
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Cancel Computation"
|
text: "Cancel Computation"
|
||||||
enabled: nodeMenu.currentNode ? nodeMenu.currentNode.canBeCanceled() : false
|
enabled: nodeMenu.currentNode.canBeCanceled()
|
||||||
visible: enabled
|
visible: enabled
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
onTriggered: uigraph.cancelNodeComputation(nodeMenu.currentNode)
|
onTriggered: uigraph.cancelNodeComputation(nodeMenu.currentNode)
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Open Folder"
|
text: "Open Folder"
|
||||||
visible: nodeMenu.currentNode ? nodeMenu.currentNode.isComputable : false
|
visible: nodeMenu.currentNode.isComputable
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
onTriggered: Qt.openUrlExternally(Filepath.stringToUrl(nodeMenu.currentNode.internalFolder))
|
onTriggered: Qt.openUrlExternally(Filepath.stringToUrl(nodeMenu.currentNode.internalFolder))
|
||||||
}
|
}
|
||||||
MenuSeparator {
|
MenuSeparator {
|
||||||
visible: nodeMenu.currentNode ? nodeMenu.currentNode.isComputable : false
|
visible: nodeMenu.currentNode.isComputable
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Cut Node(s)"
|
text: "Cut Node(s)"
|
||||||
|
@ -725,7 +754,7 @@ Item {
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: "Remove Node(s)" + (removeFollowingButton.hovered ? " From Here" : "")
|
text: "Remove Node(s)" + (removeFollowingButton.hovered ? " From Here" : "")
|
||||||
enabled: nodeMenu.currentNode ? !nodeMenu.currentNode.locked : false
|
enabled: !nodeMenu.currentNode.locked
|
||||||
onTriggered: uigraph.removeSelectedNodes()
|
onTriggered: uigraph.removeSelectedNodes()
|
||||||
MaterialToolButton {
|
MaterialToolButton {
|
||||||
id: removeFollowingButton
|
id: removeFollowingButton
|
||||||
|
@ -742,12 +771,12 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MenuSeparator {
|
MenuSeparator {
|
||||||
visible: nodeMenu.currentNode ? nodeMenu.currentNode.isComputable : false
|
visible: nodeMenu.currentNode.isComputable
|
||||||
}
|
}
|
||||||
MenuItem {
|
MenuItem {
|
||||||
id: deleteDataMenuItem
|
id: deleteDataMenuItem
|
||||||
text: "Delete Data" + (deleteFollowingButton.hovered ? " From Here" : "" ) + "..."
|
text: "Delete Data" + (deleteFollowingButton.hovered ? " From Here" : "" ) + "..."
|
||||||
visible: nodeMenu.currentNode ? nodeMenu.currentNode.isComputable : false
|
visible: nodeMenu.currentNode.isComputable
|
||||||
height: visible ? implicitHeight : 0
|
height: visible ? implicitHeight : 0
|
||||||
enabled: {
|
enabled: {
|
||||||
if (!nodeMenu.currentNode)
|
if (!nodeMenu.currentNode)
|
||||||
|
@ -763,18 +792,7 @@ Item {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
function showConfirmationDialog(deleteFollowing) {
|
onTriggered: nodeMenuLoader.showDataDeletionDialog(false)
|
||||||
uigraph.forceNodesStatusUpdate()
|
|
||||||
var obj = deleteDataDialog.createObject(root,
|
|
||||||
{
|
|
||||||
"node": nodeMenu.currentNode,
|
|
||||||
"deleteFollowing": deleteFollowing
|
|
||||||
})
|
|
||||||
obj.open()
|
|
||||||
nodeMenu.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
onTriggered: showConfirmationDialog(false)
|
|
||||||
|
|
||||||
MaterialToolButton {
|
MaterialToolButton {
|
||||||
id: deleteFollowingButton
|
id: deleteFollowingButton
|
||||||
|
@ -784,35 +802,41 @@ Item {
|
||||||
}
|
}
|
||||||
height: parent.height
|
height: parent.height
|
||||||
text: MaterialIcons.fast_forward
|
text: MaterialIcons.fast_forward
|
||||||
onClicked: parent.showConfirmationDialog(true)
|
onClicked: {
|
||||||
}
|
nodeMenuLoader.showDataDeletionDialog(true);
|
||||||
|
nodeMenu.close();
|
||||||
// Confirmation dialog for node cache deletion
|
|
||||||
Component {
|
|
||||||
id: deleteDataDialog
|
|
||||||
MessageDialog {
|
|
||||||
property var node
|
|
||||||
property bool deleteFollowing: false
|
|
||||||
|
|
||||||
focus: true
|
|
||||||
modal: false
|
|
||||||
header.visible: false
|
|
||||||
|
|
||||||
text: "Delete Data of '" + node.label + "'" + (uigraph.selectedNodes.count > 1 ? " and other selected Nodes" : "") + (deleteFollowing ? " and following Nodes?" : "?")
|
|
||||||
helperText: "Warning: This operation cannot be undone."
|
|
||||||
standardButtons: Dialog.Yes | Dialog.Cancel
|
|
||||||
|
|
||||||
onAccepted: {
|
|
||||||
if (deleteFollowing)
|
|
||||||
uigraph.clearDataFrom(uigraph.selectedNodes)
|
|
||||||
else
|
|
||||||
uigraph.clearData(uigraph.selectedNodes)
|
|
||||||
|
|
||||||
root.dataDeleted()
|
|
||||||
}
|
|
||||||
onClosed: destroy()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirmation dialog for node cache deletion
|
||||||
|
Component {
|
||||||
|
id: deleteDataDialog
|
||||||
|
MessageDialog {
|
||||||
|
property var node
|
||||||
|
property bool deleteFollowing: false
|
||||||
|
|
||||||
|
signal dataDeleted()
|
||||||
|
|
||||||
|
focus: true
|
||||||
|
modal: false
|
||||||
|
header.visible: false
|
||||||
|
|
||||||
|
text: "Delete Data of '" + node.label + "'" + (uigraph.selectedNodes.count > 1 ? " and other selected Nodes" : "") + (deleteFollowing ? " and following Nodes?" : "?")
|
||||||
|
helperText: "Warning: This operation cannot be undone."
|
||||||
|
standardButtons: Dialog.Yes | Dialog.Cancel
|
||||||
|
|
||||||
|
onAccepted: {
|
||||||
|
if (deleteFollowing)
|
||||||
|
uigraph.clearDataFrom(uigraph.selectedNodes);
|
||||||
|
else
|
||||||
|
uigraph.clearData(uigraph.selectedNodes);
|
||||||
|
dataDeleted();
|
||||||
|
}
|
||||||
|
onClosed: destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,8 +904,7 @@ Item {
|
||||||
// Keep the full selection when right-clicking on a node.
|
// Keep the full selection when right-clicking on a node.
|
||||||
nodeRepeater.updateSelectionOnClick = false;
|
nodeRepeater.updateSelectionOnClick = false;
|
||||||
}
|
}
|
||||||
nodeMenu.currentNode = node
|
nodeMenuLoader.load(node)
|
||||||
nodeMenu.popup()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectionMode != ItemSelectionModel.NoUpdate) {
|
if(selectionMode != ItemSelectionModel.NoUpdate) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue