mirror of https://gitlab.com/pamhyr/pamhyr2
network: Add nodes features.
parent
dc7c7446ff
commit
2c0b265a2b
|
|
@ -19,13 +19,13 @@ class Graph(object):
|
|||
return f"Graph {{nodes: {self._nodes}, edges: {self._edges}}}"
|
||||
|
||||
def nodes(self):
|
||||
return self._nodes.copy()
|
||||
return self._nodes
|
||||
|
||||
def nodes_names(self):
|
||||
return list(map(lambda n: n.name, self._nodes))
|
||||
|
||||
def edges(self):
|
||||
return self._edges.copy()
|
||||
return self._edges
|
||||
|
||||
def nodes_counts(self):
|
||||
return len(self._nodes)
|
||||
|
|
@ -67,7 +67,7 @@ class Graph(object):
|
|||
return edge
|
||||
|
||||
def remove_node(self, node_name:str):
|
||||
self._nodes = filter(lambda n: n.name != node_name, self._nodes)
|
||||
self._nodes = list(filter(lambda n: n.name != node_name, self._nodes))
|
||||
|
||||
def remove_edge(self, edge_name:str):
|
||||
self._edges = filter(lambda e: e.name != edge_name, self._edges)
|
||||
self._edges = list(filter(lambda e: e.name != edge_name, self._edges))
|
||||
|
|
|
|||
|
|
@ -31,3 +31,7 @@ class Node(object):
|
|||
self.name = value
|
||||
elif name == "id":
|
||||
self.id = value
|
||||
|
||||
def setPos(self, x, y):
|
||||
self.pos.x = x
|
||||
self.pos.y = y
|
||||
|
|
|
|||
|
|
@ -63,11 +63,16 @@ class ComboBoxDelegate(QItemDelegate):
|
|||
|
||||
|
||||
class TableModel(QAbstractTableModel):
|
||||
def __init__(self, headers=[], rows=[], graph=None):
|
||||
def __init__(self, headers=[], graph=None, rows_type="nodes"):
|
||||
super(QAbstractTableModel, self).__init__()
|
||||
self.rows = rows
|
||||
self.headers = headers
|
||||
self.graph = graph
|
||||
self._type = rows_type
|
||||
|
||||
if self._type == "nodes":
|
||||
self.rows = graph.nodes()
|
||||
elif self._type == "edges":
|
||||
self.rows = graph.edges()
|
||||
|
||||
def flags(self, index):
|
||||
return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
||||
|
|
@ -113,9 +118,12 @@ class TableModel(QAbstractTableModel):
|
|||
return False
|
||||
|
||||
def update(self):
|
||||
print("update")
|
||||
self.layoutChanged.emit()
|
||||
if self._type == "nodes":
|
||||
self.rows = self.graph.nodes()
|
||||
elif self._type == "edges":
|
||||
self.rows = self.graph.edges()
|
||||
|
||||
self.layoutChanged.emit()
|
||||
|
||||
class NetworkWindow(ASubWindow):
|
||||
def __init__(self, title="Network", parent=None):
|
||||
|
|
@ -123,9 +131,6 @@ class NetworkWindow(ASubWindow):
|
|||
self.ui.setWindowTitle(title)
|
||||
|
||||
self.graph = Graph()
|
||||
n1 = self.graph.add_node()
|
||||
n2 = self.graph.add_node(50.0,50.0)
|
||||
e1 = self.graph.add_edge(n1,n2)
|
||||
|
||||
# Graph Widget
|
||||
|
||||
|
|
@ -143,8 +148,8 @@ class NetworkWindow(ASubWindow):
|
|||
|
||||
self.nodes_model = TableModel(
|
||||
headers = ["name", "id", "pos"],
|
||||
rows = self.graph.nodes(),
|
||||
graph = self.graph,
|
||||
rows_type="nodes",
|
||||
)
|
||||
self.delegate_line = LineEditDelegate(parent=self)
|
||||
table = self.find(QTableView, "tableView_nodes")
|
||||
|
|
@ -156,8 +161,8 @@ class NetworkWindow(ASubWindow):
|
|||
|
||||
self.reachs_model = TableModel(
|
||||
headers = ["name", "node1", "node2"],
|
||||
rows = self.graph.edges(),
|
||||
graph = self.graph,
|
||||
rows_type="edges"
|
||||
)
|
||||
self.delegate_combobox = ComboBoxDelegate(
|
||||
graph = self.graph,
|
||||
|
|
@ -173,20 +178,26 @@ class NetworkWindow(ASubWindow):
|
|||
|
||||
self.nodes_model.dataChanged.connect(self.reachs_model.update)
|
||||
self.reachs_model.dataChanged.connect(self.nodes_model.update)
|
||||
self.graph_widget.changeEdge.connect(self.reachs_model.update)
|
||||
self.graph_widget.changeNode.connect(self.nodes_model.update)
|
||||
|
||||
self.find(QPushButton, "pushButton_add").clicked.connect(
|
||||
self.clicked_add
|
||||
)
|
||||
|
||||
self.find(QPushButton, "pushButton_del").clicked.connect(
|
||||
self.clicked_del
|
||||
)
|
||||
|
||||
|
||||
def clicked_add(self):
|
||||
if self.get_push_button_checkable("pushButton_add"):
|
||||
self.set_push_button_checkable("pushButton_del", False)
|
||||
self.graph_widget.state = "add"
|
||||
else:
|
||||
self.graph_widget.state = "move"
|
||||
|
||||
def clicked_del(self):
|
||||
if self.get_push_button_checkable("pushButton_del"):
|
||||
self.set_push_button_checkable("pushButton_add", False)
|
||||
self.graph_widget.state = "del"
|
||||
else:
|
||||
self.graph_widget.state = "move"
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from model.network.Graph import Graph
|
|||
|
||||
from PyQt5.QtCore import (
|
||||
qAbs, QLineF, QPointF, QPoint, qrand, QRectF, QSizeF, qsrand,
|
||||
Qt, QTime
|
||||
Qt, QTime, pyqtSlot, pyqtSignal,
|
||||
)
|
||||
from PyQt5.QtGui import (
|
||||
QBrush, QColor, QLinearGradient, QPainter,
|
||||
|
|
@ -20,6 +20,36 @@ from PyQt5.QtWidgets import (
|
|||
QGraphicsView, QStyle
|
||||
)
|
||||
|
||||
class LandMark(QGraphicsItem):
|
||||
def __init__(self, width, height, parent=None):
|
||||
super(LandMark, self).__init__()
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
self.center = QPoint(width / 2, height / 2)
|
||||
self.parent = parent
|
||||
|
||||
def paint(self, painter, option, widget):
|
||||
painter.setPen(Qt.NoPen)
|
||||
painter.setPen(QPen(Qt.black, 0))
|
||||
|
||||
painter.drawLine(
|
||||
-10 + self.center.x(), 0 + self.center.y(),
|
||||
10 + self.center.x(), 0 + self.center.y()
|
||||
)
|
||||
painter.drawLine(
|
||||
0 + self.center.x(), -10 + self.center.y(),
|
||||
0 + self.center.x(), 10 + self.center.y()
|
||||
)
|
||||
|
||||
def boundingRect(self):
|
||||
return QRectF(
|
||||
-10 + self.center.x(), -10 + self.center.y(),
|
||||
10 + self.center.x(), 10 + self.center.y()
|
||||
)
|
||||
|
||||
|
||||
class NodeItem(QGraphicsItem):
|
||||
Type = QGraphicsItem.UserType + 1
|
||||
|
||||
|
|
@ -58,33 +88,39 @@ class NodeItem(QGraphicsItem):
|
|||
|
||||
def paint(self, painter, option, widget):
|
||||
painter.setPen(Qt.NoPen)
|
||||
# painter.setBrush(Qt.darkGray)
|
||||
# painter.drawEllipse(-7, -7, 20, 20)
|
||||
|
||||
gradient = QRadialGradient(-3, -3, 10)
|
||||
if option.state & QStyle.State_Sunken:
|
||||
gradient.setCenter(3, 3)
|
||||
gradient.setFocalPoint(3, 3)
|
||||
gradient.setColorAt(1, QColor(Qt.yellow).lighter(120))
|
||||
gradient.setColorAt(0, QColor(Qt.darkYellow).lighter(120))
|
||||
else:
|
||||
gradient.setColorAt(0, Qt.yellow)
|
||||
gradient.setColorAt(1, Qt.darkYellow)
|
||||
color = Qt.yellow
|
||||
if self.graph.selectedNode() == self:
|
||||
color = Qt.red
|
||||
|
||||
painter.setBrush(QBrush(gradient))
|
||||
# painter.setPen(QPen(Qt.black, 0))
|
||||
painter.setBrush(QBrush(color))
|
||||
painter.drawEllipse(-10, -10, 20, 20)
|
||||
|
||||
def itemChange(self, change, value):
|
||||
if change == QGraphicsItem.ItemPositionHasChanged:
|
||||
self.graph.itemMoved()
|
||||
self.graph.nodeChangePosition(value, self)
|
||||
|
||||
return super(NodeItem, self).itemChange(change, value)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
# Switch selected node
|
||||
previous_node = self.graph.selectedNode()
|
||||
self.graph.setSelectedNode(self)
|
||||
|
||||
# Update previous node
|
||||
if previous_node:
|
||||
previous_node.update()
|
||||
|
||||
self.update()
|
||||
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):
|
||||
self.update()
|
||||
super(NodeItem, self).mouseReleaseEvent(event)
|
||||
|
|
@ -191,17 +227,22 @@ class EdgeItem(QGraphicsItem):
|
|||
painter.drawPolygon(QPolygonF([line.p1(), sourceArrowP1, sourceArrowP2]))
|
||||
painter.drawPolygon(QPolygonF([line.p2(), destArrowP1, destArrowP2]))
|
||||
|
||||
|
||||
class GraphWidget(QGraphicsView):
|
||||
changeEdge = pyqtSignal(object)
|
||||
changeNode = pyqtSignal(object)
|
||||
|
||||
def __init__(self, graph, parent=None):
|
||||
super(GraphWidget, self).__init__(parent=parent)
|
||||
|
||||
self.timerId = 0
|
||||
self.parent = parent
|
||||
self.state = "move"
|
||||
|
||||
self._selectedNode = None
|
||||
|
||||
scene = QGraphicsScene(self)
|
||||
scene.setItemIndexMethod(QGraphicsScene.NoIndex)
|
||||
scene.setSceneRect(0, 0, 10000, 10000)
|
||||
scene.setSceneRect(0, 0, 1000, 1000)
|
||||
self.setScene(scene)
|
||||
self.setCacheMode(QGraphicsView.CacheBackground)
|
||||
self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
|
||||
|
|
@ -209,23 +250,49 @@ class GraphWidget(QGraphicsView):
|
|||
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
|
||||
self.setResizeAnchor(QGraphicsView.AnchorViewCenter)
|
||||
|
||||
# scene.addItem(LandMark())
|
||||
|
||||
self.graph = graph
|
||||
for node in self.graph.nodes():
|
||||
scene.addItem(NodeItem(node, self))
|
||||
|
||||
# for edge in self.graph.edges():
|
||||
# scene.addItem(EdgeItem(edge))
|
||||
|
||||
self.scale(1, 1)
|
||||
self.previousScale = 1
|
||||
self.setMinimumSize(400, 400)
|
||||
|
||||
self.create_items()
|
||||
|
||||
def create_items(self):
|
||||
for node in self.graph.nodes():
|
||||
self.scene().addItem(NodeItem(node, self))
|
||||
|
||||
# for edge in self.graph.edges():
|
||||
# scene.addItem(EdgeItem(edge))
|
||||
|
||||
# self.mark = LandMark(1000, 1000, self)
|
||||
# self.scene().addItem(self.mark)
|
||||
|
||||
def add_node(self, pos):
|
||||
node = self.graph.add_node(pos.x(), pos.y())
|
||||
self.scene().addItem(NodeItem(node, self))
|
||||
self.changeNode.emit(self.sender())
|
||||
|
||||
def del_node(self, node):
|
||||
self.scene().clear()
|
||||
self.graph.remove_node(node.name)
|
||||
|
||||
self.create_items()
|
||||
self.changeNode.emit(self.sender())
|
||||
|
||||
def itemMoved(self):
|
||||
if not self.timerId:
|
||||
self.timerId = self.startTimer(1000 / 25)
|
||||
|
||||
def nodeChangePosition(self, pos, node):
|
||||
node.node.setPos(pos.x(), pos.y())
|
||||
|
||||
def selectedNode(self):
|
||||
return self._selectedNode
|
||||
|
||||
def setSelectedNode(self, node):
|
||||
self._selectedNode = node
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
key = event.key()
|
||||
|
||||
|
|
@ -270,3 +337,36 @@ class GraphWidget(QGraphicsView):
|
|||
# print(f"{scaleFactor} : {factor}")
|
||||
|
||||
self.scale(scaleFactor, scaleFactor)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
pos = self.mapToScene(event.pos())
|
||||
if self.state == "move":
|
||||
self.mouse_origin_x = pos.x
|
||||
self.mouse_origin_y = pos.y
|
||||
|
||||
elif self.state == "add":
|
||||
items = self.items(event.pos())
|
||||
if not items:
|
||||
self.add_node(pos)
|
||||
else:
|
||||
print(f"TODO add edge {items}")
|
||||
|
||||
elif self.state == "del":
|
||||
items = self.items(event.pos())
|
||||
print(f"del: {items}")
|
||||
if len(items) > 0:
|
||||
nodes = list(filter(lambda i: type(i) == NodeItem, items))
|
||||
if len(nodes) > 0:
|
||||
self.del_node(nodes[0].node)
|
||||
|
||||
self.update()
|
||||
super(GraphWidget, self).mousePressEvent(event)
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.update()
|
||||
super(GraphWidget, self).mouseReleaseEvent(event)
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
if self.state == "move":
|
||||
self.update()
|
||||
super(GraphWidget, self).mouseMoveEvent(event)
|
||||
|
|
|
|||
Loading…
Reference in New Issue