bec-widgets 0.54.0__py3-none-any.whl → 0.56.0__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.
- .gitlab-ci.yml +113 -8
- CHANGELOG.md +32 -21
- PKG-INFO +3 -1
- bec_widgets/cli/client.py +252 -0
- bec_widgets/cli/generate_cli.py +4 -1
- bec_widgets/cli/rpc_wigdet_handler.py +2 -1
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +29 -37
- bec_widgets/examples/motor_movement/motor_control_compilations.py +1 -7
- bec_widgets/utils/__init__.py +1 -0
- bec_widgets/utils/crosshair.py +13 -9
- bec_widgets/utils/ui_loader.py +58 -0
- bec_widgets/widgets/__init__.py +1 -0
- bec_widgets/widgets/motor_control/motor_table/motor_table.py +44 -43
- bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +25 -23
- bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +51 -48
- bec_widgets/widgets/spiral_progress_bar/__init__.py +1 -0
- bec_widgets/widgets/spiral_progress_bar/ring.py +184 -0
- bec_widgets/widgets/spiral_progress_bar/spiral_progress_bar.py +594 -0
- {bec_widgets-0.54.0.dist-info → bec_widgets-0.56.0.dist-info}/METADATA +3 -1
- {bec_widgets-0.54.0.dist-info → bec_widgets-0.56.0.dist-info}/RECORD +29 -46
- docs/user/apps.md +1 -26
- pyproject.toml +2 -1
- tests/end-2-end/test_bec_dock_rpc_e2e.py +81 -0
- tests/unit_tests/test_client_utils.py +2 -2
- tests/unit_tests/test_crosshair.py +5 -5
- tests/unit_tests/test_motor_control.py +49 -45
- tests/unit_tests/test_spiral_progress_bar.py +338 -0
- bec_widgets/examples/eiger_plot/__init__.py +0 -0
- bec_widgets/examples/eiger_plot/eiger_plot.py +0 -307
- bec_widgets/examples/eiger_plot/eiger_plot.ui +0 -207
- bec_widgets/examples/mca_readout/__init__.py +0 -0
- bec_widgets/examples/mca_readout/mca_plot.py +0 -159
- bec_widgets/examples/mca_readout/mca_sim.py +0 -28
- bec_widgets/examples/modular_app/___init__.py +0 -0
- bec_widgets/examples/modular_app/modular.ui +0 -92
- bec_widgets/examples/modular_app/modular_app.py +0 -197
- bec_widgets/examples/motor_movement/config_example.yaml +0 -17
- bec_widgets/examples/motor_movement/csax_bec_config.yaml +0 -10
- bec_widgets/examples/motor_movement/csaxs_config.yaml +0 -17
- bec_widgets/examples/motor_movement/motor_example.py +0 -1344
- bec_widgets/examples/stream_plot/__init__.py +0 -0
- bec_widgets/examples/stream_plot/line_plot.ui +0 -155
- bec_widgets/examples/stream_plot/stream_plot.py +0 -337
- docs/user/apps/modular_app.md +0 -6
- docs/user/apps/motor_app.md +0 -34
- docs/user/apps/motor_app_10fps.gif +0 -0
- docs/user/apps/plot_app.md +0 -6
- tests/unit_tests/test_eiger_plot.py +0 -115
- tests/unit_tests/test_stream_plot.py +0 -158
- {bec_widgets-0.54.0.dist-info → bec_widgets-0.56.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.54.0.dist-info → bec_widgets-0.56.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,15 +2,14 @@ import os
|
|
2
2
|
|
3
3
|
import numpy as np
|
4
4
|
import pyqtgraph as pg
|
5
|
-
|
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.
|
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
15
|
|
@@ -25,7 +24,6 @@ class JupyterConsoleWidget(RichJupyterWidget): # pragma: no cover:
|
|
25
24
|
self.kernel_client.start_channels()
|
26
25
|
|
27
26
|
self.kernel_manager.kernel.shell.push({"np": np, "pg": pg})
|
28
|
-
# self.set_console_font_size(70)
|
29
27
|
|
30
28
|
def shutdown_kernel(self):
|
31
29
|
self.kernel_client.stop_channels()
|
@@ -39,32 +37,28 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
39
37
|
super().__init__(parent)
|
40
38
|
|
41
39
|
current_path = os.path.dirname(__file__)
|
42
|
-
|
40
|
+
self.ui = UILoader().load_ui(os.path.join(current_path, "jupyter_console_window.ui"), self)
|
43
41
|
|
44
42
|
self._init_ui()
|
45
43
|
|
46
|
-
self.splitter.setSizes([200, 100])
|
44
|
+
self.ui.splitter.setSizes([200, 100])
|
47
45
|
self.safe_close = False
|
48
|
-
# self.figure.clean_signal.connect(self.confirm_close)
|
49
|
-
|
50
|
-
self.register = RPCRegister()
|
51
|
-
self.register.add_rpc(self.figure)
|
52
46
|
|
53
47
|
# console push
|
54
48
|
self.console.kernel_manager.kernel.shell.push(
|
55
49
|
{
|
56
50
|
"fig": self.figure,
|
57
|
-
"register": self.register,
|
58
51
|
"dock": self.dock,
|
59
52
|
"w1": self.w1,
|
60
53
|
"w2": self.w2,
|
61
54
|
"w3": self.w3,
|
55
|
+
"d0": self.d0,
|
62
56
|
"d1": self.d1,
|
63
57
|
"d2": self.d2,
|
64
|
-
"
|
65
|
-
"
|
66
|
-
"
|
67
|
-
"
|
58
|
+
"fig0": self.fig0,
|
59
|
+
"fig1": self.fig1,
|
60
|
+
"fig2": self.fig2,
|
61
|
+
"bar": self.bar,
|
68
62
|
"bec": self.figure.client,
|
69
63
|
"scans": self.figure.client.scans,
|
70
64
|
"dev": self.figure.client.device_manager.devices,
|
@@ -73,11 +67,11 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
73
67
|
|
74
68
|
def _init_ui(self):
|
75
69
|
# Plotting window
|
76
|
-
self.glw_1_layout = QVBoxLayout(self.glw) # Create a new QVBoxLayout
|
70
|
+
self.glw_1_layout = QVBoxLayout(self.ui.glw) # Create a new QVBoxLayout
|
77
71
|
self.figure = BECFigure(parent=self, gui_id="remote") # Create a new BECDeviceMonitor
|
78
72
|
self.glw_1_layout.addWidget(self.figure) # Add BECDeviceMonitor to the layout
|
79
73
|
|
80
|
-
self.dock_layout = QVBoxLayout(self.dock_placeholder)
|
74
|
+
self.dock_layout = QVBoxLayout(self.ui.dock_placeholder)
|
81
75
|
self.dock = BECDockArea(gui_id="remote")
|
82
76
|
self.dock_layout.addWidget(self.dock)
|
83
77
|
|
@@ -87,7 +81,7 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
87
81
|
# init dock for testing
|
88
82
|
self._init_dock()
|
89
83
|
|
90
|
-
self.console_layout = QVBoxLayout(self.widget_console)
|
84
|
+
self.console_layout = QVBoxLayout(self.ui.widget_console)
|
91
85
|
self.console = JupyterConsoleWidget()
|
92
86
|
self.console_layout.addWidget(self.console)
|
93
87
|
self.console.set_default_style("linux")
|
@@ -109,25 +103,22 @@ class JupyterConsoleWindow(QWidget): # pragma: no cover:
|
|
109
103
|
self.c1 = self.w1.get_config()
|
110
104
|
|
111
105
|
def _init_dock(self):
|
112
|
-
|
113
|
-
self.
|
114
|
-
self.
|
115
|
-
self.
|
116
|
-
|
117
|
-
self.
|
118
|
-
|
119
|
-
self.
|
120
|
-
self.
|
121
|
-
|
122
|
-
self.
|
123
|
-
self.
|
124
|
-
self.
|
125
|
-
self.
|
126
|
-
self.
|
127
|
-
self.
|
128
|
-
self.d3.add_widget(self.label_3)
|
129
|
-
self.d3.add_widget(self.button_3)
|
130
|
-
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)
|
131
122
|
|
132
123
|
self.dock.save_state()
|
133
124
|
|
@@ -153,6 +144,7 @@ if __name__ == "__main__": # pragma: no cover
|
|
153
144
|
app = QApplication(sys.argv)
|
154
145
|
app.setApplicationName("Jupyter Console")
|
155
146
|
app.setApplicationDisplayName("Jupyter Console")
|
147
|
+
qdarktheme.setup_theme("auto")
|
156
148
|
icon = QIcon()
|
157
149
|
icon.addFile(os.path.join(module_path, "assets", "terminal_icon.png"), size=QSize(48, 48))
|
158
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
|
bec_widgets/utils/__init__.py
CHANGED
@@ -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
|
bec_widgets/utils/crosshair.py
CHANGED
@@ -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(
|
12
|
-
coordinatesClicked1D = pyqtSignal(
|
11
|
+
coordinatesChanged1D = pyqtSignal(tuple)
|
12
|
+
coordinatesClicked1D = pyqtSignal(tuple)
|
13
13
|
# Signal for 2D plot
|
14
|
-
coordinatesChanged2D = pyqtSignal(
|
15
|
-
coordinatesClicked2D = pyqtSignal(
|
14
|
+
coordinatesChanged2D = pyqtSignal(tuple)
|
15
|
+
coordinatesClicked2D = pyqtSignal(tuple)
|
16
16
|
|
17
|
-
def __init__(self, plot_item: pg.PlotItem, precision: int =
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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)
|
bec_widgets/widgets/__init__.py
CHANGED
@@ -16,6 +16,7 @@ from qtpy.QtWidgets import (
|
|
16
16
|
QTableWidgetItem,
|
17
17
|
)
|
18
18
|
|
19
|
+
from bec_widgets.utils import UILoader
|
19
20
|
from bec_widgets.widgets.motor_control.motor_control import MotorControlWidget
|
20
21
|
|
21
22
|
|
@@ -37,25 +38,25 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
37
38
|
def _load_ui(self):
|
38
39
|
"""Load the UI for the coordinate table."""
|
39
40
|
current_path = os.path.dirname(__file__)
|
40
|
-
|
41
|
+
self.ui = UILoader().load_ui(os.path.join(current_path, "motor_table.ui"), self)
|
41
42
|
|
42
43
|
def _init_ui(self):
|
43
44
|
"""Initialize the UI"""
|
44
45
|
# Setup table behaviour
|
45
46
|
self._setup_table()
|
46
|
-
self.table.setSelectionBehavior(QTableWidget.SelectRows)
|
47
|
+
self.ui.table.setSelectionBehavior(QTableWidget.SelectRows)
|
47
48
|
|
48
49
|
# for tag columns default tag
|
49
50
|
self.tag_counter = 1
|
50
51
|
|
51
52
|
# Connect signals and slots
|
52
|
-
self.checkBox_resize_auto.stateChanged.connect(self.resize_table_auto)
|
53
|
-
self.comboBox_mode.currentIndexChanged.connect(self.mode_switch)
|
53
|
+
self.ui.checkBox_resize_auto.stateChanged.connect(self.resize_table_auto)
|
54
|
+
self.ui.comboBox_mode.currentIndexChanged.connect(self.mode_switch)
|
54
55
|
|
55
56
|
# Keyboard shortcuts for deleting a row
|
56
|
-
self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self.table)
|
57
|
+
self.delete_shortcut = QShortcut(QKeySequence(Qt.Key_Delete), self.ui.table)
|
57
58
|
self.delete_shortcut.activated.connect(self.delete_selected_row)
|
58
|
-
self.backspace_shortcut = QShortcut(QKeySequence(Qt.Key_Backspace), self.table)
|
59
|
+
self.backspace_shortcut = QShortcut(QKeySequence(Qt.Key_Backspace), self.ui.table)
|
59
60
|
self.backspace_shortcut.activated.connect(self.delete_selected_row)
|
60
61
|
|
61
62
|
# Warning message for mode switch enable/disable
|
@@ -83,13 +84,13 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
83
84
|
self.mode = self.config["motor_control"].get("mode", "Individual")
|
84
85
|
|
85
86
|
# Set combobox to default mode
|
86
|
-
self.comboBox_mode.setCurrentText(self.mode)
|
87
|
+
self.ui.comboBox_mode.setCurrentText(self.mode)
|
87
88
|
|
88
89
|
self._init_ui()
|
89
90
|
|
90
91
|
def _setup_table(self):
|
91
92
|
"""Setup the table with appropriate headers and configurations."""
|
92
|
-
mode = self.comboBox_mode.currentText()
|
93
|
+
mode = self.ui.comboBox_mode.currentText()
|
93
94
|
|
94
95
|
if mode == "Individual":
|
95
96
|
self._setup_individual_mode()
|
@@ -101,14 +102,14 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
101
102
|
|
102
103
|
def _setup_individual_mode(self):
|
103
104
|
"""Setup the table for individual mode."""
|
104
|
-
self.table.setColumnCount(5)
|
105
|
-
self.table.setHorizontalHeaderLabels(["Show", "Move", "Tag", "X", "Y"])
|
106
|
-
self.table.verticalHeader().setVisible(False)
|
105
|
+
self.ui.table.setColumnCount(5)
|
106
|
+
self.ui.table.setHorizontalHeaderLabels(["Show", "Move", "Tag", "X", "Y"])
|
107
|
+
self.ui.table.verticalHeader().setVisible(False)
|
107
108
|
|
108
109
|
def _setup_start_stop_mode(self):
|
109
110
|
"""Setup the table for start/stop mode."""
|
110
|
-
self.table.setColumnCount(8)
|
111
|
-
self.table.setHorizontalHeaderLabels(
|
111
|
+
self.ui.table.setColumnCount(8)
|
112
|
+
self.ui.table.setHorizontalHeaderLabels(
|
112
113
|
[
|
113
114
|
"Show",
|
114
115
|
"Move [start]",
|
@@ -120,15 +121,15 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
120
121
|
"Y [end]",
|
121
122
|
]
|
122
123
|
)
|
123
|
-
self.table.verticalHeader().setVisible(False)
|
124
|
+
self.ui.table.verticalHeader().setVisible(False)
|
124
125
|
# Set flag to track if the coordinate is stat or the end of the entry
|
125
126
|
self.is_next_entry_end = False
|
126
127
|
|
127
128
|
def mode_switch(self):
|
128
129
|
"""Switch between individual and start/stop mode."""
|
129
|
-
last_selected_index = self.comboBox_mode.currentIndex()
|
130
|
+
last_selected_index = self.ui.comboBox_mode.currentIndex()
|
130
131
|
|
131
|
-
if self.table.rowCount() > 0 and self.warning_message is True:
|
132
|
+
if self.ui.table.rowCount() > 0 and self.warning_message is True:
|
132
133
|
msgBox = QMessageBox()
|
133
134
|
msgBox.setIcon(QMessageBox.Critical)
|
134
135
|
msgBox.setText(
|
@@ -138,9 +139,9 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
138
139
|
returnValue = msgBox.exec()
|
139
140
|
|
140
141
|
if returnValue is QMessageBox.Cancel:
|
141
|
-
self.comboBox_mode.blockSignals(True) # Block signals
|
142
|
-
self.comboBox_mode.setCurrentIndex(last_selected_index)
|
143
|
-
self.comboBox_mode.blockSignals(False) # Unblock signals
|
142
|
+
self.ui.comboBox_mode.blockSignals(True) # Block signals
|
143
|
+
self.ui.comboBox_mode.setCurrentIndex(last_selected_index)
|
144
|
+
self.ui.comboBox_mode.blockSignals(False) # Unblock signals
|
144
145
|
return
|
145
146
|
|
146
147
|
# Wipe table
|
@@ -170,7 +171,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
170
171
|
y(float): Y coordinate.
|
171
172
|
"""
|
172
173
|
|
173
|
-
mode = self.comboBox_mode.currentText()
|
174
|
+
mode = self.ui.comboBox_mode.currentText()
|
174
175
|
if mode == "Individual":
|
175
176
|
checkbox_pos = 0
|
176
177
|
button_pos = 1
|
@@ -181,8 +182,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
181
182
|
color = "green"
|
182
183
|
|
183
184
|
# Add new row -> new entry
|
184
|
-
row_count = self.table.rowCount()
|
185
|
-
self.table.insertRow(row_count)
|
185
|
+
row_count = self.ui.table.rowCount()
|
186
|
+
self.ui.table.insertRow(row_count)
|
186
187
|
|
187
188
|
# Add Widgets
|
188
189
|
self._add_widgets(
|
@@ -213,8 +214,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
213
214
|
color = "blue"
|
214
215
|
|
215
216
|
# Add new row -> new entry
|
216
|
-
row_count = self.table.rowCount()
|
217
|
-
self.table.insertRow(row_count)
|
217
|
+
row_count = self.ui.table.rowCount()
|
218
|
+
self.ui.table.insertRow(row_count)
|
218
219
|
|
219
220
|
# Add Widgets
|
220
221
|
self._add_widgets(
|
@@ -236,7 +237,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
236
237
|
|
237
238
|
elif self.is_next_entry_end is True: # It is the end position of the entry
|
238
239
|
print("End position")
|
239
|
-
row_count = self.table.rowCount() - 1 # Current row
|
240
|
+
row_count = self.ui.table.rowCount() - 1 # Current row
|
240
241
|
button_pos = 2
|
241
242
|
x_pos = 6
|
242
243
|
y_pos = 7
|
@@ -294,7 +295,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
294
295
|
# Add widgets
|
295
296
|
self._add_checkbox(row, checkBox_pos, x_pos, y_pos)
|
296
297
|
self._add_move_button(row, button_pos, x_pos, y_pos)
|
297
|
-
self.table.setItem(row, tag_pos, QTableWidgetItem(tag))
|
298
|
+
self.ui.table.setItem(row, tag_pos, QTableWidgetItem(tag))
|
298
299
|
self._add_line_edit(x, row, x_pos, x_pos, y_pos, coordinate_reference, color)
|
299
300
|
self._add_line_edit(y, row, y_pos, x_pos, y_pos, coordinate_reference, color)
|
300
301
|
|
@@ -302,10 +303,10 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
302
303
|
self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
303
304
|
|
304
305
|
# Connect item edit to emit coordinates
|
305
|
-
self.table.itemChanged.connect(
|
306
|
+
self.ui.table.itemChanged.connect(
|
306
307
|
lambda: print(f"item changed from {coordinate_reference} slot \n {x}-{y}-{color}")
|
307
308
|
)
|
308
|
-
self.table.itemChanged.connect(
|
309
|
+
self.ui.table.itemChanged.connect(
|
309
310
|
lambda: self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
310
311
|
)
|
311
312
|
|
@@ -321,7 +322,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
321
322
|
show_checkbox = QCheckBox()
|
322
323
|
show_checkbox.setChecked(True)
|
323
324
|
show_checkbox.stateChanged.connect(lambda: self.emit_plot_coordinates(x_pos, y_pos))
|
324
|
-
self.table.setCellWidget(row, checkBox_pos, show_checkbox)
|
325
|
+
self.ui.table.setCellWidget(row, checkBox_pos, show_checkbox)
|
325
326
|
|
326
327
|
def _add_move_button(self, row: int, button_pos: int, x_pos: int, y_pos: int) -> None:
|
327
328
|
"""
|
@@ -334,7 +335,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
334
335
|
"""
|
335
336
|
move_button = QPushButton("Move")
|
336
337
|
move_button.clicked.connect(lambda: self.handle_move_button_click(x_pos, y_pos))
|
337
|
-
self.table.setCellWidget(row, button_pos, move_button)
|
338
|
+
self.ui.table.setCellWidget(row, button_pos, move_button)
|
338
339
|
|
339
340
|
def _add_line_edit(
|
340
341
|
self,
|
@@ -367,7 +368,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
367
368
|
edit.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
368
369
|
|
369
370
|
# Add line edit to the table
|
370
|
-
self.table.setCellWidget(row, line_pos, edit)
|
371
|
+
self.ui.table.setCellWidget(row, line_pos, edit)
|
371
372
|
edit.textChanged.connect(
|
372
373
|
lambda: self.emit_plot_coordinates(x_pos, y_pos, coordinate_reference, color)
|
373
374
|
)
|
@@ -375,10 +376,10 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
375
376
|
def wipe_motor_map_coordinates(self):
|
376
377
|
"""Wipe the motor map coordinates."""
|
377
378
|
try:
|
378
|
-
self.table.itemChanged.disconnect() # Disconnect all previous connections
|
379
|
+
self.ui.table.itemChanged.disconnect() # Disconnect all previous connections
|
379
380
|
except TypeError:
|
380
381
|
print("No previous connections to disconnect")
|
381
|
-
self.table.setRowCount(0)
|
382
|
+
self.ui.table.setRowCount(0)
|
382
383
|
reference_tags = ["Individual", "Start", "Stop"]
|
383
384
|
for reference_tag in reference_tags:
|
384
385
|
self.plot_coordinates_signal.emit([], reference_tag, "green")
|
@@ -391,7 +392,7 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
391
392
|
y_pos(int): Y position of the coordinate.
|
392
393
|
"""
|
393
394
|
button = self.sender()
|
394
|
-
row = self.table.indexAt(button.pos()).row()
|
395
|
+
row = self.ui.table.indexAt(button.pos()).row()
|
395
396
|
|
396
397
|
x = self.get_coordinate(row, x_pos)
|
397
398
|
y = self.get_coordinate(row, y_pos)
|
@@ -410,8 +411,8 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
410
411
|
f"Emitting plot coordinates: x_pos={x_pos}, y_pos={y_pos}, reference_tag={reference_tag}, color={color}"
|
411
412
|
)
|
412
413
|
coordinates = []
|
413
|
-
for row in range(self.table.rowCount()):
|
414
|
-
show = self.table.cellWidget(row, 0).isChecked()
|
414
|
+
for row in range(self.ui.table.rowCount()):
|
415
|
+
show = self.ui.table.cellWidget(row, 0).isChecked()
|
415
416
|
x = self.get_coordinate(row, x_pos)
|
416
417
|
y = self.get_coordinate(row, y_pos)
|
417
418
|
|
@@ -427,27 +428,27 @@ class MotorCoordinateTable(MotorControlWidget):
|
|
427
428
|
Returns:
|
428
429
|
float: Value of the coordinate.
|
429
430
|
"""
|
430
|
-
edit = self.table.cellWidget(row, column)
|
431
|
+
edit = self.ui.table.cellWidget(row, column)
|
431
432
|
value = float(edit.text()) if edit and edit.text() != "" else None
|
432
433
|
if value:
|
433
434
|
return value
|
434
435
|
|
435
436
|
def delete_selected_row(self):
|
436
437
|
"""Delete the selected row from the table."""
|
437
|
-
selected_rows = self.table.selectionModel().selectedRows()
|
438
|
+
selected_rows = self.ui.table.selectionModel().selectedRows()
|
438
439
|
for row in selected_rows:
|
439
|
-
self.table.removeRow(row.row())
|
440
|
-
if self.comboBox_mode.currentText() == "Start/Stop":
|
440
|
+
self.ui.table.removeRow(row.row())
|
441
|
+
if self.ui.comboBox_mode.currentText() == "Start/Stop":
|
441
442
|
self.emit_plot_coordinates(x_pos=4, y_pos=5, reference_tag="Start", color="blue")
|
442
443
|
self.emit_plot_coordinates(x_pos=6, y_pos=7, reference_tag="Stop", color="red")
|
443
444
|
self.is_next_entry_end = False
|
444
|
-
elif self.comboBox_mode.currentText() == "Individual":
|
445
|
+
elif self.ui.comboBox_mode.currentText() == "Individual":
|
445
446
|
self.emit_plot_coordinates(x_pos=3, y_pos=4, reference_tag="Individual", color="green")
|
446
447
|
|
447
448
|
def resize_table_auto(self):
|
448
449
|
"""Resize the table to fit the contents."""
|
449
|
-
if self.checkBox_resize_auto.isChecked():
|
450
|
-
self.table.resizeColumnsToContents()
|
450
|
+
if self.ui.checkBox_resize_auto.isChecked():
|
451
|
+
self.ui.table.resizeColumnsToContents()
|
451
452
|
|
452
453
|
def move_motor(self, x: float, y: float) -> None:
|
453
454
|
"""
|