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