Extend copy/paste support to selections containing multiple nodes

This commit is contained in:
Candice Bentéjac 2022-08-24 17:51:05 +02:00
parent 08d502f4a6
commit e11452efdb
2 changed files with 43 additions and 24 deletions

View file

@ -755,23 +755,25 @@ class UIGraph(QObject):
self.hoveredNode = None
@Slot(result=str)
def getSelectedNodeContent(self):
def getSelectedNodesContent(self):
"""
Return the content of the currently selected node in a string, formatted to JSON.
Return the content of the currently selected nodes in a string, formatted to JSON.
If no node is currently selected, an empty string is returned.
"""
if self._selectedNode:
if self._selectedNodes:
d = self._graph.toDict()
node = d[self._selectedNode.name]
return json.dumps(node, indent=4)
selection = {}
for node in self._selectedNodes:
selection[node.name] = d[node.name]
return json.dumps(selection, indent=4)
return ''
@Slot(str, QPoint)
def pasteNode(self, clipboardContent, position=None):
def pasteNodes(self, clipboardContent, position=None):
"""
Parse the content of the clipboard to see whether it contains
a valid node description. If that is the case, the node described
in the clipboard is built with the available information.
valid node descriptions. If that is the case, the nodes described
in the clipboard are built with the available information.
Otherwise, nothing is done.
This function does not need to be preceded by a call to "copyNodeContent".
@ -780,7 +782,7 @@ class UIGraph(QObject):
can be used to generate a node.
For example, it is enough to have:
{"nodeType":"CameraInit"}
{"nodeName": {"nodeType":"CameraInit"}}
in the clipboard to create a default CameraInit node.
"""
if not clipboardContent:
@ -794,18 +796,35 @@ class UIGraph(QObject):
if not isinstance(d, dict):
raise ValueError("The clipboard does not contain a valid node. Cannot paste it.")
nodeType = d.get("nodeType", None)
finalPosition = None
prevPosition = None
for key in d:
nodeDesc = d[key]
nodeType = nodeDesc.get("nodeType", None)
if not nodeType:
raise ValueError("The clipboard does not contain a valid node. Cannot paste it.")
pass
attributes = {}
attributes.update(d.get("inputs", {}))
attributes.update(d.get("outputs", {}))
attributes.update(nodeDesc.get("inputs", {}))
attributes.update(nodeDesc.get("outputs", {}))
if isinstance(position, QPoint):
position = Position(position.x(), position.y())
currentPosition = nodeDesc.get("position", None)
if isinstance(position, QPoint) and not finalPosition:
finalPosition = Position(position.x(), position.y())
else:
if prevPosition and currentPosition:
# if the nodes both have a position, recreate the distance between them from a different
# starting point
x = finalPosition.x + (currentPosition[0] - prevPosition[0])
y = finalPosition.y + (currentPosition[1] - prevPosition[1])
finalPosition = Position(x, y)
else:
# if either the current node or previous one lack a position, use a custom one
finalPosition = Position(finalPosition.x + self.layout.gridSpacing + self.layout.nodeWidth, finalPosition.y)
self.push(commands.PasteNodeCommand(self._graph, nodeType, position=position, **attributes))
self.push(commands.PasteNodeCommand(self._graph, nodeType, position=finalPosition, **attributes))
prevPosition = currentPosition
undoStack = Property(QObject, lambda self: self._undoStack, constant=True)
graphChanged = Signal()

View file

@ -77,9 +77,9 @@ Item {
}
/// Copy node content to clipboard
function copyNode()
function copyNodes()
{
var nodeContent = uigraph.getSelectedNodeContent()
var nodeContent = uigraph.getSelectedNodesContent()
if (nodeContent !== '') {
Clipboard.clear()
Clipboard.setText(nodeContent)
@ -87,11 +87,11 @@ Item {
}
/// Paste content of clipboard to graph editor and create new node if valid
function pasteNode()
function pasteNodes()
{
root.pastePosition = mapToItem(draggable, mouseArea.mouseX, mouseArea.mouseY)
var copiedContent = Clipboard.getText()
uigraph.pasteNode(copiedContent, root.pastePosition)
uigraph.pasteNodes(copiedContent, root.pastePosition)
}
Keys.onPressed: {
@ -107,10 +107,10 @@ Item {
if (event.key === Qt.Key_C)
if (event.modifiers == Qt.ControlModifier)
copyNode()
copyNodes()
if (event.key === Qt.Key_V)
if (event.modifiers == Qt.ControlModifier)
pasteNode()
pasteNodes()
}
MouseArea {