bec-widgets 0.91.0__py3-none-any.whl → 0.92.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. .gitlab-ci.yml +12 -8
  2. CHANGELOG.md +40 -44
  3. PKG-INFO +1 -1
  4. bec_widgets/assets/app_icons/BEC-Dark.png +0 -0
  5. bec_widgets/examples/general_app/__init__.py +0 -0
  6. bec_widgets/examples/general_app/general_app.py +92 -0
  7. bec_widgets/examples/general_app/general_app.ui +262 -0
  8. bec_widgets/examples/general_app/web_links.py +15 -0
  9. bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py +2 -1
  10. bec_widgets/qt_utils/error_popups.py +19 -30
  11. bec_widgets/qt_utils/settings_dialog.py +2 -1
  12. bec_widgets/utils/bec_connector.py +1 -1
  13. bec_widgets/widgets/console/console.py +3 -2
  14. bec_widgets/widgets/device_combobox/device_combobox.py +1 -1
  15. bec_widgets/widgets/dock/dock.py +63 -2
  16. bec_widgets/widgets/figure/figure.py +10 -10
  17. bec_widgets/widgets/figure/plots/axis_settings.py +1 -1
  18. bec_widgets/widgets/figure/plots/image/image.py +17 -17
  19. bec_widgets/widgets/figure/plots/motor_map/motor_map.py +2 -2
  20. bec_widgets/widgets/figure/plots/waveform/waveform.py +15 -15
  21. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py +1 -1
  22. bec_widgets/widgets/stop_button/stop_button.py +1 -1
  23. bec_widgets/widgets/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py +1 -1
  24. {bec_widgets-0.91.0.dist-info → bec_widgets-0.92.1.dist-info}/METADATA +1 -1
  25. {bec_widgets-0.91.0.dist-info → bec_widgets-0.92.1.dist-info}/RECORD +34 -29
  26. pyproject.toml +1 -1
  27. tests/end-2-end/test_bec_dock_rpc_e2e.py +1 -1
  28. tests/end-2-end/test_bec_figure_rpc_e2e.py +1 -1
  29. tests/unit_tests/conftest.py +12 -1
  30. tests/unit_tests/test_bec_connector.py +1 -1
  31. tests/unit_tests/test_bec_image.py +3 -3
  32. {bec_widgets-0.91.0.dist-info → bec_widgets-0.92.1.dist-info}/WHEEL +0 -0
  33. {bec_widgets-0.91.0.dist-info → bec_widgets-0.92.1.dist-info}/entry_points.txt +0 -0
  34. {bec_widgets-0.91.0.dist-info → bec_widgets-0.92.1.dist-info}/licenses/LICENSE +0 -0
@@ -18,10 +18,11 @@ import pyte
18
18
  from qtpy import QtCore, QtGui, QtWidgets
19
19
  from qtpy.QtCore import QSize, QSocketNotifier, Qt
20
20
  from qtpy.QtCore import Signal as pyqtSignal
21
- from qtpy.QtCore import Slot as pyqtSlot
22
21
  from qtpy.QtGui import QClipboard, QTextCursor
23
22
  from qtpy.QtWidgets import QApplication, QHBoxLayout, QScrollBar, QSizePolicy
24
23
 
