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
.gitlab-ci.yml CHANGED
@@ -43,13 +43,20 @@ stages:
43
43
  - export QTWEBENGINE_DISABLE_SANDBOX=1
44
44
 
45
45
  .clone-repos: &clone-repos
46
+ - echo -e "\033[35;1m Using branch $BEC_CORE_BRANCH of BEC CORE \033[0;m";
46
47
  - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
48
+ - echo -e "\033[35;1m Using branch $OPHYD_DEVICES_BRANCH of OPHYD_DEVICES \033[0;m";
47
49
  - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
48
50
  - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
49
51
 
52
+ .install-repos: &install-repos
53
+ - pip install -e ./ophyd_devices
54
+ - pip install -e ./bec/bec_lib[dev]
55
+ - pip install -e ./bec/bec_ipython_client
56
+
50
57
  .install-os-packages: &install-os-packages
51
58
  - apt-get update
52
- - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
59
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3 xvfb
53
60
  - *install-qt-webengine-deps
54
61
 
55
62
  before_script:
@@ -131,8 +138,7 @@ tests:
131
138
  script:
132
139
  - *clone-repos
133
140
  - *install-os-packages
134
- - pip install -e ./bec/bec_lib[dev]
135
- - pip install -e ./bec/bec_ipython_client
141
+ - *install-repos
136
142
  - pip install -e .[dev,pyqt6]
137
143
  - coverage run --source=./bec_widgets -m pytest -v --junitxml=report.xml --random-order --full-trace ./tests/unit_tests
138
144
  - coverage report
@@ -169,8 +175,7 @@ test-matrix:
169
175
  script:
170
176
  - *clone-repos
171
177
  - *install-os-packages
172
- - pip install -e ./bec/bec_lib[dev]
173
- - pip install -e ./bec/bec_ipython_client
178
+ - *install-repos
174
179
  - pip install -e .[dev,$QT_PCKG]
175
180
  - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
176
181
  allow_failure: true
@@ -195,10 +200,9 @@ end-2-end-conda:
195
200
 
196
201
  - cd ./bec
197
202
  - source ./bin/install_bec_dev.sh -t
198
-
199
- - pip install -e ./bec_lib[dev]
200
- - pip install -e ./bec_ipython_client[dev]
201
203
  - cd ../
204
+ - pip install -e ./ophyd_devices
205
+
202
206
  - pip install -e .[dev,pyqt6]
203
207
  - cd ./tests/end-2-end
204
208
  - pytest -v --start-servers --flush-redis --random-order
CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.92.1 (2024-07-28)
4
+
5
+ ### Build
6
+
7
+ * build(ci): install ophyd_devices in editable mode for pipelines ([`06205e0`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/06205e07903d93accf40abab153f440059f236ed))
8
+
9
+ ### Fix
10
+
11
+ * fix: use SafeSlot instead of Slot ([`bc1e239`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/bc1e23944cc0e5a861e3d0b4dc5b4ac6292d5269))
12
+
13
+ * fix: linting ([`a3fe205`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a3fe20500ae2ac03dcde07432f7e21ce5262ce46))
14
+
15
+ * fix: always add a QApplication for tests ([`61a4e32`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/61a4e32deb337ed27f2f43358b88b7266413b58e))
16
+
17
+ * fix: add xvfb to draw offscreen ([`3d681f7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/3d681f77e144e74138fc5fa65630004d7c166878))
18
+
19
+ * fix: reset ErrorPopup singleton between tests ([`5a9ccfd`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5a9ccfd1f6d2aacd5d86c1a34f74163b272d1ae4))
20
+
21
+ * fix: metaclass + QObject segfaults PyQt(cpp bindings) ([`fc57b7a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fc57b7a1262031a2df9e6a99493db87e766b779a))
22
+
23
+ ### Refactor
24
+
25
+ * refactor: renamed DeviceMonitor2DMessage ([`4be6fd6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4be6fd6b83ea1048f16310f7d2bbe777b13b245e))
26
+
27
+ * refactor: rename device_monitor to device_monitor_2d ([`714e1e1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/714e1e139e0033d2725fefb636c419ca137a68c6))
28
+
29
+ ## v0.92.0 (2024-07-24)
30
+
31
+ ### Feature
32
+
33
+ * feat(dock): dock style sheets updated ([`8ca60d5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8ca60d54b3cfa621172ce097fc1ba514c47ebac7))
34
+
35
+ * feat(general_gui): general gui added ([`5696c99`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/5696c993dc1c0da40ff3e99f754c246cc017ea32))
36
+
37
+ ### Fix
38
+
39
+ * fix(dock): custom label can be created closable ([`4457ef2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4457ef2147e21b856c9dcaf63c81ba98002dcaf1))
40
+
41
+ * fix(device_combobox): set minimum size to 125px ([`1206e15`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1206e153094cd8505badf69a1461572a76b4c5ad))
42
+
3
43
  ## v0.91.0 (2024-07-23)
