From 6b6622481bc2b50e82d60440a46ef271c4cadb9c Mon Sep 17 00:00:00 2001 From: Fred C Date: Thu, 14 Mar 2024 23:15:25 +0100 Subject: [PATCH] Full menu --- plugin_qgis_lpo/gui/menu_tools.py | 143 ++++++++++++++++++++++++++++++ plugin_qgis_lpo/plugin_main.py | 76 +++++++++++++--- 2 files changed, 206 insertions(+), 13 deletions(-) create mode 100644 plugin_qgis_lpo/gui/menu_tools.py diff --git a/plugin_qgis_lpo/gui/menu_tools.py b/plugin_qgis_lpo/gui/menu_tools.py new file mode 100644 index 0000000..51881cf --- /dev/null +++ b/plugin_qgis_lpo/gui/menu_tools.py @@ -0,0 +1,143 @@ +#! python3 # noqa: E265 + +""" + Custom menu. + + Ressources: https://realpython.com/python-menus-toolbars/#adding-help-tips-to-actions +""" + +# PyQGIS +from qgis import processing +from qgis.core import QgsApplication +from qgis.PyQt.QtCore import QCoreApplication +from qgis.PyQt.QtGui import QIcon +from qgis.PyQt.QtWidgets import QAction, QMenu + +# project +from plugin_qgis_lpo.__about__ import __title__ +from plugin_qgis_lpo.processing.provider import ( + ExtractData, + ExtractDataObservers, + RefreshData, + StateOfKnowledge, + SummaryMap, + SummaryTablePerSpecies, + SummaryTablePerTimeInterval, +) + + +class MenuTools(QMenu): + """Menu pointing to plugin processings. + + + Example: + + from .menu_tools import MenuTools + menubar.addMenu(MenuTools(self)) + """ + + def __init__(self, parent=None): + """Constructor.""" + super().__init__(parent) + + # menu definition + self.setTitle(self.tr("&Tools")) + self.setObjectName("LSCIToolsMenu") + self.setToolTipsVisible(True) + self.setToolTip(self.tr("Related utilities")) + + # build menu actions and triggers + self.initGui() + + def initGui(self): + """Create the menu entries and toolbar icons inside the QGIS GUI.""" + # -- Actions + self.act_extract_data = QAction( + icon=QIcon(ExtractData().icon()), + text=ExtractData().displayName(), + ) + self.act_extract_data_observers = QAction( + icon=QIcon(ExtractDataObservers().icon()), + text=ExtractDataObservers().displayName(), + ) + self.act_state_of_knowledge = QAction( + icon=QIcon(StateOfKnowledge().icon()), + text=StateOfKnowledge().displayName(), + ) + self.act_summary_map = QAction( + icon=QIcon(SummaryMap().icon()), + text=SummaryMap().displayName(), + ) + self.act_summary_per_species = QAction( + icon=QIcon(SummaryTablePerSpecies().icon()), + text=SummaryTablePerSpecies().displayName(), + ) + self.act_summary_per_time_interval = QAction( + icon=QIcon(SummaryTablePerTimeInterval().icon()), + text=SummaryTablePerTimeInterval().displayName(), + ) + self.act_refresh_data = QAction( + icon=QIcon(RefreshData().icon()), + text=RefreshData().displayName(), + ) + + # -- Connections + self.act_extract_data.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{ExtractData().name()}" + ).show() + ) + self.act_extract_data_observers.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{ExtractDataObservers().name()}" + ).show() + ) + self.act_state_of_knowledge.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{StateOfKnowledge().name()}" + ).show() + ) + + self.act_summary_map.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{SummaryMap().name()}" + ).show() + ) + self.act_summary_per_species.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{SummaryTablePerSpecies().name()}" + ).show() + ) + self.act_summary_per_time_interval.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{SummaryTablePerTimeInterval().name()}" + ).show() + ) + self.act_refresh_data.triggered.connect( + lambda: processing.createAlgorithmDialog( + f"plugin_qgis_lpo:{RefreshData().name()}" + ).show() + ) + + # -- Menu + self.addAction(self.act_refresh_data) + self.addSeparator() + self.addAction(self.act_summary_map) + self.addSeparator() + self.addAction(self.act_extract_data) + self.addAction(self.act_extract_data_observers) + self.addSeparator() + self.addAction(self.act_summary_per_species) + self.addAction(self.act_summary_per_time_interval) + self.addAction(self.act_state_of_knowledge) + + def tr(self, string: str) -> str: + """Returns a translatable string with the self.tr() function. + + Args: + string (str): text to translate + + Returns: + str: translated text + """ + return QCoreApplication.translate(self.__class__.__name__, string) diff --git a/plugin_qgis_lpo/plugin_main.py b/plugin_qgis_lpo/plugin_main.py index 3ce8d09..32dfb3d 100644 --- a/plugin_qgis_lpo/plugin_main.py +++ b/plugin_qgis_lpo/plugin_main.py @@ -12,7 +12,13 @@ import processing # PyQGIS -from qgis.core import QgsApplication, QgsSettings +from qgis.core import ( + QgsApplication, + QgsProcessingException, + QgsProviderConnectionException, + QgsProviderRegistry, + QgsSettings, +) from qgis.gui import QgisInterface from qgis.PyQt.QtCore import QCoreApplication, QLocale, QTranslator, QUrl from qgis.PyQt.QtGui import QDesktopServices, QIcon @@ -21,11 +27,13 @@ # project from plugin_qgis_lpo.__about__ import ( DIR_PLUGIN_ROOT, + __icon_dir_path__, __icon_path__, __title__, __uri_homepage__, ) from plugin_qgis_lpo.gui.dlg_settings import PlgOptionsFactory +from plugin_qgis_lpo.gui.menu_tools import MenuTools from plugin_qgis_lpo.processing.provider import QgisLpoProvider from plugin_qgis_lpo.processing.qgis_processing_postgis import get_connection_name from plugin_qgis_lpo.processing.species_map import CarteParEspece @@ -53,6 +61,8 @@ def __init__(self, iface: QgisInterface): self.provider: Optional[QgisLpoProvider] = None self.log = PlgLogger().log self.iface: QgisInterface = iface + self.tools_menu: Optional[QMenu] = None + self.main_menu: Optional[QMenu] = None # translation # initialize the locale self.locale: str = QgsSettings().value("locale/userLocale", QLocale().name())[ @@ -74,10 +84,9 @@ def initGui(self): """Set up plugin UI elements.""" self.initSettings() - self.provider = QgisLpoProvider() + # self.main_menu = self.iface.pluginMenu().parent().addMenu(__title__) - plugin_lpo_menu = self.iface.pluginMenu().parent().addMenu("Plugin LPO") # settings page within the QGIS preferences menu self.options_factory = PlgOptionsFactory() self.iface.registerOptionsWidgetFactory(self.options_factory) @@ -127,7 +136,7 @@ def initGui(self): QgsApplication.processingRegistry().addProvider(self.provider) self.especes_action = QAction( - # QIcon(), + QIcon(str(__icon_dir_path__ / "map.png")), "Carte par espèces", self.iface.mainWindow(), ) @@ -139,7 +148,20 @@ def initGui(self): # for a in self.iface.pluginMenu().parent().findChildren(QMenu) # if a.title() == "Plugin LPO" # ][0] - plugin_lpo_menu.addAction(self.especes_action) + self.main_menu = self.iface.pluginMenu().parent().addMenu(__title__) + self.tools_menu = MenuTools(self.iface.mainWindow()) + self.main_menu.addAction(self.tools_menu.act_extract_data) + self.main_menu.addAction(self.tools_menu.act_extract_data_observers) + self.main_menu.addAction(self.tools_menu.addSeparator()) + self.main_menu.addAction(self.tools_menu.act_summary_map) + self.main_menu.addAction(self.especes_action) + self.main_menu.addAction(self.tools_menu.addSeparator()) + self.main_menu.addAction(self.tools_menu.act_summary_per_species) + self.main_menu.addAction(self.tools_menu.act_summary_per_time_interval) + self.main_menu.addAction(self.tools_menu.act_state_of_knowledge) + self.main_menu.addAction(self.tools_menu.addSeparator()) + self.main_menu.addAction(self.tools_menu.act_refresh_data) + except IndexError: # If not successful put the button in the Plugins toolbar self.iface.addToolBarIcon(self.especes_action) @@ -148,7 +170,38 @@ def initGui(self): "La carte par espèces est accessible via la barre d'outils d'Extensions", ) - processing.run("plugin_qgis_lpo:RefreshData", {"DATABASE": "geonature_lpo"}) + self.populateSettings() + + def populateSettings(self): + try: + postgres_metadata = QgsProviderRegistry.instance().providerMetadata( + "postgres" + ) + if "geonature_lpo" in postgres_metadata.dbConnections(): + self.log( + message=f"Loading GeoNature required data", + log_level=0, + push=True, + duration=60, + ) + processing.run( + "plugin_qgis_lpo:RefreshData", {"DATABASE": "geonature_lpo"} + ) + self.log( + message=f"Loading GeoNature terminated", + log_level=0, + push=True, + duration=2, + ) + except QgsProviderConnectionException as exc: + self.log( + message=self.tr("Houston, we've got a problem: {}".format(exc)), + log_level=2, + push=True, + ) + raise QgsProcessingException( + f"Could not retrieve connection details : {str(exc)}" + ) from exc # processing.run("plugin_qgis_lpo:RefreshData", {"DATABASE": "geonature_lpo"}) def runEspeces(self): # noqa N802 connection_name = get_connection_name() @@ -188,15 +241,13 @@ def unload(self): QgsApplication.processingRegistry().removeProvider(self.provider) try: - lpo_menu = [ - a - for a in self.iface.pluginMenu().parent().findChildren(QMenu) - if a.title() == "Plugin LPO" - ][0] - lpo_menu.removeAction(self.especes_action) + self.main_menu.clear() + self.main_menu.setHidden(True) + del self.main_menu except IndexError: pass # teardown_logger(Plugin.name) + self.iface.removeToolBarIcon(self.especes_action) def run(self): @@ -204,7 +255,6 @@ def run(self): :raises Exception: if there is no item in the feed """ - try: self.log( message=self.tr("Everything ran OK."),