bec-widgets 0.79.3__py3-none-any.whl → 0.82.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 (89) hide show
  1. .gitlab-ci.yml +0 -1
  2. .pylintrc +1 -1
  3. CHANGELOG.md +52 -62
  4. PKG-INFO +1 -4
  5. README.md +2 -2
  6. bec_widgets/cli/client.py +3 -2
  7. bec_widgets/cli/generate_cli.py +11 -10
  8. bec_widgets/cli/rpc_wigdet_handler.py +1 -1
  9. bec_widgets/examples/__init__.py +0 -9
  10. bec_widgets/utils/bec_connector.py +2 -1
  11. bec_widgets/utils/bec_dispatcher.py +3 -3
  12. bec_widgets/utils/bec_widget.py +2 -0
  13. bec_widgets/utils/entry_validator.py +1 -1
  14. bec_widgets/utils/plugin_utils.py +80 -10
  15. bec_widgets/utils/ui_loader.py +85 -26
  16. bec_widgets/widgets/{device_inputs → base_classes}/device_input_base.py +2 -0
  17. bec_widgets/widgets/color_button/color_button.py +36 -0
  18. bec_widgets/widgets/{buttons/color_button → color_button}/color_button_plugin.py +1 -1
  19. bec_widgets/widgets/{buttons/color_button → color_button}/register_color_button.py +1 -1
  20. bec_widgets/widgets/device_combobox/assets/device_combobox_icon.png +0 -0
  21. bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/device_combobox.py +2 -2
  22. bec_widgets/widgets/device_combobox/device_combobox.pyproject +3 -0
  23. bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/device_combobox_plugin.py +6 -3
  24. bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/register_device_combobox.py +1 -3
  25. bec_widgets/widgets/device_line_edit/assets/line_edit_icon.png +0 -0
  26. bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/device_line_edit.py +2 -2
  27. bec_widgets/widgets/device_line_edit/device_line_edit.pyproject +3 -0
  28. bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/device_line_edit_plugin.py +6 -3
  29. bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/register_device_line_edit.py +1 -3
  30. bec_widgets/widgets/figure/plots/waveform/waveform.py +8 -2
  31. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_settings.py +1 -1
  32. bec_widgets/widgets/motor_map/motor_map_dialog/motor_map_toolbar.py +1 -1
  33. bec_widgets/widgets/motor_map/motor_map_widget.py +0 -12
  34. bec_widgets/widgets/scan_control/scan_control.py +1 -1
  35. bec_widgets/widgets/scan_control/scan_group_box.py +1 -1
  36. bec_widgets/widgets/stop_button/assets/stop.png +0 -0
  37. bec_widgets/widgets/stop_button/register_stop_button.py +15 -0
  38. bec_widgets/widgets/{buttons/stop_button → stop_button}/stop_button.py +5 -12
  39. bec_widgets/widgets/stop_button/stop_button.pyproject +1 -0
  40. bec_widgets/widgets/stop_button/stop_button_plugin.py +57 -0
  41. bec_widgets/widgets/toggle/register_toggle_switch.py +15 -0
  42. bec_widgets/widgets/toggle/toggle.py +149 -0
  43. bec_widgets/widgets/toggle/toggle_switch.pyproject +1 -0
  44. bec_widgets/widgets/toggle/toggle_switch_plugin.py +54 -0
  45. {bec_widgets-0.79.3.dist-info → bec_widgets-0.82.0.dist-info}/METADATA +1 -4
  46. {bec_widgets-0.79.3.dist-info → bec_widgets-0.82.0.dist-info}/RECORD +66 -74
  47. docs/introduction/introduction.md +1 -1
  48. docs/user/getting_started/installation.md +2 -2
  49. pyproject.toml +1 -2
  50. tests/unit_tests/test_device_input_base.py +1 -1
  51. tests/unit_tests/test_device_input_widgets.py +2 -2
  52. tests/unit_tests/test_generate_cli_client.py +41 -17
  53. tests/unit_tests/test_plugin_utils.py +2 -3
  54. tests/unit_tests/test_stop_button.py +5 -2
  55. tests/unit_tests/test_toggle.py +38 -0
  56. bec_widgets/examples/motor_movement/__init__.py +0 -9
  57. bec_widgets/examples/motor_movement/motor_control_compilations.py +0 -250
  58. bec_widgets/examples/motor_movement/motor_controller.ui +0 -926
  59. bec_widgets/widgets/buttons/__init__.py +0 -1
  60. bec_widgets/widgets/buttons/color_button/color_button.py +0 -17
  61. bec_widgets/widgets/device_inputs/__init__.py +0 -2
  62. bec_widgets/widgets/device_inputs/device_combobox/device_combobox.pyproject +0 -4
  63. bec_widgets/widgets/device_inputs/device_combobox/launch_device_combobox.py +0 -11
  64. bec_widgets/widgets/device_inputs/device_line_edit/device_line_edit.pyproject +0 -4
  65. bec_widgets/widgets/device_inputs/device_line_edit/launch_device_line_edit.py +0 -11
  66. bec_widgets/widgets/motor_control/motor_control.py +0 -252
  67. bec_widgets/widgets/motor_control/motor_table/motor_table.py +0 -484
  68. bec_widgets/widgets/motor_control/motor_table/motor_table.ui +0 -113
  69. bec_widgets/widgets/motor_control/movement_absolute/__init__.py +0 -0
  70. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.py +0 -159
  71. bec_widgets/widgets/motor_control/movement_absolute/movement_absolute.ui +0 -149
  72. bec_widgets/widgets/motor_control/movement_relative/__init__.py +0 -0
  73. bec_widgets/widgets/motor_control/movement_relative/movement_relative.py +0 -230
  74. bec_widgets/widgets/motor_control/movement_relative/movement_relative.ui +0 -298
  75. bec_widgets/widgets/motor_control/selection/__init__.py +0 -0
  76. bec_widgets/widgets/motor_control/selection/selection.py +0 -110
  77. bec_widgets/widgets/motor_control/selection/selection.ui +0 -69
  78. tests/unit_tests/test_motor_control.py +0 -588
  79. /bec_widgets/widgets/{buttons/color_button → base_classes}/__init__.py +0 -0
  80. /bec_widgets/widgets/{buttons/stop_button → color_button}/__init__.py +0 -0
  81. /bec_widgets/widgets/{buttons/color_button → color_button}/assets/color_button.png +0 -0
  82. /bec_widgets/widgets/{buttons/color_button → color_button}/color_button.pyproject +0 -0
  83. /bec_widgets/widgets/{device_inputs/device_combobox → device_combobox}/__init__.py +0 -0
  84. /bec_widgets/widgets/{device_inputs/device_line_edit → device_line_edit}/__init__.py +0 -0
  85. /bec_widgets/widgets/{motor_control → stop_button}/__init__.py +0 -0
  86. /bec_widgets/widgets/{motor_control/motor_table → toggle}/__init__.py +0 -0
  87. {bec_widgets-0.79.3.dist-info → bec_widgets-0.82.0.dist-info}/WHEEL +0 -0
  88. {bec_widgets-0.79.3.dist-info → bec_widgets-0.82.0.dist-info}/entry_points.txt +0 -0
  89. {bec_widgets-0.79.3.dist-info → bec_widgets-0.82.0.dist-info}/licenses/LICENSE +0 -0
