Start of the icon editor

This commit is contained in:
2026-07-27 13:08:15 +02:00
parent 713d094b08
commit 09a9e3f12f
11 changed files with 686 additions and 5 deletions

View File

@@ -1,16 +1,19 @@
from __future__ import annotations
from copy import deepcopy
from pathlib import Path
from PySide6.QtCore import QObject, Signal
from PySide6.QtGui import QUndoStack
from bedit_core.models import ID, Component, Port, PortID, Parameter, ParameterID
from bedit_core.models import ID, Component, ComponentID, GraphImplementation, Port, PortID, Parameter, ParameterID
from bedit_core.models import Document as CoreDocument
from bedit_gui.commands.change_icon_command import ChangeIconCommand
from bedit_gui.commands.port_commands import AddPortCommand, ChangePortCommand, RemovePortCommand
from bedit_gui.commands.param_commands import AddParamCommand, ChangeParamCommand, RemoveParamCommand
from bedit_gui.commands.rename_component_command import RenameComponentCommand
from bedit_gui.commands.rename_document_command import RenameDocumentCommand
from bedit_gui.models import Icon, IconDatabase
from bedit_gui.services import document_files
@@ -20,6 +23,7 @@ class Document(QObject):
model_changed = Signal(object)
path_changed = Signal(object)
modified_changed = Signal(bool)
icon_changed = Signal(object, object)
def __init__(self, parent: QObject | None = None) -> None:
super().__init__(parent)
@@ -89,6 +93,60 @@ class Document(QObject):
def rename_component(self, component: Component, name: str) -> None:
self.undo_stack.push(RenameComponentCommand(self, component, name))
def component_id(self, component: Component) -> ComponentID:
def find(components: dict[ComponentID, Component]) -> ComponentID | None:
for component_id, candidate in components.items():
if candidate is component:
return component_id
if isinstance(candidate.implementation, GraphImplementation):
found = find(candidate.implementation.graph.components)
if found is not None:
return found
return None
component_id = find(self.model.root)
if component_id is None:
raise ValueError("component is not part of this document")
return component_id
def stored_component_icon(self, component_id: ComponentID) -> Icon | None:
database = self._icon_database(False)
return deepcopy(database.icons.get(component_id)) if database is not None else None
def component_icon(self, component_id: ComponentID) -> Icon:
return self.stored_component_icon(component_id) or Icon()
def change_icon(self, component_id: ComponentID, icon: Icon) -> None:
self.undo_stack.push(ChangeIconCommand(self, component_id, icon))
def _set_component_icon(self, component_id: ComponentID, icon: Icon | None) -> None:
if icon is None:
database = self._icon_database(False)
if database is not None:
database.icons.pop(component_id, None)
if not database.icons:
self.model.metadata.pop("icon_database", None)
else:
self._icon_database(True).icons[component_id] = deepcopy(icon)
self.icon_changed.emit(component_id, self.stored_component_icon(component_id))
def _icon_database(self, create: bool) -> IconDatabase | None:
metadata = self.model.metadata
value = metadata.get("icon_database") if metadata is not None else None
if isinstance(value, dict):
value = IconDatabase.from_data(value)
metadata["icon_database"] = value
if isinstance(value, IconDatabase):
return value
if not create:
return None
if metadata is None:
metadata = {}
self.model.metadata = metadata
database = IconDatabase()
metadata["icon_database"] = database
return database
def update_component_ports(self, component: Component, ports: dict[PortID, Port]) -> None:
current = component.interface.ports
removed = [
@@ -113,6 +171,7 @@ class Document(QObject):
self.undo_stack.push(command)
self.undo_stack.endMacro()
def update_component_params(self, component: Component, params: dict[ParameterID, Parameter]) -> None:
current = component.parameters
removed = [
@@ -136,4 +195,3 @@ class Document(QObject):
for command in commands:
self.undo_stack.push(command)
self.undo_stack.endMacro()