Added run button and parameter dialog
This commit is contained in:
68
BEdit/src/bedit/core/simulation/runner.py
Normal file
68
BEdit/src/bedit/core/simulation/runner.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import os
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from threading import Lock, Thread
|
||||
|
||||
from bedit.core.application_log import get_logger
|
||||
|
||||
|
||||
log = get_logger(__name__)
|
||||
_worker_lock = Lock()
|
||||
_worker: Thread | None = None
|
||||
|
||||
|
||||
def run_simulation_async(
|
||||
openmodelica_path: str = "", task: Callable[[], None] | None = None
|
||||
) -> None:
|
||||
"""Start one simulation task in a background thread and return immediately."""
|
||||
|
||||
global _worker
|
||||
with _worker_lock:
|
||||
if _worker is not None and _worker.is_alive():
|
||||
raise RuntimeError("A simulation is already running")
|
||||
_worker = Thread(
|
||||
target=_run_safely,
|
||||
args=(task or (lambda: _run_openmodelica(openmodelica_path)),),
|
||||
name="bedit-simulation",
|
||||
daemon=True,
|
||||
)
|
||||
_worker.start()
|
||||
|
||||
|
||||
def simulation_is_running() -> bool:
|
||||
"""Return whether the background simulation worker is active."""
|
||||
|
||||
with _worker_lock:
|
||||
return _worker is not None and _worker.is_alive()
|
||||
|
||||
|
||||
def _run_safely(task: Callable[[], None]) -> None:
|
||||
global _worker
|
||||
try:
|
||||
task()
|
||||
except Exception:
|
||||
log.exception("Simulation run failed")
|
||||
finally:
|
||||
with _worker_lock:
|
||||
_worker = None
|
||||
|
||||
|
||||
def _run_openmodelica(openmodelica_path: str = "") -> None:
|
||||
"""Create the OpenModelica session and perform the current runner stub work."""
|
||||
|
||||
from OMPython import OMCSessionZMQ
|
||||
|
||||
omhome = _openmodelica_home(openmodelica_path)
|
||||
omc = OMCSessionZMQ(omhome=omhome)
|
||||
log.info("OpenModelica Version: %s", omc.sendExpression("getVersion()"))
|
||||
|
||||
|
||||
def _openmodelica_home(openmodelica_path: str) -> str | None:
|
||||
"""Convert an optional omc executable path to the home expected by OMPython."""
|
||||
|
||||
if not openmodelica_path.strip():
|
||||
return None
|
||||
path = Path(os.path.expandvars(openmodelica_path)).expanduser()
|
||||
if path.name.lower() in {"omc", "omc.exe"}:
|
||||
return str(path.parent.parent)
|
||||
return str(path)
|
||||
@@ -2,6 +2,7 @@ from typing import Any
|
||||
|
||||
from bedit.core.application_log import get_logger
|
||||
from bedit.core.simulation.compiler import compile_graph
|
||||
from bedit.core.simulation.runner import run_simulation_async
|
||||
|
||||
|
||||
log = get_logger(__name__)
|
||||
@@ -10,11 +11,12 @@ log = get_logger(__name__)
|
||||
class Simulation:
|
||||
"""Application-owned simulation state and compiler facade."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
def __init__(self, *, openmodelica_path: str = "") -> None:
|
||||
self.state: dict[str, Any] = {}
|
||||
self.last_compilation_input: dict[str, Any] | None = None
|
||||
self.last_compilation_output: str | None = None
|
||||
self.id_list: dict[str, Any] = {}
|
||||
self.openmodelica_path = openmodelica_path
|
||||
|
||||
def compile(self, graph: dict[str, Any]) -> None:
|
||||
"""Compile a serialized component tree and retain the result."""
|
||||
@@ -24,4 +26,8 @@ class Simulation:
|
||||
self.id_list = result.objects_by_id
|
||||
self.last_compilation_output = result.modelica
|
||||
log.info("Generated Modelica model:\n%s", self.last_compilation_output)
|
||||
log.info("Simulation settings:\n%s", self.last_compilation_input['implementation']['graph']['simulation'])
|
||||
|
||||
def run_simulation(self) -> None:
|
||||
"""Start the simulation without blocking the calling UI thread."""
|
||||
|
||||
run_simulation_async(self.openmodelica_path)
|
||||
|
||||
@@ -150,6 +150,19 @@ class EditSimulationSettingsCommand(QUndoCommand):
|
||||
self.controller._set_simulation_settings(self.owner_id, self.old)
|
||||
|
||||
|
||||
class EditGraphParametersCommand(QUndoCommand):
|
||||
def __init__(self, controller, old: dict, new: dict) -> None:
|
||||
super().__init__("Edit graph parameters")
|
||||
self.controller = controller
|
||||
self.old, self.new = old, new
|
||||
|
||||
def redo(self) -> None:
|
||||
self.controller._set_graph_parameters(self.new)
|
||||
|
||||
def undo(self) -> None:
|
||||
self.controller._set_graph_parameters(self.old)
|
||||
|
||||
|
||||
class DeleteAnnotationsCommand(QUndoCommand):
|
||||
def __init__(self, controller, owner_id: str, annotations: dict[str, Annotation]) -> None:
|
||||
super().__init__("Delete annotations")
|
||||
|
||||
@@ -13,6 +13,7 @@ from bedit.gui.controllers.commands import (
|
||||
DeleteSelectionCommand,
|
||||
DeleteAnnotationsCommand,
|
||||
EditGraphItemCommand,
|
||||
EditGraphParametersCommand,
|
||||
EditSimulationSettingsCommand,
|
||||
EditTextDefinitionCommand,
|
||||
EditComponentAppearanceCommand,
|
||||
@@ -393,12 +394,45 @@ class DocumentController(QObject):
|
||||
EditSimulationSettingsCommand(self, component.id, old, new)
|
||||
)
|
||||
|
||||
def edit_graph_parameter_values(
|
||||
self, root_id: str, values: dict[str, dict[str, str]]
|
||||
) -> None:
|
||||
root = self.document.find_component(root_id) if self.document else None
|
||||
if root is None:
|
||||
return
|
||||
subtree_ids = {component.id for component in self._component_subtree(root)}
|
||||
if not set(values) <= subtree_ids:
|
||||
raise ValueError("Parameter changes contain a component outside the active graph")
|
||||
|
||||
old: dict[str, list[dict]] = {}
|
||||
new: dict[str, list[dict]] = {}
|
||||
for component_id, parameter_values in values.items():
|
||||
component = self.document.find_component(component_id)
|
||||
known_ids = {parameter.id for parameter in component.parameters}
|
||||
if not set(parameter_values) <= known_ids:
|
||||
raise ValueError(f"Component {component.name!r} contains an unknown parameter")
|
||||
updated = deepcopy(component.parameters)
|
||||
for parameter in updated:
|
||||
if parameter.id in parameter_values:
|
||||
parameter.value = parameter_values[parameter.id]
|
||||
old[component_id] = [parameter.to_dict() for parameter in component.parameters]
|
||||
new[component_id] = [parameter.to_dict() for parameter in updated]
|
||||
|
||||
if old != new:
|
||||
self.undo_stack.push(EditGraphParametersCommand(self, old, new))
|
||||
|
||||
def compile_active_graph(self) -> None:
|
||||
component = self.active_component
|
||||
if component is None or component.implementation_kind != "graph":
|
||||
raise ValueError("Open a graph component before compiling")
|
||||
self.simulation.compile(component.to_dict())
|
||||
|
||||
def run_simulation(self) -> None:
|
||||
component = self.active_component
|
||||
if component is None or component.implementation_kind != "graph":
|
||||
raise ValueError("Open a graph component before running a simulation")
|
||||
self.simulation.run_simulation()
|
||||
|
||||
def set_route_waypoints(self, item_kind: str, item_id: str, waypoints: list[QPointF]) -> None:
|
||||
item = (
|
||||
self.active_graph.connections
|
||||
@@ -1082,6 +1116,22 @@ class DocumentController(QObject):
|
||||
owner.graph.simulation_settings = deepcopy(settings)
|
||||
self.documentReset.emit()
|
||||
|
||||
def _set_graph_parameters(self, values: dict[str, list[dict]]) -> None:
|
||||
if self.document is None:
|
||||
return
|
||||
changed_text_components: list[str] = []
|
||||
for component_id, parameters in values.items():
|
||||
component = self.document.find_component(component_id)
|
||||
if component is None:
|
||||
continue
|
||||
component.parameters = [Parameter.from_dict(item) for item in parameters]
|
||||
if component.implementation_kind == "text":
|
||||
changed_text_components.append(component_id)
|
||||
self.document.validate()
|
||||
self.documentReset.emit()
|
||||
for component_id in changed_text_components:
|
||||
self.textDefinitionChanged.emit(component_id)
|
||||
|
||||
def _replace_component(self, old_id: str, replacement: Component) -> None:
|
||||
if self.document is None:
|
||||
return
|
||||
|
||||
93
BEdit/src/bedit/gui/dialogs/graph_parameters.py
Normal file
93
BEdit/src/bedit/gui/dialogs/graph_parameters.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from copy import deepcopy
|
||||
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import QDialog, QStyledItemDelegate, QTreeWidgetItem
|
||||
|
||||
from bedit.core.model import Component
|
||||
from bedit.gui.generated.ui_graph_parameters_dialog import Ui_GraphParametersDialog
|
||||
|
||||
|
||||
COMPONENT_ID_ROLE = Qt.ItemDataRole.UserRole
|
||||
PARAMETER_ID_ROLE = Qt.ItemDataRole.UserRole + 1
|
||||
|
||||
|
||||
class ValueColumnDelegate(QStyledItemDelegate):
|
||||
"""Allow editing only in the parameter value column."""
|
||||
|
||||
def createEditor(self, parent, option, index): # noqa: N802 (Qt API name)
|
||||
parameter_id = index.siblingAtColumn(0).data(PARAMETER_ID_ROLE)
|
||||
if index.column() != 2 or parameter_id is None:
|
||||
return None
|
||||
return super().createEditor(parent, option, index)
|
||||
|
||||
|
||||
class GraphParametersDialog(QDialog):
|
||||
"""Edit every parameter value in an active component subtree."""
|
||||
|
||||
def __init__(self, root: Component, parent=None) -> None:
|
||||
super().__init__(parent)
|
||||
self.ui = Ui_GraphParametersDialog()
|
||||
self.ui.setupUi(self)
|
||||
self.ui.parameterTree.setItemDelegate(ValueColumnDelegate(self.ui.parameterTree))
|
||||
self.setWindowTitle(f"Graph Parameters — {root.name}")
|
||||
self._parameters = {
|
||||
component.id: deepcopy(component.parameters)
|
||||
for component in self._walk(root)
|
||||
}
|
||||
self._populate(root)
|
||||
self.ui.parameterTree.expandAll()
|
||||
self.ui.parameterTree.resizeColumnToContents(0)
|
||||
self.ui.parameterTree.resizeColumnToContents(1)
|
||||
|
||||
@staticmethod
|
||||
def _walk(component: Component):
|
||||
yield component
|
||||
if component.implementation_kind == "graph":
|
||||
for child in component.graph.blocks.values():
|
||||
yield from GraphParametersDialog._walk(child)
|
||||
|
||||
def _populate(self, root: Component) -> None:
|
||||
self.ui.parameterTree.clear()
|
||||
|
||||
def add_component(component: Component, parent: QTreeWidgetItem | None) -> None:
|
||||
item = QTreeWidgetItem([component.name, "", ""])
|
||||
item.setData(0, COMPONENT_ID_ROLE, component.id)
|
||||
item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)
|
||||
if parent is None:
|
||||
self.ui.parameterTree.addTopLevelItem(item)
|
||||
else:
|
||||
parent.addChild(item)
|
||||
|
||||
for parameter in self._parameters[component.id]:
|
||||
parameter_item = QTreeWidgetItem(
|
||||
[parameter.name, parameter.type, parameter.value]
|
||||
)
|
||||
parameter_item.setData(0, COMPONENT_ID_ROLE, component.id)
|
||||
parameter_item.setData(0, PARAMETER_ID_ROLE, parameter.id)
|
||||
parameter_item.setFlags(
|
||||
parameter_item.flags() | Qt.ItemFlag.ItemIsEditable
|
||||
)
|
||||
item.addChild(parameter_item)
|
||||
|
||||
if component.implementation_kind == "graph":
|
||||
for child in component.graph.blocks.values():
|
||||
add_component(child, item)
|
||||
|
||||
add_component(root, None)
|
||||
|
||||
@property
|
||||
def parameter_values(self) -> dict[str, dict[str, str]]:
|
||||
values: dict[str, dict[str, str]] = {}
|
||||
iterator = self.ui.parameterTree.invisibleRootItem()
|
||||
|
||||
def collect(parent: QTreeWidgetItem) -> None:
|
||||
for index in range(parent.childCount()):
|
||||
item = parent.child(index)
|
||||
parameter_id = item.data(0, PARAMETER_ID_ROLE)
|
||||
if parameter_id is not None:
|
||||
component_id = item.data(0, COMPONENT_ID_ROLE)
|
||||
values.setdefault(component_id, {})[parameter_id] = item.text(2)
|
||||
collect(item)
|
||||
|
||||
collect(iterator)
|
||||
return values
|
||||
@@ -26,6 +26,7 @@ class SettingsDialog(QDialog):
|
||||
self.ui.addLibraryFileButton.clicked.connect(self._add_library_file)
|
||||
self.ui.addLibraryFolderButton.clicked.connect(self._add_library_folder)
|
||||
self.ui.removeLibraryPathButton.clicked.connect(self._remove_library_path)
|
||||
self.ui.browseOpenModelicaButton.clicked.connect(self._browse_openmodelica)
|
||||
self.ui.libraryPathsList.itemSelectionChanged.connect(self._update_remove_button)
|
||||
self.ui.syntaxStylesTable.cellDoubleClicked.connect(self._choose_syntax_color)
|
||||
self._load_settings()
|
||||
@@ -46,6 +47,7 @@ class SettingsDialog(QDialog):
|
||||
self.ui.graphGridSpinBox.setValue(self.graph_grid_size(self.settings))
|
||||
self.ui.graphSnapSpinBox.setValue(self.graph_snap_size(self.settings))
|
||||
self.ui.iconGridSpinBox.setValue(self.icon_grid_size(self.settings))
|
||||
self.ui.openModelicaPathEdit.setText(self.openmodelica_path(self.settings))
|
||||
self._load_syntax_styles()
|
||||
self._update_remove_button()
|
||||
|
||||
@@ -130,6 +132,25 @@ class SettingsDialog(QDialog):
|
||||
settings = settings if settings is not None else application_settings()
|
||||
return settings.value("grid/iconSize", 8, type=int)
|
||||
|
||||
@staticmethod
|
||||
def openmodelica_path(settings: QSettings | None = None) -> str:
|
||||
settings = settings if settings is not None else application_settings()
|
||||
return str(settings.value("simulation/openModelicaPath", "") or "")
|
||||
|
||||
def _browse_openmodelica(self) -> None:
|
||||
current = self.ui.openModelicaPathEdit.text().strip()
|
||||
start = str(Path(current).expanduser().parent) if current else ""
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Select OpenModelica executable",
|
||||
start,
|
||||
"OpenModelica compiler (omc omc.exe);;All files (*)",
|
||||
)
|
||||
if path:
|
||||
# Keep symlink paths such as ~/.local/bin/omc intact; resolving them
|
||||
# could turn the selected launcher into an unrelated container script.
|
||||
self.ui.openModelicaPathEdit.setText(str(Path(path).expanduser().absolute()))
|
||||
|
||||
def _add_library_file(self) -> None:
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
@@ -176,6 +197,10 @@ class SettingsDialog(QDialog):
|
||||
self.settings.setValue("grid/graphSize", self.ui.graphGridSpinBox.value())
|
||||
self.settings.setValue("grid/graphSnapSize", self.ui.graphSnapSpinBox.value())
|
||||
self.settings.setValue("grid/iconSize", self.ui.iconGridSpinBox.value())
|
||||
self.settings.setValue(
|
||||
"simulation/openModelicaPath",
|
||||
self.ui.openModelicaPathEdit.text().strip(),
|
||||
)
|
||||
for row in range(self.ui.syntaxStylesTable.rowCount()):
|
||||
category = self.ui.syntaxStylesTable.item(row, 0).data(
|
||||
Qt.ItemDataRole.UserRole
|
||||
|
||||
64
BEdit/src/bedit/gui/generated/ui_graph_parameters_dialog.py
Normal file
64
BEdit/src/bedit/gui/generated/ui_graph_parameters_dialog.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
################################################################################
|
||||
## Form generated from reading UI file 'graph_parameters_dialog.ui'
|
||||
##
|
||||
## Created by: Qt User Interface Compiler version 6.11.1
|
||||
##
|
||||
## WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
################################################################################
|
||||
|
||||
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
||||
QMetaObject, QObject, QPoint, QRect,
|
||||
QSize, QTime, QUrl, Qt)
|
||||
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QFont, QFontDatabase, QGradient, QIcon,
|
||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QApplication, QDialog, QDialogButtonBox,
|
||||
QHeaderView, QLabel, QSizePolicy, QTreeWidget,
|
||||
QTreeWidgetItem, QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_GraphParametersDialog(object):
|
||||
def setupUi(self, GraphParametersDialog):
|
||||
if not GraphParametersDialog.objectName():
|
||||
GraphParametersDialog.setObjectName(u"GraphParametersDialog")
|
||||
GraphParametersDialog.resize(620, 480)
|
||||
self.dialogLayout = QVBoxLayout(GraphParametersDialog)
|
||||
self.dialogLayout.setObjectName(u"dialogLayout")
|
||||
self.descriptionLabel = QLabel(GraphParametersDialog)
|
||||
self.descriptionLabel.setObjectName(u"descriptionLabel")
|
||||
|
||||
self.dialogLayout.addWidget(self.descriptionLabel)
|
||||
|
||||
self.parameterTree = QTreeWidget(GraphParametersDialog)
|
||||
self.parameterTree.setObjectName(u"parameterTree")
|
||||
self.parameterTree.setAlternatingRowColors(True)
|
||||
self.parameterTree.setRootIsDecorated(True)
|
||||
self.parameterTree.setColumnCount(3)
|
||||
|
||||
self.dialogLayout.addWidget(self.parameterTree)
|
||||
|
||||
self.buttonBox = QDialogButtonBox(GraphParametersDialog)
|
||||
self.buttonBox.setObjectName(u"buttonBox")
|
||||
self.buttonBox.setStandardButtons(QDialogButtonBox.StandardButton.Cancel|QDialogButtonBox.StandardButton.Ok)
|
||||
|
||||
self.dialogLayout.addWidget(self.buttonBox)
|
||||
|
||||
|
||||
self.retranslateUi(GraphParametersDialog)
|
||||
self.buttonBox.accepted.connect(GraphParametersDialog.accept)
|
||||
self.buttonBox.rejected.connect(GraphParametersDialog.reject)
|
||||
|
||||
QMetaObject.connectSlotsByName(GraphParametersDialog)
|
||||
# setupUi
|
||||
|
||||
def retranslateUi(self, GraphParametersDialog):
|
||||
GraphParametersDialog.setWindowTitle(QCoreApplication.translate("GraphParametersDialog", u"Graph Parameters", None))
|
||||
self.descriptionLabel.setText(QCoreApplication.translate("GraphParametersDialog", u"Edit parameter values throughout the active component tree.", None))
|
||||
___qtreewidgetitem = self.parameterTree.headerItem()
|
||||
___qtreewidgetitem.setText(2, QCoreApplication.translate("GraphParametersDialog", u"Value", None))
|
||||
___qtreewidgetitem.setText(1, QCoreApplication.translate("GraphParametersDialog", u"Type", None))
|
||||
___qtreewidgetitem.setText(0, QCoreApplication.translate("GraphParametersDialog", u"Component / Parameter", None))
|
||||
# retranslateUi
|
||||
|
||||
@@ -36,84 +36,94 @@ class Ui_MainWindow(object):
|
||||
icon = QIcon()
|
||||
icon.addFile(u":/icons/icons/preferences-system.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionSimulationSettings.setIcon(icon)
|
||||
self.actionGraphParameters = QAction(MainWindow)
|
||||
self.actionGraphParameters.setObjectName(u"actionGraphParameters")
|
||||
icon1 = QIcon()
|
||||
icon1.addFile(u":/icons/icons/configure.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionGraphParameters.setIcon(icon1)
|
||||
self.actionCompile = QAction(MainWindow)
|
||||
self.actionCompile.setObjectName(u"actionCompile")
|
||||
icon1 = QIcon()
|
||||
icon1.addFile(u":/icons/icons/run-build.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCompile.setIcon(icon1)
|
||||
icon2 = QIcon()
|
||||
icon2.addFile(u":/icons/icons/run-build.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCompile.setIcon(icon2)
|
||||
self.actionRunSimulation = QAction(MainWindow)
|
||||
self.actionRunSimulation.setObjectName(u"actionRunSimulation")
|
||||
icon3 = QIcon()
|
||||
icon3.addFile(u":/icons/icons/media-playback-start.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionRunSimulation.setIcon(icon3)
|
||||
self.actionNew = QAction(MainWindow)
|
||||
self.actionNew.setObjectName(u"actionNew")
|
||||
icon2 = QIcon()
|
||||
icon2.addFile(u":/icons/icons/document-new.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionNew.setIcon(icon2)
|
||||
icon4 = QIcon()
|
||||
icon4.addFile(u":/icons/icons/document-new.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionNew.setIcon(icon4)
|
||||
self.actionRotateClockwise = QAction(MainWindow)
|
||||
self.actionRotateClockwise.setObjectName(u"actionRotateClockwise")
|
||||
icon3 = QIcon()
|
||||
icon3.addFile(u":/icons/icons/transform-rotate.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionRotateClockwise.setIcon(icon3)
|
||||
icon5 = QIcon()
|
||||
icon5.addFile(u":/icons/icons/transform-rotate.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionRotateClockwise.setIcon(icon5)
|
||||
self.actionZoomIn = QAction(MainWindow)
|
||||
self.actionZoomIn.setObjectName(u"actionZoomIn")
|
||||
icon4 = QIcon()
|
||||
icon4.addFile(u":/icons/icons/zoom-in.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionZoomIn.setIcon(icon4)
|
||||
icon6 = QIcon()
|
||||
icon6.addFile(u":/icons/icons/zoom-in.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionZoomIn.setIcon(icon6)
|
||||
self.actionZoomOut = QAction(MainWindow)
|
||||
self.actionZoomOut.setObjectName(u"actionZoomOut")
|
||||
icon5 = QIcon()
|
||||
icon5.addFile(u":/icons/icons/zoom-out.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionZoomOut.setIcon(icon5)
|
||||
icon7 = QIcon()
|
||||
icon7.addFile(u":/icons/icons/zoom-out.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionZoomOut.setIcon(icon7)
|
||||
self.actionCenterView = QAction(MainWindow)
|
||||
self.actionCenterView.setObjectName(u"actionCenterView")
|
||||
icon6 = QIcon()
|
||||
icon6.addFile(u":/icons/icons/zoom-original.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCenterView.setIcon(icon6)
|
||||
icon8 = QIcon()
|
||||
icon8.addFile(u":/icons/icons/zoom-original.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCenterView.setIcon(icon8)
|
||||
self.actionOpen = QAction(MainWindow)
|
||||
self.actionOpen.setObjectName(u"actionOpen")
|
||||
icon7 = QIcon()
|
||||
icon7.addFile(u":/icons/icons/document-open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionOpen.setIcon(icon7)
|
||||
icon9 = QIcon()
|
||||
icon9.addFile(u":/icons/icons/document-open.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionOpen.setIcon(icon9)
|
||||
self.actionReloadLibraries = QAction(MainWindow)
|
||||
self.actionReloadLibraries.setObjectName(u"actionReloadLibraries")
|
||||
self.actionReloadSimulation = QAction(MainWindow)
|
||||
self.actionReloadSimulation.setObjectName(u"actionReloadSimulation")
|
||||
self.actionSave = QAction(MainWindow)
|
||||
self.actionSave.setObjectName(u"actionSave")
|
||||
icon8 = QIcon()
|
||||
icon8.addFile(u":/icons/icons/document-save.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionSave.setIcon(icon8)
|
||||
icon10 = QIcon()
|
||||
icon10.addFile(u":/icons/icons/document-save.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionSave.setIcon(icon10)
|
||||
self.actionSaveAs = QAction(MainWindow)
|
||||
self.actionSaveAs.setObjectName(u"actionSaveAs")
|
||||
icon9 = QIcon()
|
||||
icon9.addFile(u":/icons/icons/document-save-as.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionSaveAs.setIcon(icon9)
|
||||
icon11 = QIcon()
|
||||
icon11.addFile(u":/icons/icons/document-save-as.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionSaveAs.setIcon(icon11)
|
||||
self.actionExit = QAction(MainWindow)
|
||||
self.actionExit.setObjectName(u"actionExit")
|
||||
self.actionClose = QAction(MainWindow)
|
||||
self.actionClose.setObjectName(u"actionClose")
|
||||
self.actionUndo = QAction(MainWindow)
|
||||
self.actionUndo.setObjectName(u"actionUndo")
|
||||
icon10 = QIcon()
|
||||
icon10.addFile(u":/icons/icons/edit-undo.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionUndo.setIcon(icon10)
|
||||
icon12 = QIcon()
|
||||
icon12.addFile(u":/icons/icons/edit-undo.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionUndo.setIcon(icon12)
|
||||
self.actionRedo = QAction(MainWindow)
|
||||
self.actionRedo.setObjectName(u"actionRedo")
|
||||
icon11 = QIcon()
|
||||
icon11.addFile(u":/icons/icons/edit-redo.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionRedo.setIcon(icon11)
|
||||
icon13 = QIcon()
|
||||
icon13.addFile(u":/icons/icons/edit-redo.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionRedo.setIcon(icon13)
|
||||
self.actionCut = QAction(MainWindow)
|
||||
self.actionCut.setObjectName(u"actionCut")
|
||||
icon12 = QIcon()
|
||||
icon12.addFile(u":/icons/icons/edit-cut.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCut.setIcon(icon12)
|
||||
icon14 = QIcon()
|
||||
icon14.addFile(u":/icons/icons/edit-cut.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCut.setIcon(icon14)
|
||||
self.actionCopy = QAction(MainWindow)
|
||||
self.actionCopy.setObjectName(u"actionCopy")
|
||||
icon13 = QIcon()
|
||||
icon13.addFile(u":/icons/icons/edit-copy.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCopy.setIcon(icon13)
|
||||
icon15 = QIcon()
|
||||
icon15.addFile(u":/icons/icons/edit-copy.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionCopy.setIcon(icon15)
|
||||
self.actionPaste = QAction(MainWindow)
|
||||
self.actionPaste.setObjectName(u"actionPaste")
|
||||
icon14 = QIcon()
|
||||
icon14.addFile(u":/icons/icons/edit-paste.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionPaste.setIcon(icon14)
|
||||
icon16 = QIcon()
|
||||
icon16.addFile(u":/icons/icons/edit-paste.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.actionPaste.setIcon(icon16)
|
||||
self.actionSelectAll = QAction(MainWindow)
|
||||
self.actionSelectAll.setObjectName(u"actionSelectAll")
|
||||
self.actionDelete = QAction(MainWindow)
|
||||
@@ -203,18 +213,18 @@ class Ui_MainWindow(object):
|
||||
self.workspaceHeaderLayout.setContentsMargins(6, 2, 6, 2)
|
||||
self.navigateUpButton = QToolButton(self.workspaceHeader)
|
||||
self.navigateUpButton.setObjectName(u"navigateUpButton")
|
||||
icon15 = QIcon()
|
||||
icon15.addFile(u":/icons/icons/arrow-up.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.navigateUpButton.setIcon(icon15)
|
||||
icon17 = QIcon()
|
||||
icon17.addFile(u":/icons/icons/arrow-up.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.navigateUpButton.setIcon(icon17)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.navigateUpButton)
|
||||
|
||||
self.navigateDownButton = QToolButton(self.workspaceHeader)
|
||||
self.navigateDownButton.setObjectName(u"navigateDownButton")
|
||||
self.navigateDownButton.setEnabled(False)
|
||||
icon16 = QIcon()
|
||||
icon16.addFile(u":/icons/icons/arrow-down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.navigateDownButton.setIcon(icon16)
|
||||
icon18 = QIcon()
|
||||
icon18.addFile(u":/icons/icons/arrow-down.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.navigateDownButton.setIcon(icon18)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.navigateDownButton)
|
||||
|
||||
@@ -234,9 +244,9 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.pointerToolButton = QToolButton(self.workspaceHeader)
|
||||
self.pointerToolButton.setObjectName(u"pointerToolButton")
|
||||
icon17 = QIcon()
|
||||
icon17.addFile(u":/icons/icons/edit-select.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.pointerToolButton.setIcon(icon17)
|
||||
icon19 = QIcon()
|
||||
icon19.addFile(u":/icons/icons/edit-select.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.pointerToolButton.setIcon(icon19)
|
||||
self.pointerToolButton.setCheckable(True)
|
||||
self.pointerToolButton.setChecked(True)
|
||||
|
||||
@@ -244,43 +254,43 @@ class Ui_MainWindow(object):
|
||||
|
||||
self.connectToolButton = QToolButton(self.workspaceHeader)
|
||||
self.connectToolButton.setObjectName(u"connectToolButton")
|
||||
icon18 = QIcon()
|
||||
icon18.addFile(u":/icons/icons/network-connect.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.connectToolButton.setIcon(icon18)
|
||||
icon20 = QIcon()
|
||||
icon20.addFile(u":/icons/icons/network-connect.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.connectToolButton.setIcon(icon20)
|
||||
self.connectToolButton.setCheckable(True)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.connectToolButton)
|
||||
|
||||
self.boxToolButton = QToolButton(self.workspaceHeader)
|
||||
self.boxToolButton.setObjectName(u"boxToolButton")
|
||||
icon19 = QIcon()
|
||||
icon19.addFile(u":/icons/icons/draw-rectangle.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.boxToolButton.setIcon(icon19)
|
||||
icon21 = QIcon()
|
||||
icon21.addFile(u":/icons/icons/draw-rectangle.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.boxToolButton.setIcon(icon21)
|
||||
self.boxToolButton.setCheckable(True)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.boxToolButton)
|
||||
|
||||
self.lineToolButton = QToolButton(self.workspaceHeader)
|
||||
self.lineToolButton.setObjectName(u"lineToolButton")
|
||||
icon20 = QIcon()
|
||||
icon20.addFile(u":/icons/icons/draw-bezier-curves.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.lineToolButton.setIcon(icon20)
|
||||
icon22 = QIcon()
|
||||
icon22.addFile(u":/icons/icons/draw-bezier-curves.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.lineToolButton.setIcon(icon22)
|
||||
self.lineToolButton.setCheckable(True)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.lineToolButton)
|
||||
|
||||
self.textToolButton = QToolButton(self.workspaceHeader)
|
||||
self.textToolButton.setObjectName(u"textToolButton")
|
||||
icon21 = QIcon()
|
||||
icon21.addFile(u":/icons/icons/draw-text.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.textToolButton.setIcon(icon21)
|
||||
icon23 = QIcon()
|
||||
icon23.addFile(u":/icons/icons/draw-text.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||
self.textToolButton.setIcon(icon23)
|
||||
self.textToolButton.setCheckable(True)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.textToolButton)
|
||||
|
||||
self.rotateToolButton = QToolButton(self.workspaceHeader)
|
||||
self.rotateToolButton.setObjectName(u"rotateToolButton")
|
||||
self.rotateToolButton.setIcon(icon3)
|
||||
self.rotateToolButton.setIcon(icon5)
|
||||
|
||||
self.workspaceHeaderLayout.addWidget(self.rotateToolButton)
|
||||
|
||||
@@ -433,7 +443,9 @@ class Ui_MainWindow(object):
|
||||
self.cameraToolbar.addAction(self.actionZoomOut)
|
||||
self.cameraToolbar.addAction(self.actionCenterView)
|
||||
self.simulationToolbar.addAction(self.actionSimulationSettings)
|
||||
self.simulationToolbar.addAction(self.actionGraphParameters)
|
||||
self.simulationToolbar.addAction(self.actionCompile)
|
||||
self.simulationToolbar.addAction(self.actionRunSimulation)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
|
||||
@@ -448,6 +460,10 @@ class Ui_MainWindow(object):
|
||||
self.actionSimulationSettings.setText(QCoreApplication.translate("MainWindow", u"Simulation Settings", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
self.actionSimulationSettings.setStatusTip(QCoreApplication.translate("MainWindow", u"Edit settings stored in the active graph", None))
|
||||
#endif // QT_CONFIG(statustip)
|
||||
self.actionGraphParameters.setText(QCoreApplication.translate("MainWindow", u"Graph Parameters", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
self.actionGraphParameters.setStatusTip(QCoreApplication.translate("MainWindow", u"Edit parameters throughout the active graph", None))
|
||||
#endif // QT_CONFIG(statustip)
|
||||
self.actionCompile.setText(QCoreApplication.translate("MainWindow", u"Compile", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
@@ -455,6 +471,13 @@ class Ui_MainWindow(object):
|
||||
#endif // QT_CONFIG(statustip)
|
||||
#if QT_CONFIG(shortcut)
|
||||
self.actionCompile.setShortcut(QCoreApplication.translate("MainWindow", u"F5", None))
|
||||
#endif // QT_CONFIG(shortcut)
|
||||
self.actionRunSimulation.setText(QCoreApplication.translate("MainWindow", u"Run", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
self.actionRunSimulation.setStatusTip(QCoreApplication.translate("MainWindow", u"Run the simulation", None))
|
||||
#endif // QT_CONFIG(statustip)
|
||||
#if QT_CONFIG(shortcut)
|
||||
self.actionRunSimulation.setShortcut(QCoreApplication.translate("MainWindow", u"F6", None))
|
||||
#endif // QT_CONFIG(shortcut)
|
||||
self.actionNew.setText(QCoreApplication.translate("MainWindow", u"&New", None))
|
||||
#if QT_CONFIG(statustip)
|
||||
|
||||
@@ -17,10 +17,10 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
||||
from PySide6.QtWidgets import (QAbstractButton, QAbstractItemView, QApplication, QDialog,
|
||||
QDialogButtonBox, QFormLayout, QGroupBox, QHBoxLayout,
|
||||
QHeaderView, QLabel, QListWidget, QListWidgetItem,
|
||||
QPushButton, QSizePolicy, QSpacerItem, QSpinBox,
|
||||
QTabWidget, QTableWidget, QTableWidgetItem, QVBoxLayout,
|
||||
QWidget)
|
||||
QHeaderView, QLabel, QLineEdit, QListWidget,
|
||||
QListWidgetItem, QPushButton, QSizePolicy, QSpacerItem,
|
||||
QSpinBox, QTabWidget, QTableWidget, QTableWidgetItem,
|
||||
QVBoxLayout, QWidget)
|
||||
|
||||
class Ui_SettingsDialog(object):
|
||||
def setupUi(self, SettingsDialog):
|
||||
@@ -104,6 +104,48 @@ class Ui_SettingsDialog(object):
|
||||
self.generalLayout.addItem(self.generalSpacer)
|
||||
|
||||
self.settingsTabs.addTab(self.generalTab, "")
|
||||
self.simulationTab = QWidget()
|
||||
self.simulationTab.setObjectName(u"simulationTab")
|
||||
self.simulationTabLayout = QVBoxLayout(self.simulationTab)
|
||||
self.simulationTabLayout.setObjectName(u"simulationTabLayout")
|
||||
self.openModelicaGroupBox = QGroupBox(self.simulationTab)
|
||||
self.openModelicaGroupBox.setObjectName(u"openModelicaGroupBox")
|
||||
self.openModelicaLayout = QVBoxLayout(self.openModelicaGroupBox)
|
||||
self.openModelicaLayout.setObjectName(u"openModelicaLayout")
|
||||
self.openModelicaPathLabel = QLabel(self.openModelicaGroupBox)
|
||||
self.openModelicaPathLabel.setObjectName(u"openModelicaPathLabel")
|
||||
|
||||
self.openModelicaLayout.addWidget(self.openModelicaPathLabel)
|
||||
|
||||
self.openModelicaPathLayout = QHBoxLayout()
|
||||
self.openModelicaPathLayout.setObjectName(u"openModelicaPathLayout")
|
||||
self.openModelicaPathEdit = QLineEdit(self.openModelicaGroupBox)
|
||||
self.openModelicaPathEdit.setObjectName(u"openModelicaPathEdit")
|
||||
|
||||
self.openModelicaPathLayout.addWidget(self.openModelicaPathEdit)
|
||||
|
||||
self.browseOpenModelicaButton = QPushButton(self.openModelicaGroupBox)
|
||||
self.browseOpenModelicaButton.setObjectName(u"browseOpenModelicaButton")
|
||||
|
||||
self.openModelicaPathLayout.addWidget(self.browseOpenModelicaButton)
|
||||
|
||||
|
||||
self.openModelicaLayout.addLayout(self.openModelicaPathLayout)
|
||||
|
||||
self.openModelicaHintLabel = QLabel(self.openModelicaGroupBox)
|
||||
self.openModelicaHintLabel.setObjectName(u"openModelicaHintLabel")
|
||||
self.openModelicaHintLabel.setWordWrap(True)
|
||||
|
||||
self.openModelicaLayout.addWidget(self.openModelicaHintLabel)
|
||||
|
||||
|
||||
self.simulationTabLayout.addWidget(self.openModelicaGroupBox)
|
||||
|
||||
self.simulationSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
|
||||
|
||||
self.simulationTabLayout.addItem(self.simulationSpacer)
|
||||
|
||||
self.settingsTabs.addTab(self.simulationTab, "")
|
||||
self.syntaxTab = QWidget()
|
||||
self.syntaxTab.setObjectName(u"syntaxTab")
|
||||
self.syntaxTabLayout = QVBoxLayout(self.syntaxTab)
|
||||
@@ -205,6 +247,12 @@ class Ui_SettingsDialog(object):
|
||||
self.iconGridLabel.setText(QCoreApplication.translate("SettingsDialog", u"Icon grid size:", None))
|
||||
self.iconGridSpinBox.setSuffix(QCoreApplication.translate("SettingsDialog", u" units", None))
|
||||
self.settingsTabs.setTabText(self.settingsTabs.indexOf(self.generalTab), QCoreApplication.translate("SettingsDialog", u"General", None))
|
||||
self.openModelicaGroupBox.setTitle(QCoreApplication.translate("SettingsDialog", u"OpenModelica", None))
|
||||
self.openModelicaPathLabel.setText(QCoreApplication.translate("SettingsDialog", u"OpenModelica executable:", None))
|
||||
self.openModelicaPathEdit.setPlaceholderText(QCoreApplication.translate("SettingsDialog", u"Leave empty to find omc on PATH", None))
|
||||
self.browseOpenModelicaButton.setText(QCoreApplication.translate("SettingsDialog", u"Browse\u2026", None))
|
||||
self.openModelicaHintLabel.setText(QCoreApplication.translate("SettingsDialog", u"Select the omc executable, for example ~/.local/bin/omc.", None))
|
||||
self.settingsTabs.setTabText(self.settingsTabs.indexOf(self.simulationTab), QCoreApplication.translate("SettingsDialog", u"Simulation", None))
|
||||
self.syntaxHintLabel.setText(QCoreApplication.translate("SettingsDialog", u"Double-click a colour cell to choose a colour. Word lists remain editable in data/syntax/openmodelica.json.", None))
|
||||
___qtablewidgetitem = self.syntaxStylesTable.horizontalHeaderItem(0)
|
||||
___qtablewidgetitem.setText(QCoreApplication.translate("SettingsDialog", u"Expression type", None))
|
||||
|
||||
@@ -18,6 +18,7 @@ from bedit.core.serializer import DocumentSerializer
|
||||
from bedit.core.simulation import Simulation
|
||||
from bedit.gui.controllers.document import DocumentController
|
||||
from bedit.gui.dialogs.component_options import ComponentOptionsDialog
|
||||
from bedit.gui.dialogs.graph_parameters import GraphParametersDialog
|
||||
from bedit.gui.dialogs.item_options import ItemOptionsDialog
|
||||
from bedit.gui.models.library_repository import LibraryRepository
|
||||
from bedit.gui.models.library_tree import (
|
||||
@@ -55,7 +56,9 @@ class MainWindow(QMainWindow):
|
||||
self._applying_text_definition = False
|
||||
|
||||
self.libraries = LibraryRepository(self)
|
||||
self.simulation = Simulation()
|
||||
self.simulation = Simulation(
|
||||
openmodelica_path=SettingsDialog.openmodelica_path(self.settings)
|
||||
)
|
||||
self.document_controller = DocumentController(self, simulation=self.simulation)
|
||||
self.library_tree_model = LibraryTreeModel(
|
||||
self.libraries,
|
||||
@@ -162,7 +165,9 @@ class MainWindow(QMainWindow):
|
||||
self.ui.actionSimulationSettings.triggered.connect(
|
||||
self.show_simulation_settings
|
||||
)
|
||||
self.ui.actionGraphParameters.triggered.connect(self.show_graph_parameters)
|
||||
self.ui.actionCompile.triggered.connect(self.compile_active_graph)
|
||||
self.ui.actionRunSimulation.triggered.connect(self.run_simulation)
|
||||
self.document_controller.undo_stack.canUndoChanged.connect(self.ui.actionUndo.setEnabled)
|
||||
self.document_controller.undo_stack.canRedoChanged.connect(self.ui.actionRedo.setEnabled)
|
||||
self.document_controller.modifiedChanged.connect(lambda _modified: self._update_title())
|
||||
@@ -218,6 +223,21 @@ class MainWindow(QMainWindow):
|
||||
if dialog.exec() == dialog.DialogCode.Accepted:
|
||||
self.document_controller.edit_simulation_settings(dialog.settings)
|
||||
|
||||
@Slot()
|
||||
def show_graph_parameters(self) -> None:
|
||||
component = self.document_controller.active_component
|
||||
if component is None or component.implementation_kind != "graph":
|
||||
return
|
||||
dialog = GraphParametersDialog(component, self)
|
||||
if dialog.exec() == dialog.DialogCode.Accepted:
|
||||
try:
|
||||
self.document_controller.edit_graph_parameter_values(
|
||||
component.id, dialog.parameter_values
|
||||
)
|
||||
except ValueError as error:
|
||||
self.log.error("Could not change graph parameters: %s", error)
|
||||
QMessageBox.warning(self, "Cannot change graph parameters", str(error))
|
||||
|
||||
@Slot()
|
||||
def compile_active_graph(self) -> None:
|
||||
try:
|
||||
@@ -226,6 +246,14 @@ class MainWindow(QMainWindow):
|
||||
self.log.error("Compile failed: %s", error)
|
||||
QMessageBox.warning(self, "Cannot compile", str(error))
|
||||
|
||||
@Slot()
|
||||
def run_simulation(self) -> None:
|
||||
try:
|
||||
self.document_controller.run_simulation()
|
||||
except Exception as error:
|
||||
self.log.exception("Simulation run failed")
|
||||
QMessageBox.warning(self, "Cannot run simulation", str(error))
|
||||
|
||||
def _restore_window_geometry(self) -> None:
|
||||
geometry = self.settings.value("window/geometry")
|
||||
if geometry is not None:
|
||||
@@ -252,7 +280,9 @@ class MainWindow(QMainWindow):
|
||||
self.ui.workspaceStack.setCurrentWidget(self.ui.emptyPage)
|
||||
self._set_graph_controls_visible(False)
|
||||
self.ui.actionSimulationSettings.setEnabled(False)
|
||||
self.ui.actionGraphParameters.setEnabled(False)
|
||||
self.ui.actionCompile.setEnabled(False)
|
||||
self.ui.actionRunSimulation.setEnabled(False)
|
||||
self._update_edit_actions()
|
||||
return
|
||||
self.ui.graphBreadcrumbLabel.setText(" › ".join(self.document_controller.breadcrumb()))
|
||||
@@ -261,7 +291,9 @@ class MainWindow(QMainWindow):
|
||||
)
|
||||
is_graph = component.implementation_kind == "graph"
|
||||
self.ui.actionSimulationSettings.setEnabled(is_graph)
|
||||
self.ui.actionGraphParameters.setEnabled(is_graph)
|
||||
self.ui.actionCompile.setEnabled(is_graph)
|
||||
self.ui.actionRunSimulation.setEnabled(is_graph)
|
||||
self.ui.workspaceModeLabel.setText("Graph" if is_graph else "Text")
|
||||
self.ui.workspaceStack.setCurrentWidget(
|
||||
self.ui.graphPage if is_graph else self.ui.textPage
|
||||
@@ -483,8 +515,14 @@ class MainWindow(QMainWindow):
|
||||
dialog = SettingsDialog(self)
|
||||
dialog.settingsChanged.connect(self.reload_libraries)
|
||||
dialog.settingsChanged.connect(self.refresh_editor_settings)
|
||||
dialog.settingsChanged.connect(self.refresh_simulation_preferences)
|
||||
dialog.exec()
|
||||
|
||||
def refresh_simulation_preferences(self) -> None:
|
||||
self.simulation.openmodelica_path = SettingsDialog.openmodelica_path(
|
||||
self.settings
|
||||
)
|
||||
|
||||
def refresh_editor_settings(self) -> None:
|
||||
scene = self.ui.graphView.scene()
|
||||
if scene is not None:
|
||||
|
||||
Reference in New Issue
Block a user