@@ -2,10 +2,10 @@ from typing import TYPE_CHECKING
2
2
 
3
3
  from qtpy.QtWidgets import QComboBox
4
4
 
5
- from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputBase, DeviceInputConfig
5
+ from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase, DeviceInputConfig
6
6
 
7
7
  if TYPE_CHECKING:
8
- from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputConfig
8
+ from bec_widgets.widgets.base_classes.device_input_base import DeviceInputConfig
9
9
 
10
10
 
11
11
  class DeviceComboBox(DeviceInputBase, QComboBox):
@@ -0,0 +1,3 @@
1
+ {
2
+ "files": ["device_combobox.py"]
3
+ }
@@ -1,10 +1,11 @@
1
1
  # Copyright (C) 2022 The Qt Company Ltd.
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+ import os
3
4
 
4
5
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
5
6
  from qtpy.QtGui import QIcon
6
7
 
7
- from bec_widgets.widgets.device_inputs import DeviceComboBox
8
+ from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
8
9
 
9
10
  DOM_XML = """
10
11
  <ui language='c++'>
@@ -27,10 +28,12 @@ class DeviceComboBoxPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
27
28
  return DOM_XML
28
29
 
29
30
  def group(self):
30
- return ""
31
+ return "BEC Device Inputs"
31
32
 
32
33
  def icon(self):
33
- return QIcon()
34
+ current_path = os.path.dirname(__file__)
35
+ icon_path = os.path.join(current_path, "assets", "device_combobox_icon.png")
36
+ return QIcon(icon_path)
34
37
 
35
38
  def includeFile(self):
36
39
  return "device_combobox"
@@ -6,9 +6,7 @@ def main(): # pragma: no cover
6
6
  return
7
7
  from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
8
 
9
- from bec_widgets.widgets.device_inputs.device_combobox.device_combobox_plugin import (
10
- DeviceComboBoxPlugin,
11
- )
9
+ from bec_widgets.widgets.device_combobox.device_combobox_plugin import DeviceComboBoxPlugin
12
10
 
13
11
  QPyDesignerCustomWidgetCollection.addCustomWidget(DeviceComboBoxPlugin())
14
12
 
@@ -3,10 +3,10 @@ from typing import TYPE_CHECKING
3
3
  from qtpy.QtCore import QSize
4
4
  from qtpy.QtWidgets import QCompleter, QLineEdit, QSizePolicy
5
5
 
6
- from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputBase, DeviceInputConfig
6
+ from bec_widgets.widgets.base_classes.device_input_base import DeviceInputBase, DeviceInputConfig
7
7
 
8
8
  if TYPE_CHECKING:
9
- from bec_widgets.widgets.device_inputs.device_input_base import DeviceInputConfig
9
+ from bec_widgets.widgets.base_classes.device_input_base import DeviceInputConfig
10
10
 
11
11
 
12
12
  class DeviceLineEdit(DeviceInputBase, QLineEdit):
@@ -0,0 +1,3 @@
1
+ {
2
+ "files": ["device_line_edit.py"]
3
+ }
@@ -1,10 +1,11 @@
1
1
  # Copyright (C) 2022 The Qt Company Ltd.
2
2
  # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+ import os
3
4
 
4
5
  from qtpy.QtDesigner import QDesignerCustomWidgetInterface
5
6
  from qtpy.QtGui import QIcon
6
7
 
7
- from bec_widgets.widgets.device_inputs import DeviceLineEdit
8
+ from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
8
9
 
9
10
  DOM_XML = """
