forked from CEN38/plugin_gn_tools
567 lines
19 KiB
Python
567 lines
19 KiB
Python
#! 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") |