bec-widgets 0.93.3__py3-none-any.whl → 0.93.5__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 (25) hide show
  1. CHANGELOG.md +24 -22
  2. PKG-INFO +1 -1
  3. bec_widgets/assets/toolbar_icons/device_line_edit.svg +3 -0
  4. bec_widgets/cli/client.py +9 -16
  5. bec_widgets/widgets/dock/dock_area.py +4 -4
  6. bec_widgets/widgets/{device_box/device_box.py → positioner_box/positioner_box.py} +125 -15
  7. bec_widgets/widgets/positioner_box/positioner_box.pyproject +1 -0
  8. bec_widgets/widgets/{device_box/device_box.ui → positioner_box/positioner_box.ui} +30 -3
  9. bec_widgets/widgets/{device_box/device_box_plugin.py → positioner_box/positioner_box_plugin.py} +10 -11
  10. bec_widgets/widgets/{device_box/register_device_box.py → positioner_box/register_positioner_box.py} +2 -2
  11. {bec_widgets-0.93.3.dist-info → bec_widgets-0.93.5.dist-info}/METADATA +1 -1
  12. {bec_widgets-0.93.3.dist-info → bec_widgets-0.93.5.dist-info}/RECORD +23 -22
  13. pyproject.toml +1 -1
  14. tests/end-2-end/test_bec_dock_rpc_e2e.py +13 -2
  15. tests/end-2-end/test_bec_figure_rpc_e2e.py +9 -7
  16. tests/unit_tests/test_bec_dock.py +6 -4
  17. tests/unit_tests/test_positioner_box.py +104 -0
  18. bec_widgets/widgets/device_box/device_box.pyproject +0 -1
  19. tests/unit_tests/test_device_box.py +0 -98
  20. /bec_widgets/assets/designer_icons/{device_box.png → positioner_box.png} +0 -0
  21. /bec_widgets/assets/toolbar_icons/{device_box.svg → positioner_box.svg} +0 -0
  22. /bec_widgets/widgets/{device_box → positioner_box}/__init__.py +0 -0
  23. {bec_widgets-0.93.3.dist-info → bec_widgets-0.93.5.dist-info}/WHEEL +0 -0
  24. {bec_widgets-0.93.3.dist-info → bec_widgets-0.93.5.dist-info}/entry_points.txt +0 -0
  25. {bec_widgets-0.93.3.dist-info → bec_widgets-0.93.5.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.93.5 (2024-08-08)
4
+
5
+ ### Fix
6
+
7
+ * fix(positioner_box): icons fixed ([`281633d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/281633deff15b6879dac3a4f0770fa6949aaecdc))
8
+
9
+ ### Refactor
10
+
11
+ * refactor: add button for positioner selection ([`0d190c5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0d190c5c5996e59fec4bdd44d2003e10e200b009))
12
+
13
+ ### Test
14
+
15
+ * test(dap): wait for fit ([`6269009`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6269009e5451f830cdee58a514c7858483488a8d))
16
+
17
+ * test(auto-update): wait for rendering ([`6d2442d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6d2442d23c683fe92af13df982ce681c07e99cde))
18
+
19
+ ## v0.93.4 (2024-08-07)
20
+
21
+ ### Fix
22
+
23
+ * fix: rename DeviceBox to PositionerBox, fix test for validation ([`37aa371`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/37aa371e7c4c62d70abf37abc125db0c088790fe))
24
+
25
+ * fix: add validation for bec_lib.device.Positioner; closes #268 ([`eb54e9f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/eb54e9f788e97af23db8fe0c78f8facb8688bb99))
26
+
3
27
  ## v0.93.3 (2024-08-07)
4
28
 
5
29
  ### Fix
@@ -121,25 +145,3 @@ This reverts commit fd6ae91993a23a7b8dbb2cf3c4b7c3eda6d2b0f6 ([`5aad401`](https:
121
145
  * fix(dock): custom label can be created closable ([`4457ef2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4457ef2147e21b856c9dcaf63c81ba98002dcaf1))
122
146
 
123
147
  * fix(device_combobox): set minimum size to 125px ([`1206e15`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1206e153094cd8505badf69a1461572a76b4c5ad))
124
-
125
- ## v0.91.0 (2024-07-23)
126
-
127
- ### Feature
128
-
129
- * feat(dock_area): plugin added ([`a16b87a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a16b87ac28d164230dd2e8020f50ff3a63cd407e))
130
-
131
- * feat(dock_area): Added toolbar to dock area to add widgets without CLI interactions ([`cce1367`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/cce1367a72fca7206d351894bd1831b7bbfa7ec6))
132
-
133
- * feat(toolbar): expandable menu actions ([`28f26e9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/28f26e92a46063db1a194be552156a5d3b2c43e7))
134
-
135
- ### Fix
136
-
137
- * fix(status_item): icons changed to material design ([`1b9c55a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1b9c55a46a0dfd8678c8e95ff64dd6e8cfb9233e))
138
-
139
- * fix(plugins): Qt Designer plugins icons adjusted ([`f4844d2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f4844d2e067ce75dc64b89b230d7932b308ddfc2))
140
-
141
- ### Test
142
-
143
- * test(dock_area): tests extended ([`06fab0e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/06fab0eab926cef5677d4988fd1fce09da342dd8))
144
-
145
- ## v0.90.0 (2024-07-23)
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.93.3
3
+ Version: 0.93.5
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#FFFFFF">
2
+ <path d="M180-404.87v-50.26h289.75v50.26H180Zm0-162.57v-50.25h454.62v50.25H180Zm0-162.3V-780h454.62v50.26H180ZM524.62-180v-105.69l217.15-216.16q7.46-7.07 16.11-10.3 8.65-3.23 17.3-3.23 9.43 0 18.25 3.53 8.82 3.54 16.03 10.62l37 37.38q6.87 7.47 10.21 16.16Q860-439 860-430.31t-3.37 17.69q-3.37 9-10.52 16.46L630.31-180H524.62Zm250.69-211.69 37-38.62-37-37.38-38 38 38 38Z"/>
3
+ </svg>
bec_widgets/cli/client.py CHANGED
@@ -21,9 +21,9 @@ class Widgets(str, enum.Enum):
21
21
  BECQueue = "BECQueue"
22
22
  BECStatusBox = "BECStatusBox"
23
23
  BECWaveformWidget = "BECWaveformWidget"
24
- DeviceBox = "DeviceBox"
25
24
  DeviceComboBox = "DeviceComboBox"
26
25
  DeviceLineEdit = "DeviceLineEdit"
26
+ PositionerBox = "PositionerBox"
27
27
  RingProgressBar = "RingProgressBar"
28
28
  ScanControl = "ScanControl"
29
29
  StopButton = "StopButton"
@@ -2287,7 +2287,7 @@ class BECWaveformWidget(RPCBase):
2287
2287
  """
2288
2288
 
2289
2289
 
2290
- class DeviceBox(RPCBase):
2290
+ class DeviceComboBox(RPCBase):
2291
2291
  @property
2292
2292
  @rpc_call
2293
2293
  def _config_dict(self) -> "dict":
@@ -2305,7 +2305,7 @@ class DeviceBox(RPCBase):
2305
2305
  """
2306
2306
 
2307
2307
 
2308
- class DeviceComboBox(RPCBase):
2308
+ class DeviceInputBase(RPCBase):
2309
2309
  @property
2310
2310
  @rpc_call
2311
2311
  def _config_dict(self) -> "dict":
@@ -2323,7 +2323,7 @@ class DeviceComboBox(RPCBase):
2323
2323
  """
2324
2324
 
2325
2325
 
2326
- class DeviceInputBase(RPCBase):
2326
+ class DeviceLineEdit(RPCBase):
2327
2327
  @property
2328
2328
  @rpc_call
2329
2329
  def _config_dict(self) -> "dict":
@@ -2341,21 +2341,14 @@ class DeviceInputBase(RPCBase):
2341
2341
  """
2342
2342
 
2343
2343
 
2344
- class DeviceLineEdit(RPCBase):
2345
- @property
2344
+ class PositionerBox(RPCBase):
2346
2345
  @rpc_call
2347
- def _config_dict(self) -> "dict":
2348
- """
2349
- Get the configuration of the widget.
2350
-
2351
- Returns:
2352
- dict: The configuration of the widget.
2346
+ def set_positioner(self, positioner: str):
2353
2347
  """
2348
+ Set the device
2354
2349
 
2355
- @rpc_call
2356
- def _get_all_rpc(self) -> "dict":
2357
- """
2358
- Get all registered RPC objects.
2350
+ Args:
2351
+ positioner (Positioner | str) : Positioner to set, accepts str or the device
2359
2352
  """
2360
2353
 
2361
2354
 
@@ -83,8 +83,8 @@ class BECDockArea(BECWidget, QWidget):
83
83
  "scan_control": IconAction(
84
84
  icon_path="scan_control.svg", tooltip="Add Scan Control"
85
85
  ),
86
- "device_box": IconAction(
87
- icon_path="device_box.svg", tooltip="Add Device Box"
86
+ "positioner_box": IconAction(
87
+ icon_path="positioner_box.svg", tooltip="Add Device Box"
88
88
  ),
89
89
  },
90
90
  ),
@@ -132,8 +132,8 @@ class BECDockArea(BECWidget, QWidget):
132
132
  self.toolbar.widgets["menu_devices"].widgets["scan_control"].triggered.connect(
133
133
  lambda: self.add_dock(widget="ScanControl", prefix="scan_control")
134
134
  )
135
- self.toolbar.widgets["menu_devices"].widgets["device_box"].triggered.connect(
136
- lambda: self.add_dock(widget="DeviceBox", prefix="device_box")
135
+ self.toolbar.widgets["menu_devices"].widgets["positioner_box"].triggered.connect(
136
+ lambda: self.add_dock(widget="PositionerBox", prefix="positioner_box")
137
137
  )
138
138
 
139
139
  # Menu Utils
@@ -1,22 +1,40 @@
1
+ """ Module for a PositionerBox widget to control a positioner device."""
2
+
1
3
  import os
2
4
  import uuid
3
5
 
6
+ from bec_lib.device import Positioner
4
7
  from bec_lib.endpoints import MessageEndpoints
8
+ from bec_lib.logger import bec_logger
5
9
  from bec_lib.messages import ScanQueueMessage
6
- from qtpy.QtCore import Property, Signal, Slot
7
- from qtpy.QtGui import QDoubleValidator
8
- from qtpy.QtWidgets import QDoubleSpinBox, QVBoxLayout, QWidget
10
+ from qtpy.QtCore import Property, QSize, Signal, Slot
11
+ from qtpy.QtGui import QDoubleValidator, QIcon
12
+ from qtpy.QtWidgets import QDialog, QDoubleSpinBox, QPushButton, QVBoxLayout, QWidget
9
13
 
10
14
  from bec_widgets.utils import UILoader
11
15
  from bec_widgets.utils.bec_widget import BECWidget
12
16
  from bec_widgets.utils.colors import apply_theme
17
+ from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
18
+
19
+ logger = bec_logger.logger
20
+
21
+ MODULE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
13
22
 
14
23
 
15
- class DeviceBox(BECWidget, QWidget):
24
+ class PositionerBox(BECWidget, QWidget):
25
+ """Simple Widget to control a positioner in box form"""
26
+
27
+ USER_ACCESS = ["set_positioner"]
16
28
  device_changed = Signal(str, str)
17
29
 
18
- def __init__(self, parent=None, device=None, *args, **kwargs):
19
- super().__init__(*args, **kwargs)
30
+ def __init__(self, parent=None, device: Positioner = None, *args, **kwargs):
31
+ """Initialize the PositionerBox widget.
32
+
33
+ Args:
34
+ parent: The parent widget.
35
+ device (Positioner): The device to control.
36
+ """
37
+ super().__init__(**kwargs)
20
38
  QWidget.__init__(self, parent=parent)
21
39
  self.get_bec_shortcuts()
22
40
  self._device = ""
@@ -29,10 +47,11 @@ class DeviceBox(BECWidget, QWidget):
29
47
  self.init_device()
30
48
 
31
49
  def init_ui(self):
50
+ """Init the ui"""
32
51
  self.device_changed.connect(self.on_device_change)
33
52
 
34
53
  current_path = os.path.dirname(__file__)
35
- self.ui = UILoader(self).loader(os.path.join(current_path, "device_box.ui"))
54
+ self.ui = UILoader(self).loader(os.path.join(current_path, "positioner_box.ui"))
36
55
 
37
56
  self.layout = QVBoxLayout(self)
38
57
  self.layout.addWidget(self.ui)
@@ -55,30 +74,105 @@ class DeviceBox(BECWidget, QWidget):
55
74
  self.setpoint_validator = QDoubleValidator()
56
75
  self.ui.setpoint.setValidator(self.setpoint_validator)
57
76
  self.ui.spinner_widget.start()
77
+ self.ui.tool_button.clicked.connect(self._open_dialog_selection)
78
+ icon = QIcon()
79
+ icon.addFile(
80
+ os.path.join(MODULE_PATH, "assets", "toolbar_icons", "device_line_edit.svg"),
81
+ size=QSize(16, 16),
82
+ )
83
+ self.ui.tool_button.setIcon(icon)
84
+
85
+ def _open_dialog_selection(self):
86
+ """Open dialog window for positioner selection"""
87
+ dialog = QDialog(self)
88
+ dialog.setWindowTitle("Positioner Selection")
89
+ layout = QVBoxLayout()
90
+ line_edit = DeviceLineEdit(self, client=self.client, device_filter="Positioner")
91
+ line_edit.textChanged.connect(self._positioner_changed)
92
+ layout.addWidget(line_edit)
93
+ close_button = QPushButton("Close")
94
+ close_button.clicked.connect(dialog.accept)
95
+ layout.addWidget(close_button)
96
+ dialog.setLayout(layout)
97
+ dialog.exec()
98
+
99
+ @Slot(str)
100
+ def _positioner_changed(self, positioner_name: str):
101
+ """Changed input in combobox.
102
+
103
+ Args:
104
+ positioner_name (str): name of the positioner
105
+ """
106
+ self.set_positioner(positioner_name)
58
107
 
59
108
  def init_device(self):
60
- if self.device in self.dev:
109
+ """Init the device view and readback"""
110
+ if self._check_device_is_valid(self.device):
61
111
  data = self.dev[self.device].read()
62
112
  self.on_device_readback({"signals": data}, {})
63
113
 
114
+ def _toogle_enable_buttons(self, enable: bool) -> None:
115
+ """Toogle enable/disable on available buttons
116
+
117
+ Args:
118
+ enable (bool): Enable buttons
119
+ """
120
+ self.ui.tweak_left.setEnabled(enable)
121
+ self.ui.tweak_right.setEnabled(enable)
122
+ self.ui.stop.setEnabled(enable)
123
+ self.ui.setpoint.setEnabled(enable)
124
+ self.ui.step_size.setEnabled(enable)
125
+
64
126
  @Property(str)
65
127
  def device(self):
128
+ """Property to set the device"""
66
129
  return self._device
67
130
 
68
131
  @device.setter
69
- def device(self, value):
132
+ def device(self, value: str):
133
+ """Setter, checks if device is a string"""
70
134
  if not value or not isinstance(value, str):
71
135
  return
72
136
  old_device = self._device
73
137
  self._device = value
74
138
  self.device_changed.emit(old_device, value)
75
139
 
140
+ def set_positioner(self, positioner: str):
141
+ """Set the device
142
+
143
+ Args:
144
+ positioner (Positioner | str) : Positioner to set, accepts str or the device
145
+ """
146
+ if isinstance(positioner, Positioner):
147
+ positioner = positioner.name
148
+ self.device = positioner
149
+
150
+ def _check_device_is_valid(self, device: str):
151
+ """Check if the device is a positioner
152
+
153
+ Args:
154
+ device (str): The device name
155
+ """
156
+ if device not in self.dev:
157
+ logger.info(f"Device {device} not found in the device list")
158
+ return False
159
+ if not isinstance(self.dev[device], Positioner):
160
+ logger.info(f"Device {device} is not a positioner")
161
+ return False
162
+ return True
163
+
76
164
  @Slot(str, str)
77
165
  def on_device_change(self, old_device: str, new_device: str):
78
- if new_device not in self.dev:
79
- print(f"Device {new_device} not found in the device list")
166
+ """Upon changing the device, a check will be performed if the device is a Positioner.
167
+
168
+ Args:
169
+ old_device (str): The old device name.
170
+ new_device (str): The new device name.
171
+ """
172
+ if not self._check_device_is_valid(new_device):
80
173
  return
81
- print(f"Device changed from {old_device} to {new_device}")
174
+ logger.info(f"Device changed from {old_device} to {new_device}")
175
+ self._toogle_enable_buttons(True)
82
176
  self.init_device()
83
177
  self.bec_dispatcher.disconnect_slot(
84
178
  self.on_device_readback, MessageEndpoints.device_readback(old_device)
@@ -98,6 +192,12 @@ class DeviceBox(BECWidget, QWidget):
98
192
 
99
193
  @Slot(dict, dict)
100
194
  def on_device_readback(self, msg_content: dict, metadata: dict):
195
+ """Callback for device readback.
196
+
197
+ Args:
198
+ msg_content (dict): The message content.
199
+ metadata (dict): The message metadata.
200
+ """
101
201
  signals = msg_content.get("signals", {})
102
202
  # pylint: disable=protected-access
103
203
  hinted_signals = self.dev[self.device]._hints
@@ -134,7 +234,12 @@ class DeviceBox(BECWidget, QWidget):
134
234
  pos = (readback_val - limits[0]) / (limits[1] - limits[0])
135
235
  self.ui.position_indicator.on_position_update(pos)
136
236
 
137
- def update_limits(self, limits):
237
+ def update_limits(self, limits: tuple):
238
+ """Update limits
239
+
240
+ Args:
241
+ limits (tuple): Limits of the positioner
242
+ """
138
243
  if limits == self._limits:
139
244
  return
140
245
  self._limits = limits
@@ -147,6 +252,7 @@ class DeviceBox(BECWidget, QWidget):
147
252
 
148
253
  @Slot()
149
254
  def on_stop(self):
255
+ """Stop call"""
150
256
  request_id = str(uuid.uuid4())
151
257
  params = {
152
258
  "device": self.device,
@@ -165,18 +271,22 @@ class DeviceBox(BECWidget, QWidget):
165
271
 
166
272
  @property
167
273
  def step_size(self):
274
+ """Step size for tweak"""
168
275
  return self.ui.step_size.value()
169
276
 
170
277
  @Slot()
171
278
  def on_tweak_right(self):
279
+ """Tweak motor right"""
172
280
  self.dev[self.device].move(self.step_size, relative=True)
173
281
 
174
282
  @Slot()
175
283
  def on_tweak_left(self):
284
+ """Tweak motor left"""
176
285
  self.dev[self.device].move(-self.step_size, relative=True)
177
286
 
178
287
  @Slot()
179
288
  def on_setpoint_change(self):
289
+ """Change the setpoint for the motor"""
180
290
  self.ui.setpoint.clearFocus()
181
291
  setpoint = self.ui.setpoint.text()
182
292
  self.dev[self.device].move(float(setpoint), relative=False)
@@ -190,8 +300,8 @@ if __name__ == "__main__": # pragma: no cover
190
300
  from qtpy.QtWidgets import QApplication
191
301
 
192
302
  app = QApplication(sys.argv)
193
- apply_theme("light")
194
- widget = DeviceBox(device="samx")
303
+ apply_theme("dark")
304
+ widget = PositionerBox(device="bpm4i")
195
305
 
196
306
  widget.show()
197
307
  sys.exit(app.exec_())
@@ -0,0 +1 @@
1
+ {'files': ['positioner_box.py']}
@@ -29,17 +29,24 @@
29
29
  <item>
30
30
  <widget class="QGroupBox" name="device_box">
31
31
  <property name="title">
32
- <string>Device Name</string>
32
+ <string>No positioner selected</string>
33
33
  </property>
34
34
  <layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0,0,0">
35
35
  <property name="topMargin">
36
36
  <number>0</number>
37
37
  </property>
38
38
  <item row="3" column="1">
39
- <widget class="QDoubleSpinBox" name="step_size"/>
39
+ <widget class="QDoubleSpinBox" name="step_size">
40
+ <property name="enabled">
41
+ <bool>false</bool>
42
+ </property>
43
+ </widget>
40
44
  </item>
41
45
  <item row="3" column="2">
42
46
  <widget class="QToolButton" name="tweak_right">
47
+ <property name="enabled">
48
+ <bool>false</bool>
49
+ </property>
43
50
  <property name="minimumSize">
44
51
  <size>
45
52
  <width>50</width>
@@ -67,10 +74,20 @@
67
74
  </widget>
68
75
  </item>
69
76
  <item row="2" column="0" colspan="3">
70
- <widget class="QLineEdit" name="setpoint"/>
77
+ <widget class="QLineEdit" name="setpoint">
78
+ <property name="enabled">
79
+ <bool>false</bool>
80
+ </property>
81
+ <property name="alignment">
82
+ <set>Qt::AlignmentFlag::AlignCenter</set>
83
+ </property>
84
+ </widget>
71
85
  </item>
72
86
  <item row="3" column="0">
73
87
  <widget class="QToolButton" name="tweak_left">
88
+ <property name="enabled">
89
+ <bool>false</bool>
90
+ </property>
74
91
  <property name="minimumSize">
75
92
  <size>
76
93
  <width>50</width>
@@ -99,6 +116,9 @@
99
116
  </item>
100
117
  <item row="4" column="0" colspan="3">
101
118
  <widget class="QPushButton" name="stop">
119
+ <property name="enabled">
120
+ <bool>false</bool>
121
+ </property>
102
122
  <property name="text">
103
123
  <string>Stop</string>
104
124
  </property>
@@ -108,6 +128,13 @@
108
128
  <layout class="QVBoxLayout" name="verticalLayout_2">
109
129
  <item>
110
130
  <layout class="QHBoxLayout" name="horizontalLayout">
131
+ <item>
132
+ <widget class="QToolButton" name="tool_button">
133
+ <property name="text">
134
+ <string>...</string>
135
+ </property>
136
+ </widget>
137
+ </item>
111
138
  <item>
112
139
  <spacer name="horizontalSpacer">
113
140
  <property name="orientation">
@@ -1,30 +1,29 @@
1
1
  # Copyright (C) 2022 The Qt Company Ltd.
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+
3
4
  import os
4
5
 
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
7
  from qtpy.QtGui import QIcon
7
8
 
8
- import bec_widgets
9
- from bec_widgets.widgets.device_box.device_box import DeviceBox
9
+ from bec_widgets.widgets.positioner_box.positioner_box import PositionerBox
10
10
 
11
11
  DOM_XML = """
12
12
  <ui language='c++'>
13
- <widget class='DeviceBox' name='device_box'>
13
+ <widget class='PositionerBox' name='positioner_box'>
14
14
  </widget>
15
15
  </ui>
16
16
  """
17
-
18
- MODULE_PATH = os.path.dirname(bec_widgets.__file__)
17
+ MODULE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
19
18
 
20
19
 
21
- class DeviceBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
20
+ class PositionerBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
22
21
  def __init__(self):
23
22
  super().__init__()
24
23
  self._form_editor = None
25
24
 
26
25
  def createWidget(self, parent):
27
- t = DeviceBox(parent)
26
+ t = PositionerBox(parent)
28
27
  return t
29
28
 
30
29
  def domXml(self):
@@ -34,11 +33,11 @@ class DeviceBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
33
  return "Device Control"
35
34
 
36
35
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "device_box.png")
36
+ icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "positioner_box.png")
38
37
  return QIcon(icon_path)
39
38
 
40
39
  def includeFile(self):
41
- return "device_box"
40
+ return "positioner_box"
42
41
 
43
42
  def initialize(self, form_editor):
44
43
  self._form_editor = form_editor
@@ -50,10 +49,10 @@ class DeviceBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
50
49
  return self._form_editor is not None
51
50
 
52
51
  def name(self):
53
- return "DeviceBox"
52
+ return "PositionerBox"
54
53
 
55
54
  def toolTip(self):
56
- return "A widget for controlling a single positioner. "
55
+ return "Simple Widget to control a positioner in box form"
57
56
 
58
57
  def whatsThis(self):
59
58
  return self.toolTip()
@@ -6,9 +6,9 @@ def main(): # pragma: no cover
6
6
  return
7
7
  from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
8
 
9
- from bec_widgets.widgets.device_box.device_box_plugin import DeviceBoxPlugin
9
+ from bec_widgets.widgets.positioner_box.positioner_box_plugin import PositionerBoxPlugin
10
10
 
11
- QPyDesignerCustomWidgetCollection.addCustomWidget(DeviceBoxPlugin())
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(PositionerBoxPlugin())
12
12
 
13
13
 
14
14
  if __name__ == "__main__": # pragma: no cover
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.93.3
3
+ Version: 0.93.5
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -2,11 +2,11 @@
2
2
  .gitlab-ci.yml,sha256=BtKhZI3dhK09En1BfpglYi-ZJwG6ZdC-iJr7kXFVfCg,8346
3
3
  .pylintrc,sha256=eeY8YwSI74oFfq6IYIbCqnx3Vk8ZncKaatv96n_Y8Rs,18544
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=U5vCm00ka49FYkJ9jdcAusiIKlWRfmpBHPSFiuDcsuE,6646
5
+ CHANGELOG.md,sha256=9TA6IrNnjp3uhr3k-Msk1-QcCfc2lNXu_mB-TBx7L44,6639
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=_VblxDpuCc284m1SFf95vKgTaR-Jng60jurwZViD06c,1307
7
+ PKG-INFO,sha256=h4oukmTNxTFeOKdXwV_rgzM7vsWlGaVuWvm91kRPwWk,1307
8
8
  README.md,sha256=Od69x-RS85Hph0-WwWACwal4yUd67XkEn4APEfHhHFw,2649
9
- pyproject.toml,sha256=xNXznccvvpAdxIq46iwq_IJJcLfqag12-4IaiJaw0CY,2356
9
+ pyproject.toml,sha256=t2YPaVUqAHjl16jfLZWIemuL8yDGlw3XXaMRfTXb5Tc,2356
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
12
12
  .gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
@@ -19,7 +19,6 @@ bec_widgets/assets/app_icons/terminal_icon.png,sha256=bJl7Tft4Fi2uxvuXI8o14uMHnI
19
19
  bec_widgets/assets/designer_icons/code.png,sha256=o_d4UbojdvmdPY6exO3Eu0aQlS3UbvMuwrTlptvRMQE,4420
20
20
  bec_widgets/assets/designer_icons/color_button.png,sha256=1cg0jmTbWQbfmmEb09ABoX03tovIt6loLyO90oOVe8k,4810
21
21
  bec_widgets/assets/designer_icons/colormap_selector.png,sha256=KULLUA5T9SLhcSyrdouG07nXHZtE-LNNOn0ghG7T-OQ,6831
22
- bec_widgets/assets/designer_icons/device_box.png,sha256=CtEDj_GTTi_WOmKipuMjbKsejIBVEFiAxy7QsKHke5A,3676
23
22
  bec_widgets/assets/designer_icons/device_combo_box.png,sha256=ubt4ltSC8gIkrTnzaZ58JhiIinFhmKBstYIMrcH5Ua4,3555
24
23
  bec_widgets/assets/designer_icons/device_line_edit.png,sha256=68sb_4_z7SvdTXsw21g6dIuWKX70l08LB8pW79d8cg8,3316
25
24
  bec_widgets/assets/designer_icons/dock_area.png,sha256=I5U1ivkYRtcxSF2wQQa-SMHxHYDm06Nhd0AvGip9gCk,2774
@@ -27,6 +26,7 @@ bec_widgets/assets/designer_icons/games.png,sha256=83th_P_GG6d_xd7X55rqy8yf8ygeV
27
26
  bec_widgets/assets/designer_icons/image.png,sha256=0Kppbe2BBcsXzSHjqHxjrRgBE6DUT-ZF7xNPMMI2bxA,3984
28
27
  bec_widgets/assets/designer_icons/motor_map.png,sha256=8iqST5mTnZfv9rN9rx3D-XBm232Mwvzz9D0Wx6QaT8I,7293
29
28
  bec_widgets/assets/designer_icons/position_indicator.png,sha256=9moeldNTfRWdf7aFvBS1GCewYtKC5o3hgx8BDgxALb0,2030
29
+ bec_widgets/assets/designer_icons/positioner_box.png,sha256=CtEDj_GTTi_WOmKipuMjbKsejIBVEFiAxy7QsKHke5A,3676
30
30
  bec_widgets/assets/designer_icons/queue.png,sha256=NdlrmWwon7K2zWbqg32WkHx1RBKznQDN5H-UfRVqDRA,1827
31
31
  bec_widgets/assets/designer_icons/ring_progress.png,sha256=klAmhZJOpFZOkI1fP1nk47Ug6uHXc1s_0y_vwmFMhjU,10358
32
32
  bec_widgets/assets/designer_icons/scan_control.png,sha256=WxdbBMCnGh1e_qsgPxccSDcR0hhUzUBiHtAjortzWh0,4392
@@ -47,7 +47,7 @@ bec_widgets/assets/toolbar_icons/attach_all.svg,sha256=AfnrIQ2zBkgpKdiIGY2NqJdhg
47
47
  bec_widgets/assets/toolbar_icons/auto_range.svg,sha256=vX_1qIl1dK6QEmEdp9OAw5SRcEugKvV_B5a2z8_jAtA,258
48
48
  bec_widgets/assets/toolbar_icons/compare.svg,sha256=se1AHEq0tpPueVLC05QsYXMiWbzff3sgUs_KUGXkmR0,351
49
49
  bec_widgets/assets/toolbar_icons/connection.svg,sha256=czIb1BnshmxJnER8ssU3WcLENrFSIUfMwberajWOGAk,341
50
- bec_widgets/assets/toolbar_icons/device_box.svg,sha256=cZC0vckMHsvwR1OSWzNqhG8h9CIJg6Q2Qy2wYDpzapY,266
50
+ bec_widgets/assets/toolbar_icons/device_line_edit.svg,sha256=XjEzYUIRlWc3aDM8FxvXm9RGOxRp2mZZzKnoWVLHctg,492
51
51
  bec_widgets/assets/toolbar_icons/drag_pan_mode.svg,sha256=ruinkJ0dVEPSH7ll4Pufl9c7oTwVXvcN57oTgiVRY5I,470
52
52
  bec_widgets/assets/toolbar_icons/export.svg,sha256=-kDEfxzloR1fOpZ5d4KIkxGH7wS_4Z1uJImtnKA5XxU,371
53
53
  bec_widgets/assets/toolbar_icons/fft.svg,sha256=fX31gulUsQTtpqbGbw4lpB1UwmIXh2LX2y4B2jPzyuo,2704
@@ -62,6 +62,7 @@ bec_widgets/assets/toolbar_icons/lock_aspect_ratio.svg,sha256=hq6YMySVWF01SeEXzp
62
62
  bec_widgets/assets/toolbar_icons/log_scale.png,sha256=pFYt9wn988rd-RHnyCuMw0WnIQY61UmEDvAHaiTs5dA,6453
63
63
  bec_widgets/assets/toolbar_icons/motor_map.svg,sha256=CRaoiALzdUByu6bTbJOg6czEzoI-1yRwcljlXUl4JNw,693
64
64
  bec_widgets/assets/toolbar_icons/photo_library.svg,sha256=weiDCYiHh9dzcA21D-37zpYts2CyoGAd9x-N_h292Mo,564
65
+ bec_widgets/assets/toolbar_icons/positioner_box.svg,sha256=cZC0vckMHsvwR1OSWzNqhG8h9CIJg6Q2Qy2wYDpzapY,266
65
66
  bec_widgets/assets/toolbar_icons/progress.svg,sha256=xcfcqNfhxVqmf2LbuVukuYxr1gS8kY57vCG1zDLO-rA,724
66
67
  bec_widgets/assets/toolbar_icons/queue.svg,sha256=yQuUkDo0tYT3tVqntPmiJD7YPK2bE5O8sj6GIKan3kA,248
67
68
  bec_widgets/assets/toolbar_icons/rectangle_mode.svg,sha256=N7AXB3da-RW8OpjLFeOUh1SDKVQ-9SWGPUjkryujyeE,946
@@ -81,7 +82,7 @@ bec_widgets/assets/toolbar_icons/transform.svg,sha256=Fgug9wCi1FONy08nssEvnoDDDB
81
82
  bec_widgets/assets/toolbar_icons/waveform.svg,sha256=darXWaIww4HEu9skFUd8Vs1NSAgUo1d37xBNr6DX-bM,231
82
83
  bec_widgets/cli/__init__.py,sha256=d0Q6Fn44e7wFfLabDOBxpcJ1DPKWlFunGYDUBmO-4hA,22
83
84
  bec_widgets/cli/auto_updates.py,sha256=DyBV3HnjMSH-cvVkYNcDiYKVf0Xut4Qy2qGQqkW47Bw,4833
84
- bec_widgets/cli/client.py,sha256=GqhR36UCp3ZSjzDdBlUCK4ud0RL6PRcPjv0GVuKJ1XQ,76054
85
+ bec_widgets/cli/client.py,sha256=3zXER7rSN5DfFO_-rkSrkHdERnPD5bnrk3WjxJE9EiI,75957
85
86
  bec_widgets/cli/client_utils.py,sha256=cDhabblwaP88a0jlVpbn_RWWKVbsyjhmmGtMh9gesEw,12388
86
87
  bec_widgets/cli/generate_cli.py,sha256=Ea5px9KblUlcGg-1JbJBTIU7laGg2n8PM7Efw9WVVzM,5889
87
88
  bec_widgets/cli/rpc_register.py,sha256=QxXUZu5XNg00Yf5O3UHWOXg3-f_pzKjjoZYMOa-MOJc,2216
@@ -152,12 +153,6 @@ bec_widgets/widgets/colormap_selector/colormap_selector.pyproject,sha256=lHl9qml
152
153
  bec_widgets/widgets/colormap_selector/colormap_selector_plugin.py,sha256=NWTldO9XMyyOVL0No-Bmr-tvWrinmU7LkDxB5LkIQtA,1416
153
154
  bec_widgets/widgets/colormap_selector/register_colormap_selector.py,sha256=bfw7RWmTmMLTLxGT-izSwcGtxGLKvL3jdivJw2z8oN4,512
154
155
  bec_widgets/widgets/console/console.py,sha256=NG0cBuqqPX4hC-sHhk_UEkT-nHhhN9Y7karJITPLzyo,17864
155
- bec_widgets/widgets/device_box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
- bec_widgets/widgets/device_box/device_box.py,sha256=2hWCbDaBvYnWK4-HDqeYetzb5KR4DBk7UPQJMLhT4w0,6929
157
- bec_widgets/widgets/device_box/device_box.pyproject,sha256=jtwvhaySJRdnuV99mEZT3htmWKVLphFeetEW4al7s-o,28
158
- bec_widgets/widgets/device_box/device_box.ui,sha256=z7j60J4ZKYjH9eyHl6FnZ_Z8lkdq1LQftxveSZQ6g_w,4865
159
- bec_widgets/widgets/device_box/device_box_plugin.py,sha256=ASTAEgBDKFERLT4IamuFHffe0pET6CgyjjPOD814q1A,1395
160
- bec_widgets/widgets/device_box/register_device_box.py,sha256=K7Hx4FIQDXasejaw6njwkFkkkwk63Smm6pHoOEdLWPw,467
161
156
  bec_widgets/widgets/device_combobox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
157
  bec_widgets/widgets/device_combobox/device_combo_box.pyproject,sha256=wI2eXR5ky_IM9-BCHJnH_9CEqYcZwIuLcgitSEr8OJU,40
163
158
  bec_widgets/widgets/device_combobox/device_combo_box_plugin.py,sha256=py1VYOpy0gTpdQ9eCut1dxMSfF0ckAwO5qT8ZDNkSts,1439
@@ -170,7 +165,7 @@ bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py,sha256=RPtGVPLad
170
165
  bec_widgets/widgets/device_line_edit/register_device_line_edit.py,sha256=8gEPnC8djYCw-idoZAENNB3bPOxM6pbzEp9A366EAGg,489
171
166
  bec_widgets/widgets/dock/__init__.py,sha256=B7foHt02gnhM7mFksa7GJVwT7n0j_JvYDCt6wc6XR5g,61
172
167
  bec_widgets/widgets/dock/dock.py,sha256=hQw5tpGrRbybjfF-aVEAeGdLTudtH4kFa70flu6_ZA8,10349
173
- bec_widgets/widgets/dock/dock_area.py,sha256=mHF8TPHnUl4x0ZWLQhgXF9Ca7uUBKD6ggMUIchjsisA,13559
168
+ bec_widgets/widgets/dock/dock_area.py,sha256=VfKyMxKo-r1Ugu2xjSsfGMYZUg3i3xxaokaZCFcCoxA,13579
174
169
  bec_widgets/widgets/dock/dock_area.pyproject,sha256=URW0UrDXCnkzk80rbQmUMgF6Uqay2TjHsq8Dq0g1j-c,37
175
170
  bec_widgets/widgets/dock/dock_area_plugin.py,sha256=oG2zDxUA1YLvSBoFVeFVkz4HIWLruAwOsCZ00H2Z70A,1345
176
171
  bec_widgets/widgets/dock/register_dock_area.py,sha256=Yqd1mq6CcHwlxHZxX5EHKONy4P44nMm8pso-4X0tvJI,464
@@ -209,6 +204,12 @@ bec_widgets/widgets/position_indicator/position_indicator.py,sha256=QVlWvs_RvEJe
209
204
  bec_widgets/widgets/position_indicator/position_indicator.pyproject,sha256=s0JEf5YkpMag19ddFSYeRZ8erBau7erO3bqw05YrTyg,36
210
205
  bec_widgets/widgets/position_indicator/position_indicator_plugin.py,sha256=xD8YyATYfpoHxGVcsecDKx9CLASAP6lKyypCEjRhNd0,1441
211
206
  bec_widgets/widgets/position_indicator/register_position_indicator.py,sha256=OZNiMgM_80TPSAXK_0hXAkne4vUh8DGvh_OdpOiMpwI,516
207
+ bec_widgets/widgets/positioner_box/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
208
+ bec_widgets/widgets/positioner_box/positioner_box.py,sha256=XeZragj6M1EreVQExFeqMkOCtEx2qAwDmSsMSnJS9u8,10753
209
+ bec_widgets/widgets/positioner_box/positioner_box.pyproject,sha256=7966pHdDseaHciaPNEKgdQgbUThSZf5wEDCeAEJh9po,32
210
+ bec_widgets/widgets/positioner_box/positioner_box.ui,sha256=Y-Xp0z32okT7X4-rL5r7dF_QH_QpXvPes3f778cC7_k,5633
211
+ bec_widgets/widgets/positioner_box/positioner_box_plugin.py,sha256=Q-FTqaxB78ShlhB56TtDMtllEb-USqWRw_s6gm0WUr0,1441
212
+ bec_widgets/widgets/positioner_box/register_positioner_box.py,sha256=UPOUjXXq6-IgSj0kdV_nJe1rYPMF8aIZxF4eSmWgQAg,483
212
213
  bec_widgets/widgets/ring_progress_bar/__init__.py,sha256=_uoJKnDM2YAeUBfwc5WLbIHSJj7zm_FAurSKP3WRaCw,47
213
214
  bec_widgets/widgets/ring_progress_bar/register_ring_progress_bar.py,sha256=uJrMhkuQi2PdWa0BwFJqjVXSkO-TXoyai4EQYOOe9t4,493
214
215
  bec_widgets/widgets/ring_progress_bar/ring.py,sha256=2pdEzETaJpvx4Dzyosq2YhnvDOEUvFnj_f9GfFKpG5Q,11159
@@ -315,8 +316,8 @@ docs/user/widgets/widgets.md,sha256=ZeRNmP7GUOu8kEoGu9XHsyF8Hb1foqZKEbwpgFP7ITk,
315
316
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
316
317
  tests/end-2-end/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
317
318
  tests/end-2-end/conftest.py,sha256=-BLnFE-NeCerf6xahGCkbZ4Ktactowi6RkBnboIzRvg,1767
318
- tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=hj06aUBGofq7yeFVoT3LB4NrCjc5FbOo5CGTvz7afpI,9118
319
- tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=73vuBbPJvkMR3w2jnQ7lk0z4-wN3HAmkLFDdv4BRPrM,6604
319
+ tests/end-2-end/test_bec_dock_rpc_e2e.py,sha256=FwbqHOlEcdimTiJaOJKfqHkOhqJY6R8Z9YNYnU8QCt4,9447
320
+ tests/end-2-end/test_bec_figure_rpc_e2e.py,sha256=_OTyZfkF0D9cvdwRhHNfNadCpZPWybOCryN6EUs7tXI,6804
320
321
  tests/end-2-end/test_rpc_register_e2e.py,sha256=blhMiW7HVHX1kGm5dg8Sv0PeCuJ0gnBz3evznQFz_B8,1619
321
322
  tests/end-2-end/test_scan_control_e2e.py,sha256=u7oLgFyltkMW2apSZKDukMIXvYrbhHrU32p4mBdn8VE,2276
322
323
  tests/references/SpinnerWidget/SpinnerWidget_darwin.png,sha256=-Tf5x0xY0pb-8sXH6Pk8cZL5PAxZ4vMR5RgyGCxisM4,9490
@@ -328,7 +329,7 @@ tests/unit_tests/client_mocks.py,sha256=4pS4KvvFGY9hjphds9i-GoIjVWVkax4XpDnVp6Mc
328
329
  tests/unit_tests/conftest.py,sha256=EE5RX_xR50ELJPgT2kny9rM1NCmCRO22sd_L9fvVSEk,1917
329
330
  tests/unit_tests/test_bec_connector.py,sha256=5uqBfjgMeOlGvqJlFbytxEpZ1El7_Y2q8fZHh4GvtD8,2478
330
331
  tests/unit_tests/test_bec_dispatcher.py,sha256=rYPiRizHaswhGZw55IBMneDFxmPiCCLAZQBqjEkpdyY,3992
331
- tests/unit_tests/test_bec_dock.py,sha256=oxOGzeHUmyxYI7eDOnvnhVeFNPRTlo8fjpHXMmPiS1s,5574
332
+ tests/unit_tests/test_bec_dock.py,sha256=iZcyF6tjNHstFx0rtbI8zhvFvgQiOpb_CuOF-L6Dipc,5610
332
333
  tests/unit_tests/test_bec_figure.py,sha256=oTlwHgDSrE4QRN3i9ZRM3QT2Xt8jfOyUTNxIZqZ4WKQ,9780
333
334
  tests/unit_tests/test_bec_image.py,sha256=Bc9eaLDk_9MfVFC6BZ-dymf-bQZg_CHL810nssXsj_k,2814
334
335
  tests/unit_tests/test_bec_image_widget.py,sha256=eU7uhKTQSf1Q5uV6EjsuUpf_oiMLNrZ1m10DjeQae0Y,7459
@@ -339,7 +340,6 @@ tests/unit_tests/test_client_utils.py,sha256=CBdWIVJ_UiyFzTJnX3XJm4PGw2uXhFvRCP_
339
340
  tests/unit_tests/test_color_map_selector.py,sha256=dTsizpT7TUpX2AEWIc0v09KPOryhWepFXFI9duQ3NF8,1497
340
341
  tests/unit_tests/test_color_validation.py,sha256=xbFbtFDia36XLgaNrX2IwvAX3IDC_Odpj5BGoJSgiIE,2389
341
342
  tests/unit_tests/test_crosshair.py,sha256=3OMAJ2ZaISYXMOtkXf1rPdy94vCr8njeLi6uHblBL9Q,5045
342
- tests/unit_tests/test_device_box.py,sha256=q9IVFpt1NF3TBF0Jhk-I-LRiuvvHG3FGUalw4jEYwVo,3431
343
343
  tests/unit_tests/test_device_input_base.py,sha256=LY-3adMb2xM9pBiP6V2bAJF_65csCe2Xfaq5ArVEE1E,2859
344
344
  tests/unit_tests/test_device_input_widgets.py,sha256=Y3mc_EaeQAPxpj6DijvxLLyMPSxnaNN86KhIL4ASO3E,5821
345
345
  tests/unit_tests/test_error_utils.py,sha256=LQOxz29WCGOe0qwFkaPDixjUmdnF3qeAGxD4A3t9IKg,2108
@@ -348,6 +348,7 @@ tests/unit_tests/test_generate_plugin.py,sha256=9603ucZChM-pYpHadzsR94U1Zec1KZT3
348
348
  tests/unit_tests/test_motor_map_widget.py,sha256=j3Vv_jNTsJTg6UgtwoxFp-Qwi_1blT9HK-USALPgxSI,7469
349
349
  tests/unit_tests/test_plot_base.py,sha256=evejmkYBBAu9f5XoA4dpYGPRGR5lIc3JqN4UQdGRY3Q,4134
350
350
  tests/unit_tests/test_plugin_utils.py,sha256=ayksWdrFY7kOiA0wVEjKFmFCF3UhH3lG8tzPVOpwysk,528
351
+ tests/unit_tests/test_positioner_box.py,sha256=Uc8d3rfgo74b-S53xglQr1HIXNBIKJIE5y5lkSSVZeg,3919
351
352
  tests/unit_tests/test_ring_progress_bar.py,sha256=Q-hbRPj44Oa3RLJayQGNUKTnsDllk6j4sJwyJdDudT4,12233
352
353
  tests/unit_tests/test_rpc_register.py,sha256=hECjZEimd440mwRrO0rg7L3PKN7__3DgjmESN6wx3bo,1179
353
354
  tests/unit_tests/test_rpc_server.py,sha256=MvstcvqUsnGAzUxw8Et1xXXikk_VIxFPwDZD0v1QGkg,1500
@@ -370,8 +371,8 @@ tests/unit_tests/test_configs/config_device_no_entry.yaml,sha256=hdvue9KLc_kfNzG
370
371
  tests/unit_tests/test_configs/config_scan.yaml,sha256=vo484BbWOjA_e-h6bTjSV9k7QaQHrlAvx-z8wtY-P4E,1915
371
372
  tests/unit_tests/test_msgs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
372
373
  tests/unit_tests/test_msgs/available_scans_message.py,sha256=m_z97hIrjHXXMa2Ex-UvsPmTxOYXfjxyJaGkIY6StTY,46532
373
- bec_widgets-0.93.3.dist-info/METADATA,sha256=_VblxDpuCc284m1SFf95vKgTaR-Jng60jurwZViD06c,1307
374
- bec_widgets-0.93.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
375
- bec_widgets-0.93.3.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
376
- bec_widgets-0.93.3.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
377
- bec_widgets-0.93.3.dist-info/RECORD,,
374
+ bec_widgets-0.93.5.dist-info/METADATA,sha256=h4oukmTNxTFeOKdXwV_rgzM7vsWlGaVuWvm91kRPwWk,1307
375
+ bec_widgets-0.93.5.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
376
+ bec_widgets-0.93.5.dist-info/entry_points.txt,sha256=3otEkCdDB9LZJuBLzG4pFLK5Di0CVybN_12IsZrQ-58,166
377
+ bec_widgets-0.93.5.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
378
+ bec_widgets-0.93.5.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "0.93.3"
7
+ version = "0.93.5"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -9,6 +9,10 @@ from bec_widgets.cli.auto_updates import AutoUpdates
9
9
  from bec_widgets.cli.client import BECDockArea, BECFigure, BECImageShow, BECMotorMap, BECWaveform
10
10
  from bec_widgets.utils import Colors
11
11
 
12
+ # pylint: disable=unused-argument
13
+ # pylint: disable=redefined-outer-name
14
+ # pylint: disable=too-many-locals
15
+
12
16
 
13
17
  def test_rpc_add_dock_with_figure_e2e(bec_client_lib, rpc_server_dock):
14
18
  # BEC client shortcuts
@@ -227,13 +231,20 @@ def test_ring_bar_scan_update(bec_client_lib, rpc_server_dock):
227
231
  assert bar_config["rings"][1]["max_value"] == final_samy
228
232
 
229
233
 
230
- def test_auto_update(bec_client_lib, rpc_server_dock):
234
+ def test_auto_update(bec_client_lib, rpc_server_dock, qtbot):
231
235
  dock = BECDockArea(rpc_server_dock)
232
236
 
233
237
  AutoUpdates.enabled = True
234
238
  AutoUpdates.create_default_dock = True
235
239
  dock.auto_updates = AutoUpdates(gui=dock)
236
240
  dock.auto_updates.start_default_dock()
241
+
242
+ def get_default_figure():
243
+ return dock.auto_updates.get_default_figure()
244
+
245
+ qtbot.waitUntil(lambda: get_default_figure() is not None, timeout=10000)
246
+ plt = get_default_figure()
247
+
237
248
  dock.selected_device = "bpm4i"
238
249
 
239
250
  # we need to start the update script manually; normally this is done when the GUI is started
@@ -250,7 +261,6 @@ def test_auto_update(bec_client_lib, rpc_server_dock):
250
261
  last_scan_data = queue.scan_storage.storage[-1].data
251
262
 
252
263
  # get data from curves
253
- plt = dock.auto_updates.get_default_figure()
254
264
  widgets = plt.widget_list
255
265
  plt_data = widgets[0].get_all_data()
256
266
 
@@ -271,6 +281,7 @@ def test_auto_update(bec_client_lib, rpc_server_dock):
271
281
 
272
282
  plt = dock.auto_updates.get_default_figure()
273
283
  widgets = plt.widget_list
284
+ qtbot.waitUntil(lambda: len(plt.widget_list) > 0, timeout=5000)
274
285
  plt_data = widgets[0].get_all_data()
275
286
 
276
287
  last_scan_data = queue.scan_storage.storage[-1].data
@@ -158,7 +158,7 @@ def test_rpc_motor_map(rpc_server_figure, bec_client_lib):
158
158
  )
159
159
 
160
160
 
161
- def test_dap_rpc(rpc_server_figure, bec_client_lib):
161
+ def test_dap_rpc(rpc_server_figure, bec_client_lib, qtbot):
162
162
 
163
163
  fig = BECFigure(rpc_server_figure)
164
164
  plt = fig.plot(x_name="samx", y_name="bpm4i", dap="GaussianModel")
@@ -178,13 +178,15 @@ def test_dap_rpc(rpc_server_figure, bec_client_lib):
178
178
  res = scans.line_scan(dev.samx, 0, 8, steps=50, relative=False)
179
179
  res.wait()
180
180
 
181
- time.sleep(2)
181
+ # especially on slow machines, the fit might not be done yet
182
+ # so we wait until the fit reaches the expected value
183
+ def wait_for_fit():
184
+ dap_curve = plt.get_curve("bpm4i-bpm4i-GaussianModel")
185
+ fit_params = dap_curve.dap_params
186
+ print(fit_params)
187
+ return np.isclose(fit_params["center"], 5, atol=0.5)
182
188
 
183
- dap_curve = plt.get_curve("bpm4i-bpm4i-GaussianModel")
184
- fit_params = dap_curve.dap_params
185
- print(fit_params)
186
-
187
- assert np.isclose(fit_params["center"], 5, atol=0.5)
189
+ qtbot.waitUntil(wait_for_fit, timeout=10000)
188
190
 
189
191
 
190
192
  def test_removing_subplots(rpc_server_figure, bec_client_lib):
@@ -127,10 +127,12 @@ def test_toolbar_add_plot_motor_map(bec_dock_area):
127
127
  assert bec_dock_area.panels["motor_map_1"].widgets[0].config.widget_class == "BECMotorMapWidget"
128
128
 
129
129
 
130
- def test_toolbar_add_device_device_box(bec_dock_area):
131
- bec_dock_area.toolbar.widgets["menu_devices"].widgets["device_box"].trigger()
132
- assert "device_box_1" in bec_dock_area.panels
133
- assert bec_dock_area.panels["device_box_1"].widgets[0].config.widget_class == "DeviceBox"
130
+ def test_toolbar_add_device_positioner_box(bec_dock_area):
131
+ bec_dock_area.toolbar.widgets["menu_devices"].widgets["positioner_box"].trigger()
132
+ assert "positioner_box_1" in bec_dock_area.panels
133
+ assert (
134
+ bec_dock_area.panels["positioner_box_1"].widgets[0].config.widget_class == "PositionerBox"
135
+ )
134
136
 
135
137
 
136
138
  def test_toolbar_add_utils_queue(bec_dock_area):
@@ -0,0 +1,104 @@
1
+ from unittest import mock
2
+
3
+ import pytest
4
+ from bec_lib.device import Positioner
5
+ from bec_lib.endpoints import MessageEndpoints
6
+ from bec_lib.messages import ScanQueueMessage
7
+ from qtpy.QtGui import QValidator
8
+
9
+ from bec_widgets.widgets.positioner_box.positioner_box import PositionerBox
10
+
11
+ from .client_mocks import mocked_client
12
+
13
+
14
+ @pytest.fixture
15
+ def positioner_box(qtbot, mocked_client):
16
+ with mock.patch("bec_widgets.widgets.positioner_box.positioner_box.uuid.uuid4") as mock_uuid:
17
+ mock_uuid.return_value = "fake_uuid"
18
+ with mock.patch(
19
+ "bec_widgets.widgets.positioner_box.positioner_box.PositionerBox._check_device_is_valid",
20
+ return_value=True,
21
+ ):
22
+ db = PositionerBox(device="samx", client=mocked_client)
23
+ qtbot.addWidget(db)
24
+ yield db
25
+
26
+
27
+ def test_positioner_box(positioner_box):
28
+ assert positioner_box.device == "samx"
29
+ data = positioner_box.dev["samx"].read()
30
+ # Avoid check for Positioner class from BEC in _init_device
31
+
32
+ setpoint_text = positioner_box.ui.setpoint.text()
33
+ # check that the setpoint is taken correctly after init
34
+ assert float(setpoint_text) == data["samx_setpoint"]["value"]
35
+
36
+ # check that the precision is taken correctly after isnit
37
+ precision = positioner_box.dev["samx"].precision
38
+ assert setpoint_text == f"{data['samx_setpoint']['value']:.{precision}f}"
39
+
40
+ # check that the step size is set according to the device precision
41
+ assert positioner_box.ui.step_size.value() == 10**-precision * 10
42
+
43
+
44
+ def test_positioner_box_update_limits(positioner_box):
45
+ positioner_box._limits = None
46
+ positioner_box.update_limits([0, 10])
47
+ assert positioner_box._limits == [0, 10]
48
+ assert positioner_box.setpoint_validator.bottom() == 0
49
+ assert positioner_box.setpoint_validator.top() == 10
50
+ assert positioner_box.setpoint_validator.validate("100", 0) == (
51
+ QValidator.State.Intermediate,
52
+ "100",
53
+ 0,
54
+ )
55
+
56
+ positioner_box.update_limits(None)
57
+ assert positioner_box._limits is None
58
+ assert positioner_box.setpoint_validator.validate("100", 0) == (
59
+ QValidator.State.Acceptable,
60
+ "100",
61
+ 0,
62
+ )
63
+
64
+
65
+ def test_positioner_box_on_stop(positioner_box):
66
+ with mock.patch.object(positioner_box.client.connector, "send") as mock_send:
67
+ positioner_box.on_stop()
68
+ params = {"device": "samx", "rpc_id": "fake_uuid", "func": "stop", "args": [], "kwargs": {}}
69
+ msg = ScanQueueMessage(
70
+ scan_type="device_rpc",
71
+ parameter=params,
72
+ queue="emergency",
73
+ metadata={"RID": "fake_uuid", "response": False},
74
+ )
75
+ mock_send.assert_called_once_with(MessageEndpoints.scan_queue_request(), msg)
76
+
77
+
78
+ def test_positioner_box_setpoint_change(positioner_box):
79
+ with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
80
+ positioner_box.ui.setpoint.setText("100")
81
+ positioner_box.on_setpoint_change()
82
+ mock_move.assert_called_once_with(100, relative=False)
83
+
84
+
85
+ def test_positioner_box_on_tweak_right(positioner_box):
86
+ with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
87
+ positioner_box.ui.step_size.setValue(0.1)
88
+ positioner_box.on_tweak_right()
89
+ mock_move.assert_called_once_with(0.1, relative=True)
90
+
91
+
92
+ def test_positioner_box_on_tweak_left(positioner_box):
93
+ with mock.patch.object(positioner_box.dev["samx"], "move") as mock_move:
94
+ positioner_box.ui.step_size.setValue(0.1)
95
+ positioner_box.on_tweak_left()
96
+ mock_move.assert_called_once_with(-0.1, relative=True)
97
+
98
+
99
+ def test_positioner_box_setpoint_out_of_range(positioner_box):
100
+ positioner_box.update_limits([0, 10])
101
+ positioner_box.ui.setpoint.setText("100")
102
+ positioner_box.on_setpoint_change()
103
+ assert positioner_box.ui.setpoint.text() == "100"
104
+ assert positioner_box.ui.setpoint.hasAcceptableInput() == False
@@ -1 +0,0 @@
1
- {'files': ['device_box.py']}
@@ -1,98 +0,0 @@
1
- from unittest import mock
2
-
3
- import pytest
4
- from bec_lib.endpoints import MessageEndpoints
5
- from bec_lib.messages import ScanQueueMessage
6
- from qtpy.QtGui import QValidator
7
-
8
- from bec_widgets.widgets.device_box.device_box import DeviceBox
9
-
10
- from .client_mocks import mocked_client
11
-
12
-
13
- @pytest.fixture
14
- def device_box(qtbot, mocked_client):
15
- with mock.patch("bec_widgets.widgets.device_box.device_box.uuid.uuid4") as mock_uuid:
16
- mock_uuid.return_value = "fake_uuid"
17
- db = DeviceBox(device="samx", client=mocked_client)
18
- qtbot.addWidget(db)
19
- yield db
20
-
21
-
22
- def test_device_box(device_box):
23
- assert device_box.device == "samx"
24
- data = device_box.dev["samx"].read()
25
-
26
- setpoint_text = device_box.ui.setpoint.text()
27
- # check that the setpoint is taken correctly after init
28
- assert float(setpoint_text) == data["samx_setpoint"]["value"]
29
-
30
- # check that the precision is taken correctly after init
31
- precision = device_box.dev["samx"].precision
32
- assert setpoint_text == f"{data['samx_setpoint']['value']:.{precision}f}"
33
-
34
- # check that the step size is set according to the device precision
35
- assert device_box.ui.step_size.value() == 10**-precision * 10
36
-
37
-
38
- def test_device_box_update_limits(device_box):
39
- device_box._limits = None
40
- device_box.update_limits([0, 10])
41
- assert device_box._limits == [0, 10]
42
- assert device_box.setpoint_validator.bottom() == 0
43
- assert device_box.setpoint_validator.top() == 10
44
- assert device_box.setpoint_validator.validate("100", 0) == (
45
- QValidator.State.Intermediate,
46
- "100",
47
- 0,
48
- )
49
-
50
- device_box.update_limits(None)
51
- assert device_box._limits is None
52
- assert device_box.setpoint_validator.validate("100", 0) == (
53
- QValidator.State.Acceptable,
54
- "100",
55
- 0,
56
- )
57
-
58
-
59
- def test_device_box_on_stop(device_box):
60
- with mock.patch.object(device_box.client.connector, "send") as mock_send:
61
- device_box.on_stop()
62
- params = {"device": "samx", "rpc_id": "fake_uuid", "func": "stop", "args": [], "kwargs": {}}
63
- msg = ScanQueueMessage(
64
- scan_type="device_rpc",
65
- parameter=params,
66
- queue="emergency",
67
- metadata={"RID": "fake_uuid", "response": False},
68
- )
69
- mock_send.assert_called_once_with(MessageEndpoints.scan_queue_request(), msg)
70
-
71
-
72
- def test_device_box_setpoint_change(device_box):
73
- with mock.patch.object(device_box.dev["samx"], "move") as mock_move:
74
- device_box.ui.setpoint.setText("100")
75
- device_box.on_setpoint_change()
76
- mock_move.assert_called_once_with(100, relative=False)
77
-
78
-
79
- def test_device_box_on_tweak_right(device_box):
80
- with mock.patch.object(device_box.dev["samx"], "move") as mock_move:
81
- device_box.ui.step_size.setValue(0.1)
82
- device_box.on_tweak_right()
83
- mock_move.assert_called_once_with(0.1, relative=True)
84
-
85
-
86
- def test_device_box_on_tweak_left(device_box):
87
- with mock.patch.object(device_box.dev["samx"], "move") as mock_move:
88
- device_box.ui.step_size.setValue(0.1)
89
- device_box.on_tweak_left()
90
- mock_move.assert_called_once_with(-0.1, relative=True)
91
-
92
-
93
- def test_device_box_setpoint_out_of_range(device_box):
94
- device_box.update_limits([0, 10])
95
- device_box.ui.setpoint.setText("100")
96
- device_box.on_setpoint_change()
97
- assert device_box.ui.setpoint.text() == "100"
98
- assert device_box.ui.setpoint.hasAcceptableInput() == False