10
11
  <ui language='c++'>
@@ -27,10 +28,12 @@ class DeviceLineEditPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
27
28
  return DOM_XML
28
29
 
29
30
  def group(self):
30
- return ""
31
+ return "BEC Device Inputs"
31
32
 
32
33
  def icon(self):
33
- return QIcon()
34
+ current_path = os.path.dirname(__file__)
35
+ icon_path = os.path.join(current_path, "assets", "line_edit_icon.png")
36
+ return QIcon(icon_path)
34
37
 
35
38
  def includeFile(self):
36
39
  return "device_line_edit"
@@ -6,9 +6,7 @@ def main(): # pragma: no cover
6
6
  return
7
7
  from PySide6.QtDesigner import QPyDesignerCustomWidgetCollection
8
8
 
9
- from bec_widgets.widgets.device_inputs.device_line_edit.device_line_edit_plugin import (
10
- DeviceLineEditPlugin,
11
- )
9
+ from bec_widgets.widgets.device_line_edit.device_line_edit_plugin import DeviceLineEditPlugin
12
10
 
13
11
  QPyDesignerCustomWidgetCollection.addCustomWidget(DeviceLineEditPlugin())
14
12
 
@@ -221,6 +221,7 @@ class BECWaveform(BECPlotBase):
221
221
  label: str | None = None,
222
222
  validate: bool = True,
223
223
  dap: str | None = None, # TODO add dap custom curve wrapper
224
+ **kwargs,
224
225
  ) -> BECCurve:
225
226
  """
226
227
  Plot a curve to the plot widget.
@@ -244,7 +245,7 @@ class BECWaveform(BECPlotBase):
244
245
  """
245
246
 
246
247
  if x is not None and y is not None:
247
- return self.add_curve_custom(x=x, y=y, label=label, color=color)
248
+ return self.add_curve_custom(x=x, y=y, label=label, color=color, **kwargs)
248
249
  else:
249
250
  if dap:
250
251
  self.add_dap(x_name=x_name, y_name=y_name, dap=dap)
@@ -259,6 +260,7 @@ class BECWaveform(BECPlotBase):
259
260
  color_map_z=color_map_z,
260
261
  label=label,
261
262
  validate_bec=validate,
263
+ **kwargs,
262
264
  )
263
265
 
264
266
  def add_curve_custom(
@@ -754,7 +756,11 @@ class BECWaveform(BECPlotBase):
754
756
  self.update_dap, MessageEndpoints.dap_response(self.scan_id)
755
757
  )
756
758
  if scan_index is not None:
757
- self.scan_id = self.queue.scan_storage.storage[scan_index].scan_id
759
+ try:
760
+ self.scan_id = self.queue.scan_storage.storage[scan_index].scan_id
761
+ except IndexError:
762
+ print(f"Scan index {scan_index} out of range.")
763
+ return
758
764
  elif scan_id is not None:
759
765
  self.scan_id = scan_id
760
766
 
@@ -36,7 +36,7 @@ class MotorMapSettings(QWidget):
36
36
  precision = WidgetIO.get_value(self.ui.precision)
37
37
  scatter_size = WidgetIO.get_value(self.ui.scatter_size)
38
38
  background_intensity = int(WidgetIO.get_value(self.ui.background_value) * 0.01 * 255)
39
- color = self.ui.color.color().toTuple()
39
+ color = self.ui.color.get_color("RGBA")
40
40
 
41
41
  if self.target_widget is not None:
42
42
  self.target_widget.set_max_points(max_points)
@@ -4,7 +4,7 @@ from qtpy.QtCore import QSize
4
4
  from qtpy.QtGui import QAction, QIcon
5
5
  from qtpy.QtWidgets import QHBoxLayout, QLabel, QWidget
6
6
 
7
- from bec_widgets.widgets.device_inputs import DeviceComboBox
7
+ from bec_widgets.widgets.device_combobox.device_combobox import DeviceComboBox
8
8
  from bec_widgets.widgets.toolbar.toolbar import ToolBarAction
9
9
 
10
10
 
@@ -2,7 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  import sys
4
4
 
5
- from qtpy import PYSIDE6
6
5
  from qtpy.QtWidgets import QVBoxLayout, QWidget
7
6
 
8
7
  from bec_widgets.utils import BECConnector
@@ -37,10 +36,6 @@ class BECMotorMapWidget(BECConnector, QWidget):
37
36
  client=None,
38
37
  gui_id: str | None = None,
39
38
  ) -> None:
40
- if not PYSIDE6:
41
- raise RuntimeError(
42
- "PYSIDE6 is not available in the environment. This widget is compatible only with PySide6."
43
- )
44
39
  if config is None:
45
40
  config = MotorMapConfig(widget_class=self.__class__.__name__)
46
41
  else:
@@ -216,13 +211,6 @@ class BECMotorMapWidget(BECConnector, QWidget):
216
211
 
217
212
 
218
213
  def main(): # pragma: no cover
219
-
220
- if not PYSIDE6:
221
- print(
222
- "PYSIDE6 is not available in the environment. UI files with BEC custom widgets are runnable only with PySide6."
223
- )
224
- return
225
-
226
214
  from qtpy.QtWidgets import QApplication
227
215
 
228
216
  app = QApplication(sys.argv)
@@ -12,8 +12,8 @@ from qtpy.QtWidgets import (
12
12
  )
