Commit df1a77aa authored by Pierre-Antoine Rouby's avatar Pierre-Antoine Rouby
Browse files

network: Add some features.

Showing with 166 additions and 58 deletions
+166 -58
......@@ -71,3 +71,17 @@ class Graph(object):
def remove_edge(self, edge_name:str):
self._edges = list(filter(lambda e: e.name != edge_name, self._edges))
def is_upstream_node(self, node):
return reduce(
lambda acc, e: (acc and (e.node2 != node)),
self._edges,
True
)
def is_downstream_node(self, node):
return reduce(
lambda acc, e: (acc and (e.node1 != node)),
self._edges,
True
)
......@@ -201,3 +201,9 @@ class NetworkWindow(ASubWindow):
self.graph_widget.state("del")
else:
self.graph_widget.state("move")
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Escape:
self.graph_widget.reset_selection
......@@ -90,10 +90,14 @@ class NodeItem(QGraphicsItem):
painter.setPen(Qt.NoPen)
color = Qt.yellow
if self.graph.selectedNode() == self:
color = Qt.red
if self.graph.selectedNewEdgeSrcNode() == self:
color = Qt.darkRed
elif self.graph.selectedItem() == self:
color = Qt.red
elif self.graph.graph.is_upstream_node(self.node):
color = Qt.blue
elif self.graph.graph.is_downstream_node(self.node):
color = Qt.green
painter.setBrush(QBrush(color))
painter.drawEllipse(-10, -10, 20, 20)
......@@ -108,8 +112,10 @@ class NodeItem(QGraphicsItem):
def mousePressEvent(self, event):
# Switch selected node
if not self.graph.selectedNewEdgeSrcNode():
self.graph.setSelectedNode(self)
# if not self.graph.selectedItem() is self:
# self.graph.setSelectedItem(self)
# elif self.graph.selectedItem() is self:
# self.graph.setSelectedNewEdgeSrcNode(self)
self.update()
super(NodeItem, self).mousePressEvent(event)
......@@ -163,8 +169,8 @@ class EdgeItem(QGraphicsItem):
self.prepareGeometryChange()
def boundingRect(self):
penWidth = 1.0
extra = (penWidth + 5) / 2.0
pen_width = 3.0
extra = (pen_width + 5) / 2.0
return QRectF(
self.src_pos,
......@@ -181,27 +187,64 @@ class EdgeItem(QGraphicsItem):
if line.length() == 0.0:
return
painter.setPen(QPen(Qt.black, 1, Qt.SolidLine, Qt.RoundCap,
Qt.RoundJoin))
color = Qt.blue
if self.graph.selectedItem() == self:
color = Qt.red
painter.setPen(QPen(color, 3, Qt.SolidLine, Qt.RoundCap,
Qt.RoundJoin))
painter.drawLine(line)
line_center = QPointF(
(self.src_node.pos().x() + self.dest_node.pos().x()) / 2,
(self.src_node.pos().y() + self.dest_node.pos().y()) / 2,
)
# Draw the arrows if there's enough room.
# angle = math.acos(line.dx() / line.length())
# if line.dy() >= 0:
# angle = Edge.TwoPi - angle
# sourceArrowP1 = self.sourcePoint + QPointF(math.sin(angle + Edge.Pi / 3) * self.arrowSize,
# math.cos(angle + Edge.Pi / 3) * self.arrowSize)
# sourceArrowP2 = self.sourcePoint + QPointF(math.sin(angle + Edge.Pi - Edge.Pi / 3) * self.arrowSize,
# math.cos(angle + Edge.Pi - Edge.Pi / 3) * self.arrowSize);
# destArrowP1 = self.destPoint + QPointF(math.sin(angle - Edge.Pi / 3) * self.arrowSize,
# math.cos(angle - Edge.Pi / 3) * self.arrowSize)
# destArrowP2 = self.destPoint + QPointF(math.sin(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize,
# math.cos(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize)
# painter.setBrush(Qt.black)
# painter.drawPolygon(QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
# painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))
angle = math.acos(line.dx() / line.length())
if line.dy() >= 0:
angle = (math.pi * 2.0) - angle
size = 10.0
arrow_p1 = line_center + QPointF(
math.sin(angle - math.pi / 3) * size,
math.cos(angle - math.pi / 3) * size
)
arrow_p2 = line_center + QPointF(
math.sin(angle - math.pi + math.pi / 3) * size,
math.cos(angle - math.pi + math.pi / 3) * size
)
painter.drawPolygon(QPolygonF([line_center, arrow_p1, arrow_p2]))
class NewEdgeLine(QGraphicsItem):
def __init__(self, src, dest):
super(NewEdgeLine, self).__init__()
self.src = src
self.dest = dest
def boundingRect(self):
pen_width = 2.0
extra = (pen_width + 5) / 2.0
return QRectF(
self.src,
QSizeF(
self.dest.x() - self.src.x(),
self.dest.y() - self.src.y()
)
).normalized().adjusted(-extra, -extra, extra, extra)
def paint(self, painter, option, widget):
line = QLineF(self.src, self.dest)
if line.length() == 0.0:
return
color = Qt.darkGray
painter.setPen(QPen(color, 2, Qt.SolidLine, Qt.RoundCap,
Qt.RoundJoin))
painter.drawLine(line)
class GraphWidget(QGraphicsView):
changeEdge = pyqtSignal(object)
......@@ -214,8 +257,9 @@ class GraphWidget(QGraphicsView):
self.parent = parent
self._state = "move"
self._selectedNode = None
self._selectedItem = None
self._selectedNewEdgeSrcNode = None
self.tmp_line = None
self.node_items = []
self.edge_items = []
......@@ -280,7 +324,8 @@ class GraphWidget(QGraphicsView):
self.changeNode.emit(self.sender())
def del_node(self, node):
def del_node(self, item):
node = item.node
edges = list(
filter(
lambda ie: ie.edge.node1 == node or ie.edge.node2 == node,
......@@ -302,14 +347,27 @@ class GraphWidget(QGraphicsView):
if node1 == node2:
return
edge = self.graph.add_edge(node1.node, node2.node)
iedge = EdgeItem(node1, node2, edge, self)
self.scene().addItem(iedge)
self.edge_items.append(iedge)
self.setSelectedNode(None)
# iedge = EdgeItem(node1, node2, edge, self)
# self.scene().addItem(iedge)
# self.edge_items.append(iedge)
self.setSelectedNewEdgeSrcNode(None)
self.tmp_line = None
self.scene().clear()
self.create_items()
self.changeEdge.emit(self.sender())
def del_edge(self, item):
edge = item.edge
self.graph.remove_edge(edge.name)
self.scene().clear()
self.create_items()
self.changeNode.emit(self.sender())
self.changeEdge.emit(self.sender())
def update_edges(self, node):
edges = list(
filter(
......@@ -319,6 +377,8 @@ class GraphWidget(QGraphicsView):
)
for edge in edges:
# edge.node1.update()
# edge.node2.update()
edge.update()
def itemMoved(self):
......@@ -328,14 +388,12 @@ class GraphWidget(QGraphicsView):
def nodeChangePosition(self, pos, node):
node.node.setPos(pos.x(), pos.y())
def selectedNode(self):
return self._selectedNode
def selectedItem(self):
return self._selectedItem
def setSelectedNode(self, node):
previous_node = self._selectedNode
self._selectedNode = node
if node:
self.setSelectedNewEdgeSrcNode(None)
def setSelectedItem(self, node):
previous_node = self._selectedItem
self._selectedItem = node
if previous_node:
previous_node.update()
......@@ -346,27 +404,26 @@ class GraphWidget(QGraphicsView):
def setSelectedNewEdgeSrcNode(self, node):
previous_node = self._selectedNewEdgeSrcNode
self._selectedNewEdgeSrcNode = node
if node:
self.setSelectedNode(None)
if previous_node:
previous_node.update()
def reset_selection(self):
self.setSelectedNewEdgeSrcNode(None)
if self.tmp_line is not None:
self.tmp_line = None
self.scene().clear()
self.create_items()
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_Up:
self.centerNode.moveBy(0, -20)
elif key == Qt.Key_Down:
self.centerNode.moveBy(0, 20)
elif key == Qt.Key_Left:
self.centerNode.moveBy(-20, 0)
elif key == Qt.Key_Right:
self.centerNode.moveBy(20, 0)
elif key == Qt.Key_Plus:
if key == Qt.Key_Plus:
self.scaleView(1.2)
elif key == Qt.Key_Minus:
self.scaleView(1 / 1.2)
elif key == Qt.Key_Escape:
self.reset_selection()
elif key == Qt.Key_Space or key == Qt.Key_Enter:
for item in self.scene().items():
if isinstance(item, Node):
......@@ -405,21 +462,28 @@ class GraphWidget(QGraphicsView):
elif self._state == "add":
items = self.items(event.pos())
if not items:
nodes = list(filter(lambda i: type(i) == NodeItem, items))
if not nodes:
self.add_node(pos)
else:
nodes = list(filter(lambda i: type(i) == NodeItem, items))
if self.selectedNewEdgeSrcNode() is None:
self.setSelectedNewEdgeSrcNode(nodes[0])
else:
self.add_edge(self.selectedNewEdgeSrcNode(), nodes[0])
elif self._state == "del":
items = self.items(event.pos())
items = list(
filter(
lambda i: type(i) == NodeItem or type(i) == EdgeItem,
self.items(event.pos())
)
)
if len(items) > 0:
nodes = list(filter(lambda i: type(i) == NodeItem, items))
if len(nodes) > 0:
self.del_node(nodes[0].node)
item = items[0]
if type(item) == NodeItem:
self.del_node(item)
elif type(item) == EdgeItem:
self.del_edge(item)
self.update()
super(GraphWidget, self).mousePressEvent(event)
......@@ -429,6 +493,30 @@ class GraphWidget(QGraphicsView):
super(GraphWidget, self).mouseReleaseEvent(event)
def mouseMoveEvent(self, event):
if self._state == "move":
self.update()
super(GraphWidget, self).mouseMoveEvent(event)
pos = self.mapToScene(event.pos())
items = self.items(event.pos())
selectable_items = list(
filter(
lambda i: type(i) == NodeItem or type(i) == EdgeItem,
items
)
)
if selectable_items:
self.setSelectedItem(selectable_items[0])
else:
self.setSelectedItem(None)
if self.selectedNewEdgeSrcNode() is not None:
if self.tmp_line is None:
self.tmp_line = NewEdgeLine(
self.selectedNewEdgeSrcNode().pos(),
pos
)
self.scene().addItem(self.tmp_line)
else:
self.tmp_line.dest = pos
self.tmp_line.update()
self.update()
super(GraphWidget, self).mouseMoveEvent(event)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment