Source code for plotpy.tools.item

# -*- coding: utf-8 -*-# -*- coding: utf-8 -*-
#
# Licensed under the terms of the BSD 3-Clause
# (see plotpy/LICENSE for details)

"""Item tools"""

from __future__ import annotations

from typing import Callable

from guidata.qthelpers import get_std_icon
from qtpy import QtWidgets as QW

from plotpy.config import _
from plotpy.constants import ID_ITEMLIST
from plotpy.interfaces import ICurveItemType
from plotpy.items import (
    AnnotatedCircle,
    AnnotatedEllipse,
    AnnotatedObliqueRectangle,
    AnnotatedPolygon,
    AnnotatedRectangle,
    EllipseShape,
    ObliqueRectangleShape,
    RawImageItem,
    RectangleShape,
)
from plotpy.plot import BasePlot
from plotpy.tools.base import CommandTool, DefaultToolbarID, PanelTool
from plotpy.tools.curve import edit_curve_data, export_curve_data
from plotpy.tools.image import edit_image_data, export_image_data
from plotpy.tools.misc import OpenFileTool


class ItemManipulationBaseTool(CommandTool):
    """Base class for item manipulation tools."""

    TITLE: str | None = None
    ICON: str | None = None
    TIP: str | None = None

    def __init__(
        self,
        manager,
        toolbar_id: str | type[DefaultToolbarID] | None,
        curve_func: Callable,
        image_func: Callable,
    ):
        """
        Initialize the ItemManipulationBaseTool.

        Args:
            manager: The plot manager.
            toolbar_id: ID of the toolbar to which this tool belongs.
            curve_func: Callback function for curve items.
            image_func: Callback function for image items.
        """
        super().__init__(
            manager, self.TITLE, icon=self.ICON, tip=self.TIP, toolbar_id=toolbar_id
        )
        self.curve_func = curve_func
        self.image_func = image_func

    def get_supported_items(self, plot: BasePlot) -> list:
        """
        Get supported items from the plot.

        Args:
            plot: Plot instance

        Returns:
            List of supported plot items
        """
        all_items = [
            item
            for item in plot.get_items(item_type=ICurveItemType)
            if not item.is_empty()
        ]

        all_items += [
            item
            for item in plot.get_items()
            if isinstance(item, RawImageItem) and not item.is_empty()
        ]
        if len(all_items) == 1:
            return all_items
        else:
            return [item for item in all_items if item in plot.get_selected_items()]

    def update_status(self, plot: BasePlot) -> None:
        """
        Update the status of the tool.

        Args:
            plot: Plot instance
        """
        self.action.setEnabled(len(self.get_supported_items(plot)) > 0)

    def activate_command(self, plot: BasePlot, checked: bool) -> None:
        """
        Activate tool command.

        Args:
            plot: Plot instance
            checked: Whether the tool is checked
        """
        for item in self.get_supported_items(plot):
            if ICurveItemType in item.types():
                self.curve_func(item)
            else:
                self.image_func(item)
        plot.replot()


