bec-widgets 1.16.4__py3-none-any.whl → 1.17.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.
Files changed (35) hide show
  1. CHANGELOG.md +41 -0
  2. PKG-INFO +1 -1
  3. bec_widgets/cli/client.py +46 -0
  4. bec_widgets/cli/server.py +3 -7
  5. bec_widgets/qt_utils/error_popups.py +3 -8
  6. bec_widgets/widgets/containers/dock/dock_area.py +1 -1
  7. bec_widgets/widgets/control/device_control/positioner_box/__init__.py +11 -0
  8. bec_widgets/widgets/control/device_control/positioner_box/_base/__init__.py +3 -0
  9. bec_widgets/widgets/control/device_control/positioner_box/_base/positioner_box_base.py +243 -0
  10. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/__init__.py +0 -0
  11. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py +242 -0
  12. bec_widgets/widgets/control/device_control/positioner_box/{positioner_box_plugin.py → positioner_box/positioner_box_plugin.py} +1 -1
  13. bec_widgets/widgets/control/device_control/positioner_box/{register_positioner_box.py → positioner_box/register_positioner_box.py} +1 -1
  14. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/__init__.py +0 -0
  15. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box2_d.pyproject +1 -0
  16. 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
  17. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py +482 -0
  18. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.ui +562 -0
  19. 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
  20. bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.py → positioner_control_line/positioner_control_line.py} +5 -2
  21. bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line_plugin.py → positioner_control_line/positioner_control_line_plugin.py} +1 -3
  22. bec_widgets/widgets/control/device_control/positioner_box/{register_positioner_control_line.py → positioner_control_line/register_positioner_control_line.py} +1 -1
  23. bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py +7 -6
  24. {bec_widgets-1.16.4.dist-info → bec_widgets-1.17.0.dist-info}/METADATA +1 -1
  25. {bec_widgets-1.16.4.dist-info → bec_widgets-1.17.0.dist-info}/RECORD +33 -27
  26. pyproject.toml +1 -1
  27. bec_widgets/widgets/control/device_control/positioner_box/positioner_box.py +0 -352
  28. bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box.pyproject +0 -1
  29. /bec_widgets/widgets/control/device_control/positioner_box/{positioner_box.pyproject → positioner_box/positioner_box.pyproject} +0 -0
  30. /bec_widgets/widgets/control/device_control/positioner_box/{positioner_box.ui → positioner_box/positioner_box.ui} +0 -0
  31. /bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.pyproject → positioner_control_line/positioner_control_line.pyproject} +0 -0
  32. /bec_widgets/widgets/control/device_control/positioner_box/{positioner_control_line.ui → positioner_control_line/positioner_control_line.ui} +0 -0
  33. {bec_widgets-1.16.4.dist-info → bec_widgets-1.17.0.dist-info}/WHEEL +0 -0
  34. {bec_widgets-1.16.4.dist-info → bec_widgets-1.17.0.dist-info}/entry_points.txt +0 -0
  35. {bec_widgets-1.16.4.dist-info → bec_widgets-1.17.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,7 @@ import os
6
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
7
7
 
8
8
  from bec_widgets.utils.bec_designer import designer_material_icon
9
- from bec_widgets.widgets.control.device_control.positioner_box.positioner_box import PositionerBox
9
+ from bec_widgets.widgets.control.device_control.positioner_box import PositionerBox
10
10
 
11
11
  DOM_XML = """
12
12
  <ui language='c++'>
@@ -6,7 +6,7 @@ def main(): # pragma: no cover
6
6
  return
7
7
  from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
8
 
9
- from bec_widgets.widgets.control.device_control.positioner_box.positioner_box_plugin import (
9
+ from bec_widgets.widgets.control.device_control.positioner_box.positioner_box.positioner_box_plugin import (
10
10
  PositionerBoxPlugin,
11
11
  )
12
12
 
@@ -4,36 +4,38 @@
4
4
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
5
5
 
6
6
  from bec_widgets.utils.bec_designer import designer_material_icon
7
- from bec_widgets.widgets.control.device_input.signal_combobox.signal_combobox import SignalComboBox
7
+ from bec_widgets.widgets.control.device_control.positioner_box.positioner_box_2d.positioner_box_2d import (
8
+ PositionerBox2D,
9
+ )
8
10
 
9
11
  DOM_XML = """
10
12
  <ui language='c++'>
11
- <widget class='SignalComboBox' name='signal_combo_box'>
13
+ <widget class='PositionerBox2D' name='positioner_box2_d'>
12
14
  </widget>
13
15
  </ui>
14
16
  """
15
17
 
16
18
 
17
- class SignalComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
19
+ class PositionerBox2DPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
18
20
  def __init__(self):
19
21
  super().__init__()
20
22
  self._form_editor = None
21
23
 
22
24
  def createWidget(self, parent):
23
- t = SignalComboBox(parent)
25
+ t = PositionerBox2D(parent)
24
26
  return t
25
27
 
26
28
  def domXml(self):
27
29
  return DOM_XML
28
30
 
29
31
  def group(self):
30
- return "BEC Input Widgets"
32
+ return "Device Control"
31
33
 
32
34
  def icon(self):
33
- return designer_material_icon(SignalComboBox.ICON_NAME)
35
+ return designer_material_icon(PositionerBox2D.ICON_NAME)
34
36
 
35
37
  def includeFile(self):
36
- return "signal_combo_box"
38
+ return "positioner_box2_d"
37
39
 
38
40
  def initialize(self, form_editor):
39
41
  self._form_editor = form_editor
@@ -45,10 +47,10 @@ class SignalComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
45
47
  return self._form_editor is not None
46
48
 
47
49
  def name(self):
48
- return "SignalComboBox"
50
+ return "PositionerBox2D"
49
51
 
50
52
  def toolTip(self):
51
- return ""
53
+ return "Simple Widget to control two positioners in box form"
52
54
 
53
55
  def whatsThis(self):
54
56
  return self.toolTip()
@@ -0,0 +1,482 @@
1
+ """ Module for a PositionerBox2D widget to control two positioner devices."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ from typing import Literal
7
+
8
+ from bec_lib.device import Positioner
9
+ from bec_lib.logger import bec_logger
10
+ from bec_qthemes import material_icon
11
+ from qtpy.QtCore import Signal
12
+ from qtpy.QtGui import QDoubleValidator
13
+ from qtpy.QtWidgets import QDoubleSpinBox
14
+
15
+ from bec_widgets.qt_utils.error_popups import SafeProperty, SafeSlot
16
+ from bec_widgets.utils import UILoader
17
+ from bec_widgets.utils.colors import set_theme
18
+ from bec_widgets.widgets.control.device_control.positioner_box._base import PositionerBoxBase
19
+ from bec_widgets.widgets.control.device_control.positioner_box._base.positioner_box_base import (
20
+ DeviceUpdateUIComponents,
21
+ )
22
+
23
+ logger = bec_logger.logger
24
+
25
+ MODULE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
26
+
27
+ DeviceId = Literal["horizontal", "vertical"]
28
+
29
+
30
+ class PositionerBox2D(PositionerBoxBase):
31
+ """Simple Widget to control two positioners in box form"""
32
+
33
+ ui_file = "positioner_box_2d.ui"
34
+
35
+ PLUGIN = True
36
+ USER_ACCESS = ["set_positioner_hor", "set_positioner_ver"]
37
+
38
+ device_changed_hor = Signal(str, str)
39
+ device_changed_ver = Signal(str, str)
40
+ # Signals emitted to inform listeners about a position update
41
+ position_update_hor = Signal(float)
42
+ position_update_ver = Signal(float)
43
+
44
+ def __init__(
45
+ self,
46
+ parent=None,
47
+ device_hor: Positioner | str | None = None,
48
+ device_ver: Positioner | str | None = None,
49
+ **kwargs,
50
+ ):
51
+ """Initialize the PositionerBox widget.
52
+
53
+ Args:
54
+ parent: The parent widget.
55
+ device_hor (Positioner | str): The first device to control - assigned the horizontal axis.
56
+ device_ver (Positioner | str): The second device to control - assigned the vertical axis.
57
+ """
58
+ super().__init__(parent=parent, **kwargs)
59
+
60
+ self._device_hor = ""
61
+ self._device_ver = ""
62
+ self._limits_hor = None
63
+ self._limits_ver = None
64
+ self._dialog = None
65
+ if self.current_path == "":
66
+ self.current_path = os.path.dirname(__file__)
67
+ self.init_ui()
68
+ self.device_hor = device_hor
69
+ self.device_ver = device_ver
70
+
71
+ self.connect_ui()
72
+
73
+ def init_ui(self):
74
+ """Init the ui"""
75
+ self.device_changed_hor.connect(self.on_device_change_hor)
76
+ self.device_changed_ver.connect(self.on_device_change_ver)
77
+
78
+ self.ui = UILoader(self).loader(os.path.join(self.current_path, self.ui_file))
79
+ self.setpoint_validator_hor = QDoubleValidator()
80
+ self.setpoint_validator_ver = QDoubleValidator()
81
+
82
+ def connect_ui(self):
83
+ """Connect the UI components to signals, data, or routines"""
84
+ self.addWidget(self.ui)
85
+ self.layout.setSpacing(0)
86
+ self.layout.setContentsMargins(0, 0, 0, 0)
87
+
88
+ def _init_ui(val: QDoubleValidator, device_id: DeviceId):
89
+ ui = self._device_ui_components_hv(device_id)
90
+ tweak_inc = (
91
+ self.on_tweak_inc_hor if device_id == "horizontal" else self.on_tweak_inc_ver
92
+ )
93
+ tweak_dec = (
94
+ self.on_tweak_dec_hor if device_id == "horizontal" else self.on_tweak_dec_ver
95
+ )
96
+ ui["setpoint"].setValidator(val)
97
+ ui["setpoint"].returnPressed.connect(
98
+ self.on_setpoint_change_hor
99
+ if device_id == "horizontal"
100
+ else self.on_setpoint_change_ver
101
+ )
102
+ ui["stop"].setToolTip("Stop")
103
+ ui["step_size"].setStepType(QDoubleSpinBox.StepType.AdaptiveDecimalStepType)
104
+ ui["tweak_increase"].clicked.connect(tweak_inc)
105
+ ui["tweak_decrease"].clicked.connect(tweak_dec)
106
+
107
+ _init_ui(self.setpoint_validator_hor, "horizontal")
108
+ _init_ui(self.setpoint_validator_ver, "vertical")
109
+
110
+ self.ui.stop_button.button.clicked.connect(self.on_stop)
111
+
112
+ self.ui.step_decrease_hor.clicked.connect(self.on_step_dec_hor)
113
+ self.ui.step_decrease_ver.clicked.connect(self.on_step_dec_ver)
114
+ self.ui.step_increase_hor.clicked.connect(self.on_step_inc_hor)
115
+ self.ui.step_increase_ver.clicked.connect(self.on_step_inc_ver)
116
+
117
+ self.ui.tool_button_hor.clicked.connect(
118
+ self._open_dialog_selection(self.set_positioner_hor)
119
+ )
120
+ self.ui.tool_button_ver.clicked.connect(
121
+ self._open_dialog_selection(self.set_positioner_ver)
122
+ )
123
+ icon = material_icon(icon_name="edit_note", size=(16, 16), convert_to_pixmap=False)
124
+ self.ui.tool_button_hor.setIcon(icon)
125
+ self.ui.tool_button_ver.setIcon(icon)
126
+
127
+ step_tooltip = "Step by the step size"
128
+ tweak_tooltip = "Tweak by 1/10th the step size"
129
+
130
+ for b in [
131
+ self.ui.step_increase_hor,
132
+ self.ui.step_increase_ver,
133
+ self.ui.step_decrease_hor,
134
+ self.ui.step_decrease_ver,
135
+ ]:
136
+ b.setToolTip(step_tooltip)
137
+
138
+ for b in [
139
+ self.ui.tweak_increase_hor,
140
+ self.ui.tweak_increase_ver,
141
+ self.ui.tweak_decrease_hor,
142
+ self.ui.tweak_decrease_ver,
143
+ ]:
144
+ b.setToolTip(tweak_tooltip)
145
+
146
+ icon_options = {"size": (16, 16), "convert_to_pixmap": False}
147
+ self.ui.tweak_increase_hor.setIcon(
148
+ material_icon(icon_name="keyboard_arrow_right", **icon_options)
149
+ )
150
+ self.ui.step_increase_hor.setIcon(
151
+ material_icon(icon_name="keyboard_double_arrow_right", **icon_options)
152
+ )
153
+ self.ui.tweak_decrease_hor.setIcon(
154
+ material_icon(icon_name="keyboard_arrow_left", **icon_options)
155
+ )
156
+ self.ui.step_decrease_hor.setIcon(
157
+ material_icon(icon_name="keyboard_double_arrow_left", **icon_options)
158
+ )
159
+ self.ui.tweak_increase_ver.setIcon(
160
+ material_icon(icon_name="keyboard_arrow_up", **icon_options)
161
+ )
162
+ self.ui.step_increase_ver.setIcon(
163
+ material_icon(icon_name="keyboard_double_arrow_up", **icon_options)
164
+ )
165
+ self.ui.tweak_decrease_ver.setIcon(
166
+ material_icon(icon_name="keyboard_arrow_down", **icon_options)
167
+ )
168
+ self.ui.step_decrease_ver.setIcon(
169
+ material_icon(icon_name="keyboard_double_arrow_down", **icon_options)
170
+ )
171
+
172
+ @SafeProperty(str)
173
+ def device_hor(self):
174
+ """SafeProperty to set the device"""
175
+ return self._device_hor
176
+
177
+ @device_hor.setter
178
+ def device_hor(self, value: str):
179
+ """Setter, checks if device is a string"""
180
+ if not value or not isinstance(value, str):
181
+ return
182
+ if not self._check_device_is_valid(value):
183
+ return
184
+ if value == self.device_ver:
185
+ return
186
+ old_device = self._device_hor
187
+ self._device_hor = value
188
+ self.label = f"{self._device_hor}, {self._device_ver}"
189
+ self.device_changed_hor.emit(old_device, value)
190
+ self._init_device(self.device_hor, self.position_update_hor.emit, self.update_limits_hor)
191
+
192
+ @SafeProperty(str)
193
+ def device_ver(self):
194
+ """SafeProperty to set the device"""
195
+ return self._device_ver
196
+
197
+ @device_ver.setter
198
+ def device_ver(self, value: str):
199
+ """Setter, checks if device is a string"""
200
+ if not value or not isinstance(value, str):
201
+ return
202
+ if not self._check_device_is_valid(value):
203
+ return
204
+ if value == self.device_hor:
205
+ return
206
+ old_device = self._device_ver
207
+ self._device_ver = value
208
+ self.label = f"{self._device_hor}, {self._device_ver}"
209
+ self.device_changed_ver.emit(old_device, value)
210
+ self._init_device(self.device_ver, self.position_update_ver.emit, self.update_limits_ver)
211
+
212
+ @SafeProperty(bool)
213
+ def hide_device_selection(self):
214
+ """Hide the device selection"""
215
+ return not self.ui.tool_button_hor.isVisible()
216
+
217
+ @hide_device_selection.setter
218
+ def hide_device_selection(self, value: bool):
219
+ """Set the device selection visibility"""
220
+ self.ui.tool_button_hor.setVisible(not value)
221
+ self.ui.tool_button_ver.setVisible(not value)
222
+
223
+ @SafeProperty(bool)
224
+ def hide_device_boxes(self):
225
+ """Hide the device selection"""
226
+ return not self.ui.device_box_hor.isVisible()
227
+
228
+ @hide_device_boxes.setter
229
+ def hide_device_boxes(self, value: bool):
230
+ """Set the device selection visibility"""
231
+ self.ui.device_box_hor.setVisible(not value)
232
+ self.ui.device_box_ver.setVisible(not value)
233
+
234
+ @SafeSlot(bool)
235
+ def show_device_selection(self, value: bool):
236
+ """Show the device selection
237
+
238
+ Args:
239
+ value (bool): Show the device selection
240
+ """
241
+ self.hide_device_selection = not value
242
+
243
+ @SafeSlot(str)
244
+ def set_positioner_hor(self, positioner: str | Positioner):
245
+ """Set the device
246
+
247
+ Args:
248
+ positioner (Positioner | str) : Positioner to set, accepts str or the device
249
+ """
250
+ if isinstance(positioner, Positioner):
251
+ positioner = positioner.name
252
+ self.device_hor = positioner
253
+
254
+ @SafeSlot(str)
255
+ def set_positioner_ver(self, positioner: str | Positioner):
256
+ """Set the device
257
+
258
+ Args:
259
+ positioner (Positioner | str) : Positioner to set, accepts str or the device
260
+ """
261
+ if isinstance(positioner, Positioner):
262
+ positioner = positioner.name
263
+ self.device_ver = positioner
264
+
265
+ @SafeSlot(str, str)
266
+ def on_device_change_hor(self, old_device: str, new_device: str):
267
+ """Upon changing the device, a check will be performed if the device is a Positioner.
268
+
269
+ Args:
270
+ old_device (str): The old device name.
271
+ new_device (str): The new device name.
272
+ """
273
+ if not self._check_device_is_valid(new_device):
274
+ return
275
+ self._on_device_change(
276
+ old_device,
277
+ new_device,
278
+ self.position_update_hor.emit,
279
+ self.update_limits_hor,
280
+ self.on_device_readback_hor,
281
+ self._device_ui_components_hv("horizontal"),
282
+ )
283
+
284
+ @SafeSlot(str, str)
285
+ def on_device_change_ver(self, old_device: str, new_device: str):
286
+ """Upon changing the device, a check will be performed if the device is a Positioner.
287
+
288
+ Args:
289
+ old_device (str): The old device name.
290
+ new_device (str): The new device name.
291
+ """
292
+ if not self._check_device_is_valid(new_device):
293
+ return
294
+ self._on_device_change(
295
+ old_device,
296
+ new_device,
297
+ self.position_update_ver.emit,
298
+ self.update_limits_ver,
299
+ self.on_device_readback_ver,
300
+ self._device_ui_components_hv("vertical"),
301
+ )
302
+
303
+ def _device_ui_components_hv(self, device: DeviceId) -> DeviceUpdateUIComponents:
304
+ if device == "horizontal":
305
+ return {
306
+ "spinner": self.ui.spinner_widget_hor,
307
+ "position_indicator": self.ui.position_indicator_hor,
308
+ "readback": self.ui.readback_hor,
309
+ "setpoint": self.ui.setpoint_hor,
310
+ "step_size": self.ui.step_size_hor,
311
+ "device_box": self.ui.device_box_hor,
312
+ "stop": self.ui.stop_button,
313
+ "tweak_increase": self.ui.tweak_increase_hor,
314
+ "tweak_decrease": self.ui.tweak_decrease_hor,
315
+ }
316
+ elif device == "vertical":
317
+ return {
318
+ "spinner": self.ui.spinner_widget_ver,
319
+ "position_indicator": self.ui.position_indicator_ver,
320
+ "readback": self.ui.readback_ver,
321
+ "setpoint": self.ui.setpoint_ver,
322
+ "step_size": self.ui.step_size_ver,
323
+ "device_box": self.ui.device_box_ver,
324
+ "stop": self.ui.stop_button,
325
+ "tweak_increase": self.ui.tweak_increase_ver,
326
+ "tweak_decrease": self.ui.tweak_decrease_ver,
327
+ }
328
+ else:
329
+ raise ValueError(f"Device {device} is not represented by this UI")
330
+
331
+ def _device_ui_components(self, device: str):
332
+ if device == self.device_hor:
333
+ return self._device_ui_components_hv("horizontal")
334
+ if device == self.device_ver:
335
+ return self._device_ui_components_hv("vertical")
336
+
337
+ @SafeSlot(dict, dict)
338
+ def on_device_readback_hor(self, msg_content: dict, metadata: dict):
339
+ """Callback for device readback.
340
+
341
+ Args:
342
+ msg_content (dict): The message content.
343
+ metadata (dict): The message metadata.
344
+ """
345
+ self._on_device_readback(
346
+ self.device_hor,
347
+ self._device_ui_components_hv("horizontal"),
348
+ msg_content,
349
+ metadata,
350
+ self.position_update_hor.emit,
351
+ self.update_limits_hor,
352
+ )
353
+
354
+ @SafeSlot(dict, dict)
355
+ def on_device_readback_ver(self, msg_content: dict, metadata: dict):
356
+ """Callback for device readback.
357
+
358
+ Args:
359
+ msg_content (dict): The message content.
360
+ metadata (dict): The message metadata.
361
+ """
362
+ self._on_device_readback(
363
+ self.device_ver,
364
+ self._device_ui_components_hv("vertical"),
365
+ msg_content,
366
+ metadata,
367
+ self.position_update_ver.emit,
368
+ self.update_limits_ver,
369
+ )
370
+
371
+ def update_limits_hor(self, limits: tuple):
372
+ """Update limits
373
+
374
+ Args:
375
+ limits (tuple): Limits of the positioner
376
+ """
377
+ if limits == self._limits_hor:
378
+ return
379
+ self._limits_hor = limits
380
+ self._update_limits_ui(limits, self.ui.position_indicator_hor, self.setpoint_validator_hor)
381
+
382
+ def update_limits_ver(self, limits: tuple):
383
+ """Update limits
384
+
385
+ Args:
386
+ limits (tuple): Limits of the positioner
387
+ """
388
+ if limits == self._limits_ver:
389
+ return
390
+ self._limits_ver = limits
391
+ self._update_limits_ui(limits, self.ui.position_indicator_ver, self.setpoint_validator_ver)
392
+
393
+ @SafeSlot()
394
+ def on_stop(self):
395
+ self._stop_device(f"{self.device_hor} or {self.device_ver}")
396
+
397
+ @SafeProperty(float)
398
+ def step_size_hor(self):
399
+ """Step size for tweak"""
400
+ return self.ui.step_size_hor.value()
401
+
402
+ @step_size_hor.setter
403
+ def step_size_hor(self, val: float):
404
+ """Step size for tweak"""
405
+ self.ui.step_size_hor.setValue(val)
406
+
407
+ @SafeProperty(float)
408
+ def step_size_ver(self):
409
+ """Step size for tweak"""
410
+ return self.ui.step_size_ver.value()
411
+
412
+ @step_size_ver.setter
413
+ def step_size_ver(self, val: float):
414
+ """Step size for tweak"""
415
+ self.ui.step_size_ver.setValue(val)
416
+
417
+ @SafeSlot()
418
+ def on_tweak_inc_hor(self):
419
+ """Tweak device a up"""
420
+ self.dev[self.device_hor].move(self.step_size_hor / 10, relative=True)
421
+
422
+ @SafeSlot()
423
+ def on_tweak_dec_hor(self):
424
+ """Tweak device a down"""
425
+ self.dev[self.device_hor].move(-self.step_size_hor / 10, relative=True)
426
+
427
+ @SafeSlot()
428
+ def on_step_inc_hor(self):
429
+ """Tweak device a up"""
430
+ self.dev[self.device_hor].move(self.step_size_hor, relative=True)
431
+
432
+ @SafeSlot()
433
+ def on_step_dec_hor(self):
434
+ """Tweak device a down"""
435
+ self.dev[self.device_hor].move(-self.step_size_hor, relative=True)
436
+
437
+ @SafeSlot()
438
+ def on_tweak_inc_ver(self):
439
+ """Tweak device a up"""
440
+ self.dev[self.device_ver].move(self.step_size_ver / 10, relative=True)
441
+
442
+ @SafeSlot()
443
+ def on_tweak_dec_ver(self):
444
+ """Tweak device b down"""
445
+ self.dev[self.device_ver].move(-self.step_size_ver / 10, relative=True)
446
+
447
+ @SafeSlot()
448
+ def on_step_inc_ver(self):
449
+ """Tweak device b up"""
450
+ self.dev[self.device_ver].move(self.step_size_ver, relative=True)
451
+
452
+ @SafeSlot()
453
+ def on_step_dec_ver(self):
454
+ """Tweak device a down"""
455
+ self.dev[self.device_ver].move(-self.step_size_ver, relative=True)
456
+
457
+ @SafeSlot()
458
+ def on_setpoint_change_hor(self):
459
+ """Change the setpoint for device a"""
460
+ self.ui.setpoint_hor.clearFocus()
461
+ setpoint = self.ui.setpoint_hor.text()
462
+ self.dev[self.device_hor].move(float(setpoint), relative=False)
463
+
464
+ @SafeSlot()
465
+ def on_setpoint_change_ver(self):
466
+ """Change the setpoint for device b"""
467
+ self.ui.setpoint_ver.clearFocus()
468
+ setpoint = self.ui.setpoint_ver.text()
469
+ self.dev[self.device_ver].move(float(setpoint), relative=False)
470
+
471
+
472
+ if __name__ == "__main__": # pragma: no cover
473
+ import sys
474
+
475
+ from qtpy.QtWidgets import QApplication # pylint: disable=ungrouped-imports
476
+
477
+ app = QApplication(sys.argv)
478
+ set_theme("dark")
479
+ widget = PositionerBox2D()
480
+
481
+ widget.show()
482
+ sys.exit(app.exec_())