24
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
25
+
25
26
  ansi_colors = {
26
27
  "black": "#000000",
27
28
  "red": "#CD0000",
@@ -289,7 +290,7 @@ class _TerminalWidget(QtWidgets.QPlainTextEdit):
289
290
  old["value"] = value
290
291
  self.dataReady(self.backend.screen, reset_scroll=False)
291
292
 
292
- @pyqtSlot(object)
293
+ @Slot(object)
293
294
  def keyPressEvent(self, event):
294
295
  """
295
296
  Redirect all keystrokes to the terminal process.
@@ -34,7 +34,7 @@ class DeviceComboBox(DeviceInputBase, QComboBox):
34
34
  ):
35
35
  super().__init__(client=client, config=config, gui_id=gui_id)
36
36
  QComboBox.__init__(self, parent=parent)
37
-
37
+ self.setMinimumSize(125, 26)
38
38
  self.populate_combobox()
39
39
 
40
40
  if arg_name is not None:
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from typing import TYPE_CHECKING, Any, Literal, Optional
4
4
 
5
5
  from pydantic import Field
6
- from pyqtgraph.dockarea import Dock
6
+ from pyqtgraph.dockarea import Dock, DockLabel
7
7
 
8
8
  from bec_widgets.cli.rpc_wigdet_handler import widget_handler
9
9
  from bec_widgets.utils import ConnectionConfig, GridLayoutManager
@@ -25,6 +25,64 @@ class DockConfig(ConnectionConfig):
25
25
  )
26
26
 
27
27
 
28
+ class CustomDockLabel(DockLabel):
29
+ def updateStyle(self):
30
+ r = "3px"
31
+ if self.dim:
32
+ fg = "#aaa"
33
+ bg = "#44a"
34
+ border = "#339"
35
+ else:
36
+ fg = "#fff"
37
+ bg = "#3f4042"
38
+ border = "#3f4042"
39
+
40
+ if self.orientation == "vertical":
41
+ self.vStyle = """DockLabel {
42
+ background-color : %s;
43
+ color : %s;
44
+ border-top-right-radius: 0px;
45
+ border-top-left-radius: %s;
46
+ border-bottom-right-radius: 0px;
47
+ border-bottom-left-radius: %s;
48
+ border-width: 0px;
49
+ border-right: 2px solid %s;
50
+ padding-top: 3px;
51
+ padding-bottom: 3px;
52
+ font-size: %s;
53
+ }""" % (
54
+ bg,
55
+ fg,
56
+ r,
57
+ r,
58
+ border,
59
+ self.fontSize,
60
+ )
61
+ self.setStyleSheet(self.vStyle)
62
+ else:
63
+ self.hStyle = """DockLabel {
64
+ background-color : %s;
65
+ color : %s;
66
+ border-top-right-radius: %s;
67
+ border-top-left-radius: %s;
68
+ border-bottom-right-radius: 0px;
69
+ border-bottom-left-radius: 0px;
70
+ border-width: 0px;
71
+ border-bottom: 2px solid %s;
72
+ padding-left: 3px;
73
+ padding-right: 3px;
74
+ font-size: %s;
75
+ }""" % (
76
+ bg,
77
+ fg,
78
+ r,
79
+ r,
80
+ border,
81
+ self.fontSize,
82
+ )
83
+ self.setStyleSheet(self.hStyle)
84
+
85
+
28
86
  class BECDock(BECWidget, Dock):
29
87
  USER_ACCESS = [
30
88
  "_config_dict",
@@ -51,6 +109,7 @@ class BECDock(BECWidget, Dock):
51
109
  name: str | None = None,
52
110
  client=None,
53
111
  gui_id: str | None = None,
112
+ closable: bool = True,
54
113
  **kwargs,
55
114
  ) -> None:
56
115
  if config is None:
@@ -62,7 +121,9 @@ class BECDock(BECWidget, Dock):
62
121
  config = DockConfig(**config)
63
122
  self.config = config
64
123
  super().__init__(client=client, config=config, gui_id=gui_id)
65
- Dock.__init__(self, name=name, **kwargs)
124
+ label = CustomDockLabel(text=name, closable=closable)
125
+ Dock.__init__(self, name=name, label=label, **kwargs)
126
+ # Dock.__init__(self, name=name, **kwargs)
66
127
 
67
128
  self.parent_dock_area = parent_dock_area
68
129
 
@@ -164,7 +164,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
164
164
  def __getitem__(self, key: tuple | str):
165
165
  if isinstance(key, tuple) and len(key) == 2:
166
166
  return self.axes(*key)
167
- elif isinstance(key, str):
167
+ if isinstance(key, str):
168
168
  widget = self._widgets.get(key)
169
169
  if widget is None:
170
170
  raise KeyError(f"No widget with ID {key}")
@@ -185,7 +185,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
185
185
  self.change_theme(self.config.theme)
186
186
 
187
187
  # widget_config has to be reset for not have each widget config twice when added to the figure
188
- widget_configs = [config for config in self.config.widgets.values()]
188
+ widget_configs = list(self.config.widgets.values())
189
189
  self.config.widgets = {}
190
190
  for widget_config in widget_configs:
191
191
  getattr(self, self.widget_method_map[widget_config.widget_class])(
@@ -233,8 +233,8 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
233
233
  """Export the plot widget."""
234
234
  try:
235
235
  plot_item = self.widget_list[0]
236
- except:
237
- raise ValueError("No plot widget available to export.")
236
+ except Exception as exc:
237
+ raise ValueError("No plot widget available to export.") from exc
238
238
 
239
239
  scene = plot_item.scene()
240
240
  scene.contextMenuItem = plot_item
@@ -529,12 +529,12 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
529
529
  if row is not None and col is not None:
530
530
  if self.getItem(row, col):
531
531
  raise ValueError(f"Position at row {row} and column {col} is already occupied.")
532
- else:
533
- widget.config.row = row
534
- widget.config.col = col
535
532
 
536
- # Add widget to the figure
537
- self.addItem(widget, row=row, col=col)
533
+ widget.config.row = row
534
+ widget.config.col = col
535
+
536
+ # Add widget to the figure
537
+ self.addItem(widget, row=row, col=col)
538
538
  else:
539
539
  row, col = self._find_next_empty_position()
540
540
  widget.config.row = row
@@ -721,7 +721,7 @@ class BECFigure(BECWidget, pg.GraphicsLayoutWidget):
721
721
 
722
722
  # Populate the new grid with widgets' IDs
723
723
  current_idx = 0
724
- for widget_id, widget in self._widgets.items():
724
+ for widget_id in self._widgets:
725
725
  row = current_idx // len(new_grid[0])
726
726
  col = current_idx % len(new_grid[0])
727
727
  new_grid[row][col] = widget_id
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.qt_utils.settings_dialog import SettingWidget
7
7
  from bec_widgets.utils import UILoader
8
8
  from bec_widgets.utils.widget_io import WidgetIO
@@ -7,9 +7,9 @@ import numpy as np
7
7
  from bec_lib.endpoints import MessageEndpoints
8
8
  from pydantic import BaseModel, Field, ValidationError
9
9
  from qtpy.QtCore import QThread
10
- from qtpy.QtCore import Slot as pyqtSlot
11
10
  from qtpy.QtWidgets import QWidget
12
11
 
12
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
13
13
  from bec_widgets.utils import EntryValidator
14
14
  from bec_widgets.widgets.figure.plots.image.image_item import BECImageItem, ImageItemConfig
15
15
  from bec_widgets.widgets.figure.plots.image.image_processor import (
@@ -247,7 +247,7 @@ class BECImageShow(BECPlotBase):
247
247
  Returns:
248
248
  BECImageItem: The image item.
249
249
  """
250
- image_source = "device_monitor"
250
+ image_source = "device_monitor_2d"
251
251
 
252
252
  image_exits = self._check_image_id(monitor, self._images)
253
253
  if image_exits:
@@ -287,7 +287,7 @@ class BECImageShow(BECPlotBase):
287
287
  **kwargs,
288
288
  ):
