More fixes and extended lib

This commit is contained in:
Joppe Blondel
2026-08-18 15:44:24 +02:00
parent 1d535c1f5b
commit 16d9cc7651
20 changed files with 1057 additions and 101 deletions
@@ -133,11 +133,11 @@ class DocumentTreeClipboardHandler(ClipboardHandler):
if target is None or payload is None:
return
try:
components, icons = import_components(payload)
components, icons, port_metadata = import_components(payload)
except (TypeError, ValueError) as exc:
QMessageBox.critical(self.tree, "Could not paste components", str(exc))
return
self.document.paste_components(target, components, icons)
self.document.paste_components(target, components, icons, port_metadata)
def delete(self) -> None:
self.document.delete_components(self._selected_components())
@@ -223,14 +223,14 @@ class GraphEditorClipboardHandler(ClipboardHandler):
def _paste_payload(self, graph_component: Component, payload: dict, position: tuple[int, int]) -> None:
try:
components, icons = import_components(payload)
components, icons, port_metadata = import_components(payload)
except (TypeError, ValueError) as exc:
QMessageBox.critical(self.editor, "Could not paste components", str(exc))
return
x, y = position
spacing = self.editor.snap_to_grid_size * 4
positions = {component_id: (x + index * spacing, y + index * spacing) for index, component_id in enumerate(components)}
self.document.paste_graph_components(graph_component, components, icons, positions)
self.document.paste_graph_components(graph_component, components, icons, positions, port_metadata)
def delete(self) -> None:
components = self._selected_components()
@@ -9,7 +9,7 @@ from PySide6.QtWidgets import QAbstractItemView, QDialog, QHeaderView, QMenu
from bedit_core.models import Component, ComponentID, ConnectionID, EquationImplementation, GraphImplementation, Port, PortID, Parameter, ParameterID
from bedit_core.models import Document as CoreDocument
from bedit_gui.documents import Document
from bedit_gui.models import Graph, GraphComponentLabel, Icon
from bedit_gui.models import Graph, GraphComponentLabel, Icon, PortMetadata
from bedit_gui.views.dialogs.interface_editor_dialog import InterfaceEditorDialog
from bedit_gui.views.dialogs.param_editor_dialog import ParamEditorDialog
from bedit_gui.views.icon_editor_window import IconEditorWindow
@@ -22,6 +22,7 @@ ICON_SIZE = QSize(16, 16)
class InterfaceEditorLike(Protocol):
def exec(self) -> int: ...
def ports(self) -> dict[PortID, Port]: ...
def port_metadata(self) -> dict[PortID, PortMetadata]: ...
class ParamEditorLike(Protocol):
def exec(self) -> int: ...
@@ -29,7 +30,7 @@ class ParamEditorLike(Protocol):
InterfaceEditorFactory = Callable[
[dict[PortID, Port], MainWindow],
[dict[PortID, Port], dict[PortID, PortMetadata], MainWindow],
InterfaceEditorLike,
]
@@ -60,15 +61,17 @@ class DocumentTreeController(QObject):
window.ui.documentTree.setModel(self.model)
window.ui.documentTree.selectionModel().selectionChanged.connect(self._selection_changed)
window.equation_editor.equation_text_change_requested.connect(self.document.update_component_equation_text)
window.equation_editor.port_metadata_change_requested.connect(self._change_equation_port_metadata)
document.model_changed.connect(self._on_document_changed)
document.icon_changed.connect(self._on_icon_changed)
document.port_metadata_database_changed.connect(self._on_port_metadata_database_changed)
document.graph_component_position_changed.connect(self._on_graph_component_position_changed)
document.graph_component_label_changed.connect(self._on_graph_component_label_changed)
document.graph_connection_points_changed.connect(self._on_graph_connection_points_changed)
document.equation_text_changed.connect(self._on_equation_text_changed)
self.model.rename_document_requested.connect(self.document.rename)
self.model.rename_component_requested.connect(self.document.rename_component)
window.graph_editor.component_move_requested.connect(self.document.move_graph_component)
window.graph_editor.component_moves_requested.connect(self.document.move_graph_components)
window.graph_editor.component_label_move_requested.connect(self.document.move_graph_component_label)
window.graph_editor.component_context_menu_requested.connect(self._show_graph_component_context_menu)
window.graph_editor.component_open_requested.connect(self._open_graph_component)
@@ -125,7 +128,8 @@ class DocumentTreeController(QObject):
def _show_component(self, component: Component | None) -> None:
if component is not None and isinstance(component.implementation, EquationImplementation):
self.window.equation_editor.set_component(component)
port_metadata = {port_id: self.document.port_metadata(port_id) for port_id in component.interface.ports}
self.window.equation_editor.set_component(component, port_metadata)
self.window.equation_editor.show()
else:
self.window.equation_editor.set_component(None)
@@ -133,7 +137,8 @@ class DocumentTreeController(QObject):
if component is not None and isinstance(component.implementation, GraphImplementation):
graph = self.document.graph_database().graphs.get(self.document.component_id(component), Graph())
icons = {component_id: self.document.component_icon(component_id) for component_id in component.implementation.graph.components}
self.window.graph_editor.set_component(component, graph, icons)
port_metadata = {port_id: self.document.port_metadata(port_id) for child in component.implementation.graph.components.values() for port_id in child.interface.ports}
self.window.graph_editor.set_component(component, graph, icons, port_metadata)
self.window.graph_editor.show()
else:
self.window.graph_editor.set_component(None)
@@ -152,6 +157,17 @@ class DocumentTreeController(QObject):
if graph_component is not None and isinstance(graph_component.implementation, GraphImplementation) and component_id in graph_component.implementation.graph.components:
self._show_component(graph_component)
def _on_port_metadata_database_changed(self, _database: object) -> None:
graph_component = self.window.graph_editor.component()
if graph_component is not None:
self._show_component(graph_component)
equation_component = self.window.equation_editor.component()
if equation_component is not None:
self.window.equation_editor.refresh_port_metadata({port_id: self.document.port_metadata(port_id) for port_id in equation_component.interface.ports})
def _change_equation_port_metadata(self, component: Component, port_metadata: dict[PortID, PortMetadata]) -> None:
self.document.update_component_ports(component, component.interface.ports, port_metadata)
def _on_graph_component_position_changed(self, graph_id: ComponentID, component_id: ComponentID, position: tuple[int, int] | None) -> None:
graph_component = self.window.graph_editor.component()
if graph_component is not None and self.document.component_id(graph_component) == graph_id:
@@ -242,10 +258,11 @@ class DocumentTreeController(QObject):
def _edit_interface(self, component: Component) -> None:
dialog = self.interface_editor_factory(
component.interface.ports,
{port_id: self.document.port_metadata(port_id) for port_id in component.interface.ports},
self.window,
)
if dialog.exec() == QDialog.DialogCode.Accepted:
self.document.update_component_ports(component, dialog.ports())
self.document.update_component_ports(component, dialog.ports(), dialog.port_metadata())
def _edit_params(self, component: Component) -> None:
dialog = self.param_editor_factory(
@@ -1,8 +1,8 @@
from PySide6.QtCore import QObject, QSize, Qt
from PySide6.QtWidgets import QAbstractItemView, QHeaderView
from bedit_core.models import Component, ComponentID, GraphImplementation
from bedit_gui.models import Icon, IconDatabase
from bedit_core.models import Component, ComponentID, GraphImplementation, PortID
from bedit_gui.models import Icon, IconDatabase, PortMetadata, PortMetadataDatabase
from bedit_gui.services.application_settings import ApplicationSettings
from bedit_gui.services.component_clipboard import export_component_data
from bedit_gui.services.libraries import load_library_documents
@@ -18,7 +18,7 @@ class LibraryController(QObject):
super().__init__(window)
self.window = window
self.settings = settings
self._component_sources: dict[int, tuple[ComponentID, dict[ComponentID, Icon]]] = {}
self._component_sources: dict[int, tuple[ComponentID, dict[ComponentID, Icon], dict[PortID, PortMetadata]]] = {}
self.model = LibraryTreeModel(self._component_payload)
tree = window.ui.libraryTree
@@ -44,7 +44,9 @@ class LibraryController(QObject):
for library in libraries:
database = library.document.metadata.get("icon_database") if library.document.metadata is not None else None
icons = database.icons if isinstance(database, IconDatabase) else {}
self._collect_component_sources(library.document.root, icons)
metadata_database = library.document.metadata.get("port_metadata_database") if library.document.metadata is not None else None
port_metadata = metadata_database.ports if isinstance(metadata_database, PortMetadataDatabase) else {}
self._collect_component_sources(library.document.root, icons, port_metadata)
self.model.set_documents([library.document for library in libraries])
for library in libraries:
database = library.document.metadata.get("icon_database") if library.document.metadata is not None else None
@@ -55,20 +57,22 @@ class LibraryController(QObject):
def _component_payload(self, components: list[Component]) -> dict:
roots = {}
icons = {}
port_metadata = {}
for component in components:
source = self._component_sources.get(id(component))
if source is None:
continue
component_id, source_icons = source
component_id, source_icons, source_port_metadata = source
roots[component_id] = component
icons.update(source_icons)
return export_component_data(roots, icons)
port_metadata.update(source_port_metadata)
return export_component_data(roots, icons, port_metadata)
def _collect_component_sources(self, components: dict[ComponentID, Component], icons: dict[ComponentID, Icon]) -> None:
def _collect_component_sources(self, components: dict[ComponentID, Component], icons: dict[ComponentID, Icon], port_metadata: dict[PortID, PortMetadata]) -> None:
for component_id, component in components.items():
self._component_sources[id(component)] = (component_id, icons)
self._component_sources[id(component)] = (component_id, icons, port_metadata)
if isinstance(component.implementation, GraphImplementation):
self._collect_component_sources(component.implementation.graph.components, icons)
self._collect_component_sources(component.implementation.graph.components, icons, port_metadata)
def _set_component_icons(self, components: dict[ComponentID, Component], icons: dict[ComponentID, Icon]) -> None:
for component_id, component in components.items():