mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-07-25 20:53:00 +02:00
fix(image): guard layer access during/after teardown
This commit is contained in:
@@ -1036,6 +1036,8 @@ class ImageBase(PlotBase):
|
||||
"""
|
||||
|
||||
# FIXME: this should be made more general
|
||||
if not self.layer_manager:
|
||||
return False
|
||||
return self.layer_manager["main"].image.autorange
|
||||
|
||||
@autorange.setter
|
||||
@@ -1056,6 +1058,8 @@ class ImageBase(PlotBase):
|
||||
enabled(bool): Whether to enable autorange.
|
||||
sync(bool): Whether to synchronize the autorange state across all layers.
|
||||
"""
|
||||
if not self.layer_manager:
|
||||
return
|
||||
for layer in self.layer_manager:
|
||||
if not layer.sync.autorange:
|
||||
continue
|
||||
@@ -1077,6 +1081,8 @@ class ImageBase(PlotBase):
|
||||
- "mean": Use the mean value of the image for autoranging.
|
||||
|
||||
"""
|
||||
if not self.layer_manager:
|
||||
return "mean"
|
||||
return self.layer_manager["main"].image.autorange_mode
|
||||
|
||||
@autorange_mode.setter
|
||||
@@ -1090,6 +1096,8 @@ class ImageBase(PlotBase):
|
||||
# for qt Designer
|
||||
if mode not in ["max", "mean"]:
|
||||
return
|
||||
if not self.layer_manager:
|
||||
return
|
||||
for layer in self.layer_manager:
|
||||
if not layer.sync.autorange_mode:
|
||||
continue
|
||||
@@ -1125,6 +1133,8 @@ class ImageBase(PlotBase):
|
||||
"""
|
||||
Synchronize the autorange switch with the current autorange state and mode if changed from outside.
|
||||
"""
|
||||
if not self.layer_manager:
|
||||
return
|
||||
action: SwitchableToolBarAction = self.toolbar.components.get_action("image_autorange") # type: ignore
|
||||
with action.signal_blocker():
|
||||
action.set_default_action(f"{self.layer_manager['main'].image.autorange_mode}")
|
||||
@@ -1133,7 +1143,7 @@ class ImageBase(PlotBase):
|
||||
def _sync_colorbar_levels(self):
|
||||
"""Immediately propagate current levels to the active colorbar."""
|
||||
|
||||
if not self._color_bar:
|
||||
if not self._color_bar or not self.layer_manager:
|
||||
return
|
||||
|
||||
total_vrange = (0, 0)
|
||||
|
||||
@@ -1456,4 +1456,26 @@ def test_adjust_image_buffer_coerces_list_and_scalar(qtbot, mocked_client):
|
||||
buf = view.adjust_image_buffer(image, [1, 2, 3]) # python list
|
||||
assert buf.shape == (1, 3)
|
||||
buf = view.adjust_image_buffer(image, np.array(42.0)) # 0-d scalar
|
||||
assert buf.shape[0] == 2
|
||||
assert buf.shape[0] == 2
|
||||
|
||||
|
||||
##############################################
|
||||
# Teardown safety
|
||||
##############################################
|
||||
|
||||
|
||||
def test_layer_accessors_safe_after_teardown(qtbot, mocked_client):
|
||||
"""Once layer_manager is gone (post-cleanup), signal-driven accessors must
|
||||
not raise. They used to subscript None or resurrect the 'main' layer."""
|
||||
view = create_widget(qtbot, Image, client=mocked_client)
|
||||
view.enable_full_colorbar = True
|
||||
view.layer_manager = None # simulate post-cleanup state
|
||||
|
||||
# None of these should raise:
|
||||
assert view.autorange is False
|
||||
assert view.autorange_mode == "mean"
|
||||
view.toggle_autorange(True, "mean")
|
||||
view._set_autorange(True)
|
||||
view.autorange_mode = "max"
|
||||
view._sync_autorange_switch()
|
||||
view._sync_colorbar_levels()
|
||||
|
||||
Reference in New Issue
Block a user