Symbol picker for Place → Component…. Scroll through the list to preview each symbol. Double-click a symbol to close the dialog and start placement. Escape or Cancel to dismiss without placing.
| 19 | |
| 20 | |
| 21 | class PlaceSymbolDialog(QDialog): |
| 22 | """ |
| 23 | Symbol picker for Place → Component…. |
| 24 | |
| 25 | Scroll through the list to preview each symbol. |
| 26 | Double-click a symbol to close the dialog and start placement. |
| 27 | Escape or Cancel to dismiss without placing. |
| 28 | """ |
| 29 | |
| 30 | def __init__(self, library, parent=None, pre_select: str | None = None): |
| 31 | super().__init__(parent, Qt.Window) |
| 32 | self.setWindowTitle("Place Symbol") |
| 33 | self._library = library |
| 34 | self._selected: str | None = None |
| 35 | |
| 36 | outer = QVBoxLayout(self) |
| 37 | body = QHBoxLayout() |
| 38 | outer.addLayout(body) |
| 39 | |
| 40 | # ── symbol list ─────────────────────────────────────────────────────── |
| 41 | list_col = QVBoxLayout() |
| 42 | list_col.addWidget(QLabel("Select a symbol:")) |
| 43 | self._list = QListWidget() |
| 44 | self._list.setFixedWidth(160) |
| 45 | for name in sorted(library.names): |
| 46 | self._list.addItem(QListWidgetItem(name)) |
| 47 | list_col.addWidget(self._list) |
| 48 | body.addLayout(list_col) |
| 49 | |
| 50 | # ── right side: graphic preview (top) and text info (bottom) ────────── |
| 51 | preview_col = QVBoxLayout() |
| 52 | # "Preview:" mirrors "Select a symbol:" on the left, so the preview area |
| 53 | # lines up with the top of the list. |
| 54 | preview_col.addWidget(QLabel("Preview:")) |
| 55 | |
| 56 | # ── part 1: SVG graphic, centered in a fixed white preview area ─────── |
| 57 | # The widget is sized per symbol to the symbol's own extent × DEFAULT_ZOOM |
| 58 | # (see _on_selection_changed), so it appears at the exact same pixels-per- |
| 59 | # grid-unit as on the canvas at default zoom — never stretched or clipped. |
| 60 | self._svg = QLabel() |
| 61 | self._svg.setAlignment(Qt.AlignCenter) |
| 62 | |
| 63 | # The preview area has a FIXED width (the widest symbol plus side margin) |
| 64 | # so the column does not jiggle horizontally as the selection scrolls. |
| 65 | # Its HEIGHT is its content's: the SVG widget (resized per symbol in |
| 66 | # _on_selection_changed) plus the vertical margins below — 5 grid units of |
| 67 | # clearance above and below every symbol. No border line: the symbol |
| 68 | # simply sits on a white field. |
| 69 | max_w = 0.0 |
| 70 | for n in library.names: |
| 71 | sym = library.symbol(n) |
| 72 | if sym is None: |
| 73 | continue |
| 74 | _x, _y, w, _h = sym.select_box |
| 75 | max_w = max(max_w, w) |
| 76 | pad_h = int(_PAD_GRID_H * GRID_SIZE * DEFAULT_ZOOM) |
| 77 | pad_v = int(_PAD_GRID_V * GRID_SIZE * DEFAULT_ZOOM) |
| 78 | area_w = round(max_w * DEFAULT_ZOOM + 2 * pad_h) |