bec-widgets 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CHANGELOG.md +26 -24
- PKG-INFO +1 -1
- bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui +60 -84
- bec_widgets/cli/client.py +56 -0
- bec_widgets/tests/__init__.py +0 -0
- bec_widgets/tests/utils.py +226 -0
- bec_widgets/utils/filter_io.py +156 -0
- bec_widgets/utils/widget_io.py +12 -9
- bec_widgets/widgets/base_classes/device_input_base.py +331 -62
- bec_widgets/widgets/base_classes/device_signal_input_base.py +280 -0
- bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py +1 -1
- bec_widgets/widgets/device_combobox/device_combo_box_plugin.py +1 -1
- bec_widgets/widgets/device_combobox/device_combobox.py +118 -41
- bec_widgets/widgets/device_line_edit/device_line_edit.py +122 -59
- bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py +1 -1
- bec_widgets/widgets/image/image_widget.py +7 -1
- bec_widgets/widgets/motor_map/motor_map_widget.py +4 -2
- bec_widgets/widgets/positioner_box/positioner_box.py +4 -1
- bec_widgets/widgets/scan_control/scan_control.py +2 -3
- bec_widgets/widgets/scan_control/scan_group_box.py +3 -1
- bec_widgets/widgets/signal_combobox/__init__.py +0 -0
- bec_widgets/widgets/signal_combobox/register_signal_combobox.py +15 -0
- bec_widgets/widgets/signal_combobox/signal_combobox.py +115 -0
- bec_widgets/widgets/signal_combobox/signal_combobox.pyproject +1 -0
- bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py +54 -0
- bec_widgets/widgets/signal_line_edit/__init__.py +0 -0
- bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py +15 -0
- bec_widgets/widgets/signal_line_edit/signal_line_edit.py +140 -0
- bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject +1 -0
- bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py +54 -0
- {bec_widgets-1.0.1.dist-info → bec_widgets-1.1.0.dist-info}/METADATA +1 -1
- {bec_widgets-1.0.1.dist-info → bec_widgets-1.1.0.dist-info}/RECORD +36 -22
- pyproject.toml +1 -1
- {bec_widgets-1.0.1.dist-info → bec_widgets-1.1.0.dist-info}/WHEEL +0 -0
- {bec_widgets-1.0.1.dist-info → bec_widgets-1.1.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-1.0.1.dist-info → bec_widgets-1.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,13 +1,18 @@
|
|
1
|
-
from
|
2
|
-
|
1
|
+
from bec_lib.callback_handler import EventType
|
2
|
+
from bec_lib.device import ReadoutPriority
|
3
|
+
from bec_lib.logger import bec_logger
|
3
4
|
from qtpy.QtCore import QSize, Signal, Slot
|
4
|
-
from qtpy.
|
5
|
+
from qtpy.QtGui import QPainter, QPaintEvent, QPen
|
6
|
+
from qtpy.QtWidgets import QApplication, QCompleter, QLineEdit, QSizePolicy
|
5
7
|
|
6
|
-
from bec_widgets.utils.
|
7
|
-
from bec_widgets.widgets.base_classes.device_input_base import
|
8
|
+
from bec_widgets.utils.colors import get_accent_colors
|
9
|
+
from bec_widgets.widgets.base_classes.device_input_base import (
|
10
|
+
BECDeviceFilter,
|
11
|
+
DeviceInputBase,
|
12
|
+
DeviceInputConfig,
|
13
|
+
)
|
8
14
|
|
9
|
-
|
10
|
-
from bec_widgets.widgets.base_classes.device_input_base import DeviceInputConfig
|
15
|
+
logger = bec_logger.logger
|
11
16
|
|
12
17
|
|
13
18
|
class DeviceLineEdit(DeviceInputBase, QLineEdit):
|
@@ -19,12 +24,13 @@ class DeviceLineEdit(DeviceInputBase, QLineEdit):
|
|
19
24
|
client: BEC client object.
|
20
25
|
config: Device input configuration.
|
21
26
|
gui_id: GUI ID.
|
22
|
-
device_filter: Device filter, name of the device class.
|
27
|
+
device_filter: Device filter, name of the device class from BECDeviceFilter and ReadoutPriority. Check DeviceInputBase for more details.
|
23
28
|
default: Default device name.
|
24
29
|
arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names.
|
25
30
|
"""
|
26
31
|
|
27
32
|
device_selected = Signal(str)
|
33
|
+
device_config_update = Signal()
|
28
34
|
|
29
35
|
ICON_NAME = "edit_note"
|
30
36
|
|
@@ -34,80 +40,137 @@ class DeviceLineEdit(DeviceInputBase, QLineEdit):
|
|
34
40
|
client=None,
|
35
41
|
config: DeviceInputConfig = None,
|
36
42
|
gui_id: str | None = None,
|
37
|
-
device_filter:
|
43
|
+
device_filter: BECDeviceFilter | list[BECDeviceFilter] | None = None,
|
44
|
+
readout_priority_filter: (
|
45
|
+
str | ReadoutPriority | list[str] | list[ReadoutPriority] | None
|
46
|
+
) = None,
|
47
|
+
available_devices: list[str] | None = None,
|
38
48
|
default: str | None = None,
|
39
49
|
arg_name: str | None = None,
|
40
50
|
):
|
51
|
+
self._callback_id = None
|
52
|
+
self._is_valid_input = False
|
53
|
+
self._accent_colors = get_accent_colors()
|
41
54
|
super().__init__(client=client, config=config, gui_id=gui_id)
|
42
55
|
QLineEdit.__init__(self, parent=parent)
|
43
|
-
|
44
56
|
self.completer = QCompleter(self)
|
45
57
|
self.setCompleter(self.completer)
|
46
|
-
self.populate_completer()
|
47
58
|
|
48
59
|
if arg_name is not None:
|
49
60
|
self.config.arg_name = arg_name
|
50
61
|
self.arg_name = arg_name
|
51
|
-
if device_filter is not None:
|
52
|
-
self.set_device_filter(device_filter)
|
53
|
-
if default is not None:
|
54
|
-
self.set_default_device(default)
|
55
|
-
|
56
62
|
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
|
57
63
|
self.setMinimumSize(QSize(100, 0))
|
58
64
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
self.
|
70
|
-
|
71
|
-
|
65
|
+
# We do not consider the config that is passed here, this produced problems
|
66
|
+
# with QtDesigner, since config and input arguments may differ and resolve properly
|
67
|
+
# Implementing this logic and config recoverage is postponed.
|
68
|
+
# Set available devices if passed
|
69
|
+
if available_devices is not None:
|
70
|
+
self.set_available_devices(available_devices)
|
71
|
+
# Set readout priority filter default is all
|
72
|
+
if readout_priority_filter is not None:
|
73
|
+
self.set_readout_priority_filter(readout_priority_filter)
|
74
|
+
else:
|
75
|
+
self.set_readout_priority_filter(
|
76
|
+
[
|
77
|
+
ReadoutPriority.MONITORED,
|
78
|
+
ReadoutPriority.BASELINE,
|
79
|
+
ReadoutPriority.ASYNC,
|
80
|
+
ReadoutPriority.CONTINUOUS,
|
81
|
+
ReadoutPriority.ON_REQUEST,
|
82
|
+
]
|
83
|
+
)
|
84
|
+
# Device filter default is None
|
85
|
+
if device_filter is not None:
|
86
|
+
self.set_device_filter(device_filter)
|
87
|
+
# Set default device if passed
|
88
|
+
if default is not None:
|
89
|
+
self.set_device(default)
|
90
|
+
self._callback_id = self.bec_dispatcher.client.callbacks.register(
|
91
|
+
EventType.DEVICE_UPDATE, self.on_device_update
|
92
|
+
)
|
93
|
+
self.device_config_update.connect(self.update_devices_from_filters)
|
94
|
+
self.textChanged.connect(self.check_validity)
|
95
|
+
self.check_validity(self.text())
|
96
|
+
|
97
|
+
def on_device_update(self, action: str, content: dict) -> None:
|
72
98
|
"""
|
73
|
-
|
99
|
+
Callback for device update events. Triggers the device_update signal.
|
74
100
|
|
75
101
|
Args:
|
76
|
-
|
102
|
+
action (str): The action that triggered the event.
|
103
|
+
content (dict): The content of the config update.
|
77
104
|
"""
|
78
|
-
|
79
|
-
|
105
|
+
if action in ["add", "remove", "reload"]:
|
106
|
+
self.device_config_update.emit()
|
80
107
|
|
81
|
-
def
|
82
|
-
"""
|
83
|
-
|
108
|
+
def cleanup(self):
|
109
|
+
"""Cleanup the widget."""
|
110
|
+
if self._callback_id is not None:
|
111
|
+
self.bec_dispatcher.client.callbacks.remove(self._callback_id)
|
84
112
|
|
85
|
-
|
86
|
-
default_device (str): Default device name.
|
113
|
+
def get_current_device(self) -> object:
|
87
114
|
"""
|
88
|
-
|
89
|
-
self.setText(default_device)
|
90
|
-
|
91
|
-
def populate_completer(self):
|
92
|
-
"""Populate the completer with the devices."""
|
93
|
-
self.devices = self.get_device_list(self.config.device_filter)
|
94
|
-
self.completer.setModel(self.create_completer_model(self.devices))
|
115
|
+
Get the current device object based on the current value.
|
95
116
|
|
96
|
-
|
97
|
-
|
98
|
-
|
117
|
+
Returns:
|
118
|
+
object: Device object, can be device of type Device, Positioner, Signal or ComputedSignal.
|
119
|
+
"""
|
120
|
+
dev_name = self.text()
|
121
|
+
return self.get_device_object(dev_name)
|
99
122
|
|
100
|
-
|
123
|
+
def paintEvent(self, event: QPaintEvent) -> None:
|
124
|
+
"""Extend the paint event to set the border color based on the validity of the input.
|
101
125
|
|
102
|
-
|
126
|
+
Args:
|
127
|
+
event (PySide6.QtGui.QPaintEvent) : Paint event.
|
103
128
|
"""
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
129
|
+
# logger.info(f"Received paint event: {event} in {self.__class__}")
|
130
|
+
super().paintEvent(event)
|
131
|
+
|
132
|
+
if self._is_valid_input is False and self.isEnabled() is True:
|
133
|
+
painter = QPainter(self)
|
134
|
+
pen = QPen()
|
135
|
+
pen.setWidth(2)
|
136
|
+
pen.setColor(self._accent_colors.emergency)
|
137
|
+
painter.setPen(pen)
|
138
|
+
painter.drawRect(self.rect().adjusted(1, 1, -1, -1))
|
139
|
+
painter.end()
|
140
|
+
|
141
|
+
@Slot(str)
|
142
|
+
def check_validity(self, input_text: str) -> None:
|
143
|
+
"""
|
144
|
+
Check if the current value is a valid device name.
|
108
145
|
"""
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
146
|
+
if self.validate_device(input_text) is True:
|
147
|
+
self._is_valid_input = True
|
148
|
+
self.device_selected.emit(input_text.lower())
|
149
|
+
else:
|
150
|
+
self._is_valid_input = False
|
151
|
+
self.update()
|
152
|
+
|
153
|
+
|
154
|
+
if __name__ == "__main__": # pragma: no cover
|
155
|
+
# pylint: disable=import-outside-toplevel
|
156
|
+
from qtpy.QtWidgets import QVBoxLayout, QWidget
|
157
|
+
|
158
|
+
from bec_widgets.utils.colors import set_theme
|
159
|
+
from bec_widgets.widgets.signal_combobox.signal_combobox import SignalComboBox
|
160
|
+
|
161
|
+
app = QApplication([])
|
162
|
+
set_theme("dark")
|
163
|
+
widget = QWidget()
|
164
|
+
widget.setFixedSize(200, 200)
|
165
|
+
layout = QVBoxLayout()
|
166
|
+
widget.setLayout(layout)
|
167
|
+
line_edit = DeviceLineEdit()
|
168
|
+
line_edit.filter_to_positioner = True
|
169
|
+
signal_line_edit = SignalComboBox()
|
170
|
+
line_edit.textChanged.connect(signal_line_edit.set_device)
|
171
|
+
line_edit.set_available_devices(["samx", "samy", "samz"])
|
172
|
+
line_edit.set_device("samx")
|
173
|
+
layout.addWidget(line_edit)
|
174
|
+
layout.addWidget(signal_line_edit)
|
175
|
+
widget.show()
|
176
|
+
app.exec_()
|
@@ -4,6 +4,7 @@ import sys
|
|
4
4
|
from typing import Literal, Optional
|
5
5
|
|
6
6
|
import pyqtgraph as pg
|
7
|
+
from bec_lib.device import ReadoutPriority
|
7
8
|
from qtpy.QtWidgets import QComboBox, QVBoxLayout, QWidget
|
8
9
|
|
9
10
|
from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility
|
@@ -16,6 +17,7 @@ from bec_widgets.qt_utils.toolbar import (
|
|
16
17
|
WidgetAction,
|
17
18
|
)
|
18
19
|
from bec_widgets.utils.bec_widget import BECWidget
|
20
|
+
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
19
21
|
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
|
20
22
|
from bec_widgets.widgets.figure import BECFigure
|
21
23
|
from bec_widgets.widgets.figure.plots.axis_settings import AxisSettings
|
@@ -69,7 +71,11 @@ class BECImageWidget(BECWidget, QWidget):
|
|
69
71
|
self.toolbar = ModularToolBar(
|
70
72
|
actions={
|
71
73
|
"monitor": DeviceSelectionAction(
|
72
|
-
"Monitor:",
|
74
|
+
"Monitor:",
|
75
|
+
DeviceComboBox(
|
76
|
+
device_filter=BECDeviceFilter.DEVICE,
|
77
|
+
readout_priority_filter=[ReadoutPriority.ASYNC],
|
78
|
+
),
|
73
79
|
),
|
74
80
|
"monitor_type": WidgetAction(widget=self.dim_combo_box),
|
75
81
|
"connect": MaterialIconAction(icon_name="link", tooltip="Connect Device"),
|
@@ -2,11 +2,13 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import sys
|
4
4
|
|
5
|
+
from bec_lib.device import ReadoutPriority
|
5
6
|
from qtpy.QtWidgets import QVBoxLayout, QWidget
|
6
7
|
|
7
8
|
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
|
8
9
|
from bec_widgets.qt_utils.toolbar import DeviceSelectionAction, MaterialIconAction, ModularToolBar
|
9
10
|
from bec_widgets.utils.bec_widget import BECWidget
|
11
|
+
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
10
12
|
from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
|
11
13
|
from bec_widgets.widgets.figure import BECFigure
|
12
14
|
from bec_widgets.widgets.figure.plots.motor_map.motor_map import MotorMapConfig
|
@@ -50,10 +52,10 @@ class BECMotorMapWidget(BECWidget, QWidget):
|
|
50
52
|
self.toolbar = ModularToolBar(
|
51
53
|
actions={
|
52
54
|
"motor_x": DeviceSelectionAction(
|
53
|
-
"Motor X:", DeviceComboBox(device_filter=
|
55
|
+
"Motor X:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER])
|
54
56
|
),
|
55
57
|
"motor_y": DeviceSelectionAction(
|
56
|
-
"Motor Y:", DeviceComboBox(device_filter=
|
58
|
+
"Motor Y:", DeviceComboBox(device_filter=[BECDeviceFilter.POSITIONER])
|
57
59
|
),
|
58
60
|
"connect": MaterialIconAction(icon_name="link", tooltip="Connect Motors"),
|
59
61
|
"history": MaterialIconAction(icon_name="history", tooltip="Reset Trace History"),
|
@@ -18,6 +18,7 @@ from bec_widgets.qt_utils.compact_popup import CompactPopupWidget
|
|
18
18
|
from bec_widgets.utils import UILoader
|
19
19
|
from bec_widgets.utils.bec_widget import BECWidget
|
20
20
|
from bec_widgets.utils.colors import get_accent_colors, set_theme
|
21
|
+
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
21
22
|
from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
|
22
23
|
|
23
24
|
logger = bec_logger.logger
|
@@ -97,7 +98,9 @@ class PositionerBox(BECWidget, CompactPopupWidget):
|
|
97
98
|
self._dialog = QDialog(self)
|
98
99
|
self._dialog.setWindowTitle("Positioner Selection")
|
99
100
|
layout = QVBoxLayout()
|
100
|
-
line_edit = DeviceLineEdit(
|
101
|
+
line_edit = DeviceLineEdit(
|
102
|
+
self, client=self.client, device_filter=[BECDeviceFilter.POSITIONER]
|
103
|
+
)
|
101
104
|
line_edit.textChanged.connect(self.set_positioner)
|
102
105
|
layout.addWidget(line_edit)
|
103
106
|
close_button = QPushButton("Close")
|
@@ -45,7 +45,7 @@ class ScanControl(BECWidget, QWidget):
|
|
45
45
|
scan_started = Signal()
|
46
46
|
scan_selected = Signal(str)
|
47
47
|
device_selected = Signal(str)
|
48
|
-
|
48
|
+
scan_args = Signal(list)
|
49
49
|
|
50
50
|
def __init__(
|
51
51
|
self,
|
@@ -457,8 +457,7 @@ class ScanControl(BECWidget, QWidget):
|
|
457
457
|
def run_scan(self):
|
458
458
|
"""Starts the selected scan with the given parameters."""
|
459
459
|
args, kwargs = self.get_scan_parameters()
|
460
|
-
|
461
|
-
self.scan_axis.emit(device.name, start, stop)
|
460
|
+
self.scan_args.emit(args)
|
462
461
|
scan_function = getattr(self.scans, self.comboBox_scan_selection.currentText())
|
463
462
|
if callable(scan_function):
|
464
463
|
self.scan_started.emit()
|
@@ -21,6 +21,7 @@ from qtpy.QtWidgets import (
|
|
21
21
|
)
|
22
22
|
|
23
23
|
from bec_widgets.utils.widget_io import WidgetIO
|
24
|
+
from bec_widgets.widgets.base_classes.device_input_base import BECDeviceFilter
|
24
25
|
from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
|
25
26
|
|
26
27
|
logger = bec_logger.logger
|
@@ -233,6 +234,7 @@ class ScanGroupBox(QGroupBox):
|
|
233
234
|
default = None
|
234
235
|
widget = widget_class(arg_name=arg_name, default=default)
|
235
236
|
if isinstance(widget, DeviceLineEdit):
|
237
|
+
widget.set_device_filter(BECDeviceFilter.DEVICE)
|
236
238
|
self.selected_devices[widget] = ""
|
237
239
|
widget.device_selected.connect(self.emit_device_selected)
|
238
240
|
tooltip = item.get("tooltip", None)
|
@@ -306,7 +308,7 @@ class ScanGroupBox(QGroupBox):
|
|
306
308
|
try: # In case that the bundle size changes
|
307
309
|
widget = self.layout.itemAtPosition(i, j).widget()
|
308
310
|
if isinstance(widget, DeviceLineEdit) and device_object:
|
309
|
-
value = widget.
|
311
|
+
value = widget.get_current_device()
|
310
312
|
else:
|
311
313
|
value = WidgetIO.get_value(widget)
|
312
314
|
args.append(value)
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
def main(): # pragma: no cover
|
2
|
+
from qtpy import PYSIDE6
|
3
|
+
|
4
|
+
if not PYSIDE6:
|
5
|
+
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
6
|
+
return
|
7
|
+
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
8
|
+
|
9
|
+
from bec_widgets.widgets.signal_combobox.signal_combobox_plugin import SignalComboBoxPlugin
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget(SignalComboBoxPlugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|
@@ -0,0 +1,115 @@
|
|
1
|
+
from bec_lib.device import Positioner
|
2
|
+
from ophyd import Kind
|
3
|
+
from qtpy.QtCore import QSize, Signal, Slot
|
4
|
+
from qtpy.QtWidgets import QComboBox, QSizePolicy
|
5
|
+
|
6
|
+
from bec_widgets.utils.filter_io import ComboBoxFilterHandler, FilterIO
|
7
|
+
from bec_widgets.widgets.base_classes.device_signal_input_base import DeviceSignalInputBase
|
8
|
+
|
9
|
+
|
10
|
+
class SignalComboBox(DeviceSignalInputBase, QComboBox):
|
11
|
+
"""
|
12
|
+
Line edit widget for device input with autocomplete for device names.
|
13
|
+
|
14
|
+
Args:
|
15
|
+
parent: Parent widget.
|
16
|
+
client: BEC client object.
|
17
|
+
config: Device input configuration.
|
18
|
+
gui_id: GUI ID.
|
19
|
+
device_filter: Device filter, name of the device class from BECDeviceFilter and BECReadoutPriority. Check DeviceInputBase for more details.
|
20
|
+
default: Default device name.
|
21
|
+
arg_name: Argument name, can be used for the other widgets which has to call some other function in bec using correct argument names.
|
22
|
+
"""
|
23
|
+
|
24
|
+
ICON_NAME = "list_alt"
|
25
|
+
|
26
|
+
device_signal_changed = Signal(str)
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
parent=None,
|
31
|
+
client=None,
|
32
|
+
config: DeviceSignalInputBase = None,
|
33
|
+
gui_id: str | None = None,
|
34
|
+
device: str | None = None,
|
35
|
+
signal_filter: str | list[str] | None = None,
|
36
|
+
default: str | None = None,
|
37
|
+
arg_name: str | None = None,
|
38
|
+
):
|
39
|
+
super().__init__(client=client, config=config, gui_id=gui_id)
|
40
|
+
QComboBox.__init__(self, parent=parent)
|
41
|
+
if arg_name is not None:
|
42
|
+
self.config.arg_name = arg_name
|
43
|
+
self.arg_name = arg_name
|
44
|
+
if default is not None:
|
45
|
+
self.set_device(default)
|
46
|
+
|
47
|
+
self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
|
48
|
+
self.setMinimumSize(QSize(100, 0))
|
49
|
+
# We do not consider the config that is passed here, this produced problems
|
50
|
+
# with QtDesigner, since config and input arguments may differ and resolve properly
|
51
|
+
# Implementing this logic and config recoverage is postponed.
|
52
|
+
self.currentTextChanged.connect(self.on_text_changed)
|
53
|
+
if signal_filter is not None:
|
54
|
+
self.set_filter(signal_filter)
|
55
|
+
else:
|
56
|
+
self.set_filter([Kind.hinted, Kind.normal, Kind.config])
|
57
|
+
if device is not None:
|
58
|
+
self.set_device(device)
|
59
|
+
if default is not None:
|
60
|
+
self.set_signal(default)
|
61
|
+
|
62
|
+
def update_signals_from_filters(self):
|
63
|
+
"""Update the filters for the combobox"""
|
64
|
+
super().update_signals_from_filters()
|
65
|
+
# pylint: disable=protected-access
|
66
|
+
if FilterIO._find_handler(self) is ComboBoxFilterHandler:
|
67
|
+
if len(self._config_signals) > 0:
|
68
|
+
self.insertItem(
|
69
|
+
len(self._hinted_signals) + len(self._normal_signals), "Config Signals"
|
70
|
+
)
|
71
|
+
self.model().item(len(self._hinted_signals) + len(self._normal_signals)).setEnabled(
|
72
|
+
False
|
73
|
+
)
|
74
|
+
if len(self._normal_signals) > 0:
|
75
|
+
self.insertItem(len(self._hinted_signals), "Normal Signals")
|
76
|
+
self.model().item(len(self._hinted_signals)).setEnabled(False)
|
77
|
+
if len(self._hinted_signals) > 0:
|
78
|
+
self.insertItem(0, "Hinted Signals")
|
79
|
+
self.model().item(0).setEnabled(False)
|
80
|
+
|
81
|
+
@Slot(str)
|
82
|
+
def on_text_changed(self, text: str):
|
83
|
+
"""Slot for text changed. If a device is selected and the signal is changed and valid it emits a signal.
|
84
|
+
For a positioner, the readback value has to be renamed to the device name.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
text (str): Text in the combobox.
|
88
|
+
"""
|
89
|
+
if self.validate_device(self.device) is False:
|
90
|
+
return
|
91
|
+
if self.validate_signal(text) is False:
|
92
|
+
return
|
93
|
+
if text == "readback" and isinstance(self.get_device_object(self.device), Positioner):
|
94
|
+
device_signal = self.device
|
95
|
+
else:
|
96
|
+
device_signal = f"{self.device}_{text}"
|
97
|
+
self.device_signal_changed.emit(device_signal)
|
98
|
+
|
99
|
+
|
100
|
+
if __name__ == "__main__": # pragma: no cover
|
101
|
+
# pylint: disable=import-outside-toplevel
|
102
|
+
from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
|
103
|
+
|
104
|
+
from bec_widgets.utils.colors import set_theme
|
105
|
+
|
106
|
+
app = QApplication([])
|
107
|
+
set_theme("dark")
|
108
|
+
widget = QWidget()
|
109
|
+
widget.setFixedSize(200, 200)
|
110
|
+
layout = QVBoxLayout()
|
111
|
+
widget.setLayout(layout)
|
112
|
+
box = SignalComboBox(device="samx")
|
113
|
+
layout.addWidget(box)
|
114
|
+
widget.show()
|
115
|
+
app.exec_()
|
@@ -0,0 +1 @@
|
|
1
|
+
{'files': ['signal_combobox.py']}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (C) 2022 The Qt Company Ltd.
|
2
|
+
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
3
|
+
|
4
|
+
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
5
|
+
|
6
|
+
from bec_widgets.utils.bec_designer import designer_material_icon
|
7
|
+
from bec_widgets.widgets.signal_combobox.signal_combobox import SignalComboBox
|
8
|
+
|
9
|
+
DOM_XML = """
|
10
|
+
<ui language='c++'>
|
11
|
+
<widget class='SignalComboBox' name='signal_combobox'>
|
12
|
+
</widget>
|
13
|
+
</ui>
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
class SignalComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
18
|
+
def __init__(self):
|
19
|
+
super().__init__()
|
20
|
+
self._form_editor = None
|
21
|
+
|
22
|
+
def createWidget(self, parent):
|
23
|
+
t = SignalComboBox(parent)
|
24
|
+
return t
|
25
|
+
|
26
|
+
def domXml(self):
|
27
|
+
return DOM_XML
|
28
|
+
|
29
|
+
def group(self):
|
30
|
+
return "BEC Input Widgets"
|
31
|
+
|
32
|
+
def icon(self):
|
33
|
+
return designer_material_icon(SignalComboBox.ICON_NAME)
|
34
|
+
|
35
|
+
def includeFile(self):
|
36
|
+
return "signal_combobox"
|
37
|
+
|
38
|
+
def initialize(self, form_editor):
|
39
|
+
self._form_editor = form_editor
|
40
|
+
|
41
|
+
def isContainer(self):
|
42
|
+
return False
|
43
|
+
|
44
|
+
def isInitialized(self):
|
45
|
+
return self._form_editor is not None
|
46
|
+
|
47
|
+
def name(self):
|
48
|
+
return "SignalComboBox"
|
49
|
+
|
50
|
+
def toolTip(self):
|
51
|
+
return ""
|
52
|
+
|
53
|
+
def whatsThis(self):
|
54
|
+
return self.toolTip()
|
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
def main(): # pragma: no cover
|
2
|
+
from qtpy import PYSIDE6
|
3
|
+
|
4
|
+
if not PYSIDE6:
|
5
|
+
print("PYSIDE6 is not available in the environment. Cannot patch designer.")
|
6
|
+
return
|
7
|
+
from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
|
8
|
+
|
9
|
+
from bec_widgets.widgets.signal_line_edit.signal_line_edit_plugin import SignalLineEditPlugin
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget(SignalLineEditPlugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|