bec-widgets 1.16.5__py3-none-any.whl → 1.17.1__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 +37 -0
- PKG-INFO +1 -1
- bec_widgets/cli/client.py +46 -0
- bec_widgets/utils/bec_signal_proxy.py +39 -11
- bec_widgets/widgets/containers/dock/dock_area.py +1 -1
- bec_widgets/widgets/control/device_control/positioner_box/__init__.py +11 -0
- bec_widgets/widgets/control/device_control/positioner_box/_base/__init__.py +3 -0
- bec_widgets/widgets/control/device_control/positioner_box/_base/positioner_box_base.py +243 -0
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box/__init__.py +0 -0
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py +242 -0
- bec_widgets/widgets/control/device_control/positioner_box/{positioner_box_plugin.py → positioner_box/positioner_box_plugin.py} +1 -1
- bec_widgets/widgets/control/device_control/positioner_box/{register_positioner_box.py → positioner_box/register_positioner_box.py} +1 -1
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/__init__.py +0 -0
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box2_d.pyproject +1 -0
- bec_widgets/widgets/control/{device_input/signal_combobox/signal_combo_box_plugin.py → device_control/positioner_box/positioner_box_2d/positioner_box2_d_plugin.py} +11 -9
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py +482 -0
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.ui +562 -0
- bec_widgets/widgets/control/{device_input/signal_combobox/register_signal_combo_box.py → device_control/positioner_box/positioner_box_2d/register_positioner_box2_d.py} +3 -3
- bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.py → positioner_control_line/positioner_control_line.py} +5 -2
- bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line_plugin.py → positioner_control_line/positioner_control_line_plugin.py} +1 -3
- bec_widgets/widgets/control/device_control/positioner_box/{register_positioner_control_line.py → positioner_control_line/register_positioner_control_line.py} +1 -1
- bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py +7 -6
- {bec_widgets-1.16.5.dist-info → bec_widgets-1.17.1.dist-info}/METADATA +1 -1
- {bec_widgets-1.16.5.dist-info → bec_widgets-1.17.1.dist-info}/RECORD +32 -26
- pyproject.toml +1 -1
- bec_widgets/widgets/control/device_control/positioner_box/positioner_box.py +0 -352
- bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box.pyproject +0 -1
- /bec_widgets/widgets/control/device_control/positioner_box/{positioner_box.pyproject → positioner_box/positioner_box.pyproject} +0 -0
- /bec_widgets/widgets/control/device_control/positioner_box/{positioner_box.ui → positioner_box/positioner_box.ui} +0 -0
- /bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.pyproject → positioner_control_line/positioner_control_line.pyproject} +0 -0
- /bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.ui → positioner_control_line/positioner_control_line.ui} +0 -0
- {bec_widgets-1.16.5.dist-info → bec_widgets-1.17.1.dist-info}/WHEEL +0 -0
- {bec_widgets-1.16.5.dist-info → bec_widgets-1.17.1.dist-info}/entry_points.txt +0 -0
- {bec_widgets-1.16.5.dist-info → bec_widgets-1.17.1.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -1,6 +1,43 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
3
|
|
4
|
+
## v1.17.1 (2025-01-26)
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
- **bec_signal_proxy**: Timeout for blocking implemented
|
9
|
+
([`6f2f2aa`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6f2f2aa06ae9b50f0451029caa1d8d83890a5b30))
|
10
|
+
|
11
|
+
|
12
|
+
## v1.17.0 (2025-01-23)
|
13
|
+
|
14
|
+
### Bug Fixes
|
15
|
+
|
16
|
+
- Focus policy and tab order for positioner_box_2d
|
17
|
+
([`6df5710`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6df57103bb57c97bedda570b07a31a3cc6e57d5d))
|
18
|
+
|
19
|
+
### Documentation
|
20
|
+
|
21
|
+
- Add documentation for 2D positioner box
|
22
|
+
([`9a8cc31`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9a8cc31f6c1fa5595f73c2a60372ef10d4c8eabb))
|
23
|
+
|
24
|
+
### Features
|
25
|
+
|
26
|
+
- **widget**: Add 2d positioner box widget
|
27
|
+
([`d2ffddb`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d2ffddb6d8d2473d8718f5aa650559902067ff12))
|
28
|
+
|
29
|
+
### Refactoring
|
30
|
+
|
31
|
+
- Move positioner_box and line into submodule
|
32
|
+
([`2419521`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2419521f5f05d8ff8ce975219629f77efb7fe6be))
|
33
|
+
|
34
|
+
PositionerBox and PositionerControlLine are now exported from from
|
35
|
+
bec_widgets.widgets.control.device_control.positioner_box, removing one level of hierarchy
|
36
|
+
|
37
|
+
- Move positioner_box logic to base class
|
38
|
+
([`3770db5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3770db51be68a5f3fa65e0a67a4ed3efd1c7d6fe))
|
39
|
+
|
40
|
+
|
4
41
|
## v1.16.5 (2025-01-22)
|
5
42
|
|
6
43
|
### Bug Fixes
|
PKG-INFO
CHANGED
bec_widgets/cli/client.py
CHANGED
@@ -34,6 +34,7 @@ class Widgets(str, enum.Enum):
|
|
34
34
|
Minesweeper = "Minesweeper"
|
35
35
|
PositionIndicator = "PositionIndicator"
|
36
36
|
PositionerBox = "PositionerBox"
|
37
|
+
PositionerBox2D = "PositionerBox2D"
|
37
38
|
PositionerControlLine = "PositionerControlLine"
|
38
39
|
ResetButton = "ResetButton"
|
39
40
|
ResumeButton = "ResumeButton"
|
@@ -3235,6 +3236,51 @@ class PositionerBox(RPCBase):
|
|
3235
3236
|
"""
|
3236
3237
|
|
3237
3238
|
|
3239
|
+
class PositionerBox2D(RPCBase):
|
3240
|
+
@rpc_call
|
3241
|
+
def set_positioner_hor(self, positioner: "str | Positioner"):
|
3242
|
+
"""
|
3243
|
+
Set the device
|
3244
|
+
|
3245
|
+
Args:
|
3246
|
+
positioner (Positioner | str) : Positioner to set, accepts str or the device
|
3247
|
+
"""
|
3248
|
+
|
3249
|
+
@rpc_call
|
3250
|
+
def set_positioner_ver(self, positioner: "str | Positioner"):
|
3251
|
+
"""
|
3252
|
+
Set the device
|
3253
|
+
|
3254
|
+
Args:
|
3255
|
+
positioner (Positioner | str) : Positioner to set, accepts str or the device
|
3256
|
+
"""
|
3257
|
+
|
3258
|
+
|
3259
|
+
class PositionerBoxBase(RPCBase):
|
3260
|
+
@property
|
3261
|
+
@rpc_call
|
3262
|
+
def _config_dict(self) -> "dict":
|
3263
|
+
"""
|
3264
|
+
Get the configuration of the widget.
|
3265
|
+
|
3266
|
+
Returns:
|
3267
|
+
dict: The configuration of the widget.
|
3268
|
+
"""
|
3269
|
+
|
3270
|
+
@rpc_call
|
3271
|
+
def _get_all_rpc(self) -> "dict":
|
3272
|
+
"""
|
3273
|
+
Get all registered RPC objects.
|
3274
|
+
"""
|
3275
|
+
|
3276
|
+
@property
|
3277
|
+
@rpc_call
|
3278
|
+
def _rpc_id(self) -> "str":
|
3279
|
+
"""
|
3280
|
+
Get the RPC ID of the widget.
|
3281
|
+
"""
|
3282
|
+
|
3283
|
+
|
3238
3284
|
class PositionerControlLine(RPCBase):
|
3239
3285
|
@rpc_call
|
3240
3286
|
def set_positioner(self, positioner: "str | Positioner"):
|
@@ -5,28 +5,43 @@ analyse data. Requesting a new fit may lead to request piling up and an overall
|
|
5
5
|
will allow you to decide by yourself when to unblock and execute the callback again."""
|
6
6
|
|
7
7
|
from pyqtgraph import SignalProxy
|
8
|
-
from qtpy.QtCore import
|
8
|
+
from qtpy.QtCore import QTimer, Signal
|
9
|
+
|
10
|
+
from bec_widgets.qt_utils.error_popups import SafeSlot
|
9
11
|
|
10
12
|
|
11
13
|
class BECSignalProxy(SignalProxy):
|
12
|
-
"""
|
14
|
+
"""
|
15
|
+
Thin wrapper around the SignalProxy class to allow signal calls to be blocked,
|
16
|
+
but arguments still being stored.
|
13
17
|
|
14
18
|
Args:
|
15
|
-
*args: Arguments to pass to the SignalProxy class
|
16
|
-
rateLimit (int): The rateLimit of the proxy
|
17
|
-
|
19
|
+
*args: Arguments to pass to the SignalProxy class.
|
20
|
+
rateLimit (int): The rateLimit of the proxy.
|
21
|
+
timeout (float): The number of seconds after which the proxy automatically
|
22
|
+
unblocks if still blocked. Default is 10.0 seconds.
|
23
|
+
**kwargs: Keyword arguments to pass to the SignalProxy class.
|
18
24
|
|
19
25
|
Example:
|
20
|
-
|
26
|
+
>>> proxy = BECSignalProxy(signal, rate_limit=25, slot=callback)
|
27
|
+
"""
|
21
28
|
|
22
29
|
is_blocked = Signal(bool)
|
23
30
|
|
24
|
-
def __init__(self, *args, rateLimit=25, **kwargs):
|
31
|
+
def __init__(self, *args, rateLimit=25, timeout=10.0, **kwargs):
|
25
32
|
super().__init__(*args, rateLimit=rateLimit, **kwargs)
|
26
33
|
self._blocking = False
|
27
34
|
self.old_args = None
|
28
35
|
self.new_args = None
|
29
36
|
|
37
|
+
# Store timeout value (in seconds)
|
38
|
+
self._timeout = timeout
|
39
|
+
|
40
|
+
# Create a single-shot timer for auto-unblocking
|
41
|
+
self._timer = QTimer()
|
42
|
+
self._timer.setSingleShot(True)
|
43
|
+
self._timer.timeout.connect(self._timeout_unblock)
|
44
|
+
|
30
45
|
@property
|
31
46
|
def blocked(self):
|
32
47
|
"""Returns if the proxy is blocked"""
|
@@ -46,9 +61,22 @@ class BECSignalProxy(SignalProxy):
|
|
46
61
|
self.old_args = args
|
47
62
|
super().signalReceived(*args)
|
48
63
|
|
49
|
-
|
64
|
+
self._timer.start(int(self._timeout * 1000))
|
65
|
+
|
66
|
+
@SafeSlot()
|
50
67
|
def unblock_proxy(self):
|
51
68
|
"""Unblock the proxy, and call the signalReceived method in case there was an update of the args."""
|
52
|
-
self.blocked
|
53
|
-
|
54
|
-
self.
|
69
|
+
if self.blocked:
|
70
|
+
self._timer.stop()
|
71
|
+
self.blocked = False
|
72
|
+
if self.new_args != self.old_args:
|
73
|
+
self.signalReceived(*self.new_args)
|
74
|
+
|
75
|
+
@SafeSlot()
|
76
|
+
def _timeout_unblock(self):
|
77
|
+
"""
|
78
|
+
Internal method called by the QTimer upon timeout. Unblocks the proxy
|
79
|
+
automatically if it is still blocked.
|
80
|
+
"""
|
81
|
+
if self.blocked:
|
82
|
+
self.unblock_proxy()
|
@@ -20,7 +20,7 @@ from bec_widgets.qt_utils.toolbar import (
|
|
20
20
|
from bec_widgets.utils import ConnectionConfig, WidgetContainerUtils
|
21
21
|
from bec_widgets.utils.bec_widget import BECWidget
|
22
22
|
from bec_widgets.widgets.containers.dock.dock import BECDock, DockConfig
|
23
|
-
from bec_widgets.widgets.control.device_control.positioner_box
|
23
|
+
from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox
|
24
24
|
from bec_widgets.widgets.control.scan_control.scan_control import ScanControl
|
25
25
|
from bec_widgets.widgets.editors.vscode.vscode import VSCodeEditor
|
26
26
|
from bec_widgets.widgets.plots.image.image_widget import BECImageWidget
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from bec_widgets.widgets.control.device_control.positioner_box.positioner_box.positioner_box import (
|
2
|
+
PositionerBox,
|
3
|
+
)
|
4
|
+
from bec_widgets.widgets.control.device_control.positioner_box.positioner_box_2d.positioner_box_2d import (
|
5
|
+
PositionerBox2D,
|
6
|
+
)
|
7
|
+
from bec_widgets.widgets.control.device_control.positioner_box.positioner_control_line.positioner_control_line import (
|
8
|
+
PositionerControlLine,
|
9
|
+
)
|
10
|
+
|
11
|
+
__ALL__ = ["PositionerBox", "PositionerControlLine", "PositionerBox2D"]
|
@@ -0,0 +1,243 @@
|
|
1
|
+
import uuid
|
2
|
+
from abc import abstractmethod
|
3
|
+
from ast import Tuple
|
4
|
+
from typing import Callable, TypedDict
|
5
|
+
|
6
|
+
from bec_lib.device import Positioner
|
7
|
+
from bec_lib.endpoints import MessageEndpoints
|
8
|
+
from bec_lib.logger import bec_logger
|
9
|
+
from bec_lib.messages import ScanQueueMessage
|
10
|
+
from qtpy.QtWidgets import (
|
11
|
+
QDialog,
|
12
|
+
QDoubleSpinBox,
|
13
|
+
QGroupBox,
|
14
|
+
QLabel,
|
15
|
+
QLineEdit,
|
16
|
+
QPushButton,
|
17
|
+
QVBoxLayout,
|
18
|
+
)
|
19
|
+
|
20
|
+
from bec_widgets.qt_utils.compact_popup import CompactPopupWidget
|
21
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
22
|
+
from bec_widgets.widgets.control.device_control.position_indicator.position_indicator import (
|
23
|
+
PositionIndicator,
|
24
|
+
)
|
25
|
+
from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter
|
26
|
+
from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit import (
|
27
|
+
DeviceLineEdit,
|
28
|
+
)
|
29
|
+
from bec_widgets.widgets.utility.spinner.spinner import SpinnerWidget
|
30
|
+
|
31
|
+
logger = bec_logger.logger
|
32
|
+
|
33
|
+
|
34
|
+
class DeviceUpdateUIComponents(TypedDict):
|
35
|
+
spinner: SpinnerWidget
|
36
|
+
setpoint: QLineEdit
|
37
|
+
readback: QLabel
|
38
|
+
position_indicator: PositionIndicator
|
39
|
+
step_size: QDoubleSpinBox
|
40
|
+
device_box: QGroupBox
|
41
|
+
stop: QPushButton
|
42
|
+
tweak_increase: QPushButton
|
43
|
+
tweak_decrease: QPushButton
|
44
|
+
|
45
|
+
|
46
|
+
class PositionerBoxBase(BECWidget, CompactPopupWidget):
|
47
|
+
"""Contains some core logic for positioner box widgets"""
|
48
|
+
|
49
|
+
current_path = ""
|
50
|
+
ICON_NAME = "switch_right"
|
51
|
+
|
52
|
+
def __init__(self, parent=None, **kwargs):
|
53
|
+
"""Initialize the PositionerBox widget.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
parent: The parent widget.
|
57
|
+
device (Positioner): The device to control.
|
58
|
+
"""
|
59
|
+
super().__init__(**kwargs)
|
60
|
+
CompactPopupWidget.__init__(self, parent=parent, layout=QVBoxLayout)
|
61
|
+
self._dialog = None
|
62
|
+
self.get_bec_shortcuts()
|
63
|
+
|
64
|
+
def _check_device_is_valid(self, device: str):
|
65
|
+
"""Check if the device is a positioner
|
66
|
+
|
67
|
+
Args:
|
68
|
+
device (str): The device name
|
69
|
+
"""
|
70
|
+
if device not in self.dev:
|
71
|
+
logger.info(f"Device {device} not found in the device list")
|
72
|
+
return False
|
73
|
+
if not isinstance(self.dev[device], Positioner):
|
74
|
+
logger.info(f"Device {device} is not a positioner")
|
75
|
+
return False
|
76
|
+
return True
|
77
|
+
|
78
|
+
@abstractmethod
|
79
|
+
def _device_ui_components(self, device: str) -> DeviceUpdateUIComponents: ...
|
80
|
+
|
81
|
+
def _init_device(
|
82
|
+
self,
|
83
|
+
device: str,
|
84
|
+
position_emit: Callable[[float], None],
|
85
|
+
limit_update: Callable[[tuple[float, float]], None],
|
86
|
+
):
|
87
|
+
"""Init the device view and readback"""
|
88
|
+
if self._check_device_is_valid(device):
|
89
|
+
data = self.dev[device].read()
|
90
|
+
self._on_device_readback(
|
91
|
+
device,
|
92
|
+
self._device_ui_components(device),
|
93
|
+
{"signals": data},
|
94
|
+
{},
|
95
|
+
position_emit,
|
96
|
+
limit_update,
|
97
|
+
)
|
98
|
+
|
99
|
+
def _stop_device(self, device: str):
|
100
|
+
"""Stop call"""
|
101
|
+
request_id = str(uuid.uuid4())
|
102
|
+
params = {"device": device, "rpc_id": request_id, "func": "stop", "args": [], "kwargs": {}}
|
103
|
+
msg = ScanQueueMessage(
|
104
|
+
scan_type="device_rpc",
|
105
|
+
parameter=params,
|
106
|
+
queue="emergency",
|
107
|
+
metadata={"RID": request_id, "response": False},
|
108
|
+
)
|
109
|
+
self.client.connector.send(MessageEndpoints.scan_queue_request(), msg)
|
110
|
+
|
111
|
+
# pylint: disable=unused-argument
|
112
|
+
def _on_device_readback(
|
113
|
+
self,
|
114
|
+
device: str,
|
115
|
+
ui_components: DeviceUpdateUIComponents,
|
116
|
+
msg_content: dict,
|
117
|
+
metadata: dict,
|
118
|
+
position_emit: Callable[[float], None],
|
119
|
+
limit_update: Callable[[tuple[float, float]], None],
|
120
|
+
):
|
121
|
+
signals = msg_content.get("signals", {})
|
122
|
+
# pylint: disable=protected-access
|
123
|
+
hinted_signals = self.dev[device]._hints
|
124
|
+
precision = self.dev[device].precision
|
125
|
+
|
126
|
+
spinner = ui_components["spinner"]
|
127
|
+
position_indicator = ui_components["position_indicator"]
|
128
|
+
readback = ui_components["readback"]
|
129
|
+
setpoint = ui_components["setpoint"]
|
130
|
+
|
131
|
+
readback_val = None
|
132
|
+
setpoint_val = None
|
133
|
+
|
134
|
+
if len(hinted_signals) == 1:
|
135
|
+
signal = hinted_signals[0]
|
136
|
+
readback_val = signals.get(signal, {}).get("value")
|
137
|
+
|
138
|
+
for setpoint_signal in ["setpoint", "user_setpoint"]:
|
139
|
+
setpoint_val = signals.get(f"{device}_{setpoint_signal}", {}).get("value")
|
140
|
+
if setpoint_val is not None:
|
141
|
+
break
|
142
|
+
|
143
|
+
for moving_signal in ["motor_done_move", "motor_is_moving"]:
|
144
|
+
is_moving = signals.get(f"{device}_{moving_signal}", {}).get("value")
|
145
|
+
if is_moving is not None:
|
146
|
+
break
|
147
|
+
|
148
|
+
if is_moving is not None:
|
149
|
+
spinner.setVisible(True)
|
150
|
+
if is_moving:
|
151
|
+
spinner.start()
|
152
|
+
spinner.setToolTip("Device is moving")
|
153
|
+
self.set_global_state("warning")
|
154
|
+
else:
|
155
|
+
spinner.stop()
|
156
|
+
spinner.setToolTip("Device is idle")
|
157
|
+
self.set_global_state("success")
|
158
|
+
else:
|
159
|
+
spinner.setVisible(False)
|
160
|
+
|
161
|
+
if readback_val is not None:
|
162
|
+
readback.setText(f"{readback_val:.{precision}f}")
|
163
|
+
position_emit(readback_val)
|
164
|
+
|
165
|
+
if setpoint_val is not None:
|
166
|
+
setpoint.setText(f"{setpoint_val:.{precision}f}")
|
167
|
+
|
168
|
+
limits = self.dev[device].limits
|
169
|
+
limit_update(limits)
|
170
|
+
if limits is not None and readback_val is not None and limits[0] != limits[1]:
|
171
|
+
pos = (readback_val - limits[0]) / (limits[1] - limits[0])
|
172
|
+
position_indicator.set_value(pos)
|
173
|
+
|
174
|
+
def _update_limits_ui(
|
175
|
+
self, limits: tuple[float, float], position_indicator, setpoint_validator
|
176
|
+
):
|
177
|
+
if limits is not None and limits[0] != limits[1]:
|
178
|
+
position_indicator.setToolTip(f"Min: {limits[0]}, Max: {limits[1]}")
|
179
|
+
setpoint_validator.setRange(limits[0], limits[1])
|
180
|
+
else:
|
181
|
+
position_indicator.setToolTip("No limits set")
|
182
|
+
setpoint_validator.setRange(float("-inf"), float("inf"))
|
183
|
+
|
184
|
+
def _update_device_ui(self, device: str, ui: DeviceUpdateUIComponents):
|
185
|
+
ui["device_box"].setTitle(device)
|
186
|
+
ui["readback"].setToolTip(f"{device} readback")
|
187
|
+
ui["setpoint"].setToolTip(f"{device} setpoint")
|
188
|
+
ui["step_size"].setToolTip(f"Step size for {device}")
|
189
|
+
precision = self.dev[device].precision
|
190
|
+
if precision is not None:
|
191
|
+
ui["step_size"].setDecimals(precision)
|
192
|
+
ui["step_size"].setValue(10**-precision * 10)
|
193
|
+
|
194
|
+
def _swap_readback_signal_connection(self, slot, old_device, new_device):
|
195
|
+
self.bec_dispatcher.disconnect_slot(slot, MessageEndpoints.device_readback(old_device))
|
196
|
+
self.bec_dispatcher.connect_slot(slot, MessageEndpoints.device_readback(new_device))
|
197
|
+
|
198
|
+
def _toggle_enable_buttons(self, ui: DeviceUpdateUIComponents, enable: bool) -> None:
|
199
|
+
"""Toogle enable/disable on available buttons
|
200
|
+
|
201
|
+
Args:
|
202
|
+
enable (bool): Enable buttons
|
203
|
+
"""
|
204
|
+
ui["tweak_increase"].setEnabled(enable)
|
205
|
+
ui["tweak_decrease"].setEnabled(enable)
|
206
|
+
ui["stop"].setEnabled(enable)
|
207
|
+
ui["setpoint"].setEnabled(enable)
|
208
|
+
ui["step_size"].setEnabled(enable)
|
209
|
+
|
210
|
+
def _on_device_change(
|
211
|
+
self,
|
212
|
+
old_device: str,
|
213
|
+
new_device: str,
|
214
|
+
position_emit: Callable[[float], None],
|
215
|
+
limit_update: Callable[[tuple[float, float]], None],
|
216
|
+
on_device_readback: Callable,
|
217
|
+
ui: DeviceUpdateUIComponents,
|
218
|
+
):
|
219
|
+
logger.info(f"Device changed from {old_device} to {new_device}")
|
220
|
+
self._toggle_enable_buttons(ui, True)
|
221
|
+
self._init_device(new_device, position_emit, limit_update)
|
222
|
+
self._swap_readback_signal_connection(on_device_readback, old_device, new_device)
|
223
|
+
self._update_device_ui(new_device, ui)
|
224
|
+
|
225
|
+
def _open_dialog_selection(self, set_positioner: Callable):
|
226
|
+
def _ods():
|
227
|
+
"""Open dialog window for positioner selection"""
|
228
|
+
self._dialog = QDialog(self)
|
229
|
+
self._dialog.setWindowTitle("Positioner Selection")
|
230
|
+
layout = QVBoxLayout()
|
231
|
+
line_edit = DeviceLineEdit(
|
232
|
+
self, client=self.client, device_filter=[BECDeviceFilter.POSITIONER]
|
233
|
+
)
|
234
|
+
line_edit.textChanged.connect(set_positioner)
|
235
|
+
layout.addWidget(line_edit)
|
236
|
+
close_button = QPushButton("Close")
|
237
|
+
close_button.clicked.connect(self._dialog.accept)
|
238
|
+
layout.addWidget(close_button)
|
239
|
+
self._dialog.setLayout(layout)
|
240
|
+
self._dialog.exec()
|
241
|
+
self._dialog = None
|
242
|
+
|
243
|
+
return _ods
|
File without changes
|