4
44
 
5
45
  ### Feature
@@ -88,20 +128,6 @@ This reverts commit 3798714369adf4023f833b7749d2f46a0ec74eee ([`fd6ae91`](https:
88
128
 
89
129
  * feat(waveform_widget): dap parameter window ([`1e551d6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1e551d6e9696f79ea2e0a179d13a4fc6c2a128b2))
90
130
 
91
- * feat(waveform): export to matplotlib window of current scene ([`8d93405`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8d9340539967b06b1e15f21a2106a39d5c740f31))
92
-
93
- * feat(figure): export dialog can be launched from CLI and from toolbar ([`6ff6111`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6ff611109153b9412dce37c527b19e839d99bba7))
94
-
95
- * feat(waveform_widget): added error handle utility ([`a8ff1d4`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a8ff1d4cd09cae5eaeb4bd0ea90fdd102e32f3a3))
96
-
97
- * feat(curve_dialog): add DAP functionality ([`e830565`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e8305652fde384da037242cf8f7e3606f22bcfb6))
98
-
99
- * feat(curve_dialog): curves can be added ([`c926a75`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c926a75a7927d672c044ea8f68771209ae5accc6))
100
-
101
- * feat(waveform_widget): BECWaveformWidget toolbar added import/export config ([`fa9b171`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/fa9b17191ddbb4043a658dae9aa0801e1dc22b84))
102
-
103
- * feat(waveform_widget): BECWaveformWidget added with toolbar ([`755b394`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/755b394c1c4d7c443c442d89c630d08ce5415554))
104
-
105
131
  ### Fix
106
132
 
107
133
  * fix(waveform_widget): plot API unified with BECFigure ([`2c8764a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2c8764a27de89b39b717032b58465e120ec57fbc))
@@ -114,36 +140,6 @@ This reverts commit 3798714369adf4023f833b7749d2f46a0ec74eee ([`fd6ae91`](https:
114
140
 
115
141
  * fix(waveform_widget): use @SafeSlot decorator for automatic error message ([`8e588d7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8e588d79c86e950f6915e89c08fa9415c4bd8033))
116
142
 
117
- * fix(waveform): colormaps of curves can be changed and normalised
118
-
119
- feat(waveform): colormap can be changed from curve dialog
120
-
121
- fix(curve_dialog): default dialog parameters fixed
122
-
123
- curve Dialog colormap WIP ([`33495cf`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/33495cfe03b363f18db61d8af2983f49027b7a43))
124
-
125
- * fix(waveform_widget): adapted for changes from improved scan logic from waveform widget ([`8ac35d7`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8ac35d7280b1ff007c10612228d163cc0c5d1a99))
126
-
127
- ### Refactor
128
-
129
- * refactor(icons): icons moved to the assets directory ([`a8b6ef2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a8b6ef20cccae87515b10f054d0ed5b10e152769))
130
-
131
- * refactor(waveform_widget): removed PYSIDE6 check ([`47fcb9e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/47fcb9ebfe35ae600cced95a1edc68f6f6e37a04))
132
-
133
143
  ### Test
134
144
 
135
145
  * test(waveform_widget): test added ([`8d764e2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8d764e2d46a1e017dadc3c4630648c1ca708afc2))
136
-
137
- ## v0.87.1 (2024-07-18)
138
-
139
- ### Fix
140
-
141
- * fix(dock): added hasattr to cleanup method for widgets ([`d75c55b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d75c55b2b1ccf156fb789c7813f1c5bdf256f860))
142
-
143
- * fix: add missing close() call, ensure jupyter console client.shutdown() is called in closeEvent ([`e52ee26`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/e52ee2604cb35096f1bd833ca9516d8a34197d35))
144
-
145
- ### Refactor
146
-
147
- * refactor: BECWidget is a mixin based on BECConnector, for each QWidget in BEC
148
-
149
- Handles closeEvent() and RPC registering/unregistering ([`c7feb69`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/c7feb6952d590b569f7b0cba3b019a9af0ce0c93))
PKG-INFO CHANGED
@@ -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
File without changes
@@ -0,0 +1,92 @@
1
+ import os
2
+ import sys
3
+
4
+ from qtpy.QtCore import QSize
5
+ from qtpy.QtGui import QActionGroup, QIcon
6
+ from qtpy.QtWidgets import QApplication, QMainWindow, QStyle
7
+
8
+ import bec_widgets
9
+ from bec_widgets.examples.general_app.web_links import BECWebLinksMixin
10
+ from bec_widgets.utils.colors import apply_theme
11
+ from bec_widgets.utils.ui_loader import UILoader
12
+
13
+ MODULE_PATH = os.path.dirname(bec_widgets.__file__)
14
+
15
+
16
+ class BECGeneralApp(QMainWindow):
17
+ def __init__(self, parent=None):
18
+ super(BECGeneralApp, self).__init__(parent)
19
+ ui_file_path = os.path.join(os.path.dirname(__file__), "general_app.ui")
20
+ self.load_ui(ui_file_path)
21
+
22
+ self.resize(1280, 720)
23
+
24
+ self.ini_ui()
25
+
26
+ def ini_ui(self):
27
+ self._setup_icons()
28
+ self._hook_menubar_docs()
29
+ self._hook_theme_bar()
30
+
31
+ def load_ui(self, ui_file):
32
+ loader = UILoader(self)
33
+ self.ui = loader.loader(ui_file)
34
+ self.setCentralWidget(self.ui)
35
+
36
+ def _hook_menubar_docs(self):
37
+ # BEC Docs
38
+ self.ui.action_BEC_docs.triggered.connect(BECWebLinksMixin.open_bec_docs)
39
+ # BEC Widgets Docs
40
+ self.ui.action_BEC_widgets_docs.triggered.connect(BECWebLinksMixin.open_bec_widgets_docs)
41
+ # Bug report
42
+ self.ui.action_bug_report.triggered.connect(BECWebLinksMixin.open_bec_bug_report)
43
+
44
+ def change_theme(self, theme):
45
+ apply_theme(theme)
46
+
47
+ def _setup_icons(self):
48
+ help_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxQuestion)
49
+ bug_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxInformation)
50
+ computer_icon = QIcon.fromTheme("computer")
51
+ widget_icon = QIcon(os.path.join(MODULE_PATH, "assets", "designer_icons", "dock_area.png"))
52
+
53
+ self.ui.action_BEC_docs.setIcon(help_icon)
54
+ self.ui.action_BEC_widgets_docs.setIcon(help_icon)
55
+ self.ui.action_bug_report.setIcon(bug_icon)
56
+
57
+ self.ui.central_tab.setTabIcon(0, widget_icon)
58
+ self.ui.central_tab.setTabIcon(1, computer_icon)
59
+
60
+ def _hook_theme_bar(self):
61
+ self.ui.action_light.setCheckable(True)
62
+ self.ui.action_dark.setCheckable(True)
63
+
64
+ # Create an action group to make sure only one can be checked at a time
65
+ theme_group = QActionGroup(self)
66
+ theme_group.addAction(self.ui.action_light)
67
+ theme_group.addAction(self.ui.action_dark)
68
+ theme_group.setExclusive(True)
69
+
70
+ # Connect the actions to the theme change method
71
+
72
+ self.ui.action_light.triggered.connect(lambda: self.change_theme("light"))
73
+ self.ui.action_dark.triggered.connect(lambda: self.change_theme("dark"))
74
+
75
+ self.ui.action_dark.trigger()
76
+
77
+
78
+ def main(): # pragma: no cover
79
+
80
+ app = QApplication(sys.argv)
81
+ icon = QIcon()
82
+ icon.addFile(
83
+ os.path.join(MODULE_PATH, "assets", "app_icons", "BEC-Dark.png"), size=QSize(48, 48)
84
+ )
85
+ app.setWindowIcon(icon)
86
+ main_window = BECGeneralApp()
87
+ main_window.show()
88
+ sys.exit(app.exec_())
89
+
90
+
91
+ if __name__ == "__main__": # pragma: no cover
92
+ main()
@@ -0,0 +1,262 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>MainWindow</class>
4
+ <widget class="QMainWindow" name="MainWindow">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>1718</width>
10
+ <height>1139</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>MainWindow</string>
15
+ </property>
16
+ <property name="tabShape">
17
+ <enum>QTabWidget::TabShape::Rounded</enum>
18
+ </property>
19
+ <widget class="QWidget" name="centralwidget">
20
+ <layout class="QVBoxLayout" name="verticalLayout_3">
21
+ <item>
22
+ <widget class="QTabWidget" name="central_tab">
23
+ <property name="currentIndex">
24
+ <number>0</number>
25
+ </property>
26
+ <widget class="QWidget" name="dock_area_tab">
27
+ <attribute name="title">
28
+ <string>Dock Area</string>
29
+ </attribute>
30
+ <layout class="QVBoxLayout" name="verticalLayout">
31
+ <property name="leftMargin">
32
+ <number>2</number>
33
+ </property>
34
+ <property name="topMargin">
35
+ <number>1</number>
36
+ </property>
37
+ <property name="rightMargin">
38
+ <number>2</number>
39
+ </property>
40
+ <property name="bottomMargin">
41
+ <number>2</number>
42
+ </property>
43
+ <item>
44
+ <widget class="BECDockArea" name="dock_area"/>
45
+ </item>
46
+ </layout>
47
+ </widget>
48
+ <widget class="QWidget" name="vscode_tab">
49
+ <attribute name="icon">
50
+ <iconset theme="QIcon::ThemeIcon::Computer"/>
51
+ </attribute>
52
+ <attribute name="title">
53
+ <string>Visual Studio Code</string>
54
+ </attribute>
55
+ <layout class="QVBoxLayout" name="verticalLayout_2">
56
+ <property name="leftMargin">
57
+ <number>2</number>
58
+ </property>
59
+ <property name="topMargin">
60
+ <number>1</number>
61
+ </property>
62
+ <property name="rightMargin">
63
+ <number>2</number>
64
+ </property>
65
+ <property name="bottomMargin">
66
+ <number>2</number>
67
+ </property>
68
+ <item>
69
+ <widget class="VSCodeEditor" name="vscode"/>
70
+ </item>
71
+ </layout>
72
+ </widget>
73
+ </widget>
74
+ </item>
75
+ </layout>
76
+ </widget>
77
+ <widget class="QMenuBar" name="menubar">
78
+ <property name="geometry">
79
+ <rect>
80
+ <x>0</x>
81
+ <y>0</y>
82
+ <width>1718</width>
83
+ <height>31</height>
84
+ </rect>
85
+ </property>
86
+ <widget class="QMenu" name="menuHelp">
87
+ <property name="title">
88
+ <string>Help</string>
89
+ </property>
90
+ <addaction name="action_BEC_docs"/>
91
+ <addaction name="action_BEC_widgets_docs"/>
92
+ <addaction name="action_bug_report"/>
93
+ </widget>
94
+ <widget class="QMenu" name="menuTheme">
95
+ <property name="title">
96
+ <string>Theme</string>
97
+ </property>
98
+ <addaction name="action_light"/>
99
+ <addaction name="action_dark"/>
100
+ </widget>
101
+ <addaction name="menuTheme"/>
102
+ <addaction name="menuHelp"/>
103
+ </widget>
104
+ <widget class="QStatusBar" name="statusbar"/>
105
+ <widget class="QDockWidget" name="dock_scan_control">
106
+ <property name="windowTitle">
107
+ <string>Scan Control</string>
108
+ </property>
109
+ <attribute name="dockWidgetArea">
110
+ <number>2</number>
111
+ </attribute>
112
+ <widget class="QWidget" name="dockWidgetContents_2">
113
+ <layout class="QVBoxLayout" name="verticalLayout_4">
114
+ <item>
115
+ <widget class="ScanControl" name="scan_control"/>
116
+ </item>
117
+ </layout>
118
+ </widget>
119
+ </widget>
120
+ <widget class="QDockWidget" name="dock_status_2">
121
+ <property name="windowTitle">
122
+ <string>BEC Service Status</string>
123
+ </property>
124
+ <attribute name="dockWidgetArea">
125
+ <number>2</number>
126
+ </attribute>
127
+ <widget class="QWidget" name="dockWidgetContents_3">
128
+ <layout class="QVBoxLayout" name="verticalLayout_5">
129
+ <property name="leftMargin">
130
+ <number>0</number>
131
+ </property>
132
+ <property name="topMargin">
133
+ <number>0</number>
134
+ </property>
135
+ <property name="rightMargin">
136
+ <number>0</number>
137
+ </property>
138
+ <property name="bottomMargin">
139
+ <number>0</number>
140
+ </property>
141
+ <item>
142
+ <widget class="BECStatusBox" name="bec_status_box_2"/>
143
+ </item>
144
+ </layout>
145
+ </widget>
146
+ </widget>
147
+ <widget class="QDockWidget" name="dock_queue">
148
+ <property name="windowTitle">
149
+ <string>Scan Queue</string>
150
+ </property>
151
+ <attribute name="dockWidgetArea">
152
+ <number>2</number>
153
+ </attribute>
154
+ <widget class="QWidget" name="dockWidgetContents_4">
155
+ <layout class="QVBoxLayout" name="verticalLayout_6">
156
+ <property name="leftMargin">
157
+ <number>0</number>
158
+ </property>
159
+ <property name="topMargin">
160
+ <number>0</number>
161
+ </property>
162
+ <property name="rightMargin">
163
+ <number>0</number>
164
+ </property>
165
+ <property name="bottomMargin">
166
+ <number>0</number>
167
+ </property>
168
+ <item>
169
+ <widget class="BECQueue" name="bec_queue">
170
+ <row/>
171
+ <column/>
172
+ <column/>
173
+ <column/>
174
+ <item row="0" column="0"/>
175
+ <item row="0" column="1"/>
176
+ <item row="0" column="2"/>
177
+ </widget>
178
+ </item>
179
+ </layout>
180
+ </widget>
181
+ </widget>
182
+ <action name="action_BEC_docs">
183
+ <property name="icon">
184
+ <iconset theme="QIcon::ThemeIcon::DialogQuestion"/>
185
+ </property>
186
+ <property name="text">
187
+ <string>BEC Docs</string>
188
+ </property>
189
+ </action>
190
+ <action name="action_BEC_widgets_docs">
191
+ <property name="icon">
192
+ <iconset theme="QIcon::ThemeIcon::DialogQuestion"/>
193
+ </property>
194
+ <property name="text">
195
+ <string>BEC Widgets Docs</string>
196
+ </property>
197
+ </action>
198
+ <action name="action_bug_report">
199
+ <property name="icon">
200
+ <iconset theme="QIcon::ThemeIcon::DialogError"/>
201
+ </property>
202
+ <property name="text">
203
+ <string>Bug Report</string>
204
+ </property>
205
+ </action>
206
+ <action name="action_light">
207
+ <property name="checkable">
208
+ <bool>true</bool>
209
+ </property>
210
+ <property name="text">
211
+ <string>Light</string>
212
+ </property>
213
+ </action>
214
+ <action name="action_dark">
215
+ <property name="checkable">
216
+ <bool>true</bool>
217
+ </property>
218
+ <property name="text">
219
+ <string>Dark</string>
220
+ </property>
221
+ </action>
222
+ </widget>
223
+ <customwidgets>
224
+ <customwidget>
225
+ <class>WebsiteWidget</class>
226
+ <extends>QWebEngineView</extends>
227
+ <header>website_widget</header>
228
+ </customwidget>
229
+ <customwidget>
230
+ <class>BECQueue</class>
231
+ <extends>QTableWidget</extends>
232
+ <header>bec_queue</header>
233
+ </customwidget>
234
+ <customwidget>
235
+ <class>ScanControl</class>
236
+ <extends>QWidget</extends>
237
+ <header>scan_control</header>
238
+ </customwidget>
239
+ <customwidget>
240
+ <class>VSCodeEditor</class>
241
+ <extends>WebsiteWidget</extends>
242
+ <header>vs_code_editor</header>
243
+ </customwidget>
244
+ <customwidget>
245
+ <class>BECStatusBox</class>
246
+ <extends>QWidget</extends>
247
+ <header>bec_status_box</header>
248
+ </customwidget>
249
+ <customwidget>
250
+ <class>BECDockArea</class>
251
+ <extends>QWidget</extends>
252
+ <header>dock_area</header>
253
+ </customwidget>
254
+ <customwidget>
255
+ <class>QWebEngineView</class>
256
+ <extends></extends>
257
+ <header location="global">QtWebEngineWidgets/QWebEngineView</header>
258
+ </customwidget>
259
+ </customwidgets>
260
+ <resources/>
261
+ <connections/>
262
+ </ui>
@@ -0,0 +1,15 @@
1
+ import webbrowser
2
+
3
+
4
+ class BECWebLinksMixin:
5
+ @staticmethod
6
+ def open_bec_docs():
7
+ webbrowser.open("https://beamline-experiment-control.readthedocs.io/en/latest/")
8
+
9
+ @staticmethod
10
+ def open_bec_widgets_docs():
11
+ webbrowser.open("https://bec.readthedocs.io/projects/bec-widgets/en/latest/")
12
+
13
+ @staticmethod
14
+ def open_bec_bug_report():
15
+ webbrowser.open("https://gitlab.psi.ch/groups/bec/-/issues/")
@@ -1,12 +1,13 @@
1
1
  # Copyright (C) 2022 The Qt Company Ltd.
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
3
 
4
- from qtpy.QtCore import Slot
5
4
  from qtpy.QtDesigner import QExtensionFactory, QPyDesignerTaskMenuExtension
6
5
  from qtpy.QtGui import QAction
7
6
  from qtpy.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout
8
7
  from tictactoe import TicTacToe
9
8
 
9
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
10
+
10
11
 
11
12
  class TicTacToeDialog(QDialog): # pragma: no cover
12
13
  def __init__(self, parent):
@@ -6,7 +6,7 @@ from qtpy.QtCore import QObject, Qt, Signal, Slot
6
6
  from qtpy.QtWidgets import QApplication, QMessageBox, QPushButton, QVBoxLayout, QWidget
7
7
 
8
8
 
9
- def SafeSlot(*slot_args, **slot_kwargs):
9
+ def SafeSlot(*slot_args, **slot_kwargs): # pylint: disable=invalid-name
10
10
  """Function with args, acting like a decorator, applying "error_managed" decorator + Qt Slot
11
11
  to the passed function, to display errors instead of potentially raising an exception
12
12
 
@@ -34,10 +34,7 @@ class WarningPopupUtility(QObject):
34
34
  Utility class to show warning popups in the application.
35
35
  """
36
36
 
37
- def __init__(self, parent=None):
38
- super().__init__(parent)
39
-
40
- @Slot(str, str, str, QWidget)
37
+ @SafeSlot(str, str, str, QWidget)
41
38
  def show_warning_message(self, title, message, detailed_text, widget):
42
39
  msg = QMessageBox(widget)
43
40
  msg.setIcon(QMessageBox.Warning)
@@ -60,7 +57,10 @@ class WarningPopupUtility(QObject):
60
57
  self.show_warning_message(title, message, detailed_text, widget)
61
58
 
62
59
 
63
- class ErrorPopupUtility(QObject):
60
+ _popup_utility_instance = None
61
+
62
+
63
+ class _ErrorPopupUtility(QObject):
64
64
  """
65
65
  Utility class to manage error popups in the application to show error messages to the users.
66
66
  This class is singleton and the error popup can be enabled or disabled globally or attach to widget methods with decorator @error_managed.
@@ -68,24 +68,14 @@ class ErrorPopupUtility(QObject):
68
68
 
69
69
  error_occurred = Signal(str, str, QWidget)
70
70
 
71
- _instance = None
72
- _initialized = False
73
-
74
- def __new__(cls, *args, **kwargs):
75
- if cls._instance is None:
76
- cls._instance = super(ErrorPopupUtility, cls).__new__(cls)
77
- cls._instance._initialized = False
78
- return cls._instance
79
-
80
71
  def __init__(self, parent=None):
81
- if not self._initialized:
82
- super().__init__(parent=parent)
83
- self.error_occurred.connect(self.show_error_message)
84
- self.enable_error_popup = False
85
- self._initialized = True
86
- sys.excepthook = self.custom_exception_hook
87
-
88
- @Slot(str, str, QWidget)
72
+ super().__init__(parent=parent)
73
+ self.error_occurred.connect(self.show_error_message)
74
+ self.enable_error_popup = False
75
+ self._initialized = True
76
+ sys.excepthook = self.custom_exception_hook
77
+
78
+ @SafeSlot(str, str, QWidget)
89
79
  def show_error_message(self, title, message, widget):
90
80
  detailed_text = self.format_traceback(message)
91
81
  error_message = self.parse_error_message(detailed_text)
@@ -157,13 +147,12 @@ class ErrorPopupUtility(QObject):
157
147
  """
158
148
  self.enable_error_popup = bool(state)
159
149
 
160
- @classmethod
161
- def reset_singleton(cls):
162
- """
163
- Reset the singleton instance.
164
- """
165
- cls._instance = None
166
- cls._initialized = False
150
+
151
+ def ErrorPopupUtility():
152
+ global _popup_utility_instance
153
+ if not _popup_utility_instance:
154
+ _popup_utility_instance = _ErrorPopupUtility()
155
+ return _popup_utility_instance
167
156
 
168
157
 
169
158
  class ExampleWidget(QWidget): # pragma: no cover
@@ -1,6 +1,7 @@
1
- from qtpy.QtCore import Slot
2
1
  from qtpy.QtWidgets import QDialog, QDialogButtonBox, QHBoxLayout, QPushButton, QVBoxLayout, QWidget
3
2
 
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot as Slot
4
+
4
5
 
5
6
  class SettingWidget(QWidget):
6
7
  """
@@ -10,11 +10,11 @@ import yaml
10
10
  from bec_lib.utils.import_utils import lazy_import_from
11
11
  from pydantic import BaseModel, Field, field_validator
12
12
  from qtpy.QtCore import QObject, QRunnable, QThreadPool, Signal
13
- from qtpy.QtCore import Slot as pyqtSlot
14
13
  from qtpy.QtWidgets import QApplication
15
14
 
16
15
  from bec_widgets.cli.rpc_register import RPCRegister
17
16
  from bec_widgets.qt_utils.error_popups import ErrorPopupUtility
17
+ from bec_widgets.qt_utils.error_popups import SafeSlot as pyqtSlot
18
18
  from bec_widgets.utils.yaml_dialog import load_yaml, load_yaml_gui, save_yaml, save_yaml_gui
19
19
 
20
20
  BECDispatcher = lazy_import_from("bec_widgets.utils.bec_dispatcher", ("BECDispatcher",))