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:
@@ -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([])
|
||||
|
||||
167
bec_widgets/widgets/editors/monaco/scan_control_dialog.py
Normal file
167
bec_widgets/widgets/editors/monaco/scan_control_dialog.py
Normal 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_())
|
||||
Reference in New Issue
Block a user