13
13
 
14
14
  from bec_widgets.utils import BECConnector
15
- from bec_widgets.widgets.buttons.stop_button.stop_button import StopButton
16
15
  from bec_widgets.widgets.scan_control.scan_group_box import ScanGroupBox
16
+ from bec_widgets.widgets.stop_button.stop_button import StopButton
17
17
 
18
18
 
19
19
  class ScanControl(BECConnector, QWidget):
@@ -12,7 +12,7 @@ from qtpy.QtWidgets import (
12
12
  )
13
13
 
14
14
  from bec_widgets.utils.widget_io import WidgetIO
15
- from bec_widgets.widgets.device_inputs import DeviceLineEdit
15
+ from bec_widgets.widgets.device_line_edit.device_line_edit import DeviceLineEdit
16
16
 
17
17
 
18
18
  class ScanArgType:
@@ -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.stop_button.stop_button_plugin import StopButtonPlugin
10
+
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(StopButtonPlugin())
12
+
13
+
14
+ if __name__ == "__main__": # pragma: no cover
15
+ main()
@@ -1,3 +1,4 @@
1
+ from qtpy.QtCore import Slot
1
2
  from qtpy.QtWidgets import QPushButton
2
3
 
3
4
  from bec_widgets.utils import BECConnector
@@ -12,21 +13,13 @@ class StopButton(BECConnector, QPushButton):
12
13
 
13
14
  self.get_bec_shortcuts()
14
15
  self.setText("Stop")
15
- self.setStyleSheet("background-color: #cc181e; color: white")
16
+ self.setStyleSheet(
17
+ "background-color: #cc181e; color: white; font-weight: bold; font-size: 12px;"
18
+ )
16
19
  self.clicked.connect(self.stop_scan)
17
20
 
21
+ @Slot()
18
22
  def stop_scan(self):
19
23
  """Stop the scan."""
20
24
  self.queue.request_scan_abortion()
21
25
  self.queue.request_queue_reset()
