Added ports to icon

This commit is contained in:
2026-07-27 14:12:13 +02:00
parent 035cbdf53f
commit 13d3825f9b
5 changed files with 132 additions and 7 deletions

View File

@@ -6,6 +6,7 @@ from PySide6.QtCore import QEvent, QObject, Qt, Signal
from PySide6.QtGui import QKeySequence, QPainter, QShortcut, QUndoCommand, QUndoStack, QWheelEvent, QShowEvent
from PySide6.QtWidgets import QDialog, QGraphicsView, QMainWindow, QWidget
from bedit_core.models import Port, PortID, SignalDirection
from bedit_gui.models import Icon, Shape, ShapeID
from bedit_gui.ui.generated.ui_icon_editor_window import Ui_iconEditor
from bedit_gui.views.icon_graphics_scene import IconGraphicsScene, RectangleCreationTool
@@ -69,6 +70,21 @@ class DeleteShapesCommand(QUndoCommand):
self.editor._restore_shapes(self.shapes)
class MovePortCommand(QUndoCommand):
def __init__(self, editor: IconEditorWindow, port_id: PortID, old_position: tuple[int, int], new_position: tuple[int, int]) -> None:
super().__init__("Move port")
self.editor = editor
self.port_id = port_id
self.old_position = old_position
self.new_position = new_position
def redo(self) -> None:
self.editor._move_port(self.port_id, self.new_position)
def undo(self) -> None:
self.editor._move_port(self.port_id, self.old_position)
class IconEditorWindow(QMainWindow):
"""Independent icon editing session with its own undo stack."""
@@ -78,7 +94,7 @@ class IconEditorWindow(QMainWindow):
minimum_zoom = 0.1
maximum_zoom = 10.0
def __init__(self, icon: Icon, parent: QWidget | None = None) -> None:
def __init__(self, icon: Icon, ports: dict[PortID, Port], parent: QWidget | None = None) -> None:
super().__init__(parent)
self.ui = Ui_iconEditor()
@@ -88,7 +104,10 @@ class IconEditorWindow(QMainWindow):
self._icon = deepcopy(icon)
self.scene = IconGraphicsScene(self)
self.scene.set_ports(ports)
self._ensure_port_positions(ports)
self.scene.set_icon(self._icon)
self.scene.port_moved.connect(self._port_moved)
self.scene.shape_created.connect(self._shape_created)
self.scene.shape_changed.connect(self._shape_changed)
self.scene.shape_options_requested.connect(self._show_shape_options)
@@ -197,12 +216,20 @@ class IconEditorWindow(QMainWindow):
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _move_port(self, port_id: PortID, position: tuple[int, int]) -> None:
self._icon.port_positions[port_id] = position
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _shape_created(self, shape: Shape) -> None:
self.undo_stack.push(AddShapeCommand(self, ShapeID(), shape))
def _shape_changed(self, shape_id: ShapeID, old_shape: Shape, new_shape: Shape) -> None:
self.undo_stack.push(ChangeShapeCommand(self, shape_id, old_shape, new_shape))
def _port_moved(self, port_id: PortID, old_position: tuple[int, int], new_position: tuple[int, int]) -> None:
self.undo_stack.push(MovePortCommand(self, port_id, old_position, new_position))
def _delete_selected_shapes(self) -> None:
shape_ids = self.scene.selected_shape_ids()
shapes = {shape_id: self._icon.shapes[shape_id] for shape_id in shape_ids}
@@ -219,6 +246,26 @@ class IconEditorWindow(QMainWindow):
if new_shape != old_shape:
self.undo_stack.push(ChangeShapeCommand(self, shape_id, old_shape, new_shape))
def _ensure_port_positions(self, ports: dict[PortID, Port]) -> None:
bounds = self.scene.sceneRect()
left = round(bounds.left())
top = round(bounds.top())
right = round(bounds.right() - 16)
bottom = round(bounds.bottom() - 16)
positions: dict[PortID, tuple[int, int]] = {}
input_index = 0
output_index = 0
for port_id, port in ports.items():
if port.direction is SignalDirection.INPUT:
default = (left, top + input_index * 16)
input_index += 1
else:
default = (right, top + output_index * 16)
output_index += 1
position = self._icon.port_positions.get(port_id, default)
positions[port_id] = (max(left, min(right, position[0])), max(top, min(bottom, position[1])))
self._icon.port_positions = positions
def _start_rectangle_tool(self) -> None:
layer = max((shape.layer for shape in self._icon.shapes.values()), default=-1) + 1
self.scene.set_creation_tool(RectangleCreationTool(self.scene, layer))