bec-widgets 2.12.2__py3-none-any.whl → 2.12.4__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.
@@ -0,0 +1,15 @@
1
+ name: 'Close stale issues and PRs'
2
+ on:
3
+ schedule:
4
+ - cron: '00 10 * * *'
5
+
6
+ jobs:
7
+ stale:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/stale@v9
11
+ with:
12
+ stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
13
+ stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
14
+ days-before-stale: 60
15
+ days-before-close: 7
CHANGELOG.md CHANGED
@@ -1,6 +1,39 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v2.12.4 (2025-06-10)
5
+
6
+ ### Bug Fixes
7
+
8
+ - **image_roi**: Coordinates are emitted correctly when handles are inverted; closes #672
9
+ ([`9ef418b`](https://github.com/bec-project/bec_widgets/commit/9ef418bf5597d4be77adc3c0c88c1c1619c9aa2f))
10
+
11
+ ### Continuous Integration
12
+
13
+ - Add stale issue job
14
+ ([`b3ce680`](https://github.com/bec-project/bec_widgets/commit/b3ce68070d58cdd76559cbd7db04cdbcc6c1f075))
15
+
16
+
17
+ ## v2.12.3 (2025-06-05)
18
+
19
+ ### Bug Fixes
20
+
21
+ - **crosshair**: Use objectName instead of config for retrieving the monitor name
22
+ ([`edfac87`](https://github.com/bec-project/bec_widgets/commit/edfac87868605b4b755f7732b2841673de53bc3f))
23
+
24
+ - **device_combobox**: Tuple entries of preview signals are checked in DeviceComboBoxes just for the
25
+ relevant device
26
+ ([`12f5233`](https://github.com/bec-project/bec_widgets/commit/12f523374586d55499f80baf56a50b6ef486cd43))
27
+
28
+ - **image**: Preview signals can be used in Image widget; update logic adjusted; closes #683
29
+ ([`2711164`](https://github.com/bec-project/bec_widgets/commit/271116453d1ef5316b19457d04613b6ddc939cdb))
30
+
31
+ ### Build System
32
+
33
+ - Update min dependency of bec to 3.38
34
+ ([`3740ac8`](https://github.com/bec-project/bec_widgets/commit/3740ac8e325a489d59faca648896ffcea29e1a02))
35
+
36
+
4
37
  ## v2.12.2 (2025-06-05)
5
38
 
6
39
  ### Bug Fixes
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bec_widgets
3
- Version: 2.12.2
3
+ Version: 2.12.4
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
@@ -9,8 +9,8 @@ Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Topic :: Scientific/Engineering
11
11
  Requires-Python: >=3.10
12
- Requires-Dist: bec-ipython-client<=4.0,>=2.21.4
13
- Requires-Dist: bec-lib<=4.0,>=3.29
12
+ Requires-Dist: bec-ipython-client<=4.0,>=3.38
13
+ Requires-Dist: bec-lib<=4.0,>=3.38
14
14
  Requires-Dist: bec-qthemes>=0.7,~=0.7
15
15
  Requires-Dist: black~=25.0
16
16
  Requires-Dist: isort>=5.13.2,~=5.13
bec_widgets/cli/client.py CHANGED
@@ -1459,12 +1459,12 @@ class Image(RPCBase):
1459
1459
  @rpc_call
1460
1460
  def image(
1461
1461
  self,
1462
- monitor: "str | None" = None,
1462
+ monitor: "str | tuple | None" = None,
1463
1463
  monitor_type: "Literal['auto', '1d', '2d']" = "auto",
1464
1464
  color_map: "str | None" = None,
1465
1465
  color_bar: "Literal['simple', 'full'] | None" = None,
1466
1466
  vrange: "tuple[int, int] | None" = None,
1467
- ) -> "ImageItem":
1467
+ ) -> "ImageItem | None":
1468
1468
  """
1469
1469
  Set the image source and update the image.
1470
1470
 
@@ -458,7 +458,7 @@ class Crosshair(QObject):
458
458
  )
459
459
  self.coordinatesClicked1D.emit(coordinate_to_emit)
460
460
  elif isinstance(item, pg.ImageItem):
461
- name = item.config.monitor or str(id(item))
461
+ name = item.objectName() or str(id(item))
462
462
  x, y = x_snap_values[name], y_snap_values[name]
463
463
  if x is None or y is None:
464
464
  continue
@@ -149,6 +149,25 @@ class DeviceComboBox(DeviceInputBase, QComboBox):
149
149
  self._is_valid_input = False
150
150
  self.update()
151
151
 
152
+ def validate_device(self, device: str) -> bool: # type: ignore[override]
153
+ """
154
+ Extend validation so that preview‑signal pseudo‑devices (labels like
155
+ ``"eiger_preview"``) are accepted as valid choices.
156
+
157
+ The validation run only on device not on the preview‑signal.
158
+
159
+ Args:
160
+ device: The text currently entered/selected.
161
+
162
+ Returns:
163
+ True if the device is a genuine BEC device *or* one of the
164
+ whitelisted preview‑signal entries.
165
+ """
166
+ idx = self.findText(device)
167
+ if idx >= 0 and isinstance(self.itemData(idx), tuple):
168
+ device = self.itemData(idx)[0] # type: ignore[assignment]
169
+ return super().validate_device(device)
170
+
152
171
 
153
172
  if __name__ == "__main__": # pragma: no cover
154
173
  # pylint: disable=import-outside-toplevel
@@ -35,7 +35,7 @@ class ImageConfig(ConnectionConfig):
35
35
 
36
36
 
37
37
  class ImageLayerConfig(BaseModel):
38
- monitor: str | None = Field(None, description="The name of the monitor.")
38
+ monitor: str | tuple | None = Field(None, description="The name of the monitor.")
39
39
  monitor_type: Literal["1d", "2d", "auto"] = Field("auto", description="The type of monitor.")
40
40
  source: Literal["device_monitor_1d", "device_monitor_2d", "auto"] = Field(
41
41
  "auto", description="The source of the image data."
@@ -179,12 +179,12 @@ class Image(ImageBase):
179
179
  @SafeSlot(popup_error=True)
180
180
  def image(
181
181
  self,
182
- monitor: str | None = None,
182
+ monitor: str | tuple | None = None,
183
183
  monitor_type: Literal["auto", "1d", "2d"] = "auto",
184
184
  color_map: str | None = None,
185
185
  color_bar: Literal["simple", "full"] | None = None,
186
186
  vrange: tuple[int, int] | None = None,
187
- ) -> ImageItem:
187
+ ) -> ImageItem | None:
188
188
  """
189
189
  Set the image source and update the image.
190
190
 
@@ -201,21 +201,13 @@ class Image(ImageBase):
201
201
 
202
202
  if self.subscriptions["main"].monitor:
203
203
  self.disconnect_monitor(self.subscriptions["main"].monitor)
204
- self.entry_validator.validate_monitor(monitor)
205
- self.subscriptions["main"].monitor = monitor
206
-
207
- if monitor_type == "1d":
208
- self.subscriptions["main"].source = "device_monitor_1d"
209
- self.subscriptions["main"].monitor_type = "1d"
210
- elif monitor_type == "2d":
211
- self.subscriptions["main"].source = "device_monitor_2d"
212
- self.subscriptions["main"].monitor_type = "2d"
213
- elif monitor_type == "auto":
214
- self.subscriptions["main"].source = "auto"
215
- logger.warning(
216
- f"Updates for '{monitor}' will be fetch from both 1D and 2D monitor endpoints."
217
- )
218
- self.subscriptions["main"].monitor_type = "auto"
204
+ if monitor is None or monitor == "":
205
+ logger.warning(f"No monitor specified, cannot set image, old monitor is unsubscribed")
206
+ return None
207
+ if isinstance(monitor, tuple):
208
+ self.entry_validator.validate_monitor(monitor[0])
209
+ else:
210
+ self.entry_validator.validate_monitor(monitor)
219
211
 
220
212
  self.set_image_update(monitor=monitor, type=monitor_type)
221
213
  if color_map is not None:
@@ -240,7 +232,12 @@ class Image(ImageBase):
240
232
  self.selection_bundle.dim_combo_box,
241
233
  ):
242
234
  combo.blockSignals(True)
243
- self.selection_bundle.device_combo_box.set_device(config.monitor)
235
+ if isinstance(config.monitor, tuple):
236
+ self.selection_bundle.device_combo_box.setCurrentText(
237
+ f"{config.monitor[0]}_{config.monitor[1]}"
238
+ )
239
+ else:
240
+ self.selection_bundle.device_combo_box.setCurrentText(config.monitor)
244
241
  self.selection_bundle.dim_combo_box.setCurrentText(config.monitor_type)
245
242
  for combo in (
246
243
  self.selection_bundle.device_combo_box,
@@ -340,7 +337,8 @@ class Image(ImageBase):
340
337
  ########################################
341
338
  # Connections
342
339
 
343
- def set_image_update(self, monitor: str, type: Literal["1d", "2d", "auto"]):
340
+ @SafeSlot()
341
+ def set_image_update(self, monitor: str | tuple, type: Literal["1d", "2d", "auto"]):
344
342
  """
345
343
  Set the image update method for the given monitor.
346
344
 
@@ -350,37 +348,95 @@ class Image(ImageBase):
350
348
  """
351
349
 
352
350
  # TODO consider moving connecting and disconnecting logic to Image itself if multiple images
353
- if type == "1d":
354
- self.bec_dispatcher.connect_slot(
355
- self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
356
- )
357
- elif type == "2d":
358
- self.bec_dispatcher.connect_slot(
359
- self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
360
- )
361
- elif type == "auto":
362
- self.bec_dispatcher.connect_slot(
363
- self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
364
- )
365
- self.bec_dispatcher.connect_slot(
366
- self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
367
- )
351
+ if isinstance(monitor, tuple):
352
+ device = self.dev[monitor[0]]
353
+ signal = monitor[1]
354
+ if len(monitor) == 3:
355
+ signal_config = monitor[2]
356
+ else:
357
+ signal_config = device._info["signals"][signal]
358
+ signal_class = signal_config.get("signal_class", None)
359
+ if signal_class != "PreviewSignal":
360
+ logger.warning(f"Signal '{monitor}' is not a PreviewSignal.")
361
+ return
362
+
363
+ ndim = signal_config.get("describe", None).get("signal_info", None).get("ndim", None)
364
+ if ndim is None:
365
+ logger.warning(
366
+ f"Signal '{monitor}' does not have a valid 'ndim' in its signal_info."
367
+ )
368
+ return
369
+
370
+ if ndim == 1:
371
+ self.bec_dispatcher.connect_slot(
372
+ self.on_image_update_1d, MessageEndpoints.device_preview(device.name, signal)
373
+ )
374
+ self.subscriptions["main"].source = "device_monitor_1d"
375
+ self.subscriptions["main"].monitor_type = "1d"
376
+ elif ndim == 2:
377
+ self.bec_dispatcher.connect_slot(
378
+ self.on_image_update_2d, MessageEndpoints.device_preview(device.name, signal)
379
+ )
380
+ self.subscriptions["main"].source = "device_monitor_2d"
381
+ self.subscriptions["main"].monitor_type = "2d"
382
+
383
+ else: # FIXME old monitor 1d/2d endpoint handling, present for backwards compatibility, will be removed in future versions
384
+ if type == "1d":
385
+ self.bec_dispatcher.connect_slot(
386
+ self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
387
+ )
388
+ self.subscriptions["main"].source = "device_monitor_1d"
389
+ self.subscriptions["main"].monitor_type = "1d"
390
+ elif type == "2d":
391
+ self.bec_dispatcher.connect_slot(
392
+ self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
393
+ )
394
+ self.subscriptions["main"].source = "device_monitor_2d"
395
+ self.subscriptions["main"].monitor_type = "2d"
396
+ elif type == "auto":
397
+ self.bec_dispatcher.connect_slot(
398
+ self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
399
+ )
400
+ self.bec_dispatcher.connect_slot(
401
+ self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
402
+ )
403
+ self.subscriptions["main"].source = "auto"
404
+ logger.warning(
405
+ f"Updates for '{monitor}' will be fetch from both 1D and 2D monitor endpoints."
406
+ )
407
+ self.subscriptions["main"].monitor_type = "auto"
408
+
368
409
  logger.info(f"Connected to {monitor} with type {type}")
369
410
  self.subscriptions["main"].monitor = monitor
370
411
 
371
- def disconnect_monitor(self, monitor: str):
412
+ def disconnect_monitor(self, monitor: str | tuple):
372
413
  """
373
414
  Disconnect the monitor from the image update signals, both 1D and 2D.
374
415
 
375
416
  Args:
376
- monitor(str): The name of the monitor to disconnect.
377
- """
378
- self.bec_dispatcher.disconnect_slot(
379
- self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
380
- )
381
- self.bec_dispatcher.disconnect_slot(
382
- self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
383
- )
417
+ monitor(str|tuple): The name of the monitor to disconnect, or a tuple of (device, signal) for preview signals.
418
+ """
419
+ if isinstance(monitor, tuple):
420
+ if self.subscriptions["main"].source == "device_monitor_1d":
421
+ self.bec_dispatcher.disconnect_slot(
422
+ self.on_image_update_1d, MessageEndpoints.device_preview(monitor[0], monitor[1])
423
+ )
424
+ elif self.subscriptions["main"].source == "device_monitor_2d":
425
+ self.bec_dispatcher.disconnect_slot(
426
+ self.on_image_update_2d, MessageEndpoints.device_preview(monitor[0], monitor[1])
427
+ )
428
+ else:
429
+ logger.warning(
430
+ f"Cannot disconnect monitor {monitor} with source {self.subscriptions['main'].source}"
431
+ )
432
+ return
433
+ else: # FIXME old monitor 1d/2d endpoint handling, present for backwards compatibility, will be removed in future versions
434
+ self.bec_dispatcher.disconnect_slot(
435
+ self.on_image_update_1d, MessageEndpoints.device_monitor_1d(monitor)
436
+ )
437
+ self.bec_dispatcher.disconnect_slot(
438
+ self.on_image_update_2d, MessageEndpoints.device_monitor_2d(monitor)
439
+ )
384
440
  self.subscriptions["main"].monitor = None
385
441
  self._sync_device_selection()
386
442
 
@@ -1,5 +1,5 @@
1
1
  from bec_lib.device import ReadoutPriority
2
- from qtpy.QtCore import Qt
2
+ from qtpy.QtCore import Qt, QTimer
3
3
  from qtpy.QtWidgets import QComboBox, QStyledItemDelegate
4
4
 
5
5
  from bec_widgets.utils.error_popups import SafeSlot
@@ -50,11 +50,58 @@ class MonitorSelectionToolbarBundle(ToolbarBundle):
50
50
 
51
51
  self.add_action("dim_combo", WidgetAction(widget=self.dim_combo_box, adjust_size=False))
52
52
 
53
- # Connect slots, a device will be connected upon change of any combobox
54
- self.device_combo_box.currentTextChanged.connect(lambda: self.connect_monitor())
55
- self.dim_combo_box.currentTextChanged.connect(lambda: self.connect_monitor())
53
+ self.device_combo_box.currentTextChanged.connect(self.connect_monitor)
54
+ self.dim_combo_box.currentTextChanged.connect(self.connect_monitor)
55
+
56
+ QTimer.singleShot(0, self._adjust_and_connect)
57
+
58
+ def _adjust_and_connect(self):
59
+ """
60
+ Adjust the size of the device combo box and populate it with preview signals.
61
+ Has to be done with QTimer.singleShot to ensure the UI is fully initialized, needed for testing.
62
+ """
63
+ self._populate_preview_signals()
64
+ self._reverse_device_items()
65
+ self.device_combo_box.setCurrentText("") # set again default to empty string
66
+
67
+ def _populate_preview_signals(self) -> None:
68
+ """
69
+ Populate the device combo box with preview‑signal devices in the
70
+ format '<device>_<signal>' and store the tuple(device, signal) in
71
+ the item's userData for later use.
72
+ """
73
+ preview_signals = self.target_widget.client.device_manager.get_bec_signals("PreviewSignal")
74
+ for device, signal, signal_config in preview_signals:
75
+ label = signal_config.get("obj_name", f"{device}_{signal}")
76
+ self.device_combo_box.addItem(label, (device, signal, signal_config))
77
+
78
+ def _reverse_device_items(self) -> None:
79
+ """
80
+ Reverse the current order of items in the device combo box while
81
+ keeping their userData and restoring the previous selection.
82
+ """
83
+ current_text = self.device_combo_box.currentText()
84
+ items = [
85
+ (self.device_combo_box.itemText(i), self.device_combo_box.itemData(i))
86
+ for i in range(self.device_combo_box.count())
87
+ ]
88
+ self.device_combo_box.clear()
89
+ for text, data in reversed(items):
90
+ self.device_combo_box.addItem(text, data)
91
+ if current_text:
92
+ self.device_combo_box.setCurrentText(current_text)
56
93
 
57
94
  @SafeSlot()
58
- def connect_monitor(self):
95
+ def connect_monitor(self, *args, **kwargs):
96
+ """
97
+ Connect the target widget to the selected monitor based on the current device and dimension.
98
+
99
+ If the selected device is a preview-signal device, it will use the tuple (device, signal) as the monitor.
100
+ """
59
101
  dim = self.dim_combo_box.currentText()
60
- self.target_widget.image(monitor=self.device_combo_box.currentText(), monitor_type=dim)
102
+ data = self.device_combo_box.currentData()
103
+
104
+ if isinstance(data, tuple):
105
+ self.target_widget.image(monitor=data, monitor_type="auto")
106
+ else:
107
+ self.target_widget.image(monitor=self.device_combo_box.currentText(), monitor_type=dim)
@@ -437,6 +437,23 @@ class RectangularROI(BaseROI, pg.RectROI):
437
437
  self.hoverPen = fn.mkPen(color=(255, 0, 0), width=3, style=QtCore.Qt.DashLine)
438
438
  self.handleHoverPen = fn.mkPen("lime", width=4)
439
439
 
440
+ def _normalized_edges(self) -> tuple[float, float, float, float]:
441
+ """
442
+ Return rectangle edges as (left, bottom, right, top) with consistent
443
+ ordering even when the ROI has been inverted by its scale handles.
444
+
445
+ Returns:
446
+ tuple: A tuple containing the left, bottom, right, and top edges
447
+ of the ROI rectangle in normalized coordinates.
448
+ """
449
+ x0, y0 = self.pos().x(), self.pos().y()
450
+ w, h = self.state["size"]
451
+ x_left = min(x0, x0 + w)
452
+ x_right = max(x0, x0 + w)
453
+ y_bottom = min(y0, y0 + h)
454
+ y_top = max(y0, y0 + h)
455
+ return x_left, y_bottom, x_right, y_top
456
+
440
457
  def add_scale_handle(self):
441
458
  """
442
459
  Add scale handles at every corner and edge of the ROI.
@@ -465,17 +482,15 @@ class RectangularROI(BaseROI, pg.RectROI):
465
482
 
466
483
  def _on_region_changed(self):
467
484
  """
468
- Handles ROI region change events.
485
+ Handles changes to the ROI's region.
469
486
 
470
487
  This method is called whenever the ROI's position or size changes.
471
488
  It calculates the new corner coordinates and emits the edgesChanged signal
472
489
  with the updated coordinates.
473
490
  """
474
- x0, y0 = self.pos().x(), self.pos().y()
475
- w, h = self.state["size"]
476
- self.edgesChanged.emit(x0, y0, x0 + w, y0 + h)
477
- viewBox = self.parent_plot_item.vb
478
- viewBox.update()
491
+ x_left, y_bottom, x_right, y_top = self._normalized_edges()
492
+ self.edgesChanged.emit(x_left, y_bottom, x_right, y_top)
493
+ self.parent_plot_item.vb.update()
479
494
 
480
495
  def mouseDragEvent(self, ev):
481
496
  """
@@ -489,9 +504,8 @@ class RectangularROI(BaseROI, pg.RectROI):
489
504
  """
490
505
  super().mouseDragEvent(ev)
491
506
  if ev.isFinish():
492
- x0, y0 = self.pos().x(), self.pos().y()
493
- w, h = self.state["size"]
494
- self.edgesReleased.emit(x0, y0, x0 + w, y0 + h)
507
+ x_left, y_bottom, x_right, y_top = self._normalized_edges()
508
+ self.edgesReleased.emit(x_left, y_bottom, x_right, y_top)
495
509
 
496
510
  def get_coordinates(self, typed: bool | None = None) -> dict | tuple:
497
511
  """
@@ -510,17 +524,16 @@ class RectangularROI(BaseROI, pg.RectROI):
510
524
  if typed is None:
511
525
  typed = self.description
512
526
 
513
- x0, y0 = self.pos().x(), self.pos().y()
514
- w, h = self.state["size"]
515
- x1, y1 = x0 + w, y0 + h
527
+ x_left, y_bottom, x_right, y_top = self._normalized_edges()
528
+
516
529
  if typed:
517
530
  return {
518
- "bottom_left": (x0, y0),
519
- "bottom_right": (x1, y0),
520
- "top_left": (x0, y1),
521
- "top_right": (x1, y1),
531
+ "bottom_left": (x_left, y_bottom),
532
+ "bottom_right": (x_right, y_bottom),
533
+ "top_left": (x_left, y_top),
534
+ "top_right": (x_right, y_top),
522
535
  }
523
- return ((x0, y0), (x1, y0), (x0, y1), (x1, y1))
536
+ return (x_left, y_bottom), (x_right, y_bottom), (x_left, y_top), (x_right, y_top)
524
537
 
525
538
  def _lookup_scene_image(self):
526
539
  """
@@ -654,7 +667,7 @@ class CircularROI(BaseROI, pg.CircleROI):
654
667
  if typed is None:
655
668
  typed = self.description
656
669
 
657
- d = self.state["size"][0]
670
+ d = abs(self.state["size"][0])
658
671
  cx = self.pos().x() + d / 2
659
672
  cy = self.pos().y() + d / 2
660
673
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bec_widgets
3
- Version: 2.12.2
3
+ Version: 2.12.4
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
@@ -9,8 +9,8 @@ Classifier: Development Status :: 3 - Alpha
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Topic :: Scientific/Engineering
11
11
  Requires-Python: >=3.10
12
- Requires-Dist: bec-ipython-client<=4.0,>=2.21.4
13
- Requires-Dist: bec-lib<=4.0,>=3.29
12
+ Requires-Dist: bec-ipython-client<=4.0,>=3.38
13
+ Requires-Dist: bec-lib<=4.0,>=3.38
14
14
  Requires-Dist: bec-qthemes>=0.7,~=0.7
15
15
  Requires-Dist: black~=25.0
16
16
  Requires-Dist: isort>=5.13.2,~=5.13
@@ -2,11 +2,11 @@
2
2
  .gitlab-ci.yml,sha256=1nMYldzVk0tFkBWYTcUjumOrdSADASheWOAc0kOFDYs,9509
3
3
  .pylintrc,sha256=eeY8YwSI74oFfq6IYIbCqnx3Vk8ZncKaatv96n_Y8Rs,18544
4
4
  .readthedocs.yaml,sha256=ivqg3HTaOxNbEW3bzWh9MXAkrekuGoNdj0Mj3SdRYuw,639
5
- CHANGELOG.md,sha256=UD46knQ-Uwrj7v0h-bwRm1V9iyc26qJCjqUDrNHWE-U,297187
5
+ CHANGELOG.md,sha256=On772_xBp6UXL4xD4-avtvUKnrHAn_WkDG54pbO8faw,298414
6
6
  LICENSE,sha256=Daeiu871NcAp8uYi4eB_qHgvypG-HX0ioRQyQxFwjeg,1531
7
- PKG-INFO,sha256=Kcd6OF3UQpRgaisKiMd8N-QHda0WVCx6ibH_dBz17UQ,1254
7
+ PKG-INFO,sha256=yGts5s4Gww_NSvVRgwxfZ4qy9VcGBEFgtvYb3GwhVFE,1252
8
8
  README.md,sha256=oY5Jc1uXehRASuwUJ0umin2vfkFh7tHF-LLruHTaQx0,3560
9
- pyproject.toml,sha256=fmTjR-mLrzWuJj1LqBPC9hVL4MNj_cmbjVd9AIhsGjg,2835
9
+ pyproject.toml,sha256=J2FCGRnxVqdJMydJh53r1De16ht1tmpzMqa-I5v1FEM,2827
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .github/pull_request_template.md,sha256=F_cJXzooWMFgMGtLK-7KeGcQt0B4AYFse5oN0zQ9p6g,801
12
12
  .github/ISSUE_TEMPLATE/bug_report.yml,sha256=WdRnt7HGxvsIBLzhkaOWNfg8IJQYa_oV9_F08Ym6znQ,1081
@@ -23,6 +23,7 @@ pyproject.toml,sha256=fmTjR-mLrzWuJj1LqBPC9hVL4MNj_cmbjVd9AIhsGjg,2835
23
23
  .github/workflows/pytest-matrix.yml,sha256=0gL5wNPJKJF1JapqstlYNYiJ44ko05uaTD7epa7smVw,1834
24
24
  .github/workflows/pytest.yml,sha256=hYOB7XK_79MaiELaTH7zDT-WRw-pRDe4mHyB_WfcGDc,1747
25
25
  .github/workflows/semantic_release.yml,sha256=pdkv1rVG3YgG7yu4nNWvbGZifH4bqO1eh3pM0KHRK04,3720
26
+ .github/workflows/stale-issues.yml,sha256=Q1n-RO1FjEtuWJFRXpqzWnl7Y6EUn0T2ZSRdZQadJA4,568
26
27
  .github/workflows/sync-issues-pr.yml,sha256=Wn68mK8h0xhwIX1VZPEqHEJmku2BRPOrQ6zQsuCIBJk,1039
27
28
  bec_widgets/__init__.py,sha256=mZhbU6zfFt8-A7q_do74ie89budSevwpKZ6FKtEBdmo,170
28
29
  bec_widgets/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -35,7 +36,7 @@ bec_widgets/assets/app_icons/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqg
35
36
  bec_widgets/assets/app_icons/ui_loader_tile.png,sha256=qSK3XHqvnAVGV9Q0ulORcGFbXJ9LDq2uz8l9uTtMsNk,1812476
36
37
  bec_widgets/assets/app_icons/widget_launch_tile.png,sha256=bWsICHFfSe9-ESUj3AwlE95dDOea-f6M-s9fBapsxB4,2252911
37
38
  bec_widgets/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- bec_widgets/cli/client.py,sha256=YcHF_WYmCy4DcgLhYsjVuzESxvjOlG5Ip6E3v2GmBCk,97938
39
+ bec_widgets/cli/client.py,sha256=MIHk1aBnopQ9qc9QIEldvbO2C5xW4I6U7WYjyOvaMZw,97953
39
40
  bec_widgets/cli/client_utils.py,sha256=F2hyt--jL53bN8NoWifNUMqwwx5FbpS6I1apERdTRzM,18114
40
41
  bec_widgets/cli/generate_cli.py,sha256=K_wMxo2XBUn92SnY3dSrlyUn8ax6Y20QBGCuP284DsQ,10986
41
42
  bec_widgets/cli/server.py,sha256=h7QyBOOGjyrP_fxJIIOSEMc4E06cLG0JyaofjNV6oCA,5671
@@ -72,7 +73,7 @@ bec_widgets/utils/collapsible_panel_manager.py,sha256=tvv77-9YTfYpsU6M_Le3bHR6wt
72
73
  bec_widgets/utils/colors.py,sha256=i1DuwwdXzRs7HVq9m5wXSaZOJwLX5mJPvV6GAqylZhM,18341
73
74
  bec_widgets/utils/compact_popup.py,sha256=xVK_lQqL5Hy1ZnUzHXB8GU-Ru-mXevKcdM8ync3ssiA,10269
74
75
  bec_widgets/utils/container_utils.py,sha256=J8YXombOlAPa3M8NGZdhntp2NirBu4raDEQZOgP4elM,3791
75
- bec_widgets/utils/crosshair.py,sha256=d4h3uHh9ZvW0PlI0yWI-kKvgLQP7E6HJoCPzNvojHr0,22306
76
+ bec_widgets/utils/crosshair.py,sha256=nqBPQqWzoTLZ-sPBR6ONm7M1TtGGD2EpRwm2iSNpoFo,22304
76
77
  bec_widgets/utils/entry_validator.py,sha256=lwT8HP0RDG1FXENIeZ3IDEF2DQmD8KXGkRxPoMXbryk,1817
77
78
  bec_widgets/utils/error_popups.py,sha256=UBAmD1YlAgKodpihudyf0VWtI59KGFiLgnjiKmKGjgk,13254
78
79
  bec_widgets/utils/expandable_frame.py,sha256=ynqRFwXsd6jWT5C6qjNwmmHY9Rm9UCALeL32OPQkYgw,3785
@@ -183,7 +184,7 @@ bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.p
183
184
  bec_widgets/widgets/control/device_input/device_combobox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
184
185
  bec_widgets/widgets/control/device_input/device_combobox/device_combo_box.pyproject,sha256=wI2eXR5ky_IM9-BCHJnH_9CEqYcZwIuLcgitSEr8OJU,40
185
186
  bec_widgets/widgets/control/device_input/device_combobox/device_combo_box_plugin.py,sha256=E8LD9T4O2w621q25uHqBqZLDiQ6zpMR25ZDuf51jrPw,1434
186
- bec_widgets/widgets/control/device_input/device_combobox/device_combobox.py,sha256=babUAPI8St58FV13b4RZJ10DXcj-2mlYcNKKsdpB7Hs,6507
187
+ bec_widgets/widgets/control/device_input/device_combobox/device_combobox.py,sha256=8ANCTgPtO_Fhhy1ZBUfr9Yx_aArnePgkNORYwnXE-Fw,7251
187
188
  bec_widgets/widgets/control/device_input/device_combobox/register_device_combo_box.py,sha256=elw4M4xfIFWe8C0MkdqqqyfnyOVrdl0g0j6bqwOU1GE,526
188
189
  bec_widgets/widgets/control/device_input/device_line_edit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
190
  bec_widgets/widgets/control/device_input/device_line_edit/device_line_edit.py,sha256=k87NtUD2TUB4c6-Ks-eZgafWbjTwbk0RKiqf9-OkjMk,7415
@@ -256,7 +257,7 @@ bec_widgets/widgets/games/register_minesweeper.py,sha256=8fgMBD3yB-5_eGqhG_qxpj3
256
257
  bec_widgets/widgets/plots/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
258
  bec_widgets/widgets/plots/plot_base.py,sha256=GETUsx51BE_Tuop8bC-KiFVrkR82TJ5S0cr7siouSWM,35848
258
259
  bec_widgets/widgets/plots/image/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
259
- bec_widgets/widgets/plots/image/image.py,sha256=8s9DShQVAz458aPKfJTCWEmg8HoagCX3MkjFJZXSmek,17278
260
+ bec_widgets/widgets/plots/image/image.py,sha256=wrI9C2xNEoQmCWoKjlSdRHroWHffIg_DFT4fNDTgAyE,20299
260
261
  bec_widgets/widgets/plots/image/image.pyproject,sha256=_sRCIu4MNgToaB4D7tUMWq3xKX6T2VoRS3UzGNIseHQ,23
261
262
  bec_widgets/widgets/plots/image/image_base.py,sha256=_c4rYRX2AwGyy0WWUhaAJl3gNfXSq1ts99MG8rsa-6w,36104
262
263
  bec_widgets/widgets/plots/image/image_item.py,sha256=rkL1o35Pgs1zhvv2wpSG1gt_bjP5kO4Z1oy6d2q-Yls,8577
@@ -267,7 +268,7 @@ bec_widgets/widgets/plots/image/register_image.py,sha256=0rvFyAMGRZcknc7nMVwsMGS
267
268
  bec_widgets/widgets/plots/image/setting_widgets/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
268
269
  bec_widgets/widgets/plots/image/setting_widgets/image_roi_tree.py,sha256=nlllg-yTNCjG5DxCEDSGzCNabNSTJ3TZn9mawzIiAq4,14255
269
270
  bec_widgets/widgets/plots/image/toolbar_bundles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
270
- bec_widgets/widgets/plots/image/toolbar_bundles/image_selection.py,sha256=gJhDAdHB4cAsPw7E6W6Y2iR3nF_3n_v-ElGqj4TgIGo,2646
271
+ bec_widgets/widgets/plots/image/toolbar_bundles/image_selection.py,sha256=ezs2TWZCz-3npbIFEiYuHNiuSvJptJznTEZWD_CX3po,4705
271
272
  bec_widgets/widgets/plots/image/toolbar_bundles/processing.py,sha256=99hgd1q86ZUhQYTTsFCk3Ml8oAEeZJy-WqdmsMO4bzA,3367
272
273
  bec_widgets/widgets/plots/motor_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
273
274
  bec_widgets/widgets/plots/motor_map/motor_map.py,sha256=pcQStrIJJOsxC2sW3FDMDIFmFXM94uXQVdAjPi-vBvM,29209
@@ -290,7 +291,7 @@ bec_widgets/widgets/plots/multi_waveform/settings/multi_waveform_controls.ui,sha
290
291
  bec_widgets/widgets/plots/multi_waveform/toolbar_bundles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
291
292
  bec_widgets/widgets/plots/multi_waveform/toolbar_bundles/monitor_selection.py,sha256=lGreAkRBd-A4X_wqYZiKyGDmb_3uzLunjSju9A2PjWw,2532
292
293
  bec_widgets/widgets/plots/roi/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
293
- bec_widgets/widgets/plots/roi/image_roi.py,sha256=HIDlsRJtsZf2Iu09tHQuRXI0jFUiBJzTvKe8C_aI1no,32333
294
+ bec_widgets/widgets/plots/roi/image_roi.py,sha256=EobZDeUV3l9O08tKwFGZEvkGNOMnVp0hHWNodYce9I0,32998
294
295
  bec_widgets/widgets/plots/scatter_waveform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
295
296
  bec_widgets/widgets/plots/scatter_waveform/register_scatter_waveform.py,sha256=KttVjlAK3PfP9tyMfLnqEm6kphap8NZyqyaRry8oebY,514
296
297
  bec_widgets/widgets/plots/scatter_waveform/scatter_curve.py,sha256=nCyZ_6EunS1m5XkLB-CwfBV9L4IX04D9SpHlHc8zG_I,6763
@@ -407,8 +408,8 @@ bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.py,sha256=O
407
408
  bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.pyproject,sha256=Lbi9zb6HNlIq14k6hlzR-oz6PIFShBuF7QxE6d87d64,34
408
409
  bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button_plugin.py,sha256=CzChz2SSETYsR8-36meqWnsXCT-FIy_J_xeU5coWDY8,1350
409
410
  bec_widgets/widgets/utility/visual/dark_mode_button/register_dark_mode_button.py,sha256=rMpZ1CaoucwobgPj1FuKTnt07W82bV1GaSYdoqcdMb8,521
410
- bec_widgets-2.12.2.dist-info/METADATA,sha256=Kcd6OF3UQpRgaisKiMd8N-QHda0WVCx6ibH_dBz17UQ,1254
411
- bec_widgets-2.12.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
412
- bec_widgets-2.12.2.dist-info/entry_points.txt,sha256=dItMzmwA1wizJ1Itx15qnfJ0ZzKVYFLVJ1voxT7K7D4,214
413
- bec_widgets-2.12.2.dist-info/licenses/LICENSE,sha256=Daeiu871NcAp8uYi4eB_qHgvypG-HX0ioRQyQxFwjeg,1531
414
- bec_widgets-2.12.2.dist-info/RECORD,,
411
+ bec_widgets-2.12.4.dist-info/METADATA,sha256=yGts5s4Gww_NSvVRgwxfZ4qy9VcGBEFgtvYb3GwhVFE,1252
412
+ bec_widgets-2.12.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
413
+ bec_widgets-2.12.4.dist-info/entry_points.txt,sha256=dItMzmwA1wizJ1Itx15qnfJ0ZzKVYFLVJ1voxT7K7D4,214
414
+ bec_widgets-2.12.4.dist-info/licenses/LICENSE,sha256=Daeiu871NcAp8uYi4eB_qHgvypG-HX0ioRQyQxFwjeg,1531
415
+ bec_widgets-2.12.4.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 = "2.12.2"
7
+ version = "2.12.4"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [
@@ -13,15 +13,15 @@ classifiers = [
13
13
  "Topic :: Scientific/Engineering",
14
14
  ]
15
15
  dependencies = [
16
- "bec_ipython_client>=2.21.4, <=4.0", # needed for jupyter console
17
- "bec_lib>=3.29, <=4.0",
16
+ "bec_ipython_client>=3.38, <=4.0", # needed for jupyter console
17
+ "bec_lib>=3.38, <=4.0",
18
18
  "bec_qthemes~=0.7, >=0.7",
19
- "black~=25.0", # needed for bw-generate-cli
20
- "isort~=5.13, >=5.13.2", # needed for bw-generate-cli
19
+ "black~=25.0", # needed for bw-generate-cli
20
+ "isort~=5.13, >=5.13.2", # needed for bw-generate-cli
21
21
  "pydantic~=2.0",
22
22
  "pyqtgraph~=0.13",
23
23
  "PySide6~=6.8.2",
24
- "qtconsole~=5.5, >=5.5.1", # needed for jupyter console
24
+ "qtconsole~=5.5, >=5.5.1", # needed for jupyter console
25
25
  "qtpy~=2.4",
26
26
  ]
27
27