Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
1bf9114
Basic prototype of tabs and simulation run widget
TooMuchDakka Dec 26, 2025
33c1e54
Added quantum register search controls and fixed qubits toggle functi…
TooMuchDakka Dec 28, 2025
9008f95
Added validator for quantum register contents input fields. Added qub…
TooMuchDakka Dec 28, 2025
7f103dc
Removed some unnecessary scroll areas between simulation run widget a…
TooMuchDakka Dec 29, 2025
146b2fb
Added comment regarding potential rendering issues when using widgets…
TooMuchDakka Dec 31, 2025
7be1d58
Basic prototype using model-view architecture to display simulation r…
TooMuchDakka Dec 31, 2025
9abbe44
Basic still faulty print of quantum register contents in QStyledItemD…
TooMuchDakka Jan 2, 2026
9f0b759
Split model and styled item delegate as well as simulation run edit d…
TooMuchDakka Jan 4, 2026
45e6a91
Add logic for simulation run list controls as well as for simulation …
TooMuchDakka Jan 4, 2026
e41054a
Added icons to buttons of simulation run overview dialog
TooMuchDakka Jan 4, 2026
74f39cd
Fixed height calculation for simulation run cards
TooMuchDakka Jan 5, 2026
3051605
Replaced InputOutputStateMapping with SimulationRunModel containing f…
TooMuchDakka Jan 5, 2026
04ee7e2
Refactored existing simulation run editor dialog to be opened when cl…
TooMuchDakka Jan 6, 2026
a5e87fa
Internal simulation run model is now updated in edit dialog and added…
TooMuchDakka Jan 6, 2026
dedb20a
Added controls to init and reset expected output state in simulation …
TooMuchDakka Jan 7, 2026
3775c90
Added quantum register layout info label, quantum register content va…
TooMuchDakka Jan 7, 2026
8e9899f
Invalid values for qubits of quantum register will no disable control…
TooMuchDakka Jan 7, 2026
823d9b9
Added warnings for switching between simulation run tabs widget tabs …
TooMuchDakka Jan 7, 2026
b28c0a0
Implemented basic thread communication between UI and simulation run …
TooMuchDakka Jan 8, 2026
067fb59
Added progress controls and cancellation controls to qt simulation ru…
TooMuchDakka Jan 8, 2026
ce68abe
Refactored simulation run overview delegate by moving shared code int…
TooMuchDakka Jan 9, 2026
4f29d10
Added simulation run execution styled item delegate and small bugfixe…
TooMuchDakka Jan 11, 2026
fa15d2c
Refactored all simulation run combinations generator into worker inst…
TooMuchDakka Jan 13, 2026
34ba955
Small improvements helping to reduce a complete hang of the GUI added…
TooMuchDakka Jan 15, 2026
a11727c
All input states generator now used QReadWriteLock instead of QMutex.…
TooMuchDakka Jan 15, 2026
e238121
mend
TooMuchDakka Jan 15, 2026
50fb7a8
Simulation run dialog closeEvent is now correctly handled and correct…
TooMuchDakka Jan 15, 2026
6497271
Edit dialog of simulation run now uses copy of reference simulation r…
TooMuchDakka Jan 15, 2026
e3bc0b6
Basic setup of ijson library to allow for import of simulation runs f…
TooMuchDakka Jan 18, 2026
f83c6f1
Added tool tip containing information about expected .json file forma…
TooMuchDakka Jan 18, 2026
fe63c77
Reworked acknowledgement of batch data to worker by introducing separ…
TooMuchDakka Jan 18, 2026
4d26730
Refactored some shared worker functionality into shared base class
TooMuchDakka Jan 18, 2026
2a687f4
Added descriptive comments about worker-object and QThread relationsh…
TooMuchDakka Jan 19, 2026
7cd18b8
Refactored shared logging and message box functionality to helper cla…
TooMuchDakka Jan 20, 2026
1e8aec3
Refactored simulation run export dialog to use reusable BaseProgressD…
TooMuchDakka Jan 20, 2026
5891e8e
Refactored simulation run import worker/dialog to use shared worker/p…
TooMuchDakka Jan 21, 2026
6b1e472
Simulation run execution worker and dialog are now using batch instea…
TooMuchDakka Jan 22, 2026
d7c2640
Simplified input state generation loop in simulatin run generator worker
TooMuchDakka Jan 22, 2026
0b86952
Split __init__ function creating dialog controls into separate functi…
TooMuchDakka Jan 22, 2026
0eb4e74
All simulation run dialogs are now centered when opened, added functi…
TooMuchDakka Jan 22, 2026
2c2ebb6
Simulation run editor will now close when any of the required QtWidge…
TooMuchDakka Jan 23, 2026
7d14e7a
Refactoring of simulation_view folder by creating subfolders to group…
TooMuchDakka Jan 23, 2026
a8f02ca
QuantumCircuitSimulationDialog is now opened using offically recommen…
TooMuchDakka Jan 23, 2026
045593d
Simulation run styled item delegate now draws expected and actual qua…
TooMuchDakka Jan 24, 2026
3adb48d
Simulation run execution dialog listview now also lists help text reg…
TooMuchDakka Jan 25, 2026
cd04d5a
Simulation run editor now displays both the expected as well as the a…
TooMuchDakka Jan 25, 2026
4e9f401
Quantum register and qubit search functionality now also includes exp…
TooMuchDakka Jan 25, 2026
2f56a45
Improvided error reporting on expected batch data type missmatch
TooMuchDakka Jan 26, 2026
0835ca6
Unified checks for required QtWidgets in all dialogs and renamed opti…
TooMuchDakka Jan 26, 2026
0f966ff
Added reject() implementation to handle correctly reuse cancellation …
TooMuchDakka Jan 26, 2026
6dcbdb9
Associated SyReC program is now also serialized into exported JSON da…
TooMuchDakka Jan 28, 2026
e2f9fb4
Fixed enabled state of simulation run modification buttons when cance…
TooMuchDakka Jan 28, 2026
c217ec7
Added optional typing-extensions project dependency
TooMuchDakka Jan 28, 2026
44bde58
Export to file now allows for file creation, fixed display of runtime…
TooMuchDakka Jan 28, 2026
e118494
Applied CodeRabbit code review suggestions
TooMuchDakka Jan 29, 2026
3852240
Exporting stringified SyReC programs is only supported in quantum cir…
TooMuchDakka Jan 29, 2026
d4b8bb0
Further CodeRabbit code review suggestions
TooMuchDakka Jan 29, 2026
75198a1
Added pyqtSlot() decorator to simulation run editor dialog
TooMuchDakka Jan 29, 2026
3eb25c3
Fixed decorator signature missmatch during expected output state miss…
TooMuchDakka Jan 29, 2026
380d3b0
Removed unneeded regex in simulation run editor dialog
TooMuchDakka Jan 29, 2026
5a8fc84
Added missing return type to __init__ constructors of newly added cla…
TooMuchDakka Jan 29, 2026
a1f384e
Further CodeRabbit suggestions that unifies worker and worker thread …
TooMuchDakka Jan 30, 2026
9b40e65
Added missing @override decorators to closeEvent and reject functions…
TooMuchDakka Jan 30, 2026
e7880a8
Removed redundant name parameter from signal declarations and smaller…
TooMuchDakka Jan 31, 2026
9259c47
Added prototype refactoring of cancellable base worker to support pro…
TooMuchDakka Feb 1, 2026
fd8dda5
Reworked all input states genertion worker to use new producer worker…
TooMuchDakka Feb 1, 2026
76dc5a4
Refactored simulation run json import worker and dialog to use produc…
TooMuchDakka Feb 1, 2026
a33c6d2
Refactored simulation run json exportt worker and dialog to use produ…
TooMuchDakka Feb 1, 2026
4d04744
Moved QtSimulationRunModel property shared by all simulation run dial…
TooMuchDakka Feb 1, 2026
bd3b1af
Added import failure and default fallback for ijson package
TooMuchDakka Feb 1, 2026
81aa987
Added some doc strings and refactored some shared functionality in si…
TooMuchDakka Feb 3, 2026
9600082
Simulation run execution mode can now be selected via dropdown. Execu…
TooMuchDakka Feb 4, 2026
800fba9
Added some docstrings and marked all protected/private instance varia…
TooMuchDakka Feb 4, 2026
8ea4637
Fixed various smaller selection change bugs that effected the simulat…
TooMuchDakka Feb 4, 2026
859efae
Added back missing edited simulation run model index instance variabl…
TooMuchDakka Feb 4, 2026
92eca56
Merge of changes from main branch
TooMuchDakka Feb 4, 2026
0fe9463
Refactored some class variables to instance variable in SyReCEditor p…
TooMuchDakka Feb 4, 2026
5357109
Added temporary workaround for quantum registers of ancillary variabl…
TooMuchDakka Feb 4, 2026
6c9fc03
CodeRabbit trivial or minor issue suggestions
TooMuchDakka Feb 4, 2026
3b49ad7
Enabling simulation run execution controls in load from file tab now …
TooMuchDakka Feb 4, 2026
58bca5b
Simulation run json export worker now puts element in queue before em…
TooMuchDakka Feb 4, 2026
4916ee5
Further CodeRabbit suggestions
TooMuchDakka Feb 5, 2026
348ad2a
CodeRabbit suggestions to replace positional boolean arguments with k…
TooMuchDakka Feb 5, 2026
b8bc8ce
Transformed some boolean positional arguments to keyword only ones an…
TooMuchDakka Feb 5, 2026
63ae6c7
Transformed some boolean positional arguments to keyword only ones an…
TooMuchDakka Feb 5, 2026
f03adbe
Fixed some invalid types in typing.cast calls as well as wrong type h…
TooMuchDakka Feb 5, 2026
61181f4
Removed some dead code and simplified match check for quantum registe…
TooMuchDakka Feb 5, 2026
c5c204b
Updated parent widget constructor argument type signaturet in LineEdi…
TooMuchDakka Feb 5, 2026
f2b0ab3
Added missing return type to LineEditWithDynamicWidth constructor
TooMuchDakka Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ requires-python = ">=3.10"
dependencies = [
"mqt.core~=3.4.1",
"PyQt6>=6.8",
"ijson>=3.4.0",
"typing-extensions>=4.1.0; python_version < '3.11'"
]
Comment thread
TooMuchDakka marked this conversation as resolved.
dynamic = ["version"]

