Skip to content

Commit 1896ebd

Browse files
committed
horizontal cyclic node connection pipe drawing.
1 parent 68db17c commit 1896ebd

File tree

2 files changed

+87
-10
lines changed

2 files changed

+87
-10
lines changed

NodeGraphQt/qgraphics/pipe.py

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,46 @@ def paint(self, painter, option, widget):
158158
# QPaintDevice: Cannot destroy paint device that is being painted.
159159
painter.restore()
160160

161+
def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path):
162+
"""
163+
Draws the pipe path around the node if the in port and out port
164+
connect to each other for cycle connection.
165+
166+
Args:
167+
start_port (PortItem): port used to draw the starting point.
168+
pos1 (QPointF): start port position.
169+
pos2 (QPointF): end port position.
170+
path (QPainterPath): path to draw.
171+
"""
172+
173+
def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path):
174+
"""
175+
Draws the pipe path around the node if the in port and out port
176+
connect to each other for cycle connection.
177+
178+
Args:
179+
start_port (PortItem): port used to draw the starting point.
180+
pos1 (QPointF): start port position.
181+
pos2 (QPointF): end port position.
182+
path (QPainterPath): path to draw.
183+
"""
184+
ptype = start_port.port_type
185+
in_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2
186+
out_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1
187+
188+
n_rect = start_port.node.boundingRect()
189+
padding = 40
190+
191+
left = out_pos.x() + padding
192+
right = in_pos.x() - padding
193+
path.moveTo(out_pos)
194+
path.lineTo(left, out_pos.y())
195+
path.lineTo(left, out_pos.y() + n_rect.bottom())
196+
path.lineTo(right, out_pos.y() + n_rect.bottom())
197+
path.lineTo(right, in_pos.y())
198+
path.lineTo(in_pos)
199+
self.setPath(path)
200+
161201
def __draw_path_vertical(self, start_port, pos1, pos2, path):
162202
"""
163203
Draws the vertical path between ports.
@@ -274,45 +314,76 @@ def draw_path(self, start_port, end_port=None, cursor_pos=None):
274314
path = QtGui.QPainterPath()
275315
path.moveTo(line.x1(), line.y1())
276316

317+
direction = self.viewer_layout_direction()
318+
319+
if end_port and not self.viewer().acyclic:
320+
if end_port.node == start_port.node:
321+
if direction is LayoutDirectionEnum.VERTICAL.value:
322+
self.__draw_path_cycled_vertical(
323+
start_port, pos1, pos2, path
324+
)
325+
return
326+
elif direction is LayoutDirectionEnum.HORIZONTAL.value:
327+
self.__draw_path_cycled_horizontal(
328+
start_port, pos1, pos2, path
329+
)
330+
return
331+
277332
if self.viewer_pipe_layout() == PipeLayoutEnum.STRAIGHT.value:
278333
path.lineTo(pos2)
279334
self.setPath(path)
280335
return
281336

282-
if self.viewer_layout_direction() is LayoutDirectionEnum.VERTICAL.value:
337+
if direction is LayoutDirectionEnum.VERTICAL.value:
283338
self.__draw_path_vertical(start_port, pos1, pos2, path)
284-
elif self.viewer_layout_direction() is LayoutDirectionEnum.HORIZONTAL.value:
339+
elif direction is LayoutDirectionEnum.HORIZONTAL.value:
285340
self.__draw_path_horizontal(start_port, pos1, pos2, path)
286341

287342
def reset_path(self):
288343
path = QtGui.QPainterPath(QtCore.QPointF(0.0, 0.0))
289344
self.setPath(path)
290345

291346
@staticmethod
292-
def calc_distance(p1, p2):
347+
def _calc_distance(p1, p2):
293348
x = math.pow((p2.x() - p1.x()), 2)
294349
y = math.pow((p2.y() - p1.y()), 2)
295350
return math.sqrt(x + y)
296351

297352
def port_from_pos(self, pos, reverse=False):
298353
inport_pos = self.input_port.scenePos()
299354
outport_pos = self.output_port.scenePos()
300-
input_dist = self.calc_distance(inport_pos, pos)
301-
output_dist = self.calc_distance(outport_pos, pos)
355+
input_dist = self._calc_distance(inport_pos, pos)
356+
output_dist = self._calc_distance(outport_pos, pos)
302357
if input_dist < output_dist:
303358
port = self.output_port if reverse else self.input_port
304359
else:
305360
port = self.input_port if reverse else self.output_port
306361
return port
307362

308-
def viewer_pipe_layout(self):
363+
def viewer(self):
364+
"""
365+
Returns:
366+
NodeViewer: node graph viewer.
367+
"""
309368
if self.scene():
310-
viewer = self.scene().viewer()
369+
return self.scene().viewer()
370+
371+
def viewer_pipe_layout(self):
372+
"""
373+
Returns:
374+
int: pipe layout mode.
375+
"""
376+
viewer = self.viewer()
377+
if viewer:
311378
return viewer.get_pipe_layout()
312379

313380
def viewer_layout_direction(self):
314-
if self.scene():
315-
viewer = self.scene().viewer()
381+
"""
382+
Returns:
383+
int: graph layout mode.
384+
"""
385+
viewer = self.viewer()
386+
if viewer:
316387
return viewer.get_layout_direction()
317388

318389
def activate(self):

NodeGraphQt/widgets/viewer.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -897,14 +897,20 @@ def apply_live_connection(self, event):
897897
if self._start_port is end_port:
898898
return
899899

900+
# if connection to itself
901+
same_node_connection = end_port.node == self._start_port.node
902+
if not self.acyclic:
903+
# allow a node cycle connection.
904+
same_node_connection = False
905+
900906
# restore connection check.
901907
restore_connection = any([
902908
# if the end port is locked.
903909
end_port.locked,
904910
# if same port type.
905911
end_port.port_type == self._start_port.port_type,
906912
# if connection to itself.
907-
end_port.node == self._start_port.node,
913+
same_node_connection,
908914
# if end port is the start port.
909915
end_port == self._start_port,
910916
# if detached port is the end port.

0 commit comments

Comments
 (0)