Fixed signal tree and added progress bar in besim

This commit is contained in:
2026-08-02 18:51:33 +02:00
parent dfff760cc1
commit 961a173a17
5 changed files with 40 additions and 4 deletions

View File

@@ -15,6 +15,14 @@ from bedit_gui.views.simulation_window import SimulationWindow
logger = get_logger(__name__) logger = get_logger(__name__)
def _signal_tree_parts(signal: str) -> list[str]:
if signal.startswith("der(") and signal.endswith(")"):
parts = signal[4:-1].split(".")
if len(parts) > 1:
return [*parts[:-1], f"der({parts[-1]})"]
return signal.split(".")
class SimulationPlotController(QObject): class SimulationPlotController(QObject):
def __init__(self, window: SimulationWindow, files: SimulationFileController) -> None: def __init__(self, window: SimulationWindow, files: SimulationFileController) -> None:
super().__init__(window) super().__init__(window)
@@ -129,7 +137,7 @@ class SimulationPlotController(QObject):
nodes: dict[tuple[str, ...], QTreeWidgetItem] = {} nodes: dict[tuple[str, ...], QTreeWidgetItem] = {}
for signal in signals: for signal in signals:
parent = tree.invisibleRootItem() parent = tree.invisibleRootItem()
parts = signal.split(".") parts = _signal_tree_parts(signal)
for depth, part in enumerate(parts, start=1): for depth, part in enumerate(parts, start=1):
path = tuple(parts[:depth]) path = tuple(parts[:depth])
item = nodes.get(path) item = nodes.get(path)

View File

@@ -24,6 +24,7 @@ class SimulationRunController(QObject):
run_completed = Signal(object) run_completed = Signal(object)
run_cancelled = Signal() run_cancelled = Signal()
run_failed = Signal(object) run_failed = Signal(object)
run_progress = Signal(int)
simulation_state_changed = Signal() simulation_state_changed = Signal()
def __init__(self, window: SimulationWindow, files: SimulationFileController, session_factory: SessionFactory = _create_session) -> None: def __init__(self, window: SimulationWindow, files: SimulationFileController, session_factory: SessionFactory = _create_session) -> None:
@@ -34,6 +35,7 @@ class SimulationRunController(QObject):
self.session: SimulationSession | None = None self.session: SimulationSession | None = None
self._running = False self._running = False
self._reset_pending = False self._reset_pending = False
self.window.ui.progressBar.setValue(0)
window.ui.actionRun_Simulation.triggered.connect(self.start) window.ui.actionRun_Simulation.triggered.connect(self.start)
window.ui.actionStop_Simulation.triggered.connect(self.stop) window.ui.actionStop_Simulation.triggered.connect(self.stop)
@@ -42,6 +44,7 @@ class SimulationRunController(QObject):
self.run_completed.connect(self._completed) self.run_completed.connect(self._completed)
self.run_cancelled.connect(self._cancelled) self.run_cancelled.connect(self._cancelled)
self.run_failed.connect(self._failed) self.run_failed.connect(self._failed)
self.run_progress.connect(self.window.ui.progressBar.setValue)
self._load_session() self._load_session()
@property @property
@@ -54,6 +57,7 @@ class SimulationRunController(QObject):
start_time = self.session.settings.start_time start_time = self.session.settings.start_time
stop_time = self.session.current_end_time + self.session.settings.duration stop_time = self.session.current_end_time + self.session.settings.duration
self._running = True self._running = True
self.window.ui.progressBar.setValue(0)
self._update_actions() self._update_actions()
logger.info("Starting simulation from %s to %s", start_time, stop_time) logger.info("Starting simulation from %s to %s", start_time, stop_time)
Thread(target=self._run_worker, args=(self.session,), name="besim-run", daemon=True).start() Thread(target=self._run_worker, args=(self.session,), name="besim-run", daemon=True).start()
@@ -78,13 +82,14 @@ class SimulationRunController(QObject):
if self.session is None: if self.session is None:
return return
self.session.reset() self.session.reset()
self.window.ui.progressBar.setValue(0)
self._store_session_state() self._store_session_state()
logger.info("Reset simulation to start time %s", self.session.current_end_time) logger.info("Reset simulation to start time %s", self.session.current_end_time)
self._update_actions() self._update_actions()
def _run_worker(self, session: SimulationSession) -> None: def _run_worker(self, session: SimulationSession) -> None:
try: try:
result = asyncio.run(session.run_next()) result = asyncio.run(self._run_with_progress(session))
except SimulationCancelledError: except SimulationCancelledError:
self.run_cancelled.emit() self.run_cancelled.emit()
except (OSError, RuntimeError, TypeError, ValueError) as exc: except (OSError, RuntimeError, TypeError, ValueError) as exc:
@@ -92,9 +97,21 @@ class SimulationRunController(QObject):
else: else:
self.run_completed.emit(result) self.run_completed.emit(result)
async def _run_with_progress(self, session: SimulationSession) -> SimulationResult:
task = asyncio.create_task(session.run_next())
last_progress = -1
while not task.done():
progress = min(session.get_progress(), 99)
if progress != last_progress:
self.run_progress.emit(progress)
last_progress = progress
await asyncio.sleep(0.1)
return await task
def _completed(self, result: SimulationResult) -> None: def _completed(self, result: SimulationResult) -> None:
self._running = False self._running = False
self._store_session_state() self._store_session_state()
self.window.ui.progressBar.setValue(100)
logger.info("Simulation completed at time %s", self.session.current_end_time if self.session is not None else "unknown") logger.info("Simulation completed at time %s", self.session.current_end_time if self.session is not None else "unknown")
if result.process_output.strip(): if result.process_output.strip():
logger.info("Simulation output:\n%s", result.process_output.strip()) logger.info("Simulation output:\n%s", result.process_output.strip())
@@ -122,6 +139,7 @@ class SimulationRunController(QObject):
root = self.files.root root = self.files.root
compiled = self.files.compiled_model compiled = self.files.compiled_model
self._reset_pending = False self._reset_pending = False
self.window.ui.progressBar.setValue(0)
if root is None or compiled is None: if root is None or compiled is None:
self.session = None self.session = None
else: else:

View File

@@ -27,6 +27,13 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QMenuBar" name="menubar"> <widget class="QMenuBar" name="menubar">
@@ -35,7 +42,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>800</width>
<height>22</height> <height>19</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menuFile"> <widget class="QMenu" name="menuFile">

View File

@@ -45,6 +45,9 @@ class SimulationSession:
def is_running(self) -> bool: def is_running(self) -> bool:
return self._simulation.is_running return self._simulation.is_running
def get_progress(self) -> int:
return self._simulation.get_progress()
async def run_next(self) -> SimulationResult: async def run_next(self) -> SimulationResult:
start_time = self.settings.start_time start_time = self.settings.start_time
stop_time = self.current_end_time + self.settings.duration stop_time = self.current_end_time + self.settings.duration

View File

@@ -2,7 +2,7 @@
"file_format_version": 1, "file_format_version": 1,
"root_type": "simulation_root", "root_type": "simulation_root",
"format_version": 1, "format_version": 1,
"source_document": "/home/joppe/Projects/BEdit/untitled.bedit.json", "source_document": "untitled.bedit.json",
"source_document_id": "3b6780c7-488b-471e-a784-392db7632090", "source_document_id": "3b6780c7-488b-471e-a784-392db7632090",
"component": "50e6ef97-f686-4400-bc01-e5a352e8cc22", "component": "50e6ef97-f686-4400-bc01-e5a352e8cc22",
"component_path": "some_bondgraph", "component_path": "some_bondgraph",