A dead branch of implementing the visualisation
We need more object-oriented approach to make this manageable. Keeping this for reference.visu_broken
parent
c500a97fa6
commit
b564a01e82
@ -0,0 +1,133 @@
|
|||||||
|
from birdvisu.maps import Topology, TopologyDifference
|
||||||
|
|
||||||
|
from PySide6 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from enum import Enum, auto
|
||||||
|
|
||||||
|
class NodeType(Enum):
|
||||||
|
ROUTER = auto()
|
||||||
|
NETWORK = auto()
|
||||||
|
|
||||||
|
class NodeStatus(Enum):
|
||||||
|
NORMAL = auto()
|
||||||
|
MISSING = auto()
|
||||||
|
EXTRA = auto()
|
||||||
|
DISCREPANCY = auto()
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class VisualisationNode:
|
||||||
|
position: tuple[float, float]
|
||||||
|
type: NodeType
|
||||||
|
status: NodeStatus
|
||||||
|
details: tuple[str, list]
|
||||||
|
|
||||||
|
def draw_on_scene(self, scene):
|
||||||
|
# FIXME: Allow different styles
|
||||||
|
# TODO: not everything is a QRectF…
|
||||||
|
x, y = self.position
|
||||||
|
fill = QtGui.QBrush(QtGui.QColor(
|
||||||
|
{
|
||||||
|
# Poor man's switch
|
||||||
|
# Py 3.10 might be too new and this is probably more compact still.
|
||||||
|
NodeStatus.NORMAL: 'black',
|
||||||
|
NodeStatus.MISSING: 'red',
|
||||||
|
NodeStatus.EXTRA: 'green',
|
||||||
|
NodeStatus.DISCREPANCY: 'blue',
|
||||||
|
}[self.status]
|
||||||
|
))
|
||||||
|
w, h = {
|
||||||
|
NodeType.ROUTER: (40, 40),
|
||||||
|
NodeType.NETWORK: (10, 10),
|
||||||
|
}[self.type]
|
||||||
|
return scene.addRect(
|
||||||
|
QtCore.QRectF(x, y, w, h),
|
||||||
|
brush = fill,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def nodes_from_topodiff(topodiff, visu_style='default') -> list[VisualisationNode]:
|
||||||
|
result = []
|
||||||
|
|
||||||
|
def get_node(dir_tuple, type):
|
||||||
|
n, nd = dir_tuple
|
||||||
|
visu_details = list(filter(lambda x: x[0] == ('visualisation '+visu_style), nd))
|
||||||
|
if len(visu_details) > 1:
|
||||||
|
visu_details = visu_details[0][1]
|
||||||
|
det_dict = {}
|
||||||
|
for det in visu_details:
|
||||||
|
k, v = det.split(' ', maxxplit=1)
|
||||||
|
det_dict[k] = v
|
||||||
|
pos = det_dict['position']
|
||||||
|
x, y = map(float, pos.strip('[]').split())
|
||||||
|
else:
|
||||||
|
# Probably an extra node
|
||||||
|
# TODO: proper automatic placement
|
||||||
|
import random
|
||||||
|
x = random.randint(0, 2000) # FIXME: dimensions?
|
||||||
|
y = random.randint(0, 2000)
|
||||||
|
return VisualisationNode(
|
||||||
|
position = (x, y),
|
||||||
|
type = type,
|
||||||
|
status = NodeStatus.NORMAL, # Will change in a while
|
||||||
|
details = dir_tuple,
|
||||||
|
)
|
||||||
|
|
||||||
|
for r in topodiff.reference.routers:
|
||||||
|
node = get_node(r, type=NodeType.ROUTER)
|
||||||
|
if r[0] in topodiff.routers_missing:
|
||||||
|
node.status = NodeStatus.MISSING
|
||||||
|
result.append(node)
|
||||||
|
|
||||||
|
for n in topodiff.reference.networks:
|
||||||
|
node = get_node(n, type=NodeType.NETWORK)
|
||||||
|
if n[0] in topodiff.networks_missing:
|
||||||
|
node.status = NodeStatus.MISSING
|
||||||
|
result.append(node)
|
||||||
|
|
||||||
|
for r in topodiff.actual.routers:
|
||||||
|
if r[0] in topodiff.routers_extra:
|
||||||
|
node = get_node(r, type=NodeType.ROUTER)
|
||||||
|
node.status = NodeStatus.EXTRA
|
||||||
|
result.append(node)
|
||||||
|
|
||||||
|
for n in topodiff.actual.networks:
|
||||||
|
if n[0] in topodiff.networks_extra:
|
||||||
|
node = get_node(n, type=NodeType.NETWORK)
|
||||||
|
node.status = NodeStatus.EXTRA
|
||||||
|
result.append(node)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Visualisation(QtWidgets.QWidget):
|
||||||
|
def __init__(self, topodiff=None):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
# guard:
|
||||||
|
self.scene = None
|
||||||
|
self.view = None
|
||||||
|
self.topodiff = None
|
||||||
|
self.items_nodes = None
|
||||||
|
self.items_edges = None
|
||||||
|
|
||||||
|
if topodiff is not None:
|
||||||
|
self.set_topology_difference(topodiff)
|
||||||
|
|
||||||
|
def set_topology_difference(self, topodiff):
|
||||||
|
self.topodiff = topodiff
|
||||||
|
self.draw_scene()
|
||||||
|
|
||||||
|
def draw_scene(self):
|
||||||
|
self.scene = QtWidgets.QGraphicsScene(self)
|
||||||
|
self.view = QtWidgets.QGraphicsView(self.scene)
|
||||||
|
|
||||||
|
if self.topodiff is not None:
|
||||||
|
nodes = nodes_from_topodiff(self.topodiff)
|
||||||
|
# TODO: filtering (dependent on UI)
|
||||||
|
if self.items_nodes is None:
|
||||||
|
self.items_nodes = {} # dict: ident -> QGraphicsItem
|
||||||
|
for n in nodes:
|
||||||
|
assert n.details[0] not in self.items_nodes, f'{n.details} already in dictionary'
|
||||||
|
self.items_nodes[n.details[0]] = n.draw_on_scene(self.scene)
|
Loading…
Reference in New Issue