# PamhyrToolbar.py -- Pamhyr # Copyright (C) 2023-2024 INRAE # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # -*- coding: utf-8 -*- import os import logging import matplotlib as mpl from matplotlib.backends import qt_compat from matplotlib.backends.backend_qt5 import NavigationToolbar2QT from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import QAction from PyQt5.QtCore import pyqtSignal, QSize _translate = QtCore.QCoreApplication.translate logger = logging.getLogger() file_path = os.path.abspath(os.path.dirname(__file__)) class PamhyrPlotToolbar(NavigationToolbar2QT): """ MatPlotLib plot toolbar for Pamhyr """ isometric_signal = pyqtSignal(str) def __init__(self, canvas, parent, items=["home", "move", "zoom", "save"]): """PamhyrPlotToolbar Args: canvas: MatPlotLib canvas parent: parent Qt object items: Enables items (default: "home", "move", "zoom", "save") """ self._canvas = canvas self._items = items self.toolitems = [ (None, None, None, None), ] self.icons = [] if "home" in items: self.init_tool_home() if "back/forward" in items: self.init_tool_back_forward() if "move" in items: self.init_tool_move() self.add_tool_separator() elif "home" in items or "back/forward" in items: self.add_tool_separator() if "zoom" in items: self.init_tool_zoom() if "iso" in items: self.init_tool_iso() self.add_tool_separator() elif "zoom" in items: self.add_tool_separator() if "save" in items: self.init_tool_save() NavigationToolbar2QT.__init__(self, canvas, parent) btn_size = QSize(40, 28) actions = self.findChildren(QAction) for a, i in self.icons: self._actions[a].setIcon(i) self.addSeparator() def add_tool_separator(self): self.toolitems.append((None, None, None, None)) def init_tool_home(self): self.toolitems.append( ( 'Home', _translate("Toolbar", 'Default view'), 'home', 'home' ) ) def init_tool_back_forward(self): self.toolitems.append( ( 'Back', _translate("Toolbar", 'Back to previous view'), 'back', 'back' ) ) self.toolitems.append( ( 'Forward', _translate("Toolbar", 'Return to next view'), 'forward', 'forward' ) ) def init_tool_move(self): self.toolitems.append( ( 'Pan', _translate("Toolbar", 'Axes panoramic'), 'move', 'pan' ) ) def init_tool_zoom(self): self.toolitems.append( ( 'Zoom', _translate("Toolbar", 'Zoom'), 'zoom_to_rect', 'zoom' ) ) icon_zoom = QtGui.QIcon() icon_zoom.addPixmap(QtGui.QPixmap( os.path.abspath(f"{file_path}/../../ui/ressources/zoom.png") )) self.icons.append(("zoom", icon_zoom)) def init_tool_iso(self): self.toolitems.append( ( 'Isometric_view', _translate("Toolbar", 'Isometric view (Shift+W)'), '', 'isometric_view' ) ) self.toolitems.append( ( 'GlobalView', _translate("Toolbar", 'Auto scale view (Shift+X)'), '', 'non_isometric_view' ) ) icon_btn_isometric_view = QtGui.QIcon() icon_btn_isometric_view.addPixmap( QtGui.QPixmap( os.path.abspath( f"{file_path}/../../ui/ressources/zoom_fit_11.png" ) ) ) icon_btn_global_view = QtGui.QIcon() icon_btn_global_view.addPixmap( QtGui.QPixmap( os.path.abspath( f"{file_path}/../../ui/ressources/zoom_fit.png" ) ) ) self.icons.append(("isometric_view", icon_btn_isometric_view)) self.icons.append(("non_isometric_view", icon_btn_global_view)) def init_tool_save(self): self.toolitems.append( ( 'Save', _translate("Toolbar", 'Save the figure'), 'filesave', 'save_figure' ) ) icon_save = QtGui.QIcon() icon_save.addPixmap( QtGui.QPixmap( os.path.abspath( f"{file_path}/../../ui/ressources/save.png" ) ) ) self.icons.append(("save_figure", icon_save)) def save_figure(self, *args): file_types = self.canvas.get_supported_filetypes_grouped() default_file_type = self.canvas.get_default_filetype() start = os.path.join( os.path.expanduser(mpl.rcParams['savefig.directory']), self.canvas.get_default_filename() ) filters = [] selected_filter = None for name in file_types: exts = file_types[name] exts_list = " ".join([f"*.{ext}" for ext in exts]) new = f"{name} ({exts_list})" if default_file_type in exts: selected_filter = new filters.append(new) filters = ';;'.join(filters) file_name, _ = qt_compat._getSaveFileName( self.canvas.parent(), _translate("MainWindow_reach", "Select destination file"), start, filters, selected_filter ) if file_name: try: self.canvas.figure.savefig(file_name) except Exception as e: QtWidgets.QMessageBox.critical( self, "Error saving file", str(e), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton ) def isometric_view(self): self._canvas.axes.axis("equal") self._canvas.figure.canvas.draw_idle() self.isometric_signal[str].emit("vue iso") def non_isometric_view(self): self._canvas.axes.axis("tight") self._canvas.toolbar.update() self._canvas.figure.canvas.draw_idle() def toolitems_translation(self): self._actions['home'].setToolTip(_translate("Toolbar", "Default view")) self._actions['back'].setToolTip( _translate("Toolbar", "Back to previous view")) self._actions['forward'].setToolTip( _translate("Toolbar", "Return to next view")) self._actions['pan'].setToolTip( _translate("Toolbar", "Axes panoramic")) self._actions['zoom'].setToolTip(_translate("Toolbar", "Zoom")) self._actions['save_figure'].setToolTip( _translate("Toolbar", "Save the figure")) self.action_isometric_view.setToolTip( _translate("Toolbar", "Isometric view (Shift+W)")) self.action_auto_global_view.setToolTip( _translate("Toolbar", "Auto scale view (Shift+X)"))