mirror of https://gitlab.com/pamhyr/pamhyr2
network: Add edge feature and delete node feature.
parent
2c0b265a2b
commit
9e892ba587
|
|
@ -191,13 +191,13 @@ class NetworkWindow(ASubWindow):
|
||||||
def clicked_add(self):
|
def clicked_add(self):
|
||||||
if self.get_push_button_checkable("pushButton_add"):
|
if self.get_push_button_checkable("pushButton_add"):
|
||||||
self.set_push_button_checkable("pushButton_del", False)
|
self.set_push_button_checkable("pushButton_del", False)
|
||||||
self.graph_widget.state = "add"
|
self.graph_widget.state("add")
|
||||||
else:
|
else:
|
||||||
self.graph_widget.state = "move"
|
self.graph_widget.state("move")
|
||||||
|
|
||||||
def clicked_del(self):
|
def clicked_del(self):
|
||||||
if self.get_push_button_checkable("pushButton_del"):
|
if self.get_push_button_checkable("pushButton_del"):
|
||||||
self.set_push_button_checkable("pushButton_add", False)
|
self.set_push_button_checkable("pushButton_add", False)
|
||||||
self.graph_widget.state = "del"
|
self.graph_widget.state("del")
|
||||||
else:
|
else:
|
||||||
self.graph_widget.state = "move"
|
self.graph_widget.state("move")
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,8 @@ class NodeItem(QGraphicsItem):
|
||||||
color = Qt.yellow
|
color = Qt.yellow
|
||||||
if self.graph.selectedNode() == self:
|
if self.graph.selectedNode() == self:
|
||||||
color = Qt.red
|
color = Qt.red
|
||||||
|
if self.graph.selectedNewEdgeSrcNode() == self:
|
||||||
|
color = Qt.darkRed
|
||||||
|
|
||||||
painter.setBrush(QBrush(color))
|
painter.setBrush(QBrush(color))
|
||||||
painter.drawEllipse(-10, -10, 20, 20)
|
painter.drawEllipse(-10, -10, 20, 20)
|
||||||
|
|
@ -101,26 +103,17 @@ class NodeItem(QGraphicsItem):
|
||||||
self.graph.itemMoved()
|
self.graph.itemMoved()
|
||||||
self.graph.nodeChangePosition(value, self)
|
self.graph.nodeChangePosition(value, self)
|
||||||
|
|
||||||
|
self.graph.update_edges(self)
|
||||||
return super(NodeItem, self).itemChange(change, value)
|
return super(NodeItem, self).itemChange(change, value)
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
# Switch selected node
|
# Switch selected node
|
||||||
previous_node = self.graph.selectedNode()
|
if not self.graph.selectedNewEdgeSrcNode():
|
||||||
self.graph.setSelectedNode(self)
|
self.graph.setSelectedNode(self)
|
||||||
|
|
||||||
# Update previous node
|
|
||||||
if previous_node:
|
|
||||||
previous_node.update()
|
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
super(NodeItem, self).mousePressEvent(event)
|
super(NodeItem, self).mousePressEvent(event)
|
||||||
|
|
||||||
# def mouseMoveEvent(self, event):
|
|
||||||
# self.node.setPos(event.pos().x(), event.pos().y())
|
|
||||||
|
|
||||||
# self.update()
|
|
||||||
# super(NodeItem, self).mousePressEvent(event)
|
|
||||||
|
|
||||||
def mouseReleaseEvent(self, event):
|
def mouseReleaseEvent(self, event):
|
||||||
self.update()
|
self.update()
|
||||||
super(NodeItem, self).mouseReleaseEvent(event)
|
super(NodeItem, self).mouseReleaseEvent(event)
|
||||||
|
|
@ -128,79 +121,62 @@ class NodeItem(QGraphicsItem):
|
||||||
class EdgeItem(QGraphicsItem):
|
class EdgeItem(QGraphicsItem):
|
||||||
Type = QGraphicsItem.UserType + 2
|
Type = QGraphicsItem.UserType + 2
|
||||||
|
|
||||||
def __init__(self, edge):
|
def __init__(self, src_node_item, dest_node_item, edge, graph_widget):
|
||||||
super(EdgeItem, self).__init__()
|
super(EdgeItem, self).__init__()
|
||||||
|
|
||||||
self.arrowSize = 10.0
|
self.src_node = src_node_item
|
||||||
self.sourcePoint = QPointF()
|
self.dest_node = dest_node_item
|
||||||
self.destPoint = QPointF()
|
self.edge = edge
|
||||||
|
|
||||||
|
self.graph = graph_widget
|
||||||
|
|
||||||
|
self.src_pos = src_node_item.pos()
|
||||||
|
self.dest_pos = dest_node_item.pos()
|
||||||
|
|
||||||
self.setAcceptedMouseButtons(Qt.NoButton)
|
self.setAcceptedMouseButtons(Qt.NoButton)
|
||||||
self.source = edge.node1
|
|
||||||
self.dest = edge.node2
|
|
||||||
self.edge = edge
|
|
||||||
self.adjust()
|
self.adjust()
|
||||||
|
|
||||||
def type(self):
|
def type(self):
|
||||||
return Edge.Type
|
return Edge.Type
|
||||||
|
|
||||||
def sourceNode(self):
|
def sourceNode(self):
|
||||||
return self.source
|
return self.src_node.node
|
||||||
|
|
||||||
def setSourceNode(self, node):
|
def setSourceNode(self, node_item):
|
||||||
self.source = node
|
self.src_node = node_item
|
||||||
self.adjust()
|
self.adjust()
|
||||||
|
|
||||||
def destNode(self):
|
def destNode(self):
|
||||||
return self.dest
|
return self.dest
|
||||||
|
|
||||||
def setDestNode(self, node):
|
def setDestNode(self, node_item):
|
||||||
self.dest = node
|
self.dest_node = node_item
|
||||||
self.adjust()
|
self.adjust()
|
||||||
|
|
||||||
def adjust(self):
|
def adjust(self):
|
||||||
if not self.source or not self.dest:
|
|
||||||
return
|
|
||||||
|
|
||||||
line = QLineF(
|
line = QLineF(
|
||||||
self.mapFromItem(self.source, 0, 0),
|
self.mapFromItem(self.src_node, 0, 0),
|
||||||
self.mapFromItem(self.dest, 0, 0)
|
self.mapFromItem(self.dest_node, 0, 0)
|
||||||
)
|
)
|
||||||
length = line.length()
|
length = line.length()
|
||||||
|
|
||||||
self.prepareGeometryChange()
|
self.prepareGeometryChange()
|
||||||
|
|
||||||
if length > 20.0:
|
|
||||||
edgeOffset = QPointF((line.dx() * 10) / length,
|
|
||||||
(line.dy() * 10) / length)
|
|
||||||
|
|
||||||
self.sourcePoint = line.p1() + edgeOffset
|
|
||||||
self.destPoint = line.p2() - edgeOffset
|
|
||||||
else:
|
|
||||||
self.sourcePoint = line.p1()
|
|
||||||
self.destPoint = line.p1()
|
|
||||||
|
|
||||||
def boundingRect(self):
|
def boundingRect(self):
|
||||||
if not self.source or not self.dest:
|
|
||||||
return QRectF()
|
|
||||||
|
|
||||||
penWidth = 1.0
|
penWidth = 1.0
|
||||||
extra = (penWidth + self.arrowSize) / 2.0
|
extra = (penWidth + 5) / 2.0
|
||||||
|
|
||||||
return QRectF(
|
return QRectF(
|
||||||
self.sourcePoint,
|
self.src_pos,
|
||||||
QSizeF(
|
QSizeF(
|
||||||
self.destPoint.x() - self.sourcePoint.x(),
|
self.dest_pos.x() - self.src_pos.x(),
|
||||||
self.destPoint.y() - self.sourcePoint.y()
|
self.dest_pos.y() - self.src_pos.y()
|
||||||
)
|
)
|
||||||
).normalized().adjusted(-extra, -extra, extra, extra)
|
).normalized().adjusted(-extra, -extra, extra, extra)
|
||||||
|
|
||||||
def paint(self, painter, option, widget):
|
def paint(self, painter, option, widget):
|
||||||
if not self.source or not self.dest:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Draw the line itself.
|
# Draw the line itself.
|
||||||
line = QLineF(self.sourcePoint, self.destPoint)
|
line = QLineF(self.src_node.pos(), self.dest_node.pos())
|
||||||
|
|
||||||
if line.length() == 0.0:
|
if line.length() == 0.0:
|
||||||
return
|
return
|
||||||
|
|
@ -210,22 +186,22 @@ class EdgeItem(QGraphicsItem):
|
||||||
painter.drawLine(line)
|
painter.drawLine(line)
|
||||||
|
|
||||||
# Draw the arrows if there's enough room.
|
# Draw the arrows if there's enough room.
|
||||||
angle = math.acos(line.dx() / line.length())
|
# angle = math.acos(line.dx() / line.length())
|
||||||
if line.dy() >= 0:
|
# if line.dy() >= 0:
|
||||||
angle = Edge.TwoPi - angle
|
# angle = Edge.TwoPi - angle
|
||||||
|
|
||||||
sourceArrowP1 = self.sourcePoint + QPointF(math.sin(angle + Edge.Pi / 3) * self.arrowSize,
|
# sourceArrowP1 = self.sourcePoint + QPointF(math.sin(angle + Edge.Pi / 3) * self.arrowSize,
|
||||||
math.cos(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,
|
# sourceArrowP2 = self.sourcePoint + QPointF(math.sin(angle + Edge.Pi - Edge.Pi / 3) * self.arrowSize,
|
||||||
math.cos(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,
|
# destArrowP1 = self.destPoint + QPointF(math.sin(angle - Edge.Pi / 3) * self.arrowSize,
|
||||||
math.cos(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,
|
# destArrowP2 = self.destPoint + QPointF(math.sin(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize,
|
||||||
math.cos(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize)
|
# math.cos(angle - Edge.Pi + Edge.Pi / 3) * self.arrowSize)
|
||||||
|
|
||||||
painter.setBrush(Qt.black)
|
# painter.setBrush(Qt.black)
|
||||||
painter.drawPolygon(QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
|
# painter.drawPolygon(QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
|
||||||
painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))
|
# painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))
|
||||||
|
|
||||||
class GraphWidget(QGraphicsView):
|
class GraphWidget(QGraphicsView):
|
||||||
changeEdge = pyqtSignal(object)
|
changeEdge = pyqtSignal(object)
|
||||||
|
|
@ -236,9 +212,13 @@ class GraphWidget(QGraphicsView):
|
||||||
|
|
||||||
self.timerId = 0
|
self.timerId = 0
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.state = "move"
|
self._state = "move"
|
||||||
|
|
||||||
self._selectedNode = None
|
self._selectedNode = None
|
||||||
|
self._selectedNewEdgeSrcNode = None
|
||||||
|
|
||||||
|
self.node_items = []
|
||||||
|
self.edge_items = []
|
||||||
|
|
||||||
scene = QGraphicsScene(self)
|
scene = QGraphicsScene(self)
|
||||||
scene.setItemIndexMethod(QGraphicsScene.NoIndex)
|
scene.setItemIndexMethod(QGraphicsScene.NoIndex)
|
||||||
|
|
@ -259,26 +239,87 @@ class GraphWidget(QGraphicsView):
|
||||||
self.create_items()
|
self.create_items()
|
||||||
|
|
||||||
def create_items(self):
|
def create_items(self):
|
||||||
for node in self.graph.nodes():
|
self.node_items = []
|
||||||
self.scene().addItem(NodeItem(node, self))
|
self.edge_items = []
|
||||||
|
|
||||||
# for edge in self.graph.edges():
|
for node in self.graph.nodes():
|
||||||
# scene.addItem(EdgeItem(edge))
|
inode = NodeItem(node, self)
|
||||||
|
self.scene().addItem(inode)
|
||||||
|
self.node_items.append(inode)
|
||||||
|
|
||||||
|
for edge in self.graph.edges():
|
||||||
|
n1 = list(
|
||||||
|
filter(
|
||||||
|
lambda n: n.node.name == edge.node1.name,
|
||||||
|
self.node_items
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
n2 = list(
|
||||||
|
filter(
|
||||||
|
lambda n: n.node.name == edge.node2.name,
|
||||||
|
self.node_items
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
iedge = EdgeItem(n1[0], n2[0], edge, self)
|
||||||
|
self.scene().addItem(iedge)
|
||||||
|
self.edge_items.append(iedge)
|
||||||
|
|
||||||
# self.mark = LandMark(1000, 1000, self)
|
# self.mark = LandMark(1000, 1000, self)
|
||||||
# self.scene().addItem(self.mark)
|
# self.scene().addItem(self.mark)
|
||||||
|
|
||||||
|
def state(self, status):
|
||||||
|
self._state = status
|
||||||
|
|
||||||
def add_node(self, pos):
|
def add_node(self, pos):
|
||||||
node = self.graph.add_node(pos.x(), pos.y())
|
node = self.graph.add_node(pos.x(), pos.y())
|
||||||
self.scene().addItem(NodeItem(node, self))
|
inode = NodeItem(node, self)
|
||||||
|
self.scene().addItem(inode)
|
||||||
|
self.node_items.append(inode)
|
||||||
|
|
||||||
self.changeNode.emit(self.sender())
|
self.changeNode.emit(self.sender())
|
||||||
|
|
||||||
def del_node(self, node):
|
def del_node(self, node):
|
||||||
self.scene().clear()
|
edges = list(
|
||||||
|
filter(
|
||||||
|
lambda ie: ie.edge.node1 == node or ie.edge.node2 == node,
|
||||||
|
self.edge_items
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for edge in edges:
|
||||||
|
self.graph.remove_edge(edge.edge.name)
|
||||||
|
|
||||||
self.graph.remove_node(node.name)
|
self.graph.remove_node(node.name)
|
||||||
|
|
||||||
|
self.scene().clear()
|
||||||
self.create_items()
|
self.create_items()
|
||||||
self.changeNode.emit(self.sender())
|
self.changeNode.emit(self.sender())
|
||||||
|
self.changeEdge.emit(self.sender())
|
||||||
|
|
||||||
|
def add_edge(self, node1, node2):
|
||||||
|
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)
|
||||||
|
self.setSelectedNewEdgeSrcNode(None)
|
||||||
|
self.changeEdge.emit(self.sender())
|
||||||
|
|
||||||
|
def update_edges(self, node):
|
||||||
|
edges = list(
|
||||||
|
filter(
|
||||||
|
lambda ie: ie.edge.node1 == node.node or ie.edge.node2 == node.node,
|
||||||
|
self.edge_items
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for edge in edges:
|
||||||
|
edge.update()
|
||||||
|
|
||||||
def itemMoved(self):
|
def itemMoved(self):
|
||||||
if not self.timerId:
|
if not self.timerId:
|
||||||
|
|
@ -291,7 +332,25 @@ class GraphWidget(QGraphicsView):
|
||||||
return self._selectedNode
|
return self._selectedNode
|
||||||
|
|
||||||
def setSelectedNode(self, node):
|
def setSelectedNode(self, node):
|
||||||
|
previous_node = self._selectedNode
|
||||||
self._selectedNode = node
|
self._selectedNode = node
|
||||||
|
if node:
|
||||||
|
self.setSelectedNewEdgeSrcNode(None)
|
||||||
|
|
||||||
|
if previous_node:
|
||||||
|
previous_node.update()
|
||||||
|
|
||||||
|
def selectedNewEdgeSrcNode(self):
|
||||||
|
return self._selectedNewEdgeSrcNode
|
||||||
|
|
||||||
|
def setSelectedNewEdgeSrcNode(self, node):
|
||||||
|
previous_node = self._selectedNewEdgeSrcNode
|
||||||
|
self._selectedNewEdgeSrcNode = node
|
||||||
|
if node:
|
||||||
|
self.setSelectedNode(None)
|
||||||
|
|
||||||
|
if previous_node:
|
||||||
|
previous_node.update()
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
key = event.key()
|
key = event.key()
|
||||||
|
|
@ -340,20 +399,23 @@ class GraphWidget(QGraphicsView):
|
||||||
|
|
||||||
def mousePressEvent(self, event):
|
def mousePressEvent(self, event):
|
||||||
pos = self.mapToScene(event.pos())
|
pos = self.mapToScene(event.pos())
|
||||||
if self.state == "move":
|
if self._state == "move":
|
||||||
self.mouse_origin_x = pos.x
|
self.mouse_origin_x = pos.x()
|
||||||
self.mouse_origin_y = pos.y
|
self.mouse_origin_y = pos.y()
|
||||||
|
|
||||||
elif self.state == "add":
|
elif self._state == "add":
|
||||||
items = self.items(event.pos())
|
items = self.items(event.pos())
|
||||||
if not items:
|
if not items:
|
||||||
self.add_node(pos)
|
self.add_node(pos)
|
||||||
else:
|
else:
|
||||||
print(f"TODO add edge {items}")
|
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":
|
elif self._state == "del":
|
||||||
items = self.items(event.pos())
|
items = self.items(event.pos())
|
||||||
print(f"del: {items}")
|
|
||||||
if len(items) > 0:
|
if len(items) > 0:
|
||||||
nodes = list(filter(lambda i: type(i) == NodeItem, items))
|
nodes = list(filter(lambda i: type(i) == NodeItem, items))
|
||||||
if len(nodes) > 0:
|
if len(nodes) > 0:
|
||||||
|
|
@ -367,6 +429,6 @@ class GraphWidget(QGraphicsView):
|
||||||
super(GraphWidget, self).mouseReleaseEvent(event)
|
super(GraphWidget, self).mouseReleaseEvent(event)
|
||||||
|
|
||||||
def mouseMoveEvent(self, event):
|
def mouseMoveEvent(self, event):
|
||||||
if self.state == "move":
|
if self._state == "move":
|
||||||
self.update()
|
self.update()
|
||||||
super(GraphWidget, self).mouseMoveEvent(event)
|
super(GraphWidget, self).mouseMoveEvent(event)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue