Added new and delete component actions

This commit is contained in:
2026-07-27 15:29:59 +02:00
parent a4daaa8798
commit 51a1537c9c
3 changed files with 139 additions and 1 deletions

View File

@@ -0,0 +1,106 @@
from PySide6.QtGui import QUndoCommand
from bedit_core.models import Component, ComponentID, Connection, ConnectionID, EquationImplementation, Graph, GraphImplementation, Interface
class AddEmptyGraphComponent(QUndoCommand):
def __init__(self, document: object, parent: Component) -> None:
super().__init__("Add graph component")
if not isinstance(parent.implementation, GraphImplementation):
raise TypeError("parent component must have a graph implementation")
self.document = document
self.graph = parent.implementation.graph
self.component_id = ComponentID()
self.component = Component(name="New Graph Component", interface=Interface(), parameters={}, implementation=GraphImplementation(Graph()))
def redo(self) -> None:
self.graph.components[self.component_id] = self.component
self.document.model_changed.emit(self.document.model)
def undo(self) -> None:
del self.graph.components[self.component_id]
self.document.model_changed.emit(self.document.model)
class AddEmptyEquationComponent(QUndoCommand):
def __init__(self, document: object, parent: Component) -> None:
super().__init__("Add equation component")
if not isinstance(parent.implementation, GraphImplementation):
raise TypeError("parent component must have a graph implementation")
self.document = document
self.graph = parent.implementation.graph
self.component_id = ComponentID()
self.component = Component(name="New Equation Component", interface=Interface(), parameters={}, implementation=EquationImplementation())
def redo(self) -> None:
self.graph.components[self.component_id] = self.component
self.document.model_changed.emit(self.document.model)
def undo(self) -> None:
del self.graph.components[self.component_id]
self.document.model_changed.emit(self.document.model)
class DeleteComponent(QUndoCommand):
def __init__(self, document: object, component: Component) -> None:
super().__init__("Delete component")
self.document = document
self.component = component
self.components, self.component_id, self.parent_graph = self._find_component(document.model.root, component)
self.component_index = list(self.components).index(self.component_id)
port_ids = set(component.interface.ports)
self.connections: list[tuple[int, ConnectionID, Connection]] = []
if self.parent_graph is not None:
for index, (connection_id, connection) in enumerate(self.parent_graph.connections.items()):
if connection.source in port_ids or connection.target in port_ids:
self.connections.append((index, connection_id, connection))
self.icons = {}
for component_id in self._component_ids(self.component_id, component):
icon = document.stored_component_icon(component_id)
if icon is not None:
self.icons[component_id] = icon
def redo(self) -> None:
if self.parent_graph is not None:
for _, connection_id, _ in self.connections:
self.parent_graph.connections.pop(connection_id, None)
self.components.pop(self.component_id, None)
self.document.model_changed.emit(self.document.model)
for component_id in self.icons:
self.document._set_component_icon(component_id, None)
def undo(self) -> None:
self._restore_item(self.components, self.component_id, self.component, self.component_index)
if self.parent_graph is not None:
for index, connection_id, connection in self.connections:
self._restore_item(self.parent_graph.connections, connection_id, connection, index)
self.document.model_changed.emit(self.document.model)
for component_id, icon in self.icons.items():
self.document._set_component_icon(component_id, icon)
@classmethod
def _find_component(cls, components: dict[ComponentID, Component], target: Component, parent_graph: Graph | None = None) -> tuple[dict[ComponentID, Component], ComponentID, Graph | None]:
for component_id, component in components.items():
if component is target:
return components, component_id, parent_graph
if isinstance(component.implementation, GraphImplementation):
try:
return cls._find_component(component.implementation.graph.components, target, component.implementation.graph)
except ValueError:
pass
raise ValueError("component is not part of this document")
@classmethod
def _component_ids(cls, component_id: ComponentID, component: Component) -> list[ComponentID]:
component_ids = [component_id]
if isinstance(component.implementation, GraphImplementation):
for child_id, child in component.implementation.graph.components.items():
component_ids.extend(cls._component_ids(child_id, child))
return component_ids
@staticmethod
def _restore_item(items: dict, item_id: object, item: object, index: int) -> None:
values = list(items.items())
values.insert(index, (item_id, item))
items.clear()
items.update(values)