Skip to content

Commit

Permalink
add close (#283)
Browse files Browse the repository at this point in the history
  • Loading branch information
tlambert03 committed Sep 11, 2021
1 parent 8d47eba commit 3803ea5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 8 deletions.
3 changes: 3 additions & 0 deletions magicgui/backends/_qtpy/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def __init__(self, qwidg: QtW.QWidget):
self._event_filter = EventFilter()
self._qwidget.installEventFilter(self._event_filter)

def _mgui_close_widget(self):
self._qwidget.close()

def _mgui_get_visible(self):
return self._qwidget.isVisible()

Expand Down
4 changes: 4 additions & 0 deletions magicgui/widgets/_bases/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ def hide(self):
"""
self.visible = False

def close(self) -> None:
"""Close widget."""
self._widget._mgui_close_widget()

def render(self) -> np.ndarray:
"""Return an RGBA (MxNx4) numpy array bitmap of the rendered widget."""
return self._widget._mgui_render()
Expand Down
9 changes: 7 additions & 2 deletions magicgui/widgets/_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,17 @@ def __init__(self, **kwargs):
pass

@abstractmethod
def _mgui_get_visible(self):
def _mgui_close_widget(self) -> None:
"""Close widget."""
raise NotImplementedError()

@abstractmethod
def _mgui_get_visible(self) -> bool:
"""Get widget visibility."""
raise NotImplementedError()

@abstractmethod
def _mgui_set_visible(self, value: bool):
def _mgui_set_visible(self, value: bool) -> None:
"""Set widget visibility."""
raise NotImplementedError()

Expand Down
28 changes: 22 additions & 6 deletions tests/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
)
def test_widgets(WidgetClass):
"""Test that we can retrieve getters, setters, and signals for most Widgets."""
_ = WidgetClass()
wdg: widgets.Widget = WidgetClass()
wdg.close()


expectations = (
Expand All @@ -35,13 +36,16 @@ def test_widgets(WidgetClass):
@pytest.mark.parametrize("kwargs, expect_type", expectations)
def test_create_widget(kwargs, expect_type):
"""Test that various values get turned into widgets."""
assert isinstance(widgets.create_widget(**kwargs), expect_type)
wdg = widgets.create_widget(**kwargs)
assert isinstance(wdg, expect_type)
wdg.close()


# fmt: off
class MyBadWidget:
"""INCOMPLETE widget implementation and will error."""

def _mgui_close_widget(self): ... # noqa
def _mgui_get_visible(self): ... # noqa
def _mgui_set_visible(self): ... # noqa
def _mgui_get_enabled(self): ... # noqa
Expand Down Expand Up @@ -81,9 +85,9 @@ def test_custom_widget():
"""Test that create_widget works with arbitrary backend implementations."""
# by implementing the ValueWidgetProtocol, magicgui will know to wrap the above
# widget with a widgets._bases.ValueWidget
assert isinstance(
widgets.create_widget(1, widget_type=MyValueWidget), ValueWidget # type:ignore
)
wdg = widgets.create_widget(1, widget_type=MyValueWidget) # type:ignore
assert isinstance(wdg, ValueWidget)
wdg.close()


def test_custom_widget_fails():
Expand Down Expand Up @@ -142,7 +146,7 @@ def test_basic_widget_attributes():
with pytest.raises(KeyError):
widget.param_kind = "not a proper param type"
with pytest.raises(TypeError):
widget.param_kind = 1
widget.param_kind = 1 # type: ignore

assert repr(widget) == "SpinBox(value=1, annotation=None, name='my_name')"
assert widget.options == {
Expand All @@ -152,6 +156,7 @@ def test_basic_widget_attributes():
"enabled": False,
"visible": False,
}
widget.close()


def test_tooltip():
Expand Down Expand Up @@ -190,6 +195,7 @@ def test_container_widget():
del container[1:]
del container[-1]
assert not container
container.close()


def test_container_label_widths():
Expand All @@ -210,6 +216,7 @@ def _label_width():
before = _label_width()
container.append(labelb)
assert _label_width() > before
container.close()


def test_labeled_widget_container():
Expand All @@ -231,6 +238,7 @@ def test_labeled_widget_container():
assert not lw.visible
w1.label = "another label"
assert lw._label_widget.value == "another label"
container.close()


def test_visible_in_container():
Expand All @@ -249,6 +257,7 @@ def test_visible_in_container():
assert not w3.visible
w1.show()
assert w1.visible
container.close()


def test_delete_widget():
Expand Down Expand Up @@ -285,6 +294,7 @@ def test_unhashable_choice_data():
assert combo.choices == ([1, 2, 3], [1, 2, 5])
combo.choices = ("x", "y", "z")
assert combo.choices == ("x", "y", "z")
combo.close()


def test_bound_values():
Expand Down Expand Up @@ -463,6 +473,7 @@ def add(num1: int, num2: int) -> int:
assert isinstance(add._help_text_edit, widgets.TextEdit)
assert add._help_text_edit.value.startswith("Adds the given two numbers")
assert add._help_text_edit.read_only
add.close()


def test_range_widget():
Expand Down Expand Up @@ -519,6 +530,8 @@ def func(x: int, y: str):
assert not c2.visible
c2.show()
assert c2.visible and func.visible
c2.close()
assert not func.visible


def test_file_dialog_events():
Expand Down Expand Up @@ -576,6 +589,8 @@ def test_extreme_floats(WdgClass, value):
_value = 1 / value
wdg2 = WdgClass(value=_value, step=_value / 10, max=_value * 100)
assert round(wdg2.value / _value, 4) == 1.0
wdg.close()
wdg2.close()


@pytest.mark.parametrize("Cls", [widgets.ComboBox, widgets.RadioButtons])
Expand Down Expand Up @@ -621,6 +636,7 @@ def test_categorical_widgets_with_enums(Cls):
assert wdg.value == MyEnum.B
assert wdg.current_choice == "B"
assert wdg.choices == tuple(MyEnum.__members__.values())
wdg.close()


@pytest.mark.skipif(use_app().backend_name != "qt", reason="only on qt")
Expand Down

0 comments on commit 3803ea5

Please sign in to comment.