[docs] class EditItemDataTool(ItemManipulationBaseTool): """Tool for editing item data.""" TITLE: str = _("Edit data...") ICON: str = "arredit.png" def __init__(self, manager, toolbar_id: str | type[DefaultToolbarID] | None = None): """ Initialize the EditItemDataTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__( manager, toolbar_id, curve_func=edit_curve_data, image_func=edit_image_data )
[docs] def get_supported_items(self, plot: BasePlot) -> list: """ Get supported items from the plot. Args: plot: Plot instance Returns: List of supported plot items """ items = super().get_supported_items(plot) # Read-only items are not editable, obviously return [item for item in items if not item.is_readonly()]
[docs] class ExportItemDataTool(ItemManipulationBaseTool): """Tool for exporting item data.""" TITLE: str = _("Export data...") ICON: str = "export.png" def __init__(self, manager, toolbar_id: str | type[DefaultToolbarID] | None = None): """ Initialize the ExportItemDataTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__( manager, toolbar_id, curve_func=export_curve_data, image_func=export_image_data, )
[docs] class ItemCenterTool(CommandTool): """Tool for centering items.""" def __init__(self, manager, toolbar_id: str | type[DefaultToolbarID] | None = None): """ Initialize the ItemCenterTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__( manager, _("Center items"), "center.png", toolbar_id=toolbar_id )
[docs] def get_supported_items(self, plot: BasePlot) -> list: """ Get supported items from the plot. Args: plot: Plot instance Returns: List of supported plot items """ item_types = ( RectangleShape, EllipseShape, ObliqueRectangleShape, AnnotatedRectangle, AnnotatedEllipse, AnnotatedObliqueRectangle, AnnotatedCircle, AnnotatedPolygon, ) # Read-only items are not editable, obviously return [ item for item in plot.get_selected_items(z_sorted=True) if isinstance(item, item_types) and not item.is_readonly() ]
[docs] def update_status(self, plot: BasePlot) -> None: """ Update the status of the tool. Args: plot: Plot instance """ self.action.setEnabled(len(self.get_supported_items(plot)) > 1)
[docs] def activate_command(self, plot: BasePlot, checked: bool) -> None: """ Activate tool command. Args: plot: Plot instance checked: Whether the tool is checked """ items = self.get_supported_items(plot) xc0, yc0 = items.pop(-1).get_center() for item in items: xc, yc = item.get_center() item.move_with_selection(xc0 - xc, yc0 - yc) plot.replot()
[docs] class DeleteItemTool(CommandTool): """ """ def __init__(self, manager, toolbar_id: str | type[DefaultToolbarID] | None = None): """ Initialize the DeleteItemTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__(manager, _("Remove"), "trash.png", toolbar_id=toolbar_id)
[docs] def get_supported_items(self, plot: BasePlot) -> list: """ Get supported items from the plot. Args: plot: Plot instance Returns: List of supported plot items """ return [item for item in plot.get_selected_items() if not item.is_readonly()]
[docs] def update_status(self, plot: BasePlot) -> None: """ Update the status of the tool. Args: plot: Plot instance """ self.action.setEnabled(len(self.get_supported_items(plot)) > 0)
[docs] def activate_command(self, plot: BasePlot, checked: bool) -> None: """ Activate tool command. Args: plot: Plot instance checked: Whether the tool is checked """ items = self.get_supported_items(plot) if len(items) == 1: message = _("Do you really want to remove this item?") else: message = _("Do you really want to remove selected items?") answer = QW.QMessageBox.warning( plot, _("Remove"), message, QW.QMessageBox.Yes | QW.QMessageBox.No ) if answer == QW.QMessageBox.Yes: plot.del_items(items) plot.replot()
[docs] class SaveItemsTool(CommandTool): """ """ def __init__( self, manager, toolbar_id: str | type[DefaultToolbarID] = DefaultToolbarID ): """ Initialize the SaveItemsTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__( manager, _("Save items"), get_std_icon("DialogSaveButton", 16), toolbar_id=toolbar_id, )
[docs] def activate_command(self, plot: BasePlot, checked: bool) -> None: """ Activate tool command. Args: plot: Plot instance checked: Whether the tool is checked """ fname, _f = QW.QFileDialog.getSaveFileName( plot, _("Save items as"), _("untitled"), "{} (*.gui)".format(_("plotpy items")), ) if not fname: return with open(fname, "wb") as itemfile: plot.save_items(itemfile, selected=True)
[docs] class LoadItemsTool(OpenFileTool): """ """ def __init__( self, manager, toolbar_id: str | type[DefaultToolbarID] = DefaultToolbarID ): """ Initialize the LoadItemsTool. Args: manager: The plot manager. toolbar_id: ID of the toolbar to which this tool belongs. """ super().__init__( manager, title=_("Load items"), formats="*.gui", toolbar_id=toolbar_id )
[docs] def activate_command(self, plot: BasePlot, checked: bool) -> None: """ Activate tool command. Args: plot: Plot instance checked: Whether the tool is checked """ filename = self.get_filename(plot) if not filename: return with open(filename, "rb") as itemfile: plot.restore_items(itemfile) plot.replot()
[docs] class ItemListPanelTool(PanelTool): """Tool for managing the item list panel.""" panel_name: str = _("Item list") panel_id: str = ID_ITEMLIST