A single placed component on the schematic canvas. symbol_name : key into the symbol library (e.g. "resistor") instance_id : unique label on this schematic (e.g. "R1") prop_display maps each property key to (show_value, show_name): show_value=False → no label for
| 464 | |
| 465 | |
| 466 | class ComponentItem(_ViewBoxSvgItem): |
| 467 | """ |
| 468 | A single placed component on the schematic canvas. |
| 469 | |
| 470 | symbol_name : key into the symbol library (e.g. "resistor") |
| 471 | instance_id : unique label on this schematic (e.g. "R1") |
| 472 | |
| 473 | prop_display maps each property key to (show_value, show_name): |
| 474 | show_value=False → no label for this property |
| 475 | show_value=True, show_name=False → displays the value only (e.g. "1k") |
| 476 | show_value=True, show_name=True → displays "name: value" (e.g. "value: 1k") |
| 477 | """ |
| 478 | |
| 479 | def __init__(self, symbol_name: str, instance_id: str, svg_bytes: bytes): |
| 480 | stripped, texts = _split_symbol_text(svg_bytes) |
| 481 | super().__init__(stripped) |
| 482 | self.symbol_name = symbol_name |
| 483 | self.instance_id = instance_id |
| 484 | self._svg_bytes = stripped |
| 485 | # Embedded symbol text, drawn upright in paint()/export (not in the artwork). |
| 486 | self.symbol_texts = texts |
| 487 | self.model: str = SYMBOL_MODEL.get(symbol_name, "") |
| 488 | self.params: dict[str, str] = params_for_symbol(symbol_name) or fixed_params_for_symbol(symbol_name) |
| 489 | _n_refs = refs_for_symbol(symbol_name) |
| 490 | _is_sub = SYMBOL_PREFIX.get(symbol_name) == "X" |
| 491 | self.refs: list[str] = [] if _is_sub else ["?"] * _n_refs |
| 492 | # Ground and port are power symbols — show net name, never refdes |
| 493 | _show_refdes = symbol_name not in ("0", "port") |
| 494 | self.prop_display: dict[str, tuple[bool, bool]] = {"refdes": (_show_refdes, False)} |
| 495 | # Parameter default visibility comes from the symbol's data-params. |
| 496 | _param_disp = SYMBOL_PARAM_DISPLAY.get(symbol_name, {}) |
| 497 | for pname in self.params: |
| 498 | self.prop_display[pname] = _param_disp.get(pname, (False, False)) |
| 499 | # References are shown by default. |
| 500 | for i in range(refs_for_symbol(symbol_name)): |
| 501 | self.prop_display[f"ref {i + 1}"] = (True, False) |
| 502 | # The model is shown per the symbol's data-model flag (subcircuit blocks |
| 503 | # and "?" reminders set it, e.g. data-model="?|1"). |
| 504 | if self.model: |
| 505 | self.prop_display["model"] = (SYMBOL_MODEL_SHOW.get(symbol_name, False), False) |
| 506 | # Power symbols (ground/port) carry a net-name field, shown by default. |
| 507 | if symbol_name in ("0", "port"): |
| 508 | self.prop_display["name"] = (True, False) |
| 509 | self.prop_offsets: dict[str, tuple[float, float]] = {} |
| 510 | self.h_flip: bool = False |
| 511 | self.v_flip: bool = False |
| 512 | self._labels: dict[str, _PropertyLabel] = {} |
| 513 | # Key of the label the user last clicked, or None. Drives the dashed |
| 514 | # leader line: a clicked attribute shows only its own line; selecting the |
| 515 | # component body (no active label) shows lines to all attributes. |
| 516 | self._active_label_key: "str | None" = None |
| 517 | self.setFlag(QGraphicsItem.ItemIsSelectable) |
| 518 | self.setFlag(QGraphicsItem.ItemIsMovable) |
| 519 | self.setFlag(QGraphicsItem.ItemSendsGeometryChanges) |
| 520 | self.setZValue(config.Z_COMPONENT) # above wires so labels stay selectable |
| 521 | self._prev_pos: "QPointF | None" = None |
| 522 | # Wires captured at the start of a drag (as [(wire, point_index), …]) so |
| 523 | # they follow this component's pins. None until the first move of a drag; |
no outgoing calls
no test coverage detected