bec-widgets 0.94.7__py3-none-any.whl → 0.95.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 (125) hide show
  1. CHANGELOG.md +46 -44
  2. PKG-INFO +1 -1
  3. bec_widgets/cli/client.py +19 -0
  4. bec_widgets/examples/plugin_example_pyside/tictactoeplugin.py +5 -3
  5. bec_widgets/widgets/bec_queue/bec_queue_plugin.py +5 -3
  6. bec_widgets/widgets/bec_status_box/bec_status_box_plugin.py +5 -3
  7. bec_widgets/widgets/color_button/color_button_plugin.py +5 -3
  8. bec_widgets/widgets/colormap_selector/colormap_selector_plugin.py +5 -3
  9. bec_widgets/widgets/device_browser/__init__.py +0 -0
  10. bec_widgets/widgets/device_browser/device_browser.py +107 -0
  11. bec_widgets/widgets/device_browser/device_browser.pyproject +1 -0
  12. bec_widgets/widgets/device_browser/device_browser.ui +44 -0
  13. bec_widgets/widgets/device_browser/device_browser_plugin.py +57 -0
  14. bec_widgets/widgets/device_browser/device_item/__init__.py +1 -0
  15. bec_widgets/widgets/device_browser/device_item/device_item.py +53 -0
  16. bec_widgets/widgets/device_browser/register_device_browser.py +15 -0
  17. bec_widgets/widgets/device_combobox/device_combo_box_plugin.py +5 -3
  18. bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py +5 -3
  19. bec_widgets/widgets/dock/dock_area_plugin.py +5 -3
  20. bec_widgets/widgets/image/bec_image_widget_plugin.py +5 -3
  21. bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py +5 -3
  22. bec_widgets/widgets/position_indicator/position_indicator_plugin.py +5 -3
  23. bec_widgets/widgets/positioner_box/positioner_box_plugin.py +5 -3
  24. bec_widgets/widgets/positioner_box/positioner_control_line_plugin.py +5 -3
  25. bec_widgets/widgets/ring_progress_bar/ring_progress_bar_plugin.py +5 -3
  26. bec_widgets/widgets/scan_control/scan_control_plugin.py +5 -3
  27. bec_widgets/widgets/spinner/spinner_widget_plugin.py +5 -3
  28. bec_widgets/widgets/stop_button/stop_button_plugin.py +5 -3
  29. bec_widgets/widgets/text_box/text_box_plugin.py +5 -3
  30. bec_widgets/widgets/toggle/toggle_switch_plugin.py +5 -3
  31. bec_widgets/widgets/vscode/vs_code_editor_plugin.py +5 -3
  32. bec_widgets/widgets/waveform/bec_waveform_widget_plugin.py +5 -3
  33. bec_widgets/widgets/website/website_widget_plugin.py +5 -3
  34. {bec_widgets-0.94.7.dist-info → bec_widgets-0.95.1.dist-info}/METADATA +1 -1
  35. {bec_widgets-0.94.7.dist-info → bec_widgets-0.95.1.dist-info}/RECORD +97 -77
  36. docs/_static/custom.css +10 -10
  37. docs/assets/widget_screenshots/buttons.png +0 -0
  38. docs/assets/widget_screenshots/device_box.png +0 -0
  39. docs/assets/widget_screenshots/device_browser.png +0 -0
  40. docs/assets/widget_screenshots/device_inputs.png +0 -0
  41. docs/assets/widget_screenshots/dock_area.png +0 -0
  42. docs/assets/widget_screenshots/figure.png +0 -0
  43. docs/assets/widget_screenshots/image_widget.png +0 -0
  44. docs/assets/widget_screenshots/motor_map_widget.png +0 -0
  45. docs/assets/widget_screenshots/position_indicator.png +0 -0
  46. docs/assets/widget_screenshots/queue.png +0 -0
  47. docs/assets/widget_screenshots/ring_progress_bar.png +0 -0
  48. docs/assets/widget_screenshots/scan_controller.png +0 -0
  49. docs/assets/widget_screenshots/spinner.gif +0 -0
  50. docs/assets/widget_screenshots/status_box.png +0 -0
  51. docs/assets/widget_screenshots/text_box.png +0 -0
  52. docs/assets/widget_screenshots/toggle.png +0 -0
  53. docs/assets/widget_screenshots/waveform_widget.png +0 -0
  54. docs/assets/widget_screenshots/website.png +0 -0
  55. docs/conf.py +1 -0
  56. docs/developer/developer.md +2 -0
  57. docs/developer/introduction/introduction.md +1 -0
  58. docs/developer/introduction/useful_links.md +23 -0
  59. docs/index.md +4 -0
  60. docs/requirements.txt +1 -0
  61. docs/user/user.md +4 -0
  62. docs/user/widgets/bec_figure/bec_figure.md +105 -0
  63. docs/user/widgets/bec_status_box/bec_status_box.md +38 -0
  64. docs/user/widgets/buttons/buttons.md +50 -0
  65. docs/user/widgets/device_browser/device_browser.md +36 -0
  66. docs/user/widgets/device_browser/device_browser.png +0 -0
  67. docs/user/widgets/device_input/device_input.md +100 -0
  68. docs/user/widgets/dock_area/BECDockArea.png +0 -0
  69. docs/user/widgets/dock_area/bec_dock_area.md +107 -0
  70. docs/user/widgets/image/image_widget.md +84 -0
  71. docs/user/widgets/motor_map/motor_map.md +80 -0
  72. docs/user/widgets/position_indicator/position_indicator.md +76 -0
  73. docs/user/widgets/positioner_box/positioner_box.md +63 -0
  74. docs/user/widgets/progress_bar/ring_progress_bar.md +103 -0
  75. docs/user/widgets/queue/queue.md +41 -0
  76. docs/user/widgets/scan_control/scan_control.md +46 -0
  77. docs/user/widgets/spinner/spinner.md +75 -0
  78. docs/user/widgets/text_box/text_box.md +74 -0
  79. docs/user/widgets/toggle/toggle.md +66 -0
  80. docs/user/widgets/waveform/waveform_widget.md +132 -0
  81. docs/user/widgets/website/website.md +69 -0
  82. docs/user/widgets/widgets.md +212 -12
  83. pyproject.toml +1 -1
  84. tests/unit_tests/client_mocks.py +14 -0
  85. tests/unit_tests/test_device_browser.py +83 -0
  86. bec_widgets/assets/designer_icons/code.png +0 -0
  87. bec_widgets/assets/designer_icons/color_button.png +0 -0
  88. bec_widgets/assets/designer_icons/colormap_selector.png +0 -0
  89. bec_widgets/assets/designer_icons/device_combo_box.png +0 -0
  90. bec_widgets/assets/designer_icons/device_line_edit.png +0 -0
  91. bec_widgets/assets/designer_icons/dock_area.png +0 -0
  92. bec_widgets/assets/designer_icons/games.png +0 -0
  93. bec_widgets/assets/designer_icons/image.png +0 -0
  94. bec_widgets/assets/designer_icons/motor_map.png +0 -0
  95. bec_widgets/assets/designer_icons/position_indicator.png +0 -0
  96. bec_widgets/assets/designer_icons/positioner_box.png +0 -0
  97. bec_widgets/assets/designer_icons/queue.png +0 -0
  98. bec_widgets/assets/designer_icons/ring_progress.png +0 -0
  99. bec_widgets/assets/designer_icons/scan_control.png +0 -0
  100. bec_widgets/assets/designer_icons/spinner.png +0 -0
  101. bec_widgets/assets/designer_icons/status.png +0 -0
  102. bec_widgets/assets/designer_icons/stop.png +0 -0
  103. bec_widgets/assets/designer_icons/text.png +0 -0
  104. bec_widgets/assets/designer_icons/toggle.png +0 -0
  105. bec_widgets/assets/designer_icons/waveform.png +0 -0
  106. bec_widgets/assets/designer_icons/web.png +0 -0
  107. docs/user/widgets/bec_figure.md +0 -146
  108. docs/user/widgets/bec_status_box.md +0 -30
  109. docs/user/widgets/buttons.md +0 -37
  110. docs/user/widgets/ring_progress_bar.md +0 -54
  111. docs/user/widgets/scan_control.md +0 -35
  112. docs/user/widgets/text_box.md +0 -33
  113. docs/user/widgets/website.md +0 -21
  114. {bec_widgets-0.94.7.dist-info → bec_widgets-0.95.1.dist-info}/WHEEL +0 -0
  115. {bec_widgets-0.94.7.dist-info → bec_widgets-0.95.1.dist-info}/entry_points.txt +0 -0
  116. {bec_widgets-0.94.7.dist-info → bec_widgets-0.95.1.dist-info}/licenses/LICENSE +0 -0
  117. /docs/user/widgets/{BECFigure.png → bec_figure/BECFigure.png} +0 -0
  118. /docs/user/widgets/{bec_status_box.gif → bec_status_box/bec_status_box.gif} +0 -0
  119. /docs/user/widgets/{image_plot.gif → image/image_plot.gif} +0 -0
  120. /docs/user/widgets/{motor.gif → motor_map/motor.gif} +0 -0
  121. /docs/user/widgets/{progress_bar.gif → progress_bar/progress_bar.gif} +0 -0
  122. /docs/user/widgets/{scan_control.gif → scan_control/scan_control.gif} +0 -0
  123. /docs/user/widgets/{bec_figure_dap.gif → waveform/bec_figure_dap.gif} +0 -0
  124. /docs/user/widgets/{scatter_2D.gif → waveform/scatter_2D.gif} +0 -0
  125. /docs/user/widgets/{w1D.gif → waveform/w1D.gif} +0 -0
CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.95.1 (2024-08-22)
4
+
5
+ ### Documentation
6
+
7
+ * docs: links section added ([`2bf5c70`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2bf5c7096e7d822713e1b50bde89f072e6356e17))
8
+
9
+ ### Fix
10
+
11
+ * fix(docs): changed link to scan gui config in main docs ([`640464a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/640464a6543b2111bdb58d0174f2ce86c5836cbe))
12
+
13
+ ### Refactor
14
+
15
+ * refactor: removed designer pngs ([`84abe46`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/84abe460502d838aac41bb8ff63d93c9fcec9214))
16
+
17
+ * refactor: moved to dynamically loaded material design icons ([`1d2afaa`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1d2afaa09e64b7f714d72796e87e2cb49b2a75a7))
18
+
19
+ ## v0.95.0 (2024-08-21)
20
+
21
+ ### Documentation
22
+
23
+ * docs(device_browser): added user docs ([`2c31cc9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2c31cc90ae751f14a653cbbdd6c353d6359aaafe))
24
+
25
+ * docs(user): widget gallery with documentation added ([`7357f3d`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/7357f3d2a189f9f04954a027f39ce07c394d57ec))
26
+
27
+ * docs: added sphinx-inline-tabs as sphinx dependency ([`e9ecd26`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e9ecd268c602ea9572df0e8d508e49ee62d0c170))
28
+
29
+ * docs(cards): changed index cards to custom css class instead of overwriting the default sd-card theme ([`91ba30e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/91ba30e8d054a9c7f6c6d98b21113a5d0b1bbbbb))
30
+
31
+ ### Feature
32
+
33
+ * feat(cli): added device_browser to cli ([`196504b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/196504b533367a899c19b88af4ccd5b39dc46aac))
34
+
35
+ * feat(widgets): added device_browser widget ([`73f5a2f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/73f5a2f085b289ac18fa8a918b6ad7cfed595fb4))
36
+
37
+ ### Fix
38
+
39
+ * fix(device_browser): fixed plugin assignment for designer ([`6500393`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/650039303aae9bbec62c676285938416fff146ce))
40
+
41
+ ### Refactor
42
+
43
+ * refactor(docs): review response ([`4790afd`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4790afde3d61fc9beb073c2775c339d4f80779e3))
44
+
45
+ ### Test
46
+
47
+ * test: added test for device browser ([`e870e5b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e870e5ba083c61df581c9c0305adabe72967f997))
48
+
3
49
  ## v0.94.7 (2024-08-20)