289
289
  image_source = "custom"
290
- # image_source = "device_monitor"
290
+ # image_source = "device_monitor_2d"
291
291
 
292
292
  image_exits = self._check_image_id(name, self._images)
293
293
  if image_exits:
@@ -500,7 +500,7 @@ class BECImageShow(BECPlotBase):
500
500
  self.update_image(device, data)
501
501
  self.update_vrange(device, self.processor.config.stats)
502
502
 
503
- @pyqtSlot(dict)
503
+ @Slot(dict)
504
504
  def on_image_update(self, msg: dict):
505
505
  """
506
506
  Update the image of the device monitor from bec.
@@ -510,11 +510,11 @@ class BECImageShow(BECPlotBase):
510
510
  """
511
511
  data = msg["data"]
512
512
  device = msg["device"]
513
- image = self._images["device_monitor"][device]
513
+ image = self._images["device_monitor_2d"][device]
514
514
  image.raw_data = data
515
515
  self.process_image(device, image, data)
516
516
 
517
- @pyqtSlot(str, np.ndarray)
517
+ @Slot(str, np.ndarray)
518
518
  def update_image(self, device: str, data: np.ndarray):
519
519
  """
520
520
  Update the image of the device monitor.
@@ -523,10 +523,10 @@ class BECImageShow(BECPlotBase):
523
523
  device(str): The name of the device.
524
524
  data(np.ndarray): The data to be updated.
525
525
  """
