Forked from HYCAR-Hydro / airGR
Source project has a limited visibility.
navigation_toolbar_2qt.py 7.13 KiB
# navigation_toolbar_2qt.py -- Pamhyr
# Copyright (C) 2023  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 PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QAction
from matplotlib.backends.backend_qt5 import NavigationToolbar2QT
from PyQt5.QtCore import pyqtSignal, QSize

_translate = QtCore.QCoreApplication.translate

logger = logging.getLogger()
file_path = os.path.abspath(os.path.dirname(__file__))


class PamHyrNavigationToolbar2QT(NavigationToolbar2QT):
    """
    Cette classe est une personnalisation de la toolbar (NavigationToolbar2QT). Elle permet l'internationnalisation et
    l'ajout d'autres boutons à la toolbar initiale
    """
    isometric_signal = pyqtSignal(str)

    def __init__(self, canvas, parent, items = ["home", "move", "zoom", "save"]):
        """
        Args:
            canvas: canvas de matplotlib
            parent: parent du canvas
        """
        self.my_canvas = canvas

        self._items = items
        self.toolitems = [
            (None, None, None, None),
        ]

        icons = []

        if "home" in items:
            self.toolitems.append(('Home', _translate("Toolbar", 'Default view'), 'home', 'home'))
            self.toolitems.append((None, None, None, None))

        if "back/forward" in items:
            self.toolitems.append(('Back', _translate("Toolbar", 'Back to previous view'), 'back', 'back'))
            self.toolitems.append(('Forward', _translate("Toolbar", 'Return to next view'), 'forward', 'forward'))
            self.toolitems.append((None, None, None, None))

        if "move" in items:
            self.toolitems.append(
                ('Pan', _translate(
                    "Toolbar",
                    'Axes panoramic'
                ), 'move', 'pan'))
            self.toolitems.append((None, None, None, None))

        if "zoom" in items:
            self.toolitems.append(('Zoom', _translate("Toolbar", 'Zoom'), 'zoom_to_rect', 'zoom'))
            self.toolitems.append((None, None, None, None))

            icon_zoom = QtGui.QIcon()
            icon_zoom.addPixmap(QtGui.QPixmap(
                f"{os.path.dirname(os.path.dirname(file_path))}/resources/icons/zoom.png"
            ))

            icons.append(("zoom",icon_zoom))

        if "iso" in items:
            self.toolitems.append(
                ('Isometric_view', _translate(
                    "Toolbar", 'Isometric view (Shift+W)'
                ), '', 'isometric_view')
            )
            self.toolitems.append((None, None, None, None))

            self.toolitems.append(
                ('GlobalView', _translate(
                    "Toolbar", 'Auto scale view (Shift+X)'
                ), '', 'non_isometric_view')
            )
            self.toolitems.append((None, None, None, None)),

            icon_btn_isometric_view = QtGui.QIcon()
            icon_btn_isometric_view.addPixmap(
                QtGui.QPixmap(f"{os.path.dirname(os.path.dirname(file_path))}/resources"
                              f"/icons/zoom_fit_11.png"))

            icon_btn_global_view = QtGui.QIcon()
            icon_btn_global_view.addPixmap(
                QtGui.QPixmap(f"{os.path.dirname(os.path.dirname(file_path))}/resources/icons"
                              f"/zoom_fit.png"))

            icons.append(("isometric_view", icon_btn_isometric_view))
            icons.append(("non_isometric_view", icon_btn_global_view))

        if "save" in items:
            self.toolitems.append(
                ('Save', _translate(
                    "Toolbar", 'Save the figure'
                ), 'filesave', 'save_figure')
            )
            self.toolitems.append((None, None, None, None))

        NavigationToolbar2QT.__init__(self, canvas, parent)
        btn_size = QSize(30, 30)
        actions = self.findChildren(QAction)

        for a, i in icons:
            self._actions[a].setIcon(i)

        self.addSeparator()

    def save_figure(self, *args):
        filetypes = self.canvas.get_supported_filetypes_grouped()
        sorted_filetypes = sorted(filetypes.items())
        default_filetype = self.canvas.get_default_filetype()

        startpath = os.path.expanduser(mpl.rcParams['savefig.directory'])
        start = os.path.join(startpath, self.canvas.get_default_filename())
        filters = []
        selectedFilter = None
        for name, exts in sorted_filetypes:
            exts_list = " ".join(['*.%s' % ext for ext in exts])
            filter = '%s (%s)' % (name, exts_list)
            if default_filetype in exts:
                selectedFilter = filter
            filters.append(filter)
        filters = ';;'.join(filters)

        fname, filter = qt_compat._getSaveFileName(
            self.canvas.parent(),
            _translate("MainWindow_reach", "Select destination file"),
            start,
            filters, selectedFilter)

        if fname:
            if startpath != "":
                mpl.rcParams['savefig.directory'] = os.path.dirname(fname)

            try:
                self.canvas.figure.savefig(fname)
            except Exception as e:
                QtWidgets.QMessageBox.critical(
                    self, "Error saving file", str(e),
                    QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.NoButton
                )

    def cursor1(self):
        logger.info("TODO: cursor1")

    def isometric_view(self):
        self.my_canvas.axes.axis("equal")
        self.my_canvas.figure.canvas.draw_idle()
        self.isometric_signal[str].emit("vue iso")

    def non_isometric_view(self):
        self.my_canvas.axes.axis("tight")
        self.my_canvas.toolbar.update()
        self.my_canvas.figure.canvas.draw_idle()

    def toolitems_translation(self):
        self._actions['home'].setToolTip(_translate("Toolbar", "Vue originale"))
        self._actions['back'].setToolTip(_translate("Toolbar", "Retour à la vue précédente"))
        self._actions['forward'].setToolTip(_translate("Toolbar", "Passer à la vue suivante"))
        self._actions['pan'].setToolTip(_translate("Toolbar", "Panoramique des axes avec la "
                                                              "souris gauche, zoom avec la droite"))
        self._actions['zoom'].setToolTip(_translate("Toolbar", "Zoom"))
        self._actions['save_figure'].setToolTip(_translate("Toolbar", "Enregistrer la figure"))
        self.action_isometric_view.setToolTip(_translate("Toolbar", "Vue isométrique (Shift+W)"))
        self.action_auto_global_view.setToolTip(_translate("Toolbar", "Vue globale automatique (Shift+X)"))