Draggable, selectable net-name label, child of WireItem. Position is stored on the parent as label_offset relative to points[0], so the label travels with the wire during rubber-banding. WireItem has no rotation transform, so the label is always horizontal. The label sits abov
| 30 | |
| 31 | |
| 32 | class _NetLabel(QGraphicsSimpleTextItem): |
| 33 | """ |
| 34 | Draggable, selectable net-name label, child of WireItem. |
| 35 | |
| 36 | Position is stored on the parent as label_offset relative to points[0], |
| 37 | so the label travels with the wire during rubber-banding. |
| 38 | WireItem has no rotation transform, so the label is always horizontal. |
| 39 | |
| 40 | The label sits above wires in Z-order so it receives clicks first. |
| 41 | When selected a bounding-box is drawn (like a component selection rect). |
| 42 | """ |
| 43 | |
| 44 | def __init__(self, parent: "WireItem"): |
| 45 | super().__init__(parent) |
| 46 | self.setFont(NET_LABEL_FONT) |
| 47 | self.setBrush(QBrush(NET_LABEL_COLOR)) |
| 48 | self.setPen(QPen(Qt.NoPen)) |
| 49 | self.setFlag(QGraphicsItem.ItemIsMovable) |
| 50 | self.setFlag(QGraphicsItem.ItemIsSelectable) # selectable independently |
| 51 | self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) |
| 52 | self.setAcceptedMouseButtons(Qt.LeftButton) |
| 53 | self.setZValue(Z_NET_LABEL) |
| 54 | |
| 55 | def shape(self) -> QPainterPath: |
| 56 | # Pad the clickable area beyond the tight glyph bounds so a short net |
| 57 | # name is an easy target (the default shape is hard to hit). |
| 58 | path = QPainterPath() |
| 59 | path.addRect(self.boundingRect().adjusted(-3, -2, 3, 2)) |
| 60 | return path |
| 61 | |
| 62 | def mousePressEvent(self, event): |
| 63 | w = self.parentItem() |
| 64 | if w is not None: |
| 65 | w._label_active = True |
| 66 | w.update() |
| 67 | # Accept the event so the wire behind is not also selected. |
| 68 | event.accept() |
| 69 | super().mousePressEvent(event) |
| 70 | |
| 71 | def mouseReleaseEvent(self, event): |
| 72 | w = self.parentItem() |
| 73 | if w is not None: |
| 74 | w._label_active = False |
| 75 | w.update() |
| 76 | super().mouseReleaseEvent(event) |
| 77 | |
| 78 | def paint(self, painter: QPainter, option, widget=None): |
| 79 | # Draw text without Qt's default selection indicator. |
| 80 | clean_option = option.__class__(option) |
| 81 | clean_option.state = option.state & ~QStyle.State_Selected |
| 82 | super().paint(painter, clean_option, widget) |
| 83 | if option.state & QStyle.State_Selected: |
| 84 | painter.save() |
| 85 | painter.setPen(QPen(QColor(0, 120, 215), 0.8)) |
| 86 | painter.setBrush(Qt.NoBrush) |
| 87 | painter.drawRect(self.boundingRect()) |
| 88 | painter.restore() |
| 89 |