4
50
 
5
51
  ### Fix
@@ -106,52 +152,8 @@ Terminating client connections has to be done at the application level ([`198c1d
106
152
 
107
153
  * fix(website): fixed teardown of website widgets ([`a3d4f5a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a3d4f5ac4bc52acfed2791a1724fade6972ed320))
108
154
 
109
- * fix(dock): properly shut down docks and dock areas ([`bc26497`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc264975b1363c9dfea516621d7878c320677d15))
110
-
111
- * fix(figure): cleanup pyqtgraph ([`ad07bbf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ad07bbf85e9c8d9838bdd686f69d41c235b7db19))
112
-
113
155
  ### Test
114
156
 
115
157
  * test: removed quit from teardown ([`cf94599`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/cf94599c2544d6831c8afbe7b340082077557ed1))
116
158
 
117
159
  * test: removed explicit call to close the widget ([`bf6294e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bf6294ecbfd494565d2dc215e4d7e0c280ac7745))
118
-
119
- * test: use factory instead of fixture to properly cleanup widgets on teardown ([`9856857`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9856857f4cc7fa229c10d00fbae4452464a207cb))
120
-
121
- * test: ensure all toplevelwidgets are closed ([`f9e5897`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/f9e58979009cf632feea529700ad191401dd7eb8))
122
-
123
- ## v0.93.2 (2024-08-07)
124
-
125
- ### Fix
126
-
127
- * fix(scan_group_box): Scan Spinboxes limits increased to max allowed values; setting dialog for step size and decimal precision for ScanDoubleSpinBox on right click ([`a372925`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a372925fffa787c686198ae7cb3f9c15b459c109))
128
-
129
- ## v0.93.1 (2024-08-06)
130
-
131
- ### Documentation
132
-
133
- * docs: added video tutorial section with BSEG YT video ([`302ae90`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/302ae90139f6a88e2401fe29fe312387486e27a9))
134
-
135
- ### Fix
136
-
137
- * fix(dock): docks have more recognizable red icon for closing docks ([`af86860`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/af86860bf35474805fb1a7bc3725cf8835ed4cc7))
138
-
139
- ## v0.93.0 (2024-08-05)
140
-
141
- ### Feature
142
-
143
- * feat(themes): moved themes to bec_qthemes
144
-
145
- This reverts commit fd6ae91993a23a7b8dbb2cf3c4b7c3eda6d2b0f6 ([`5aad401`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5aad401ef8774c7330784f72cd3b9d8c253e2b6a))
146
-
147
- ## v0.92.5 (2024-08-05)
148
-
149
- ### Fix
150
-
151
- * fix(spinner): stop timer on close event ([`30fef92`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/30fef929cf6fb4b73f48151c92a0ee54c734031d))
152
-
153
- * fix(status_box): fix cleanup of status box ([`1f30dd7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1f30dd73a9c1e3135087a5eef92c7329f54a604e))
154
-
155
- ### Test
156
-
157
- * test: register all widgets with qtbot and close them ([`73cd11e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/73cd11e47277e4437554b785a9551b28a572094f))
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.94.7
3
+ Version: 0.95.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
bec_widgets/cli/client.py CHANGED
@@ -21,6 +21,7 @@ class Widgets(str, enum.Enum):
21
21
  BECQueue = "BECQueue"
