bec-widgets 1.17.2__py3-none-any.whl → 1.18.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 (27) hide show
  1. .gitlab-ci.yml +5 -6
  2. CHANGELOG.md +37 -0
  3. PKG-INFO +1 -4
  4. README.md +15 -19
  5. bec_widgets/cli/generate_cli.py +15 -6
  6. bec_widgets/examples/jupyter_console/jupyter_console_window.py +12 -0
  7. bec_widgets/qt_utils/round_frame.py +6 -4
  8. bec_widgets/qt_utils/side_panel.py +60 -79
  9. bec_widgets/widgets/control/device_input/signal_combobox/register_signal_combo_box.py +17 -0
  10. bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box.pyproject +1 -0
  11. bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box_plugin.py +54 -0
  12. bec_widgets/widgets/control/device_input/signal_line_edit/signal_line_edit_plugin.py +1 -1
  13. bec_widgets/widgets/plots_next_gen/plot_base.py +571 -0
  14. bec_widgets/widgets/plots_next_gen/setting_menus/__init__.py +0 -0
  15. bec_widgets/widgets/plots_next_gen/setting_menus/axis_settings.py +95 -0
  16. bec_widgets/widgets/plots_next_gen/setting_menus/axis_settings_horizontal.ui +256 -0
  17. bec_widgets/widgets/plots_next_gen/setting_menus/axis_settings_vertical.ui +240 -0
  18. bec_widgets/widgets/plots_next_gen/toolbar_bundles/__init__.py +0 -0
  19. bec_widgets/widgets/plots_next_gen/toolbar_bundles/mouse_interactions.py +88 -0
  20. bec_widgets/widgets/plots_next_gen/toolbar_bundles/plot_export.py +63 -0
  21. bec_widgets/widgets/plots_next_gen/toolbar_bundles/save_state.py +48 -0
  22. {bec_widgets-1.17.2.dist-info → bec_widgets-1.18.1.dist-info}/METADATA +1 -4
  23. {bec_widgets-1.17.2.dist-info → bec_widgets-1.18.1.dist-info}/RECORD +27 -15
  24. pyproject.toml +1 -2
  25. {bec_widgets-1.17.2.dist-info → bec_widgets-1.18.1.dist-info}/WHEEL +0 -0
  26. {bec_widgets-1.17.2.dist-info → bec_widgets-1.18.1.dist-info}/entry_points.txt +0 -0
  27. {bec_widgets-1.17.2.dist-info → bec_widgets-1.18.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,256 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>427</width>
10
+ <height>270</height>
11
+ </rect>
12
+ </property>
13
+ <property name="minimumSize">
14
+ <size>
15
+ <width>0</width>
16
+ <height>250</height>
17
+ </size>
18
+ </property>
19
+ <property name="maximumSize">
20
+ <size>
21
+ <width>16777215</width>
22
+ <height>278</height>
23
+ </size>
24
+ </property>
25
+ <property name="windowTitle">
26
+ <string>Form</string>
27
+ </property>
28
+ <layout class="QGridLayout" name="gridLayout">
29
+ <item row="0" column="0" colspan="2">
30
+ <layout class="QHBoxLayout" name="horizontalLayout">
31
+ <item>
32
+ <widget class="QLabel" name="plot_title_label">
33
+ <property name="text">
34
+ <string>Plot Title</string>
35
+ </property>
36
+ </widget>
37
+ </item>
38
+ <item>
39
+ <widget class="QLineEdit" name="plot_title"/>
40
+ </item>
41
+ </layout>
42
+ </item>
43
+ <item row="1" column="0">
44
+ <widget class="QLabel" name="label_outer_axes">
45
+ <property name="text">
46
+ <string>Outer Axes</string>
47
+ </property>
48
+ </widget>
49
+ </item>
50
+ <item row="2" column="1">
51
+ <widget class="QGroupBox" name="y_axis_box">
52
+ <property name="title">
53
+ <string>Y Axis</string>
54
+ </property>
55
+ <layout class="QGridLayout" name="gridLayout_5">
56
+ <item row="3" column="2">
57
+ <widget class="QComboBox" name="y_scale">
58
+ <item>
59
+ <property name="text">
60
+ <string>linear</string>
61
+ </property>
62
+ </item>
63
+ <item>
64
+ <property name="text">
65
+ <string>log</string>
66
+ </property>
67
+ </item>
68
+ </widget>
69
+ </item>
70
+ <item row="2" column="2">
71
+ <widget class="QDoubleSpinBox" name="y_max">
72
+ <property name="alignment">
73
+ <set>Qt::AlignmentFlag::AlignCenter</set>
74
+ </property>
75
+ <property name="minimum">
76
+ <double>-9999.000000000000000</double>
77
+ </property>
78
+ <property name="maximum">
79
+ <double>9999.000000000000000</double>
80
+ </property>
81
+ </widget>
82
+ </item>
83
+ <item row="1" column="0" colspan="2">
84
+ <widget class="QLabel" name="y_min_label">
85
+ <property name="text">
86
+ <string>Min</string>
87
+ </property>
88
+ </widget>
89
+ </item>
90
+ <item row="1" column="2">
91
+ <widget class="QDoubleSpinBox" name="y_min">
92
+ <property name="alignment">
93
+ <set>Qt::AlignmentFlag::AlignCenter</set>
94
+ </property>
95
+ <property name="minimum">
96
+ <double>-9999.000000000000000</double>
97
+ </property>
98
+ <property name="maximum">
99
+ <double>9999.000000000000000</double>
100
+ </property>
101
+ </widget>
102
+ </item>
103
+ <item row="0" column="2">
104
+ <widget class="QLineEdit" name="y_label"/>
105
+ </item>
106
+ <item row="3" column="0">
107
+ <widget class="QLabel" name="y_scale_label">
108
+ <property name="text">
109
+ <string>Scale</string>
110
+ </property>
111
+ </widget>
112
+ </item>
113
+ <item row="0" column="0">
114
+ <widget class="QLabel" name="y_label_label">
115
+ <property name="text">
116
+ <string>Label</string>
117
+ </property>
118
+ </widget>
119
+ </item>
120
+ <item row="2" column="0">
121
+ <widget class="QLabel" name="y_max_label">
122
+ <property name="text">
123
+ <string>Max</string>
124
+ </property>
125
+ </widget>
126
+ </item>
127
+ <item row="4" column="2">
128
+ <widget class="QCheckBox" name="y_grid">
129
+ <property name="text">
130
+ <string/>
131
+ </property>
132
+ </widget>
133
+ </item>
134
+ <item row="4" column="0">
135
+ <widget class="QLabel" name="y_grid_label">
136
+ <property name="text">
137
+ <string>Grid</string>
138
+ </property>
139
+ </widget>
140
+ </item>
141
+ </layout>
142
+ </widget>
143
+ </item>
144
+ <item row="2" column="0">
145
+ <widget class="QGroupBox" name="x_axis_box">
146
+ <property name="title">
147
+ <string>X Axis</string>
148
+ </property>
149
+ <layout class="QGridLayout" name="gridLayout_4">
150
+ <item row="3" column="0">
151
+ <widget class="QLabel" name="x_scale_label">
152
+ <property name="text">
153
+ <string>Scale</string>
154
+ </property>
155
+ </widget>
156
+ </item>
157
+ <item row="1" column="2">
158
+ <widget class="QDoubleSpinBox" name="x_min">
159
+ <property name="alignment">
160
+ <set>Qt::AlignmentFlag::AlignCenter</set>
161
+ </property>
162
+ <property name="minimum">
163
+ <double>-9999.000000000000000</double>
164
+ </property>
165
+ <property name="maximum">
166
+ <double>9999.000000000000000</double>
167
+ </property>
168
+ </widget>
169
+ </item>
170
+ <item row="1" column="0" colspan="2">
171
+ <widget class="QLabel" name="x_min_label">
172
+ <property name="text">
173
+ <string>Min</string>
174
+ </property>
175
+ </widget>
176
+ </item>
177
+ <item row="2" column="2">
178
+ <widget class="QDoubleSpinBox" name="x_max">
179
+ <property name="alignment">
180
+ <set>Qt::AlignmentFlag::AlignCenter</set>
181
+ </property>
182
+ <property name="minimum">
183
+ <double>-9999.000000000000000</double>
184
+ </property>
185
+ <property name="maximum">
186
+ <double>9999.000000000000000</double>
187
+ </property>
188
+ </widget>
189
+ </item>
190
+ <item row="3" column="2">
191
+ <widget class="QComboBox" name="x_scale">
192
+ <item>
193
+ <property name="text">
194
+ <string>linear</string>
195
+ </property>
196
+ </item>
197
+ <item>
198
+ <property name="text">
199
+ <string>log</string>
200
+ </property>
201
+ </item>
202
+ </widget>
203
+ </item>
204
+ <item row="2" column="0">
205
+ <widget class="QLabel" name="x_max_label">
206
+ <property name="text">
207
+ <string>Max</string>
208
+ </property>
209
+ </widget>
210
+ </item>
211
+ <item row="0" column="2">
212
+ <widget class="QLineEdit" name="x_label"/>
213
+ </item>
214
+ <item row="0" column="0">
215
+ <widget class="QLabel" name="x_label_label">
216
+ <property name="text">
217
+ <string>Label</string>
218
+ </property>
219
+ </widget>
220
+ </item>
221
+ <item row="4" column="2">
222
+ <widget class="QCheckBox" name="x_grid">
223
+ <property name="text">
224
+ <string/>
225
+ </property>
226
+ </widget>
227
+ </item>
228
+ <item row="4" column="0">
229
+ <widget class="QLabel" name="x_grid_label">
230
+ <property name="text">
231
+ <string>Grid</string>
232
+ </property>
233
+ </widget>
234
+ </item>
235
+ </layout>
236
+ </widget>
237
+ </item>
238
+ <item row="1" column="1">
239
+ <widget class="ToggleSwitch" name="switch_outer_axes">
240
+ <property name="checked" stdset="0">
241
+ <bool>false</bool>
242
+ </property>
243
+ </widget>
244
+ </item>
245
+ </layout>
246
+ </widget>
247
+ <customwidgets>
248
+ <customwidget>
249
+ <class>ToggleSwitch</class>
250
+ <extends>QWidget</extends>
251
+ <header>toggle_switch</header>
252
+ </customwidget>
253
+ </customwidgets>
254
+ <resources/>
255
+ <connections/>
256
+ </ui>
@@ -0,0 +1,240 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ui version="4.0">
3
+ <class>Form</class>
4
+ <widget class="QWidget" name="Form">
5
+ <property name="geometry">
6
+ <rect>
7
+ <x>0</x>
8
+ <y>0</y>
9
+ <width>241</width>
10
+ <height>526</height>
11
+ </rect>
12
+ </property>
13
+ <property name="windowTitle">
14
+ <string>Form</string>
15
+ </property>
16
+ <layout class="QGridLayout" name="gridLayout">
17
+ <item row="4" column="0" colspan="2">
18
+ <widget class="QGroupBox" name="x_axis_box">
19
+ <property name="title">
20
+ <string>X Axis</string>
21
+ </property>
22
+ <layout class="QGridLayout" name="gridLayout_4">
23
+ <item row="2" column="2">
24
+ <widget class="QDoubleSpinBox" name="x_max">
25
+ <property name="alignment">
26
+ <set>Qt::AlignmentFlag::AlignCenter</set>
27
+ </property>
28
+ <property name="minimum">
29
+ <double>-9999.000000000000000</double>
30
+ </property>
31
+ <property name="maximum">
32
+ <double>9999.000000000000000</double>
33
+ </property>
34
+ </widget>
35
+ </item>
36
+ <item row="3" column="0">
37
+ <widget class="QLabel" name="x_scale_label">
38
+ <property name="text">
39
+ <string>Log</string>
40
+ </property>
41
+ </widget>
42
+ </item>
43
+ <item row="0" column="2">
44
+ <widget class="QLineEdit" name="x_label"/>
45
+ </item>
46
+ <item row="2" column="0">
47
+ <widget class="QLabel" name="x_max_label">
48
+ <property name="text">
49
+ <string>Max</string>
50
+ </property>
51
+ </widget>
52
+ </item>
53
+ <item row="3" column="2">
54
+ <widget class="ToggleSwitch" name="x_log">
55
+ <property name="checked" stdset="0">
56
+ <bool>false</bool>
57
+ </property>
58
+ </widget>
59
+ </item>
60
+ <item row="5" column="0">
61
+ <widget class="QLabel" name="x_grid_label">
62
+ <property name="text">
63
+ <string>Grid</string>
64
+ </property>
65
+ </widget>
66
+ </item>
67
+ <item row="1" column="2">
68
+ <widget class="QDoubleSpinBox" name="x_min">
69
+ <property name="alignment">
70
+ <set>Qt::AlignmentFlag::AlignCenter</set>
71
+ </property>
72
+ <property name="minimum">
73
+ <double>-9999.000000000000000</double>
74
+ </property>
75
+ <property name="maximum">
76
+ <double>9999.000000000000000</double>
77
+ </property>
78
+ </widget>
79
+ </item>
80
+ <item row="1" column="0" colspan="2">
81
+ <widget class="QLabel" name="x_min_label">
82
+ <property name="text">
83
+ <string>Min</string>
84
+ </property>
85
+ </widget>
86
+ </item>
87
+ <item row="0" column="0">
88
+ <widget class="QLabel" name="x_label_label">
89
+ <property name="text">
90
+ <string>Label</string>
91
+ </property>
92
+ </widget>
93
+ </item>
94
+ <item row="5" column="2">
95
+ <widget class="ToggleSwitch" name="x_grid">
96
+ <property name="checked" stdset="0">
97
+ <bool>false</bool>
98
+ </property>
99
+ </widget>
100
+ </item>
101
+ </layout>
102
+ </widget>
103
+ </item>
104
+ <item row="0" column="0" colspan="2">
105
+ <layout class="QHBoxLayout" name="horizontalLayout">
106
+ <item>
107
+ <widget class="QLabel" name="plot_title_label">
108
+ <property name="text">
109
+ <string>Plot Title</string>
110
+ </property>
111
+ </widget>
112
+ </item>
113
+ <item>
114
+ <widget class="QLineEdit" name="title"/>
115
+ </item>
116
+ </layout>
117
+ </item>
118
+ <item row="2" column="0">
119
+ <widget class="QLabel" name="label_outer_axes">
120
+ <property name="text">
121
+ <string>Outer Axes</string>
122
+ </property>
123
+ </widget>
124
+ </item>
125
+ <item row="5" column="0" colspan="2">
126
+ <widget class="QGroupBox" name="y_axis_box">
127
+ <property name="title">
128
+ <string>Y Axis</string>
129
+ </property>
130
+ <layout class="QGridLayout" name="gridLayout_5">
131
+ <item row="2" column="2">
132
+ <widget class="QDoubleSpinBox" name="y_max">
133
+ <property name="alignment">
134
+ <set>Qt::AlignmentFlag::AlignCenter</set>
135
+ </property>
136
+ <property name="minimum">
137
+ <double>-9999.000000000000000</double>
138
+ </property>
139
+ <property name="maximum">
140
+ <double>9999.000000000000000</double>
141
+ </property>
142
+ </widget>
143
+ </item>
144
+ <item row="1" column="0" colspan="2">
145
+ <widget class="QLabel" name="y_min_label">
146
+ <property name="text">
147
+ <string>Min</string>
148
+ </property>
149
+ </widget>
150
+ </item>
151
+ <item row="1" column="2">
152
+ <widget class="QDoubleSpinBox" name="y_min">
153
+ <property name="alignment">
154
+ <set>Qt::AlignmentFlag::AlignCenter</set>
155
+ </property>
156
+ <property name="minimum">
157
+ <double>-9999.000000000000000</double>
158
+ </property>
159
+ <property name="maximum">
160
+ <double>9999.000000000000000</double>
161
+ </property>
162
+ </widget>
163
+ </item>
164
+ <item row="0" column="2">
165
+ <widget class="QLineEdit" name="y_label"/>
166
+ </item>
167
+ <item row="3" column="0">
168
+ <widget class="QLabel" name="y_scale_label">
169
+ <property name="text">
170
+ <string>Log</string>
171
+ </property>
172
+ </widget>
173
+ </item>
174
+ <item row="0" column="0">
175
+ <widget class="QLabel" name="y_label_label">
176
+ <property name="text">
177
+ <string>Label</string>
178
+ </property>
179
+ </widget>
180
+ </item>
181
+ <item row="2" column="0">
182
+ <widget class="QLabel" name="y_max_label">
183
+ <property name="text">
184
+ <string>Max</string>
185
+ </property>
186
+ </widget>
187
+ </item>
188
+ <item row="4" column="0">
189
+ <widget class="QLabel" name="y_grid_label">
190
+ <property name="text">
191
+ <string>Grid</string>
192
+ </property>
193
+ </widget>
194
+ </item>
195
+ <item row="3" column="2">
196
+ <widget class="ToggleSwitch" name="y_log">
197
+ <property name="checked" stdset="0">
198
+ <bool>false</bool>
199
+ </property>
200
+ </widget>
201
+ </item>
202
+ <item row="4" column="2">
203
+ <widget class="ToggleSwitch" name="y_grid">
204
+ <property name="checked" stdset="0">
205
+ <bool>false</bool>
206
+ </property>
207
+ </widget>
208
+ </item>
209
+ </layout>
210
+ </widget>
211
+ </item>
212
+ <item row="2" column="1">
213
+ <widget class="ToggleSwitch" name="outer_axes">
214
+ <property name="checked" stdset="0">
215
+ <bool>false</bool>
216
+ </property>
217
+ </widget>
218
+ </item>
219
+ <item row="1" column="0">
220
+ <widget class="QLabel" name="label">
221
+ <property name="text">
222
+ <string>Inner Axes</string>
223
+ </property>
224
+ </widget>
225
+ </item>
226
+ <item row="1" column="1">
227
+ <widget class="ToggleSwitch" name="inner_axes"/>
228
+ </item>
229
+ </layout>
230
+ </widget>
231
+ <customwidgets>
232
+ <customwidget>
233
+ <class>ToggleSwitch</class>
234
+ <extends>QWidget</extends>
235
+ <header>toggle_switch</header>
236
+ </customwidget>
237
+ </customwidgets>
238
+ <resources/>
239
+ <connections/>
240
+ </ui>
@@ -0,0 +1,88 @@
1
+ import pyqtgraph as pg
2
+
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot
4
+ from bec_widgets.qt_utils.toolbar import MaterialIconAction, ToolbarBundle
5
+
6
+
7
+ class MouseInteractionToolbarBundle(ToolbarBundle):
8
+ """
9
+ A bundle of actions that are hooked in this constructor itself,
10
+ so that you can immediately connect the signals and toggle states.
11
+
12
+ This bundle is for a toolbar that controls mouse interactions on a plot.
13
+ """
14
+
15
+ def __init__(self, bundle_id="mouse_interaction", target_widget=None, **kwargs):
16
+ super().__init__(bundle_id=bundle_id, actions=[], **kwargs)
17
+ self.target_widget = target_widget
18
+
19
+ # Create each MaterialIconAction with a parent
20
+ # so the signals can fire even if the toolbar isn't added yet.
21
+ drag = MaterialIconAction(
22
+ icon_name="drag_pan",
23
+ tooltip="Drag Mouse Mode",
24
+ checkable=True,
25
+ parent=self.target_widget, # or any valid parent
26
+ )
27
+ rect = MaterialIconAction(
28
+ icon_name="frame_inspect",
29
+ tooltip="Rectangle Zoom Mode",
30
+ checkable=True,
31
+ parent=self.target_widget,
32
+ )
33
+ auto = MaterialIconAction(
34
+ icon_name="open_in_full",
35
+ tooltip="Autorange Plot",
36
+ checkable=False,
37
+ parent=self.target_widget,
38
+ )
39
+ aspect_ratio = MaterialIconAction(
40
+ icon_name="aspect_ratio",
41
+ tooltip="Lock image aspect ratio",
42
+ checkable=True,
43
+ parent=self.target_widget,
44
+ )
45
+
46
+ # Add them to the bundle
47
+ self.add_action("drag_mode", drag)
48
+ self.add_action("rectangle_mode", rect)
49
+ self.add_action("auto_range", auto)
50
+ self.add_action("aspect_ratio", aspect_ratio)
51
+
52
+ # Immediately connect signals
53
+ drag.action.toggled.connect(self.enable_mouse_pan_mode)
54
+ rect.action.toggled.connect(self.enable_mouse_rectangle_mode)
55
+ auto.action.triggered.connect(self.autorange_plot)
56
+ aspect_ratio.action.toggled.connect(self.lock_aspect_ratio)
57
+
58
+ @SafeSlot(bool)
59
+ def enable_mouse_rectangle_mode(self, checked: bool):
60
+ """
61
+ Enable the rectangle zoom mode on the plot widget.
62
+ """
63
+ self.actions["drag_mode"].action.setChecked(not checked)
64
+ if self.target_widget and checked:
65
+ self.target_widget.plot_item.getViewBox().setMouseMode(pg.ViewBox.RectMode)
66
+
67
+ @SafeSlot(bool)
68
+ def enable_mouse_pan_mode(self, checked: bool):
69
+ """
70
+ Enable the pan mode on the plot widget.
71
+ """
72
+ self.actions["rectangle_mode"].action.setChecked(not checked)
73
+ if self.target_widget and checked:
74
+ self.target_widget.plot_item.getViewBox().setMouseMode(pg.ViewBox.PanMode)
75
+
76
+ @SafeSlot()
77
+ def autorange_plot(self):
78
+ """
79
+ Enable autorange on the plot widget.
80
+ """
81
+ if self.target_widget:
82
+ self.target_widget.auto_range_x = True
83
+ self.target_widget.auto_range_y = True
84
+
85
+ @SafeSlot(bool)
86
+ def lock_aspect_ratio(self, checked: bool):
87
+ if self.target_widget:
88
+ self.target_widget.lock_aspect_ratio = checked
@@ -0,0 +1,63 @@
1
+ from pyqtgraph.exporters import MatplotlibExporter
2
+
3
+ from bec_widgets.qt_utils.error_popups import SafeSlot, WarningPopupUtility
4
+ from bec_widgets.qt_utils.toolbar import MaterialIconAction, ToolbarBundle
5
+
6
+
7
+ class PlotExportBundle(ToolbarBundle):
8
+ """
9
+ A bundle of actions that are hooked in this constructor itself,
10
+ so that you can immediately connect the signals and toggle states.
11
+
12
+ This bundle is for a toolbar that controls exporting a plot.
13
+ """
14
+
15
+ def __init__(self, bundle_id="mouse_interaction", target_widget=None, **kwargs):
16
+ super().__init__(bundle_id=bundle_id, actions=[], **kwargs)
17
+ self.target_widget = target_widget
18
+
19
+ # Create each MaterialIconAction with a parent
20
+ # so the signals can fire even if the toolbar isn't added yet.
21
+ save = MaterialIconAction(
22
+ icon_name="save", tooltip="Open Export Dialog", parent=self.target_widget
23
+ )
24
+ matplotlib = MaterialIconAction(
25
+ icon_name="photo_library", tooltip="Open Matplotlib Dialog", parent=self.target_widget
26
+ )
27
+
28
+ # Add them to the bundle
29
+ self.add_action("save", save)
30
+ self.add_action("matplotlib", matplotlib)
31
+
32
+ # Immediately connect signals
33
+ save.action.triggered.connect(self.export_dialog)
34
+ matplotlib.action.triggered.connect(self.matplotlib_dialog)
35
+
36
+ @SafeSlot()
37
+ def export_dialog(self):
38
+ """
39
+ Open the export dialog for the plot widget.
40
+ """
41
+ if self.target_widget:
42
+ scene = self.target_widget.plot_item.scene()
43
+ scene.contextMenuItem = self.target_widget.plot_item
44
+ scene.showExportDialog()
45
+
46
+ @SafeSlot()
47
+ def matplotlib_dialog(self):
48
+ """
49
+ Export the plot widget to Matplotlib.
50
+ """
51
+ if self.target_widget:
52
+ try:
53
+ import matplotlib as mpl
54
+
55
+ MatplotlibExporter(self.target_widget.plot_item).export()
56
+ except:
57
+ warning_util = WarningPopupUtility()
58
+ warning_util.show_warning(
59
+ title="Matplotlib not installed",
60
+ message="Matplotlib is required for this feature.",
61
+ detailed_text="Please install matplotlib in your Python environment by using 'pip install matplotlib'.",
62
+ )
63
+ return