1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-03-06 08:52:53 +01:00

wip - scan control dialog

This commit is contained in:
2025-09-15 11:44:38 +02:00
committed by Klaus Wakonig
parent f2b422014f
commit 4623b5dc2e
2 changed files with 202 additions and 3 deletions

View File

@@ -6,8 +6,8 @@ import black
import isort
import qtmonaco
from bec_lib.logger import bec_logger
from qtpy.QtCore import Signal
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
from PySide6.QtCore import Signal
from qtpy.QtWidgets import QApplication, QDialog, QVBoxLayout, QWidget
from bec_widgets.utils.bec_widget import BECWidget
from bec_widgets.utils.colors import get_theme_name
@@ -59,6 +59,8 @@ class MonacoWidget(BECWidget, QWidget):
self.editor.text_changed.connect(self.text_changed.emit)
self.editor.text_changed.connect(self._check_save_status)
self.editor.initialized.connect(self.apply_theme)
self.editor.initialized.connect(self._setup_context_menu)
self.editor.context_menu_action_triggered.connect(self._handle_context_menu_action)
self._current_file = None
self._original_content = ""
@@ -109,7 +111,7 @@ class MonacoWidget(BECWidget, QWidget):
content = self.get_text()
try:
formatted_content = black.format_str(content, mode=black.Mode(line_length=100))
except black.NothingChanged:
except Exception: # black.NothingChanged or other formatting exceptions
formatted_content = content
config = isort.Config(
@@ -288,6 +290,36 @@ class MonacoWidget(BECWidget, QWidget):
"""
return self.editor.get_lsp_header()
def _setup_context_menu(self):
"""Setup custom context menu actions for the Monaco editor."""
# Add the "Insert Scan" action to the context menu
self.editor.add_action("insert_scan", "Insert Scan", "python")
# Add the "Format Code" action to the context menu
self.editor.add_action("format_code", "Format Code", "python")
def _handle_context_menu_action(self, action_id: str):
"""Handle context menu action triggers."""
if action_id == "insert_scan":
self._show_scan_control_dialog()
elif action_id == "format_code":
self._format_code()
def _show_scan_control_dialog(self):
"""Show the scan control dialog and insert the generated scan code."""
# Import here to avoid circular imports
from bec_widgets.widgets.editors.monaco.scan_control_dialog import ScanControlDialog
dialog = ScanControlDialog(self, client=self.client)
if dialog.exec_() == QDialog.DialogCode.Accepted:
scan_code = dialog.get_scan_code()
if scan_code:
# Insert the scan code at the current cursor position
self.insert_text(scan_code)
def _format_code(self):
"""Format the current code in the editor."""
self.format()
if __name__ == "__main__": # pragma: no cover
qapp = QApplication([])

View File

@@ -0,0 +1,167 @@
"""
Scan Control Dialog for Monaco Editor
This module provides a dialog wrapper around the ScanControl widget,
allowing users to configure and generate scan code that can be inserted
into the Monaco editor.
"""
from bec_lib.device import Device
from PySide6.QtCore import QSize
from qtpy.QtCore import Qt
from qtpy.QtWidgets import QDialog, QDialogButtonBox, QPushButton, QVBoxLayout
from bec_widgets.widgets.control.scan_control import ScanControl
class ScanControlDialog(QDialog):
"""
Dialog window containing the ScanControl widget for generating scan code.
This dialog allows users to configure scan parameters and generates
Python code that can be inserted into the Monaco editor.
"""
def __init__(self, parent=None, client=None):
super().__init__(parent)
self.setWindowTitle("Insert Scan")
# Store the client for passing to ScanControl
self.client = client
self._scan_code = ""
self._setup_ui()
def sizeHint(self) -> QSize:
return QSize(600, 800)
def _setup_ui(self):
"""Setup the dialog UI with ScanControl widget and buttons."""
layout = QVBoxLayout(self)
# Create the scan control widget
self.scan_control = ScanControl(parent=self, client=self.client)
self.scan_control.show_scan_control_buttons(False)
layout.addWidget(self.scan_control)
# Create dialog buttons
button_box = QDialogButtonBox(Qt.Orientation.Horizontal, self)
# Create custom buttons with appropriate text
insert_button = QPushButton("Insert")
cancel_button = QPushButton("Cancel")
button_box.addButton(insert_button, QDialogButtonBox.ButtonRole.AcceptRole)
button_box.addButton(cancel_button, QDialogButtonBox.ButtonRole.RejectRole)
layout.addWidget(button_box)
# Connect button signals
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
def _generate_scan_code(self):
"""Generate Python code for the configured scan."""
try:
# Get scan parameters from the scan control widget
args, kwargs = self.scan_control.get_scan_parameters()
scan_name = self.scan_control.current_scan
if not scan_name:
self._scan_code = ""
return
# Process arguments and add device prefix where needed
processed_args = self._process_arguments_for_code_generation(args)
processed_kwargs = self._process_kwargs_for_code_generation(kwargs)
# Generate the Python code string
code_parts = []
# Add scan function call
if processed_args and processed_kwargs:
# Format arguments
args_str = ", ".join(processed_args)
# Format keyword arguments
kwargs_str = ", ".join(
f"{k}={v}" for k, v in processed_kwargs.items() if k != "metadata"
)
if args_str and kwargs_str:
code_parts.append(f"scans.{scan_name}({args_str}, {kwargs_str})")
elif args_str:
code_parts.append(f"scans.{scan_name}({args_str})")
elif kwargs_str:
code_parts.append(f"scans.{scan_name}({kwargs_str})")
else:
code_parts.append(f"scans.{scan_name}()")
elif processed_args:
args_str = ", ".join(processed_args)
code_parts.append(f"scans.{scan_name}({args_str})")
elif processed_kwargs:
kwargs_str = ", ".join(
f"{k}={v}" for k, v in processed_kwargs.items() if k != "metadata"
)
if kwargs_str:
code_parts.append(f"scans.{scan_name}({kwargs_str})")
else:
code_parts.append(f"scans.{scan_name}()")
else:
code_parts.append(f"scans.{scan_name}()")
self._scan_code = "\n".join(code_parts)
except Exception as e:
print(f"Error generating scan code: {e}")
self._scan_code = f"# Error generating scan code: {e}\n"
def _process_arguments_for_code_generation(self, args):
"""Process arguments to add device prefixes and proper formatting."""
processed = []
for arg in args:
if isinstance(arg, Device):
processed.append(f"dev.{arg.name}")
else:
# Regular argument - format appropriately
processed.append(repr(arg))
return processed
def _process_kwargs_for_code_generation(self, kwargs):
"""Process keyword arguments to add device prefixes and proper formatting."""
processed = {}
for key, value in kwargs.items():
if isinstance(value, Device):
processed[key] = f"dev.{value.name}"
else:
processed[key] = repr(value)
return processed
def get_scan_code(self) -> str:
"""
Get the generated scan code.
Returns:
str: The Python code for the configured scan.
"""
return self._scan_code
def accept(self):
"""Override accept to generate code before closing."""
self._generate_scan_code()
super().accept()
if __name__ == "__main__": # pragma: no cover
import sys
from qtpy.QtWidgets import QApplication
app = QApplication(sys.argv)
dialog = ScanControlDialog()
dialog.show()
sys.exit(app.exec_())