Expand Down Expand Up @@ -153,7 +155,7 @@ explicit_package_bases = true
warn_unreachable = true

[[tool.mypy.overrides]]
module = ["mqt.syrec.pysyrec.*", "PyQt6.*"]
module = ["mqt.syrec.pysyrec.*", "PyQt6.*", "ijson.*"]
ignore_missing_imports = true


Expand Down Expand Up @@ -212,6 +214,7 @@ extend-select = [
"YTT", # flake8-2020
]
ignore = [
"FBT001", # Boolean positional arguments - conflicts with PyQt6 signal/slot mechanism
"PLR09", # Too many <...>
"PLR2004", # Magic value used in comparison
"S101", # Use of assert detected
Expand Down
65 changes: 65 additions & 0 deletions python/mqt/syrec/logger_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

import logging
from typing import Final

DEFAULT_LOGGER_NAME: Final[str] = "syrec-console-logger"


def configure_default_console_logger() -> None:
# For supported log message formats (see https://docs.python.org/3/library/logging.html#formatter-objects)
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
if logger.handlers:
return

handler = logging.StreamHandler()
handler.setFormatter(
logging.Formatter(
"%(asctime)s-%(levelname)s-[%(filename)s:%(lineno)s - %(funcName)20s()]-%(message)s",
datefmt="%H:%M:%S",
)
)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)


def log_debug_to_console(
info_msg: str, num_additionally_skipped_stack_frames_starting_from_caller_function: int = 0
) -> None:
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
# We do not want to log the origin of the helper function but of the caller of the function itself.
# The origin of the log entry is set to the stack frame of the caller but can be advanced further up in the stack trace
logger.debug(msg=info_msg, stacklevel=(2 + num_additionally_skipped_stack_frames_starting_from_caller_function))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.


def log_info_to_console(
info_msg: str, num_additionally_skipped_stack_frames_starting_from_caller_function: int = 0
) -> None:
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
# We do not want to log the origin of the helper function but of the caller of the function itself.
# The origin of the log entry is set to the stack frame of the caller but can be advanced further up in the stack trace
logger.info(msg=info_msg, stacklevel=(2 + num_additionally_skipped_stack_frames_starting_from_caller_function))


def log_warning_to_console(
warn_msg: str, num_additionally_skipped_stack_frames_starting_from_caller_function: int = 0
) -> None:
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
# We do not want to log the origin of the helper function but of the caller of the function itself.
# The origin of the log entry is set to the stack frame of the caller but can be advanced further up in the stack trace
logger.warning(msg=warn_msg, stacklevel=(2 + num_additionally_skipped_stack_frames_starting_from_caller_function))


def log_error_to_console(
err_msg: str, num_additionally_skipped_stack_frames_starting_from_caller_function: int = 0
) -> None:
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
# We do not want to log the origin of the helper function but of the caller of the function itself.
# The origin of the log entry is set to the stack frame of the caller but can be advanced further up in the stack trace
logger.error(msg=err_msg, stacklevel=(2 + num_additionally_skipped_stack_frames_starting_from_caller_function))
144 changes: 144 additions & 0 deletions python/mqt/syrec/message_box_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

from __future__ import annotations

import sys
from enum import Enum

from PyQt6 import QtWidgets

if sys.version_info >= (3, 11):
from typing import assert_never
else:
from typing_extensions import assert_never

