0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-14 03:31:50 +02:00

wip - namespace

This commit is contained in:
2025-03-13 10:09:17 +01:00
parent ba347e026a
commit 17f6dbb0d4
3 changed files with 242 additions and 477 deletions

View File

@ -50,27 +50,12 @@ class Widgets(str, enum.Enum):
class AbortButton(RPCBase): class AbortButton(RPCBase):
@property """A button that abort the scan."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
@ -230,14 +215,7 @@ class BECDock(RPCBase):
@property @property
@rpc_call @rpc_call
def _rpc_id(self) -> "str": def element_list(self) -> "list[BECWidget]":
"""
Get the RPC ID of the widget.
"""
@property
@rpc_call
def widget_list(self) -> "list[BECWidget]":
""" """
Get the widgets in the dock. Get the widgets in the dock.
@ -245,27 +223,58 @@ class BECDock(RPCBase):
widgets(list): The widgets in the dock. widgets(list): The widgets in the dock.
""" """
@property
@rpc_call
def elements(self) -> "dict[str, BECWidget]":
"""
Get the widgets in the dock.
Returns:
widgets(dict): The widgets in the dock.
"""
@rpc_call
def new(
self,
widget: "BECWidget | str",
name: "str | None" = None,
row: "int | None" = None,
col: "int" = 0,
rowspan: "int" = 1,
colspan: "int" = 1,
shift: "Literal['down', 'up', 'left', 'right']" = "down",
) -> "BECWidget":
"""
Add a widget to the dock.
Args:
widget(QWidget): The widget to add. It can not be BECDock or BECDockArea.
name(str): The name of the widget.
row(int): The row to add the widget to. If None, the widget will be added to the next available row.
col(int): The column to add the widget to.
rowspan(int): The number of rows the widget should span.
colspan(int): The number of columns the widget should span.
shift(Literal["down", "up", "left", "right"]): The direction to shift the widgets if the position is occupied.
"""
@rpc_call
def show(self):
"""
Show the dock.
"""
@rpc_call
def hide(self):
"""
Hide the dock.
"""
@rpc_call @rpc_call
def show_title_bar(self): def show_title_bar(self):
""" """
Hide the title bar of the dock. Hide the title bar of the dock.
""" """
@rpc_call
def hide_title_bar(self):
"""
Hide the title bar of the dock.
"""
@rpc_call
def get_widgets_positions(self) -> "dict":
"""
Get the positions of the widgets in the dock.
Returns:
dict: The positions of the widgets in the dock as dict -> {(row, col, rowspan, colspan):widget}
"""
@rpc_call @rpc_call
def set_title(self, title: "str"): def set_title(self, title: "str"):
""" """
@ -276,29 +285,13 @@ class BECDock(RPCBase):
""" """
@rpc_call @rpc_call
def add_widget( def hide_title_bar(self):
self,
widget: "BECWidget | str",
row=None,
col=0,
rowspan=1,
colspan=1,
shift: "Literal['down', 'up', 'left', 'right']" = "down",
) -> "BECWidget":
""" """
Add a widget to the dock. Hide the title bar of the dock.
Args:
widget(QWidget): The widget to add.
row(int): The row to add the widget to. If None, the widget will be added to the next available row.
col(int): The column to add the widget to.
rowspan(int): The number of rows the widget should span.
colspan(int): The number of columns the widget should span.
shift(Literal["down", "up", "left", "right"]): The direction to shift the widgets if the position is occupied.
""" """
@rpc_call @rpc_call
def list_eligible_widgets(self) -> "list": def available_widgets(self) -> "list":
""" """
List all widgets that can be added to the dock. List all widgets that can be added to the dock.
@ -307,23 +300,18 @@ class BECDock(RPCBase):
""" """
@rpc_call @rpc_call
def move_widget(self, widget: "QWidget", new_row: "int", new_col: "int"): def delete(self, widget_name: "str") -> "None":
"""
Move a widget to a new position in the layout.
Args:
widget(QWidget): The widget to move.
new_row(int): The new row to move the widget to.
new_col(int): The new column to move the widget to.
"""
@rpc_call
def remove_widget(self, widget_rpc_id: "str"):
""" """
Remove a widget from the dock. Remove a widget from the dock.
Args: Args:
widget_rpc_id(str): The ID of the widget to remove. widget_name(str): Delete the widget with the given name.
"""
@rpc_call
def delete_all(self):
"""
Remove all widgets from the dock.
""" """
@rpc_call @rpc_call
@ -346,21 +334,50 @@ class BECDock(RPCBase):
class BECDockArea(RPCBase): class BECDockArea(RPCBase):
@property
@rpc_call @rpc_call
def _config_dict(self) -> "dict": def new(
self,
name: "str | None" = None,
widget: "str | QWidget | None" = None,
widget_name: "str | None" = None,
position: "Literal['bottom', 'top', 'left', 'right', 'above', 'below']" = "bottom",
relative_to: "BECDock | None" = None,
closable: "bool" = True,
floating: "bool" = False,
row: "int | None" = None,
col: "int" = 0,
rowspan: "int" = 1,
colspan: "int" = 1,
) -> "BECDock":
""" """
Get the configuration of the widget. Add a dock to the dock area. Dock has QGridLayout as layout manager by default.
Args:
name(str): The name of the dock to be displayed and for further references. Has to be unique.
widget(str|QWidget|None): The widget to be added to the dock. While using RPC, only BEC RPC widgets from RPCWidgetHandler are allowed.
position(Literal["bottom", "top", "left", "right", "above", "below"]): The position of the dock.
relative_to(BECDock): The dock to which the new dock should be added relative to.
closable(bool): Whether the dock is closable.
floating(bool): Whether the dock is detached after creating.
row(int): The row of the added widget.
col(int): The column of the added widget.
rowspan(int): The rowspan of the added widget.
colspan(int): The colspan of the added widget.
Returns: Returns:
dict: The configuration of the widget. BECDock: The created dock.
""" """
@property
@rpc_call @rpc_call
def selected_device(self) -> "str": def show(self):
""" """
None Show all windows including floating docks.
"""
@rpc_call
def hide(self):
"""
Hide all windows including floating docks.
""" """
@property @property
@ -372,76 +389,35 @@ class BECDockArea(RPCBase):
dock_dict(dict): The docks in the dock area. dock_dict(dict): The docks in the dock area.
""" """
@property
@rpc_call @rpc_call
def save_state(self) -> "dict": def panel_list(self) -> "list[BECDock]":
""" """
Save the state of the dock area. Get the docks in the dock area.
Returns: Returns:
dict: The state of the dock area. list: The docks in the dock area.
""" """
@rpc_call @rpc_call
def remove_dock(self, name: "str"): def delete(self, dock_name: "str"):
""" """
Remove a dock by name and ensure it is properly closed and cleaned up. Delete a dock by name.
Args: Args:
name(str): The name of the dock to remove. dock_name(str): The name of the dock to delete.
""" """
@rpc_call @rpc_call
def restore_state( def delete_all(self) -> "None":
self, state: "dict" = None, missing: "Literal['ignore', 'error']" = "ignore", extra="bottom"
):
""" """
Restore the state of the dock area. If no state is provided, the last state is restored. Delete all docks.
Args:
state(dict): The state to restore.
missing(Literal['ignore','error']): What to do if a dock is missing.
extra(str): Extra docks that are in the dockarea but that are not mentioned in state will be added to the bottom of the dockarea, unless otherwise specified by the extra argument.
""" """
@rpc_call @rpc_call
def add_dock( def remove(self) -> "None":
self,
name: "str" = None,
position: "Literal['bottom', 'top', 'left', 'right', 'above', 'below']" = None,
relative_to: "BECDock | None" = None,
closable: "bool" = True,
floating: "bool" = False,
prefix: "str" = "dock",
widget: "str | QWidget | None" = None,
row: "int" = None,
col: "int" = 0,
rowspan: "int" = 1,
colspan: "int" = 1,
) -> "BECDock":
""" """
Add a dock to the dock area. Dock has QGridLayout as layout manager by default. Remove the dock area.
Args:
name(str): The name of the dock to be displayed and for further references. Has to be unique.
position(Literal["bottom", "top", "left", "right", "above", "below"]): The position of the dock.
relative_to(BECDock): The dock to which the new dock should be added relative to.
closable(bool): Whether the dock is closable.
floating(bool): Whether the dock is detached after creating.
prefix(str): The prefix for the dock name if no name is provided.
widget(str|QWidget|None): The widget to be added to the dock. While using RPC, only BEC RPC widgets from RPCWidgetHandler are allowed.
row(int): The row of the added widget.
col(int): The column of the added widget.
rowspan(int): The rowspan of the added widget.
colspan(int): The colspan of the added widget.
Returns:
BECDock: The created dock.
"""
@rpc_call
def clear_all(self):
"""
Close all docks and remove all temp areas.
""" """
@rpc_call @rpc_call
@ -462,40 +438,35 @@ class BECDockArea(RPCBase):
Return all floating docks to the dock area. Return all floating docks to the dock area.
""" """
@rpc_call
def _get_all_rpc(self) -> "dict":
"""
Get all registered RPC objects.
"""
@property @property
@rpc_call @rpc_call
def temp_areas(self) -> "list": def selected_device(self) -> "str":
"""
Get the temporary areas in the dock area.
Returns:
list: The temporary areas in the dock area.
"""
@rpc_call
def show(self):
"""
Show all windows including floating docks.
"""
@rpc_call
def hide(self):
"""
Hide all windows including floating docks.
"""
@rpc_call
def delete(self):
""" """
None None
""" """
@rpc_call
def save_state(self) -> "dict":
"""
Save the state of the dock area.
Returns:
dict: The state of the dock area.
"""
@rpc_call
def restore_state(
self, state: "dict" = None, missing: "Literal['ignore', 'error']" = "ignore", extra="bottom"
):
"""
Restore the state of the dock area. If no state is provided, the last state is restored.
Args:
state(dict): The state to restore.
missing(Literal['ignore','error']): What to do if a dock is missing.
extra(str): Extra docks that are in the dockarea but that are not mentioned in state will be added to the bottom of the dockarea, unless otherwise specified by the extra argument.
"""
class BECFigure(RPCBase): class BECFigure(RPCBase):
@property @property
@ -1409,27 +1380,10 @@ class BECImageWidget(RPCBase):
class BECMainWindow(RPCBase): class BECMainWindow(RPCBase):
@property
@rpc_call @rpc_call
def _config_dict(self) -> "dict": def remove(self):
""" """
Get the configuration of the widget. Cleanup the BECConnector
Returns:
dict: The configuration of the widget.
"""
@rpc_call
def _get_all_rpc(self) -> "dict":
"""
Get all registered RPC objects.
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
@ -2230,6 +2184,8 @@ class BECPlotBase(RPCBase):
class BECProgressBar(RPCBase): class BECProgressBar(RPCBase):
"""A custom progress bar with smooth transitions. The displayed text can be customized using a template."""
@rpc_call @rpc_call
def set_value(self, value): def set_value(self, value):
""" """
@ -2281,52 +2237,22 @@ class BECProgressBar(RPCBase):
class BECQueue(RPCBase): class BECQueue(RPCBase):
@property """Widget to display the BEC queue."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class BECStatusBox(RPCBase): class BECStatusBox(RPCBase):
@property """An autonomous widget to display the status of BEC services."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
@ -2845,6 +2771,8 @@ class Curve(RPCBase):
class DapComboBox(RPCBase): class DapComboBox(RPCBase):
"""The DAPComboBox widget is an extension to the QComboBox with all avaialble DAP model from BEC."""
@rpc_call @rpc_call
def select_y_axis(self, y_axis: str): def select_y_axis(self, y_axis: str):
""" """
@ -2883,156 +2811,66 @@ class DarkModeButton(RPCBase):
class DeviceBrowser(RPCBase): class DeviceBrowser(RPCBase):
@property
@rpc_call @rpc_call
def _config_dict(self) -> "dict": def remove(self):
""" """
Get the configuration of the widget. Cleanup the BECConnector
Returns:
dict: The configuration of the widget.
"""
@rpc_call
def _get_all_rpc(self) -> "dict":
"""
Get all registered RPC objects.
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class DeviceComboBox(RPCBase): class DeviceComboBox(RPCBase):
@property """Combobox widget for device input with autocomplete for device names."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class DeviceInputBase(RPCBase): class DeviceInputBase(RPCBase):
@property """Mixin base class for device input widgets."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class DeviceLineEdit(RPCBase): class DeviceLineEdit(RPCBase):
@property """Line edit widget for device input with autocomplete for device names."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class DeviceSignalInputBase(RPCBase): class DeviceSignalInputBase(RPCBase):
@property """Mixin base class for device signal input widgets."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class LMFitDialog(RPCBase): class LMFitDialog(RPCBase):
@property """Dialog for displaying the fit summary and params for LMFit DAP processes"""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class LogPanel(RPCBase): class LogPanel(RPCBase):
"""Displays a log panel"""
@rpc_call @rpc_call
def set_plain_text(self, text: str) -> None: def set_plain_text(self, text: str) -> None:
""" """
@ -3095,6 +2933,8 @@ class PositionIndicator(RPCBase):
class PositionerBox(RPCBase): class PositionerBox(RPCBase):
"""Simple Widget to control a positioner in box form"""
@rpc_call @rpc_call
def set_positioner(self, positioner: "str | Positioner"): def set_positioner(self, positioner: "str | Positioner"):
""" """
@ -3106,6 +2946,8 @@ class PositionerBox(RPCBase):
class PositionerBox2D(RPCBase): class PositionerBox2D(RPCBase):
"""Simple Widget to control two positioners in box form"""
@rpc_call @rpc_call
def set_positioner_hor(self, positioner: "str | Positioner"): def set_positioner_hor(self, positioner: "str | Positioner"):
""" """
@ -3126,31 +2968,18 @@ class PositionerBox2D(RPCBase):
class PositionerBoxBase(RPCBase): class PositionerBoxBase(RPCBase):
@property """Contains some core logic for positioner box widgets"""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class PositionerControlLine(RPCBase): class PositionerControlLine(RPCBase):
"""A widget that controls a single device."""
@rpc_call @rpc_call
def set_positioner(self, positioner: "str | Positioner"): def set_positioner(self, positioner: "str | Positioner"):
""" """
@ -3162,6 +2991,8 @@ class PositionerControlLine(RPCBase):
class PositionerGroup(RPCBase): class PositionerGroup(RPCBase):
"""Simple Widget to control a positioner in box form"""
@rpc_call @rpc_call
def set_positioners(self, device_names: "str"): def set_positioners(self, device_names: "str"):
""" """
@ -3172,52 +3003,22 @@ class PositionerGroup(RPCBase):
class ResetButton(RPCBase): class ResetButton(RPCBase):
@property """A button that resets the scan queue."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class ResumeButton(RPCBase): class ResumeButton(RPCBase):
@property """A button that continue scan queue."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
@ -3501,131 +3302,56 @@ class RingProgressBar(RPCBase):
class ScanControl(RPCBase): class ScanControl(RPCBase):
@property
@rpc_call @rpc_call
def _config_dict(self) -> "dict": def remove(self):
""" """
Get the configuration of the widget. Cleanup the BECConnector
Returns:
dict: The configuration of the widget.
"""
@rpc_call
def _get_all_rpc(self) -> "dict":
"""
Get all registered RPC objects.
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class ScanMetadata(RPCBase): class ScanMetadata(RPCBase):
@property """Dynamically generates a form for inclusion of metadata for a scan. Uses the"""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class SignalComboBox(RPCBase): class SignalComboBox(RPCBase):
@property """Line edit widget for device input with autocomplete for device names."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class SignalLineEdit(RPCBase): class SignalLineEdit(RPCBase):
@property """Line edit widget for device input with autocomplete for device names."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class StopButton(RPCBase): class StopButton(RPCBase):
@property """A button that stops the current scan."""
@rpc_call
def _config_dict(self) -> "dict":
"""
Get the configuration of the widget.
Returns:
dict: The configuration of the widget.
"""
@rpc_call @rpc_call
def _get_all_rpc(self) -> "dict": def remove(self):
""" """
Get all registered RPC objects. Cleanup the BECConnector
"""
@property
@rpc_call
def _rpc_id(self) -> "str":
"""
Get the RPC ID of the widget.
""" """
class TextBox(RPCBase): class TextBox(RPCBase):
"""A widget that displays text in plain and HTML format"""
@rpc_call @rpc_call
def set_plain_text(self, text: str) -> None: def set_plain_text(self, text: str) -> None:
""" """
@ -3645,7 +3371,10 @@ class TextBox(RPCBase):
""" """
class VSCodeEditor(RPCBase): ... class VSCodeEditor(RPCBase):
"""A widget to display the VSCode editor."""
...
class Waveform(RPCBase): class Waveform(RPCBase):
@ -4060,6 +3789,8 @@ class Waveform(RPCBase):
class WebsiteWidget(RPCBase): class WebsiteWidget(RPCBase):
"""A simple widget to display a website"""
@rpc_call @rpc_call
def set_url(self, url: str) -> None: def set_url(self, url: str) -> None:
""" """

View File

@ -95,9 +95,21 @@ class {class_name}(RPCBase):"""
self.content += f""" self.content += f"""
class {class_name}(RPCBase):""" class {class_name}(RPCBase):"""
if cls.__doc__:
# We only want the first line of the docstring
# But skip the first line if it's a blank line
first_line = cls.__doc__.split("\n")[0]
if first_line:
class_docs = first_line
else:
class_docs = cls.__doc__.split("\n")[1]
self.content += f"""
\"\"\"{class_docs}\"\"\"
"""
if not cls.USER_ACCESS: if not cls.USER_ACCESS:
self.content += """... self.content += """...
""" """
for method in cls.USER_ACCESS: for method in cls.USER_ACCESS:
is_property_setter = False is_property_setter = False
obj = getattr(cls, method, None) obj = getattr(cls, method, None)

