mirror of https://gitlab.com/pamhyr/pamhyr2
network: Add some features.
parent
9e892ba587
commit
df1a77aa4f
|
|
@ -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
|
||||
angle = math.acos(line.dx() / line.length())
|
||||
if line.dy() >= 0:
|
||||
angle = (math.pi * 2.0) - 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)
|
||||
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.setBrush(Qt.black)
|
||||
# painter.drawPolygon(QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
|
||||
# painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue