bec-widgets 1.0.2__py3-none-any.whl → 1.2.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 (36) hide show
  1. CHANGELOG.md +30 -35
  2. PKG-INFO +1 -1
  3. bec_widgets/cli/client.py +56 -0
  4. bec_widgets/tests/__init__.py +0 -0
  5. bec_widgets/tests/utils.py +226 -0
  6. bec_widgets/utils/colors.py +110 -27
  7. bec_widgets/utils/filter_io.py +156 -0
  8. bec_widgets/utils/widget_io.py +12 -9
  9. bec_widgets/widgets/base_classes/device_input_base.py +331 -62
  10. bec_widgets/widgets/base_classes/device_signal_input_base.py +280 -0
  11. bec_widgets/widgets/bec_status_box/status_item.py +1 -0
  12. bec_widgets/widgets/dap_combo_box/dap_combo_box_plugin.py +1 -1
  13. bec_widgets/widgets/device_combobox/device_combo_box_plugin.py +1 -1
  14. bec_widgets/widgets/device_combobox/device_combobox.py +118 -41
  15. bec_widgets/widgets/device_line_edit/device_line_edit.py +122 -59
  16. bec_widgets/widgets/device_line_edit/device_line_edit_plugin.py +1 -1
  17. bec_widgets/widgets/image/image_widget.py +7 -1
  18. bec_widgets/widgets/motor_map/motor_map_widget.py +4 -2
  19. bec_widgets/widgets/positioner_box/positioner_box.py +4 -1
  20. bec_widgets/widgets/scan_control/scan_group_box.py +3 -1
  21. bec_widgets/widgets/signal_combobox/__init__.py +0 -0
  22. bec_widgets/widgets/signal_combobox/register_signal_combobox.py +15 -0
  23. bec_widgets/widgets/signal_combobox/signal_combobox.py +115 -0
  24. bec_widgets/widgets/signal_combobox/signal_combobox.pyproject +1 -0
  25. bec_widgets/widgets/signal_combobox/signal_combobox_plugin.py +54 -0
  26. bec_widgets/widgets/signal_line_edit/__init__.py +0 -0
  27. bec_widgets/widgets/signal_line_edit/register_signal_line_edit.py +15 -0
  28. bec_widgets/widgets/signal_line_edit/signal_line_edit.py +140 -0
  29. bec_widgets/widgets/signal_line_edit/signal_line_edit.pyproject +1 -0
  30. bec_widgets/widgets/signal_line_edit/signal_line_edit_plugin.py +54 -0
  31. {bec_widgets-1.0.2.dist-info → bec_widgets-1.2.0.dist-info}/METADATA +1 -1
  32. {bec_widgets-1.0.2.dist-info → bec_widgets-1.2.0.dist-info}/RECORD +36 -22
  33. pyproject.toml +1 -1
  34. {bec_widgets-1.0.2.dist-info → bec_widgets-1.2.0.dist-info}/WHEEL +0 -0
  35. {bec_widgets-1.0.2.dist-info → bec_widgets-1.2.0.dist-info}/entry_points.txt +0 -0
  36. {bec_widgets-1.0.2.dist-info → bec_widgets-1.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,156 @@
1
+ """Module for handling filter I/O operations in BEC Widgets for input fields.
2
+ These operations include filtering device/signal names and/or device types.
3
+ """
4
+
5
+ from abc import ABC, abstractmethod
6
+
7
+ from bec_lib.logger import bec_logger
8
+ from qtpy.QtCore import QStringListModel
9
+ from qtpy.QtWidgets import QComboBox, QCompleter, QLineEdit
10
+
11
+ logger = bec_logger.logger
12
+
13
+
14
+ class WidgetFilterHandler(ABC):
15
+ """Abstract base class for widget filter handlers"""
16
+
17
+ @abstractmethod
18
+ def set_selection(self, widget, selection: list) -> None:
19
+ """Set the filtered_selection for the widget
20
+
21
+ Args:
22
+ selection (list): Filtered selection of items
23
+ """
24
+
25
+ @abstractmethod
26
+ def check_input(self, widget, text: str) -> bool:
27
+ """Check if the input text is in the filtered selection
28
+
29
+ Args:
30
+ widget: Widget instance
31
+ text (str): Input text
32
+
33
+ Returns:
34
+ bool: True if the input text is in the filtered selection
35
+ """
36
+
37
+
38
+ class LineEditFilterHandler(WidgetFilterHandler):
39
+ """Handler for QLineEdit widget"""
40
+
41
+ def set_selection(self, widget: QLineEdit, selection: list) -> None:
42
+ """Set the selection for the widget to the completer model
43
+
44
+ Args:
45
+ widget (QLineEdit): The QLineEdit widget
46
+ selection (list): Filtered selection of items
47
+ """
48
+ if not isinstance(widget.completer, QCompleter):
49
+ completer = QCompleter(widget)
50
+ widget.setCompleter(completer)
51
+ widget.completer.setModel(QStringListModel(selection, widget))
52
+
53
+ def check_input(self, widget: QLineEdit, text: str) -> bool:
54
+ """Check if the input text is in the filtered selection
55
+
56
+ Args:
57
+ widget (QLineEdit): The QLineEdit widget
58
+ text (str): Input text
59
+
60
+ Returns:
61
+ bool: True if the input text is in the filtered selection
62
+ """
63
+ model = widget.completer.model()
64
+ model_data = [model.data(model.index(i)) for i in range(model.rowCount())]
65
+ return text in model_data
66
+
67
+
68
+ class ComboBoxFilterHandler(WidgetFilterHandler):
69
+ """Handler for QComboBox widget"""
70
+
71
+ def set_selection(self, widget: QComboBox, selection: list) -> None:
72
+ """Set the selection for the widget to the completer model
73
+
74
+ Args:
75
+ widget (QComboBox): The QComboBox widget
76
+ selection (list): Filtered selection of items
77
+ """
78
+ widget.clear()
79
+ widget.addItems(selection)
80
+
81
+ def check_input(self, widget: QComboBox, text: str) -> bool:
82
+ """Check if the input text is in the filtered selection
83
+
84
+ Args:
85
+ widget (QComboBox): The QComboBox widget
86
+ text (str): Input text
87
+
88
+ Returns:
89
+ bool: True if the input text is in the filtered selection
90
+ """
91
+ return text in [widget.itemText(i) for i in range(widget.count())]
92
+
93
+
94
+ class FilterIO:
95
+ """Public interface to set filters for input widgets.
96
+ It supports the list of widgets stored in class attribute _handlers.
97
+ """
98
+
99
+ _handlers = {QLineEdit: LineEditFilterHandler, QComboBox: ComboBoxFilterHandler}
100
+
101
+ @staticmethod
102
+ def set_selection(widget, selection: list, ignore_errors=True):
103
+ """
104
+ Retrieve value from the widget instance.
105
+
106
+ Args:
107
+ widget: Widget instance.
108
+ selection(list): List of filtered selection items.
109
+ ignore_errors(bool, optional): Whether to ignore if no handler is found.
110
+ """
111
+ handler_class = FilterIO._find_handler(widget)
112
+ if handler_class:
113
+ return handler_class().set_selection(widget=widget, selection=selection)
114
+ if not ignore_errors:
115
+ raise ValueError(
116
+ f"No matching handler for widget type: {type(widget)} in handler list {FilterIO._handlers}"
117
+ )
118
+ return None
119
+
120
+ @staticmethod
121
+ def check_input(widget, text: str, ignore_errors=True):
122
+ """
123
+ Check if the input text is in the filtered selection.
124
+
125
+ Args:
126
+ widget: Widget instance.
127
+ text(str): Input text.
128
+ ignore_errors(bool, optional): Whether to ignore if no handler is found.
129
+
130
+ Returns:
131
+ bool: True if the input text is in the filtered selection.
132
+ """
133
+ handler_class = FilterIO._find_handler(widget)
134
+ if handler_class:
135
+ return handler_class().check_input(widget=widget, text=text)
136
+ if not ignore_errors:
137
+ raise ValueError(
138
+ f"No matching handler for widget type: {type(widget)} in handler list {FilterIO._handlers}"
139
+ )
140
+ return None
141
+
142
+ @staticmethod
143
+ def _find_handler(widget):
144
+ """
145
+ Find the appropriate handler for the widget by checking its base classes.
146
+
147
+ Args:
148
+ widget: Widget instance.
149
+
150
+ Returns:
151
+ handler_class: The handler class if found, otherwise None.
152
+ """
153
+ for base in type(widget).__mro__:
154
+ if base in FilterIO._handlers:
155
+ return FilterIO._handlers[base]
156
+ return None
@@ -1,5 +1,6 @@
1
1
  # pylint: disable=no-name-in-module
2
2
  from abc import ABC, abstractmethod
3
+ from typing import Literal
3
4
 
4
5
  from qtpy.QtWidgets import (
5
6
  QApplication,
@@ -20,7 +21,7 @@ class WidgetHandler(ABC):
20
21
  """Abstract base class for all widget handlers."""
21
22
 
22
23
  @abstractmethod
23
- def get_value(self, widget: QWidget):
24
+ def get_value(self, widget: QWidget, **kwargs):
24
25
  """Retrieve value from the widget instance."""
25
26
 
26
27
  @abstractmethod
@@ -31,7 +32,7 @@ class WidgetHandler(ABC):
31
32
  class LineEditHandler(WidgetHandler):
32
33
  """Handler for QLineEdit widgets."""
33
34
 
34
- def get_value(self, widget: QLineEdit) -> str:
35
+ def get_value(self, widget: QLineEdit, **kwargs) -> str:
35
36
  return widget.text()
36
37
 
37
38
  def set_value(self, widget: QLineEdit, value: str) -> None:
@@ -41,7 +42,9 @@ class LineEditHandler(WidgetHandler):
41
42
  class ComboBoxHandler(WidgetHandler):
42
43
  """Handler for QComboBox widgets."""
43
44
 
44
- def get_value(self, widget: QComboBox) -> int:
45
+ def get_value(self, widget: QComboBox, as_string: bool = False, **kwargs) -> int | str:
46
+ if as_string is True:
47
+ return widget.currentText()
45
48
  return widget.currentIndex()
46
49
 
47
50
  def set_value(self, widget: QComboBox, value: int | str) -> None:
@@ -54,7 +57,7 @@ class ComboBoxHandler(WidgetHandler):
54
57
  class TableWidgetHandler(WidgetHandler):
55
58
  """Handler for QTableWidget widgets."""
56
59
 
57
- def get_value(self, widget: QTableWidget) -> list:
60
+ def get_value(self, widget: QTableWidget, **kwargs) -> list:
58
61
  return [
59
62
  [
60
63
  widget.item(row, col).text() if widget.item(row, col) else ""
@@ -73,7 +76,7 @@ class TableWidgetHandler(WidgetHandler):
73
76
  class SpinBoxHandler(WidgetHandler):
74
77
  """Handler for QSpinBox and QDoubleSpinBox widgets."""
75
78
 
76
- def get_value(self, widget):
79
+ def get_value(self, widget, **kwargs):
77
80
  return widget.value()
78
81
 
79
82
  def set_value(self, widget, value):
@@ -83,7 +86,7 @@ class SpinBoxHandler(WidgetHandler):
83
86
  class CheckBoxHandler(WidgetHandler):
84
87
  """Handler for QCheckBox widgets."""
85
88
 
86
- def get_value(self, widget):
89
+ def get_value(self, widget, **kwargs):
87
90
  return widget.isChecked()
88
91
 
89
92
  def set_value(self, widget, value):
@@ -93,7 +96,7 @@ class CheckBoxHandler(WidgetHandler):
93
96
  class LabelHandler(WidgetHandler):
94
97
  """Handler for QLabel widgets."""
95
98
 
96
- def get_value(self, widget):
99
+ def get_value(self, widget, **kwargs):
97
100
  return widget.text()
98
101
 
99
102
  def set_value(self, widget, value):
@@ -114,7 +117,7 @@ class WidgetIO:
114
117
  }
115
118
 
116
119
  @staticmethod
117
- def get_value(widget, ignore_errors=False):
120
+ def get_value(widget, ignore_errors=False, **kwargs):
118
121
  """
119
122
  Retrieve value from the widget instance.
120
123
 
@@ -124,7 +127,7 @@ class WidgetIO:
124
127
  """
125
128
  handler_class = WidgetIO._find_handler(widget)
126
129
  if handler_class:
127
- return handler_class().get_value(widget) # Instantiate the handler
130
+ return handler_class().get_value(widget, **kwargs) # Instantiate the handler
128
131
  if not ignore_errors:
129
132
  raise ValueError(f"No handler for widget type: {type(widget)}")
130
133
  return None