#! python3 # noqa: E265 """Main plugin module.""" # standard from functools import partial from pathlib import Path from typing import Optional # PyQGIS from qgis.core import ( Qgis, QgsApplication, QgsSettings, QgsProject, QgsGeometry, QgsMapLayerProxyModel, QgsCoordinateReferenceSystem, QgsCoordinateTransform, ) from qgis.gui import QgisInterface from qgis.PyQt.QtCore import QCoreApplication, QLocale, QTranslator, QUrl from qgis.PyQt.QtGui import QDesktopServices, QIcon from qgis.PyQt.QtWidgets import QAction, QMessageBox from qgis.PyQt.QtNetwork import QNetworkAccessManager from qgis.PyQt.QtWidgets import QCheckBox, QApplication # project from gn_tools.__about__ import ( DIR_PLUGIN_ROOT, __icon_path__, __title__, __uri_homepage__, __domain_url__, __biodiv_aura__, __gbif__, __api_sn_web__, __api_sn_exp__, __api_lst_ex__, __api_cd_sta__, ) from gn_tools.gui.dlg_settings import PlgOptionsFactory, PlgOptionsManager from gn_tools.gui.dlg_gn_tools import gnToolsDialog from gn_tools.gui.dlg_gn_synthese import gnToolsSynthese from gn_tools.processing import ( GnToolsProvider, GetLogin, ParamWidget, LoadingImport, RectangleFeatureTool, PivotStatus, GetFilterFromAPI, ) from gn_tools.toolbelt import PlgLogger # ############################################################################ # ########## Classes ############### # ################################## class GnToolsPlugin: def __init__(self, iface: QgisInterface): """Constructor. :param iface: An interface instance that will be passed to this class which \ provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ self.iface = iface self.canvas = iface.mapCanvas() self.project = QgsProject.instance() self.log = PlgLogger().log self.provider: Optional[GnToolsProvider] = None self.rectangle = None self.src_bdd = { 'GéoNature':__domain_url__, "Biodiv'AuRA":__biodiv_aura__ } self.syn_params = {} # translation # initialize the locale self.locale: str = QgsSettings().value("locale/userLocale", QLocale().name())[ 0:2 ] locale_path: Path = ( DIR_PLUGIN_ROOT / "resources" / "i18n" / f"{__title__.lower()}_{self.locale}.qm" ) self.log(message=f"Translation: {self.locale}, {locale_path}", log_level=Qgis.MessageLevel.NoLevel) if locale_path.exists(): self.translator = QTranslator() self.translator.load(str(locale_path.resolve())) QCoreApplication.installTranslator(self.translator) lst_src = [] for src,url in self.src_bdd.items(): if url != '': self.src_bdd[src] = url + '/' if url[-1] != '/' else url lst_src += [src] # self.domain_url = self.src_bdd['GéoNature'] self.dlg = gnToolsDialog() self.dlg_syn = gnToolsSynthese() # Masquer les widgets self.dlg.pub_access.setVisible(False) # self.dlg.syn_tools.setVisible(False) self.dlg_syn.date_min.clear() self.dlg_syn.date_max.clear() self.dlg.status.setDisabled(True) self.dlg.src_database.addItems(['',*lst_src]) self.dlg.src_database.currentTextChanged.connect( self.define_domain_url ) # Biodiv'AuRA check box action self.dlg.pub_access.toggled.connect( self.dlg.mAuthConfigSelect.setEnabled ) self.dlg.pub_access.toggled.connect( self.dlg.mAuthConfigSelect.setDisabled ) # Import the extent drawer tool and connect a signal to make the window appear once the extent is drawned self.move_tool = RectangleFeatureTool(self.project, self.canvas) self.move_tool.signal.connect(self.activate_window) # Login to GN self.dlg.login_gn.clicked.connect(self.connect_src) # Filter Active Layer self.dlg.draw_bounds.setDisabled(True) self.dlg.bound_log.setReadOnly(True) self.dlg.bound_log.setPlainText('') self.dlg.draw_bounds.clicked.connect(self.pointer) self.dlg.active_filter_layer.setDisabled(True) self.dlg.active_filter_layer.clicked.connect(self.filter_layer_activate) self.dlg.filter_layer.setDisabled(True) self.dlg.use_entity.setDisabled(True) self.dlg.use_entity.setChecked(False) self.dlg.map_layers.setFilters(QgsMapLayerProxyModel.VectorLayer) self.dlg.map_layers.setAllowEmptyLayer(True) self.filter_layers() self.canvas.layersChanged.connect(self.filter_layers) self.dlg.filter_layer.setFilters(QgsMapLayerProxyModel.VectorLayer) self.dlg.filter_layer.setAllowEmptyLayer(True) self.dlg.filter_layer.layerChanged.connect(self.extend_layer) self.dlg.map_layers.layerChanged.connect(self.param_cd_taxon) # Filtre de la synthèse self.dlg.syn_tools.clicked.connect(self.dlg_syn.show) # Clear button self.dlg.clear_filter.setDisabled(True) self.dlg.clear_filter.clicked.connect(self.clear_filter) # Finished Button self.dlg.buttonBox.accepted.disconnect() self.dlg.buttonBox.accepted.connect(self.accept) self.dlg.buttonBox.rejected.connect(self.reject) def initGui(self): """Set up plugin UI elements.""" self.manager = QNetworkAccessManager() self.manager.accepted = False # settings page within the QGIS preferences menu self.options_factory = PlgOptionsFactory() self.iface.registerOptionsWidgetFactory(self.options_factory) # -- Actions self.action_help = QAction( QgsApplication.getThemeIcon("mActionHelpContents.svg"), self.tr("Help"), self.iface.mainWindow(), ) self.action_help.triggered.connect( partial(QDesktopServices.openUrl, QUrl(__uri_homepage__)) ) self.action_settings = QAction( QgsApplication.getThemeIcon("console/iconSettingsConsole.svg"), self.tr("Settings"), self.iface.mainWindow(), ) self.action_settings.triggered.connect( lambda: self.iface.showOptionsDialog( currentPage="mOptionsPage{}".format(__title__) ) ) self.action_gn_tools = QAction( QIcon(str(__icon_path__)), f"{__title__} - Import project", self.iface.mainWindow(), ) self.iface.addToolBarIcon(self.action_gn_tools) self.action_gn_tools.triggered.connect( lambda: self.run_gn_tools() ) # -- Menu self.iface.addPluginToMenu(__title__, self.action_gn_tools) self.iface.addPluginToMenu(__title__, self.action_settings) self.iface.addPluginToMenu(__title__, self.action_help) # -- Processing self.initProcessing() # -- Help menu # documentation self.iface.pluginHelpMenu().addSeparator() self.action_help_plugin_menu_documentation = QAction( QIcon(str(__icon_path__)), f"{__title__} - Documentation", self.iface.mainWindow(), ) self.action_help_plugin_menu_documentation.triggered.connect( partial(QDesktopServices.openUrl, QUrl(__uri_homepage__)) ) self.iface.pluginHelpMenu().addAction( self.action_help_plugin_menu_documentation ) self.dlg.is_connect.setText('Non connecté..') def initProcessing(self): """Initialize the processing provider.""" self.provider = GnToolsProvider() QgsApplication.processingRegistry().addProvider(self.provider) def tr(self, message: str) -> str: """Get the translation for a string using Qt translation API. :param message: string to be translated. :type message: str :returns: Translated version of message. :rtype: str """ return QCoreApplication.translate(self.__class__.__name__, message) def unload(self): """Cleans up when plugin is disabled/uninstalled.""" # -- Clean up toolbar self.iface.removeToolBarIcon(self.action_gn_tools) # -- Clean up menu self.iface.removePluginMenu(__title__, self.action_gn_tools) self.iface.removePluginMenu(__title__, self.action_help) self.iface.removePluginMenu(__title__, self.action_settings) # -- Clean up preferences panel in QGIS settings self.iface.unregisterOptionsWidgetFactory(self.options_factory) # -- Unregister processing QgsApplication.processingRegistry().removeProvider(self.provider) # remove from QGIS help/extensions menu if self.action_help_plugin_menu_documentation: self.iface.pluginHelpMenu().removeAction( self.action_help_plugin_menu_documentation ) # remove actions del self.action_gn_tools del self.action_settings del self.action_help def run(self): """Main process. :raises Exception: if there is no item in the feed """ try: self.log( message=self.tr("Everything ran OK."), log_level=Qgis.MessageLevel.Success, push=False, ) print("tom") except Exception as err: self.log( message=self.tr("Houston, we've got a problem: {}".format(err)), log_level=Qgis.MessageLevel.Critical, push=True, ) def define_domain_url(self): self.src_name = self.dlg.src_database.currentText() if self.src_name != '': self.domain_url = self.src_bdd[self.src_name] self.dlg.report_url.setText(self.domain_url[:42]) if self.src_name == 'GBIF': self.dlg.mAuthConfigSelect.setDisabled(True) self.dlg.login_gn.setDisabled(True) self.dlg.is_connect.setText('No connection need') self.print_change() ParamWidget( parent=self,network_manager=self.manager ) else: self.dlg.mAuthConfigSelect.setEnabled(True) self.dlg.login_gn.setEnabled(True) self.dlg.is_connect.setText('Non connecté..') if self.src_name == "Biodiv'AuRA": self.dlg.pub_access.setVisible(True) self.dlg.status.setDisabled(True) else : self.dlg.pub_access.setVisible(False) self.dlg.pub_access.setChecked(False) self.dlg.status.setEnabled(True) else: self.dlg.clear_filter.setDisabled(True) self.dlg.draw_bounds.setDisabled(True) self.dlg.active_filter_layer.setDisabled(True) self.dlg.pub_access.setVisible(False) self.dlg.pub_access.setChecked(False) self.dlg.mAuthConfigSelect.setDisabled(True) self.dlg.login_gn.setDisabled(True) self.dlg.status.setDisabled(True) self.dlg.is_connect.setText('Non connecté..') def filter_layers(self): checked_layers = self.canvas.layers() excluded_layers = [l for l in QgsProject.instance().mapLayers().values() if not l in checked_layers] self.dlg.map_layers.setExceptedLayerList(excluded_layers) self.dlg.filter_layer.setExceptedLayerList(excluded_layers) self.param_cd_taxon() return excluded_layers def run_gn_tools(self): """Main process. Create a QGIS project with ZH data from GeoNature.""" print("****** CREATE PROJECT ******") # Get base url for all the request from the dlg settings self.plg_settings = PlgOptionsManager().get_plg_settings() if self.plg_settings.domain_url: self.domain_url = self.plg_settings.domain_url else : self.domain_url = __domain_url__ if self.domain_url[-1] != '/': self.domain_url = self.domain_url + '/' # self.study_area_list = self.plg_settings.study_area_list # self.dl_zh_pot = self.plg_settings.dl_zh_pot # self.export_number = self.plg_settings.export_number if self.domain_url == "": msg = QMessageBox() msg.warning( None, self.tr("Warning"), self.tr("You need to inform GeoNature's URL"), # noqa: E501 ) self.iface.showOptionsDialog(currentPage="mOptionsPage{}".format(__title__)) self.run_gn_tools() else: # Initiate class print(self.domain_url) print(self.dlg.src_database.currentText()) if self.dlg.src_database.currentText() != '': api = self.src_bdd[self.dlg.src_database.currentText()] self.dlg.report_url.setText(api[:42]) self.domain_url = api self.src_name = self.dlg.src_database.currentText() self.dlg.show() # Run the dialog event loop result = self.dlg.exec() if result: # Do something useful here - delete the line containing pass and # substitute with you print('ok') print(result) self.dlg.activateWindow() pass def connect_src(self): print('connect_src : ',self.src_name) if self.src_name == 'GéoNature': self.getLogin = GetLogin(parent=self,network_manager=self.manager) self.getLogin.finished_login.connect(self.param_widget) elif self.src_name == "Biodiv'AuRA": if self.dlg.pub_access.isChecked(): user = { 'usr': 'user-public', 'pwd': 'public' } self.getLogin = GetLogin(parent=self,network_manager=self.manager,params=user) self.getLogin.finished_login.connect(self.param_widget) else : self.getLogin = GetLogin(parent=self,network_manager=self.manager) self.getLogin.finished_login.connect(self.param_widget) # if self.manager.cookieJar(): # self.dlg.is_connect.setText("Good Job !") # else: # self.dlg.is_connect.setText("Aie !") def param_widget(self): print(self.manager.cookieStatus) if self.manager.cookieStatus==200: self.paramWidget = ParamWidget( parent=self,network_manager=self.manager ) self.dlg.source_import.currentTextChanged.connect( self.print_change ) def param_cd_taxon(self): layer = self.dlg.map_layers.currentLayer() if layer: cols_name = layer.fields().names() self.dlg.cd_taxon.clear() self.dlg.cd_taxon.addItems(cols_name) def print_change(self): self.dlg.clear_filter.setEnabled(True) self.dlg.draw_bounds.setEnabled(True) self.dlg.active_filter_layer.setEnabled(True) txt = self.dlg.source_import.currentText() self.dlg.syn_tools.setVisible(True if txt == 'Synthèse taxons' else False ) if txt == 'Synthèse taxons': self.syn = GetFilterFromAPI( parent=self, network_manager=self.manager ) print(self.dlg.source_import.currentIndex()) def pointer(self): self.dlg.filter_layer.setDisabled(True) self.dlg.use_entity.setDisabled(True) self.dlg.use_entity.setChecked(False) self.dlg.bound_log.setPlainText('') # Add the tool to draw a rectangle self.iface.mainWindow().activateWindow() self.canvas.setMapTool(self.move_tool) def activate_window(self): # Put the dialog on top once the rectangle is drawn self.dlg.activateWindow() self.canvas.unsetMapTool(self.move_tool) self.check_valid() def check_valid(self): self.rectangle = QgsGeometry.fromRect(self.move_tool.new_extent) sourceCrs = QgsCoordinateReferenceSystem(self.project.crs()) destCrs = QgsCoordinateReferenceSystem(4326) tr = QgsCoordinateTransform(sourceCrs, destCrs, self.project) self.rectangle.transform(tr) self.dlg.bound_log.setPlainText( 'Bound selected : ' + str(self.rectangle.asWkt()) ) print('rectangle : ',self.rectangle.asJson()) def filter_layer_activate(self): self.dlg.bound_log.setPlainText('') self.extend_layer() self.dlg.filter_layer.setEnabled(True) self.dlg.use_entity.setEnabled(True) self.canvas.unsetMapTool(self.move_tool) def extend_layer(self): if self.dlg_syn.jdd_box.checkedItemsData(): print('checked : ',self.dlg_syn.jdd_box.checkedItems()) print('checked : ',self.syn_params) if self.dlg.filter_layer.currentText() != '': layer = self.dlg.filter_layer.currentLayer() destCrs = QgsCoordinateReferenceSystem(4326) self.rectangle = QgsGeometry.fromRect( layer.extent() ) if self.dlg.use_entity.isChecked(): geoms = [f.geometry() for f in layer.getSelectedFeatures()] if geoms: union = QgsGeometry.unaryUnion(geoms) self.rectangle = QgsGeometry.fromRect( union.boundingBox() ) if layer.crs() != destCrs: tr = QgsCoordinateTransform(layer.crs(), destCrs, self.project) self.rectangle.transform(tr) print(layer.extent()) print(layer.crs()) def clear_filter(self): self.dlg.bound_log.setPlainText('') self.rectangle = None def accept(self): currentTab = self.dlg.tab.currentWidget().objectName() if self.manager.accepted or self.src_name=='GBIF' : self.dlg.buttonBox.blockSignals(False) if currentTab == 'import_2': load = LoadingImport( parent=self,network_manager=self.manager ) # load.finished_dl.connect() elif currentTab == 'status': PivotStatus( parent=self,network_manager=self.manager, layer=self.dlg.map_layers.currentLayer(), cd_nom=self.dlg.cd_taxon.currentText(), ) # print("Work in progress ..") # msg = QMessageBox() # msg.warning( # None, # self.tr("Warning"), # self.tr("Work in progress .."), # noqa: E501 # ) print("Accepted") else: msg = QMessageBox() msg.warning( None, self.tr("Warning"), self.tr("Opération impossible ! \nVous n'êtes pas connectez à GéoNature"), # noqa: E501 ) self.dlg.show() def reject(self): QApplication.restoreOverrideCursor() print("Rejected")