[commands] new AddEdge/RemoveEdge commands

This commit is contained in:
Yann Lanthony 2017-10-13 10:53:49 +02:00
parent e4ccef2187
commit d4509ec20e
2 changed files with 60 additions and 11 deletions

View file

@ -97,12 +97,13 @@ class Attribute(BaseObject):
# only dependent of the linked node uid, so it is independent # only dependent of the linked node uid, so it is independent
# from the cache folder which may be used in the filepath. # from the cache folder which may be used in the filepath.
return self.node.uid() return self.node.uid()
if self.isLink(): if self.isLink:
return self.getLinkParam().uid() return self.getLinkParam().uid()
if isinstance(self._value, basestring): if isinstance(self._value, basestring):
return hash(str(self._value)) return hash(str(self._value))
return hash(self._value) return hash(self._value)
@property
def isLink(self): def isLink(self):
""" """
If the attribute is a link to another attribute. If the attribute is a link to another attribute.
@ -113,7 +114,7 @@ class Attribute(BaseObject):
return self in self.node.graph.edges.keys() return self in self.node.graph.edges.keys()
def getLinkParam(self): def getLinkParam(self):
if not self.isLink(): if not self.isLink:
return None return None
return self.node.graph.edge(self).src return self.node.graph.edge(self).src
@ -135,7 +136,7 @@ class Attribute(BaseObject):
def getExportValue(self): def getExportValue(self):
value = self._value value = self._value
# print('getExportValue: ', self.name(), value, self.isLink()) # print('getExportValue: ', self.name(), value, self.isLink())
if self.isLink(): if self.isLink:
value = '{' + self.getLinkParam().fullName() + '}' value = '{' + self.getLinkParam().fullName() + '}'
return value return value
@ -144,6 +145,8 @@ class Attribute(BaseObject):
valueChanged = Signal() valueChanged = Signal()
value = Property("QVariant", value.fget, value.fset, notify=valueChanged) value = Property("QVariant", value.fget, value.fset, notify=valueChanged)
isOutput = Property(bool, isOutput.fget, constant=True) isOutput = Property(bool, isOutput.fget, constant=True)
isLinkChanged = Signal()
isLink = Property(bool, isLink.fget, notify=isLinkChanged)
class Edge(BaseObject): class Edge(BaseObject):
@ -602,20 +605,31 @@ class Graph(BaseObject):
nodesWithOutput = set([edge.src.node for edge in self.edges]) nodesWithOutput = set([edge.src.node for edge in self.edges])
return set(self._nodes) - nodesWithOutput return set(self._nodes) - nodesWithOutput
def addEdge(self, outputAttr, inputAttr): def addEdge(self, srcAttr, dstAttr):
assert isinstance(outputAttr, Attribute) assert isinstance(srcAttr, Attribute)
assert isinstance(inputAttr, Attribute) assert isinstance(dstAttr, Attribute)
if outputAttr.node.graph != self or inputAttr.node.graph != self: if srcAttr.node.graph != self or dstAttr.node.graph != self:
raise RuntimeError('The attributes of the edge should be part of a common graph.') raise RuntimeError('The attributes of the edge should be part of a common graph.')
if inputAttr in self.edges.keys(): if dstAttr in self.edges.keys():
raise RuntimeError('Input attribute "{}" is already connected.'.format(inputAttr.fullName())) raise RuntimeError('Destination attribute "{}" is already connected.'.format(dstAttr.fullName()))
self.edges.add(Edge(inputAttr, outputAttr)) edge = Edge(dstAttr, srcAttr)
inputAttr.valueChanged.emit() self.edges.add(edge)
dstAttr.valueChanged.emit()
dstAttr.isLinkChanged.emit()
return edge
def addEdges(self, *edges): def addEdges(self, *edges):
for edge in edges: for edge in edges:
self.addEdge(*edge) self.addEdge(*edge)
def removeEdge(self, dstAttr):
if dstAttr not in self.edges.keys():
raise RuntimeError('Attribute "{}" is not connected'.format(dstAttr.fullName()))
edge = self.edges.pop(dstAttr)
dstAttr.valueChanged.emit()
dstAttr.isLinkChanged.emit()
return edge
def getDepth(self, node): def getDepth(self, node):
return len(self.dfsNodesOnFinish([node])) return len(self.dfsNodesOnFinish([node]))

View file

@ -132,3 +132,38 @@ class SetAttributeCommand(GraphCommand):
def undoImpl(self): def undoImpl(self):
self.graph.node(self.nodeName).attribute(self.attrName).value = self.oldValue self.graph.node(self.nodeName).attribute(self.attrName).value = self.oldValue
class AddEdgeCommand(GraphCommand):
def __init__(self, graph, src, dst, parent=None):
super(AddEdgeCommand, self).__init__(graph, parent)
self.srcNode, self.srcAttr = src.fullName().split(".")
self.dstNode, self.dstAttr = dst.fullName().split(".")
self.setText("Connect '{}'->'{}'".format(src.fullName(), dst.fullName()))
def redoImpl(self):
try:
self.graph.addEdge(self.graph.node(self.srcNode).attribute(self.srcAttr),
self.graph.node(self.dstNode).attribute(self.dstAttr))
except RuntimeError:
return False
return True
def undoImpl(self):
self.graph.removeEdge(self.graph.node(self.dstNode).attribute(self.dstAttr))
class RemoveEdgeCommand(GraphCommand):
def __init__(self, graph, edge, parent=None):
super(RemoveEdgeCommand, self).__init__(graph, parent)
self.srcNode, self.srcAttr = edge.src.fullName().split(".")
self.dstNode, self.dstAttr = edge.dst.fullName().split(".")
self.setText("Disconnect '{}'->'{}'".format(edge.src.fullName(), edge.dst.fullName()))
def redoImpl(self):
self.graph.removeEdge(self.graph.node(self.dstNode).attribute(self.dstAttr))
return True
def undoImpl(self):
self.graph.addEdge(self.graph.node(self.srcNode).attribute(self.srcAttr),
self.graph.node(self.dstNode).attribute(self.dstAttr))