526
- image_to_update = self._images["device_monitor"][device]
526
+ image_to_update = self._images["device_monitor_2d"][device]
527
527
  image_to_update.updateImage(data, autoLevels=image_to_update.config.autorange)
528
528
 
529
- @pyqtSlot(str, ImageStats)
529
+ @Slot(str, ImageStats)
530
530
  def update_vrange(self, device: str, stats: ImageStats):
531
531
  """
532
532
  Update the scaling of the image.
@@ -534,7 +534,7 @@ class BECImageShow(BECPlotBase):
534
534
  Args:
535
535
  stats(ImageStats): The statistics of the image.
536
536
  """
537
- image_to_update = self._images["device_monitor"][device]
537
+ image_to_update = self._images["device_monitor_2d"][device]
538
538
  if image_to_update.config.autorange:
539
539
  image_to_update.auto_update_vrange(stats)
540
540
 
@@ -547,7 +547,7 @@ class BECImageShow(BECPlotBase):
547
547
  data = image.raw_data
548
548
  self.process_image(image_id, image, data)
549
549
 
550
- def _connect_device_monitor(self, monitor: str):
550
+ def _connect_device_monitor_2d(self, monitor: str):
551
551
  """
552
552
  Connect to the device monitor.
553
553
 
@@ -561,13 +561,13 @@ class BECImageShow(BECPlotBase):
561
561
  previous_monitor = None
562
562
  if previous_monitor and image_item.connected is True:
563
563
  self.bec_dispatcher.disconnect_slot(
564
- self.on_image_update, MessageEndpoints.device_monitor(previous_monitor)
564
+ self.on_image_update, MessageEndpoints.device_monitor_2d(previous_monitor)
565
565
  )
566
566
  image_item.connected = False
567
567
  if monitor and image_item.connected is False:
568
568
  self.entry_validator.validate_monitor(monitor)
569
569
  self.bec_dispatcher.connect_slot(
570
- self.on_image_update, MessageEndpoints.device_monitor(monitor)
570
+ self.on_image_update, MessageEndpoints.device_monitor_2d(monitor)
571
571
  )
572
572
  image_item.set_monitor(monitor)
573
573
  image_item.connected = True
@@ -581,8 +581,8 @@ class BECImageShow(BECPlotBase):
581
581
  if self.single_image is True and len(self.images) > 0:
582
582
  self.remove_image(0)
583
583
  self._images[source][name] = image
584
- if source == "device_monitor":
585
- self._connect_device_monitor(config.monitor)
584
+ if source == "device_monitor_2d":
585
+ self._connect_device_monitor_2d(config.monitor)
586
586
  self.config.images[name] = config
587
587
  if data is not None:
588
588
  image.setImage(data)
@@ -668,15 +668,15 @@ class BECImageShow(BECPlotBase):
668
668
  image = self.find_image_by_monitor(image_id)
669
669
  if image:
670
670
  self.bec_dispatcher.disconnect_slot(
671
- self.on_image_update, MessageEndpoints.device_monitor(image.config.monitor)
671
+ self.on_image_update, MessageEndpoints.device_monitor_2d(image.config.monitor)
672
672
  )
673
673
 
674
674
  def cleanup(self):
675
675
  """
676
676
  Clean up the widget.
