Skip to content

Commit

Permalink
Merge pull request #383 from jchanvfx/port_connection_signal_fix_#373
Browse files Browse the repository at this point in the history
emit signals from undo fix #373
  • Loading branch information
jchanvfx authored Sep 14, 2023
2 parents 4a645b4 + 8e2a625 commit bea91e9
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 71 deletions.
89 changes: 70 additions & 19 deletions NodeGraphQt/base/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,54 +165,73 @@ class NodeAddedCmd(QtWidgets.QUndoCommand):
graph (NodeGraphQt.NodeGraph): node graph.
node (NodeGraphQt.NodeObject): node.
pos (tuple(float, float)): initial node position (optional).
emit_signal (bool): emit node creation signals. (default: True)
"""

def __init__(self, graph, node, pos=None):
def __init__(self, graph, node, pos=None, emit_signal=True):
QtWidgets.QUndoCommand.__init__(self)
self.setText('added node')
self.viewer = graph.viewer()
self.model = graph.model
self.graph = graph
self.node = node
self.pos = pos
self.emit_signal = emit_signal

def undo(self):
node_id = self.node.id
self.pos = self.pos or self.node.pos()
self.model.nodes.pop(self.node.id)
self.graph.model.nodes.pop(self.node.id)
self.node.view.delete()

if self.emit_signal:
self.graph.nodes_deleted.emit([node_id])

def redo(self):
self.model.nodes[self.node.id] = self.node
self.viewer.add_node(self.node.view, self.pos)
self.graph.model.nodes[self.node.id] = self.node
self.graph.viewer().add_node(self.node.view, self.pos)

# node width & height is calculated when it's added to the scene,
# so we have to update the node model here.
self.node.model.width = self.node.view.width
self.node.model.height = self.node.view.height

if self.emit_signal:
self.graph.node_created.emit(self.node)


class NodeRemovedCmd(QtWidgets.QUndoCommand):
class NodesRemovedCmd(QtWidgets.QUndoCommand):
"""
Node deleted command.
Args:
graph (NodeGraphQt.NodeGraph): node graph.
node (NodeGraphQt.BaseNode or NodeGraphQt.NodeObject): node.
nodes (list[NodeGraphQt.BaseNode or NodeGraphQt.NodeObject]): nodes.
emit_signal (bool): emit node deletion signals. (default: True)
"""

def __init__(self, graph, node):
def __init__(self, graph, nodes, emit_signal=True):
QtWidgets.QUndoCommand.__init__(self)
self.setText('deleted node')
self.scene = graph.scene()
self.model = graph.model
self.node = node
self.setText('deleted node(s)')
self.graph = graph
self.nodes = nodes
self.emit_signal = emit_signal

def undo(self):
self.model.nodes[self.node.id] = self.node
self.scene.addItem(self.node.view)
for node in self.nodes:
self.graph.model.nodes[node.id] = node
self.graph.scene().addItem(node.view)

if self.emit_signal:
self.graph.node_created.emit(node)

def redo(self):
self.model.nodes.pop(self.node.id)
self.node.view.delete()
node_ids = []
for node in self.nodes:
node_ids.append(node.id)
self.graph.model.nodes.pop(node.id)
node.view.delete()

if self.emit_signal:
self.graph.nodes_deleted.emit(node_ids)


class NodeInputConnectedCmd(QtWidgets.QUndoCommand):
Expand Down Expand Up @@ -276,12 +295,14 @@ class PortConnectedCmd(QtWidgets.QUndoCommand):
Args:
src_port (NodeGraphQt.Port): source port.
trg_port (NodeGraphQt.Port): target port.
emit_signal (bool): emit port connection signals.
"""

def __init__(self, src_port, trg_port):
def __init__(self, src_port, trg_port, emit_signal):
QtWidgets.QUndoCommand.__init__(self)
self.source = src_port
self.target = trg_port
self.emit_signal = emit_signal

def undo(self):
src_model = self.source.model
Expand All @@ -303,6 +324,13 @@ def undo(self):

self.source.view.disconnect_from(self.target.view)

# emit "port_disconnected" signal from the parent graph.
if self.emit_signal:
ports = {p.type_(): p for p in [self.source, self.target]}
graph = self.source.node().graph
graph.port_disconnected.emit(ports[PortTypeEnum.IN.value],
ports[PortTypeEnum.OUT.value])

def redo(self):
src_model = self.source.model
trg_model = self.target.model
Expand All @@ -314,6 +342,13 @@ def redo(self):

self.source.view.connect_to(self.target.view)

# emit "port_connected" signal from the parent graph.
if self.emit_signal:
ports = {p.type_(): p for p in [self.source, self.target]}
graph = self.source.node().graph
graph.port_connected.emit(ports[PortTypeEnum.IN.value],
ports[PortTypeEnum.OUT.value])


class PortDisconnectedCmd(QtWidgets.QUndoCommand):
"""
Expand All @@ -322,12 +357,14 @@ class PortDisconnectedCmd(QtWidgets.QUndoCommand):
Args:
src_port (NodeGraphQt.Port): source port.
trg_port (NodeGraphQt.Port): target port.
emit_signal (bool): emit port connection signals.
"""