from .logger_utils import log_debug_to_console, log_error_to_console, log_info_to_console, log_warning_to_console


class MessageBoxType(Enum):
QUESTION = 0
INFO = 1
WARNING = 2
ERROR = 3


def show_and_request_ok_in_optionally_cancellable_notification(
message_box_type: MessageBoxType,
message_box_parent: QtWidgets.QWidget,
message_box_title: str,
message_box_content: str,
*,
is_cancellable: bool,
log_contents: bool = True,
) -> bool:
clicked_message_box_button: QtWidgets.QMessageBox.StandardButton | None = None
match message_box_type:
case MessageBoxType.QUESTION:
if log_contents:
log_debug_to_console(
f"{message_box_title} - {message_box_content}",
num_additionally_skipped_stack_frames_starting_from_caller_function=1,
)

clicked_message_box_button = QtWidgets.QMessageBox.question(
message_box_parent,
message_box_title,
message_box_content,
buttons=_get_buttons_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
defaultButton=_get_default_button_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
)
return _check_whether_message_ok_was_clicked(message_box_type, clicked_message_box_button)
case MessageBoxType.INFO:
if log_contents:
log_info_to_console(
f"{message_box_title} - {message_box_content}",
num_additionally_skipped_stack_frames_starting_from_caller_function=1,
)

clicked_message_box_button = QtWidgets.QMessageBox.information(
message_box_parent,
message_box_title,
message_box_content,
buttons=_get_buttons_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
defaultButton=_get_default_button_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
)
return _check_whether_message_ok_was_clicked(message_box_type, clicked_message_box_button)
case MessageBoxType.WARNING:
if log_contents:
log_warning_to_console(
f"{message_box_title} - {message_box_content}",
num_additionally_skipped_stack_frames_starting_from_caller_function=1,
)

clicked_message_box_button = QtWidgets.QMessageBox.warning(
message_box_parent,
message_box_title,
message_box_content,
buttons=_get_buttons_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
defaultButton=_get_default_button_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
)
return _check_whether_message_ok_was_clicked(message_box_type, clicked_message_box_button)
case MessageBoxType.ERROR:
if log_contents:
log_error_to_console(
f"{message_box_title} - {message_box_content}",
num_additionally_skipped_stack_frames_starting_from_caller_function=1,
)

clicked_message_box_button = QtWidgets.QMessageBox.critical(
message_box_parent,
message_box_title,
message_box_content,
buttons=_get_buttons_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
defaultButton=_get_default_button_for_message_box_type(message_box_type, is_cancellable=is_cancellable),
)
return _check_whether_message_ok_was_clicked(message_box_type, clicked_message_box_button)
case _:
# Added guard to handle new message box types
assert_never(message_box_type)


def _get_buttons_for_message_box_type(
message_box_type: MessageBoxType, *, is_cancellable: bool
) -> QtWidgets.QMessageBox.StandardButton:
if message_box_type == MessageBoxType.QUESTION:
return (
(QtWidgets.QMessageBox.StandardButton.Yes | QtWidgets.QMessageBox.StandardButton.No)
if is_cancellable
else QtWidgets.QMessageBox.StandardButton.Yes
)
return (
(QtWidgets.QMessageBox.StandardButton.Ok | QtWidgets.QMessageBox.StandardButton.Cancel)
if is_cancellable
else QtWidgets.QMessageBox.StandardButton.Ok
)


# Get the default button that will be pressed if the user presses ENTER in the open message box
def _get_default_button_for_message_box_type(
message_box_type: MessageBoxType, *, is_cancellable: bool
) -> QtWidgets.QMessageBox.StandardButton:
if message_box_type == MessageBoxType.QUESTION:
return QtWidgets.QMessageBox.StandardButton.No if is_cancellable else QtWidgets.QMessageBox.StandardButton.Yes
return QtWidgets.QMessageBox.StandardButton.Cancel if is_cancellable else QtWidgets.QMessageBox.StandardButton.Ok


def _check_whether_message_ok_was_clicked(
message_box_type: MessageBoxType,
clicked_message_box_button: QtWidgets.QMessageBox.StandardButton | None,
) -> bool:
# Pressing the ESC key in a QMessageBox can return None is no escape button can be determined or was configured (see https://doc.qt.io/qt-6/qmessagebox.html#default-and-escape-keys)
if message_box_type == MessageBoxType.QUESTION:
return (
clicked_message_box_button is not None
and clicked_message_box_button == QtWidgets.QMessageBox.StandardButton.Yes
)
return (
clicked_message_box_button is not None and clicked_message_box_button == QtWidgets.QMessageBox.StandardButton.Ok
)
Loading
Loading