bec-widgets 0.55.0__py3-none-any.whl → 0.56.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 (44) hide show
  1. .gitlab-ci.yml +113 -8
  2. CHANGELOG.md +34 -28
  3. PKG-INFO +3 -1
  4. bec_widgets/examples/jupyter_console/jupyter_console_window.py +28 -38
  5. bec_widgets/examples/motor_movement/motor_control_compilations.py +1 -7
  6. bec_widgets/utils/__init__.py +1 -0
  7. bec_widgets/utils/crosshair.py +13 -9
  8. bec_widgets/utils/ui_loader.py +58 -0
  9. bec_widgets/widgets/motor_control/motor_table/motor_table.py +44 -43
  10. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +25 -23
  11. bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +51 -48
  12. bec_widgets/widgets/spiral_progress_bar/ring.py +5 -5
  13. {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/METADATA +3 -1
  14. {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/RECORD +22 -43
  15. docs/user/apps.md +1 -26
  16. pyproject.toml +2 -1
  17. tests/end-2-end/test_bec_dock_rpc_e2e.py +1 -1
  18. tests/unit_tests/test_client_utils.py +2 -2
  19. tests/unit_tests/test_crosshair.py +5 -5
  20. tests/unit_tests/test_motor_control.py +49 -45
  21. bec_widgets/examples/eiger_plot/__init__.py +0 -0
  22. bec_widgets/examples/eiger_plot/eiger_plot.py +0 -307
  23. bec_widgets/examples/eiger_plot/eiger_plot.ui +0 -207
  24. bec_widgets/examples/mca_readout/__init__.py +0 -0
  25. bec_widgets/examples/mca_readout/mca_plot.py +0 -159
  26. bec_widgets/examples/mca_readout/mca_sim.py +0 -28
  27. bec_widgets/examples/modular_app/___init__.py +0 -0
  28. bec_widgets/examples/modular_app/modular.ui +0 -92
  29. bec_widgets/examples/modular_app/modular_app.py +0 -197
  30. bec_widgets/examples/motor_movement/config_example.yaml +0 -17
  31. bec_widgets/examples/motor_movement/csax_bec_config.yaml +0 -10
  32. bec_widgets/examples/motor_movement/csaxs_config.yaml +0 -17
  33. bec_widgets/examples/motor_movement/motor_example.py +0 -1344
  34. bec_widgets/examples/stream_plot/__init__.py +0 -0
  35. bec_widgets/examples/stream_plot/line_plot.ui +0 -155
  36. bec_widgets/examples/stream_plot/stream_plot.py +0 -337
  37. docs/user/apps/modular_app.md +0 -6
  38. docs/user/apps/motor_app.md +0 -34
  39. docs/user/apps/motor_app_10fps.gif +0 -0
  40. docs/user/apps/plot_app.md +0 -6
  41. tests/unit_tests/test_eiger_plot.py +0 -115
  42. tests/unit_tests/test_stream_plot.py +0 -158
  43. {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/WHEEL +0 -0
  44. {bec_widgets-0.55.0.dist-info → bec_widgets-0.56.1.dist-info}/licenses/LICENSE +0 -0
.gitlab-ci.yml CHANGED
@@ -1,7 +1,7 @@
1
1
  # This file is a template, and might need editing before it works on your project.
2
2
  # Official language image. Look for the different tagged releases at:
3
3
  # https://hub.docker.com/r/library/python/tags/
4
- image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.10
4
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.11
5
5
  #commands to run in the Docker container before starting each job.
6
6
  variables:
7
7
  DOCKER_TLS_CERTDIR: ""
@@ -23,7 +23,6 @@ workflow:
23
23
  include:
24
24
  - template: Security/Secret-Detection.gitlab-ci.yml
25
25
 
26
-
27
26
  # different stages in the pipeline
28
27
  stages:
29
28
  - Formatter
@@ -65,7 +64,7 @@ pylint:
65
64
  - ./pylint/
66
65
  expire_in: 1 week
67
66
  rules:
68
- - if: $CI_PROJECT_PATH == "bec/bec_widgets"
67
+ - if: $CI_PROJECT_PATH == "bec/bec_widgets"
69
68
 
70
69
  pylint-check:
71
70
  stage: Formatter
@@ -98,7 +97,7 @@ pylint-check:
98
97
  - ./pylint/
99
98
  expire_in: 1 week
100
99
  rules:
101
- - if: $CI_PROJECT_PATH == "bec/bec_widgets"
100
+ - if: $CI_PROJECT_PATH == "bec/bec_widgets"
102
101
 
103
102
  tests:
104
103
  stage: test
@@ -124,17 +123,124 @@ tests:
124
123
  coverage_format: cobertura
125
124
  path: coverage.xml
126
125
 
126
+ tests-3.10-pyside6:
127
+ extends: "tests"
128
+ stage: AdditionalTests
129
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.10
130
+ script:
131
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
132
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
133
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
134
+ - apt-get update
135
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
136
+ - pip install -e ./bec/bec_lib[dev]
137
+ - pip install -e .[dev,pyside6]
138
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
139
+ allow_failure: true
127
140
 
128
- tests-3.11:
141
+ tests-3.12-pyside6:
142
+ extends: "tests"
143
+ stage: AdditionalTests
144
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.12
145
+ script:
146
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
147
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
148
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
149
+ - apt-get update
150
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
151
+ - pip install -e ./bec/bec_lib[dev]
152
+ - pip install -e .[dev,pyside6]
153
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
154
+ allow_failure: true
155
+
156
+ tests-3.10-pyqt5:
157
+ extends: "tests"
158
+ stage: AdditionalTests
159
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.10
160
+ script:
161
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
162
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
163
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
164
+ - apt-get update
165
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
166
+ - pip install -e ./bec/bec_lib[dev]
167
+ - pip install -e .[dev,pyqt5]
168
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
169
+ allow_failure: true
170
+
171
+ tests-3.11-pyqt5:
129
172
  extends: "tests"
130
173
  stage: AdditionalTests
131
174
  image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.11
175
+ script:
176
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
177
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
178
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
179
+ - apt-get update
180
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
181
+ - pip install -e ./bec/bec_lib[dev]
182
+ - pip install -e .[dev,pyqt5]
183
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
132
184
  allow_failure: true
133
185
 
134
- tests-3.12:
186
+ tests-3.12-pyqt5:
135
187
  extends: "tests"
136
188
  stage: AdditionalTests
137
189
  image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.12
190
+ script:
191
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
192
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
193
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
194
+ - apt-get update
195
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
196
+ - pip install -e ./bec/bec_lib[dev]
197
+ - pip install -e .[dev,pyqt5]
198
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
199
+ allow_failure: true
200
+
201
+ tests-3.10-pyqt6:
202
+ extends: "tests"
203
+ stage: AdditionalTests
204
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.10
205
+ script:
206
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
207
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
208
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
209
+ - apt-get update
210
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
211
+ - pip install -e ./bec/bec_lib[dev]
212
+ - pip install -e .[dev,pyqt6]
213
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
214
+ allow_failure: true
215
+
216
+ tests-3.11-pyqt6:
217
+ extends: "tests"
218
+ stage: AdditionalTests
219
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.11
220
+ script:
221
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
222
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
223
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
224
+ - apt-get update
225
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
226
+ - pip install -e ./bec/bec_lib[dev]
227
+ - pip install -e .[dev,pyqt6]
228
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
229
+ allow_failure: true
230
+
231
+ tests-3.12-pyqt6:
232
+ extends: "tests"
233
+ stage: AdditionalTests
234
+ image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/python:3.12
235
+ script:
236
+ - git clone --branch $BEC_CORE_BRANCH https://gitlab.psi.ch/bec/bec.git
237
+ - git clone --branch $OPHYD_DEVICES_BRANCH https://gitlab.psi.ch/bec/ophyd_devices.git
238
+ - export OHPYD_DEVICES_PATH=$PWD/ophyd_devices
239
+ - apt-get update
240
+ - apt-get install -y libgl1-mesa-glx libegl1-mesa x11-utils libxkbcommon-x11-0 libdbus-1-3
241
+ - pip install -e ./bec/bec_lib[dev]
242
+ - pip install -e .[dev,pyqt6]
243
+ - pytest -v --junitxml=report.xml --random-order ./tests/unit_tests
138
244
  allow_failure: true
139
245
 
140
246
  end-2-end-conda:
@@ -150,7 +256,7 @@ end-2-end-conda:
150
256
  - conda config --prepend channels conda-forge
151
257
  - conda config --set channel_priority strict
152
258
  - conda config --set always_yes yes --set changeps1 no
153
- - conda create -q -n test-environment python=3.10
259
+ - conda create -q -n test-environment python=3.11
154
260
  - conda init bash
155
261
  - source ~/.bashrc
156
262
  - conda activate test-environment
@@ -183,7 +289,6 @@ end-2-end-conda:
183
289
  - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
184
290
  - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "production"'
185
291
 
186
-
187
292
  semver:
188
293
  stage: Deploy
189
294
  needs: ["tests"]
CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
 
4
4
 
5
+ ## v0.56.1 (2024-06-04)
6
+
7
+ ### Fix
8
+
9
+ * fix(spiral_progress_bar/rings): config min/max values added check for floats ([`9d615c9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/9d615c915c8f7cc2ea8f1dc17993b98fe462c682))
10
+
11
+ * fix(spiral_progress_bar): Endpoint is always stored as a string in the RingConnection Config ([`d253991`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/d2539918b296559e1d684344e179775a2423daa9))
12
+
13
+
14
+ ## v0.56.0 (2024-05-29)
15
+
16
+ ### Build
17
+
18
+ * build: added pyside6 as dependency ([`db301b1`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/db301b1be27bba76c8bb21fbff93cb4902b592a5))
19
+
20
+ ### Ci
21
+
22
+ * ci: added tests for pyside6, pyqt6 and pyqt5, default test and e2e is python 3.11 and pyqt6 ([`855be35`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/855be3551a1372bcbebba6f8930903f99202bbca))
23
+
24
+ ### Documentation
25
+
26
+ * docs(examples): example apps section deleted ([`ad208a5`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ad208a5ef8495c45a8b83a4850ba9a1041b42717))
27
+
28
+ ### Feature
29
+
30
+ * feat(utils/ui_loader): universal ui loader for pyside/pyqt ([`0fea8d6`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/0fea8d606574fa99dda3b117da5d5209c251f694))
31
+
32
+ ### Fix
33
+
34
+ * fix(examples): outdated examples removed (mca_plot.py, stream_plot.py, motor_example.py) ([`ddc9510`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/ddc9510c2ba8dadf291809eeb5b135a105259492))
35
+
36
+ * fix: compatibility adjustment to .ui loading and tests for PySide6 ([`07b99d9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/07b99d91a57a645cddd76294f48d78773e4c9ea5))
37
+
38
+
5
39
  ## v0.55.0 (2024-05-24)
6
40
 
7
41
  ### Feature
@@ -141,31 +175,3 @@
141
175
  ### Fix
142
176
 
143
177
  * fix(cli): BECFigure takes the port to connect to redis from the current BECClient, supporting plugins ([`57cb136`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/57cb136a098e87a452414bf44e627edb562f6799))
144
-
145
-
146
- ## v0.50.0 (2024-04-29)
147
-
148
- ### Feature
149
-
150
- * feat(plots): universal cleanup and remove also for children items ([`381d713`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/381d713837bb9217c58ba1d8b89691aa35c9f5ec))
151
-
152
- * feat(rpc/rpc_register): singleton rpc register for all rpc connections for session ([`a898e7e`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/a898e7e4f14e9ae854703dddbd1eb8c50cb640ff))
153
-
154
- ### Fix
155
-
156
- * fix(widgets/figure): access pattern changed for getting widgets by coordinates for rpc ([`13c018a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/13c018a79704a7497c140df57179d294e43ecffa))
157
-
158
- * fix(plots): cleanup policy reviewed for children items ([`8f20a0b`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/8f20a0b3b1b5dd117b36b45645717190b9ee9cbf))
159
-
160
- * fix(rpc/client_utils): getoutput more transparent + error handling ([`6b6a6b2`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/6b6a6b2249f24d3d02bd5fcd7ef1c63ed794c304))
161
-
162
- * fix(rpc_register): thread lock for listign all connections ([`2ca3267`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/2ca32675ec3f00137e2140259db51f6e5aa7bb71))
163
-
164
- ### Test
165
-
166
- * test(cli/rpc_register): e2e RPCRegister ([`4f261be`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/4f261be4c7cfe54501443d031f9266f4f838f6e2))
167
-
168
- * test(cli/rpc_register): rpc_register tests added ([`40eb75f`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/40eb75f85a4d99d498b086a37e799276a9d2ac3f))
169
-
170
-
171
- ## v0.49.1 (2024-04-26)
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.55.0
3
+ Version: 0.56.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
@@ -31,3 +31,5 @@ Provides-Extra: pyqt5
31
31
  Requires-Dist: pyqt5>=5.9; extra == 'pyqt5'
32
32
  Provides-Extra: pyqt6
33
33
  Requires-Dist: pyqt6>=6.7; extra == 'pyqt6'
34
+ Provides-Extra: pyside6
35
+ Requires-Dist: pyside6>=6.7; extra == 'pyside6'
@@ -2,18 +2,16 @@ import os
2
2
 
3
3
  import numpy as np
4
4
  import pyqtgraph as pg
5
- from pyqtgraph.Qt import QtWidgets, uic
5
+ import qdarktheme
6
6
  from qtconsole.inprocess import QtInProcessKernelManager
7
7
  from qtconsole.rich_jupyter_widget import RichJupyterWidget
8
8
  from qtpy.QtCore import QSize
9
9
  from qtpy.QtGui import QIcon
10
10
  from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget
11
11
 
12
- from bec_widgets.cli.rpc_register import RPCRegister
13
- from bec_widgets.utils import BECDispatcher
12
+ from bec_widgets.utils import BECDispatcher, UILoader
14
13
  from bec_widgets.widgets import BECFigure
15
14
  from bec_widgets.widgets.dock.dock_area import BECDockArea
16
- from bec_widgets.widgets.spiral_progress_bar.spiral_progress_bar import SpiralProgressBar
17
15
 
18
16
 
19
17
  class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
@@ -26,7 +24,6 @@ class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
26
24
  self.kernel_client.start_channels()
27
25
 
28
26
  self.kernel_manager.kernel.shell.push({"np": np, "pg": pg})
29
- # self.set_console_font_size(70)
30
27
 
31
28
  def shutdown_kernel(self):
32
29
  self.kernel_client.stop_channels()
@@ -40,33 +37,28 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
40
37
  super().__init__(parent)
41
38
 
42
39
  current_path = os.path.dirname(__file__)
43
- uic.loadUi(os.path.join(current_path, "jupyter_console_window.ui"), self)
40
+ self.ui = UILoader().load_ui(os.path.join(current_path, "jupyter_console_window.ui"), self)
44
41
 
45
42
  self._init_ui()
46
43
 
47
- self.splitter.setSizes([200, 100])
44
+ self.ui.splitter.setSizes([200, 100])
48
45
  self.safe_close = False
49
- # self.figure.clean_signal.connect(self.confirm_close)
50
-
51
- self.register = RPCRegister()
52
- self.register.add_rpc(self.figure)
53
46
 
54
47
  # console push
55
48
  self.console.kernel_manager.kernel.shell.push(
56
49
  {
57
50
  "fig": self.figure,
58
- "register": self.register,
59
51
  "dock": self.dock,
60
52
  "w1": self.w1,
61
53
  "w2": self.w2,
62
54
  "w3": self.w3,
55
+ "d0": self.d0,
63
56
  "d1": self.d1,
64
57
  "d2": self.d2,
65
- "d3": self.d3,
58
+ "fig0": self.fig0,
59
+ "fig1": self.fig1,
60
+ "fig2": self.fig2,
66
61
  "bar": self.bar,
67
- "b2a": self.button_2_a,
68
- "b2b": self.button_2_b,
69
- "b2c": self.button_2_c,
70
62
  "bec": self.figure.client,
71
63
  "scans": self.figure.client.scans,
72
64
  "dev": self.figure.client.device_manager.devices,
@@ -75,11 +67,11 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
75
67
 
76
68
  def _init_ui(self):
77
69
  # Plotting window
78
- self.glw_1_layout = QVBoxLayout(self.glw) # Create a new QVBoxLayout
70
+ self.glw_1_layout = QVBoxLayout(self.ui.glw) # Create a new QVBoxLayout
79
71
  self.figure = BECFigure(parent=self, gui_id="remote") # Create a new BECDeviceMonitor
80
72
  self.glw_1_layout.addWidget(self.figure) # Add BECDeviceMonitor to the layout
81
73
 
82
- self.dock_layout = QVBoxLayout(self.dock_placeholder)
74
+ self.dock_layout = QVBoxLayout(self.ui.dock_placeholder)
83
75
  self.dock = BECDockArea(gui_id="remote")
84
76
  self.dock_layout.addWidget(self.dock)
85
77
 
@@ -89,7 +81,7 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
89
81
  # init dock for testing
90
82
  self._init_dock()
91
83
 
92
- self.console_layout = QVBoxLayout(self.widget_console)
84
+ self.console_layout = QVBoxLayout(self.ui.widget_console)
93
85
  self.console = JupyterConsoleWidget()
94
86
  self.console_layout.addWidget(self.console)
95
87
  self.console.set_default_style("linux")
@@ -111,25 +103,22 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
111
103
  self.c1 = self.w1.get_config()
112
104
 
113
105
  def _init_dock(self):
114
- self.button_1 = QtWidgets.QPushButton("Button 1 ")
115
- self.button_2_a = QtWidgets.QPushButton("Button to be added at place 0,0 in d3")
116
- self.button_2_b = QtWidgets.QPushButton("button after without postions specified")
117
- self.button_2_c = QtWidgets.QPushButton("button super late")
118
- self.button_3 = QtWidgets.QPushButton("Button above Figure ")
119
- self.bar = SpiralProgressBar()
120
-
121
- self.label_2 = QtWidgets.QLabel("label which is added separately")
122
- self.label_3 = QtWidgets.QLabel("Label above figure")
123
-
124
- self.d1 = self.dock.add_dock(widget=self.button_1, position="left")
125
- self.d1.addWidget(self.label_2)
126
- self.d2 = self.dock.add_dock(widget=self.bar, position="right")
127
- self.d3 = self.dock.add_dock(name="figure")
128
- self.fig_dock3 = BECFigure()
129
- self.fig_dock3.plot(x_name="samx", y_name="bpm4d")
130
- self.d3.add_widget(self.label_3)
131
- self.d3.add_widget(self.button_3)
132
- self.d3.add_widget(self.fig_dock3)
106
+
107
+ self.d0 = self.dock.add_dock(name="dock_0")
108
+ self.fig0 = self.d0.add_widget_bec("BECFigure")
109
+ self.fig0.image("eiger", vrange=(0, 100))
110
+
111
+ self.d1 = self.dock.add_dock(name="dock_1", position="right")
112
+ self.fig1 = self.d1.add_widget_bec("BECFigure")
113
+ self.fig1.plot(x_name="samx", y_name="bpm4i")
114
+ self.fig1.plot(x_name="samx", y_name="bpm3a")
115
+
116
+ self.d2 = self.dock.add_dock(name="dock_2", position="bottom")
117
+ self.fig2 = self.d2.add_widget_bec("BECFigure", row=0, col=0)
118
+ self.fig2.motor_map(x_name="samx", y_name="samy")
119
+ self.fig2.plot(x_name="samx", y_name="bpm4i")
120
+ self.bar = self.d2.add_widget_bec("SpiralProgressBar", row=0, col=1)
121
+ self.bar.set_diameter(200)
133
122
 
134
123
  self.dock.save_state()
135
124
 
@@ -155,6 +144,7 @@ if __name__ == "__main__": # pragma: no cover
155
144
  app = QApplication(sys.argv)
156
145
  app.setApplicationName("Jupyter Console")
157
146
  app.setApplicationDisplayName("Jupyter Console")
147
+ qdarktheme.setup_theme("auto")
158
148
  icon = QIcon()
159
149
  icon.addFile(os.path.join(module_path, "assets", "terminal_icon.png"), size=QSize(48, 48))
160
150
  app.setWindowIcon(icon)
@@ -151,7 +151,7 @@ class MotorControlPanel(QWidget):
151
151
  self.selection_widget.selected_motors_signal.connect(self.absolute_widget.change_motors)
152
152
 
153
153
  # Set the window to a fixed size based on its contents
154
- self.layout().setSizeConstraint(layout.SetFixedSize)
154
+ # self.layout().setSizeConstraint(layout.SetFixedSize)
155
155
 
156
156
 
157
157
  class MotorControlPanelAbsolute(QWidget):
@@ -178,9 +178,6 @@ class MotorControlPanelAbsolute(QWidget):
178
178
  # Connecting signals and slots
179
179
  self.selection_widget.selected_motors_signal.connect(self.absolute_widget.change_motors)
180
180
 
181
- # Set the window to a fixed size based on its contents
182
- self.layout().setSizeConstraint(layout.SetFixedSize)
183
-
184
181
 
185
182
  class MotorControlPanelRelative(QWidget):
186
183
  def __init__(self, parent=None, client=None, config=None):
@@ -206,9 +203,6 @@ class MotorControlPanelRelative(QWidget):
206
203
  # Connecting signals and slots
207
204
  self.selection_widget.selected_motors_signal.connect(self.relative_widget.change_motors)
208
205
 
209
- # Set the window to a fixed size based on its contents
210
- self.layout().setSizeConstraint(layout.SetFixedSize)
211
-
212
206
 
213
207
  if __name__ == "__main__": # pragma: no cover
214
208
  import argparse
@@ -7,4 +7,5 @@ from .crosshair import Crosshair
7
7
  from .entry_validator import EntryValidator
8
8
  from .layout_manager import GridLayoutManager
9
9
  from .rpc_decorator import register_rpc_methods, rpc_public
10
+ from .ui_loader import UILoader
10
11
  from .validator_delegate import DoubleValidationDelegate
@@ -8,13 +8,13 @@ from qtpy.QtCore import Signal as pyqtSignal
8
8
 
9
9
  class Crosshair(QObject):
10
10
  # Signal for 1D plot
11
- coordinatesChanged1D = pyqtSignal(float, list)
12
- coordinatesClicked1D = pyqtSignal(float, list)
11
+ coordinatesChanged1D = pyqtSignal(tuple)
12
+ coordinatesClicked1D = pyqtSignal(tuple)
13
13
  # Signal for 2D plot
14
- coordinatesChanged2D = pyqtSignal(float, float)
15
- coordinatesClicked2D = pyqtSignal(float, float)
14
+ coordinatesChanged2D = pyqtSignal(tuple)
15
+ coordinatesClicked2D = pyqtSignal(tuple)
16
16
 
17
- def __init__(self, plot_item: pg.PlotItem, precision: int = None, parent=None):
17
+ def __init__(self, plot_item: pg.PlotItem, precision: int = 3, parent=None):
18
18
  """
19
19
  Crosshair for 1D and 2D plots.
20
20
 
@@ -174,10 +174,11 @@ class Crosshair(QObject):
174
174
  if isinstance(item, pg.PlotDataItem):
175
175
  if x is None or all(v is None for v in y_values):
176
176
  return
177
- self.coordinatesChanged1D.emit(
177
+ coordinate_to_emit = (
178
178
  round(x, self.precision),
179
179
  [round(y_val, self.precision) for y_val in y_values],
180
180
  )
181
+ self.coordinatesChanged1D.emit(coordinate_to_emit)
181
182
  for i, y_val in enumerate(y_values):
182
183
  self.marker_moved_1d[i].setData(
183
184
  [x if not self.is_log_x else np.log10(x)],
@@ -186,7 +187,8 @@ class Crosshair(QObject):
186
187
  elif isinstance(item, pg.ImageItem):
187
188
  if x is None or y_values is None:
188
189
  return
189
- self.coordinatesChanged2D.emit(x, y_values)
190
+ coordinate_to_emit = (x, y_values)
191
+ self.coordinatesChanged2D.emit(coordinate_to_emit)
190
192
 
191
193
  def mouse_clicked(self, event):
192
194
  """Handles the mouse clicked event, updating the crosshair position and emitting signals.
@@ -209,10 +211,11 @@ class Crosshair(QObject):
209
211
  if isinstance(item, pg.PlotDataItem):
210
212
  if x is None or all(v is None for v in y_values):
211
213
  return
212
- self.coordinatesClicked1D.emit(
214
+ coordinate_to_emit = (
213
215
  round(x, self.precision),
214
216
  [round(y_val, self.precision) for y_val in y_values],
215
217
  )
218
+ self.coordinatesClicked1D.emit(coordinate_to_emit)
216
219
  for i, y_val in enumerate(y_values):
217
220
  for marker in self.marker_clicked_1d[i]:
218
221
  marker.setData(
@@ -222,7 +225,8 @@ class Crosshair(QObject):
222
225
  elif isinstance(item, pg.ImageItem):
223
226
  if x is None or y_values is None:
224
227
  return
225
- self.coordinatesClicked2D.emit(x, y_values)
228
+ coordinate_to_emit = (x, y_values)
229
+ self.coordinatesClicked2D.emit(coordinate_to_emit)
226
230
  self.marker_2d.setPos([x, y_values])
227
231
 
228
232
  def check_log(self):
@@ -0,0 +1,58 @@
1
+ from qtpy import QT_VERSION
2
+ from qtpy.QtCore import QFile, QIODevice
3
+
4
+
5
+ class UILoader:
6
+ """Universal UI loader for PyQt5, PyQt6, PySide2, and PySide6."""
7
+
8
+ def __init__(self, parent=None):
9
+ self.parent = parent
10
+ if QT_VERSION.startswith("5"):
11
+ # PyQt5 or PySide2
12
+ from qtpy import uic
13
+
14
+ self.loader = uic.loadUi
15
+ elif QT_VERSION.startswith("6"):
16
+ # PyQt6 or PySide6
17
+ try:
18
+ from PySide6.QtUiTools import QUiLoader
19
+
20
+ self.loader = self.load_ui_pyside6
21
+ except ImportError:
22
+ from PyQt6.uic import loadUi
23
+
24
+ self.loader = loadUi
25
+
26
+ def load_ui_pyside6(self, ui_file, parent=None):
27
+ """
28
+ Specific loader for PySide6 using QUiLoader.
29
+ Args:
30
+ ui_file(str): Path to the .ui file.
31
+ parent(QWidget): Parent widget.
32
+
33
+ Returns:
34
+ QWidget: The loaded widget.
35
+ """
36
+ from PySide6.QtUiTools import QUiLoader
37
+
38
+ loader = QUiLoader(parent)
39
+ file = QFile(ui_file)
40
+ if not file.open(QIODevice.ReadOnly):
41
+ raise IOError(f"Cannot open file: {ui_file}")
42
+ widget = loader.load(file, parent)
43
+ file.close()
44
+ return widget
45
+
46
+ def load_ui(self, ui_file, parent=None):
47
+ """
48
+ Universal UI loader method.
49
+ Args:
50
+ ui_file(str): Path to the .ui file.
51
+ parent(QWidget): Parent widget.
52
+
53
+ Returns:
54
+ QWidget: The loaded widget.
55
+ """
56
+ if parent is None:
57
+ parent = self.parent
58
+ return self.loader(ui_file, parent)