diff --git a/bec_widgets/utils/plot_indicator_items.py b/bec_widgets/utils/plot_indicator_items.py index 7671b4d6..45390912 100644 --- a/bec_widgets/utils/plot_indicator_items.py +++ b/bec_widgets/utils/plot_indicator_items.py @@ -171,7 +171,7 @@ class BECArrowItem(BECIndicatorItem): def __init__(self, plot_item: pg.PlotItem = None, parent=None): super().__init__(plot_item=plot_item, parent=parent) - self.arrow_item = pg.ArrowItem(parent=parent) + self.arrow_item = pg.ArrowItem() self.arrow_item.skip_auto_range = True self._pos = (0, 0) self.arrow_item.setVisible(False) diff --git a/bec_widgets/widgets/plots_next_gen/plot_base.py b/bec_widgets/widgets/plots_next_gen/plot_base.py index 5779bf63..bdf0bafa 100644 --- a/bec_widgets/widgets/plots_next_gen/plot_base.py +++ b/bec_widgets/widgets/plots_next_gen/plot_base.py @@ -16,6 +16,7 @@ from bec_widgets.qt_utils.toolbar import MaterialIconAction, ModularToolBar, Too from bec_widgets.utils import ConnectionConfig, Crosshair, EntryValidator from bec_widgets.utils.bec_widget import BECWidget from bec_widgets.utils.fps_counter import FPSCounter +from bec_widgets.utils.plot_indicator_items import BECArrowItem, BECTickItem from bec_widgets.utils.widget_state_manager import WidgetStateManager from bec_widgets.widgets.containers.layout_manager.layout_manager import LayoutManagerWidget from bec_widgets.widgets.plots_next_gen.setting_menus.axis_settings import AxisSettings @@ -115,6 +116,10 @@ class PlotBase(BECWidget, QWidget): self._user_y_label = "" self._y_label_suffix = "" + # Plot Indicator Items + self.tick_item = BECTickItem(parent=self, plot_item=self.plot_item) + self.arrow_item = BECArrowItem(parent=self, plot_item=self.plot_item) + self._init_ui() self._connect_to_theme_change() @@ -967,6 +972,8 @@ class PlotBase(BECWidget, QWidget): def cleanup(self): self.unhook_crosshair() self.unhook_fps_monitor(delete_label=True) + self.tick_item.cleanup() + self.arrow_item.cleanup() if self.axis_settings_dialog is not None: self.axis_settings_dialog.close() self.axis_settings_dialog = None diff --git a/tests/unit_tests/test_utils_plot_indicators.py b/tests/unit_tests/test_utils_plot_indicators.py index 9c3037e5..4f61bbc3 100644 --- a/tests/unit_tests/test_utils_plot_indicators.py +++ b/tests/unit_tests/test_utils_plot_indicators.py @@ -1,114 +1,111 @@ -# TODO temporary disabled until migrate tick and arrow items to new system -# import pytest -# from qtpy.QtCore import QPointF -# -# from bec_widgets.widgets.containers.figure import BECFigure -# -# from .client_mocks import mocked_client -# -# -# @pytest.fixture -# def plot_widget_with_arrow_item(qtbot, mocked_client): -# widget = BECFigure(client=mocked_client()) -# qtbot.addWidget(widget) -# qtbot.waitExposed(widget) -# waveform = widget.plot() -# -# yield waveform.arrow_item, waveform.plot_item -# -# -# @pytest.fixture -# def plot_widget_with_tick_item(qtbot, mocked_client): -# widget = BECFigure(client=mocked_client()) -# qtbot.addWidget(widget) -# qtbot.waitExposed(widget) -# waveform = widget.plot() -# -# yield waveform.tick_item, waveform.plot_item -# -# -# def test_arrow_item_add_to_plot(plot_widget_with_arrow_item): -# """Test the add_to_plot method""" -# arrow_item, plot_item = plot_widget_with_arrow_item -# assert arrow_item.plot_item is not None -# assert arrow_item.plot_item.items == [] -# arrow_item.add_to_plot() -# assert arrow_item.plot_item.items == [arrow_item.arrow_item] -# arrow_item.remove_from_plot() -# -# -# def test_arrow_item_set_position(plot_widget_with_arrow_item): -# """Test the set_position method""" -# arrow_item, plot_item = plot_widget_with_arrow_item -# container = [] -# -# def signal_callback(tup: tuple): -# container.append(tup) -# -# arrow_item.add_to_plot() -# arrow_item.position_changed.connect(signal_callback) -# arrow_item.set_position(pos=(1, 1)) -# point = QPointF(1.0, 1.0) -# assert arrow_item.arrow_item.pos() == point -# arrow_item.set_position(pos=(2, 2)) -# point = QPointF(2.0, 2.0) -# assert arrow_item.arrow_item.pos() == point -# assert container == [(1, 1), (2, 2)] -# arrow_item.remove_from_plot() -# -# -# def test_arrow_item_cleanup(plot_widget_with_arrow_item): -# """Test cleanup procedure""" -# arrow_item, plot_item = plot_widget_with_arrow_item -# arrow_item.add_to_plot() -# assert arrow_item.item_on_plot is True -# arrow_item.cleanup() -# assert arrow_item.plot_item.items == [] -# assert arrow_item.item_on_plot is False -# assert arrow_item.arrow_item is None -# -# -# def test_tick_item_add_to_plot(plot_widget_with_tick_item): -# """Test the add_to_plot method""" -# tick_item, plot_item = plot_widget_with_tick_item -# assert tick_item.plot_item is not None -# assert tick_item.plot_item.items == [] -# tick_item.add_to_plot() -# assert tick_item.plot_item.layout.itemAt(2, 1) == tick_item.tick_item -# assert tick_item.item_on_plot is True -# new_pos = plot_item.vb.geometry().bottom() -# pos = tick_item.tick.pos() -# new_pos = tick_item.tick_item.mapFromParent(QPointF(pos.x(), new_pos)) -# assert new_pos.y() == pos.y() -# tick_item.remove_from_plot() -# -# -# def test_tick_item_set_position(plot_widget_with_tick_item): -# """Test the set_position method""" -# tick_item, plot_item = plot_widget_with_tick_item -# container = [] -# -# def signal_callback(val: float): -# container.append(val) -# -# tick_item.add_to_plot() -# tick_item.position_changed.connect(signal_callback) -# -# tick_item.set_position(pos=1) -# assert tick_item._pos == 1 -# tick_item.set_position(pos=2) -# assert tick_item._pos == 2 -# assert container == [1.0, 2.0] -# tick_item.remove_from_plot() -# -# -# def test_tick_item_cleanup(plot_widget_with_tick_item): -# """Test cleanup procedure""" -# tick_item, plot_item = plot_widget_with_tick_item -# tick_item.add_to_plot() -# assert tick_item.item_on_plot is True -# tick_item.cleanup() -# ticks = getattr(tick_item.plot_item.layout.itemAt(3, 1), "ticks", None) -# assert ticks == None -# assert tick_item.item_on_plot is False -# assert tick_item.tick_item is None +import pytest +from qtpy.QtCore import QPointF + +from bec_widgets.widgets.plots_next_gen.waveform.waveform import Waveform + +from .client_mocks import mocked_client + + +@pytest.fixture +def plot_widget_with_arrow_item(qtbot, mocked_client): + widget = Waveform(client=mocked_client()) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + + yield widget.arrow_item, widget.plot_item + + +@pytest.fixture +def plot_widget_with_tick_item(qtbot, mocked_client): + widget = Waveform(client=mocked_client()) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + + yield widget.tick_item, widget.plot_item + + +def test_arrow_item_add_to_plot(plot_widget_with_arrow_item): + """Test the add_to_plot method""" + arrow_item, plot_item = plot_widget_with_arrow_item + assert arrow_item.plot_item is not None + assert arrow_item.plot_item.items == [] + arrow_item.add_to_plot() + assert arrow_item.plot_item.items == [arrow_item.arrow_item] + arrow_item.remove_from_plot() + + +def test_arrow_item_set_position(plot_widget_with_arrow_item): + """Test the set_position method""" + arrow_item, plot_item = plot_widget_with_arrow_item + container = [] + + def signal_callback(tup: tuple): + container.append(tup) + + arrow_item.add_to_plot() + arrow_item.position_changed.connect(signal_callback) + arrow_item.set_position(pos=(1, 1)) + point = QPointF(1.0, 1.0) + assert arrow_item.arrow_item.pos() == point + arrow_item.set_position(pos=(2, 2)) + point = QPointF(2.0, 2.0) + assert arrow_item.arrow_item.pos() == point + assert container == [(1, 1), (2, 2)] + arrow_item.remove_from_plot() + + +def test_arrow_item_cleanup(plot_widget_with_arrow_item): + """Test cleanup procedure""" + arrow_item, plot_item = plot_widget_with_arrow_item + arrow_item.add_to_plot() + assert arrow_item.item_on_plot is True + arrow_item.cleanup() + assert arrow_item.plot_item.items == [] + assert arrow_item.item_on_plot is False + assert arrow_item.arrow_item is None + + +def test_tick_item_add_to_plot(plot_widget_with_tick_item): + """Test the add_to_plot method""" + tick_item, plot_item = plot_widget_with_tick_item + assert tick_item.plot_item is not None + assert tick_item.plot_item.items == [] + tick_item.add_to_plot() + assert tick_item.plot_item.layout.itemAt(2, 1) == tick_item.tick_item + assert tick_item.item_on_plot is True + new_pos = plot_item.vb.geometry().bottom() + pos = tick_item.tick.pos() + new_pos = tick_item.tick_item.mapFromParent(QPointF(pos.x(), new_pos)) + assert new_pos.y() == pos.y() + tick_item.remove_from_plot() + + +def test_tick_item_set_position(plot_widget_with_tick_item): + """Test the set_position method""" + tick_item, plot_item = plot_widget_with_tick_item + container = [] + + def signal_callback(val: float): + container.append(val) + + tick_item.add_to_plot() + tick_item.position_changed.connect(signal_callback) + + tick_item.set_position(pos=1) + assert tick_item._pos == 1 + tick_item.set_position(pos=2) + assert tick_item._pos == 2 + assert container == [1.0, 2.0] + tick_item.remove_from_plot() + + +def test_tick_item_cleanup(plot_widget_with_tick_item): + """Test cleanup procedure""" + tick_item, plot_item = plot_widget_with_tick_item + tick_item.add_to_plot() + assert tick_item.item_on_plot is True + tick_item.cleanup() + ticks = getattr(tick_item.plot_item.layout.itemAt(3, 1), "ticks", None) + assert ticks == None + assert tick_item.item_on_plot is False + assert tick_item.tick_item is None