1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-03-08 01:37:52 +01:00

fix(advanced_dock_area): remove widget from dock area by object name

This commit is contained in:
2026-01-13 12:05:55 +01:00
parent 22df7bb532
commit 8f44213ecc
4 changed files with 121 additions and 0 deletions

View File

@@ -113,6 +113,7 @@ class AdvancedDockArea(RPCBase):
title_buttons: "Mapping[str, bool] | Sequence[str] | str | None" = None,
show_settings_action: "bool | None" = None,
promote_central: "bool" = False,
object_name: "str | None" = None,
**widget_kwargs,
) -> "QWidget | CDockWidget | BECWidget":
"""
@@ -155,6 +156,25 @@ class AdvancedDockArea(RPCBase):
Delete all docks and their associated widgets.
"""
@rpc_call
def remove_widget(self, object_name: "str") -> "bool":
"""
Remove a widget from the dock area by its object name.
Args:
object_name: The object name of the widget to remove.
Returns:
bool: True if the widget was found and removed, False otherwise.
Raises:
ValueError: If no widget with the given object name is found.
Example:
>>> dock_area.remove_widget("my_widget")
True
"""
@rpc_call
def set_layout_ratios(
self,
@@ -1058,6 +1078,7 @@ class DockAreaWidget(RPCBase):
promote_central: "bool" = False,
dock_icon: "QIcon | None" = None,
apply_widget_icon: "bool" = True,
object_name: "str | None" = None,
**widget_kwargs,
) -> "QWidget | CDockWidget | BECWidget":
"""
@@ -1093,6 +1114,9 @@ class DockAreaWidget(RPCBase):
the widget's ``ICON_NAME`` attribute is used when available.
apply_widget_icon(bool): When False, skip automatically resolving the icon from
the widget's ``ICON_NAME`` (useful for callers who want no icon and do not pass one explicitly).
object_name(str | None): Optional object name to assign to the created widget.
**widget_kwargs: Additional keyword arguments passed to the widget constructor
when creating by type name.
Returns:
The widget instance by default, or the created `CDockWidget` when `return_dock` is True.
@@ -1134,6 +1158,25 @@ class DockAreaWidget(RPCBase):
Delete all docks and their associated widgets.
"""
@rpc_call
def remove_widget(self, object_name: "str") -> "bool":
"""
Remove a widget from the dock area by its object name.
Args:
object_name: The object name of the widget to remove.
Returns:
bool: True if the widget was found and removed, False otherwise.
Raises:
ValueError: If no widget with the given object name is found.
Example:
>>> dock_area.remove_widget("my_widget")
True
"""
@rpc_call
def set_layout_ratios(
self,
@@ -2723,6 +2766,7 @@ class MonacoDock(RPCBase):
promote_central: "bool" = False,
dock_icon: "QIcon | None" = None,
apply_widget_icon: "bool" = True,
object_name: "str | None" = None,
**widget_kwargs,
) -> "QWidget | CDockWidget | BECWidget":
"""
@@ -2758,6 +2802,9 @@ class MonacoDock(RPCBase):
the widget's ``ICON_NAME`` attribute is used when available.
apply_widget_icon(bool): When False, skip automatically resolving the icon from
the widget's ``ICON_NAME`` (useful for callers who want no icon and do not pass one explicitly).
object_name(str | None): Optional object name to assign to the created widget.
**widget_kwargs: Additional keyword arguments passed to the widget constructor
when creating by type name.
Returns:
The widget instance by default, or the created `CDockWidget` when `return_dock` is True.
@@ -2799,6 +2846,25 @@ class MonacoDock(RPCBase):
Delete all docks and their associated widgets.
"""
@rpc_call
def remove_widget(self, object_name: "str") -> "bool":
"""
Remove a widget from the dock area by its object name.
Args:
object_name: The object name of the widget to remove.
Returns:
bool: True if the widget was found and removed, False otherwise.
Raises:
ValueError: If no widget with the given object name is found.
Example:
>>> dock_area.remove_widget("my_widget")
True
"""
@rpc_call
def set_layout_ratios(
self,

View File

@@ -99,6 +99,7 @@ class AdvancedDockArea(DockAreaWidget):
"lock_workspace",
"attach_all",
"delete_all",
"remove_widget",
"set_layout_ratios",
"describe_layout",
"print_layout_structure",

View File

@@ -54,6 +54,7 @@ class DockAreaWidget(BECWidget, QWidget):
"widget_list",
"attach_all",
"delete_all",
"remove_widget",
"set_layout_ratios",
"describe_layout",
"print_layout_structure",
@@ -1375,6 +1376,31 @@ class DockAreaWidget(BECWidget, QWidget):
QtAds.DockWidgetArea.RightDockWidgetArea, dock, target
)
@SafeSlot(str)
def remove_widget(self, object_name: str) -> bool:
"""
Remove a widget from the dock area by its object name.
Args:
object_name: The object name of the widget to remove.
Returns:
bool: True if the widget was found and removed, False otherwise.
Raises:
ValueError: If no widget with the given object name is found.
Example:
>>> dock_area.remove_widget("my_widget")
True
"""
dock_map = self.dock_map()
dock = dock_map.get(object_name)
if dock is None:
raise ValueError(f"No widget found with object name '{object_name}'.")
self._delete_dock(dock)
return True
@SafeSlot()
def delete_all(self):
"""Delete all docks and their associated widgets."""

View File

@@ -250,6 +250,34 @@ class TestBasicDockArea:
basic_dock_area.delete_all()
assert basic_dock_area.dock_list() == []
def test_remove_widget_by_object_name(self, basic_dock_area, qtbot):
"""Test remove_widget removes widget by object name."""
panel_one = QWidget(parent=basic_dock_area)
panel_one.setObjectName("panel_one")
panel_two = QWidget(parent=basic_dock_area)
panel_two.setObjectName("panel_two")
basic_dock_area.new(panel_one, return_dock=True)
basic_dock_area.new(panel_two, return_dock=True)
assert len(basic_dock_area.dock_list()) == 2
assert "panel_one" in basic_dock_area.dock_map()
assert "panel_two" in basic_dock_area.dock_map()
# Remove panel_one
result = basic_dock_area.remove_widget("panel_one")
qtbot.wait(100)
assert result is True
assert len(basic_dock_area.dock_list()) == 1
assert "panel_one" not in basic_dock_area.dock_map()
assert "panel_two" in basic_dock_area.dock_map()
def test_remove_widget_raises_for_unknown_name(self, basic_dock_area):
"""Test remove_widget raises ValueError for non-existent widget."""
with pytest.raises(ValueError, match="No widget found with object name 'nonexistent'"):
basic_dock_area.remove_widget("nonexistent")
def test_manifest_serialization_includes_floating_geometry(
self, basic_dock_area, qtbot, tmp_path
):