Add node to graph with Ctrl+V if valid node content is in the clipboard

Attempt to paste the clipboard's content in the graph when Ctrl+V is
pressed. If the clipboard contains a valid node description, add the
corresponding node to the graph.
Otherwise, do nothing.
This commit is contained in:
Candice Bentéjac 2022-08-18 16:51:05 +02:00
parent 751bad96c6
commit ddda62a652
5 changed files with 80 additions and 0 deletions

View file

@ -396,6 +396,15 @@ class Graph(BaseObject):
return duplicates
def pasteNode(self, nodeType, **kwargs):
name = self._createUniqueNodeName(nodeType)
node = None
with GraphModification(self):
node = Node(nodeType, **kwargs)
self._addNode(node, name)
self._applyExpr()
return node
def outEdges(self, attribute):
""" Return the list of edges starting from the given attribute """
# type: (Attribute,) -> [Edge]

View file

@ -195,6 +195,26 @@ class DuplicateNodesCommand(GraphCommand):
self.graph.removeNode(duplicate)
class PasteNodeCommand(GraphCommand):
"""
Handle node pasting in a Graph.
"""
def __init__(self, graph, nodeType, parent=None, **kwargs):
super(PasteNodeCommand, self).__init__(graph, parent)
self.nodeType = nodeType
self.nodeName = None
self.kwargs = kwargs
def redoImpl(self):
node = self.graph.pasteNode(self.nodeType, **self.kwargs)
self.nodeName = node.name
self.setText("Paste Node {}".format(self.nodeName))
return node
def undoImpl(self):
self.graph.removeNode(self.nodeName)
class SetAttributeCommand(GraphCommand):
def __init__(self, graph, attribute, value, parent=None):
super(SetAttributeCommand, self).__init__(graph, parent)

View file

@ -15,6 +15,10 @@ class ClipboardHelper(QObject):
def setText(self, value):
self._clipboard.setText(value)
@Slot(result=str)
def getText(self):
return self._clipboard.text()
@Slot()
def clear(self):
self._clipboard.clear()

View file

@ -766,6 +766,44 @@ class UIGraph(QObject):
return json.dumps(node, indent=4)
return ''
@Slot(str)
def pasteNode(self, clipboardContent):
"""
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.
Otherwise, nothing is done.
This function does not need to be preceded by a call to "copyNodeContent".
Any clipboard content that contains at least a node type with a valid JSON
formatting (dictionary form with double quotes around the keys and values)
can be used to generate a node.
For example, it is enough to have:
{"nodeType":"CameraInit"}
in the clipboard to create a default CameraInit node.
"""
if not clipboardContent:
return
d = {}
try:
d = json.loads(clipboardContent)
except ValueError as e:
raise ValueError(e)
if not isinstance(d, dict):
raise ValueError("The clipboard does not contain a valid node. Cannot paste it.")
nodeType = d.get("nodeType", None)
if not nodeType:
raise ValueError("The clipboard does not contain a valid node. Cannot paste it.")
attributes = {}
attributes.update(d.get("inputs", {}))
attributes.update(d.get("outputs", {}))
self.push(commands.PasteNodeCommand(self._graph, nodeType, **attributes))
undoStack = Property(QObject, lambda self: self._undoStack, constant=True)
graphChanged = Signal()
graph = Property(Graph, lambda self: self._graph, notify=graphChanged)

View file

@ -85,6 +85,12 @@ Item {
}
}
/// Paste content of clipboard to graph editor and create new node if valid
function pasteNode()
{
var copiedContent = Clipboard.getText()
uigraph.pasteNode(copiedContent)
}
Keys.onPressed: {
if (event.key === Qt.Key_F)
@ -100,6 +106,9 @@ Item {
if (event.key === Qt.Key_C)
if (event.modifiers == Qt.ControlModifier)
copyNode()
if (event.key === Qt.Key_V)
if (event.modifiers == Qt.ControlModifier)
pasteNode()
}
MouseArea {