new text mode editor
This commit is contained in:
@@ -31,6 +31,7 @@ from bedit.core.model import (
|
||||
Endpoint,
|
||||
GraphDocument,
|
||||
Icon,
|
||||
Parameter,
|
||||
Port,
|
||||
clone_component,
|
||||
)
|
||||
@@ -47,6 +48,7 @@ class DocumentController(QObject):
|
||||
componentMoved = Signal(str, QPointF)
|
||||
componentRotated = Signal(str, float)
|
||||
componentPropertiesChanged = Signal(str)
|
||||
textDefinitionChanged = Signal(str)
|
||||
connectionAdded = Signal(str)
|
||||
connectionRemoved = Signal(str)
|
||||
graphItemChanged = Signal(str, str)
|
||||
@@ -153,12 +155,13 @@ class DocumentController(QObject):
|
||||
if self.document is None:
|
||||
raise ValueError("Open or create a document first")
|
||||
number = len(self.document.roots) + 1
|
||||
base_name = f"New {'Graph' if kind == 'graph' else 'Text'} Block "
|
||||
component = Component(
|
||||
id=str(uuid4()),
|
||||
name=f"New {'Graph' if kind == 'graph' else 'Text'} Block {number}",
|
||||
name=self._available_component_name(base_name, self.document.roots.values(), number),
|
||||
implementation_kind=kind,
|
||||
icon=Icon(text="Graph" if kind == "graph" else "Text"),
|
||||
source={"equations": [], "parameters": {}} if kind == "text" else {},
|
||||
source={"equations": "", "parameters": []} if kind == "text" else {},
|
||||
)
|
||||
self.undo_stack.push(AddComponentCommand(self, None, component))
|
||||
self.activate_component(component.id)
|
||||
@@ -171,12 +174,13 @@ class DocumentController(QObject):
|
||||
if owner is None or owner.implementation_kind != "graph":
|
||||
raise ValueError("Children can only be added to graph components")
|
||||
number = len(owner.graph.blocks) + 1
|
||||
base_name = f"New {'Graph' if kind == 'graph' else 'Text'} Block "
|
||||
component = Component(
|
||||
id=str(uuid4()),
|
||||
name=f"New {'Graph' if kind == 'graph' else 'Text'} Block {number}",
|
||||
name=self._available_component_name(base_name, owner.graph.blocks.values(), number),
|
||||
implementation_kind=kind,
|
||||
icon=Icon(text="Graph" if kind == "graph" else "Text"),
|
||||
source={"equations": [], "parameters": {}} if kind == "text" else {},
|
||||
source={"equations": "", "parameters": []} if kind == "text" else {},
|
||||
)
|
||||
self.undo_stack.push(AddComponentCommand(self, owner_id, component))
|
||||
return component.id
|
||||
@@ -211,6 +215,9 @@ class DocumentController(QObject):
|
||||
if self.active_component is None or self.active_component.implementation_kind != "graph":
|
||||
raise ValueError("Open a graph component before placing components")
|
||||
component = clone_component(source)
|
||||
component.name = self._available_component_name(
|
||||
source.name, self.active_component.graph.blocks.values(), 0
|
||||
)
|
||||
component.x, component.y = position.x(), position.y()
|
||||
self.undo_stack.push(AddComponentCommand(self, self.active_component_id, component))
|
||||
return component.id
|
||||
@@ -470,7 +477,8 @@ class DocumentController(QObject):
|
||||
self,
|
||||
inputs: list[Port],
|
||||
outputs: list[Port],
|
||||
source: dict,
|
||||
equations: str,
|
||||
parameters: list[Parameter],
|
||||
) -> None:
|
||||
component = self.active_component
|
||||
if component is None or component.implementation_kind != "text":
|
||||
@@ -479,6 +487,13 @@ class DocumentController(QObject):
|
||||
output_ids = [port.id for port in outputs]
|
||||
if len(set(input_ids)) != len(input_ids) or len(set(output_ids)) != len(output_ids):
|
||||
raise ValueError("Input and output IDs must be unique")
|
||||
if any(not port.name.strip() for port in (*inputs, *outputs)):
|
||||
raise ValueError("Every port must have a name")
|
||||
parameter_ids = [parameter.id for parameter in parameters]
|
||||
if len(set(parameter_ids)) != len(parameter_ids):
|
||||
raise ValueError("Parameter IDs must be unique")
|
||||
if any(not parameter.name.strip() for parameter in parameters):
|
||||
raise ValueError("Every parameter must have a name")
|
||||
if self.document is not None:
|
||||
parent = self.document.find_parent(component.id)
|
||||
if parent is not None:
|
||||
@@ -505,7 +520,10 @@ class DocumentController(QObject):
|
||||
new = {
|
||||
"inputs": [port.to_dict() for port in inputs],
|
||||
"outputs": [port.to_dict() for port in outputs],
|
||||
"source": deepcopy(source),
|
||||
"source": {
|
||||
"equations": equations,
|
||||
"parameters": [parameter.to_dict() for parameter in parameters],
|
||||
},
|
||||
}
|
||||
if old != new:
|
||||
self.undo_stack.push(EditTextDefinitionCommand(self, component.id, old, new))
|
||||
@@ -525,6 +543,9 @@ class DocumentController(QObject):
|
||||
component = self.document.find_component(component_id)
|
||||
if component is None:
|
||||
return
|
||||
siblings = self._component_siblings(component_id)
|
||||
if any(item.id != component_id and item.name == name for item in siblings):
|
||||
raise ValueError(f"A component named {name!r} already exists at this level")
|
||||
old = {
|
||||
"name": component.name,
|
||||
"icon": component.icon.to_dict(),
|
||||
@@ -726,10 +747,13 @@ class DocumentController(QObject):
|
||||
pairs = [(source, clone_component(source)) for source in source_components]
|
||||
id_map = {source.id: clone.id for source, clone in pairs}
|
||||
blocks = {}
|
||||
for _source, clone in pairs:
|
||||
used = list(owner.graph.blocks.values())
|
||||
for source, clone in pairs:
|
||||
clone.name = self._available_component_name(source.name, used, 0)
|
||||
clone.x += offset.x()
|
||||
clone.y += offset.y()
|
||||
blocks[clone.id] = clone
|
||||
used.append(clone)
|
||||
connections = {}
|
||||
for source in source_connections:
|
||||
if source.source.block not in id_map or source.target.block not in id_map:
|
||||
@@ -759,6 +783,26 @@ class DocumentController(QObject):
|
||||
raise ValueError("The containing component is no longer in the document")
|
||||
return owner.graph
|
||||
|
||||
@staticmethod
|
||||
def _available_component_name(
|
||||
base: str, components, start: int = 0
|
||||
) -> str:
|
||||
used = {component.name for component in components}
|
||||
number = start
|
||||
while f"{base}{number}" in used:
|
||||
number += 1
|
||||
return f"{base}{number}"
|
||||
|
||||
def _component_siblings(self, component_id: str):
|
||||
if self.document is None:
|
||||
return ()
|
||||
parent = self.document.find_parent(component_id)
|
||||
return (
|
||||
parent.graph.blocks.values()
|
||||
if parent is not None
|
||||
else self.document.roots.values()
|
||||
)
|
||||
|
||||
def _insert_component(self, owner_id: str | None, component: Component) -> None:
|
||||
if self.document is None:
|
||||
raise ValueError("There is no open document")
|
||||
@@ -1039,5 +1083,4 @@ class DocumentController(QObject):
|
||||
component.source = deepcopy(values["source"])
|
||||
self.interfaceChanged.emit()
|
||||
self.documentReset.emit()
|
||||
if component_id == self.active_component_id:
|
||||
self.activeGraphChanged.emit()
|
||||
self.textDefinitionChanged.emit(component_id)
|
||||
|
||||
Reference in New Issue
Block a user