22
22
  BECStatusBox = "BECStatusBox"
23
23
  BECWaveformWidget = "BECWaveformWidget"
24
+ DeviceBrowser = "DeviceBrowser"
24
25
  DeviceComboBox = "DeviceComboBox"
25
26
  DeviceLineEdit = "DeviceLineEdit"
26
27
  PositionerBox = "PositionerBox"
@@ -2288,6 +2289,24 @@ class BECWaveformWidget(RPCBase):
2288
2289
  """
2289
2290
 
2290
2291
 
2292
+ class DeviceBrowser(RPCBase):
2293
+ @property
2294
+ @rpc_call
2295
+ def _config_dict(self) -> "dict":
2296
+ """
2297
+ Get the configuration of the widget.
2298
+
2299
+ Returns:
2300
+ dict: The configuration of the widget.
2301
+ """
2302
+
2303
+ @rpc_call
2304
+ def _get_all_rpc(self) -> "dict":
2305
+ """
2306
+ Get all registered RPC objects.
2307
+ """
2308
+
2309
+
2291
2310
  class DeviceComboBox(RPCBase):
2292
2311
  @property
2293
2312
  @rpc_call
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.examples.plugin_example_pyside.tictactoe import TicTacToe
@@ -46,8 +47,9 @@ class TicTacToePlugin(QDesignerCustomWidgetInterface): # pragma: no cover
46
47
  return "Games"
47
48
 
48
49
  def icon(self):
49
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "games.png")
50
- return QIcon(icon_path)
50
+ palette = QGuiApplication.palette()
51
+ pixmap = material_icon("sports_esports", color=palette.text().color(), filled=True)
52
+ return QIcon(pixmap)
51
53
 
52
54
  def includeFile(self):
53
55
  return "tictactoe"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.bec_queue.bec_queue import BECQueue
@@ -34,8 +35,9 @@ class BECQueuePlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "BEC Services"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "device_line_edit.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("edit_note", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "bec_queue"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.bec_status_box.bec_status_box import BECStatusBox
@@ -34,8 +35,9 @@ class BECStatusBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "BEC Services"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "status.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("dns", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "bec_status_box"
@@ -1,7 +1,8 @@
1
1
  import os
2
2
 
3
+ from bec_qthemes import material_icon
3
4
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
4
- from qtpy.QtGui import QIcon
5
+ from qtpy.QtGui import QGuiApplication, QIcon
5
6
 
6
7
  import bec_widgets
7
8
  from bec_widgets.widgets.color_button.color_button import ColorButton
@@ -31,8 +32,9 @@ class ColorButtonPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
31
32
  return "BEC Buttons"
32
33
 
33
34
  def icon(self):
34
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "color_button.png")
35
- return QIcon(icon_path)
35
+ palette = QGuiApplication.palette()
36
+ pixmap = material_icon("colors", color=palette.text().color(), filled=True)
37
+ return QIcon(pixmap)
36
38
 
37
39
  def includeFile(self):
38
40
  return "color_button"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.colormap_selector.colormap_selector import ColormapSelector
@@ -34,8 +35,9 @@ class ColormapSelectorPlugin(QDesignerCustomWidgetInterface): # pragma: no cove
34
35
  return "BEC Buttons"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "colormap_selector.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("palette", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "colormap_selector"
File without changes
@@ -0,0 +1,107 @@
1
+ import os
2
+ import re
3
+ from typing import Optional
4
+
5
+ from bec_lib.callback_handler import EventType
6
+ from pyqtgraph import SignalProxy
7
+ from qtpy.QtCore import Signal, Slot
8
+ from qtpy.QtWidgets import QLineEdit, QListWidgetItem, QVBoxLayout, QWidget
9
+
10
+ from bec_widgets.utils.bec_widget import BECWidget
11
+ from bec_widgets.utils.ui_loader import UILoader
12
+ from bec_widgets.widgets.device_browser.device_item import DeviceItem
13
+
14
+
15
+ class DeviceBrowser(BECWidget, QWidget):
16
+ device_update: Signal = Signal()
17
+
18
+ def __init__(
19
+ self,
20
+ parent: Optional[QWidget] = None,
21
+ config=None,
22
+ client=None,
23
+ gui_id: Optional[str] = None,
24
+ ) -> None:
25
+ super().__init__(client=client, config=config, gui_id=gui_id)
26
+ QWidget.__init__(self, parent)
27
+
28
+ self.get_bec_shortcuts()
29
+ self.ui = None
30
+ self.ini_ui()
31
+
32
+ self.proxy_device_update = SignalProxy(
33
+ self.ui.filter_input.textChanged, rateLimit=500, slot=self.update_device_list
34
+ )
35
+ self.bec_dispatcher.client.callbacks.register(
36
+ EventType.DEVICE_UPDATE, self.on_device_update
37
+ )
38
+ self.device_update.connect(self.update_device_list)
39
+
40
+ self.update_device_list()
41
+
42
+ def ini_ui(self) -> None:
43
+ """
44
+ Initialize the UI by loading the UI file and setting the layout.
45
+ """
46
+ layout = QVBoxLayout()
47
+ layout.setContentsMargins(0, 0, 0, 0)
48
+
49
+ ui_file_path = os.path.join(os.path.dirname(__file__), "device_browser.ui")
50
+ self.ui = UILoader(self).loader(ui_file_path)
51
+ layout.addWidget(self.ui)
52
+ self.setLayout(layout)
53
+
54
+ def on_device_update(self, action: str, content: dict) -> None:
55
+ """
56
+ Callback for device update events. Triggers the device_update signal.
57
+
58
+ Args:
59
+ action (str): The action that triggered the event.
60
+ content (dict): The content of the config update.
61
+ """
62
+ if action in ["add", "remove", "reload"]:
63
+ self.device_update.emit()
64
+
65
+ @Slot()
66
+ def update_device_list(self) -> None:
67
+ """
68
+ Update the device list based on the filter input.
69
+ There are two ways to trigger this function:
70
+ 1. By changing the text in the filter input.
71
+ 2. By emitting the device_update signal.
72
+
73
+ Either way, the function will filter the devices based on the filter input text and update the device list.
74
+ """
75
+ filter_text = self.ui.filter_input.text()
76
+ try:
77
+ regex = re.compile(filter_text, re.IGNORECASE)
78
+ except re.error:
79
+ regex = None # Invalid regex, disable filtering
80
+
81
+ dev_list = self.ui.device_list
82
+ dev_list.clear()
83
+ for device in self.dev:
84
+ if regex is None or regex.search(device):
85
+ item = QListWidgetItem(dev_list)
86
+ device_item = DeviceItem(device)
87
+
88
+ # pylint: disable=protected-access
89
+ tooltip = self.dev[device]._config.get("description", "")
90
+ device_item.setToolTip(tooltip)
91
+ item.setSizeHint(device_item.sizeHint())
92
+ dev_list.setItemWidget(item, device_item)
93
+ dev_list.addItem(item)
94
+
95
+
96
+ if __name__ == "__main__": # pragma: no cover
97
+ import sys
98
+
99
+ from qtpy.QtWidgets import QApplication
100
+
101
+ from bec_widgets.utils.colors import apply_theme
102
+
103
+ app = QApplication(sys.argv)
104
+ apply_theme("light")
105
+ widget = DeviceBrowser()
106
+ widget.show()
107
+ sys.exit(app.exec_())
@@ -0,0 +1 @@
1
+ {'files': ['device_browser.py']}
@@ -0,0 +1,44 @@
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>406</width>
10
+ <height>500</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Form</string>
15
+ </property>
16
+ <layout class="QVBoxLayout" name="verticalLayout">
17
+ <item>
18
+ <widget class="QGroupBox" name="browser_group_box">
19
+ <property name="title">
20
+ <string>Device Browser</string>
21
+ </property>
22
+ <layout class="QVBoxLayout" name="verticalLayout_2">
23
+ <item>
24
+ <layout class="QHBoxLayout" name="filter_layout">
25
+ <item>
26
+ <widget class="QLineEdit" name="filter_input">
27
+ <property name="placeholderText">
28
+ <string>Filter</string>
29
+ </property>
30
+ </widget>
31
+ </item>
32
+ </layout>
33
+ </item>
34
+ <item>
35
+ <widget class="QListWidget" name="device_list"/>
36
+ </item>
37
+ </layout>
38
+ </widget>
39
+ </item>
40
+ </layout>
41
+ </widget>
42
+ <resources/>
43
+ <connections/>
44
+ </ui>
@@ -0,0 +1,57 @@
1
+ # Copyright (C) 2022 The Qt Company Ltd.
2
+ # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+
4
+ from bec_qthemes import material_icon
5
+ from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
+ from qtpy.QtGui import QGuiApplication, QIcon
7
+
8
+ from bec_widgets.widgets.device_browser.device_browser import DeviceBrowser
9
+
10
+ DOM_XML = """
11
+ <ui language='c++'>
12
+ <widget class='DeviceBrowser' name='device_browser'>
13
+ </widget>
14
+ </ui>
15
+ """
16
+
17
+
18
+ class DeviceBrowserPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
19
+ def __init__(self):
20
+ super().__init__()
21
+ self._form_editor = None
22
+
23
+ def createWidget(self, parent):
24
+ t = DeviceBrowser(parent)
25
+ return t
26
+
27
+ def domXml(self):
28
+ return DOM_XML
29
+
30
+ def group(self):
31
+ return "BEC Services"
32
+
33
+ def icon(self):
34
+ palette = QGuiApplication.palette()
35
+ pixmap = material_icon("lists", color=palette.text().color(), filled=True)
36
+ return QIcon(pixmap)
37
+
38
+ def includeFile(self):
39
+ return "device_browser"
40
+
41
+ def initialize(self, form_editor):
42
+ self._form_editor = form_editor
43
+
44
+ def isContainer(self):
45
+ return False
46
+
47
+ def isInitialized(self):
48
+ return self._form_editor is not None
49
+
50
+ def name(self):
51
+ return "DeviceBrowser"
52
+
53
+ def toolTip(self):
54
+ return "DeviceBrowser"
55
+
56
+ def whatsThis(self):
57
+ return self.toolTip()
@@ -0,0 +1 @@
1
+ from .device_item import DeviceItem
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from qtpy.QtCore import QMimeData, Qt
6
+ from qtpy.QtGui import QDrag
7
+ from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget
8
+
9
+ if TYPE_CHECKING:
10
+ from qtpy.QtGui import QMouseEvent
11
+
12
+
13
+ class DeviceItem(QWidget):
14
+ def __init__(self, device: str) -> None:
15
+ super().__init__()
16
+ self.device = device
17
+ layout = QHBoxLayout()
18
+ layout.setContentsMargins(10, 2, 10, 2)
19
+ self.label = QLabel(device)
20
+ layout.addWidget(self.label)
21
+ self.setLayout(layout)
22
+
23
+ self.setStyleSheet(
24
+ """
25
+ border: 1px solid #ddd;
26
+ border-radius: 5px;
27
+ padding: 10px;
28
+ """
29
+ )
30
+
31
+ def mousePressEvent(self, event: QMouseEvent) -> None:
32
+ if event.button() == Qt.LeftButton:
33
+ drag = QDrag(self)
34
+ mime_data = QMimeData()
35
+ mime_data.setText(self.device)
36
+ drag.setMimeData(mime_data)
37
+ drag.exec_(Qt.MoveAction)
38
+
39
+ def mouseDoubleClickEvent(self, event: QMouseEvent) -> None:
40
+ print("Double Clicked")
41
+ # TODO: Implement double click action for opening the device properties dialog
42
+ return super().mouseDoubleClickEvent(event)
43
+
44
+
45
+ if __name__ == "__main__": # pragma: no cover
46
+ import sys
47
+
48
+ from qtpy.QtWidgets import QApplication
49
+
50
+ app = QApplication(sys.argv)
51
+ widget = DeviceItem("Device")
52
+ widget.show()
53
+ sys.exit(app.exec_())
@@ -0,0 +1,15 @@
1
+ def main(): # pragma: no cover
2
+ from qtpy import PYSIDE6
3
+
4
+ if not PYSIDE6:
5
+ print("PYSIDE6 is not available in the environment. Cannot patch designer.")
6
+ return
7
+ from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
+
9
+ from bec_widgets.widgets.device_browser.device_browser_plugin import DeviceBrowserPlugin
10
+
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(DeviceBrowserPlugin())
12
+
13
+
14
+ if __name__ == "__main__": # pragma: no cover
15
+ main()
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
@@ -34,8 +35,9 @@ class DeviceComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "Device Control"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "device_combo_box.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("list_alt", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "device_combobox"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
@@ -34,8 +35,9 @@ class DeviceLineEditPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "Device Control"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "device_line_edit.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("edit_note", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "device_line_edit"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.dock import BECDockArea
@@ -34,8 +35,9 @@ class BECDockAreaPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "BEC Plots"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "dock_area.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("widgets", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "dock_area"
@@ -2,8 +2,9 @@
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
  import os
4
4
 
5
+ from bec_qthemes import material_icon
5
6
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
- from qtpy.QtGui import QIcon
7
+ from qtpy.QtGui import QGuiApplication, QIcon
7
8
 
8
9
  import bec_widgets
9
10
  from bec_widgets.widgets.image.image_widget import BECImageWidget
@@ -34,8 +35,9 @@ class BECImageWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
34
35
  return "BEC Plots"
35
36
 
36
37
  def icon(self):
37
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "image.png")
38
- return QIcon(icon_path)
38
+ palette = QGuiApplication.palette()
39
+ pixmap = material_icon("image", color=palette.text().color(), filled=True)
40
+ return QIcon(pixmap)
39
41
 
40
42
  def includeFile(self):
41
43
  return "bec_image_widget"
@@ -1,7 +1,8 @@
1
1
  import os
2
2
 
3
+ from bec_qthemes import material_icon
3
4
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
4
- from qtpy.QtGui import QIcon
5
+ from qtpy.QtGui import QGuiApplication, QIcon
5
6
 
6
7
  import bec_widgets
7
8
  from bec_widgets.widgets.motor_map.motor_map_widget import BECMotorMapWidget
@@ -32,8 +33,9 @@ class BECMotorMapWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cov
32
33
  return "BEC Plots"
33
34
 
34
35
  def icon(self):
35
- icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "motor_map.png")
36
- return QIcon(icon_path)
36
+ palette = QGuiApplication.palette()
37
+ pixmap = material_icon("my_location", color=palette.text().color(), filled=True)
38
+ return QIcon(pixmap)
37
39
 
38
40
  def includeFile(self):
39
41
  return "bec_motor_map_widget"