def __init__(self, src_port, trg_port):
def __init__(self, src_port, trg_port, emit_signal):
QtWidgets.QUndoCommand.__init__(self)
self.source = src_port
self.target = trg_port
self.emit_signal = emit_signal

def undo(self):
src_model = self.source.model
Expand All @@ -340,6 +377,13 @@ def undo(self):

self.source.view.connect_to(self.target.view)

# emit "port_connected" signal from the parent graph.
if self.emit_signal:
ports = {p.type_(): p for p in [self.source, self.target]}
graph = self.source.node().graph
graph.port_connected.emit(ports[PortTypeEnum.IN.value],
ports[PortTypeEnum.OUT.value])

def redo(self):
src_model = self.source.model
trg_model = self.target.model
Expand All @@ -360,6 +404,13 @@ def redo(self):

self.source.view.disconnect_from(self.target.view)

# emit "port_disconnected" signal from the parent graph.
if self.emit_signal:
ports = {p.type_(): p for p in [self.source, self.target]}
graph = self.source.node().graph
graph.port_disconnected.emit(ports[PortTypeEnum.IN.value],
ports[PortTypeEnum.OUT.value])


class PortLockedCmd(QtWidgets.QUndoCommand):
"""
Expand Down
37 changes: 21 additions & 16 deletions NodeGraphQt/base/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from Qt import QtCore, QtWidgets

from NodeGraphQt.base.commands import (NodeAddedCmd,
NodeRemovedCmd,
NodesRemovedCmd,
NodeMovedCmd,
PortConnectedCmd)
from NodeGraphQt.base.factory import NodeFactory
Expand Down Expand Up @@ -1255,7 +1255,9 @@ def format_color(clr):

node.update()

undo_cmd = NodeAddedCmd(self, node, node.model.pos)
undo_cmd = NodeAddedCmd(
self, node, pos=node.model.pos, emit_signal=True
)
if push_undo:
undo_label = 'create node: "{}"'.format(node.NODE_NAME)
self._undo_stack.beginMacro(undo_label)
Expand All @@ -1266,10 +1268,10 @@ def format_color(clr):
else:
for n in self.selected_nodes():
n.set_property('selected', False, push_undo=False)
NodeAddedCmd(self, node, node.model.pos).redo()
undo_cmd.redo()

self.node_created.emit(node)
return node

raise NodeCreationError('Can\'t find node: "{}"'.format(node_type))

def add_node(self, node, pos=None, selected=True, push_undo=True):
Expand Down Expand Up @@ -1341,14 +1343,15 @@ def add_node(self, node, pos=None, selected=True, push_undo=True):
# update method must be called before it's been added to the viewer.
node.update()

undo_cmd = NodeAddedCmd(self, node, pos=pos, emit_signal=False)
if push_undo:
self._undo_stack.beginMacro('add node: "{}"'.format(node.name()))
self._undo_stack.push(NodeAddedCmd(self, node, pos))
self._undo_stack.push(undo_cmd)
if selected:
node.set_selected(True)
self._undo_stack.endMacro()
else:
NodeAddedCmd(self, node, pos).redo()
undo_cmd.redo()

def delete_node(self, node, push_undo=True):
"""
Expand Down Expand Up @@ -1382,13 +1385,12 @@ def delete_node(self, node, push_undo=True):
if isinstance(node, GroupNode) and node.is_expanded:
node.collapse()

undo_cmd = NodesRemovedCmd(self, [node], emit_signal=True)
if push_undo:
self._undo_stack.push(NodeRemovedCmd(self, node))
self._undo_stack.push(undo_cmd)
self._undo_stack.endMacro()
else:
NodeRemovedCmd(self, node).redo()

self.nodes_deleted.emit([node_id])
undo_cmd.redo()

def remove_node(self, node, push_undo=True):
"""
Expand Down Expand Up @@ -1425,11 +1427,12 @@ def remove_node(self, node, push_undo=True):
push_undo=push_undo)
p.clear_connections(push_undo=push_undo)

undo_cmd = NodesRemovedCmd(self, [node], emit_signal=False)
if push_undo:
self._undo_stack.push(NodeRemovedCmd(self, node))
self._undo_stack.push(undo_cmd)
self._undo_stack.endMacro()
else:
NodeRemovedCmd(self, node).redo()
undo_cmd.redo()

def delete_nodes(self, nodes, push_undo=True):
"""
Expand Down Expand Up @@ -1468,12 +1471,14 @@ def delete_nodes(self, nodes, push_undo=True):
connected_ports=False,
push_undo=push_undo)
p.clear_connections(push_undo=push_undo)
if push_undo:
self._undo_stack.push(NodeRemovedCmd(self, node))
else:
NodeRemovedCmd(self, node).redo()

undo_cmd = NodesRemovedCmd(self, nodes, emit_signal=True)
if push_undo:
self._undo_stack.push(undo_cmd)
self._undo_stack.endMacro()
else:
undo_cmd.redo()

self.nodes_deleted.emit(node_ids)

def extract_nodes(self, nodes, push_undo=True, prompt_warning=True):
Expand Down
Loading

0 comments on commit bea91e9

Please sign in to comment.