bec-widgets 1.25.1__py3-none-any.whl → 2.0.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 (196) hide show
  1. .gitlab-ci.yml +3 -5
  2. CHANGELOG.md +639 -0
  3. PKG-INFO +3 -3
  4. bec_widgets/__init__.py +4 -0
  5. bec_widgets/applications/bw_launch.py +23 -0
  6. bec_widgets/applications/launch_window.py +430 -0
  7. bec_widgets/assets/app_icons/auto_update.png +0 -0
  8. bec_widgets/assets/app_icons/ui_loader_tile.png +0 -0
  9. bec_widgets/cli/__init__.py +0 -1
  10. bec_widgets/cli/client.py +1779 -2064
  11. bec_widgets/cli/client_utils.py +346 -174
  12. bec_widgets/cli/generate_cli.py +143 -37
  13. bec_widgets/cli/rpc/rpc_base.py +152 -21
  14. bec_widgets/cli/rpc/rpc_register.py +113 -6
  15. bec_widgets/cli/rpc/rpc_widget_handler.py +13 -11
  16. bec_widgets/cli/server.py +125 -239
  17. bec_widgets/examples/jupyter_console/jupyter_console_window.py +97 -145
  18. bec_widgets/examples/plugin_example_pyside/tictactoetaskmenu.py +1 -1
  19. bec_widgets/utils/bec_connector.py +190 -21
  20. bec_widgets/utils/bec_designer.py +7 -0
  21. bec_widgets/utils/bec_dispatcher.py +71 -4
  22. bec_widgets/utils/bec_plugin_helper.py +89 -0
  23. bec_widgets/utils/bec_signal_proxy.py +1 -1
  24. bec_widgets/utils/bec_widget.py +26 -10
  25. bec_widgets/utils/colors.py +1 -1
  26. bec_widgets/{qt_utils → utils}/compact_popup.py +2 -0
  27. bec_widgets/utils/container_utils.py +37 -12
  28. bec_widgets/utils/crosshair.py +25 -8
  29. bec_widgets/utils/entry_validator.py +3 -1
  30. bec_widgets/{qt_utils → utils}/error_popups.py +18 -0
  31. bec_widgets/{qt_utils → utils}/expandable_frame.py +2 -2
  32. bec_widgets/utils/forms_from_types/forms.py +182 -0
  33. bec_widgets/{widgets/editors/scan_metadata/_metadata_widgets.py → utils/forms_from_types/items.py} +41 -30
  34. bec_widgets/utils/generate_designer_plugin.py +40 -36
  35. bec_widgets/utils/linear_region_selector.py +2 -0
  36. bec_widgets/utils/name_utils.py +16 -0
  37. bec_widgets/{qt_utils → utils}/palette_viewer.py +2 -2
  38. bec_widgets/utils/plot_indicator_items.py +2 -5
  39. bec_widgets/utils/plugin_utils.py +47 -1
  40. bec_widgets/{qt_utils → utils}/round_frame.py +14 -14
  41. bec_widgets/utils/rpc_server.py +277 -0
  42. bec_widgets/utils/serialization.py +44 -0
  43. bec_widgets/{qt_utils → utils}/settings_dialog.py +26 -1
  44. bec_widgets/{qt_utils → utils}/side_panel.py +17 -10
  45. bec_widgets/{qt_utils → utils}/toolbar.py +69 -25
  46. bec_widgets/utils/ui_loader.py +8 -8
  47. bec_widgets/utils/widget_io.py +166 -25
  48. bec_widgets/widgets/containers/auto_update/auto_updates.py +364 -0
  49. bec_widgets/widgets/containers/dock/dock.py +157 -49
  50. bec_widgets/widgets/containers/dock/dock_area.py +188 -138
  51. bec_widgets/widgets/containers/layout_manager/layout_manager.py +2 -1
  52. bec_widgets/widgets/containers/main_window/addons/web_links.py +15 -0
  53. bec_widgets/widgets/containers/main_window/main_window.py +189 -41
  54. bec_widgets/widgets/control/buttons/button_abort/button_abort.py +3 -4
  55. bec_widgets/widgets/control/buttons/button_reset/button_reset.py +3 -4
  56. bec_widgets/widgets/control/buttons/button_resume/button_resume.py +3 -3
  57. bec_widgets/widgets/control/buttons/stop_button/stop_button.py +18 -7
  58. bec_widgets/widgets/control/device_control/position_indicator/position_indicator.py +22 -3
  59. bec_widgets/widgets/control/device_control/positioner_box/_base/positioner_box_base.py +31 -13
  60. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.py +3 -1
  61. bec_widgets/widgets/control/device_control/positioner_box/positioner_box/positioner_box.ui +27 -4
  62. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.py +5 -2
  63. bec_widgets/widgets/control/device_control/positioner_box/positioner_box_2d/positioner_box_2d.ui +97 -31
  64. bec_widgets/widgets/control/device_control/positioner_box/positioner_control_line/positioner_control_line.ui +11 -4
  65. bec_widgets/widgets/control/device_control/positioner_group/positioner_group.py +2 -3
  66. bec_widgets/widgets/control/device_input/base_classes/device_input_base.py +29 -4
  67. bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.py +1 -0
  68. bec_widgets/widgets/control/device_input/device_combobox/device_combobox.py +2 -2
  69. bec_widgets/widgets/control/device_input/device_line_edit/device_line_edit.py +2 -2
  70. bec_widgets/widgets/control/device_input/signal_combobox/signal_combobox.py +1 -2
  71. bec_widgets/widgets/control/device_input/signal_line_edit/signal_line_edit.py +1 -2
  72. bec_widgets/widgets/control/scan_control/scan_control.py +7 -5
  73. bec_widgets/widgets/control/scan_control/scan_group_box.py +28 -5
  74. bec_widgets/widgets/dap/dap_combo_box/dap_combo_box.py +1 -2
  75. bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog.py +3 -4
  76. bec_widgets/widgets/dap/lmfit_dialog/lmfit_dialog_vertical.ui +14 -8
  77. bec_widgets/widgets/editors/console/console.py +1 -1
  78. bec_widgets/widgets/editors/{scan_metadata/additional_metadata_table.py → dict_backed_table.py} +29 -6
  79. bec_widgets/widgets/editors/scan_metadata/__init__.py +0 -7
  80. bec_widgets/widgets/editors/scan_metadata/_util.py +1 -1
  81. bec_widgets/widgets/{plots/motor_map/register_bec_motor_map_widget.py → editors/scan_metadata/register_scan_metadata.py} +2 -4
  82. bec_widgets/widgets/editors/scan_metadata/scan_metadata.py +42 -136
  83. bec_widgets/widgets/editors/scan_metadata/scan_metadata.pyproject +1 -0
  84. bec_widgets/widgets/{plots/multi_waveform/bec_multi_waveform_widget_plugin.py → editors/scan_metadata/scan_metadata_plugin.py} +9 -9
  85. bec_widgets/widgets/editors/text_box/text_box.py +2 -3
  86. bec_widgets/widgets/editors/website/website.py +2 -2
  87. bec_widgets/widgets/games/minesweeper.py +3 -2
  88. bec_widgets/widgets/plots/image/image.py +960 -0
  89. bec_widgets/widgets/plots/image/image.pyproject +1 -0
  90. bec_widgets/widgets/plots/image/image_item.py +279 -0
  91. bec_widgets/widgets/plots/{motor_map/bec_motor_map_widget_plugin.py → image/image_plugin.py} +11 -13
  92. bec_widgets/widgets/{containers/figure/plots → plots}/image/image_processor.py +31 -64
  93. bec_widgets/widgets/plots/image/{register_bec_image_widget.py → register_image.py} +2 -2
  94. bec_widgets/widgets/plots/image/toolbar_bundles/image_selection.py +59 -0
  95. bec_widgets/widgets/plots/image/toolbar_bundles/processing.py +79 -0
  96. bec_widgets/widgets/plots/motor_map/motor_map.py +832 -0
  97. bec_widgets/widgets/plots/motor_map/motor_map.pyproject +1 -0
  98. bec_widgets/widgets/plots/motor_map/motor_map_plugin.py +54 -0
  99. bec_widgets/widgets/plots/{multi_waveform/register_bec_multi_waveform_widget.py → motor_map/register_motor_map.py} +2 -4
  100. bec_widgets/widgets/plots/motor_map/settings/motor_map_settings.py +129 -0
  101. bec_widgets/widgets/plots/motor_map/settings/motor_map_settings.ui +120 -0
  102. bec_widgets/widgets/plots/motor_map/toolbar_bundles/motor_selection.py +70 -0
  103. bec_widgets/widgets/plots/multi_waveform/multi_waveform.py +508 -0
  104. bec_widgets/widgets/plots/multi_waveform/multi_waveform.pyproject +1 -0
  105. bec_widgets/widgets/plots/multi_waveform/multi_waveform_plugin.py +54 -0
  106. bec_widgets/widgets/plots/multi_waveform/register_multi_waveform.py +15 -0
  107. bec_widgets/widgets/plots/multi_waveform/settings/control_panel.py +144 -0
  108. bec_widgets/widgets/plots/multi_waveform/settings/multi_waveform_controls.ui +164 -0
  109. bec_widgets/widgets/plots/multi_waveform/toolbar_bundles/monitor_selection.py +65 -0
  110. bec_widgets/widgets/{plots_next_gen → plots}/plot_base.py +321 -40
  111. bec_widgets/widgets/plots/{waveform/register_bec_waveform_widget.py → scatter_waveform/register_scatter_waveform.py} +3 -3
  112. bec_widgets/widgets/plots/scatter_waveform/scatter_curve.py +197 -0
  113. bec_widgets/widgets/plots/scatter_waveform/scatter_waveform.py +553 -0
  114. bec_widgets/widgets/plots/scatter_waveform/scatter_waveform.pyproject +1 -0
  115. bec_widgets/widgets/plots/{image/bec_image_widget_plugin.py → scatter_waveform/scatter_waveform_plugin.py} +9 -13
  116. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_setting.py +138 -0
  117. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_settings_horizontal.ui +195 -0
  118. bec_widgets/widgets/plots/scatter_waveform/settings/scatter_curve_settings_vertical.ui +204 -0
  119. bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings.py +8 -8
  120. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/mouse_interactions.py +4 -18
  121. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/plot_export.py +14 -3
  122. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/roi_bundle.py +6 -1
  123. bec_widgets/widgets/{plots_next_gen → plots}/toolbar_bundles/save_state.py +2 -2
  124. bec_widgets/widgets/{containers/figure/plots/waveform/waveform_curve.py → plots/waveform/curve.py} +119 -49
  125. bec_widgets/widgets/plots/waveform/register_waveform.py +15 -0
  126. bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_setting.py +125 -0
  127. bec_widgets/widgets/plots/waveform/settings/curve_settings/curve_tree.py +576 -0
  128. bec_widgets/widgets/plots/waveform/utils/__init__.py +0 -0
  129. bec_widgets/widgets/plots/waveform/utils/roi_manager.py +84 -0
  130. bec_widgets/widgets/plots/waveform/waveform.py +1794 -0
  131. bec_widgets/widgets/plots/waveform/waveform.pyproject +1 -0
  132. bec_widgets/widgets/plots/waveform/{bec_waveform_widget_plugin.py → waveform_plugin.py} +9 -13
  133. bec_widgets/widgets/progress/bec_progressbar/bec_progressbar.py +1 -2
  134. bec_widgets/widgets/progress/ring_progress_bar/ring.py +11 -10
  135. bec_widgets/widgets/progress/ring_progress_bar/ring_progress_bar.py +24 -14
  136. bec_widgets/widgets/services/bec_queue/bec_queue.py +13 -11
  137. bec_widgets/widgets/services/bec_status_box/bec_status_box.py +3 -4
  138. bec_widgets/widgets/services/device_browser/device_browser.py +5 -2
  139. bec_widgets/widgets/services/device_browser/device_item/device_item.py +1 -1
  140. bec_widgets/widgets/utility/logpanel/logpanel.py +36 -17
  141. bec_widgets/widgets/utility/spinbox/decimal_spinbox.py +3 -3
  142. bec_widgets/widgets/utility/visual/color_button/color_button.py +1 -1
  143. bec_widgets/widgets/utility/visual/colormap_widget/colormap_widget.py +4 -6
  144. bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.py +4 -8
  145. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/METADATA +3 -3
  146. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/RECORD +168 -153
  147. pyproject.toml +3 -3
  148. bec_widgets/applications/alignment/alignment_1d/alignment_1d.py +0 -198
  149. bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui +0 -615
  150. bec_widgets/applications/bec_app.py +0 -84
  151. bec_widgets/cli/auto_updates.py +0 -168
  152. bec_widgets/widgets/containers/figure/__init__.py +0 -1
  153. bec_widgets/widgets/containers/figure/figure.py +0 -796
  154. bec_widgets/widgets/containers/figure/plots/axis_settings.py +0 -91
  155. bec_widgets/widgets/containers/figure/plots/axis_settings.ui +0 -256
  156. bec_widgets/widgets/containers/figure/plots/image/image.py +0 -772
  157. bec_widgets/widgets/containers/figure/plots/image/image_item.py +0 -337
  158. bec_widgets/widgets/containers/figure/plots/motor_map/motor_map.py +0 -525
  159. bec_widgets/widgets/containers/figure/plots/multi_waveform/multi_waveform.py +0 -340
  160. bec_widgets/widgets/containers/figure/plots/plot_base.py +0 -505
  161. bec_widgets/widgets/containers/figure/plots/waveform/waveform.py +0 -1563
  162. bec_widgets/widgets/plots/image/bec_image_widget.pyproject +0 -1
  163. bec_widgets/widgets/plots/image/image_widget.py +0 -515
  164. bec_widgets/widgets/plots/motor_map/bec_motor_map_widget.pyproject +0 -1
  165. bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.py +0 -56
  166. bec_widgets/widgets/plots/motor_map/motor_map_dialog/motor_map_settings.ui +0 -108
  167. bec_widgets/widgets/plots/motor_map/motor_map_widget.py +0 -234
  168. bec_widgets/widgets/plots/multi_waveform/bec_multi_waveform_widget.pyproject +0 -1
  169. bec_widgets/widgets/plots/multi_waveform/multi_waveform_controls.ui +0 -99
  170. bec_widgets/widgets/plots/multi_waveform/multi_waveform_widget.py +0 -536
  171. bec_widgets/widgets/plots/waveform/bec_waveform_widget.pyproject +0 -1
  172. bec_widgets/widgets/plots/waveform/waveform_popups/curve_dialog/curve_dialog.py +0 -336
  173. bec_widgets/widgets/plots/waveform/waveform_popups/curve_dialog/curve_dialog.ui +0 -372
  174. bec_widgets/widgets/plots/waveform/waveform_popups/dap_summary_dialog/dap_summary_dialog.py +0 -25
  175. bec_widgets/widgets/plots/waveform/waveform_widget.py +0 -751
  176. /bec_widgets/{qt_utils → utils}/collapsible_panel_manager.py +0 -0
  177. /bec_widgets/{applications/alignment → utils/forms_from_types}/__init__.py +0 -0
  178. /bec_widgets/{qt_utils → utils}/redis_message_waiter.py +0 -0
  179. /bec_widgets/{applications/alignment/alignment_1d → widgets/containers/auto_update}/__init__.py +0 -0
  180. /bec_widgets/{qt_utils → widgets/containers/main_window/addons}/__init__.py +0 -0
  181. /bec_widgets/widgets/{containers/figure/plots → plots/image/toolbar_bundles}/__init__.py +0 -0
  182. /bec_widgets/widgets/{containers/figure/plots/image → plots/motor_map/settings}/__init__.py +0 -0
  183. /bec_widgets/widgets/{containers/figure/plots/motor_map → plots/motor_map/toolbar_bundles}/__init__.py +0 -0
  184. /bec_widgets/widgets/{containers/figure/plots/multi_waveform → plots/multi_waveform/settings}/__init__.py +0 -0
  185. /bec_widgets/widgets/{containers/figure/plots/waveform → plots/multi_waveform/toolbar_bundles}/__init__.py +0 -0
  186. /bec_widgets/widgets/plots/{motor_map/motor_map_dialog → scatter_waveform}/__init__.py +0 -0
  187. /bec_widgets/widgets/plots/{waveform/waveform_popups → scatter_waveform/settings}/__init__.py +0 -0
  188. /bec_widgets/widgets/plots/{waveform/waveform_popups/curve_dialog → setting_menus}/__init__.py +0 -0
  189. /bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings_horizontal.ui +0 -0
  190. /bec_widgets/widgets/{plots_next_gen → plots}/setting_menus/axis_settings_vertical.ui +0 -0
  191. /bec_widgets/widgets/plots/{waveform/waveform_popups/dap_summary_dialog → toolbar_bundles}/__init__.py +0 -0
  192. /bec_widgets/widgets/{plots_next_gen/setting_menus → plots/waveform/settings}/__init__.py +0 -0
  193. /bec_widgets/widgets/{plots_next_gen/toolbar_bundles → plots/waveform/settings/curve_settings}/__init__.py +0 -0
  194. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/WHEEL +0 -0
  195. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/entry_points.txt +0 -0
  196. {bec_widgets-1.25.1.dist-info → bec_widgets-2.0.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1 @@
1
+ {'files': ['motor_map.py']}
@@ -0,0 +1,54 @@
1
+ # Copyright (C) 2022 The Qt Company Ltd.
2
+ # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+
4
+ from qtpy.QtDesigner import QDesignerCustomWidgetInterface
5
+
6
+ from bec_widgets.utils.bec_designer import designer_material_icon
7
+ from bec_widgets.widgets.plots.motor_map.motor_map import MotorMap
8
+
9
+ DOM_XML = """
10
+ <ui language='c++'>
11
+ <widget class='MotorMap' name='motor_map'>
12
+ </widget>
13
+ </ui>
14
+ """
15
+
16
+
17
+ class MotorMapPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
18
+ def __init__(self):
19
+ super().__init__()
20
+ self._form_editor = None
21
+
22
+ def createWidget(self, parent):
23
+ t = MotorMap(parent)
24
+ return t
25
+
26
+ def domXml(self):
27
+ return DOM_XML
28
+
29
+ def group(self):
30
+ return "Plot Widgets"
31
+
32
+ def icon(self):
33
+ return designer_material_icon(MotorMap.ICON_NAME)
34
+
35
+ def includeFile(self):
36
+ return "motor_map"
37
+
38
+ def initialize(self, form_editor):
39
+ self._form_editor = form_editor
40
+
41
+ def isContainer(self):
42
+ return False
43
+
44
+ def isInitialized(self):
45
+ return self._form_editor is not None
46
+
47
+ def name(self):
48
+ return "MotorMap"
49
+
50
+ def toolTip(self):
51
+ return "MotorMap"
52
+
53
+ def whatsThis(self):
54
+ return self.toolTip()
@@ -6,11 +6,9 @@ def main(): # pragma: no cover
6
6
  return
7
7
  from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
8
 
9
- from bec_widgets.widgets.plots.multi_waveform.bec_multi_waveform_widget_plugin import (
10
- BECMultiWaveformWidgetPlugin,
11
- )
9
+ from bec_widgets.widgets.plots.motor_map.motor_map_plugin import MotorMapPlugin
12
10
 
13
- QPyDesignerCustomWidgetCollection.addCustomWidget(BECMultiWaveformWidgetPlugin())
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(MotorMapPlugin())
14
12
 
15
13
 
16
14
  if __name__ == "__main__": # pragma: no cover
@@ -0,0 +1,129 @@
1
+ import os
2
+
3
+ from qtpy.QtWidgets import QFrame, QScrollArea, QVBoxLayout, QWidget
4
+
5
+ from bec_widgets.utils import UILoader
6
+ from bec_widgets.utils.error_popups import SafeSlot
7
+ from bec_widgets.utils.settings_dialog import SettingWidget
8
+ from bec_widgets.utils.widget_io import WidgetIO
9
+
10
+
11
+ class MotorMapSettings(SettingWidget):
12
+ """
13
+ A settings widget for the MotorMap widget.
14
+
15
+ The widget has skip_settings property set to True, which means it should not be saved
16
+ in the settings file. It is used to mirror the properties of the target widget.
17
+ """
18
+
19
+ def __init__(self, parent=None, target_widget=None, popup=False, *args, **kwargs):
20
+ super().__init__(parent=parent, *args, **kwargs)
21
+
22
+ self.setProperty("skip_settings", True)
23
+ current_path = os.path.dirname(__file__)
24
+
25
+ form = UILoader().load_ui(os.path.join(current_path, "motor_map_settings.ui"), self)
26
+
27
+ self.target_widget = target_widget
28
+ self.popup = popup
29
+
30
+ # # Scroll area
31
+ self.scroll_area = QScrollArea(self)
32
+ self.scroll_area.setWidgetResizable(True)
33
+ self.scroll_area.setFrameShape(QFrame.NoFrame)
34
+ self.scroll_area.setWidget(form)
35
+
36
+ self.layout = QVBoxLayout(self)
37
+ self.layout.setContentsMargins(0, 0, 0, 0)
38
+ self.layout.addWidget(self.scroll_area)
39
+ self.ui = form
40
+
41
+ self.ui_widget_list = [
42
+ self.ui.max_points,
43
+ self.ui.num_dim_points,
44
+ self.ui.precision,
45
+ self.ui.scatter_size,
46
+ self.ui.background_value,
47
+ ]
48
+
49
+ if self.target_widget is not None and self.popup is False:
50
+ self.connect_all_signals()
51
+ self.target_widget.property_changed.connect(self.update_property)
52
+
53
+ self.fetch_all_properties()
54
+
55
+ def connect_all_signals(self):
56
+ for widget in self.ui_widget_list:
57
+ WidgetIO.connect_widget_change_signal(widget, self.set_property)
58
+ self.ui.color_scatter.color_selected.connect(
59
+ lambda color: self.target_widget.setProperty("color_scatter", color)
60
+ )
61
+
62
+ @SafeSlot()
63
+ def set_property(self, widget: QWidget, value):
64
+ """
65
+ Set property of the target widget based on the widget that emitted the signal.
66
+ The name of the property has to be the same as the objectName of the widget
67
+ and compatible with WidgetIO.
68
+
69
+ Args:
70
+ widget(QWidget): The widget that emitted the signal.
71
+ value(): The value to set the property to.
72
+ """
73
+
74
+ try: # to avoid crashing when the widget is not found in Designer
75
+ property_name = widget.objectName()
76
+ setattr(self.target_widget, property_name, value)
77
+ except RuntimeError:
78
+ return
79
+ if property_name == "color_scatter":
80
+ # Update the color scatter button
81
+ self.ui.color_scatter.set_color(value)
82
+
83
+ @SafeSlot()
84
+ def update_property(self, property_name: str, value):
85
+ """
86
+ Update the value of the widget based on the property name and value.
87
+ The name of the property has to be the same as the objectName of the widget
88
+ and compatible with WidgetIO.
89
+
90
+ Args:
91
+ property_name(str): The name of the property to update.
92
+ value: The value to set the property to.
93
+ """
94
+ try: # to avoid crashing when the widget is not found in Designer
95
+ widget_to_set = self.ui.findChild(QWidget, property_name)
96
+ except RuntimeError:
97
+ return
98
+ if widget_to_set is None:
99
+ return
100
+ if widget_to_set is self.ui.color_scatter:
101
+ # Update the color scatter button
102
+ self.ui.color_scatter.set_color(value)
103
+ return
104
+ # Block signals to avoid triggering set_property again
105
+ was_blocked = widget_to_set.blockSignals(True)
106
+ WidgetIO.set_value(widget_to_set, value)
107
+ widget_to_set.blockSignals(was_blocked)
108
+
109
+ def fetch_all_properties(self):
110
+ """
111
+ Fetch all properties from the target widget and update the settings widget.
112
+ """
113
+ for widget in self.ui_widget_list:
114
+ property_name = widget.objectName()
115
+ value = getattr(self.target_widget, property_name)
116
+ WidgetIO.set_value(widget, value)
117
+
118
+ self.ui.color_scatter.set_color(self.target_widget.color)
119
+
120
+ def accept_changes(self):
121
+ """
122
+ Apply all properties from the settings widget to the target widget.
123
+ """
124
+ for widget in self.ui_widget_list:
125
+ property_name = widget.objectName()
126
+ value = WidgetIO.get_value(widget)
127
+ setattr(self.target_widget, property_name, value)
128
+
129
+ self.target_widget.color_scatter = self.ui.color_scatter.get_color()
@@ -0,0 +1,120 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>235</width>
10
+ <height>228</height>
11
+ </rect>
12
+ </property>
13
+ <property name="minimumSize">
14
+ <size>
15
+ <width>0</width>
16
+ <height>228</height>
17
+ </size>
18
+ </property>
19
+ <property name="maximumSize">
20
+ <size>
21
+ <width>16777215</width>
22
+ <height>228</height>
23
+ </size>
24
+ </property>
25
+ <property name="windowTitle">
26
+ <string>Form</string>
27
+ </property>
28
+ <layout class="QGridLayout" name="gridLayout">
29
+ <item row="0" column="0">
30
+ <widget class="QLabel" name="max_point_label">
31
+ <property name="text">
32
+ <string>Max Points</string>
33
+ </property>
34
+ </widget>
35
+ </item>
36
+ <item row="0" column="1">
37
+ <widget class="QSpinBox" name="max_points">
38
+ <property name="maximum">
39
+ <number>10000</number>
40
+ </property>
41
+ </widget>
42
+ </item>
43
+ <item row="1" column="0">
44
+ <widget class="QLabel" name="trace_label">
45
+ <property name="text">
46
+ <string>Trace Dim</string>
47
+ </property>
48
+ </widget>
49
+ </item>
50
+ <item row="1" column="1">
51
+ <widget class="QSpinBox" name="num_dim_points">
52
+ <property name="maximum">
53
+ <number>1000</number>
54
+ </property>
55
+ </widget>
56
+ </item>
57
+ <item row="2" column="0">
58
+ <widget class="QLabel" name="precision_label">
59
+ <property name="text">
60
+ <string>Precision</string>
61
+ </property>
62
+ </widget>
63
+ </item>
64
+ <item row="2" column="1">
65
+ <widget class="QSpinBox" name="precision">
66
+ <property name="maximum">
67
+ <number>15</number>
68
+ </property>
69
+ </widget>
70
+ </item>
71
+ <item row="3" column="0">
72
+ <widget class="QLabel" name="scatter_size_label">
73
+ <property name="text">
74
+ <string>Scatter Size</string>
75
+ </property>
76
+ </widget>
77
+ </item>
78
+ <item row="3" column="1">
79
+ <widget class="QSpinBox" name="scatter_size">
80
+ <property name="maximum">
81
+ <number>20</number>
82
+ </property>
83
+ </widget>
84
+ </item>
85
+ <item row="4" column="0">
86
+ <widget class="QLabel" name="background_label">
87
+ <property name="text">
88
+ <string>Background Intensity</string>
89
+ </property>
90
+ </widget>
91
+ </item>
92
+ <item row="4" column="1">
93
+ <widget class="QSpinBox" name="background_value">
94
+ <property name="maximum">
95
+ <number>100</number>
96
+ </property>
97
+ </widget>
98
+ </item>
99
+ <item row="5" column="0">
100
+ <widget class="QLabel" name="color_label">
101
+ <property name="text">
102
+ <string>Color</string>
103
+ </property>
104
+ </widget>
105
+ </item>
106
+ <item row="5" column="1">
107
+ <widget class="ColorButton" name="color_scatter"/>
108
+ </item>
109
+ </layout>
110
+ </widget>
111
+ <customwidgets>
112
+ <customwidget>
113
+ <class>ColorButton</class>
114
+ <extends>QWidget</extends>
115
+ <header>color_button</header>
116
+ </customwidget>
117
+ </customwidgets>
118
+ <resources/>
119
+ <connections/>
120
+ </ui>
@@ -0,0 +1,70 @@
1
+ from bec_lib.device import ReadoutPriority
2
+ from qtpy.QtCore import Qt
3
+ from qtpy.QtWidgets import QStyledItemDelegate
4
+
5
+ from bec_widgets.utils.error_popups import SafeSlot
6
+ from bec_widgets.utils.toolbar import ToolbarBundle, WidgetAction
7
+ from bec_widgets.widgets.control.device_input.base_classes.device_input_base import BECDeviceFilter
8
+ from bec_widgets.widgets.control.device_input.device_combobox.device_combobox import DeviceComboBox
9
+
10
+
11
+ class NoCheckDelegate(QStyledItemDelegate):
12
+ """To reduce space in combo boxes by removing the checkmark."""
13
+
14
+ def initStyleOption(self, option, index):
15
+ super().initStyleOption(option, index)
16
+ # Remove any check indicator
17
+ option.checkState = Qt.Unchecked
18
+
19
+
20
+ class MotorSelectionToolbarBundle(ToolbarBundle):
21
+ """
22
+ A bundle of actions for a toolbar that selects motors.
23
+ """
24
+
25
+ def __init__(self, bundle_id="motor_selection", target_widget=None, **kwargs):
26
+ super().__init__(bundle_id=bundle_id, actions=[], **kwargs)
27
+ self.target_widget = target_widget
28
+
29
+ # Motor X
30
+ self.motor_x = DeviceComboBox(
31
+ parent=self.target_widget, device_filter=[BECDeviceFilter.POSITIONER]
32
+ )
33
+ self.motor_x.addItem("", None)
34
+ self.motor_x.setCurrentText("")
35
+ self.motor_x.setToolTip("Select Motor X")
36
+ self.motor_x.setItemDelegate(NoCheckDelegate(self.motor_x))
37
+
38
+ # Motor X
39
+ self.motor_y = DeviceComboBox(
40
+ parent=self.target_widget, device_filter=[BECDeviceFilter.POSITIONER]
41
+ )
42
+ self.motor_y.addItem("", None)
43
+ self.motor_y.setCurrentText("")
44
+ self.motor_y.setToolTip("Select Motor Y")
45
+ self.motor_y.setItemDelegate(NoCheckDelegate(self.motor_y))
46
+
47
+ self.add_action("motor_x", WidgetAction(widget=self.motor_x, adjust_size=False))
48
+ self.add_action("motor_y", WidgetAction(widget=self.motor_y, adjust_size=False))
49
+
50
+ # Connect slots, a device will be connected upon change of any combobox
51
+ self.motor_x.currentTextChanged.connect(lambda: self.connect_motors())
52
+ self.motor_y.currentTextChanged.connect(lambda: self.connect_motors())
53
+
54
+ @SafeSlot()
55
+ def connect_motors(self):
56
+ motor_x = self.motor_x.currentText()
57
+ motor_y = self.motor_y.currentText()
58
+
59
+ if motor_x != "" and motor_y != "":
60
+ if (
61
+ motor_x != self.target_widget.config.x_motor.name
62
+ or motor_y != self.target_widget.config.y_motor.name
63
+ ):
64
+ self.target_widget.map(motor_x, motor_y)
65
+
66
+ def cleanup(self):
67
+ self.motor_x.close()
68
+ self.motor_x.deleteLater()
69
+ self.motor_y.close()
70
+ self.motor_y.deleteLater()