Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion NodeGraphQt/pkg_info.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
__version__ = '0.5.9'
__version__ = '0.5.10'
__status__ = 'Work in Progress'
__license__ = 'MIT'

Expand Down
102 changes: 93 additions & 9 deletions NodeGraphQt/qgraphics/pipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,58 @@ def paint(self, painter, option, widget):
# QPaintDevice: Cannot destroy paint device that is being painted.
painter.restore()

def __draw_path_cycled_vertical(self, start_port, pos1, pos2, path):
"""
Draw pipe vertically around node if connection is cyclic.

Args:
start_port (PortItem): port used to draw the starting point.
pos1 (QPointF): start port position.
pos2 (QPointF): end port position.
path (QPainterPath): path to draw.
"""
n_rect = start_port.node.boundingRect()
ptype = start_port.port_type
start_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2
end_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1

padding = 40
top = start_pos.y() - padding
bottom = end_pos.y() + padding
path.moveTo(end_pos)
path.lineTo(end_pos.x(), bottom)
path.lineTo(end_pos.x() + n_rect.right(), bottom)
path.lineTo(end_pos.x() + n_rect.right(), top)
path.lineTo(start_pos.x(), top)
path.lineTo(start_pos)
self.setPath(path)

def __draw_path_cycled_horizontal(self, start_port, pos1, pos2, path):
"""
Draw pipe horizontally around node if connection is cyclic.

Args:
start_port (PortItem): port used to draw the starting point.
pos1 (QPointF): start port position.
pos2 (QPointF): end port position.
path (QPainterPath): path to draw.
"""
n_rect = start_port.node.boundingRect()
ptype = start_port.port_type
start_pos = pos1 if ptype == PortTypeEnum.IN.value else pos2
end_pos = pos2 if ptype == PortTypeEnum.IN.value else pos1

padding = 40
left = end_pos.x() + padding
right = start_pos.x() - padding
path.moveTo(start_pos)
path.lineTo(right, start_pos.y())
path.lineTo(right, end_pos.y() + n_rect.bottom())
path.lineTo(left, end_pos.y() + n_rect.bottom())
path.lineTo(left, end_pos.y())
path.lineTo(end_pos)
self.setPath(path)

def __draw_path_vertical(self, start_port, pos1, pos2, path):
"""
Draws the vertical path between ports.
Expand Down Expand Up @@ -272,47 +324,79 @@ def draw_path(self, start_port, end_port=None, cursor_pos=None):

line = QtCore.QLineF(pos1, pos2)
path = QtGui.QPainterPath()

direction = self.viewer_layout_direction()

if end_port and not self.viewer().acyclic:
if end_port.node == start_port.node:
if direction is LayoutDirectionEnum.VERTICAL.value:
self.__draw_path_cycled_vertical(
start_port, pos1, pos2, path
)
return
elif direction is LayoutDirectionEnum.HORIZONTAL.value:
self.__draw_path_cycled_horizontal(
start_port, pos1, pos2, path
)
return

path.moveTo(line.x1(), line.y1())

if self.viewer_pipe_layout() == PipeLayoutEnum.STRAIGHT.value:
path.lineTo(pos2)
self.setPath(path)
return

if self.viewer_layout_direction() is LayoutDirectionEnum.VERTICAL.value:
if direction is LayoutDirectionEnum.VERTICAL.value:
self.__draw_path_vertical(start_port, pos1, pos2, path)
elif self.viewer_layout_direction() is LayoutDirectionEnum.HORIZONTAL.value:
elif direction is LayoutDirectionEnum.HORIZONTAL.value:
self.__draw_path_horizontal(start_port, pos1, pos2, path)

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

@staticmethod
def calc_distance(p1, p2):
def _calc_distance(p1, p2):
x = math.pow((p2.x() - p1.x()), 2)
y = math.pow((p2.y() - p1.y()), 2)
return math.sqrt(x + y)

def port_from_pos(self, pos, reverse=False):
inport_pos = self.input_port.scenePos()
outport_pos = self.output_port.scenePos()
input_dist = self.calc_distance(inport_pos, pos)
output_dist = self.calc_distance(outport_pos, pos)
input_dist = self._calc_distance(inport_pos, pos)
output_dist = self._calc_distance(outport_pos, pos)
if input_dist < output_dist:
port = self.output_port if reverse else self.input_port
else:
port = self.input_port if reverse else self.output_port
return port

def viewer_pipe_layout(self):
def viewer(self):
"""
Returns:
NodeViewer: node graph viewer.
"""
if self.scene():
viewer = self.scene().viewer()
return self.scene().viewer()

def viewer_pipe_layout(self):
"""
Returns:
int: pipe layout mode.
"""
viewer = self.viewer()
if viewer:
return viewer.get_pipe_layout()

def viewer_layout_direction(self):
if self.scene():
viewer = self.scene().viewer()
"""
Returns:
int: graph layout mode.
"""
viewer = self.viewer()
if viewer:
return viewer.get_layout_direction()

def activate(self):
Expand Down
8 changes: 7 additions & 1 deletion NodeGraphQt/widgets/viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -897,14 +897,20 @@ def apply_live_connection(self, event):
if self._start_port is end_port:
return

# if connection to itself
same_node_connection = end_port.node == self._start_port.node
if not self.acyclic:
# allow a node cycle connection.
same_node_connection = False

# restore connection check.
restore_connection = any([
# if the end port is locked.
end_port.locked,
# if same port type.
end_port.port_type == self._start_port.port_type,
# if connection to itself.
end_port.node == self._start_port.node,
same_node_connection,
# if end port is the start port.
end_port == self._start_port,
# if detached port is the end port.
Expand Down