bec-widgets 0.117.1__py3-none-any.whl → 0.119.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.
Files changed (26) hide show
  1. CHANGELOG.md +47 -51
  2. PKG-INFO +1 -1
  3. bec_widgets/applications/alignment/alignment_1d/alignment_1d.py +33 -89
  4. bec_widgets/applications/alignment/alignment_1d/alignment_1d.ui +413 -715
  5. bec_widgets/examples/jupyter_console/jupyter_console_window.py +1 -1
  6. bec_widgets/qt_utils/compact_popup.py +68 -23
  7. bec_widgets/qt_utils/toolbar.py +51 -12
  8. bec_widgets/widgets/device_line_edit/device_line_edit.py +15 -1
  9. bec_widgets/widgets/figure/figure.py +10 -1
  10. bec_widgets/widgets/figure/plots/image/image.py +86 -19
  11. bec_widgets/widgets/image/image_widget.py +15 -2
  12. bec_widgets/widgets/positioner_box/positioner_box.py +10 -4
  13. bec_widgets/widgets/positioner_group/__init__.py +0 -0
  14. bec_widgets/widgets/positioner_group/positioner_group.py +170 -0
  15. bec_widgets/widgets/positioner_group/positioner_group.pyproject +1 -0
  16. bec_widgets/widgets/positioner_group/positioner_group_plugin.py +57 -0
  17. bec_widgets/widgets/positioner_group/register_positioner_group.py +15 -0
  18. bec_widgets/widgets/scan_control/scan_control.py +74 -122
  19. bec_widgets/widgets/scan_control/scan_group_box.py +66 -11
  20. bec_widgets/widgets/stop_button/stop_button.py +1 -1
  21. {bec_widgets-0.117.1.dist-info → bec_widgets-0.119.0.dist-info}/METADATA +1 -1
  22. {bec_widgets-0.117.1.dist-info → bec_widgets-0.119.0.dist-info}/RECORD +26 -21
  23. pyproject.toml +1 -1
  24. {bec_widgets-0.117.1.dist-info → bec_widgets-0.119.0.dist-info}/WHEEL +0 -0
  25. {bec_widgets-0.117.1.dist-info → bec_widgets-0.119.0.dist-info}/entry_points.txt +0 -0
  26. {bec_widgets-0.117.1.dist-info → bec_widgets-0.119.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,170 @@
1
+ """ Module for a PositionerGroup widget to control a positioner device."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from bec_lib.device import Positioner
6
+ from bec_lib.logger import bec_logger
7
+ from qtpy.QtCore import Property, QSize, Signal, Slot
8
+ from qtpy.QtWidgets import QGridLayout, QGroupBox, QSizePolicy, QVBoxLayout, QWidget
9
+
10
+ from bec_widgets.utils.bec_widget import BECWidget
11
+ from bec_widgets.widgets.positioner_box.positioner_box import PositionerBox
12
+
13
+ logger = bec_logger.logger
14
+
15
+
16
+ class PositionerGroupBox(QGroupBox):
17
+
18
+ position_update = Signal(float)
19
+
20
+ def __init__(self, parent, dev_name):
21
+ super().__init__(parent)
22
+
23
+ self.device_name = dev_name
24
+
25
+ QVBoxLayout(self)
26
+ self.layout().setContentsMargins(0, 0, 0, 0)
27
+ self.layout().setSpacing(0)
28
+ self.widget = PositionerBox(self, dev_name)
29
+ self.widget.compact_view = True
30
+ self.widget.expand_popup = False
31
+ self.layout().addWidget(self.widget)
32
+ self.widget.position_update.connect(self._on_position_update)
33
+ self.widget.expand.connect(self._on_expand)
34
+ self.setTitle(self.device_name)
35
+ self.widget.init_device() # force readback
36
+
37
+ def _on_expand(self, expand):
38
+ if expand:
39
+ self.setTitle("")
40
+ self.setFlat(True)
41
+ else:
42
+ self.setTitle(self.device_name)
43
+ self.setFlat(False)
44
+
45
+ def _on_position_update(self, pos: float):
46
+ self.position_update.emit(pos)
47
+ self.widget.label = f"%.{self.widget.dev[self.widget.device].precision}f" % pos
48
+
49
+ def close(self):
50
+ self.widget.close()
51
+ super().close()
52
+
53
+
54
+ class PositionerGroup(BECWidget, QWidget):
55
+ """Simple Widget to control a positioner in box form"""
56
+
57
+ ICON_NAME = "grid_view"
58
+ USER_ACCESS = ["set_positioners"]
59
+
60
+ # Signal emitted to inform listeners about a position update of the first positioner
61
+ position_update = Signal(float)
62
+ # Signal emitted to inform listeners about (positioner, pos) updates
63
+ device_position_update = Signal(str, float)
64
+
65
+ def __init__(self, parent=None, **kwargs):
66
+ """Initialize the widget.
67
+
68
+ Args:
69
+ parent: The parent widget.
70
+ """
71
+ super().__init__(**kwargs)
72
+ QWidget.__init__(self, parent)
73
+
74
+ self.get_bec_shortcuts()
75
+
76
+ QGridLayout(self)
77
+ self.layout().setContentsMargins(0, 0, 0, 0)
78
+
79
+ self._device_widgets = {}
80
+ self._grid_ncols = 2
81
+
82
+ def minimumSizeHint(self):
83
+ return QSize(300, 30)
84
+
85
+ @Slot(str)
86
+ def set_positioners(self, device_names: str):
87
+ """Redraw grid with positioners from device_names string
88
+
89
+ Device names must be separated by space
90
+ """
91
+ devs = device_names.split()
92
+ for dev_name in devs:
93
+ if not self._check_device_is_valid(dev_name):
94
+ raise ValueError(f"{dev_name} is not a valid Positioner")
95
+ for i, existing_widget in enumerate(self._device_widgets.values()):
96
+ self.layout().removeWidget(existing_widget)
97
+ existing_widget.position_update.disconnect(self._on_position_update)
98
+ if i == 0:
99
+ existing_widget.position_update.disconnect(self.position_update)
100
+ for i, dev_name in enumerate(devs):
101
+ widget = self._device_widgets.get(dev_name)
102
+ if widget is None:
103
+ widget = PositionerGroupBox(self, dev_name)
104
+ self._device_widgets[dev_name] = widget
105
+ widget.position_update.connect(self._on_position_update)
106
+ if i == 0:
107
+ # only emit 'position_update' for the first positioner in grid
108
+ widget.position_update.connect(self.position_update)
109
+ self.layout().addWidget(widget, i // self._grid_ncols, i % self._grid_ncols)
110
+ to_remove = set(self._device_widgets) - set(devs)
111
+ for dev_name in to_remove:
112
+ self._device_widgets[dev_name].close()
113
+ del self._device_widgets[dev_name]
114
+
115
+ def _check_device_is_valid(self, device: str):
116
+ """Check if the device is a positioner
117
+
118
+ Args:
119
+ device (str): The device name
120
+ """
121
+ if device not in self.dev:
122
+ logger.info(f"Device {device} not found in the device list")
123
+ return False
124
+ if not isinstance(self.dev[device], Positioner):
125
+ logger.info(f"Device {device} is not a positioner")
126
+ return False
127
+ return True
128
+
129
+ def _on_position_update(self, pos: float):
130
+ widget = self.sender()
131
+ self.device_position_update.emit(widget.title(), pos)
132
+
133
+ @Property(str)
134
+ def devices_list(self):
135
+ """Device names string separated by space"""
136
+ return " ".join(self._device_widgets)
137
+
138
+ @devices_list.setter
139
+ def devices_list(self, device_names: str):
140
+ """Set devices list from device names string separated by space"""
141
+ devs = device_names.split()
142
+ for dev_name in devs:
143
+ if not self._check_device_is_valid(dev_name):
144
+ return
145
+ self.set_positioners(device_names)
146
+
147
+ @Property(int)
148
+ def grid_max_cols(self):
149
+ """Max number of columns for widgets grid"""
150
+ return self._grid_ncols
151
+
152
+ @grid_max_cols.setter
153
+ def grid_max_cols(self, ncols: int):
154
+ """Set max number of columns for widgets grid"""
155
+ self._grid_ncols = ncols
156
+ self.set_positioners(self.devices_list)
157
+
158
+
159
+ if __name__ == "__main__": # pragma: no cover
160
+ import sys
161
+
162
+ from qtpy.QtWidgets import QApplication # pylint: disable=ungrouped-imports
163
+
164
+ app = QApplication(sys.argv)
165
+ widget = PositionerGroup()
166
+ widget.grid_max_cols = 3
167
+ widget.set_positioners("samx samy samz")
168
+
169
+ widget.show()
170
+ sys.exit(app.exec_())
@@ -0,0 +1 @@
1
+ {'files': ['positioner_group.py']}
@@ -0,0 +1,57 @@
1
+ # Copyright (C) 2022 The Qt Company Ltd.
2
+ # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+
4
+ import os
5
+
6
+ from qtpy.QtDesigner import QDesignerCustomWidgetInterface
7
+
8
+ from bec_widgets.utils.bec_designer import designer_material_icon
9
+ from bec_widgets.widgets.positioner_group.positioner_group import PositionerGroup
10
+
11
+ DOM_XML = """
12
+ <ui language='c++'>
13
+ <widget class='PositionerGroup' name='positioner_group'>
14
+ </widget>
15
+ </ui>
16
+ """
17
+ MODULE_PATH = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
18
+
19
+
20
+ class PositionerGroupPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
21
+ def __init__(self):
22
+ super().__init__()
23
+ self._form_editor = None
24
+
25
+ def createWidget(self, parent):
26
+ t = PositionerGroup(parent)
27
+ return t
28
+
29
+ def domXml(self):
30
+ return DOM_XML
31
+
32
+ def group(self):
33
+ return "Device Control"
34
+
35
+ def icon(self):
36
+ return designer_material_icon(PositionerGroup.ICON_NAME)
37
+
38
+ def includeFile(self):
39
+ return "positioner_group"
40
+
41
+ def initialize(self, form_editor):
42
+ self._form_editor = form_editor
43
+
44
+ def isContainer(self):
45
+ return False
46
+
47
+ def isInitialized(self):
48
+ return self._form_editor is not None
49
+
50
+ def name(self):
51
+ return "PositionerGroup"
52
+
53
+ def toolTip(self):
54
+ return "Container Widget to control positioners in compact form, in a grid"
55
+
56
+ def whatsThis(self):
57
+ 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.positioner_group.positioner_group_plugin import PositionerGroupPlugin
10
+
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(PositionerGroupPlugin())
12
+
13
+
14
+ if __name__ == "__main__": # pragma: no cover
15
+ main()
@@ -1,4 +1,5 @@
1
1
  from collections import defaultdict
2
+ from types import SimpleNamespace
2
3
  from typing import Optional
3
4
 
4
5
  from bec_lib.endpoints import MessageEndpoints
@@ -7,11 +8,11 @@ from qtpy.QtCore import Property, Signal, Slot
7
8
  from qtpy.QtWidgets import (
8
9
  QApplication,
9
10
  QComboBox,
10
- QGroupBox,
11
11
  QHBoxLayout,
12
12
  QLabel,
13
13
  QPushButton,
14
14
  QSizePolicy,
15
+ QSpacerItem,
15
16
  QVBoxLayout,
16
17
  QWidget,
17
18
  )
@@ -19,6 +20,7 @@ from qtpy.QtWidgets import (
19
20
  from bec_widgets.qt_utils.error_popups import SafeSlot
20
21
  from bec_widgets.utils import ConnectionConfig
21
22
  from bec_widgets.utils.bec_widget import BECWidget
23
+ from bec_widgets.utils.colors import get_accent_colors
22
24
  from bec_widgets.widgets.scan_control.scan_group_box import ScanGroupBox
23
25
  from bec_widgets.widgets.stop_button.stop_button import StopButton
24
26
  from bec_widgets.widgets.toggle.toggle import ToggleSwitch
@@ -42,6 +44,7 @@ class ScanControl(BECWidget, QWidget):
42
44
 
43
45
  scan_started = Signal()
44
46
  scan_selected = Signal(str)
47
+ device_selected = Signal(str)
45
48
  scan_axis = Signal(str, float, float)
46
49
 
47
50
  def __init__(
@@ -61,6 +64,8 @@ class ScanControl(BECWidget, QWidget):
61
64
  super().__init__(client=client, gui_id=gui_id, config=config)
62
65
  QWidget.__init__(self, parent=parent)
63
66
 
67
+ self._hide_add_remove_buttons = False
68
+
64
69
  # Client from BEC + shortcuts to device manager and scans
65
70
  self.get_bec_shortcuts()
66
71
 
@@ -84,12 +89,54 @@ class ScanControl(BECWidget, QWidget):
84
89
  """
85
90
  Initializes the UI of the scan control widget. Create the top box for scan selection and populate scans to main combobox.
86
91
  """
87
-
88
- # Scan selection group box
89
- self.scan_selection_group = self.create_scan_selection_group()
92
+ palette = get_accent_colors()
93
+ if palette is None:
94
+ palette = SimpleNamespace(
95
+ default=QColor("blue"),
96
+ success=QColor("green"),
97
+ warning=QColor("orange"),
98
+ emergency=QColor("red"),
99
+ )
100
+ # Scan selection box
101
+ self.scan_selection_group = QWidget(self)
102
+ QVBoxLayout(self.scan_selection_group)
103
+ scan_selection_layout = QHBoxLayout()
104
+ self.comboBox_scan_selection_label = QLabel("Scan:", self.scan_selection_group)
105
+ self.comboBox_scan_selection = QComboBox(self.scan_selection_group)
106
+ scan_selection_layout.addWidget(self.comboBox_scan_selection_label, 0)
107
+ scan_selection_layout.addWidget(self.comboBox_scan_selection, 1)
108
+ self.scan_selection_group.layout().addLayout(scan_selection_layout)
109
+
110
+ # Label to reload the last scan parameters within scan selection group box
111
+ self.toggle_layout = QHBoxLayout()
112
+ self.toggle_layout.addSpacerItem(
113
+ QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed)
114
+ )
115
+ self.last_scan_label = QLabel("Restore last scan parameters", self.scan_selection_group)
116
+ self.toggle = ToggleSwitch(parent=self.scan_selection_group, checked=False)
117
+ self.toggle.enabled.connect(self.request_last_executed_scan_parameters)
118
+ self.toggle_layout.addWidget(self.last_scan_label)
119
+ self.toggle_layout.addWidget(self.toggle)
120
+ self.scan_selection_group.layout().addLayout(self.toggle_layout)
90
121
  self.scan_selection_group.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
91
122
  self.layout.addWidget(self.scan_selection_group)
92
123
 
124
+ # Scan control (Run/Stop) buttons
125
+ self.scan_control_group = QWidget(self)
126
+ self.scan_control_group.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
127
+ self.button_layout = QHBoxLayout(self.scan_control_group)
128
+ self.button_run_scan = QPushButton("Start", self.scan_control_group)
129
+ self.button_run_scan.setStyleSheet(
130
+ f"background-color: {palette.success.name()}; color: white"
131
+ )
132
+ self.button_stop_scan = StopButton(parent=self.scan_control_group)
133
+ self.button_stop_scan.setStyleSheet(
134
+ f"background-color: {palette.emergency.name()}; color: white"
135
+ )
136
+ self.button_layout.addWidget(self.button_run_scan)
137
+ self.button_layout.addWidget(self.button_stop_scan)
138
+ self.layout.addWidget(self.scan_control_group)
139
+
93
140
  # Default scan from config
94
141
  if self.config.default_scan is not None:
95
142
  self.comboBox_scan_selection.setCurrentText(self.config.default_scan)
@@ -99,67 +146,11 @@ class ScanControl(BECWidget, QWidget):
99
146
  self.comboBox_scan_selection.currentIndexChanged.connect(self.on_scan_selection_changed)
100
147
  self.button_run_scan.clicked.connect(self.run_scan)
101
148
 
102
- # Add bundle button
103
- self.button_add_bundle = QPushButton("Add Bundle")
104
- self.button_add_bundle.setVisible(False)
105
- # Remove bundle button
106
- self.button_remove_bundle = QPushButton("Remove Bundle")
107
- self.button_remove_bundle.setVisible(False)
108
-
109
- bundle_layout = QHBoxLayout()
110
- bundle_layout.addWidget(self.button_add_bundle)
111
- bundle_layout.addWidget(self.button_remove_bundle)
112
- self.layout.addLayout(bundle_layout)
113
-
114
- self.button_add_bundle.clicked.connect(self.add_arg_bundle)
115
- self.button_remove_bundle.clicked.connect(self.remove_arg_bundle)
116
-
117
149
  self.scan_selected.connect(self.scan_select)
118
150
 
119
151
  # Initialize scan selection
120
152
  self.populate_scans()
121
153
 
122
- def create_scan_selection_group(self) -> QGroupBox:
123
- """
124
- Creates the scan selection group box with combobox to select the scan and start/stop button.
125
-
126
- Returns:
127
- QGroupBox: Group box containing the scan selection widgets.
128
- """
129
-
130
- scan_selection_group = QGroupBox("Scan Selection", self)
131
- self.scan_selection_layout = QVBoxLayout(scan_selection_group)
132
- self.comboBox_scan_selection = QComboBox(scan_selection_group)
133
-
134
- # Buttons
135
- self.button_layout = QHBoxLayout()
136
- ## Run button
137
- self.button_run_scan = QPushButton("Start", scan_selection_group)
138
- self.button_run_scan.setStyleSheet("background-color: #559900; color: white")
139
- ## Stop button
140
- self.button_stop_scan = StopButton(parent=scan_selection_group)
141
- ## Add buttons to layout
142
- self.button_layout.addWidget(self.button_run_scan)
143
- self.button_layout.addWidget(self.button_stop_scan)
144
-
145
- # Label to reload the last scan parameters
146
- self.toggle_layout = QHBoxLayout()
147
- ## Label
148
- self.last_scan_label = QLabel("Restore last scan parameters", scan_selection_group)
149
- ## Switch toggle button
150
- self.toggle = ToggleSwitch(parent=scan_selection_group, checked=False)
151
- self.toggle.enabled.connect(self.request_last_executed_scan_parameters)
152
- ## Add label and switch to layout
153
- self.toggle_layout.addWidget(self.last_scan_label)
154
- self.toggle_layout.addWidget(self.toggle)
155
-
156
- # Add widgets to layout
157
- self.scan_selection_layout.addWidget(self.comboBox_scan_selection)
158
- self.scan_selection_layout.addLayout(self.button_layout)
159
- self.scan_selection_layout.addLayout(self.toggle_layout)
160
-
161
- return scan_selection_group
162
-
163
154
  def populate_scans(self):
164
155
  """Populates the scan selection combo box with available scans from BEC session."""
165
156
  self.available_scans = self.client.connector.get(
@@ -282,29 +273,6 @@ class ScanControl(BECWidget, QWidget):
282
273
  for box in self.kwarg_boxes:
283
274
  box.setVisible(not hide)
284
275
 
285
- @Property(bool)
286
- def hide_scan_remember_toggle(self):
287
- """Property to hide the scan remember toggle."""
288
- return not self.toggle.isVisible()
289
-
290
- @hide_scan_remember_toggle.setter
291
- def hide_scan_remember_toggle(self, hide: bool):
292
- """Setter for the hide_scan_remember_toggle property.
293
-
294
- Args:
295
- hide(bool): Hide or show the scan remember toggle.
296
- """
297
- self.show_scan_remember_toggle(not hide)
298
-
299
- @Slot(bool)
300
- def show_scan_remember_toggle(self, show: bool):
301
- """Shows or hides the scan control buttons."""
302
- self.toggle.setVisible(show)
303
- self.last_scan_label.setVisible(show)
304
-
305
- show_group = show or self.button_run_scan.isVisible()
306
- self.scan_selection_group.setVisible(show_group)
307
-
308
276
  @Property(bool)
309
277
  def hide_scan_control_buttons(self):
310
278
  """Property to hide the scan control buttons."""
@@ -322,11 +290,7 @@ class ScanControl(BECWidget, QWidget):
322
290
  @Slot(bool)
323
291
  def show_scan_control_buttons(self, show: bool):
324
292
  """Shows or hides the scan control buttons."""
325
- self.button_run_scan.setVisible(show)
326
- self.button_stop_scan.setVisible(show)
327
-
328
- show_group = show or self.button_run_scan.isVisible()
329
- self.scan_selection_group.setVisible(show_group)
293
+ self.scan_control_group.setVisible(show)
330
294
 
331
295
  @Property(bool)
332
296
  def hide_scan_selection_combobox(self):
@@ -345,10 +309,7 @@ class ScanControl(BECWidget, QWidget):
345
309
  @Slot(bool)
346
310
  def show_scan_selection_combobox(self, show: bool):
347
311
  """Shows or hides the scan selection combobox."""
348
- self.comboBox_scan_selection.setVisible(show)
349
-
350
- show_group = show or self.button_run_scan.isVisible()
351
- self.scan_selection_group.setVisible(show_group)
312
+ self.scan_selection_group.setVisible(show)
352
313
 
353
314
  @Slot(str)
354
315
  def scan_select(self, scan_name: str):
@@ -365,11 +326,7 @@ class ScanControl(BECWidget, QWidget):
365
326
  self.arg_group = gui_config.get("arg_group", None)
366
327
  self.kwarg_groups = gui_config.get("kwarg_groups", None)
367
328
 
368
- show_bundle_buttons = bool(self.arg_group["arg_inputs"])
369
-
370
- self._show_bundle_buttons(show_bundle_buttons)
371
-
372
- if show_bundle_buttons:
329
+ if bool(self.arg_group["arg_inputs"]):
373
330
  self.add_arg_group(self.arg_group)
374
331
  if len(self.kwarg_groups) > 0:
375
332
  self.add_kwargs_boxes(self.kwarg_groups)
@@ -377,28 +334,21 @@ class ScanControl(BECWidget, QWidget):
377
334
  self.update()
378
335
  self.adjustSize()
379
336
 
380
- def _show_bundle_buttons(self, show: bool):
381
- """Shows or hides the bundle buttons based on the show argument.
382
-
383
- Args:
384
- show(bool): Show or hide the bundle buttons.
385
- """
386
- self.button_add_bundle.setVisible(show)
387
- self.button_remove_bundle.setVisible(show)
388
-
389
337
  @Property(bool)
390
- def hide_bundle_buttons(self):
391
- """Property to hide the bundle buttons."""
392
- return not self.button_add_bundle.isVisible()
338
+ def hide_add_remove_buttons(self):
339
+ """Property to hide the add_remove buttons."""
340
+ return self._hide_add_remove_buttons
393
341
 
394
- @hide_bundle_buttons.setter
395
- def hide_bundle_buttons(self, hide: bool):
396
- """Setter for the hide_bundle_buttons property.
342
+ @hide_add_remove_buttons.setter
343
+ def hide_add_remove_buttons(self, hide: bool):
344
+ """Setter for the hide_add_remove_buttons property.
397
345
 
398
346
  Args:
399
- hide(bool): Hide or show the bundle buttons.
347
+ hide(bool): Hide or show the add_remove buttons.
400
348
  """
401
- self._show_bundle_buttons(not hide)
349
+ self._hide_add_remove_buttons = hide
350
+ if self.arg_box is not None:
351
+ self.arg_box.hide_add_remove_buttons = hide
402
352
 
403
353
  def add_kwargs_boxes(self, groups: list):
404
354
  """
@@ -420,18 +370,20 @@ class ScanControl(BECWidget, QWidget):
420
370
  Args:
421
371
  """
422
372
  self.arg_box = ScanGroupBox(box_type="args", config=group)
373
+ self.arg_box.device_selected.connect(self.emit_device_selected)
423
374
  self.arg_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
375
+ self.arg_box.hide_add_remove_buttons = self._hide_add_remove_buttons
424
376
  self.layout.addWidget(self.arg_box)
425
377
 
426
- @Slot()
427
- def add_arg_bundle(self):
428
- """Adds a new argument bundle to the scan control layout."""
429
- self.arg_box.add_widget_bundle()
378
+ @Slot(str)
379
+ def emit_device_selected(self, dev_names):
380
+ """
381
+ Emit the signal to inform about selected device(s)
430
382
 
431
- @Slot()
432
- def remove_arg_bundle(self):
433
- """Removes the last argument bundle from the scan control layout."""
434
- self.arg_box.remove_widget_bundle()
383
+ "dev_names" is a string separated by space, in case of multiple devices
384
+ """
385
+ self._selected_devices = dev_names
386
+ self.device_selected.emit(dev_names)
435
387
 
436
388
  def reset_layout(self):
437
389
  """Clears the scan control layout from GuiGroups and ArgGroups boxes."""