mirror of
https://github.com/bec-project/bec_widgets.git
synced 2025-07-13 19:21:50 +02:00
fix(scan_control): adapted widget to scan BEC gui config
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import qdarktheme
|
||||
from bec_lib.endpoints import MessageEndpoints
|
||||
from qtpy.QtWidgets import (
|
||||
QApplication,
|
||||
@ -13,6 +14,7 @@ from qtpy.QtWidgets import (
|
||||
QLayout,
|
||||
QLineEdit,
|
||||
QPushButton,
|
||||
QSizePolicy,
|
||||
QSpinBox,
|
||||
QTableWidget,
|
||||
QTableWidgetItem,
|
||||
@ -20,8 +22,12 @@ from qtpy.QtWidgets import (
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from bec_widgets.utils.bec_dispatcher import BECDispatcher
|
||||
from bec_widgets.utils import BECConnector
|
||||
from bec_widgets.utils.widget_io import WidgetIO
|
||||
from bec_widgets.widgets import StopButton
|
||||
|
||||
# TODO GENERAL
|
||||
# - extract
|
||||
|
||||
|
||||
class ScanArgType:
|
||||
@ -30,24 +36,52 @@ class ScanArgType:
|
||||
INT = "int"
|
||||
BOOL = "bool"
|
||||
STR = "str"
|
||||
DEVICEBASE = "DeviceBase"
|
||||
LITERALS = "dict"
|
||||
|
||||
|
||||
class ScanControl(QWidget):
|
||||
class ArgLabel(QLabel):
|
||||
def __init__(self, text: str, parent=None, arg_name: str = None, *args, **kwargs):
|
||||
super().__init__(text, parent=parent, *args, **kwargs)
|
||||
self.arg_name = arg_name
|
||||
|
||||
|
||||
class DeviceLineEdit(BECConnector, QLineEdit):
|
||||
def __init__(self, parent=None, client=None, gui_id: str | None = None):
|
||||
super().__init__(client=client, gui_id=gui_id)
|
||||
QLineEdit.__init__(self, parent=parent)
|
||||
|
||||
self.get_bec_shortcuts()
|
||||
|
||||
def get_device(self):
|
||||
return getattr(self.dev, self.text().lower())
|
||||
|
||||
|
||||
class ScanControl(BECConnector, QWidget):
|
||||
WIDGET_HANDLER = {
|
||||
ScanArgType.DEVICE: QLineEdit,
|
||||
ScanArgType.DEVICE: DeviceLineEdit,
|
||||
ScanArgType.DEVICEBASE: DeviceLineEdit,
|
||||
ScanArgType.FLOAT: QDoubleSpinBox,
|
||||
ScanArgType.INT: QSpinBox,
|
||||
ScanArgType.BOOL: QCheckBox,
|
||||
ScanArgType.STR: QLineEdit,
|
||||
ScanArgType.LITERALS: QComboBox, # TODO figure out combobox logic
|
||||
}
|
||||
|
||||
def __init__(self, parent=None, client=None, allowed_scans=None):
|
||||
super().__init__(parent)
|
||||
def __init__(
|
||||
self, parent=None, client=None, gui_id: str | None = None, allowed_scans: list | None = None
|
||||
):
|
||||
super().__init__(client=client, gui_id=gui_id)
|
||||
QWidget.__init__(self, parent=parent)
|
||||
|
||||
# Client from BEC + shortcuts to device manager and scans
|
||||
self.client = BECDispatcher().client if client is None else client
|
||||
self.dev = self.client.device_manager.devices
|
||||
self.scans = self.client.scans
|
||||
self.get_bec_shortcuts()
|
||||
|
||||
# Main layout
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.arg_box = None
|
||||
self.kwarg_boxes = []
|
||||
self.expert_mode = False # TODO implement in the future versions
|
||||
|
||||
# Scan list - allowed scans for the GUI
|
||||
self.allowed_scans = allowed_scans
|
||||
@ -56,69 +90,55 @@ class ScanControl(QWidget):
|
||||
self._init_UI()
|
||||
|
||||
def _init_UI(self):
|
||||
self.verticalLayout = QVBoxLayout(self)
|
||||
"""
|
||||
Initializes the UI of the scan control widget. Create the top box for scan selection and populate scans to main combobox.
|
||||
"""
|
||||
|
||||
# Scan selection group box
|
||||
self.scan_selection_group = QGroupBox("Scan Selection", self)
|
||||
self.scan_selection_layout = QVBoxLayout(self.scan_selection_group)
|
||||
self.comboBox_scan_selection = QComboBox(self.scan_selection_group)
|
||||
self.button_run_scan = QPushButton("Run Scan", self.scan_selection_group)
|
||||
self.scan_selection_layout.addWidget(self.comboBox_scan_selection)
|
||||
self.scan_selection_layout.addWidget(self.button_run_scan)
|
||||
self.verticalLayout.addWidget(self.scan_selection_group)
|
||||
|
||||
# Scan control group box
|
||||
self.scan_control_group = QGroupBox("Scan Control", self)
|
||||
self.scan_control_layout = QVBoxLayout(self.scan_control_group)
|
||||
self.verticalLayout.addWidget(self.scan_control_group)
|
||||
|
||||
# Kwargs layout - just placeholder
|
||||
self.kwargs_layout = QGridLayout()
|
||||
self.scan_control_layout.addLayout(self.kwargs_layout)
|
||||
|
||||
# 1st Separator
|
||||
self.add_horizontal_separator(self.scan_control_layout)
|
||||
|
||||
# Buttons
|
||||
self.button_layout = QHBoxLayout()
|
||||
self.pushButton_add_bundle = QPushButton("Add Bundle", self.scan_control_group)
|
||||
self.pushButton_add_bundle.clicked.connect(self.add_bundle)
|
||||
self.pushButton_remove_bundle = QPushButton("Remove Bundle", self.scan_control_group)
|
||||
self.pushButton_remove_bundle.clicked.connect(self.remove_bundle)
|
||||
self.button_layout.addWidget(self.pushButton_add_bundle)
|
||||
self.button_layout.addWidget(self.pushButton_remove_bundle)
|
||||
self.scan_control_layout.addLayout(self.button_layout)
|
||||
|
||||
# 2nd Separator
|
||||
self.add_horizontal_separator(self.scan_control_layout)
|
||||
|
||||
# Initialize the QTableWidget for args
|
||||
self.args_table = QTableWidget()
|
||||
self.args_table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
|
||||
|
||||
self.scan_control_layout.addWidget(self.args_table)
|
||||
self.scan_selection_group = self.create_scan_selection_group()
|
||||
self.scan_selection_group.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
|
||||
self.layout.addWidget(self.scan_selection_group)
|
||||
|
||||
# Connect signals
|
||||
self.comboBox_scan_selection.currentIndexChanged.connect(self.on_scan_selected)
|
||||
self.button_run_scan.clicked.connect(self.run_scan)
|
||||
self.button_add_bundle.clicked.connect(self.add_arg_bundle)
|
||||
self.button_remove_bundle.clicked.connect(self.remove_arg_bundle)
|
||||
|
||||
# Initialize scan selection
|
||||
self.populate_scans()
|
||||
|
||||
def add_horizontal_separator(self, layout) -> None:
|
||||
def create_scan_selection_group(self) -> QGroupBox:
|
||||
"""
|
||||
Adds a horizontal separator to the given layout
|
||||
Creates the scan selection group box with combobox to select the scan and start/stop button.
|
||||
|
||||
Args:
|
||||
layout: Layout to add the separator to
|
||||
Returns:
|
||||
QGroupBox: Group box containing the scan selection widgets.
|
||||
"""
|
||||
separator = QFrame(self.scan_control_group)
|
||||
separator.setFrameShape(QFrame.HLine)
|
||||
separator.setFrameShadow(QFrame.Sunken)
|
||||
layout.addWidget(separator)
|
||||
|
||||
scan_selection_group = QGroupBox("Scan Selection", self)
|
||||
self.scan_selection_layout = QGridLayout(scan_selection_group)
|
||||
self.comboBox_scan_selection = QComboBox(scan_selection_group)
|
||||
# Run button
|
||||
self.button_run_scan = QPushButton("Start", scan_selection_group)
|
||||
self.button_run_scan.setStyleSheet("background-color: #559900; color: white")
|
||||
# Stop button
|
||||
self.button_stop_scan = StopButton(parent=scan_selection_group)
|
||||
# Add bundle button
|
||||
self.button_add_bundle = QPushButton("Add Bundle", scan_selection_group)
|
||||
# Remove bundle button
|
||||
self.button_remove_bundle = QPushButton("Remove Bundle", scan_selection_group)
|
||||
|
||||
self.scan_selection_layout.addWidget(self.comboBox_scan_selection, 0, 0, 1, 2)
|
||||
self.scan_selection_layout.addWidget(self.button_run_scan, 1, 0)
|
||||
self.scan_selection_layout.addWidget(self.button_stop_scan, 1, 1)
|
||||
self.scan_selection_layout.addWidget(self.button_add_bundle, 2, 0)
|
||||
self.scan_selection_layout.addWidget(self.button_remove_bundle, 2, 1)
|
||||
|
||||
return scan_selection_group
|
||||
|
||||
def populate_scans(self):
|
||||
"""Populates the scan selection combo box with available scans"""
|
||||
"""Populates the scan selection combo box with available scans from BEC session."""
|
||||
self.available_scans = self.client.connector.get(
|
||||
MessageEndpoints.available_scans()
|
||||
).resource
|
||||
@ -132,38 +152,141 @@ class ScanControl(QWidget):
|
||||
|
||||
else:
|
||||
allowed_scans = self.allowed_scans
|
||||
# TODO check parent class is ScanBase -> filter out the scans not relevant for GUI
|
||||
self.comboBox_scan_selection.addItems(allowed_scans)
|
||||
|
||||
def on_scan_selected(self):
|
||||
"""Callback for scan selection combo box"""
|
||||
self.reset_layout()
|
||||
selected_scan_name = self.comboBox_scan_selection.currentText()
|
||||
selected_scan_info = self.available_scans.get(selected_scan_name, {})
|
||||
|
||||
print(selected_scan_info) # TODO remove when widget will be more mature
|
||||
# Generate kwargs input
|
||||
self.generate_kwargs_input_fields(selected_scan_info)
|
||||
gui_config = selected_scan_info.get("gui_config", {})
|
||||
self.arg_group = gui_config.get("arg_group", None)
|
||||
self.kwarg_groups = gui_config.get("kwarg_groups", None)
|
||||
|
||||
# Args section
|
||||
self.generate_args_input_fields(selected_scan_info)
|
||||
if len(self.arg_group["arg_inputs"]) > 0:
|
||||
self.add_arg_group(self.arg_group)
|
||||
if len(self.kwarg_groups) > 0:
|
||||
self.add_kwargs_boxes(self.kwarg_groups)
|
||||
|
||||
def add_labels_to_layout(self, labels: list, grid_layout: QGridLayout) -> None:
|
||||
self.update()
|
||||
self.adjustSize()
|
||||
|
||||
def add_input_labels(self, group_inputs: dict, grid_layout: QGridLayout, row: int) -> None:
|
||||
"""
|
||||
Adds labels to the given grid layout as a separate row.
|
||||
Adds the given arg_group from arg_bundle to the scan control layout. The input labels are always added to the first row.
|
||||
|
||||
Args:
|
||||
labels (list): List of label names to add.
|
||||
grid_layout (QGridLayout): The grid layout to which labels will be added.
|
||||
group(dict): Dictionary containing the arg_group information.
|
||||
grid_layout(QGridLayout): The grid layout to which the arg_group will be added.
|
||||
"""
|
||||
row_index = grid_layout.rowCount() # Get the next available row
|
||||
for column_index, label_name in enumerate(labels):
|
||||
label = QLabel(label_name["name"].capitalize(), self.scan_control_group)
|
||||
# Add the label to the grid layout at the calculated row and current column
|
||||
grid_layout.addWidget(label, row_index, column_index)
|
||||
for column_index, item in enumerate(group_inputs):
|
||||
arg_name = item.get("name", None)
|
||||
display_name = item.get("display_name", arg_name)
|
||||
tooltip = item.get("tooltip", None)
|
||||
label = ArgLabel(text=display_name, arg_name=arg_name)
|
||||
if tooltip is not None:
|
||||
label.setToolTip(item["tooltip"])
|
||||
grid_layout.addWidget(label, row, column_index)
|
||||
|
||||
def add_input_widgets(self, group_inputs: dict, grid_layout: QGridLayout, row) -> None:
|
||||
for column_index, item in enumerate(group_inputs):
|
||||
widget = self.WIDGET_HANDLER.get(item["type"], None)
|
||||
if widget is None:
|
||||
print(f"Unsupported annotation '{item['type']}' for parameter '{item['name']}'")
|
||||
continue
|
||||
if isinstance(widget, (QSpinBox, QDoubleSpinBox)):
|
||||
widget.setRange(-9999, 9999)
|
||||
# if item["default"] != "_empty": # TODO fix for comboboxes and spinboxes
|
||||
# WidgetIO.set_value(widget, item["default"])
|
||||
# widget.setValue(item["default"])
|
||||
grid_layout.addWidget(widget(), row, column_index)
|
||||
|
||||
def add_input_box(self, group: dict, rows: int = 1):
|
||||
"""
|
||||
Adds the given gui_group to the scan control layout.
|
||||
|
||||
Args:
|
||||
group(dict): Dictionary containing the gui_group information.
|
||||
rows(int): Number of input rows to add to the layout.
|
||||
"""
|
||||
input_box = QGroupBox(group["name"])
|
||||
group_layout = QGridLayout(input_box)
|
||||
self.add_input_labels(group["inputs"], group_layout, 0)
|
||||
for i in range(rows):
|
||||
self.add_input_widgets(group["inputs"], group_layout, i + 1)
|
||||
input_box.setLayout(group_layout)
|
||||
self.layout.addWidget(input_box)
|
||||
input_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
|
||||
return input_box
|
||||
|
||||
def add_kwargs_boxes(self, groups: list):
|
||||
"""
|
||||
Adds the given gui_groups to the scan control layout.
|
||||
|
||||
Args:
|
||||
groups(list): List of dictionaries containing the gui_group information.
|
||||
"""
|
||||
for group in groups:
|
||||
box = self.add_input_box(group)
|
||||
self.layout.addWidget(box)
|
||||
self.kwarg_boxes.append(box)
|
||||
|
||||
def add_arg_group(self, group: dict):
|
||||
"""
|
||||
Adds the given gui_groups to the scan control layout.
|
||||
|
||||
Args:
|
||||
"""
|
||||
self.arg_box = self.add_input_box(group, rows=group["min"])
|
||||
self.real_arg_box_row_count = group["min"]
|
||||
self.layout.addWidget(self.arg_box)
|
||||
|
||||
def add_arg_bundle(self):
|
||||
if self.arg_box is not None:
|
||||
current_row_count = self.arg_box.layout().rowCount()
|
||||
if self.arg_group["max"] is not None and current_row_count >= self.arg_group["max"]:
|
||||
return
|
||||
self.add_input_widgets(
|
||||
self.arg_group["inputs"], self.arg_box.layout(), self.arg_box.layout().rowCount()
|
||||
)
|
||||
|
||||
self.real_arg_box_row_count += 1
|
||||
|
||||
print(f"row count REAL: {self.real_arg_box_row_count}")
|
||||
print(f"row count QT: {self.arg_box.layout().rowCount()}")
|
||||
|
||||
def remove_arg_bundle(self):
|
||||
if self.arg_box is not None:
|
||||
current_row_count = self.real_arg_box_row_count # self.arg_box.layout().rowCount()
|
||||
layout = self.arg_box.layout()
|
||||
if current_row_count > self.arg_group["min"]:
|
||||
for i in range(layout.columnCount()):
|
||||
widget = layout.itemAtPosition(current_row_count, i).widget()
|
||||
layout.removeWidget(widget)
|
||||
widget.deleteLater()
|
||||
self.real_arg_box_row_count -= 1
|
||||
print(f"row count REAL: {self.real_arg_box_row_count}")
|
||||
print(f"row count QT: {self.arg_box.layout().rowCount()}")
|
||||
# self.arg_box.layout().removeRow(current_row_count - 1)
|
||||
|
||||
def reset_layout(self):
|
||||
"""Clears the scan control layout from GuiGroups and ArgGroups boxes."""
|
||||
if self.arg_box is not None:
|
||||
self.layout.removeWidget(self.arg_box)
|
||||
self.arg_box = None
|
||||
if self.kwarg_boxes != []:
|
||||
self.remove_kwarg_boxes()
|
||||
|
||||
def remove_kwarg_boxes(self):
|
||||
for box in self.kwarg_boxes:
|
||||
self.layout.removeWidget(box)
|
||||
box.deleteLater()
|
||||
self.kwarg_boxes = []
|
||||
|
||||
def add_labels_to_table(
|
||||
self, labels: list, table: QTableWidget
|
||||
) -> None: # TODO could be moved to BECTable
|
||||
) -> None: # TODO could be moved to BECTable -> not needed
|
||||
"""
|
||||
Adds labels to the given table widget as a header row.
|
||||
|
||||
@ -174,7 +297,9 @@ class ScanControl(QWidget):
|
||||
table.setColumnCount(len(labels))
|
||||
table.setHorizontalHeaderLabels(labels)
|
||||
|
||||
def generate_args_input_fields(self, scan_info: dict) -> None:
|
||||
def generate_args_input_fields(
|
||||
self, scan_info: dict
|
||||
) -> None: # TODO decide how to deal with arg bundles
|
||||
"""
|
||||
Generates input fields for args.
|
||||
|
||||
@ -196,7 +321,9 @@ class ScanControl(QWidget):
|
||||
for i in range(self.arg_size_min):
|
||||
self.add_bundle()
|
||||
|
||||
def generate_kwargs_input_fields(self, scan_info: dict) -> None:
|
||||
def generate_kwargs_input_fields(
|
||||
self, scan_info: dict, inputs: dict = {}, hidden: list = []
|
||||
) -> None: # TODO can be removed
|
||||
"""
|
||||
Generates input fields for kwargs
|
||||
|
||||
@ -212,7 +339,11 @@ class ScanControl(QWidget):
|
||||
signature = scan_info.get("signature", [])
|
||||
|
||||
# Extract kwargs from the converted signature
|
||||
parameters = [param for param in signature if param["annotation"] != "_empty"]
|
||||
parameters = [
|
||||
param
|
||||
for param in signature
|
||||
if param["annotation"] != "_empty" and param["name"] not in hidden
|
||||
]
|
||||
|
||||
# Add labels
|
||||
self.add_labels_to_layout(parameters, self.kwargs_layout)
|
||||
@ -222,7 +353,25 @@ class ScanControl(QWidget):
|
||||
|
||||
self.add_widgets_row_to_layout(self.kwargs_layout, widgets)
|
||||
|
||||
def generate_widgets_from_signature(self, parameters: list) -> list:
|
||||
def create_widget_group(self, title: str, widgets: list) -> QGroupBox: # TODO to be removed
|
||||
"""
|
||||
Creates a group box containing the given widgets.
|
||||
|
||||
Args:
|
||||
title(str): Title of the group box.
|
||||
widgets(list): List of widgets to add to the group box.
|
||||
|
||||
Returns:
|
||||
QGroupBox: Group box containing the given widgets.
|
||||
"""
|
||||
group_box = QGroupBox(title)
|
||||
group_layout = QVBoxLayout(group_box)
|
||||
for widget in widgets:
|
||||
group_layout.addWidget(widget)
|
||||
group_box.setLayout(group_layout)
|
||||
return group_box
|
||||
|
||||
def generate_widgets_from_signature(self, parameters: list) -> list: # TODO to be removed
|
||||
"""
|
||||
Generates widgets from the given list of items.
|
||||
|
||||
@ -259,15 +408,17 @@ class ScanControl(QWidget):
|
||||
# set high default range for spin boxes #TODO can be linked to motor/device limits from BEC
|
||||
if isinstance(widget, (QSpinBox, QDoubleSpinBox)):
|
||||
widget.setRange(-9999, 9999)
|
||||
if item_default is not None:
|
||||
WidgetIO.set_value(widget, item_default)
|
||||
# if item_default is not None:
|
||||
# WidgetIO.set_value(widget, item_default)
|
||||
|
||||
# Add the widget to the list
|
||||
widgets.append(widget)
|
||||
|
||||
return widgets
|
||||
|
||||
def set_args_table_limits(self, table: QTableWidget, scan_info: dict) -> None:
|
||||
def set_args_table_limits(
|
||||
self, table: QTableWidget, scan_info: dict
|
||||
) -> None: # TODO can be removed
|
||||
# Get bundle info
|
||||
arg_bundle_size = scan_info.get("arg_bundle_size", {})
|
||||
self.arg_size_min = arg_bundle_size.get("min", 1)
|
||||
@ -278,7 +429,7 @@ class ScanControl(QWidget):
|
||||
|
||||
def add_widgets_row_to_layout(
|
||||
self, grid_layout: QGridLayout, widgets: list, row_index: int = None
|
||||
) -> None:
|
||||
) -> None: # TODO to be removed
|
||||
"""
|
||||
Adds a row of widgets to the given grid layout.
|
||||
|
||||
@ -297,7 +448,7 @@ class ScanControl(QWidget):
|
||||
|
||||
def add_widgets_row_to_table(
|
||||
self, table_widget: QTableWidget, widgets: list, row_index: int = None
|
||||
) -> None:
|
||||
) -> None: # TODO to be removed
|
||||
"""
|
||||
Adds a row of widgets to the given QTableWidget.
|
||||
|
||||
@ -329,7 +480,7 @@ class ScanControl(QWidget):
|
||||
max(widget.sizeHint().height() for widget in widgets if isinstance(widget, QWidget)),
|
||||
)
|
||||
|
||||
def remove_last_row_from_table(self, table_widget: QTableWidget) -> None:
|
||||
def remove_last_row_from_table(self, table_widget: QTableWidget) -> None: # TODO to be removed
|
||||
"""
|
||||
Removes the last row from the given QTableWidget until only one row is left.
|
||||
|
||||
@ -342,12 +493,12 @@ class ScanControl(QWidget):
|
||||
): # Check to ensure there is a minimum number of rows remaining
|
||||
table_widget.removeRow(row_count - 1)
|
||||
|
||||
def create_new_grid_layout(self):
|
||||
def create_new_grid_layout(self): # TODO to be removed
|
||||
new_layout = QGridLayout()
|
||||
# TODO maybe setup other layouts properties here?
|
||||
return new_layout
|
||||
|
||||
def clear_and_delete_layout(self, layout: QLayout):
|
||||
def clear_and_delete_layout(self, layout: QLayout): # TODO can be removed
|
||||
"""
|
||||
Clears and deletes the given layout and all its child widgets.
|
||||
|
||||
@ -366,7 +517,7 @@ class ScanControl(QWidget):
|
||||
self.clear_and_delete_layout(sub_layout)
|
||||
layout.deleteLater()
|
||||
|
||||
def add_bundle(self) -> None:
|
||||
def add_bundle(self) -> None: # TODO can be removed
|
||||
"""Adds a new bundle to the scan control layout"""
|
||||
# Get widgets used for particular scan and save them to be able to use for adding bundles
|
||||
args_widgets = self.generate_widgets_from_signature(
|
||||
@ -376,7 +527,7 @@ class ScanControl(QWidget):
|
||||
# Add first widgets row to the table
|
||||
self.add_widgets_row_to_table(self.args_table, args_widgets)
|
||||
|
||||
def remove_bundle(self) -> None:
|
||||
def remove_bundle(self) -> None: # TODO can be removed
|
||||
"""Removes the last bundle from the scan control layout"""
|
||||
self.remove_last_row_from_table(self.args_table)
|
||||
|
||||
@ -424,35 +575,65 @@ class ScanControl(QWidget):
|
||||
args.extend(row_args)
|
||||
return args
|
||||
|
||||
def extract_kwargs(self, box: QGroupBox) -> dict:
|
||||
"""
|
||||
Extracts the parameters from the given group box.
|
||||
|
||||
Args:
|
||||
box(QGroupBox): Group box from which to extract the parameters.
|
||||
|
||||
Returns:
|
||||
dict: Dictionary containing the extracted parameters.
|
||||
"""
|
||||
parameters = {}
|
||||
keys = [label.arg_name for label in box.findChildren(ArgLabel)]
|
||||
layout = box.layout()
|
||||
for i in range(layout.columnCount()):
|
||||
key = keys[i]
|
||||
widget = layout.itemAtPosition(1, i).widget()
|
||||
if isinstance(widget, DeviceLineEdit):
|
||||
value = widget.get_device()
|
||||
else:
|
||||
value = WidgetIO.get_value(widget)
|
||||
parameters[key] = value
|
||||
return parameters
|
||||
|
||||
def extract_args(self, box):
|
||||
args = []
|
||||
layout = box.layout()
|
||||
for i in range(layout.columnCount()):
|
||||
widget = layout.itemAtPosition(1, i).widget()
|
||||
if isinstance(widget, DeviceLineEdit):
|
||||
value = widget.get_device()
|
||||
else:
|
||||
value = WidgetIO.get_value(widget)
|
||||
args.append(value)
|
||||
return args
|
||||
|
||||
def run_scan(self):
|
||||
# Extract kwargs for the scan
|
||||
kwargs = {
|
||||
k.lower(): v
|
||||
for k, v in self.extract_kwargs_from_grid_row(self.kwargs_layout, 1).items()
|
||||
}
|
||||
|
||||
# Extract args from the table
|
||||
args = self.extract_args_from_table(self.args_table)
|
||||
|
||||
# Convert args to lowercase if they are strings
|
||||
args = [arg.lower() if isinstance(arg, str) else arg for arg in args]
|
||||
|
||||
# Execute the scan
|
||||
args = []
|
||||
kwargs = {}
|
||||
if self.arg_box is not None:
|
||||
args = self.extract_args(self.arg_box)
|
||||
for box in self.kwarg_boxes:
|
||||
box_kwargs = self.extract_kwargs(box)
|
||||
kwargs.update(box_kwargs)
|
||||
print(kwargs)
|
||||
scan_function = getattr(self.scans, self.comboBox_scan_selection.currentText())
|
||||
print(f"called with args: {args} and kwargs: {kwargs}")
|
||||
if callable(scan_function):
|
||||
scan_function(*args, **kwargs)
|
||||
|
||||
def close(self):
|
||||
super().close()
|
||||
|
||||
|
||||
# Application example
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
# BECclient global variables
|
||||
client = BECDispatcher().client
|
||||
client.start()
|
||||
|
||||
app = QApplication([])
|
||||
scan_control = ScanControl(client=client, allowed_scans=["line_scan", "grid_scan"])
|
||||
scan_control = ScanControl(allowed_scans=["fermat_scan", "round_scan", "line_scan"])
|
||||
|
||||
qdarktheme.setup_theme("auto")
|
||||
window = scan_control
|
||||
window.show()
|
||||
app.exec()
|
||||
|
Reference in New Issue
Block a user