bec-widgets 2.1.2__py3-none-any.whl → 2.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.
CHANGELOG.md CHANGED
@@ -1,6 +1,27 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## v2.2.0 (2025-05-09)
5
+
6
+ ### Features
7
+
8
+ - **launcher**: Add support for launching plugin widget
9
+ ([`1fb680a`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/1fb680abb40668e72007c245f32c80112466c46e))
10
+
11
+ ### Refactoring
12
+
13
+ - **launch_window**: Widget tile added
14
+ ([`b9e56c9`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/b9e56c96cbae561beb893cedb7d18e9b6a7bfc76))
15
+
16
+
17
+ ## v2.1.3 (2025-05-07)
18
+
19
+ ### Bug Fixes
20
+
21
+ - **bec-dispatcher**: Fix reference to boundmethods to avoid duplicated subscriptions
22
+ ([`cf59d31`](https://gitlab.psi.ch/bec/bec_widgets/-/commit/cf59d311132cd1a21f1893c19cc9f2a7e45101d0))
23
+
24
+
4
25
  ## v2.1.2 (2025-05-06)
5
26
 
6
27
  ### Bug Fixes
PKG-INFO CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bec_widgets
3
- Version: 2.1.2
3
+ Version: 2.2.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
@@ -2,10 +2,10 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  import xml.etree.ElementTree as ET
5
- from typing import TYPE_CHECKING
5
+ from typing import TYPE_CHECKING, Callable
6
6
 
7
7
  from bec_lib.logger import bec_logger
8
- from qtpy.QtCore import Qt, Signal
8
+ from qtpy.QtCore import Qt, Signal # type: ignore
9
9
  from qtpy.QtGui import QPainter, QPainterPath, QPixmap
10
10
  from qtpy.QtWidgets import (
11
11
  QApplication,
@@ -21,8 +21,10 @@ from qtpy.QtWidgets import (
21
21
 
22
22
  import bec_widgets
23
23
  from bec_widgets.cli.rpc.rpc_register import RPCRegister
24
+ from bec_widgets.utils.bec_plugin_helper import get_all_plugin_widgets
24
25
  from bec_widgets.utils.container_utils import WidgetContainerUtils
25
26
  from bec_widgets.utils.error_popups import SafeSlot
27
+ from bec_widgets.utils.name_utils import pascal_to_snake
26
28
  from bec_widgets.utils.plugin_utils import get_plugin_auto_updates
27
29
  from bec_widgets.utils.round_frame import RoundedFrame
28
30
  from bec_widgets.utils.toolbar import ModularToolBar
@@ -35,6 +37,8 @@ from bec_widgets.widgets.utility.visual.dark_mode_button.dark_mode_button import
35
37
  if TYPE_CHECKING: # pragma: no cover
36
38
  from qtpy.QtCore import QObject
37
39
 
40
+ from bec_widgets.utils.bec_widget import BECWidget
41
+
38
42
  logger = bec_logger.logger
39
43
  MODULE_PATH = os.path.dirname(bec_widgets.__file__)
40
44
 
@@ -141,6 +145,7 @@ class LaunchWindow(BECMainWindow):
141
145
  super().__init__(parent=parent, gui_id=gui_id, window_title=window_title, **kwargs)
142
146
 
143
147
  self.app = QApplication.instance()
148
+ self.tiles: dict[str, LaunchTile] = {}
144
149
 
145
150
  # Toolbar
146
151
  self.dark_mode_button = DarkModeButton(parent=self, toolbar=True)
@@ -156,58 +161,105 @@ class LaunchWindow(BECMainWindow):
156
161
  self.central_widget.layout = QHBoxLayout(self.central_widget)
157
162
  self.setCentralWidget(self.central_widget)
158
163
 
159
- self.tile_dock_area = LaunchTile(
164
+ self.register_tile(
165
+ name="dock_area",
160
166
  icon_path=os.path.join(MODULE_PATH, "assets", "app_icons", "bec_widgets_icon.png"),
161
167
  top_label="Get started",
162
168
  main_label="BEC Dock Area",
163
169
  description="Highly flexible and customizable dock area application with modular widgets.",
170
+ action_button=lambda: self.launch("dock_area"),
171
+ show_selector=False,
164
172
  )
165
- self.tile_dock_area.setFixedSize(*self.TILE_SIZE)
166
173
 
167
- self.tile_auto_update = LaunchTile(
174
+ self.available_auto_updates: dict[str, type[AutoUpdates]] = (
175
+ self._update_available_auto_updates()
176
+ )
177
+ self.register_tile(
178
+ name="auto_update",
168
179
  icon_path=os.path.join(MODULE_PATH, "assets", "app_icons", "auto_update.png"),
169
180
  top_label="Get automated",
170
181
  main_label="BEC Auto Update Dock Area",
171
182
  description="Dock area with auto update functionality for BEC widgets plotting.",
183
+ action_button=self._open_auto_update,
172
184
  show_selector=True,
185
+ selector_items=list(self.available_auto_updates.keys()) + ["Default"],
173
186
  )
174
- self.tile_auto_update.setFixedSize(*self.TILE_SIZE)
175
187
 
176
- self.tile_ui_file = LaunchTile(
188
+ self.register_tile(
189
+ name="custom_ui_file",
177
190
  icon_path=os.path.join(MODULE_PATH, "assets", "app_icons", "ui_loader_tile.png"),
178
191
  top_label="Get customized",
179
192
  main_label="Launch Custom UI File",
180
193
  description="GUI application with custom UI file.",
194
+ action_button=self._open_custom_ui_file,
195
+ show_selector=False,
181
196
  )
182
- self.tile_ui_file.setFixedSize(*self.TILE_SIZE)
183
-
184
- # Add tiles to the main layout
185
- self.central_widget.layout.addWidget(self.tile_dock_area)
186
- self.central_widget.layout.addWidget(self.tile_auto_update)
187
- self.central_widget.layout.addWidget(self.tile_ui_file)
188
197
 
189
- # hacky solution no time to waste
190
- self.tiles = [self.tile_dock_area, self.tile_auto_update, self.tile_ui_file]
198
+ # plugin widgets
199
+ self.available_widgets: dict[str, BECWidget] = get_all_plugin_widgets()
200
+ if self.available_widgets:
201
+ plugin_repo_name = next(iter(self.available_widgets.values())).__module__.split(".")[0]
202
+ plugin_repo_name = plugin_repo_name.removesuffix("_bec").upper()
203
+ self.register_tile(
204
+ name="widget",
205
+ icon_path=os.path.join(
206
+ MODULE_PATH, "assets", "app_icons", "widget_launch_tile.png"
207
+ ),
208
+ top_label="Get quickly started",
209
+ main_label=f"Launch a {plugin_repo_name} Widget",
210
+ description=f"GUI application with one widget from the {plugin_repo_name} repository.",
211
+ action_button=self._open_widget,
212
+ show_selector=True,
213
+ selector_items=list(self.available_widgets.keys()),
214
+ )
191
215
 
192
- # Connect signals
193
- self.tile_dock_area.action_button.clicked.connect(lambda: self.launch("dock_area"))
194
- self.tile_auto_update.action_button.clicked.connect(self._open_auto_update)
195
- self.tile_ui_file.action_button.clicked.connect(self._open_custom_ui_file)
196
216
  self._update_theme()
197
217
 
198
- # Auto updates
199
- self.available_auto_updates: dict[str, type[AutoUpdates]] = (
200
- self._update_available_auto_updates()
201
- )
202
- if self.tile_auto_update.selector is not None:
203
- self.tile_auto_update.selector.addItems(
204
- list(self.available_auto_updates.keys()) + ["Default"]
205
- )
206
-
207
218
  self.register = RPCRegister()
208
219
  self.register.callbacks.append(self._turn_off_the_lights)
209
220
  self.register.broadcast()
210
221
 
222
+ def register_tile(
223
+ self,
224
+ name: str,
225
+ icon_path: str | None = None,
226
+ top_label: str | None = None,
227
+ main_label: str | None = None,
228
+ description: str | None = None,
229
+ action_button: Callable | None = None,
230
+ show_selector: bool = False,
231
+ selector_items: list[str] | None = None,
232
+ ):
233
+ """
234
+ Register a tile in the launcher window.
235
+
236
+ Args:
237
+ name(str): The name of the tile.
238
+ icon_path(str): The path to the icon.
239
+ top_label(str): The top label of the tile.
240
+ main_label(str): The main label of the tile.
241
+ description(str): The description of the tile.
242
+ action_button(callable): The action to be performed when the button is clicked.
243
+ show_selector(bool): Whether to show a selector or not.
244
+ selector_items(list[str]): The items to be shown in the selector.
245
+ """
246
+
247
+ tile = LaunchTile(
248
+ icon_path=icon_path,
249
+ top_label=top_label,
250
+ main_label=main_label,
251
+ description=description,
252
+ show_selector=show_selector,
253
+ )
254
+ tile.setFixedSize(*self.TILE_SIZE)
255
+ if action_button:
256
+ tile.action_button.clicked.connect(action_button)
257
+ if show_selector and selector_items:
258
+ tile.selector.addItems(selector_items)
259
+ self.central_widget.layout.addWidget(tile)
260
+
261
+ self.tiles[name] = tile
262
+
211
263
  def launch(
212
264
  self,
213
265
  launch_script: str,
@@ -256,6 +308,12 @@ class LaunchWindow(BECMainWindow):
256
308
  auto_update = kwargs.pop("auto_update", None)
257
309
  return self._launch_auto_update(auto_update)
258
310
 
311
+ if launch_script == "widget":
312
+ widget = kwargs.pop("widget", None)
313
+ if widget is None:
314
+ raise ValueError("Widget name must be provided.")
315
+ return self._launch_widget(widget)
316
+
259
317
  launch = getattr(bw_launch, launch_script, None)
260
318
  if launch is None:
261
319
  raise ValueError(f"Launch script {launch_script} not found.")
@@ -273,6 +331,7 @@ class LaunchWindow(BECMainWindow):
273
331
  else:
274
332
  window = BECMainWindow()
275
333
  window.setCentralWidget(result_widget)
334
+ window.setWindowTitle(f"BEC - {result_widget.objectName()}")
276
335
  window.show()
277
336
  return result_widget
278
337
 
@@ -321,11 +380,28 @@ class LaunchWindow(BECMainWindow):
321
380
  window.show()
322
381
  return window
323
382
 
383
+ def _launch_widget(self, widget: type[BECWidget]) -> QWidget:
384
+ name = pascal_to_snake(widget.__name__)
385
+
386
+ WidgetContainerUtils.raise_for_invalid_name(name)
387
+
388
+ window = BECMainWindow()
389
+
390
+ widget_instance = widget(root_widget=True, object_name=name)
391
+ assert isinstance(widget_instance, QWidget)
392
+ QApplication.processEvents()
393
+
394
+ window.setCentralWidget(widget_instance)
395
+ window.resize(window.minimumSizeHint())
396
+ window.setWindowTitle(f"BEC - {widget_instance.objectName()}")
397
+ window.show()
398
+ return window
399
+
324
400
  def apply_theme(self, theme: str):
325
401
  """
326
402
  Change the theme of the application.
327
403
  """
328
- for tile in self.tiles:
404
+ for tile in self.tiles.values():
329
405
  tile.apply_theme(theme)
330
406
 
331
407
  super().apply_theme(theme)
@@ -334,14 +410,25 @@ class LaunchWindow(BECMainWindow):
334
410
  """
335
411
  Open the auto update window.
336
412
  """
337
- if self.tile_auto_update.selector is None:
413
+ if self.tiles["auto_update"].selector is None:
338
414
  auto_update = None
339
415
  else:
340
- auto_update = self.tile_auto_update.selector.currentText()
416
+ auto_update = self.tiles["auto_update"].selector.currentText()
341
417
  if auto_update == "Default":
342
418
  auto_update = None
343
419
  return self.launch("auto_update", auto_update=auto_update)
344
420
 
421
+ def _open_widget(self):
422
+ """
423
+ Open a widget from the available widgets.
424
+ """
425
+ if self.tiles["widget"].selector is None:
426
+ return
427
+ widget = self.tiles["widget"].selector.currentText()
428
+ if widget not in self.available_widgets:
429
+ raise ValueError(f"Widget {widget} not found in available widgets.")
430
+ return self.launch("widget", widget=self.available_widgets[widget])
431
+
345
432
  @SafeSlot(popup_error=True)
346
433
  def _open_custom_ui_file(self):
347
434
  """
@@ -4,8 +4,9 @@ import collections
4
4
  import random
5
5
  import string
6
6
  from collections.abc import Callable
7
- from typing import TYPE_CHECKING, Union
7
+ from typing import TYPE_CHECKING, DefaultDict, Hashable, Union
8
8
 
9
+ import louie
9
10
  import redis
10
11
  from bec_lib.client import BECClient
11
12
  from bec_lib.logger import bec_logger
@@ -41,15 +42,25 @@ class QtThreadSafeCallback(QObject):
41
42
  self.cb_info = cb_info
42
43
 
43
44
  self.cb = cb
45
+ self.cb_ref = louie.saferef.safe_ref(cb)
44
46
  self.cb_signal.connect(self.cb)
47
+ self.topics = set()
45
48
 
46
49
  def __hash__(self):
47
50
  # make 2 differents QtThreadSafeCallback to look
48
51
  # identical when used as dictionary keys, if the
49
52
  # callback is the same
50
- return f"{id(self.cb)}{self.cb_info}".__hash__()
53
+ return f"{id(self.cb_ref)}{self.cb_info}".__hash__()
54
+
55
+ def __eq__(self, other):
56
+ if not isinstance(other, QtThreadSafeCallback):
57
+ return False
58
+ return self.cb_ref == other.cb_ref and self.cb_info == other.cb_info
51
59
 
52
60
  def __call__(self, msg_content, metadata):
61
+ if self.cb_ref() is None:
62
+ # callback has been deleted
63
+ return
53
64
  self.cb_signal.emit(msg_content, metadata)
54
65
 
55
66
 
@@ -96,7 +107,7 @@ class BECDispatcher:
96
107
  cls,
97
108
  client=None,
98
109
  config: str | ServiceConfig | None = None,
99
- gui_id: str = None,
110
+ gui_id: str | None = None,
100
111
  *args,
101
112
  **kwargs,
102
113
  ):
@@ -109,7 +120,9 @@ class BECDispatcher:
109
120
  if self._initialized:
110
121
  return
111
122
 
112
- self._slots = collections.defaultdict(set)
123
+ self._registered_slots: DefaultDict[Hashable, QtThreadSafeCallback] = (
124
+ collections.defaultdict()
125
+ )
113
126
  self.client = client
114
127
 
115
128
  if self.client is None:
@@ -162,10 +175,13 @@ class BECDispatcher:
162
175
  topics (EndpointInfo | str | list): A topic or list of topics that can typically be acquired via bec_lib.MessageEndpoints
163
176
  cb_info (dict | None): A dictionary containing information about the callback. Defaults to None.
164
177
  """
165
- slot = QtThreadSafeCallback(cb=slot, cb_info=cb_info)
166
- self.client.connector.register(topics, cb=slot, **kwargs)
178
+ qt_slot = QtThreadSafeCallback(cb=slot, cb_info=cb_info)
179
+ if qt_slot not in self._registered_slots:
180
+ self._registered_slots[qt_slot] = qt_slot
181
+ qt_slot = self._registered_slots[qt_slot]
182
+ self.client.connector.register(topics, cb=qt_slot, **kwargs)
167
183
  topics_str, _ = self.client.connector._convert_endpointinfo(topics)
168
- self._slots[slot].update(set(topics_str))
184
+ qt_slot.topics.update(set(topics_str))
169
185
 
170
186
  def disconnect_slot(self, slot: Callable, topics: Union[str, list]):
171
187
  """
@@ -178,16 +194,16 @@ class BECDispatcher:
178
194
  # find the right slot to disconnect from ;
179
195
  # slot callbacks are wrapped in QtThreadSafeCallback objects,
180
196
  # but the slot we receive here is the original callable
181
- for connected_slot in self._slots:
197
+ for connected_slot in self._registered_slots.values():
182
198
  if connected_slot.cb == slot:
183
199
  break
184
200
  else:
185
201
  return
186
202
  self.client.connector.unregister(topics, cb=connected_slot)
187
203
  topics_str, _ = self.client.connector._convert_endpointinfo(topics)
188
- self._slots[connected_slot].difference_update(set(topics_str))
189
- if not self._slots[connected_slot]:
190
- del self._slots[connected_slot]
204
+ self._registered_slots[connected_slot].topics.difference_update(set(topics_str))
205
+ if not self._registered_slots[connected_slot].topics:
206
+ del self._registered_slots[connected_slot]
191
207
 
192
208
  def disconnect_topics(self, topics: Union[str, list]):
193
209
  """
@@ -198,11 +214,16 @@ class BECDispatcher:
198
214
  """
199
215
  self.client.connector.unregister(topics)
200
216
  topics_str, _ = self.client.connector._convert_endpointinfo(topics)
201
- for slot in list(self._slots.keys()):
202
- slot_topics = self._slots[slot]
203
- slot_topics.difference_update(set(topics_str))
204
- if not slot_topics:
205
- del self._slots[slot]
217
+
218
+ remove_slots = []
219
+ for connected_slot in self._registered_slots.values():
220
+ connected_slot.topics.difference_update(set(topics_str))
221
+
222
+ if not connected_slot.topics:
223
+ remove_slots.append(connected_slot)
224
+
225
+ for connected_slot in remove_slots:
226
+ self._registered_slots.pop(connected_slot, None)
206
227
 
207
228
  def disconnect_all(self, *args, **kwargs):
208
229
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bec_widgets
3
- Version: 2.1.2
3
+ Version: 2.2.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
@@ -2,11 +2,11 @@
2
2
  .gitlab-ci.yml,sha256=1nMYldzVk0tFkBWYTcUjumOrdSADASheWOAc0kOFDYs,9509
3
3
  .pylintrc,sha256=eeY8YwSI74oFfq6IYIbCqnx3Vk8ZncKaatv96n_Y8Rs,18544
4
4
  .readthedocs.yaml,sha256=aSOc277LqXcsTI6lgvm_JY80lMlr69GbPKgivua2cS0,603
5
- CHANGELOG.md,sha256=-NKbjMkJw5Y_NGzR5o_NSDUEBJk2lbLqIbrlq0EKzps,271406
5
+ CHANGELOG.md,sha256=Sa5kPhzCM6mhb3mpCJFWOM7wWAKVJKIdRg3gYqpfO2U,272001
6
6
  LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
7
- PKG-INFO,sha256=5sfOavPZf4UvV9AqHkiwbsUmR1ANqIBkHSMDcMKRdO0,1224
7
+ PKG-INFO,sha256=4CeB9Lxhqoz69h6jjuMsK8VZVTzKyPlHU0hkfbEKn8U,1224
8
8
  README.md,sha256=KgdKusjlvEvFtdNZCeDMO91y77MWK2iDcYMDziksOr4,2553
9
- pyproject.toml,sha256=BqRAPn18d8SH92IHfQeZcguEYPoXMIptC2JFn-Y-M6w,2568
9
+ pyproject.toml,sha256=ErqMD3R6tXqNkTKz_z6ikrXg7QAjTsNIFRCfRYyq6Fk,2568
10
10
  .git_hooks/pre-commit,sha256=n3RofIZHJl8zfJJIUomcMyYGFi_rwq4CC19z0snz3FI,286
11
11
  .gitlab/issue_templates/bug_report_template.md,sha256=gAuyEwl7XlnebBrkiJ9AqffSNOywmr8vygUFWKTuQeI,386
12
12
  .gitlab/issue_templates/documentation_update_template.md,sha256=FHLdb3TS_D9aL4CYZCjyXSulbaW5mrN2CmwTaeLPbNw,860
@@ -15,12 +15,13 @@ pyproject.toml,sha256=BqRAPn18d8SH92IHfQeZcguEYPoXMIptC2JFn-Y-M6w,2568
15
15
  bec_widgets/__init__.py,sha256=mZhbU6zfFt8-A7q_do74ie89budSevwpKZ6FKtEBdmo,170
16
16
  bec_widgets/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  bec_widgets/applications/bw_launch.py,sha256=4lngXb8Ht_cvQtCwjjbAoqPNuE2V0Ja5WIPHpwgjcRI,687
18
- bec_widgets/applications/launch_window.py,sha256=MGkhdLhNODDILuWgBkOhcxe92kWCLUfvemNE3029GDA,15594
18
+ bec_widgets/applications/launch_window.py,sha256=SKmbhquqggpF76e0wZKPtttotRkNQua3HxaxqFF4TWk,18918
19
19
  bec_widgets/assets/app_icons/BEC-General-App.png,sha256=hc2ktly53DZAbl_rE3cb-vdRa5gtdCmBEjfwm2y5P4g,447581
20
20
  bec_widgets/assets/app_icons/alignment_1d.png,sha256=5VouaWieb4lVv3wUBNHaO5ovUW2Fk25aTKYQzOWy0mg,2071069
21
21
  bec_widgets/assets/app_icons/auto_update.png,sha256=YKoAJTWAlWzreYvOm0BttDRFr29tulolZgKirRhAFlA,2197066
22
22
  bec_widgets/assets/app_icons/bec_widgets_icon.png,sha256=K8dgGwIjalDh9PRHUsSQBqgdX7a00nM3igZdc20pkYM,1747017
23
23
  bec_widgets/assets/app_icons/ui_loader_tile.png,sha256=qSK3XHqvnAVGV9Q0ulORcGFbXJ9LDq2uz8l9uTtMsNk,1812476
24
+ bec_widgets/assets/app_icons/widget_launch_tile.png,sha256=bWsICHFfSe9-ESUj3AwlE95dDOea-f6M-s9fBapsxB4,2252911
24
25
  bec_widgets/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
26
  bec_widgets/cli/client.py,sha256=2Z0ihxMONJChLuhMxaRon0gNsnbuhTz4jlsSg-xAKEk,80350
26
27
  bec_widgets/cli/client_utils.py,sha256=F2hyt--jL53bN8NoWifNUMqwwx5FbpS6I1apERdTRzM,18114
@@ -49,7 +50,7 @@ bec_widgets/tests/utils.py,sha256=GbQtN7qf9n-8FoAfNddZ4aAqA7oBo_hGAlnKELd6Xzw,69
49
50
  bec_widgets/utils/__init__.py,sha256=1930ji1Jj6dVuY81Wd2kYBhHYNV-2R0bN_L4o9zBj1U,533
50
51
  bec_widgets/utils/bec_connector.py,sha256=Ao_DN6oiHlpbVDHDK0RLpAgz2zDbhmwYee8yc3y7m2g,18875
51
52
  bec_widgets/utils/bec_designer.py,sha256=ehNl_i743rijmhPiIGNd1bihE7-l4oJzTVoa4yjPjls,5426
52
- bec_widgets/utils/bec_dispatcher.py,sha256=Zv2D0Ah0ZmXBNk8AbdHD2osHgTXqkvw51I_iCrSmVYA,8990
53
+ bec_widgets/utils/bec_dispatcher.py,sha256=y9EFIgU3JqIs7R10XnLh0I1_Skts9sbPe3ijOVJumYs,9837
53
54
  bec_widgets/utils/bec_plugin_helper.py,sha256=efg97QDAqhZYeqE1wk3vEgkFuhNewg4rvJrtB7mRCAE,3139
54
55
  bec_widgets/utils/bec_signal_proxy.py,sha256=Yc08fdBEDABrowwNPSngT9-28R8FD4ml7oTL6BoMyEE,3263
55
56
  bec_widgets/utils/bec_table.py,sha256=nA2b8ukSeUfquFMAxGrUVOqdrzMoDYD6O_4EYbOG2zk,717
@@ -377,8 +378,8 @@ bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.py,sha256=O
377
378
  bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button.pyproject,sha256=Lbi9zb6HNlIq14k6hlzR-oz6PIFShBuF7QxE6d87d64,34
378
379
  bec_widgets/widgets/utility/visual/dark_mode_button/dark_mode_button_plugin.py,sha256=CzChz2SSETYsR8-36meqWnsXCT-FIy_J_xeU5coWDY8,1350
379
380
  bec_widgets/widgets/utility/visual/dark_mode_button/register_dark_mode_button.py,sha256=rMpZ1CaoucwobgPj1FuKTnt07W82bV1GaSYdoqcdMb8,521
380
- bec_widgets-2.1.2.dist-info/METADATA,sha256=5sfOavPZf4UvV9AqHkiwbsUmR1ANqIBkHSMDcMKRdO0,1224
381
- bec_widgets-2.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
382
- bec_widgets-2.1.2.dist-info/entry_points.txt,sha256=dItMzmwA1wizJ1Itx15qnfJ0ZzKVYFLVJ1voxT7K7D4,214
383
- bec_widgets-2.1.2.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
384
- bec_widgets-2.1.2.dist-info/RECORD,,
381
+ bec_widgets-2.2.0.dist-info/METADATA,sha256=4CeB9Lxhqoz69h6jjuMsK8VZVTzKyPlHU0hkfbEKn8U,1224
382
+ bec_widgets-2.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
383
+ bec_widgets-2.2.0.dist-info/entry_points.txt,sha256=dItMzmwA1wizJ1Itx15qnfJ0ZzKVYFLVJ1voxT7K7D4,214
384
+ bec_widgets-2.2.0.dist-info/licenses/LICENSE,sha256=YRKe85CBRyP7UpEAWwU8_qSIyuy5-l_9C-HKg5Qm8MQ,1511
385
+ bec_widgets-2.2.0.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "bec_widgets"
7
- version = "2.1.2"
7
+ version = "2.2.0"
8
8
  description = "BEC Widgets"
9
9
  requires-python = ">=3.10"
10
10
  classifiers = [