View File

@ -15,6 +15,7 @@ from bec_lib.utils.import_utils import lazy_import
from qtpy.QtCore import Qt, QTimer from qtpy.QtCore import Qt, QTimer
from redis.exceptions import RedisError from redis.exceptions import RedisError
from bec_widgets.cli.rpc import rpc_register
from bec_widgets.cli.rpc.rpc_register import RPCRegister from bec_widgets.cli.rpc.rpc_register import RPCRegister
from bec_widgets.qt_utils.error_popups import ErrorPopupUtility from bec_widgets.qt_utils.error_popups import ErrorPopupUtility
from bec_widgets.utils import BECDispatcher from bec_widgets.utils import BECDispatcher
@ -36,6 +37,8 @@ def rpc_exception_hook(err_func):
old_exception_hook = popup.custom_exception_hook old_exception_hook = popup.custom_exception_hook
# install err_func, if it is a callable # install err_func, if it is a callable
# IMPORTANT, Keep self here, because this method is overwriting the custom_exception_hook
# of the ErrorPopupUtility (popup instance) class.
def custom_exception_hook(self, exc_type, value, tb, **kwargs): def custom_exception_hook(self, exc_type, value, tb, **kwargs):
err_func({"error": popup.get_error_message(exc_type, value, tb)}) err_func({"error": popup.get_error_message(exc_type, value, tb)})
@ -56,14 +59,15 @@ class BECWidgetsCLIServer:
dispatcher: BECDispatcher = None, dispatcher: BECDispatcher = None,
client=None, client=None,
config=None, config=None,
gui_class: Union[BECFigure, BECDockArea] = BECFigure, gui_class: Union[BECFigure, BECDockArea] = BECDockArea,
gui_class_id: str = "bec",
) -> None: ) -> None:
self.status = messages.BECStatus.BUSY self.status = messages.BECStatus.BUSY
self.dispatcher = BECDispatcher(config=config) if dispatcher is None else dispatcher self.dispatcher = BECDispatcher(config=config) if dispatcher is None else dispatcher
self.client = self.dispatcher.client if client is None else client self.client = self.dispatcher.client if client is None else client
self.client.start() self.client.start()
self.gui_id = gui_id self.gui_id = gui_id
self.gui = gui_class(gui_id=self.gui_id) # register broadcast callback
self.rpc_register = RPCRegister() self.rpc_register = RPCRegister()
self.rpc_register.add_rpc(self.gui) self.rpc_register.add_rpc(self.gui)
@ -78,6 +82,8 @@ class BECWidgetsCLIServer:
self.status = messages.BECStatus.RUNNING self.status = messages.BECStatus.RUNNING
logger.success(f"Server started with gui_id: {self.gui_id}") logger.success(f"Server started with gui_id: {self.gui_id}")
# Create initial object -> BECFigure or BECDockArea
self.gui = gui_class(parent=None, name=gui_class_id)
def on_rpc_update(self, msg: dict, metadata: dict): def on_rpc_update(self, msg: dict, metadata: dict):
request_id = metadata.get("request_id") request_id = metadata.get("request_id")
@ -135,6 +141,9 @@ class BECWidgetsCLIServer:
if isinstance(obj, BECConnector): if isinstance(obj, BECConnector):
return { return {
"gui_id": obj.gui_id, "gui_id": obj.gui_id,
"name": (
obj._name if hasattr(obj, "_name") else obj.__class__.__name__
), # pylint: disable=protected-access
"widget_class": obj.__class__.__name__, "widget_class": obj.__class__.__name__,
"config": obj.config.model_dump(), "config": obj.config.model_dump(),
"__rpc__": True, "__rpc__": True,
@ -179,7 +188,12 @@ class SimpleFileLikeFromLogOutputFunc:
return return
def _start_server(gui_id: str, gui_class: Union[BECFigure, BECDockArea], config: str | None = None): def _start_server(
gui_id: str,
gui_class: Union[BECFigure, BECDockArea],
gui_class_id: str = "bec",
config: str | None = None,
):
if config: if config:
try: try:
config = json.loads(config) config = json.loads(config)
@ -196,7 +210,9 @@ def _start_server(gui_id: str, gui_class: Union[BECFigure, BECDockArea], config:
# service_name="BECWidgetsCLIServer", # service_name="BECWidgetsCLIServer",
# service_config=service_config.service_config, # service_config=service_config.service_config,
# ) # )
server = BECWidgetsCLIServer(gui_id=gui_id, config=service_config, gui_class=gui_class) server = BECWidgetsCLIServer(
gui_id=gui_id, config=service_config, gui_class=gui_class, gui_class_id=gui_class_id
)
return server return server
@ -217,6 +233,12 @@ def main():
type=str, type=str,
help="Name of the gui class to be rendered. Possible values: \n- BECFigure\n- BECDockArea", help="Name of the gui class to be rendered. Possible values: \n- BECFigure\n- BECDockArea",
) )
parser.add_argument(
"--gui_class_id",
type=str,
default="bec",
help="The id of the gui class that is added to the QApplication",
)
parser.add_argument("--config", type=str, help="Config file or config string.") parser.add_argument("--config", type=str, help="Config file or config string.")
parser.add_argument("--hide", action="store_true", help="Hide on startup") parser.add_argument("--hide", action="store_true", help="Hide on startup")
@ -256,14 +278,14 @@ def main():
# store gui id within QApplication object, to make it available to all widgets # store gui id within QApplication object, to make it available to all widgets
app.gui_id = args.id app.gui_id = args.id
server = _start_server(args.id, gui_class, args.config) # args.id = "abff6"
server = _start_server(args.id, gui_class, args.gui_class_id, args.config)
win = BECMainWindow(gui_id=f"{server.gui_id}:window") win = BECMainWindow(gui_id=f"{server.gui_id}:window")
win.setAttribute(Qt.WA_ShowWithoutActivating) win.setAttribute(Qt.WA_ShowWithoutActivating)
win.setWindowTitle("BEC Widgets") win.setWindowTitle("BEC")
RPCRegister().add_rpc(win) RPCRegister().add_rpc(win)
gui = server.gui gui = server.gui
win.setCentralWidget(gui) win.setCentralWidget(gui)
if not args.hide: if not args.hide: