bec-widgets 0.87.0__py3-none-any.whl → 0.88.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.
- CHANGELOG.md +66 -70
- PKG-INFO +1 -1
- bec_widgets/assets/designer_icons/BECWaveformWidget.png +0 -0
- bec_widgets/assets/designer_icons/colormap_selector.png +0 -0
- bec_widgets/assets/toolbar_icons/add.svg +3 -0
- bec_widgets/assets/toolbar_icons/auto_range.svg +3 -0
- bec_widgets/assets/toolbar_icons/drag_pan_mode.svg +3 -0
- bec_widgets/assets/toolbar_icons/export.svg +9 -0
- bec_widgets/assets/toolbar_icons/fitting_parameters.svg +3 -0
- bec_widgets/assets/toolbar_icons/import.svg +9 -0
- bec_widgets/assets/toolbar_icons/line_axis.svg +3 -0
- bec_widgets/assets/toolbar_icons/photo_library.svg +3 -0
- bec_widgets/assets/toolbar_icons/rectangle_mode.svg +3 -0
- bec_widgets/assets/toolbar_icons/remove.svg +5 -0
- bec_widgets/assets/toolbar_icons/save.svg +3 -0
- bec_widgets/assets/toolbar_icons/settings.svg +4 -0
- bec_widgets/cli/client.py +307 -5
- bec_widgets/cli/server.py +2 -1
- bec_widgets/examples/jupyter_console/jupyter_console_window.py +13 -7
- bec_widgets/examples/plugin_example_pyside/tictactoe.py +1 -0
- bec_widgets/utils/bec_connector.py +19 -18
- bec_widgets/utils/bec_widget.py +19 -4
- bec_widgets/widgets/base_classes/device_input_base.py +3 -5
- bec_widgets/widgets/bec_queue/bec_queue.py +3 -2
- bec_widgets/widgets/bec_status_box/bec_status_box.py +2 -11
- bec_widgets/widgets/{color_map_selector/color_map_selector.py → colormap_selector/colormap_selector.py} +3 -1
- bec_widgets/widgets/colormap_selector/colormap_selector.pyproject +1 -0
- bec_widgets/widgets/{color_map_selector/color_map_selector_plugin.py → colormap_selector/colormap_selector_plugin.py} +8 -6
- bec_widgets/widgets/{color_map_selector/register_color_map_selector.py → colormap_selector/register_colormap_selector.py} +1 -1
- bec_widgets/widgets/device_box/device_box.py +2 -2
- bec_widgets/widgets/device_combobox/device_combobox.py +1 -8
- bec_widgets/widgets/device_line_edit/device_line_edit.py +2 -9
- bec_widgets/widgets/dock/dock.py +8 -6
- bec_widgets/widgets/dock/dock_area.py +4 -2
- bec_widgets/widgets/figure/figure.py +16 -8
- bec_widgets/widgets/figure/plots/axis_settings.py +38 -11
- bec_widgets/widgets/figure/plots/image/image.py +2 -4
- bec_widgets/widgets/figure/plots/motor_map/motor_map.py +1 -1
- bec_widgets/widgets/figure/plots/plot_base.py +7 -8
- bec_widgets/widgets/figure/plots/waveform/waveform.py +49 -53
- bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +10 -1
- bec_widgets/widgets/jupyter_console/jupyter_console.py +6 -0
- bec_widgets/widgets/motor_map/bec_motor_map_widget_plugin.py +1 -1
- bec_widgets/widgets/motor_map/motor_map_widget.py +9 -6
- bec_widgets/widgets/ring_progress_bar/ring.py +0 -4
- bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py +8 -8
- bec_widgets/widgets/scan_control/scan_control.py +2 -6
- bec_widgets/widgets/stop_button/stop_button.py +2 -2
- bec_widgets/widgets/text_box/text_box.py +3 -2
- bec_widgets/widgets/waveform/__init__.py +0 -0
- bec_widgets/widgets/waveform/bec_waveform_widget.pyproject +1 -0
- bec_widgets/widgets/waveform/bec_waveform_widget_plugin.py +59 -0
- bec_widgets/widgets/waveform/register_bec_waveform_widget.py +15 -0
- bec_widgets/widgets/waveform/waveform_toolbar/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.py +341 -0
- bec_widgets/widgets/waveform/waveform_toolbar/curve_dialog/curve_dialog.ui +358 -0
- bec_widgets/widgets/waveform/waveform_toolbar/dap_summary_dialog/__init__.py +0 -0
- bec_widgets/widgets/waveform/waveform_toolbar/dap_summary_dialog/dap_summary.ui +127 -0
- bec_widgets/widgets/waveform/waveform_toolbar/dap_summary_dialog/dap_summary_dialog.py +69 -0
- bec_widgets/widgets/waveform/waveform_toolbar/waveform_toolbar.py +117 -0
- bec_widgets/widgets/waveform/waveform_widget.py +571 -0
- bec_widgets/widgets/website/website.py +2 -2
- {bec_widgets-0.87.0.dist-info → bec_widgets-0.88.0.dist-info}/METADATA +1 -1
- {bec_widgets-0.87.0.dist-info → bec_widgets-0.88.0.dist-info}/RECORD +75 -48
- pyproject.toml +1 -1
- tests/unit_tests/test_color_map_selector.py +1 -1
- tests/unit_tests/test_device_input_base.py +10 -4
- tests/unit_tests/test_waveform_widget.py +264 -0
- bec_widgets/widgets/color_map_selector/assets/color_map_selector_icon.png +0 -0
- bec_widgets/widgets/color_map_selector/color_map_selector.pyproject +0 -1
- /bec_widgets/assets/{bec_widgets_icon.png → app_icons/bec_widgets_icon.png} +0 -0
- /bec_widgets/assets/{terminal_icon.png → app_icons/terminal_icon.png} +0 -0
- /bec_widgets/widgets/{color_map_selector → colormap_selector}/__init__.py +0 -0
- {bec_widgets-0.87.0.dist-info → bec_widgets-0.88.0.dist-info}/WHEEL +0 -0
- {bec_widgets-0.87.0.dist-info → bec_widgets-0.88.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-0.87.0.dist-info → bec_widgets-0.88.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,7 +6,7 @@ from qtpy.QtWidgets import QVBoxLayout, QWidget
|
|
6
6
|
|
7
7
|
from bec_widgets.qt_utils.settings_dialog import SettingsDialog
|
8
8
|
from bec_widgets.qt_utils.toolbar import ModularToolBar
|
9
|
-
from bec_widgets.utils import
|
9
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
10
10
|
from bec_widgets.widgets.figure import BECFigure
|
11
11
|
from bec_widgets.widgets.figure.plots.motor_map.motor_map import MotorMapConfig
|
12
12
|
from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_settings import MotorMapSettings
|
@@ -18,7 +18,7 @@ from bec_widgets.widgets.motor_map.motor_map_dialog.motor_map_toolbar import (
|
|
18
18
|
)
|
19
19
|
|
20
20
|
|
21
|
-
class BECMotorMapWidget(
|
21
|
+
class BECMotorMapWidget(BECWidget, QWidget):
|
22
22
|
USER_ACCESS = [
|
23
23
|
"change_motors",
|
24
24
|
"set_max_points",
|
@@ -28,6 +28,7 @@ class BECMotorMapWidget(BECConnector, QWidget):
|
|
28
28
|
"set_scatter_size",
|
29
29
|
"get_data",
|
30
30
|
"reset_history",
|
31
|
+
"export",
|
31
32
|
]
|
32
33
|
|
33
34
|
def __init__(
|
@@ -202,16 +203,18 @@ class BECMotorMapWidget(BECConnector, QWidget):
|
|
202
203
|
"""
|
203
204
|
self.map.set_scatter_size(scatter_size)
|
204
205
|
|
206
|
+
def export(self):
|
207
|
+
"""
|
208
|
+
Show the export dialog for the motor map.
|
209
|
+
"""
|
210
|
+
self.map.export()
|
211
|
+
|
205
212
|
def cleanup(self):
|
206
213
|
self.fig.cleanup()
|
207
214
|
self.toolbar.widgets["motor_x"].device_combobox.cleanup()
|
208
215
|
self.toolbar.widgets["motor_y"].device_combobox.cleanup()
|
209
216
|
return super().cleanup()
|
210
217
|
|
211
|
-
def closeEvent(self, event):
|
212
|
-
self.cleanup()
|
213
|
-
QWidget().closeEvent(event)
|
214
|
-
|
215
218
|
|
216
219
|
def main(): # pragma: no cover
|
217
220
|
from qtpy.QtWidgets import QApplication
|
@@ -10,7 +10,8 @@ from qtpy import QtCore, QtGui
|
|
10
10
|
from qtpy.QtCore import QSize, Slot
|
11
11
|
from qtpy.QtWidgets import QSizePolicy, QWidget
|
12
12
|
|
13
|
-
from bec_widgets.utils import
|
13
|
+
from bec_widgets.utils import Colors, ConnectionConfig, EntryValidator
|
14
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
14
15
|
from bec_widgets.widgets.ring_progress_bar.ring import Ring, RingConfig
|
15
16
|
|
16
17
|
|
@@ -66,7 +67,7 @@ class RingProgressBarConfig(ConnectionConfig):
|
|
66
67
|
_validate_colormap = field_validator("color_map")(Colors.validate_color_map)
|
67
68
|
|
68
69
|
|
69
|
-
class RingProgressBar(
|
70
|
+
class RingProgressBar(BECWidget, QWidget):
|
70
71
|
USER_ACCESS = [
|
71
72
|
"_get_all_rpc",
|
72
73
|
"_rpc_id",
|
@@ -208,7 +209,7 @@ class RingProgressBar(BECConnector, QWidget):
|
|
208
209
|
index(int): Index of the progress bar to remove.
|
209
210
|
"""
|
210
211
|
ring = self._find_ring_by_index(index)
|
211
|
-
ring.
|
212
|
+
ring.reset_connection()
|
212
213
|
self._rings.remove(ring)
|
213
214
|
self.config.rings.remove(ring.config)
|
214
215
|
self.config.num_bars -= 1
|
@@ -622,9 +623,8 @@ class RingProgressBar(BECConnector, QWidget):
|
|
622
623
|
|
623
624
|
def clear_all(self):
|
624
625
|
for ring in self._rings:
|
625
|
-
ring.
|
626
|
-
|
627
|
-
self._rings = []
|
626
|
+
ring.reset_connection()
|
627
|
+
self._rings.clear()
|
628
628
|
self.update()
|
629
629
|
self.initialize_bars()
|
630
630
|
|
@@ -633,6 +633,6 @@ class RingProgressBar(BECConnector, QWidget):
|
|
633
633
|
self.on_scan_queue_status, MessageEndpoints.scan_queue_status()
|
634
634
|
)
|
635
635
|
for ring in self._rings:
|
636
|
-
ring.
|
637
|
-
|
636
|
+
ring.reset_connection()
|
637
|
+
self._rings.clear()
|
638
638
|
super().cleanup()
|
@@ -10,13 +10,13 @@ from qtpy.QtWidgets import (
|
|
10
10
|
QWidget,
|
11
11
|
)
|
12
12
|
|
13
|
-
from bec_widgets.utils import
|
13
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
14
14
|
from bec_widgets.utils.colors import apply_theme
|
15
15
|
from bec_widgets.widgets.scan_control.scan_group_box import ScanGroupBox
|
16
16
|
from bec_widgets.widgets.stop_button.stop_button import StopButton
|
17
17
|
|
18
18
|
|
19
|
-
class ScanControl(
|
19
|
+
class ScanControl(BECWidget, QWidget):
|
20
20
|
|
21
21
|
def __init__(
|
22
22
|
self, parent=None, client=None, gui_id: str | None = None, allowed_scans: list | None = None
|
@@ -196,10 +196,6 @@ class ScanControl(BECConnector, QWidget):
|
|
196
196
|
widget.cleanup()
|
197
197
|
super().cleanup()
|
198
198
|
|
199
|
-
def closeEvent(self, event):
|
200
|
-
self.cleanup()
|
201
|
-
return QWidget.closeEvent(self, event)
|
202
|
-
|
203
199
|
|
204
200
|
# Application example
|
205
201
|
if __name__ == "__main__": # pragma: no cover
|
@@ -1,10 +1,10 @@
|
|
1
1
|
from qtpy.QtCore import Slot
|
2
2
|
from qtpy.QtWidgets import QPushButton
|
3
3
|
|
4
|
-
from bec_widgets.utils import
|
4
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
5
5
|
|
6
6
|
|
7
|
-
class StopButton(
|
7
|
+
class StopButton(BECWidget, QPushButton):
|
8
8
|
"""A button that stops the current scan."""
|
9
9
|
|
10
10
|
def __init__(self, parent=None, client=None, config=None, gui_id=None):
|
@@ -3,7 +3,8 @@ import re
|
|
3
3
|
from pydantic import Field, field_validator
|
4
4
|
from qtpy.QtWidgets import QTextEdit
|
5
5
|
|
6
|
-
from bec_widgets.utils.bec_connector import
|
6
|
+
from bec_widgets.utils.bec_connector import ConnectionConfig
|
7
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
7
8
|
from bec_widgets.utils.colors import Colors
|
8
9
|
|
9
10
|
|
@@ -27,7 +28,7 @@ class TextBoxConfig(ConnectionConfig):
|
|
27
28
|
_validate_background_color = field_validator("background_color")(Colors.validate_color)
|
28
29
|
|
29
30
|
|
30
|
-
class TextBox(
|
31
|
+
class TextBox(BECWidget, QTextEdit):
|
31
32
|
|
32
33
|
USER_ACCESS = ["set_color", "set_text", "set_font_size"]
|
33
34
|
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
{'files': ['waveform_widget.py']}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright (C) 2022 The Qt Company Ltd.
|
2
|
+
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
3
|
+
import os
|
4
|
+
|
5
|
+
from qtpy.QtDesigner import QDesignerCustomWidgetInterface
|
6
|
+
from qtpy.QtGui import QIcon
|
7
|
+
|
8
|
+
import bec_widgets
|
9
|
+
from bec_widgets.widgets.waveform.waveform_widget import BECWaveformWidget
|
10
|
+
|
11
|
+
DOM_XML = """
|
12
|
+
<ui language='c++'>
|
13
|
+
<widget class='BECWaveformWidget' name='bec_waveform_widget'>
|
14
|
+
</widget>
|
15
|
+
</ui>
|
16
|
+
"""
|
17
|
+
|
18
|
+
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
|
19
|
+
|
20
|
+
|
21
|
+
class BECWaveformWidgetPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
22
|
+
def __init__(self):
|
23
|
+
super().__init__()
|
24
|
+
self._form_editor = None
|
25
|
+
|
26
|
+
def createWidget(self, parent):
|
27
|
+
t = BECWaveformWidget(parent)
|
28
|
+
return t
|
29
|
+
|
30
|
+
def domXml(self):
|
31
|
+
return DOM_XML
|
32
|
+
|
33
|
+
def group(self):
|
34
|
+
return "BEC Plots"
|
35
|
+
|
36
|
+
def icon(self):
|
37
|
+
icon_path = os.path.join(MODULE_PATH, "assets", "designer_icons", "BECWaveformWidget.png")
|
38
|
+
return QIcon(icon_path)
|
39
|
+
|
40
|
+
def includeFile(self):
|
41
|
+
return "bec_waveform_widget"
|
42
|
+
|
43
|
+
def initialize(self, form_editor):
|
44
|
+
self._form_editor = form_editor
|
45
|
+
|
46
|
+
def isContainer(self):
|
47
|
+
return False
|
48
|
+
|
49
|
+
def isInitialized(self):
|
50
|
+
return self._form_editor is not None
|
51
|
+
|
52
|
+
def name(self):
|
53
|
+
return "BECWaveformWidget"
|
54
|
+
|
55
|
+
def toolTip(self):
|
56
|
+
return "BECWaveformWidget"
|
57
|
+
|
58
|
+
def whatsThis(self):
|
59
|
+
return self.toolTip()
|
@@ -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.waveform.bec_waveform_widget_plugin import BECWaveformWidgetPlugin
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget(BECWaveformWidgetPlugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|
File without changes
|
File without changes
|
@@ -0,0 +1,341 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
from typing import Literal
|
5
|
+
|
6
|
+
from pydantic import BaseModel
|
7
|
+
from qtpy.QtCore import QObject, QSize, Slot
|
8
|
+
from qtpy.QtGui import QIcon
|
9
|
+
from qtpy.QtWidgets import QComboBox, QLineEdit, QPushButton, QSpinBox, QTableWidget, QVBoxLayout
|
10
|
+
|
11
|
+
import bec_widgets
|
12
|
+
from bec_widgets.qt_utils.error_popups import WarningPopupUtility
|
13
|
+
from bec_widgets.qt_utils.settings_dialog import SettingWidget
|
14
|
+
from bec_widgets.utils import Colors, UILoader
|
15
|
+
from bec_widgets.widgets.color_button.color_button import ColorButton
|
16
|
+
from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
|
17
|
+
|
18
|
+
MODULE_PATH = os.path.dirname(bec_widgets.__file__)
|
19
|
+
|
20
|
+
|
21
|
+
class CurveSettings(SettingWidget):
|
22
|
+
def __init__(self, parent=None, *args, **kwargs):
|
23
|
+
super().__init__(parent, *args, **kwargs)
|
24
|
+
current_path = os.path.dirname(__file__)
|
25
|
+
|
26
|
+
self.ui = UILoader(self).loader(os.path.join(current_path, "curve_dialog.ui"))
|
27
|
+
self._setup_icons()
|
28
|
+
|
29
|
+
self.warning_util = WarningPopupUtility(self)
|
30
|
+
|
31
|
+
self.layout = QVBoxLayout(self)
|
32
|
+
self.layout.addWidget(self.ui)
|
33
|
+
|
34
|
+
self.ui.add_curve.clicked.connect(self.add_curve)
|
35
|
+
self.ui.add_dap.clicked.connect(self.add_dap)
|
36
|
+
self.ui.x_mode.currentIndexChanged.connect(self.set_x_mode)
|
37
|
+
self.ui.normalize_colors_scan.clicked.connect(lambda: self.change_colormap("scan"))
|
38
|
+
self.ui.normalize_colors_dap.clicked.connect(lambda: self.change_colormap("dap"))
|
39
|
+
|
40
|
+
def _setup_icons(self):
|
41
|
+
add_icon = QIcon()
|
42
|
+
add_icon.addFile(
|
43
|
+
os.path.join(MODULE_PATH, "assets", "toolbar_icons", "add.svg"), size=QSize(20, 20)
|
44
|
+
)
|
45
|
+
self.ui.add_dap.setIcon(add_icon)
|
46
|
+
self.ui.add_dap.setToolTip("Add DAP Curve")
|
47
|
+
self.ui.add_curve.setIcon(add_icon)
|
48
|
+
self.ui.add_curve.setToolTip("Add Scan Curve")
|
49
|
+
|
50
|
+
@Slot(dict)
|
51
|
+
def display_current_settings(self, config: dict | BaseModel):
|
52
|
+
|
53
|
+
# What elements should be enabled
|
54
|
+
x_name = self.target_widget.waveform._x_axis_mode["name"]
|
55
|
+
x_entry = self.target_widget.waveform._x_axis_mode["entry"]
|
56
|
+
self._enable_ui_elements(x_name, x_entry)
|
57
|
+
cm = self.target_widget.config.color_palette
|
58
|
+
self.ui.color_map_selector_scan.combo.setCurrentText(cm)
|
59
|
+
|
60
|
+
# Scan Curve Table
|
61
|
+
for label, curve in config["scan_segment"].items():
|
62
|
+
row_count = self.ui.scan_table.rowCount()
|
63
|
+
self.ui.scan_table.insertRow(row_count)
|
64
|
+
DialogRow(
|
65
|
+
parent=self,
|
66
|
+
table_widget=self.ui.scan_table,
|
67
|
+
client=self.target_widget.client,
|
68
|
+
row=row_count,
|
69
|
+
config=curve.config,
|
70
|
+
).add_scan_row()
|
71
|
+
|
72
|
+
# Add DAP Curves
|
73
|
+
for label, curve in config["DAP"].items():
|
74
|
+
row_count = self.ui.dap_table.rowCount()
|
75
|
+
self.ui.dap_table.insertRow(row_count)
|
76
|
+
DialogRow(
|
77
|
+
parent=self,
|
78
|
+
table_widget=self.ui.dap_table,
|
79
|
+
client=self.target_widget.client,
|
80
|
+
row=row_count,
|
81
|
+
config=curve.config,
|
82
|
+
).add_dap_row()
|
83
|
+
|
84
|
+
def _enable_ui_elements(self, name, entry):
|
85
|
+
if name is None:
|
86
|
+
name = "best_effort"
|
87
|
+
if name in ["index", "timestamp", "best_effort"]:
|
88
|
+
self.ui.x_mode.setCurrentText(name)
|
89
|
+
self.set_x_mode()
|
90
|
+
else:
|
91
|
+
self.ui.x_mode.setCurrentText("device")
|
92
|
+
self.set_x_mode()
|
93
|
+
self.ui.x_name.setText(name)
|
94
|
+
self.ui.x_entry.setText(entry)
|
95
|
+
|
96
|
+
@Slot()
|
97
|
+
def set_x_mode(self):
|
98
|
+
x_mode = self.ui.x_mode.currentText()
|
99
|
+
if x_mode in ["index", "timestamp", "best_effort"]:
|
100
|
+
self.ui.x_name.setEnabled(False)
|
101
|
+
self.ui.x_entry.setEnabled(False)
|
102
|
+
self.ui.dap_table.setEnabled(False)
|
103
|
+
self.ui.add_dap.setEnabled(False)
|
104
|
+
if self.ui.dap_table.rowCount() > 0:
|
105
|
+
self.warning_util.show_warning(
|
106
|
+
title="DAP Warning",
|
107
|
+
message="DAP is not supported without specific x-axis device. All current DAP curves will be removed.",
|
108
|
+
detailed_text=f"Affected curves: {[self.ui.dap_table.cellWidget(row, 0).text() for row in range(self.ui.dap_table.rowCount())]}",
|
109
|
+
)
|
110
|
+
else:
|
111
|
+
self.ui.x_name.setEnabled(True)
|
112
|
+
self.ui.x_entry.setEnabled(True)
|
113
|
+
self.ui.dap_table.setEnabled(True)
|
114
|
+
self.ui.add_dap.setEnabled(True)
|
115
|
+
|
116
|
+
@Slot()
|
117
|
+
def change_colormap(self, target: Literal["scan", "dap"]):
|
118
|
+
if target == "scan":
|
119
|
+
cm = self.ui.color_map_selector_scan.combo.currentText()
|
120
|
+
table = self.ui.scan_table
|
121
|
+
if target == "dap":
|
122
|
+
cm = self.ui.color_map_selector_dap.combo.currentText()
|
123
|
+
table = self.ui.dap_table
|
124
|
+
rows = table.rowCount()
|
125
|
+
colors = Colors.golden_angle_color(colormap=cm, num=rows + 1, format="HEX")
|
126
|
+
color_button_col = 2 if target == "scan" else 3
|
127
|
+
for row, color in zip(range(rows), colors):
|
128
|
+
table.cellWidget(row, color_button_col).setColor(color)
|
129
|
+
|
130
|
+
@Slot()
|
131
|
+
def accept_changes(self):
|
132
|
+
self.accept_curve_changes()
|
133
|
+
|
134
|
+
def accept_curve_changes(self):
|
135
|
+
old_curves_scans = list(self.target_widget.waveform._curves_data["scan_segment"].values())
|
136
|
+
old_curves_dap = list(self.target_widget.waveform._curves_data["DAP"].values())
|
137
|
+
for curve in old_curves_scans:
|
138
|
+
curve.remove()
|
139
|
+
for curve in old_curves_dap:
|
140
|
+
curve.remove()
|
141
|
+
self.get_curve_params()
|
142
|
+
|
143
|
+
def get_curve_params(self):
|
144
|
+
x_mode = self.ui.x_mode.currentText()
|
145
|
+
|
146
|
+
if x_mode in ["index", "timestamp", "best_effort"]:
|
147
|
+
x_name = x_mode
|
148
|
+
x_entry = x_mode
|
149
|
+
else:
|
150
|
+
x_name = self.ui.x_name.text()
|
151
|
+
x_entry = self.ui.x_entry.text()
|
152
|
+
|
153
|
+
self.target_widget.set_x(x_name=x_name, x_entry=x_entry)
|
154
|
+
|
155
|
+
for row in range(self.ui.scan_table.rowCount()):
|
156
|
+
y_name = self.ui.scan_table.cellWidget(row, 0).text()
|
157
|
+
y_entry = self.ui.scan_table.cellWidget(row, 1).text()
|
158
|
+
color = self.ui.scan_table.cellWidget(row, 2).get_color()
|
159
|
+
style = self.ui.scan_table.cellWidget(row, 3).currentText()
|
160
|
+
width = self.ui.scan_table.cellWidget(row, 4).value()
|
161
|
+
symbol_size = self.ui.scan_table.cellWidget(row, 5).value()
|
162
|
+
self.target_widget.plot(
|
163
|
+
y_name=y_name,
|
164
|
+
y_entry=y_entry,
|
165
|
+
color=color,
|
166
|
+
pen_style=style,
|
167
|
+
pen_width=width,
|
168
|
+
symbol_size=symbol_size,
|
169
|
+
)
|
170
|
+
|
171
|
+
if x_mode not in ["index", "timestamp", "best_effort"]:
|
172
|
+
|
173
|
+
for row in range(self.ui.dap_table.rowCount()):
|
174
|
+
y_name = self.ui.dap_table.cellWidget(row, 0).text()
|
175
|
+
y_entry = self.ui.dap_table.cellWidget(row, 1).text()
|
176
|
+
dap = self.ui.dap_table.cellWidget(row, 2).currentText()
|
177
|
+
color = self.ui.dap_table.cellWidget(row, 3).get_color()
|
178
|
+
style = self.ui.dap_table.cellWidget(row, 4).currentText()
|
179
|
+
width = self.ui.dap_table.cellWidget(row, 5).value()
|
180
|
+
symbol_size = self.ui.dap_table.cellWidget(row, 6).value()
|
181
|
+
|
182
|
+
self.target_widget.add_dap(
|
183
|
+
x_name=x_name,
|
184
|
+
x_entry=x_entry,
|
185
|
+
y_name=y_name,
|
186
|
+
y_entry=y_entry,
|
187
|
+
dap=dap,
|
188
|
+
color=color,
|
189
|
+
pen_style=style,
|
190
|
+
pen_width=width,
|
191
|
+
symbol_size=symbol_size,
|
192
|
+
)
|
193
|
+
self.target_widget.scan_history(-1)
|
194
|
+
|
195
|
+
def add_curve(self):
|
196
|
+
row_count = self.ui.scan_table.rowCount()
|
197
|
+
self.ui.scan_table.insertRow(row_count)
|
198
|
+
DialogRow(
|
199
|
+
parent=self,
|
200
|
+
table_widget=self.ui.scan_table,
|
201
|
+
client=self.target_widget.client,
|
202
|
+
row=row_count,
|
203
|
+
config=None,
|
204
|
+
).add_scan_row()
|
205
|
+
|
206
|
+
def add_dap(self):
|
207
|
+
row_count = self.ui.dap_table.rowCount()
|
208
|
+
self.ui.dap_table.insertRow(row_count)
|
209
|
+
DialogRow(
|
210
|
+
parent=self,
|
211
|
+
table_widget=self.ui.dap_table,
|
212
|
+
client=self.target_widget.client,
|
213
|
+
row=row_count,
|
214
|
+
config=None,
|
215
|
+
).add_dap_row()
|
216
|
+
|
217
|
+
|
218
|
+
class DialogRow(QObject):
|
219
|
+
def __init__(
|
220
|
+
self,
|
221
|
+
parent=None,
|
222
|
+
table_widget: QTableWidget = None,
|
223
|
+
row: int = None,
|
224
|
+
config: dict = None,
|
225
|
+
client=None,
|
226
|
+
):
|
227
|
+
|
228
|
+
super().__init__(parent=parent)
|
229
|
+
self.client = client
|
230
|
+
|
231
|
+
self.table_widget = table_widget
|
232
|
+
self.row = row
|
233
|
+
self.config = config
|
234
|
+
self.init_default_widgets()
|
235
|
+
|
236
|
+
def init_default_widgets(self):
|
237
|
+
|
238
|
+
# Remove Button
|
239
|
+
self.remove_button = RemoveButton()
|
240
|
+
|
241
|
+
# Name and Entry
|
242
|
+
self.device_line_edit = DeviceLineEdit()
|
243
|
+
self.entry_line_edit = QLineEdit()
|
244
|
+
|
245
|
+
self.dap_combo = QComboBox()
|
246
|
+
self.populate_dap_combobox()
|
247
|
+
|
248
|
+
# Styling
|
249
|
+
self.color_button = ColorButton()
|
250
|
+
self.style_combo = StyleComboBox()
|
251
|
+
self.width = QSpinBox()
|
252
|
+
self.width.setMinimum(1)
|
253
|
+
self.width.setMaximum(20)
|
254
|
+
self.width.setValue(2)
|
255
|
+
|
256
|
+
self.symbol_size = QSpinBox()
|
257
|
+
self.symbol_size.setMinimum(1)
|
258
|
+
self.symbol_size.setMaximum(20)
|
259
|
+
self.symbol_size.setValue(5)
|
260
|
+
|
261
|
+
self.remove_button.clicked.connect(
|
262
|
+
lambda: self.remove_row()
|
263
|
+
) # From some reason do not work without lambda
|
264
|
+
|
265
|
+
def populate_dap_combobox(self):
|
266
|
+
available_models = [
|
267
|
+
attr
|
268
|
+
for attr in dir(self.client.dap)
|
269
|
+
if not attr.startswith("__")
|
270
|
+
and not callable(getattr(self.client.dap, attr))
|
271
|
+
and not attr.startswith("_")
|
272
|
+
]
|
273
|
+
self.dap_combo.addItems(available_models)
|
274
|
+
|
275
|
+
def add_scan_row(self):
|
276
|
+
if self.config is not None:
|
277
|
+
self.device_line_edit.setText(self.config.signals.y.name)
|
278
|
+
self.entry_line_edit.setText(self.config.signals.y.entry)
|
279
|
+
self.color_button.setColor(self.config.color)
|
280
|
+
self.style_combo.setCurrentText(self.config.pen_style)
|
281
|
+
self.width.setValue(self.config.pen_width)
|
282
|
+
self.symbol_size.setValue(self.config.symbol_size)
|
283
|
+
else:
|
284
|
+
default_color = Colors.golden_angle_color(
|
285
|
+
colormap="magma", num=self.row + 1, format="HEX"
|
286
|
+
)[-1]
|
287
|
+
self.color_button.setColor(default_color)
|
288
|
+
|
289
|
+
self.table_widget.setCellWidget(self.row, 0, self.device_line_edit)
|
290
|
+
self.table_widget.setCellWidget(self.row, 1, self.entry_line_edit)
|
291
|
+
self.table_widget.setCellWidget(self.row, 2, self.color_button)
|
292
|
+
self.table_widget.setCellWidget(self.row, 3, self.style_combo)
|
293
|
+
self.table_widget.setCellWidget(self.row, 4, self.width)
|
294
|
+
self.table_widget.setCellWidget(self.row, 5, self.symbol_size)
|
295
|
+
self.table_widget.setCellWidget(self.row, 6, self.remove_button)
|
296
|
+
|
297
|
+
def add_dap_row(self):
|
298
|
+
if self.config is not None:
|
299
|
+
self.device_line_edit.setText(self.config.signals.y.name)
|
300
|
+
self.entry_line_edit.setText(self.config.signals.y.entry)
|
301
|
+
self.dap_combo.setCurrentText(self.config.signals.dap)
|
302
|
+
self.color_button.setColor(self.config.color)
|
303
|
+
self.style_combo.setCurrentText(self.config.pen_style)
|
304
|
+
self.width.setValue(self.config.pen_width)
|
305
|
+
self.symbol_size.setValue(self.config.symbol_size)
|
306
|
+
else:
|
307
|
+
default_color = Colors.golden_angle_color(
|
308
|
+
colormap="magma", num=self.row + 1, format="HEX"
|
309
|
+
)[-1]
|
310
|
+
self.color_button.setColor(default_color)
|
311
|
+
|
312
|
+
self.table_widget.setCellWidget(self.row, 0, self.device_line_edit)
|
313
|
+
self.table_widget.setCellWidget(self.row, 1, self.entry_line_edit)
|
314
|
+
self.table_widget.setCellWidget(self.row, 2, self.dap_combo)
|
315
|
+
self.table_widget.setCellWidget(self.row, 3, self.color_button)
|
316
|
+
self.table_widget.setCellWidget(self.row, 4, self.style_combo)
|
317
|
+
self.table_widget.setCellWidget(self.row, 5, self.width)
|
318
|
+
self.table_widget.setCellWidget(self.row, 6, self.symbol_size)
|
319
|
+
self.table_widget.setCellWidget(self.row, 7, self.remove_button)
|
320
|
+
|
321
|
+
@Slot()
|
322
|
+
def remove_row(self):
|
323
|
+
row = self.table_widget.indexAt(self.remove_button.pos()).row()
|
324
|
+
self.cleanup()
|
325
|
+
self.table_widget.removeRow(row)
|
326
|
+
|
327
|
+
def cleanup(self):
|
328
|
+
self.device_line_edit.cleanup()
|
329
|
+
|
330
|
+
|
331
|
+
class StyleComboBox(QComboBox):
|
332
|
+
def __init__(self, parent=None):
|
333
|
+
super().__init__(parent)
|
334
|
+
self.addItems(["solid", "dash", "dot", "dashdot"])
|
335
|
+
|
336
|
+
|
337
|
+
class RemoveButton(QPushButton):
|
338
|
+
def __init__(self, parent=None):
|
339
|
+
super().__init__(parent)
|
340
|
+
icon_path = os.path.join(MODULE_PATH, "assets", "toolbar_icons", "remove.svg")
|
341
|
+
self.setIcon(QIcon(icon_path))
|