bec-widgets 2.8.4__py3-none-any.whl → 2.9.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 +28 -0
- PKG-INFO +1 -1
- bec_widgets/cli/client.py +73 -0
- bec_widgets/utils/bec_dispatcher.py +6 -4
- bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.py +13 -12
- bec_widgets/widgets/control/device_input/signal_combobox/signal_combobox.py +11 -5
- bec_widgets/widgets/utility/signal_label/register_signal_label.py +15 -0
- bec_widgets/widgets/utility/signal_label/signal_label.py +456 -0
- bec_widgets/widgets/utility/signal_label/signal_label.pyproject +1 -0
- bec_widgets/widgets/utility/signal_label/signal_label_plugin.py +54 -0
- {bec_widgets-2.8.4.dist-info → bec_widgets-2.9.0.dist-info}/METADATA +1 -1
- {bec_widgets-2.8.4.dist-info → bec_widgets-2.9.0.dist-info}/RECORD +16 -12
- pyproject.toml +1 -1
- {bec_widgets-2.8.4.dist-info → bec_widgets-2.9.0.dist-info}/WHEEL +0 -0
- {bec_widgets-2.8.4.dist-info → bec_widgets-2.9.0.dist-info}/entry_points.txt +0 -0
- {bec_widgets-2.8.4.dist-info → bec_widgets-2.9.0.dist-info}/licenses/LICENSE +0 -0
CHANGELOG.md
CHANGED
@@ -1,6 +1,34 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
3
|
|
4
|
+
## v2.9.0 (2025-05-30)
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
- **DeviceSignalInput**: Improve robustness
|
9
|
+
([`91195ae`](https://github.com/bec-project/bec_widgets/commit/91195ae0fdf024daf2daaa4ea2963992b4e40e04))
|
10
|
+
|
11
|
+
use set for storing filter properties to allow multiple set to true or false
|
12
|
+
|
13
|
+
### Code Style
|
14
|
+
|
15
|
+
- Typing in bec_dispatcher
|
16
|
+
([`a6c5c21`](https://github.com/bec-project/bec_widgets/commit/a6c5c21afaa6dcf33ce71027e8730354ee34e3b4))
|
17
|
+
|
18
|
+
### Documentation
|
19
|
+
|
20
|
+
- Add usage docs for signal label widget
|
21
|
+
([`2b9919b`](https://github.com/bec-project/bec_widgets/commit/2b9919bb34a66708f4b910ffc17dc253e9b7f70d))
|
22
|
+
|
23
|
+
### Features
|
24
|
+
|
25
|
+
- (#569) add signal label widget
|
26
|
+
([`822e7d0`](https://github.com/bec-project/bec_widgets/commit/822e7d06ff7479d006ae99942fed5e2c836831ce))
|
27
|
+
|
28
|
+
add a widget which shows the current value of a signal from BEC. configurable with many properties
|
29
|
+
in designer. intended for use mainly in static GUIs.
|
30
|
+
|
31
|
+
|
4
32
|
## v2.8.4 (2025-05-30)
|
5
33
|
|
6
34
|
### Bug Fixes
|
PKG-INFO
CHANGED
bec_widgets/cli/client.py
CHANGED
@@ -52,6 +52,7 @@ _Widgets = {
|
|
52
52
|
"ScanControl": "ScanControl",
|
53
53
|
"ScatterWaveform": "ScatterWaveform",
|
54
54
|
"SignalComboBox": "SignalComboBox",
|
55
|
+
"SignalLabel": "SignalLabel",
|
55
56
|
"SignalLineEdit": "SignalLineEdit",
|
56
57
|
"StopButton": "StopButton",
|
57
58
|
"TextBox": "TextBox",
|
@@ -3459,6 +3460,78 @@ class SignalComboBox(RPCBase):
|
|
3459
3460
|
"""
|
3460
3461
|
|
3461
3462
|
|
3463
|
+
class SignalLabel(RPCBase):
|
3464
|
+
@property
|
3465
|
+
@rpc_call
|
3466
|
+
def custom_label(self) -> "str":
|
3467
|
+
"""
|
3468
|
+
Use a cusom label rather than the signal name
|
3469
|
+
"""
|
3470
|
+
|
3471
|
+
@property
|
3472
|
+
@rpc_call
|
3473
|
+
def custom_units(self) -> "str":
|
3474
|
+
"""
|
3475
|
+
Use a custom unit string
|
3476
|
+
"""
|
3477
|
+
|
3478
|
+
@custom_label.setter
|
3479
|
+
@rpc_call
|
3480
|
+
def custom_label(self) -> "str":
|
3481
|
+
"""
|
3482
|
+
Use a cusom label rather than the signal name
|
3483
|
+
"""
|
3484
|
+
|
3485
|
+
@custom_units.setter
|
3486
|
+
@rpc_call
|
3487
|
+
def custom_units(self) -> "str":
|
3488
|
+
"""
|
3489
|
+
Use a custom unit string
|
3490
|
+
"""
|
3491
|
+
|
3492
|
+
@property
|
3493
|
+
@rpc_call
|
3494
|
+
def decimal_places(self) -> "int":
|
3495
|
+
"""
|
3496
|
+
Format to a given number of decimal_places. Set to 0 to disable.
|
3497
|
+
"""
|
3498
|
+
|
3499
|
+
@decimal_places.setter
|
3500
|
+
@rpc_call
|
3501
|
+
def decimal_places(self) -> "int":
|
3502
|
+
"""
|
3503
|
+
Format to a given number of decimal_places. Set to 0 to disable.
|
3504
|
+
"""
|
3505
|
+
|
3506
|
+
@property
|
3507
|
+
@rpc_call
|
3508
|
+
def show_default_units(self) -> "bool":
|
3509
|
+
"""
|
3510
|
+
Show default units obtained from the signal alongside it
|
3511
|
+
"""
|
3512
|
+
|
3513
|
+
@show_default_units.setter
|
3514
|
+
@rpc_call
|
3515
|
+
def show_default_units(self) -> "bool":
|
3516
|
+
"""
|
3517
|
+
Show default units obtained from the signal alongside it
|
3518
|
+
"""
|
3519
|
+
|
3520
|
+
@property
|
3521
|
+
@rpc_call
|
3522
|
+
def show_select_button(self) -> "bool":
|
3523
|
+
"""
|
3524
|
+
Show the button to select the signal to display
|
3525
|
+
"""
|
3526
|
+
|
3527
|
+
@show_select_button.setter
|
3528
|
+
@rpc_call
|
3529
|
+
def show_select_button(self) -> "bool":
|
3530
|
+
"""
|
3531
|
+
Show the button to select the signal to display
|
3532
|
+
"""
|
3533
|
+
|
3534
|
+
|
3462
3535
|
class SignalLineEdit(RPCBase):
|
3463
3536
|
"""Line edit widget for device input with autocomplete for device names."""
|
3464
3537
|
|
@@ -163,7 +163,7 @@ class BECDispatcher:
|
|
163
163
|
def connect_slot(
|
164
164
|
self,
|
165
165
|
slot: Callable,
|
166
|
-
topics:
|
166
|
+
topics: EndpointInfo | str | list[EndpointInfo] | list[str],
|
167
167
|
cb_info: dict | None = None,
|
168
168
|
**kwargs,
|
169
169
|
) -> None:
|
@@ -172,7 +172,7 @@ class BECDispatcher:
|
|
172
172
|
Args:
|
173
173
|
slot (Callable): A slot method/function that accepts two inputs: content and metadata of
|
174
174
|
the corresponding pub/sub message
|
175
|
-
topics
|
175
|
+
topics EndpointInfo | str | list[EndpointInfo] | list[str]: A topic or list of topics that can typically be acquired via bec_lib.MessageEndpoints
|
176
176
|
cb_info (dict | None): A dictionary containing information about the callback. Defaults to None.
|
177
177
|
"""
|
178
178
|
qt_slot = QtThreadSafeCallback(cb=slot, cb_info=cb_info)
|
@@ -183,13 +183,15 @@ class BECDispatcher:
|
|
183
183
|
topics_str, _ = self.client.connector._convert_endpointinfo(topics)
|
184
184
|
qt_slot.topics.update(set(topics_str))
|
185
185
|
|
186
|
-
def disconnect_slot(
|
186
|
+
def disconnect_slot(
|
187
|
+
self, slot: Callable, topics: EndpointInfo | str | list[EndpointInfo] | list[str]
|
188
|
+
):
|
187
189
|
"""
|
188
190
|
Disconnect a slot from a topic.
|
189
191
|
|
190
192
|
Args:
|
191
193
|
slot(Callable): The slot to disconnect
|
192
|
-
topics
|
194
|
+
topics EndpointInfo | str | list[EndpointInfo] | list[str]: A topic or list of topics to unsub from.
|
193
195
|
"""
|
194
196
|
# find the right slot to disconnect from ;
|
195
197
|
# slot callbacks are wrapped in QtThreadSafeCallback objects,
|
@@ -1,10 +1,11 @@
|
|
1
1
|
from bec_lib.callback_handler import EventType
|
2
2
|
from bec_lib.device import Signal
|
3
3
|
from bec_lib.logger import bec_logger
|
4
|
-
from qtpy.QtCore import Property
|
4
|
+
from qtpy.QtCore import Property
|
5
5
|
|
6
6
|
from bec_widgets.utils import ConnectionConfig
|
7
7
|
from bec_widgets.utils.bec_widget import BECWidget
|
8
|
+
from bec_widgets.utils.error_popups import SafeSlot
|
8
9
|
from bec_widgets.utils.filter_io import FilterIO
|
9
10
|
from bec_widgets.utils.ophyd_kind_util import Kind
|
10
11
|
from bec_widgets.utils.widget_io import WidgetIO
|
@@ -49,7 +50,7 @@ class DeviceSignalInputBase(BECWidget):
|
|
49
50
|
|
50
51
|
self._device = None
|
51
52
|
self.get_bec_shortcuts()
|
52
|
-
self._signal_filter =
|
53
|
+
self._signal_filter = set()
|
53
54
|
self._signals = []
|
54
55
|
self._hinted_signals = []
|
55
56
|
self._normal_signals = []
|
@@ -60,7 +61,7 @@ class DeviceSignalInputBase(BECWidget):
|
|
60
61
|
|
61
62
|
### Qt Slots ###
|
62
63
|
|
63
|
-
@
|
64
|
+
@SafeSlot(str)
|
64
65
|
def set_signal(self, signal: str):
|
65
66
|
"""
|
66
67
|
Set the signal.
|
@@ -76,7 +77,7 @@ class DeviceSignalInputBase(BECWidget):
|
|
76
77
|
f"Signal {signal} not found for device {self.device} and filtered selection {self.signal_filter}."
|
77
78
|
)
|
78
79
|
|
79
|
-
@
|
80
|
+
@SafeSlot(str)
|
80
81
|
def set_device(self, device: str | None):
|
81
82
|
"""
|
82
83
|
Set the device. If device is not valid, device will be set to None which happens
|
@@ -90,8 +91,8 @@ class DeviceSignalInputBase(BECWidget):
|
|
90
91
|
self._device = device
|
91
92
|
self.update_signals_from_filters()
|
92
93
|
|
93
|
-
@
|
94
|
-
@
|
94
|
+
@SafeSlot(dict, dict)
|
95
|
+
@SafeSlot()
|
95
96
|
def update_signals_from_filters(
|
96
97
|
self, content: dict | None = None, metadata: dict | None = None
|
97
98
|
):
|
@@ -158,9 +159,9 @@ class DeviceSignalInputBase(BECWidget):
|
|
158
159
|
@include_hinted_signals.setter
|
159
160
|
def include_hinted_signals(self, value: bool):
|
160
161
|
if value:
|
161
|
-
self._signal_filter.
|
162
|
+
self._signal_filter.add(Kind.hinted)
|
162
163
|
else:
|
163
|
-
self._signal_filter.
|
164
|
+
self._signal_filter.discard(Kind.hinted)
|
164
165
|
self.update_signals_from_filters()
|
165
166
|
|
166
167
|
@Property(bool)
|
@@ -171,9 +172,9 @@ class DeviceSignalInputBase(BECWidget):
|
|
171
172
|
@include_normal_signals.setter
|
172
173
|
def include_normal_signals(self, value: bool):
|
173
174
|
if value:
|
174
|
-
self._signal_filter.
|
175
|
+
self._signal_filter.add(Kind.normal)
|
175
176
|
else:
|
176
|
-
self._signal_filter.
|
177
|
+
self._signal_filter.discard(Kind.normal)
|
177
178
|
self.update_signals_from_filters()
|
178
179
|
|
179
180
|
@Property(bool)
|
@@ -184,9 +185,9 @@ class DeviceSignalInputBase(BECWidget):
|
|
184
185
|
@include_config_signals.setter
|
185
186
|
def include_config_signals(self, value: bool):
|
186
187
|
if value:
|
187
|
-
self._signal_filter.
|
188
|
+
self._signal_filter.add(Kind.config)
|
188
189
|
else:
|
189
|
-
self._signal_filter.
|
190
|
+
self._signal_filter.discard(Kind.config)
|
190
191
|
self.update_signals_from_filters()
|
191
192
|
|
192
193
|
### Properties and Methods ###
|
@@ -1,11 +1,13 @@
|
|
1
1
|
from bec_lib.device import Positioner
|
2
|
-
from qtpy.QtCore import QSize, Signal
|
2
|
+
from qtpy.QtCore import QSize, Signal
|
3
3
|
from qtpy.QtWidgets import QComboBox, QSizePolicy
|
4
4
|
|
5
|
+
from bec_widgets.utils.error_popups import SafeSlot
|
5
6
|
from bec_widgets.utils.filter_io import ComboBoxFilterHandler, FilterIO
|
6
7
|
from bec_widgets.utils.ophyd_kind_util import Kind
|
7
8
|
from bec_widgets.widgets.control.device_input.base_classes.device_signal_input_base import (
|
8
9
|
DeviceSignalInputBase,
|
10
|
+
DeviceSignalInputBaseConfig,
|
9
11
|
)
|
10
12
|
|
11
13
|
|
@@ -35,7 +37,7 @@ class SignalComboBox(DeviceSignalInputBase, QComboBox):
|
|
35
37
|
self,
|
36
38
|
parent=None,
|
37
39
|
client=None,
|
38
|
-
config:
|
40
|
+
config: DeviceSignalInputBaseConfig | None = None,
|
39
41
|
gui_id: str | None = None,
|
40
42
|
device: str | None = None,
|
41
43
|
signal_filter: str | list[str] | None = None,
|
@@ -65,9 +67,13 @@ class SignalComboBox(DeviceSignalInputBase, QComboBox):
|
|
65
67
|
if default is not None:
|
66
68
|
self.set_signal(default)
|
67
69
|
|
68
|
-
|
70
|
+
@SafeSlot()
|
71
|
+
@SafeSlot(dict, dict)
|
72
|
+
def update_signals_from_filters(
|
73
|
+
self, content: dict | None = None, metadata: dict | None = None
|
74
|
+
):
|
69
75
|
"""Update the filters for the combobox"""
|
70
|
-
super().update_signals_from_filters()
|
76
|
+
super().update_signals_from_filters(content, metadata)
|
71
77
|
# pylint: disable=protected-access
|
72
78
|
if FilterIO._find_handler(self) is ComboBoxFilterHandler:
|
73
79
|
if len(self._config_signals) > 0:
|
@@ -84,7 +90,7 @@ class SignalComboBox(DeviceSignalInputBase, QComboBox):
|
|
84
90
|
self.insertItem(0, "Hinted Signals")
|
85
91
|
self.model().item(0).setEnabled(False)
|
86
92
|
|
87
|
-
@
|
93
|
+
@SafeSlot(str)
|
88
94
|
def on_text_changed(self, text: str):
|
89
95
|
"""Slot for text changed. If a device is selected and the signal is changed and valid it emits a signal.
|
90
96
|
For a positioner, the readback value has to be renamed to the device name.
|
@@ -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.utility.signal_label.signal_label_plugin import SignalLabelPlugin
|
10
|
+
|
11
|
+
QPyDesignerCustomWidgetCollection.addCustomWidget(SignalLabelPlugin())
|
12
|
+
|
13
|
+
|
14
|
+
if __name__ == "__main__": # pragma: no cover
|
15
|
+
main()
|
@@ -0,0 +1,456 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import sys
|
4
|
+
import traceback
|
5
|
+
from typing import TYPE_CHECKING
|
6
|
+
|
7
|
+
from bec_lib.device import Device, Signal
|
8
|
+
from bec_lib.endpoints import MessageEndpoints
|
9
|
+
from bec_qthemes import material_icon
|
10
|
+
from qtpy.QtCore import Signal as QSignal
|
11
|
+
from qtpy.QtWidgets import (
|
12
|
+
QApplication,
|
13
|
+
QComboBox,
|
14
|
+
QDialog,
|
15
|
+
QDialogButtonBox,
|
16
|
+
QGroupBox,
|
17
|
+
QHBoxLayout,
|
18
|
+
QLabel,
|
19
|
+
QLineEdit,
|
20
|
+
QToolButton,
|
21
|
+
QVBoxLayout,
|
22
|
+
QWidget,
|
23
|
+
)
|
24
|
+
|
25
|
+
from bec_widgets.utils.bec_connector import ConnectionConfig
|
26
|
+
from bec_widgets.utils.bec_widget import BECWidget
|
27
|
+
from bec_widgets.utils.colors import get_accent_colors
|
28
|
+
from bec_widgets.utils.error_popups import SafeProperty, SafeSlot
|
29
|
+
from bec_widgets.utils.ophyd_kind_util import Kind
|
30
|
+
from bec_widgets.widgets.control.device_input.base_classes.device_input_base import (
|
31
|
+
DeviceInputConfig,
|
32
|
+
)
|
33
|
+
from bec_widgets.widgets.control.device_input.base_classes.device_signal_input_base import (
|
34
|
+
DeviceSignalInputBaseConfig,
|
35
|
+
)
|
36
|
+
from bec_widgets.widgets.control.device_input.device_line_edit.device_line_edit import (
|
37
|
+
DeviceLineEdit,
|
38
|
+
)
|
39
|
+
from bec_widgets.widgets.control.device_input.signal_combobox.signal_combobox import SignalComboBox
|
40
|
+
|
41
|
+
if TYPE_CHECKING:
|
42
|
+
from bec_lib.client import BECClient
|
43
|
+
|
44
|
+
|
45
|
+
class ChoiceDialog(QDialog):
|
46
|
+
accepted_output = QSignal(str, str)
|
47
|
+
|
48
|
+
CONNECTION_ERROR_STR = "Error: client is not connected!"
|
49
|
+
|
50
|
+
def __init__(
|
51
|
+
self,
|
52
|
+
parent: QWidget | None = None,
|
53
|
+
config: ConnectionConfig | None = None,
|
54
|
+
client: BECClient | None = None,
|
55
|
+
show_hinted: bool = True,
|
56
|
+
show_normal: bool = False,
|
57
|
+
show_config: bool = False,
|
58
|
+
):
|
59
|
+
if not client or not client.started:
|
60
|
+
self._display_error()
|
61
|
+
return
|
62
|
+
super().__init__(parent=parent)
|
63
|
+
self.setWindowTitle("Choose device and signal...")
|
64
|
+
self._accent_colors = get_accent_colors()
|
65
|
+
|
66
|
+
layout = QHBoxLayout()
|
67
|
+
|
68
|
+
config_dict = config.model_dump() if config is not None else {}
|
69
|
+
self._device_config = DeviceInputConfig.model_validate(config_dict)
|
70
|
+
self._signal_config = DeviceSignalInputBaseConfig.model_validate(config_dict)
|
71
|
+
self._device_field = DeviceLineEdit(
|
72
|
+
config=self._device_config, parent=parent, client=client
|
73
|
+
)
|
74
|
+
self._signal_field = SignalComboBox(
|
75
|
+
config=self._signal_config,
|
76
|
+
device=self._signal_config.device,
|
77
|
+
parent=parent,
|
78
|
+
client=client,
|
79
|
+
)
|
80
|
+
layout.addWidget(self._device_field)
|
81
|
+
layout.addWidget(self._signal_field)
|
82
|
+
|
83
|
+
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
84
|
+
self.button_box.accepted.connect(self.accept)
|
85
|
+
self.button_box.rejected.connect(self.reject)
|
86
|
+
layout.addWidget(self.button_box)
|
87
|
+
|
88
|
+
self._signal_field.include_hinted_signals = show_hinted
|
89
|
+
self._signal_field.include_normal_signals = show_normal
|
90
|
+
self._signal_field.include_config_signals = show_config
|
91
|
+
|
92
|
+
self.setLayout(layout)
|
93
|
+
self._device_field.textChanged.connect(self._update_device)
|
94
|
+
self._device_field.setText(config.device if config is not None else "")
|
95
|
+
|
96
|
+
def _display_error(self):
|
97
|
+
try:
|
98
|
+
super().__init__()
|
99
|
+
except Exception:
|
100
|
+
...
|
101
|
+
layout = QHBoxLayout()
|
102
|
+
layout.addWidget(QLabel(self.CONNECTION_ERROR_STR))
|
103
|
+
self.button_box = QDialogButtonBox(QDialogButtonBox.Cancel)
|
104
|
+
self.button_box.accepted.connect(self.reject)
|
105
|
+
layout.addWidget(self.button_box)
|
106
|
+
self.setLayout(layout)
|
107
|
+
|
108
|
+
@SafeSlot(str)
|
109
|
+
def _update_device(self, device: str):
|
110
|
+
if device in self._device_field.dev:
|
111
|
+
self._device_field.set_device(device)
|
112
|
+
self._signal_field.set_device(device)
|
113
|
+
self._device_field.setStyleSheet(
|
114
|
+
f"QLineEdit {{ border-style: solid; border-width: 2px; border-color: {self._accent_colors.success.name() if self._accent_colors else 'green'}}}"
|
115
|
+
)
|
116
|
+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(True)
|
117
|
+
else:
|
118
|
+
self._device_field.setStyleSheet(
|
119
|
+
f"QLineEdit {{ border-style: solid; border-width: 2px; border-color: {self._accent_colors.emergency.name() if self._accent_colors else 'red'}}}"
|
120
|
+
)
|
121
|
+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
|
122
|
+
self._signal_field.clear()
|
123
|
+
|
124
|
+
def accept(self):
|
125
|
+
self.accepted_output.emit(self._device_field.text(), self._signal_field.currentText())
|
126
|
+
return super().accept()
|
127
|
+
|
128
|
+
|
129
|
+
class SignalLabel(BECWidget, QWidget):
|
130
|
+
|
131
|
+
ICON_NAME = "scoreboard"
|
132
|
+
RPC = True
|
133
|
+
PLUGIN = True
|
134
|
+
|
135
|
+
USER_ACCESS = [
|
136
|
+
"custom_label",
|
137
|
+
"custom_units",
|
138
|
+
"custom_label.setter",
|
139
|
+
"custom_units.setter",
|
140
|
+
"decimal_places",
|
141
|
+
"decimal_places.setter",
|
142
|
+
"show_default_units",
|
143
|
+
"show_default_units.setter",
|
144
|
+
"show_select_button",
|
145
|
+
"show_select_button.setter",
|
146
|
+
]
|
147
|
+
|
148
|
+
def __init__(
|
149
|
+
self,
|
150
|
+
parent: QWidget | None = None,
|
151
|
+
client: BECClient | None = None,
|
152
|
+
device: str | None = None,
|
153
|
+
signal: str | None = None,
|
154
|
+
show_select_button: bool = True,
|
155
|
+
show_default_units: bool = False,
|
156
|
+
custom_label: str = "",
|
157
|
+
custom_units: str = "",
|
158
|
+
**kwargs,
|
159
|
+
):
|
160
|
+
"""Initialize the SignalLabel widget.
|
161
|
+
|
162
|
+
Args:
|
163
|
+
parent (QWidget, optional): The parent widget. Defaults to None.
|
164
|
+
client (BECClient, optional): The BEC client. Defaults to None.
|
165
|
+
device (str, optional): The device name. Defaults to None.
|
166
|
+
signal (str, optional): The signal name. Defaults to None.
|
167
|
+
selection_dialog_config (DeviceSignalInputBaseConfig | dict, optional): Configuration for the signal selection dialog.
|
168
|
+
show_select_button (bool, optional): Whether to show the select button. Defaults to True.
|
169
|
+
show_default_units (bool, optional): Whether to show default units. Defaults to False.
|
170
|
+
custom_label (str, optional): Custom label for the widget. Defaults to "".
|
171
|
+
custom_units (str, optional): Custom units for the widget. Defaults to "".
|
172
|
+
"""
|
173
|
+
self._config = DeviceSignalInputBaseConfig(default=signal, device=device)
|
174
|
+
super().__init__(parent=parent, client=client, **kwargs)
|
175
|
+
|
176
|
+
self._device = device
|
177
|
+
self._signal = signal
|
178
|
+
|
179
|
+
self._custom_label: str = custom_label
|
180
|
+
self._custom_units: str = custom_units
|
181
|
+
self._show_default_units: bool = show_default_units
|
182
|
+
self._decimal_places = 3
|
183
|
+
|
184
|
+
self._show_hinted_signals: bool = True
|
185
|
+
self._show_normal_signals: bool = False
|
186
|
+
self._show_config_signals: bool = False
|
187
|
+
|
188
|
+
self._outer_layout = QHBoxLayout()
|
189
|
+
self._layout = QHBoxLayout()
|
190
|
+
self._outer_layout.setContentsMargins(0, 0, 0, 0)
|
191
|
+
self._layout.setContentsMargins(0, 0, 0, 0)
|
192
|
+
self.setLayout(self._outer_layout)
|
193
|
+
|
194
|
+
self._label = QGroupBox(custom_label)
|
195
|
+
self._outer_layout.addWidget(self._label)
|
196
|
+
self._update_label()
|
197
|
+
self._label.setLayout(self._layout)
|
198
|
+
|
199
|
+
self._value: str = ""
|
200
|
+
self._display = QLabel()
|
201
|
+
self._layout.addWidget(self._display)
|
202
|
+
|
203
|
+
self._select_button = QToolButton()
|
204
|
+
self._select_button.setIcon(material_icon(icon_name="settings", size=(20, 20)))
|
205
|
+
self._show_select_button: bool = show_select_button
|
206
|
+
self._layout.addWidget(self._select_button)
|
207
|
+
self._display.setMinimumHeight(self._select_button.sizeHint().height())
|
208
|
+
self.show_select_button = self._show_select_button
|
209
|
+
|
210
|
+
self._select_button.clicked.connect(self.show_choice_dialog)
|
211
|
+
self.get_bec_shortcuts()
|
212
|
+
|
213
|
+
self._connected: bool = False
|
214
|
+
self.connect_device()
|
215
|
+
|
216
|
+
def _create_dialog(self):
|
217
|
+
return ChoiceDialog(
|
218
|
+
config=self._config,
|
219
|
+
parent=self,
|
220
|
+
client=self.client,
|
221
|
+
show_config=self.show_config_signals,
|
222
|
+
show_normal=self.show_normal_signals,
|
223
|
+
show_hinted=self.show_hinted_signals,
|
224
|
+
)
|
225
|
+
|
226
|
+
@SafeSlot()
|
227
|
+
def _process_dialog(self, device: str, signal: str):
|
228
|
+
self.disconnect_device()
|
229
|
+
self.device = device
|
230
|
+
self.signal = signal
|
231
|
+
self._update_label()
|
232
|
+
self.connect_device()
|
233
|
+
|
234
|
+
def show_choice_dialog(self):
|
235
|
+
dialog = self._create_dialog()
|
236
|
+
dialog.accepted_output.connect(self._process_dialog)
|
237
|
+
dialog.open()
|
238
|
+
return dialog
|
239
|
+
|
240
|
+
def connect_device(self):
|
241
|
+
"""Subscribe to the Redis topic for the device to display"""
|
242
|
+
if not self._connected and self._device and self._device in self.dev:
|
243
|
+
self._connected = True
|
244
|
+
self._readback_endpoint = MessageEndpoints.device_readback(self._device)
|
245
|
+
self.bec_dispatcher.connect_slot(self.on_device_readback, self._readback_endpoint)
|
246
|
+
self._manual_read()
|
247
|
+
self.set_display_value(self._value)
|
248
|
+
|
249
|
+
def disconnect_device(self):
|
250
|
+
"""Unsubscribe from the Redis topic for the device to display"""
|
251
|
+
if self._connected:
|
252
|
+
self._connected = False
|
253
|
+
self.bec_dispatcher.disconnect_slot(self.on_device_readback, self._readback_endpoint)
|
254
|
+
|
255
|
+
def _manual_read(self):
|
256
|
+
if self._device is None or not isinstance(
|
257
|
+
(device := self.dev.get(self._device)), Device | Signal
|
258
|
+
):
|
259
|
+
self._units = ""
|
260
|
+
self._value = "__"
|
261
|
+
return
|
262
|
+
signal: Signal = (
|
263
|
+
getattr(device, self.signal, None) if isinstance(device, Device) else device
|
264
|
+
)
|
265
|
+
if not isinstance(signal, Signal): # Avoid getting other attributes of device, e.g. methods
|
266
|
+
signal = None
|
267
|
+
if signal is None:
|
268
|
+
self._units = ""
|
269
|
+
self._value = "__"
|
270
|
+
return
|
271
|
+
self._value = signal.get()
|
272
|
+
self._units = signal.get_device_config().get("egu", "")
|
273
|
+
|
274
|
+
@SafeSlot(dict, dict)
|
275
|
+
def on_device_readback(self, msg: dict, metadata: dict) -> None:
|
276
|
+
"""
|
277
|
+
Update the display with the new value.
|
278
|
+
"""
|
279
|
+
try:
|
280
|
+
signal_to_read = self._patch_hinted_signal()
|
281
|
+
self._value = msg["signals"][signal_to_read]["value"]
|
282
|
+
self.set_display_value(self._value)
|
283
|
+
except Exception as e:
|
284
|
+
self._display.setText("ERROR!")
|
285
|
+
self._display.setToolTip(
|
286
|
+
f"Error processing incoming reading: {msg}, handled with exception: {''.join(traceback.format_exception(e))}"
|
287
|
+
)
|
288
|
+
|
289
|
+
def _patch_hinted_signal(self):
|
290
|
+
if self.dev[self._device]._info["signals"] == {}:
|
291
|
+
return self._signal
|
292
|
+
signal_info = self.dev[self._device]._info["signals"][self._signal]
|
293
|
+
return (
|
294
|
+
signal_info["obj_name"] if signal_info["kind_str"] == Kind.hinted.name else self._signal
|
295
|
+
)
|
296
|
+
|
297
|
+
@SafeProperty(str)
|
298
|
+
def device(self) -> str:
|
299
|
+
"""The device from which to select a signal"""
|
300
|
+
return self._device or "Not set!"
|
301
|
+
|
302
|
+
@device.setter
|
303
|
+
def device(self, value: str) -> None:
|
304
|
+
self.disconnect_device()
|
305
|
+
self._device = value
|
306
|
+
self._config.device = value
|
307
|
+
self.connect_device()
|
308
|
+
self._update_label()
|
309
|
+
|
310
|
+
@SafeProperty(str)
|
311
|
+
def signal(self) -> str:
|
312
|
+
"""The signal to display"""
|
313
|
+
return self._signal or "Not set!"
|
314
|
+
|
315
|
+
@signal.setter
|
316
|
+
def signal(self, value: str) -> None:
|
317
|
+
self.disconnect_device()
|
318
|
+
self._signal = value
|
319
|
+
self._config.default = value
|
320
|
+
self.connect_device()
|
321
|
+
self._update_label()
|
322
|
+
|
323
|
+
@SafeProperty(bool)
|
324
|
+
def show_select_button(self) -> bool:
|
325
|
+
"""Show the button to select the signal to display"""
|
326
|
+
return self._show_select_button
|
327
|
+
|
328
|
+
@show_select_button.setter
|
329
|
+
def show_select_button(self, value: bool) -> None:
|
330
|
+
self._show_select_button = value
|
331
|
+
self._select_button.setVisible(value)
|
332
|
+
|
333
|
+
@SafeProperty(bool)
|
334
|
+
def show_default_units(self) -> bool:
|
335
|
+
"""Show default units obtained from the signal alongside it"""
|
336
|
+
return self._show_default_units
|
337
|
+
|
338
|
+
@show_default_units.setter
|
339
|
+
def show_default_units(self, value: bool) -> None:
|
340
|
+
self._show_default_units = value
|
341
|
+
self.set_display_value(self._value)
|
342
|
+
|
343
|
+
@SafeProperty(str)
|
344
|
+
def custom_label(self) -> str:
|
345
|
+
"""Use a cusom label rather than the signal name"""
|
346
|
+
return self._custom_label
|
347
|
+
|
348
|
+
@custom_label.setter
|
349
|
+
def custom_label(self, value: str) -> None:
|
350
|
+
self._custom_label = value
|
351
|
+
self._update_label()
|
352
|
+
|
353
|
+
@SafeProperty(str)
|
354
|
+
def custom_units(self) -> str:
|
355
|
+
"""Use a custom unit string"""
|
356
|
+
return self._custom_units
|
357
|
+
|
358
|
+
@custom_units.setter
|
359
|
+
def custom_units(self, value: str) -> None:
|
360
|
+
self._custom_units = value
|
361
|
+
self.set_display_value(self._value)
|
362
|
+
|
363
|
+
@SafeProperty(int)
|
364
|
+
def decimal_places(self) -> int:
|
365
|
+
"""Format to a given number of decimal_places. Set to 0 to disable."""
|
366
|
+
return self._decimal_places
|
367
|
+
|
368
|
+
@decimal_places.setter
|
369
|
+
def decimal_places(self, value: int) -> None:
|
370
|
+
self._decimal_places = value
|
371
|
+
self._update_label()
|
372
|
+
|
373
|
+
@SafeProperty(bool)
|
374
|
+
def show_hinted_signals(self) -> bool:
|
375
|
+
"""In the signal selection menu, show hinted signals"""
|
376
|
+
return self._show_hinted_signals
|
377
|
+
|
378
|
+
@show_hinted_signals.setter
|
379
|
+
def show_hinted_signals(self, value: bool) -> None:
|
380
|
+
self._show_hinted_signals = value
|
381
|
+
|
382
|
+
@SafeProperty(bool)
|
383
|
+
def show_config_signals(self) -> bool:
|
384
|
+
"""In the signal selection menu, show config signals"""
|
385
|
+
return self._show_config_signals
|
386
|
+
|
387
|
+
@show_config_signals.setter
|
388
|
+
def show_config_signals(self, value: bool) -> None:
|
389
|
+
self._show_config_signals = value
|
390
|
+
|
391
|
+
@SafeProperty(bool)
|
392
|
+
def show_normal_signals(self) -> bool:
|
393
|
+
"""In the signal selection menu, show normal signals"""
|
394
|
+
return self._show_normal_signals
|
395
|
+
|
396
|
+
@show_normal_signals.setter
|
397
|
+
def show_normal_signals(self, value: bool) -> None:
|
398
|
+
self._show_normal_signals = value
|
399
|
+
|
400
|
+
def _format_value(self, value: str):
|
401
|
+
if self._decimal_places == 0:
|
402
|
+
return value
|
403
|
+
try:
|
404
|
+
return f"{float(value):0.{self._decimal_places}f}"
|
405
|
+
except ValueError:
|
406
|
+
return value
|
407
|
+
|
408
|
+
@SafeSlot(str)
|
409
|
+
def set_display_value(self, value: str):
|
410
|
+
"""Set the display to a given value, appending the units if specified"""
|
411
|
+
self._display.setText(f"{self._format_value(value)}{self._units_string}")
|
412
|
+
self._display.setToolTip("")
|
413
|
+
|
414
|
+
@property
|
415
|
+
def _units_string(self):
|
416
|
+
if self.custom_units or self._show_default_units:
|
417
|
+
return f" {self.custom_units or self._default_units or ''}"
|
418
|
+
return ""
|
419
|
+
|
420
|
+
@property
|
421
|
+
def _default_units(self) -> str:
|
422
|
+
return self._units
|
423
|
+
|
424
|
+
@property
|
425
|
+
def _default_label(self) -> str:
|
426
|
+
return (
|
427
|
+
str(self._signal) if self._device == self._signal else f"{self._device} {self._signal}"
|
428
|
+
)
|
429
|
+
|
430
|
+
def _update_label(self):
|
431
|
+
self._label.setTitle(
|
432
|
+
self._custom_label if self._custom_label else f"{self._default_label}:"
|
433
|
+
)
|
434
|
+
|
435
|
+
|
436
|
+
if __name__ == "__main__":
|
437
|
+
|
438
|
+
app = QApplication(sys.argv)
|
439
|
+
w = QWidget()
|
440
|
+
w.setLayout(QVBoxLayout())
|
441
|
+
w.layout().addWidget(
|
442
|
+
SignalLabel(
|
443
|
+
device="samx",
|
444
|
+
signal="readback",
|
445
|
+
custom_label="custom label:",
|
446
|
+
custom_units=" m/s/s",
|
447
|
+
show_select_button=False,
|
448
|
+
)
|
449
|
+
)
|
450
|
+
w.layout().addWidget(SignalLabel(device="samy", signal="readback", show_default_units=True))
|
451
|
+
l = SignalLabel()
|
452
|
+
l.device = "bpm4i"
|
453
|
+
l.signal = "bpm4i"
|
454
|
+
w.layout().addWidget(l)
|
455
|
+
w.show()
|
456
|
+
sys.exit(app.exec_())
|
@@ -0,0 +1 @@
|
|
1
|
+
{'files': ['signal_label.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
|
+
|
6
|
+
from bec_widgets.utils.bec_designer import designer_material_icon
|
7
|
+
from bec_widgets.widgets.utility.signal_label.signal_label import SignalLabel
|
8
|
+
|
9
|
+
DOM_XML = """
|
10
|
+
<ui language='c++'>
|
11
|
+
<widget class='SignalLabel' name='signal_label'>
|
12
|
+
</widget>
|
13
|
+
</ui>
|
14
|
+
"""
|
15
|
+
|
16
|
+
|
17
|
+
class SignalLabelPlugin(QDesignerCustomWidgetInterface): # pragma: no cover
|
18
|
+
def __init__(self):
|
19
|
+
super().__init__()
|
20
|
+
self._form_editor = None
|
21
|
+
|
22
|
+
def createWidget(self, parent):
|
23
|
+
t = SignalLabel(parent)
|
24
|
+
return t
|
25
|
+
|
26
|
+
def domXml(self):
|
27
|
+
return DOM_XML
|
28
|
+
|
29
|
+
def group(self):
|
30
|
+
return "BEC Utils"
|
31
|
+
|
32
|
+
def icon(self):
|
33
|
+
return designer_material_icon(SignalLabel.ICON_NAME)
|
34
|
+
|
35
|
+
def includeFile(self):
|
36
|
+
return "signal_label"
|
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 "SignalLabel"
|
49
|
+
|
50
|
+
def toolTip(self):
|
51
|
+
return "Display the live value of any signal"
|
52
|
+
|
53
|
+
def whatsThis(self):
|
54
|
+
return self.toolTip()
|
@@ -2,11 +2,11 @@
|
|
2
2
|
.gitlab-ci.yml,sha256=1nMYldzVk0tFkBWYTcUjumOrdSADASheWOAc0kOFDYs,9509
|
3
3
|
.pylintrc,sha256=eeY8YwSI74oFfq6IYIbCqnx3Vk8ZncKaatv96n_Y8Rs,18544
|
4
4
|
.readthedocs.yaml,sha256=ivqg3HTaOxNbEW3bzWh9MXAkrekuGoNdj0Mj3SdRYuw,639
|
5
|
-
CHANGELOG.md,sha256=
|
5
|
+
CHANGELOG.md,sha256=OSzHSaLDu5mXNSmpwp2ap-7qZ1f9GBHYVpGFP2lud3c,290774
|
6
6
|
LICENSE,sha256=Daeiu871NcAp8uYi4eB_qHgvypG-HX0ioRQyQxFwjeg,1531
|
7
|
-
PKG-INFO,sha256=
|
7
|
+
PKG-INFO,sha256=7m3lNNzWQOJNlrFeOIh5CNZty3XmjTVzlF26SB9hvnw,1273
|
8
8
|
README.md,sha256=oY5Jc1uXehRASuwUJ0umin2vfkFh7tHF-LLruHTaQx0,3560
|
9
|
-
pyproject.toml,sha256=
|
9
|
+
pyproject.toml,sha256=B8K6rKqQOCYlyMtMbH0kkOBNe3pCGvWk0X0EUsCpCrs,2902
|
10
10
|
.git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
|
11
11
|
.github/pull_request_template.md,sha256=F_cJXzooWMFgMGtLK-7KeGcQt0B4AYFse5oN0zQ9p6g,801
|
12
12
|
.github/ISSUE_TEMPLATE/bug_report.yml,sha256=WdRnt7HGxvsIBLzhkaOWNfg8IJQYa_oV9_F08Ym6znQ,1081
|
@@ -35,7 +35,7 @@ bec_widgets/assets/app_icons/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqg
|
|
35
35
|
bec_widgets/assets/app_icons/ui_loader_tile.png,sha256=qSK3XHqvnAVGV9Q0ulORcGFbXJ9LDq2uz8l9uTtMsNk,1812476
|
36
36
|
bec_widgets/assets/app_icons/widget_launch_tile.png,sha256=bWsICHFfSe9-ESUj3AwlE95dDOea-f6M-s9fBapsxB4,2252911
|
37
37
|
bec_widgets/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
38
|
-
bec_widgets/cli/client.py,sha256=
|
38
|
+
bec_widgets/cli/client.py,sha256=Pl93U3IyN5OisaEDCrS2ytY5CppRfuyIiCppXNMf8yg,96703
|
39
39
|
bec_widgets/cli/client_utils.py,sha256=F2hyt--jL53bN8NoWifNUMqwwx5FbpS6I1apERdTRzM,18114
|
40
40
|
bec_widgets/cli/generate_cli.py,sha256=K_wMxo2XBUn92SnY3dSrlyUn8ax6Y20QBGCuP284DsQ,10986
|
41
41
|
bec_widgets/cli/server.py,sha256=h7QyBOOGjyrP_fxJIIOSEMc4E06cLG0JyaofjNV6oCA,5671
|
@@ -62,7 +62,7 @@ bec_widgets/tests/utils.py,sha256=DSzi6Z70fospjfyx0Uz5bWIDwaAzKbzcHfWPW0YyxzQ,71
|
|
62
62
|
bec_widgets/utils/__init__.py,sha256=1930ji1Jj6dVuY81Wd2kYBhHYNV-2R0bN_L4o9zBj1U,533
|
63
63
|
bec_widgets/utils/bec_connector.py,sha256=ATOSyZqryn1QHPc7aotiDnUtzFhlj_gmcukMT_pqjHQ,19272
|
64
64
|
bec_widgets/utils/bec_designer.py,sha256=ehNl_i743rijmhPiIGNd1bihE7-l4oJzTVoa4yjPjls,5426
|
65
|
-
bec_widgets/utils/bec_dispatcher.py,sha256=
|
65
|
+
bec_widgets/utils/bec_dispatcher.py,sha256=qYyd0SjCCUDwihxUFYzlKVxvZwSqQpDDPxF7_xt-sz0,9948
|
66
66
|
bec_widgets/utils/bec_plugin_helper.py,sha256=tLXEyzh0LWuRp-1XhJg32m-hUSLfRStC0YRUWKdhY5Q,3565
|
67
67
|
bec_widgets/utils/bec_signal_proxy.py,sha256=Yc08fdBEDABrowwNPSngT9-28R8FD4ml7oTL6BoMyEE,3263
|
68
68
|
bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
|
@@ -177,7 +177,7 @@ bec_widgets/widgets/control/device_control/positioner_group/register_positioner_
|
|
177
177
|
bec_widgets/widgets/control/device_input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
178
178
|
bec_widgets/widgets/control/device_input/base_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
179
179
|
bec_widgets/widgets/control/device_input/base_classes/device_input_base.py,sha256=r4DwWQz2wwNQ3Uswzdy12MGycV7pFrE_Zv4h_2G5IRA,15915
|
180
|
-
bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.py,sha256=
|
180
|
+
bec_widgets/widgets/control/device_input/base_classes/device_signal_input_base.py,sha256=wLEzPfEqaCPL3EpvMgFL5aZqSwuGj1OEkiyKaOQ7M1I,9330
|
181
181
|
bec_widgets/widgets/control/device_input/device_combobox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
182
182
|
bec_widgets/widgets/control/device_input/device_combobox/device_combo_box.pyproject,sha256=wI2eXR5ky_IM9-BCHJnH_9CEqYcZwIuLcgitSEr8OJU,40
|
183
183
|
bec_widgets/widgets/control/device_input/device_combobox/device_combo_box_plugin.py,sha256=E8LD9T4O2w621q25uHqBqZLDiQ6zpMR25ZDuf51jrPw,1434
|
@@ -192,7 +192,7 @@ bec_widgets/widgets/control/device_input/signal_combobox/__init__.py,sha256=47DE
|
|
192
192
|
bec_widgets/widgets/control/device_input/signal_combobox/register_signal_combo_box.py,sha256=VEdFRUfLph7JE2arcnzHw8etsE-4wZkwyzlNLMJBsZk,526
|
193
193
|
bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box.pyproject,sha256=xod6iyRD-WD0Uk6LWXjSxFJCQy-831pvTkKcw2FAdnM,33
|
194
194
|
bec_widgets/widgets/control/device_input/signal_combobox/signal_combo_box_plugin.py,sha256=sstqm2KtyR5wwOIYJRbzOqHMq5_9ExKP-YS5qV5ACrA,1373
|
195
|
-
bec_widgets/widgets/control/device_input/signal_combobox/signal_combobox.py,sha256=
|
195
|
+
bec_widgets/widgets/control/device_input/signal_combobox/signal_combobox.py,sha256=vM4PsYDl8RBHb9g083fRpeUZZkW1u1m7uXfaVMGUpyY,4869
|
196
196
|
bec_widgets/widgets/control/device_input/signal_line_edit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
197
197
|
bec_widgets/widgets/control/device_input/signal_line_edit/register_signal_line_edit.py,sha256=aQLTy_3gbji0vq5VvvAddHFimpwGGaMYJy5iGgX23aM,527
|
198
198
|
bec_widgets/widgets/control/device_input/signal_line_edit/signal_line_edit.py,sha256=-y_Oy8A7pQVQbzjvHznGxTX-wCisP-4l5py7WOm1_EY,6008
|
@@ -363,6 +363,10 @@ bec_widgets/widgets/utility/logpanel/log_panel.pyproject,sha256=2ncs1bsu-wICstR1
|
|
363
363
|
bec_widgets/widgets/utility/logpanel/log_panel_plugin.py,sha256=KY7eS1uGZzLYtDAdBv6S2mw8UjcDGVt3UklN_D5M06A,1250
|
364
364
|
bec_widgets/widgets/utility/logpanel/logpanel.py,sha256=tnjczAwtfe1biL-u9h9tntoQerWo3iLVD9RTSLOvd5o,20651
|
365
365
|
bec_widgets/widgets/utility/logpanel/register_log_panel.py,sha256=LFUE5JzCYvIwJQtTqZASLVAHYy3gO1nrHzPVH_kpCEY,470
|
366
|
+
bec_widgets/widgets/utility/signal_label/register_signal_label.py,sha256=wDB4Q3dSbZ51hsxnuB74oXdMRoLgDRd-XfhaomYY2OA,483
|
367
|
+
bec_widgets/widgets/utility/signal_label/signal_label.py,sha256=bht1zpHKxrslfFCknnLe3Q9FeF8Do0j6onWAiLXZan0,15875
|
368
|
+
bec_widgets/widgets/utility/signal_label/signal_label.pyproject,sha256=DXgt__AGnPCqXo5A92aTPH0SxbWlvgyNzKraWUuumWg,30
|
369
|
+
bec_widgets/widgets/utility/signal_label/signal_label_plugin.py,sha256=ZXR8oYl4NkPcXJ8pgDcdXcg3teB0MHtoNZoiGDmgCoU,1298
|
366
370
|
bec_widgets/widgets/utility/spinbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
367
371
|
bec_widgets/widgets/utility/spinbox/bec_spin_box.pyproject,sha256=RIg1SZuCltuZZuK1O4Djg0TpCInhoCw8KeqNaf1_K0A,33
|
368
372
|
bec_widgets/widgets/utility/spinbox/bec_spin_box_plugin.py,sha256=-XNrUAz1LZQPhJrH1sszfGrpBfpHUIfNO4bw7MPcc3k,1255
|
@@ -404,8 +408,8 @@ bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.py,sha256=O
|
|
404
408
|
bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.pyproject,sha256=Lbi9zb6HNlIq14k6hlzR-oz6PIFShBuF7QxE6d87d64,34
|
405
409
|
bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button_plugin.py,sha256=CzChz2SSETYsR8-36meqWnsXCT-FIy_J_xeU5coWDY8,1350
|
406
410
|
bec_widgets/widgets/utility/visual/dark_mode_button/register_dark_mode_button.py,sha256=rMpZ1CaoucwobgPj1FuKTnt07W82bV1GaSYdoqcdMb8,521
|
407
|
-
bec_widgets-2.
|
408
|
-
bec_widgets-2.
|
409
|
-
bec_widgets-2.
|
410
|
-
bec_widgets-2.
|
411
|
-
bec_widgets-2.
|
411
|
+
bec_widgets-2.9.0.dist-info/METADATA,sha256=7m3lNNzWQOJNlrFeOIh5CNZty3XmjTVzlF26SB9hvnw,1273
|
412
|
+
bec_widgets-2.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
413
|
+
bec_widgets-2.9.0.dist-info/entry_points.txt,sha256=dItMzmwA1wizJ1Itx15qnfJ0ZzKVYFLVJ1voxT7K7D4,214
|
414
|
+
bec_widgets-2.9.0.dist-info/licenses/LICENSE,sha256=Daeiu871NcAp8uYi4eB_qHgvypG-HX0ioRQyQxFwjeg,1531
|
415
|
+
bec_widgets-2.9.0.dist-info/RECORD,,
|
pyproject.toml
CHANGED
File without changes
|
File without changes
|
File without changes
|