22
-
23
-
24
- if __name__ == "__main__": # pragma: no cover
25
- import sys
26
-
27
- from qtpy.QtWidgets import QApplication
28
-
29
- app = QApplication(sys.argv)
30
- widget = StopButton()
31
- widget.show()
32
- sys.exit(app.exec_())
@@ -0,0 +1 @@
1
+ {'files': ['stop_button.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
+ import os
4
+
5
+ from qtpy.QtDesigner import QDesignerCustomWidgetInterface
6
+ from qtpy.QtGui import QIcon
7
+
8
+ from bec_widgets.widgets.stop_button.stop_button import StopButton
9
+
10
+ DOM_XML = """
11
+ <ui language='c++'>
12
+ <widget class='StopButton' name='stop_button'>
13
+ </widget>
14
+ </ui>
15
+ """
16
+
17
+
18
+ class StopButtonPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
19
+ def __init__(self):
20
+ super().__init__()
21
+ self._form_editor = None
22
+
23
+ def createWidget(self, parent):
24
+ t = StopButton(parent)
25
+ return t
26
+
27
+ def domXml(self):
28
+ return DOM_XML
29
+
30
+ def group(self):
31
+ return "BEC Buttons"
32
+
33
+ def icon(self):
34
+ current_path = os.path.dirname(__file__)
35
+ icon_path = os.path.join(current_path, "assets", "stop.png")
36
+ return QIcon(icon_path)
37
+
38
+ def includeFile(self):
39
+ return "stop_button"
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 "StopButton"
52
+
53
+ def toolTip(self):
54
+ return "A button that stops the current scan."
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.toggle.toggle_switch_plugin import ToggleSwitchPlugin
10
+
11
+ QPyDesignerCustomWidgetCollection.addCustomWidget(ToggleSwitchPlugin())
12
+
13
+
14
+ if __name__ == "__main__": # pragma: no cover
15
+ main()
@@ -0,0 +1,149 @@
1
+ import sys
2
+
3
+ from qtpy.QtCore import Property, QEasingCurve, QPointF, QPropertyAnimation, Qt
4
+ from qtpy.QtGui import QColor, QPainter
5
+ from qtpy.QtWidgets import QApplication, QWidget
6
+
7
+
8
+ class ToggleSwitch(QWidget):
9
+ """
10
+ A simple toggle.
11
+ """
12
+
13
+ def __init__(self, parent=None):
14
+ super().__init__(parent)
15
+ self.setFixedSize(40, 21)
16
+
17
+ self._thumb_pos = QPointF(3, 2) # Use QPointF for the thumb position
18
+ self._active_track_color = QColor(33, 150, 243)
19
+ self._active_thumb_color = QColor(255, 255, 255)
20
+ self._inactive_track_color = QColor(200, 200, 200)
21
+ self._inactive_thumb_color = QColor(255, 255, 255)
22
+
23
+ self._checked = False
24
+ self._track_color = self.inactive_track_color
25
+ self._thumb_color = self.inactive_thumb_color
26
+
27
+ self._animation = QPropertyAnimation(self, b"thumb_pos")
28
+ self._animation.setDuration(200)
29
+ self._animation.setEasingCurve(QEasingCurve.Type.OutBack)
30
+ self.setProperty("checked", True)
31
+
32
+ @Property(bool)
33
+ def checked(self):
34
+ """
35
+ The checked state of the toggle switch.
36
+ """
37
+ return self._checked
38
+
39
+ @checked.setter
40
+ def checked(self, state):
41
+ self._checked = state
42
+ self.update_colors()
43
+ self.set_thumb_pos_to_state()
44
+
45
+ @Property(QPointF)
46
+ def thumb_pos(self):
47
+ return self._thumb_pos
48
+
49
+ @thumb_pos.setter
50
+ def thumb_pos(self, pos):
51
+ self._thumb_pos = pos
52
+ self.update()
53
+
54
+ @Property(QColor)
55
+ def active_track_color(self):
56
+ return self._active_track_color
57
+
58
+ @active_track_color.setter
59
+ def active_track_color(self, color):
60
+ self._active_track_color = color
61
+ self.update_colors()
62
+ self.update()
63
+
64
+ @Property(QColor)
65
+ def active_thumb_color(self):
66
+ return self._active_thumb_color
67
+
68
+ @active_thumb_color.setter
69
+ def active_thumb_color(self, color):
70
+ self._active_thumb_color = color
71
+ self.update_colors()
72
+ self.update()
73
+
74
+ @Property(QColor)
75
+ def inactive_track_color(self):
76
+ return self._inactive_track_color
77
+
78
+ @inactive_track_color.setter
79
+ def inactive_track_color(self, color):
80
+ self._inactive_track_color = color
81
+ self.update_colors()
82
+ self.update()
83
+
84
+ @Property(QColor)
85
+ def inactive_thumb_color(self):
86
+ return self._inactive_thumb_color
87
+
88
+ @inactive_thumb_color.setter
89
+ def inactive_thumb_color(self, color):
90
+ self._inactive_thumb_color = color
91
+ self.update_colors()
92
+ self.update()
93
+
94
+ def paintEvent(self, event):
95
+ painter = QPainter(self)
96
+ painter.setRenderHint(QPainter.Antialiasing)
97
+
98
+ # Draw track
99
+ painter.setBrush(self._track_color)
100
+ painter.setPen(Qt.NoPen)
101
+ painter.drawRoundedRect(
102
+ 0, 0, self.width(), self.height(), self.height() / 2, self.height() / 2
103
+ )
104
+
105
+ # Draw thumb
106
+ painter.setBrush(self._thumb_color)
107
+ diameter = int(self.height() * 0.8)
108
+ painter.drawEllipse(int(self._thumb_pos.x()), int(self._thumb_pos.y()), diameter, diameter)
109
+
110
+ def mousePressEvent(self, event):
111
+ if event.button() == Qt.LeftButton:
112
+ self._checked = not self._checked
113
+ self.update_colors()
114
+ self.animate_thumb()
115
+
116
+ def update_colors(self):
117
+
118
+ self._thumb_color = self.active_thumb_color if self._checked else self.inactive_thumb_color
119
+ self._track_color = self.active_track_color if self._checked else self.inactive_track_color
120
+
121
+ def get_thumb_pos(self, checked):
122
+ return QPointF(self.width() - self.height() + 3, 2) if checked else QPointF(3, 2)
123
+
124
+ def set_thumb_pos_to_state(self):
125
+ # this is to avoid that linter complains about the thumb_pos setter
126
+ self.setProperty("thumb_pos", self.get_thumb_pos(self._checked))
127
+ self.update_colors()
128
+
129
+ def animate_thumb(self):
130
+ start_pos = self.thumb_pos
131
+ end_pos = self.get_thumb_pos(self._checked)
132
+
133
+ self._animation.stop()
134
+ self._animation.setStartValue(start_pos)
135
+ self._animation.setEndValue(end_pos)
136
+ self._animation.start()
137
+
138
+ def sizeHint(self):
139
+ return self.minimumSizeHint()
140
+
141
+ def minimumSizeHint(self):
142
+ return self.size()
143
+
144
+
145
+ if __name__ == "__main__": # pragma: no cover
146
+ app = QApplication(sys.argv)
147
+ window = ToggleSwitch()
148
+ window.show()
149
+ sys.exit(app.exec())
@@ -0,0 +1 @@
1
+ {'files': ['toggle.py']}
@@ -0,0 +1,54 @@
1
+ # Copyright (C) 2022 The Qt Company Ltd.
2
+ # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
3
+
4
+ from qtpy.QtDesigner import QDesignerCustomWidgetInterface
5
+ from qtpy.QtGui import QIcon
6
+
7
+ from bec_widgets.widgets.toggle.toggle import ToggleSwitch
8
+
9
+ DOM_XML = """
10
+ <ui language='c++'>
11
+ <widget class='ToggleSwitch' name='toggle_switch'>
12
+ </widget>
13
+ </ui>
14
+ """
15
+
16
+
17
+ class ToggleSwitchPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
18
+ def __init__(self):
19
+ super().__init__()
20
+ self._form_editor = None
21
+
22
+ def createWidget(self, parent):
23
+ t = ToggleSwitch(parent)
24
+ return t
25
+
26
+ def domXml(self):
27
+ return DOM_XML
28
+
29
+ def group(self):
30
+ return ""
31
+
32
+ def icon(self):
33
+ return QIcon()
34
+
35
+ def includeFile(self):
36
+ return "toggle_switch"
37
+
38
+ def initialize(self, form_editor):
39
+ self._form_editor = form_editor
40
+
41
+ def isContainer(self):
42
+ return False
43
+
44
+ def isInitialized(self):
45
+ return self._form_editor is not None
46
+
47
+ def name(self):
48
+ return "ToggleSwitch"
49
+
50
+ def toolTip(self):
51
+ return "ToggleSwitch"
52
+
53
+ def whatsThis(self):
54
+ return self.toolTip()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: bec_widgets
3
- Version: 0.79.3
3
+ Version: 0.82.0
4
4
  Summary: BEC Widgets
5
5
  Project-URL: Bug Tracker, https://gitlab.psi.ch/bec/bec_widgets/issues
6
6
  Project-URL: Homepage, https://gitlab.psi.ch/bec/bec_widgets
@@ -28,9 +28,6 @@ Requires-Dist: pytest-random-order~=1.1; extra == 'dev'
28
28
  Requires-Dist: pytest-timeout~=2.2; extra == 'dev'
29
29
  Requires-Dist: pytest-xvfb~=3.0; extra == 'dev'
30
30
  Requires-Dist: pytest~=8.0; extra == 'dev'
31
- Provides-Extra: pyqt5
32
- Requires-Dist: pyqt5>=5.9; extra == 'pyqt5'
33
- Requires-Dist: pyqtwebengine>=5.9; extra == 'pyqt5'
34
31
  Provides-Extra: pyqt6
35
32
  Requires-Dist: pyqt6-webengine>=6.7; extra == 'pyqt6'
36
33
  Requires-Dist: pyqt6>=6.7; extra == 'pyqt6'