677
677
  """
678
- for monitor in self._images["device_monitor"]:
678
+ for monitor in self._images["device_monitor_2d"]:
679
679
  self.bec_dispatcher.disconnect_slot(
680
- self.on_image_update, MessageEndpoints.device_monitor(monitor)
680
+ self.on_image_update, MessageEndpoints.device_monitor_2d(monitor)
681
681
  )
682
682
  self.images.clear()
@@ -10,9 +10,9 @@ from pydantic import Field, ValidationError, field_validator
10
10
  from pydantic_core import PydanticCustomError
11
11
  from qtpy import QtCore, QtGui
12
12
  from qtpy.QtCore import Signal as pyqtSignal
13
- from qtpy.QtCore import Slot
14
13
  from qtpy.QtWidgets import QWidget
15
14
 
15
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
16
16
  from bec_widgets.utils import Colors, EntryValidator
17
17
  from bec_widgets.widgets.figure.plots.plot_base import BECPlotBase, SubplotConfig
18
18
  from bec_widgets.widgets.figure.plots.waveform.waveform import Signal, SignalData
@@ -444,7 +444,7 @@ class BECMotorMap(BECPlotBase):
444
444
  return None
445
445
 
446
446
  @Slot()
447
- def _update_plot(self):
447
+ def _update_plot(self, _=None):
448
448
  """Update the motor map plot."""
449
449
  # If the number of points exceeds max_points, delete the oldest points
450
450
  if len(self.database_buffer["x"]) > self.config.max_points:
@@ -11,9 +11,9 @@ from bec_lib.endpoints import MessageEndpoints
11
11
  from pydantic import Field, ValidationError, field_validator
12
12
  from pyqtgraph.exporters import MatplotlibExporter
13
13
  from qtpy.QtCore import Signal as pyqtSignal
14
- from qtpy.QtCore import Slot as pyqtSlot
15
14
  from qtpy.QtWidgets import QWidget
16
15
 
16
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
17
17
  from bec_widgets.utils import Colors, EntryValidator
18
18
  from bec_widgets.widgets.figure.plots.plot_base import BECPlotBase, SubplotConfig
19
19
  from bec_widgets.widgets.figure.plots.waveform.waveform_curve import (
@@ -391,7 +391,7 @@ class BECWaveform(BECPlotBase):
391
391
  self.async_signal_update.emit()
392
392
  self.scan_signal_update.emit()
393
393
 
394
- @pyqtSlot()
394
+ @Slot()
395
395
  def auto_range(self):
396
396
  self.plot_item.autoRange()
397
397
 
@@ -408,7 +408,7 @@ class BECWaveform(BECPlotBase):
408
408
  """
409
409
  self.plot_item.enableAutoRange(axis, enabled)
410
410
 
411
- @pyqtSlot()
411
+ @Slot()
412
412
  def auto_range(self):
413
413
  self.plot_item.autoRange()
414
414
 
@@ -642,7 +642,7 @@ class BECWaveform(BECPlotBase):
642
642
  self.refresh_dap()
643
643
  return curve
644
644
 
645
- @pyqtSlot()
645
+ @Slot()
646
646
  def get_dap_params(self) -> dict:
647
647
  """
648
648
  Get the DAP parameters of all DAP curves.
@@ -655,7 +655,7 @@ class BECWaveform(BECPlotBase):
655
655
  params[curve_id] = curve.dap_params
656
656
  return params
657
657
 
658
- @pyqtSlot()
658
+ @Slot()
659
659
  def get_dap_summary(self) -> dict:
660
660
  """
661
661
  Get the DAP summary of all DAP curves.
@@ -921,7 +921,7 @@ class BECWaveform(BECPlotBase):
921
921
  else:
922
922
  raise IndexError(f"Curve order {N} out of range.")
923
923
 
924
- @pyqtSlot(dict)
924
+ @Slot(dict)
925
925
  def on_scan_status(self, msg):
