Source code for radioviz.tools.base_tool

#  Copyright 2025–2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""
Base tool definition for the radioviz application.

This module defines the base classes and structures used to implement tools
within the radioviz application framework. It provides the foundational
abstractions for creating tools that can be integrated into the main
application window, including support for analysis actions, context menu
actions, and dockable views.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Generic, Optional

from PySide6.QtGui import QAction
from PySide6.QtWidgets import QWidget

from radioviz.models.overlays import OverlaySpec
from radioviz.services.typing_helpers import require_not_none
from radioviz.services.window_factory import WindowSpec
from radioviz.services.workspace_manager import ToolWorkspace
from radioviz.tools.tool_api import T_Tool_Controller

if TYPE_CHECKING:
    from radioviz.tools.tool_api import ToolContext


[docs] @dataclass class ToolEvent: """ Event structure for tool communication. This dataclass represents events that can be triggered within the tool system to communicate between different components of the application. """ #: Unique identifier of the tool that triggered the event tool_id: str #: Type of event being triggered event: str #: Optional payload data associated with the event payload: Any = None
[docs] class Tool(Generic[T_Tool_Controller]): """ Base class for defining application tools. This class serves as the foundation for implementing various tools within the radioviz application. Each tool should inherit from this base class and implement the required methods to integrate with the application's UI and functionality. The tool instance is created once per application run and contains metadata about the tool along with registration information for windows and overlays. It does not contain any view-specific logic. """ #: Unique identifier of the tool tool_id: str = 'base' #: Human-readable name name: str = 'Base Tool' #: Tooltip or description description: str = '' #: List of window specifications to register windows_to_be_registered: list[WindowSpec] = [] #: List of overlay specifications to register overlays_to_be_registered: list[OverlaySpec] = [] def __init__(self) -> None: self._controller: Optional[T_Tool_Controller] = None self._restore_spec: Optional[ToolWorkspace] = None
[docs] def _require_restore_spec(self) -> ToolWorkspace: """ Return the workspace spec used for restoration or raise if missing. :return: The workspace specification for this restore :rtype: ToolWorkspace :raises RuntimeError: If the restore spec has not been set """ return require_not_none(self._restore_spec, f'{self.tool_id} restore spec')
[docs] def create_controller(self, ctx: ToolContext) -> T_Tool_Controller: """ Create a controller instance for this tool. This method must be implemented by subclasses to provide a concrete controller implementation that manages the tool's behavior and state. :param ctx: The tool context containing application state and services :type ctx: ToolContext :return: A controller instance for managing the tool :rtype: ToolController[Any, Any] :raise NotImplementedError: Always raised by the base implementation """ raise NotImplementedError
# ---- Menu items -----------------------------------------------------
[docs] def create_analysis_action(self, parent: QWidget, controller: T_Tool_Controller) -> Optional[QAction]: """ Create an action for the main window 'Analysis' menu. This method creates a menu action that will appear in the main window's Analysis menu. Tools that don't expose a trigger action should return None. :param parent: The parent widget for the action :type parent: QWidget :param controller: The tool controller instance :type controller: ToolController[Any, Any] :return: A QAction instance or None if no action is needed :rtype: QAction or None """ return None
[docs] def create_context_menu_action(self, parent: QWidget, controller: T_Tool_Controller) -> Optional[QAction]: """ Create an action for the image context menu. This method creates a menu action that will appear in the context menu when right-clicking on images. Can be None if the tool doesn't need context menu integration. :param parent: The parent widget for the action :type parent: QWidget :param controller: The tool controller instance :type controller: ToolController[Any, Any] :return: A QAction instance or None if no action is needed :rtype: QAction or None """ return None
[docs] def create_view_menu_action(self, parent: QWidget, controller: T_Tool_Controller) -> Optional[QAction]: """ Create an action for the 'View' menu to toggle dock visibility. This method creates a menu action that allows users to toggle the visibility of a dockable widget associated with this tool. Only applicable when the controller has a dock. :param parent: The parent widget for the action :type parent: QWidget :param controller: The tool controller instance :type controller: ToolController[Any, Any] :return: A QAction instance for toggling dock visibility or None :rtype: QAction or None """ if not controller.has_dock: return None act = QAction(self.name + ' Dock', parent) act.setCheckable(True) act.toggled.connect(controller.toggle_dock_visibility) controller._dock_visibility_action = act return act