parent
3243ae1c26
commit
12b0c6578e
@ -0,0 +1,195 @@
|
|||||||
|
from PySide6.QtWidgets import QGraphicsItem, QGraphicsRectItem, QGraphicsSimpleTextItem, QGraphicsLineItem
|
||||||
|
from PySide6.QtCore import QLineF, Qt
|
||||||
|
from PySide6.QtGui import QColor, QBrush, QPen
|
||||||
|
|
||||||
|
def _rid_to_str(rid):
|
||||||
|
from ipaddress import IPv4Address
|
||||||
|
return str(IPv4Address(rid))
|
||||||
|
|
||||||
|
def _addrs_as_str(addrs):
|
||||||
|
if addrs is None: return ''
|
||||||
|
from ipaddress import IPv4Network, IPv6Network
|
||||||
|
if isinstance(addrs, IPv4Network) or isinstance(addrs, IPv6Network): return str(addrs)
|
||||||
|
return '\n'.join(str(a) for a in addrs)
|
||||||
|
|
||||||
|
# TODO: we MAY WISH TO use QGraphicsItemGroup.
|
||||||
|
# TODO: Do not duplicate so much code!
|
||||||
|
# TODO: tooltips?
|
||||||
|
class RouterGraphicsItem(QGraphicsItem):
|
||||||
|
def __init__(self, vtxid, style, window, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.vertex_id = vtxid
|
||||||
|
self.window = window
|
||||||
|
|
||||||
|
size = 30
|
||||||
|
self.icon = QGraphicsRectItem(-size/2, -size/2, size, size, parent=self)
|
||||||
|
self.icon.setZValue(200)
|
||||||
|
self.icon.setBrush(QBrush(QColor('yellow')))
|
||||||
|
self.label = QGraphicsSimpleTextItem(parent=self.icon)
|
||||||
|
self.label.setY(size * 0.8)
|
||||||
|
self.label.setText(_rid_to_str(vtxid.router_id))
|
||||||
|
# Center text
|
||||||
|
text_width = self.label.boundingRect().width()
|
||||||
|
self.label.setX(-text_width/2)
|
||||||
|
|
||||||
|
br = self.icon.boundingRect()
|
||||||
|
br.adjust(-5, -5, 5, 5)
|
||||||
|
self.highlight = QGraphicsRectItem(br, parent=self)
|
||||||
|
self.highlight.setZValue(190)
|
||||||
|
p = self.highlight.pen()
|
||||||
|
p.setStyle(Qt.PenStyle.NoPen)
|
||||||
|
self.highlight.setPen(p)
|
||||||
|
self.setFlag(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
|
||||||
|
self.apply_position(style)
|
||||||
|
self.apply_style(style)
|
||||||
|
self.setZValue(200)
|
||||||
|
|
||||||
|
def apply_position(self, style):
|
||||||
|
x, y = style['position']
|
||||||
|
self.setPos(x, y)
|
||||||
|
|
||||||
|
def apply_style(self, style):
|
||||||
|
# Highlight:
|
||||||
|
r,g,b,a = style['highlight_colour']
|
||||||
|
color = QColor(r,g,b,a)
|
||||||
|
br = self.highlight.brush()
|
||||||
|
br.setStyle(Qt.BrushStyle.SolidPattern)
|
||||||
|
br.setColor(color)
|
||||||
|
self.highlight.setBrush(br)
|
||||||
|
|
||||||
|
# Vertex moving
|
||||||
|
def mouseMoveEvent(self, evt):
|
||||||
|
# Other selected graphics items do not receive the event, so we need to
|
||||||
|
# move everything.
|
||||||
|
selected_items = self.window.scene.selectedItems()
|
||||||
|
all_edges = set()
|
||||||
|
for qgri in selected_items:
|
||||||
|
# It is a vertex.
|
||||||
|
vtxid = self.window.topologyitems[qgri]
|
||||||
|
vtx = self.window.annot_topo.topology.vertices[vtxid]
|
||||||
|
all_edges |= vtx.incoming_edges | vtx.outgoing_edges
|
||||||
|
for edge in all_edges:
|
||||||
|
self.window.graphicsitems[edge].update_line()
|
||||||
|
super().mouseMoveEvent(evt)
|
||||||
|
|
||||||
|
# Admit we are basically only a wrapper of the icon.
|
||||||
|
def boundingRect(self):
|
||||||
|
return self.icon.boundingRect()
|
||||||
|
def paint(self, painter, option, widget):
|
||||||
|
self.icon.paint(painter, option, widget)
|
||||||
|
|
||||||
|
class NetworkGraphicsItem(QGraphicsItem):
|
||||||
|
def __init__(self, vtxid, style, window, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.vertex_id = vtxid
|
||||||
|
self.window = window
|
||||||
|
|
||||||
|
size = 40
|
||||||
|
self.icon = QGraphicsRectItem(-size/2, -size/2, size, size, parent=self)
|
||||||
|
self.icon.setZValue(200)
|
||||||
|
self.icon.setBrush(QBrush(QColor('gray')))
|
||||||
|
self.label = QGraphicsSimpleTextItem(parent=self.icon)
|
||||||
|
self.label.setText(_addrs_as_str(vtxid.address))
|
||||||
|
# Center text
|
||||||
|
text_width = self.label.boundingRect().width()
|
||||||
|
self.label.setX(-text_width/2)
|
||||||
|
text_height = self.label.boundingRect().height()
|
||||||
|
self.label.setY(-text_height/2)
|
||||||
|
|
||||||
|
br = self.icon.boundingRect()
|
||||||
|
br.adjust(-5, -5, 5, 5)
|
||||||
|
self.highlight = QGraphicsRectItem(br, parent=self)
|
||||||
|
self.highlight.setZValue(190)
|
||||||
|
p = self.highlight.pen()
|
||||||
|
p.setStyle(Qt.PenStyle.NoPen)
|
||||||
|
self.highlight.setPen(p)
|
||||||
|
self.setFlag(QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
|
||||||
|
self.apply_position(style)
|
||||||
|
self.apply_style(style)
|
||||||
|
self.setZValue(200)
|
||||||
|
|
||||||
|
def apply_position(self, style):
|
||||||
|
x, y = style['position']
|
||||||
|
self.setPos(x, y)
|
||||||
|
|
||||||
|
def apply_style(self, style):
|
||||||
|
# Highlight:
|
||||||
|
r,g,b,a = style['highlight_colour']
|
||||||
|
color = QColor(r,g,b,a)
|
||||||
|
br = self.highlight.brush()
|
||||||
|
br.setColor(color)
|
||||||
|
br.setStyle(Qt.BrushStyle.SolidPattern)
|
||||||
|
self.highlight.setBrush(br)
|
||||||
|
|
||||||
|
# Vertex moving
|
||||||
|
def mouseMoveEvent(self, evt):
|
||||||
|
# Other selected graphics items do not receive the event, so we need to
|
||||||
|
# move everything.
|
||||||
|
selected_items = self.window.scene.selectedItems()
|
||||||
|
all_edges = set()
|
||||||
|
for qgri in selected_items:
|
||||||
|
# It is a vertex.
|
||||||
|
vtxid = self.window.topologyitems[qgri]
|
||||||
|
vtx = self.window.annot_topo.topology.vertices[vtxid]
|
||||||
|
all_edges |= vtx.incoming_edges | vtx.outgoing_edges
|
||||||
|
for edge in all_edges:
|
||||||
|
self.window.graphicsitems[edge].update_line()
|
||||||
|
super().mouseMoveEvent(evt)
|
||||||
|
|
||||||
|
# Admit we are basically only a wrapper of the icon.
|
||||||
|
def boundingRect(self):
|
||||||
|
return self.icon.boundingRect()
|
||||||
|
def paint(self, painter, option, widget):
|
||||||
|
self.icon.paint(painter, option, widget)
|
||||||
|
|
||||||
|
class EdgeGraphicsItem(QGraphicsItem):
|
||||||
|
def __init__(self, edge, style, window, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.edge = edge
|
||||||
|
self.window = window
|
||||||
|
|
||||||
|
# Cache the two related objects.
|
||||||
|
# NOTE: this is only possible because the main window first creates vertices and then edges.
|
||||||
|
self.e_source = self.window.graphicsitems[edge.source]
|
||||||
|
self.e_target = self.window.graphicsitems[edge.target]
|
||||||
|
|
||||||
|
qlinef = QLineF(self.e_source.x(), self.e_source.y(), self.e_target.x(), self.e_target.y())
|
||||||
|
self.top_line = QGraphicsLineItem(qlinef, parent=self)
|
||||||
|
self.top_line.setZValue(100)
|
||||||
|
|
||||||
|
self.bottom_line = QGraphicsLineItem(qlinef, parent=self.top_line)
|
||||||
|
self.bottom_line.setZValue(90)
|
||||||
|
self.apply_style(style)
|
||||||
|
self.setZValue(100)
|
||||||
|
|
||||||
|
def update_line(self):
|
||||||
|
qlinef = QLineF(self.e_source.x(), self.e_source.y(), self.e_target.x(), self.e_target.y())
|
||||||
|
self.top_line.setLine(qlinef)
|
||||||
|
self.bottom_line.setLine(qlinef)
|
||||||
|
|
||||||
|
def apply_style(self, style):
|
||||||
|
if 'width' in style:
|
||||||
|
p = self.top_line.pen()
|
||||||
|
p.setWidth(style['width'])
|
||||||
|
self.top_line.setPen(p)
|
||||||
|
p = QPen(p)
|
||||||
|
p.setWidth(1.5*style['width'])
|
||||||
|
self.bottom_line.setPen(p)
|
||||||
|
if 'colour' in style:
|
||||||
|
r,g,b,a = style['colour']
|
||||||
|
col = QColor(r,g,b,a)
|
||||||
|
p = self.top_line.pen()
|
||||||
|
p.setColor(col)
|
||||||
|
self.top_line.setPen(p)
|
||||||
|
if 'highlight_colour' in style:
|
||||||
|
r,g,b,a = style['highlight_colour']
|
||||||
|
col = QColor(r,g,b,a)
|
||||||
|
p = self.bottom_line.pen()
|
||||||
|
p.setColor(col)
|
||||||
|
self.bottom_line.setPen(p)
|
||||||
|
|
||||||
|
def boundingRect(self):
|
||||||
|
return self.top_line.boundingRect()
|
||||||
|
def paint(self, painter, option, widget):
|
||||||
|
return self.top_line.paint(painter, option, widget)
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
def create_qgritems(at):
|
|
||||||
shape = MyGraphicsRectItem(-size/2, -size/2, size, size)
|
|
||||||
shape.setBrush(brush)
|
|
||||||
shape.setPos(x, y)
|
|
||||||
shape.setToolTip(rk)
|
|
||||||
label = QtWidgets.QGraphicsSimpleTextItem(rk, parent=shape)
|
|
||||||
label.setY(size*0.8)
|
|
||||||
# Centering:
|
|
||||||
text_width = label.boundingRect().width()
|
|
||||||
label.setX(-text_width/2)
|
|
||||||
shape.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsSelectable)
|
|
||||||
at.router_annotations[rk].append(shape)
|
|
||||||
|
|
||||||
for nk, n in topo.networks.items():
|
|
||||||
size = 10
|
|
||||||
brush = None
|
|
||||||
for tag in at.network_annotations[nk][-1::-1]:
|
|
||||||
if isinstance(tag, QtGui.QBrush):
|
|
||||||
brush = tag
|
|
||||||
break
|
|
||||||
pos = None
|
|
||||||
for tag in at.network_annotations[nk][-1::-1]:
|
|
||||||
if isinstance(tag, Position):
|
|
||||||
pos = tag
|
|
||||||
break
|
|
||||||
x = pos.x
|
|
||||||
y = pos.y
|
|
||||||
|
|
||||||
shape = MyGraphicsRectItem(-size/2, -size/2, size, size)
|
|
||||||
shape.setBrush(brush)
|
|
||||||
shape.setPos(x, y)
|
|
||||||
shape.setToolTip(nk)
|
|
||||||
label = QtWidgets.QGraphicsSimpleTextItem(nk, parent=shape)
|
|
||||||
label.setY(size*0.8)
|
|
||||||
# Centering:
|
|
||||||
text_width = label.boundingRect().width()
|
|
||||||
label.setX(-text_width/2)
|
|
||||||
shape.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable | QtWidgets.QGraphicsItem.ItemIsSelectable)
|
|
||||||
at.network_annotations[nk].append(shape)
|
|
||||||
|
|
||||||
for lk, l in topo.links.items():
|
|
||||||
rid = l.router.ident
|
|
||||||
nid = l.network.ident
|
|
||||||
|
|
||||||
rpos = None
|
|
||||||
for tag in at.router_annotations[rid][-1::-1]:
|
|
||||||
if isinstance(tag, QtWidgets.QGraphicsRectItem):
|
|
||||||
ritem = tag
|
|
||||||
if isinstance(tag, Position):
|
|
||||||
rpos = tag
|
|
||||||
break
|
|
||||||
npos = None
|
|
||||||
for tag in at.network_annotations[nid][-1::-1]:
|
|
||||||
if isinstance(tag, QtWidgets.QGraphicsRectItem):
|
|
||||||
nitem = tag
|
|
||||||
if isinstance(tag, Position):
|
|
||||||
npos = tag
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
from PySide6.QtWidgets import QGraphicsRectItem
|
|
||||||
from PySide6.QtCore import QLineF
|
|
||||||
|
|
||||||
class MyGraphicsRectItem(QGraphicsRectItem):
|
|
||||||
#def __init__(self, *a, **kwa):
|
|
||||||
# return super().__init__(*a, **kwa)
|
|
||||||
#def itemChange(self, change, val):
|
|
||||||
# return super().itemChange(change, val)
|
|
||||||
def mouseMoveEvent(self, evt):
|
|
||||||
print(f'Moving: {self}')
|
|
||||||
line = self.data(0)
|
|
||||||
other_end = line.data(0)
|
|
||||||
if other_end == self:
|
|
||||||
other_end = line.data(1)
|
|
||||||
new_qlinef = QLineF(
|
|
||||||
self.x(),
|
|
||||||
self.y(),
|
|
||||||
other_end.x(),
|
|
||||||
other_end.y(),
|
|
||||||
)
|
|
||||||
line.setLine(new_qlinef)
|
|
||||||
return super().mouseMoveEvent(evt)
|
|
||||||
|
|
Loading…
Reference in New Issue