926
926
  """
927
927
  Handle the scan status message.
@@ -945,7 +945,7 @@ class BECWaveform(BECPlotBase):
945
945
  for curve_id, curve in self._curves_data["async"].items():
946
946
  self.setup_async(curve.config.signals.y.name)
947
947
 
948
- @pyqtSlot(dict, dict)
948
+ @Slot(dict, dict)
949
949
  def on_scan_segment(self, msg: dict, metadata: dict):
950
950
  """
951
951
  Handle new scan segments and saves data to a dictionary. Linked through bec_dispatcher.
@@ -1004,7 +1004,7 @@ class BECWaveform(BECPlotBase):
1004
1004
  self.update_dap, MessageEndpoints.dap_response(f"{new_scan_id}-{self.gui_id}")
1005
1005
  )
1006
1006
 
1007
- @pyqtSlot(str)
1007
+ @Slot(str)
1008
1008
  def setup_async(self, device: str):
1009
1009
  self.bec_dispatcher.disconnect_slot(
1010
1010
  self.on_async_readback, MessageEndpoints.device_async_readback(self.old_scan_id, device)
@@ -1020,8 +1020,8 @@ class BECWaveform(BECPlotBase):
1020
1020
  from_start=True,
1021
1021
  )
1022
1022
 
1023
- @pyqtSlot()
1024
- def refresh_dap(self):
1023
+ @Slot()
1024
+ def refresh_dap(self, _=None):
1025
1025
  """
1026
1026
  Refresh the DAP curves with the latest data from the DAP model MessageEndpoints.dap_response().
1027
1027
  """
@@ -1069,7 +1069,7 @@ class BECWaveform(BECPlotBase):
1069
1069
  )
1070
1070
  self.client.connector.set_and_publish(MessageEndpoints.dap_request(), msg)
1071
1071
 
1072
- @pyqtSlot(dict, dict)
1072
+ @Slot(dict, dict)
1073
1073
  def update_dap(self, msg, metadata):
1074
1074
  self.msg = msg
1075
1075
  scan_id, x_name, x_entry, y_name, y_entry = msg["dap_request"].content["config"]["args"]
@@ -1089,7 +1089,7 @@ class BECWaveform(BECPlotBase):
1089
1089
  self.dap_summary_update.emit(curve.dap_summary)
1090
1090
  break
1091
1091
 
1092
- @pyqtSlot(dict, dict)
1092
+ @Slot(dict, dict)
1093
1093
  def on_async_readback(self, msg, metadata):
1094
1094
  """
1095
1095
  Get async data readback.
@@ -1127,7 +1127,7 @@ class BECWaveform(BECPlotBase):
1127
1127
  else:
1128
1128
  curve.setData(data_plot)
1129
1129
 
1130
- @pyqtSlot()
1130
+ @Slot()
1131
1131
  def replot_async_curve(self):
1132
1132
  try:
1133
1133
  data = self.scan_item.async_data
@@ -1152,8 +1152,8 @@ class BECWaveform(BECPlotBase):
1152
1152
  else:
1153
1153
  curve.setData(data_x, data_y)
1154
1154
 
1155
- @pyqtSlot()
1156
- def _update_scan_curves(self):
1155
+ @Slot()
1156
+ def _update_scan_curves(self, _=None):
1157
1157
  """
1158
1158
  Update the scan curves with the data from the scan segment.
1159
1159
  """
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.qt_utils.settings_dialog import SettingWidget
7
7
  from bec_widgets.utils import UILoader
8
8
  from bec_widgets.utils.widget_io import WidgetIO
@@ -1,6 +1,6 @@
1
- from qtpy.QtCore import Slot
2
1
  from qtpy.QtWidgets import QPushButton
3
2
 
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
4
4
  from bec_widgets.utils.bec_widget import BECWidget
5
5
 
6
6
 
@@ -1,8 +1,8 @@
1
1
  import os
2
2
 
3
- from qtpy.QtCore import Slot
4
3
  from qtpy.QtWidgets import QDialog, QTreeWidgetItem, QVBoxLayout
5
4
 
5
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
6
6
  from bec_widgets.utils import UILoader
7
7
 
8
8
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.91.0
3
+ Version: 0.92.1
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