From 20668b3aa6640d60db2887ac9d6bd44e1b0f97c2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 28 Jul 2023 15:01:53 +0200 Subject: [PATCH 1/9] remove unused code --- plugin/idg/gui/about_box.py | 47 --- plugin/idg/gui/dock.py | 58 ---- plugin/idg/gui/param_box.py | 277 --------------- plugin/idg/gui/tree_items.py | 158 --------- plugin/idg/gui/tree_widget.py | 131 ------- plugin/idg/plugin_main.py | 39 +-- plugin/idg/toolbelt/__init__.py | 1 - plugin/idg/toolbelt/browser.py | 2 +- plugin/idg/toolbelt/nodes.py | 413 ----------------------- plugin/idg/toolbelt/plugin_globals.py | 110 +----- plugin/idg/toolbelt/plugin_icons.py | 43 --- plugin/idg/toolbelt/remote_platforms.py | 6 +- plugin/idg/toolbelt/tree_node_factory.py | 195 +---------- 13 files changed, 12 insertions(+), 1468 deletions(-) delete mode 100644 plugin/idg/gui/about_box.py delete mode 100644 plugin/idg/gui/dock.py delete mode 100644 plugin/idg/gui/param_box.py delete mode 100644 plugin/idg/gui/tree_items.py delete mode 100644 plugin/idg/gui/tree_widget.py delete mode 100644 plugin/idg/toolbelt/nodes.py delete mode 100644 plugin/idg/toolbelt/plugin_icons.py diff --git a/plugin/idg/gui/about_box.py b/plugin/idg/gui/about_box.py deleted file mode 100644 index a28a4c0..0000000 --- a/plugin/idg/gui/about_box.py +++ /dev/null @@ -1,47 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtWidgets import QWidget, QDialog, QVBoxLayout, QLabel, QTextEdit, QFrame -from qgis.PyQt.QtGui import QPixmap - -from idg.toolbelt import PluginGlobals - - -class AboutBox(QDialog): - """ - About box of the plugin - """ - - def __init__(self, parent=None): - - QWidget.__init__(self, parent) - - mainLayout = QVBoxLayout() - - logo_file_path = PluginGlobals.instance().logo_file_path - self.logo = QLabel() - self.logo.setPixmap(QPixmap(logo_file_path)) - mainLayout.addWidget(self.logo) - - - title = u"À propos de l'extension Géo2France…" - description = u"""Extension pour QGIS donnant un accès simplifié aux ressources géographiques utiles aux -partenaires de Géo2France -Version {0} -Plus d'informations à l'adresse suivante : -{1} - """.format(PluginGlobals.instance().PLUGIN_VERSION, - PluginGlobals.instance().PLUGIN_SOURCE_REPOSITORY) - - self.textArea = QTextEdit() - self.textArea.setReadOnly(True) - self.textArea.setText(description) - self.textArea.setFrameShape(QFrame.NoFrame) - mainLayout.addWidget(self.textArea) - - self.setModal(True) - self.setSizeGripEnabled(False) - - self.setLayout(mainLayout) - - self.setFixedSize(400, 250) - self.setWindowTitle(title) diff --git a/plugin/idg/gui/dock.py b/plugin/idg/gui/dock.py deleted file mode 100644 index 320f274..0000000 --- a/plugin/idg/gui/dock.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtCore import Qt -from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout -from qgis.gui import QgsDockWidget - -from idg.__about__ import __title__ -from idg.gui.tree_widget import TreeWidget - - -class DockWidget(QgsDockWidget): - """ - The dock widget containing the tree view displaying the Géo2France resources - """ - - def __init__(self, parent=None): - """ """ - super(DockWidget, self).__init__() - self.setObjectName("SimpleAccessDock") - self.init_gui() - - def init_gui(self): - """ """ - self.setWindowTitle(__title__) - self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) - - self.treeWidget = TreeWidget() - - self.layout = QVBoxLayout() - self.layout.setSpacing(2) - self.layout.setMargin(0) - self.layout.addWidget(self.treeWidget) - - self.dockWidgetContents = QWidget() - self.dockWidgetContents.setLayout(self.layout) - self.setWidget(self.dockWidgetContents) - - def set_tree_content(self, resources_tree): - """ - Creates the items of the tree widget - """ - self.treeWidget.set_tree_content(resources_tree) - self.update_visibility_of_tree_items() - - def update_visibility_of_tree_items(self): - """ - Update the visibility of tree items: - - visibility of empty groups - - visibility of items with status = warn - """ - self.treeWidget.update_visibility_of_tree_items() - - def dockStateChanged(self, floating): - """ """ - if floating: - self.resize(300, 450) - else: - pass diff --git a/plugin/idg/gui/param_box.py b/plugin/idg/gui/param_box.py deleted file mode 100644 index 651b52a..0000000 --- a/plugin/idg/gui/param_box.py +++ /dev/null @@ -1,277 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtWidgets import QWidget, QVBoxLayout, QFormLayout, QLabel, QLineEdit, QCheckBox -from qgis.PyQt.QtWidgets import QDialogButtonBox, QMessageBox, QDialog -from qgis.PyQt.QtCore import Qt -from qgis.core import * -from qgis.gui import * - -from idg.toolbelt import PluginGlobals -from idg.toolbelt.tree_node_factory import TreeNodeFactory, download_tree_config_file - - -class ParamBox(QDialog): - """ - Param box of the plugin - """ - - def __init__(self, parent=None, tree_dock=None): - QWidget.__init__(self, parent) - self.tree_dock = tree_dock - - # Init GUI - self.init_gui() - - # Evaluate flags and tupdate the state of the Apply button - self.evaluate_flags() - - def init_gui(self): - """ - """ - dlg_layout = QVBoxLayout() - params_layout = QVBoxLayout() - params_layout.setAlignment(Qt.AlignTop) - - # Config files groupbox - self.config_files_groupbox = QgsCollapsibleGroupBox(u"Fichier de configuration de l'arbre des ressources") - config_file_groupbox_layout = QFormLayout(self.config_files_groupbox) - - # URL of the file - self.config_file_url_label = QLabel(u"URL du fichier", self) - self.config_file_url_edit = QLineEdit(self) - self.config_file_url_edit.editingFinished.connect(self.config_file_url_changed) - config_file_groupbox_layout.addRow(self.config_file_url_label, self.config_file_url_edit) - - # Download the file at startup - self.download_cb = QCheckBox(u"Télécharger le fichier à chaque lancement de QGIS", self) - self.download_cb.stateChanged.connect(self.download_cb_changed) - config_file_groupbox_layout.addRow(self.download_cb) - - params_layout.addWidget(self.config_files_groupbox) - - # Download the file now - self.download_now_label = QLabel(u"Télécharger le fichier maintenant", self) - self.download_now_btnbox = QDialogButtonBox() - self.download_now_btnbox.setOrientation(Qt.Horizontal) - self.download_now_btnbox.setStandardButtons(QDialogButtonBox.Yes) - self.download_now_btnbox.button(QDialogButtonBox.Yes).clicked.connect(self.download_file_now) - config_file_groupbox_layout.addRow(self.download_now_label, self.download_now_btnbox) - - # Content of the resource tree groupbox - self.resource_tree_groupbox = QgsCollapsibleGroupBox(u"Contenu de l'arbre des ressources") - resource_tree_groupbox_layout = QFormLayout(self.resource_tree_groupbox) - - # Hide resources with a warn flag - self.hide_resources_with_warn_status_cb = QCheckBox(u"Masquer les ressources en cours d'intégration", self) - self.hide_resources_with_warn_status_cb.stateChanged.connect(self.hide_resources_with_warn_cb_changed) - resource_tree_groupbox_layout.addRow(self.hide_resources_with_warn_status_cb) - - # Hide empty groups in the resources tree - self.hide_empty_groups_cb = QCheckBox(u"Masquer les groupes de ressources vides", self) - self.hide_empty_groups_cb.stateChanged.connect(self.hide_empty_groups_cb_changed) - resource_tree_groupbox_layout.addRow(self.hide_empty_groups_cb) - - params_layout.addWidget(self.resource_tree_groupbox) - dlg_layout.addLayout(params_layout) - - # Set values - self.set_values_from_qsettings() - - # Bottom dialog buttons - self.button_box = QDialogButtonBox() - self.button_box.setOrientation(Qt.Horizontal) - self.button_box.setStandardButtons( - QDialogButtonBox.RestoreDefaults|QDialogButtonBox.Apply|QDialogButtonBox.Close) - self.button_box.button(QDialogButtonBox.RestoreDefaults).clicked.connect(self.restore_defaults_button_clicked) - self.button_box.button(QDialogButtonBox.Close).clicked.connect(self.close_button_clicked) - self.button_box.button(QDialogButtonBox.Apply).clicked.connect(self.apply_button_clicked) - - # Dialog box title, layout, size and display - title = u"Paramétrage de l'extension Géo2France…" - self.setWindowTitle(title) - dlg_layout.addWidget(self.button_box) - self.setLayout(dlg_layout) - self.setMinimumWidth(500) - self.resize(self.sizeHint()) - self.setSizeGripEnabled(False) - self.setFixedSize(self.size()) - self.show() - self.setSizeGripEnabled(False) - - def set_values_from_qsettings(self): - """ - """ - # URL of the file - self.config_file_url_edit.blockSignals(True) - self.config_file_url_edit.setText(PluginGlobals.instance().CONFIG_FILE_URLS[0]) - self.config_file_url_edit.setCursorPosition(0) - self.config_file_url_edit.blockSignals(False) - - # Download the file at startup - self.download_cb.blockSignals(True) - self.download_cb.setChecked(PluginGlobals.instance().CONFIG_FILES_DOWNLOAD_AT_STARTUP) - self.download_cb.blockSignals(False) - - # Hide resources with a warn flag - self.hide_resources_with_warn_status_cb.blockSignals(True) - self.hide_resources_with_warn_status_cb.setChecked(PluginGlobals.instance().HIDE_RESOURCES_WITH_WARN_STATUS) - self.hide_resources_with_warn_status_cb.blockSignals(False) - - # Hide empty groups in the resources tree - self.hide_empty_groups_cb.blockSignals(True) - self.hide_empty_groups_cb.setChecked(PluginGlobals.instance().HIDE_EMPTY_GROUPS) - self.hide_empty_groups_cb.blockSignals(False) - - def evaluate_flags(self): - """ - """ - # Detect modifications - file_url_changed = (self.config_file_url_edit.text() != PluginGlobals.instance().CONFIG_FILE_URLS[0]) - - download_at_startup_changed = \ - (self.download_cb.isChecked() != PluginGlobals.instance().CONFIG_FILES_DOWNLOAD_AT_STARTUP) - - hide_resources_with_warn_status_changed = \ - (self.hide_resources_with_warn_status_cb.isChecked() != - PluginGlobals.instance().HIDE_RESOURCES_WITH_WARN_STATUS) - - hide_empty_groups_changed = \ - (self.hide_empty_groups_cb.isChecked() != PluginGlobals.instance().HIDE_EMPTY_GROUPS) - - # Init flags - self.need_update_visibility_of_tree_items = hide_empty_groups_changed or hide_resources_with_warn_status_changed - self.need_update_of_tree_content = file_url_changed - self.need_save = file_url_changed or download_at_startup_changed or \ - hide_resources_with_warn_status_changed or \ - hide_empty_groups_changed - - # Update state of the Apply Button - self.button_box.button(QDialogButtonBox.Apply).setEnabled(self.need_save) - - def download_cb_changed(self, state): - """ - Event sent when the state of the checkbox change - """ - self.evaluate_flags() - - def config_file_url_changed(self): - """ - Event sent when the text of the line edit has been edited - """ - self.evaluate_flags() - - def hide_resources_with_warn_cb_changed(self, state): - """ - Event sent when the state of the checkbox change - """ - self.evaluate_flags() - - def hide_empty_groups_cb_changed(self, state): - """ - Event sent when the state of the checkbox change - """ - self.evaluate_flags() - - def download_file_now(self): - """ - """ - # Download, read the resources tree file and update the GUI - download_tree_config_file(self.config_file_url_edit.text()) - self.ressources_tree = TreeNodeFactory(PluginGlobals.instance().config_file_path).root_node - if self.tree_dock is not None: - self.tree_dock.set_tree_content(self.ressources_tree) - - def save_settings(self): - """ - """ - # URL of the file - new_value = [self.config_file_url_edit.text()] - PluginGlobals.instance().set_qgis_settings_value("config_file_urls", new_value) - - # Download the file at startup - new_value = self.download_cb.isChecked() - PluginGlobals.instance().set_qgis_settings_value("config_files_download_at_startup", new_value) - - # Hide resources with a warn flag - new_value = self.hide_resources_with_warn_status_cb.isChecked() - PluginGlobals.instance().set_qgis_settings_value("hide_resources_with_warn_status", new_value) - - # Hide empty groups in the resources tree - new_value = self.hide_empty_groups_cb.isChecked() - PluginGlobals.instance().set_qgis_settings_value("hide_empty_groups", new_value) - - # Download, read the resources tree file and update the GUI - if self.need_update_of_tree_content: - download_tree_config_file(PluginGlobals.instance().CONFIG_FILE_URLS[0]) - self.ressources_tree = TreeNodeFactory(PluginGlobals.instance().config_file_path).root_node - self.tree_dock.set_tree_content(self.ressources_tree) - - # Update the visibility of tree items - elif self.need_update_visibility_of_tree_items and self.tree_dock is not None: - self.tree_dock.update_visibility_of_tree_items() - - def apply_button_clicked(self): - """ - """ - self.save_settings() - self.evaluate_flags() - - def close_button_clicked(self): - """ - """ - self.close() - - def restore_defaults_button_clicked(self): - """ - """ - # URL of the file - self.config_file_url_edit.blockSignals(True) - self.config_file_url_edit.setText(PluginGlobals.instance().get_qgis_setting_default_value( - "CONFIG_FILE_URLS")[0]) - self.config_file_url_edit.setCursorPosition(0) - self.config_file_url_edit.blockSignals(False) - - # Download the file at startup - self.download_cb.blockSignals(True) - self.download_cb.setChecked(PluginGlobals.instance().get_qgis_setting_default_value( - "CONFIG_FILES_DOWNLOAD_AT_STARTUP")) - self.download_cb.blockSignals(False) - - # Hide resources with a warn flag - self.hide_resources_with_warn_status_cb.blockSignals(True) - self.hide_resources_with_warn_status_cb.setChecked(PluginGlobals.instance().get_qgis_setting_default_value( - "HIDE_RESOURCES_WITH_WARN_STATUS")) - self.hide_resources_with_warn_status_cb.blockSignals(False) - - # Hide empty groups in the resources tree - self.hide_empty_groups_cb.blockSignals(True) - self.hide_empty_groups_cb.setChecked(PluginGlobals.instance().get_qgis_setting_default_value( - "HIDE_EMPTY_GROUPS")) - self.hide_empty_groups_cb.blockSignals(False) - - self.evaluate_flags() - - def closeEvent(self, evnt): - """ - """ - - if self.need_save: - reply = QMessageBox.question( - self, - u"Sauvegarder ?", - u"Voulez-vous appliquer les changements avant de fermer la fenêtre de paramétrage de l'extension ?", - QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel, QMessageBox.Yes) - - if reply == QMessageBox.No: - evnt.accept() - super(ParamBox, self).closeEvent(evnt) - elif reply == QMessageBox.Yes: - self.save_settings() - evnt.accept() - super(ParamBox, self).closeEvent(evnt) - - else: - evnt.accept() - super(ParamBox, self).closeEvent(evnt) - - evnt.ignore() diff --git a/plugin/idg/gui/tree_items.py b/plugin/idg/gui/tree_items.py deleted file mode 100644 index c90212a..0000000 --- a/plugin/idg/gui/tree_items.py +++ /dev/null @@ -1,158 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtWidgets import QTreeWidgetItem, QMenu -from qgis.PyQt.QtCore import Qt - -from idg.toolbelt import PluginGlobals - - -def expand_item_and_subitems(item): - """ - """ - if not item.isExpanded(): - item.setExpanded(True) - - nb_subitems = item.childCount() - - for i in range(nb_subitems): - expand_item_and_subitems(item.child(i)) - - -def collapse_item_and_subitems(item): - """ - """ - if item.isExpanded(): - item.setExpanded(False) - - nb_subitems = item.childCount() - - for i in range(nb_subitems): - collapse_item_and_subitems(item.child(i)) - - -def contains_unexpanded_subitems(item): - """ - """ - if not item.isExpanded(): - return True - - nb_subitems = item.childCount() - - for i in range(nb_subitems): - if contains_unexpanded_subitems(item.child(i)): - return True - - return False - - -class TreeWidgetItem(QTreeWidgetItem): - """ - An item of the Géo2France tree view - """ - - def __init__(self, parent, item_data=None): - """ - """ - QTreeWidgetItem.__init__(self, parent) - - # Item data - self.item_data = item_data - - # Item title and description - self.setText(0, item_data.title) - self.setToolTip(0, item_data.description) - - # Item icon - icon = self.item_data.icon - if icon is not None: - self.setIcon(0, icon) - - # QT flags - # Enable selection and drag of the item - if self.item_data.can_be_added_to_map: - self.setFlags(Qt.ItemIsDragEnabled | Qt.ItemIsEnabled | Qt.ItemIsSelectable) - else: - self.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) - - def run_default_action(self): - """ - """ - if self.item_data.can_be_added_to_map: - self.run_add_to_map_action() - - def run_add_to_map_action(self): - """ - Add the resource to the map - """ - self.item_data.run_add_to_map_action() - - def run_show_metadata_action(self): - """ - Displays the resource metadata - """ - self.item_data.run_show_metadata_action() - - def contains_unexpanded_subitems(self): - """ - Determines if subitems are not expanded - """ - if not self.isExpanded(): - return True - else: - return contains_unexpanded_subitems(self) - - def run_expand_all_subitems_action(self): - """ - Expands all subitems - """ - expand_item_and_subitems(self) - - def run_collapse_all_subitems_action(self): - """ - Expands all subitems - """ - collapse_item_and_subitems(self) - - def run_report_issue_action(self): - """ - Report an issue - """ - self.item_data.run_report_issue_action() - - def create_menu(self): - """ - Creates a contextual menu - """ - menu = QMenu() - - if self.item_data.can_be_added_to_map: - add_to_map_action = menu.addAction(u"Ajouter à la carte") - add_to_map_action.triggered.connect(self.run_add_to_map_action) - - if self.item_data.metadata_url: - show_metadata_action = menu.addAction(u"Afficher les métadonnées...") - show_metadata_action.triggered.connect(self.run_show_metadata_action) - - if self.childCount() > 0 and self.contains_unexpanded_subitems(): - expand_all_subitems_action = menu.addAction(u"Afficher tous les descendants") - expand_all_subitems_action.triggered.connect(self.run_expand_all_subitems_action) - - if self.childCount() > 0 and self.isExpanded(): - expand_all_subitems_action = menu.addAction(u"Masquer tous les descendants") - expand_all_subitems_action.triggered.connect(self.run_collapse_all_subitems_action) - - return menu - - def is_an_empty_group(self): - """ - Indicates if this tem is an empty group - """ - child_count = self.childCount() - - if child_count == 0: - return self.item_data.node_type == PluginGlobals.instance().NODE_TYPE_FOLDER - else: - for i in range(child_count): - if not self.child(i).is_an_empty_group(): - return False - return True diff --git a/plugin/idg/gui/tree_widget.py b/plugin/idg/gui/tree_widget.py deleted file mode 100644 index 8c462d3..0000000 --- a/plugin/idg/gui/tree_widget.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtWidgets import QTreeWidget, QAbstractItemView -from qgis.PyQt.QtCore import Qt, QByteArray, QDataStream, QIODevice -from qgis.core import Qgis, QgsMessageLog - -from .tree_items import TreeWidgetItem -from idg.toolbelt import PluginGlobals - - -class TreeWidget(QTreeWidget): - """ - The tree widget used in the Géo2France dock - """ - - def __init__(self): - objectName = 'TreeWidget' - - super(TreeWidget, self).__init__() - - # Selection - self.setSelectionMode(QAbstractItemView.SingleSelection) - - # Columns and headers - self.setColumnCount(1) - self.setHeaderLabel('') - self.setHeaderHidden(True) - - # Events - self.itemDoubleClicked.connect(self.tree_item_double_clicked) - - # Context menu - self.setContextMenuPolicy(Qt.CustomContextMenu) - self.customContextMenuRequested.connect(self.open_menu) - - # Enable drag of tree items - self.setDragEnabled(True) - self.setAcceptDrops(True) - - def set_tree_content(self, resources_tree): - """ - Creates the items of the tree widget - """ - - def create_subitem(subtree, parent_item=self): - """ - """ - subitem = TreeWidgetItem(parent_item, subtree) - if subtree.children is not None and len(subtree.children) > 0: - for child in subtree.children: - create_subitem(child, subitem) - - self.clear() - - if resources_tree is None: - QgsMessageLog.logMessage(u"Faute de fichier de configuration valide, aucune ressource ne peut être chargée " - u"dans le panneau de l'extension Géo2France.", - tag=u"Géo2France", level=Qgis.Warning) - elif resources_tree.children is not None and len(resources_tree.children) > 0: - for child in resources_tree.children: - create_subitem(child, self) - - def update_visibility_of_tree_items(self): - """ - Update the visibility of tree items: - - visibility of empty groups - - visibility of items with status = warn - """ - hide_items_with_warn_status = PluginGlobals.instance().HIDE_RESOURCES_WITH_WARN_STATUS - hide_empty_groups = PluginGlobals.instance().HIDE_EMPTY_GROUPS - - def update_visibility_of_subitems(item, hide_empty_groups, hide_items_with_warn_status): - - if hasattr(item, "item_data") and item.item_data.status == PluginGlobals.instance().NODE_STATUS_WARN: - item.setHidden(hide_items_with_warn_status) - - child_count = item.childCount() - if child_count > 0: - for i in range(child_count): - sub_item = item.child(i) - if sub_item.is_an_empty_group(): - sub_item.setHidden(hide_empty_groups) - - update_visibility_of_subitems(sub_item, hide_empty_groups, hide_items_with_warn_status) - - update_visibility_of_subitems(self.invisibleRootItem(), hide_empty_groups, hide_items_with_warn_status) - - def tree_item_double_clicked(self, item, column): - """ - Handles double clic on an item - """ - item.run_default_action() - - def open_menu(self, position): - """ - Handles context menu in the tree - """ - selected_item = self.currentItem() - menu = selected_item.create_menu() - menu.exec_(self.viewport().mapToGlobal(position)) - - # Constant and methods used for drag and drop of tree items onto the map - - QGIS_URI_MIME = "application/x-vnd.qgis.qgis.uri" - - def mimeTypes(self): - """ - """ - return [self.QGIS_URI_MIME] - - def mimeData(self, items): - """ - """ - mime_data = QTreeWidget.mimeData(self, items) - encoded_data = QByteArray() - stream = QDataStream(encoded_data, QIODevice.WriteOnly) - - for item in items: - layer_mime_data = item.item_data.layer_mime_data() - stream.writeQString(layer_mime_data) - - mime_data.setData(self.QGIS_URI_MIME, encoded_data) - return mime_data - - def dropMimeData(self, parent, index, data, action): - """ - """ - if action == Qt.IgnoreAction: - return True - - return False diff --git a/plugin/idg/plugin_main.py b/plugin/idg/plugin_main.py index c658ea0..8a868b6 100644 --- a/plugin/idg/plugin_main.py +++ b/plugin/idg/plugin_main.py @@ -20,10 +20,7 @@ from idg.toolbelt import PluginGlobals, PlgOptionsManager, IdgProvider, RemotePlatforms -from idg.gui.dock import DockWidget -from idg.gui.about_box import AboutBox -from idg.gui.param_box import ParamBox -from idg.toolbelt.tree_node_factory import TreeNodeFactory, download_tree_config_file, download_all_config_files, download_default_idg_list, DownloadAllConfigFilesAsync +from idg.toolbelt.tree_node_factory import download_all_config_files, download_default_idg_list, DownloadAllConfigFilesAsync import os import json @@ -52,7 +49,7 @@ def __init__(self, iface: QgisInterface): self.tr = plg_translation_mngr.tr PluginGlobals.instance().set_plugin_path(os.path.dirname(os.path.abspath(__file__))) - PluginGlobals.instance().set_plugin_iface(self.iface) + #PluginGlobals.instance().set_plugin_iface(self.iface) PluginGlobals.instance().reload_globals_from_qgis_settings() config_struct = None @@ -113,16 +110,12 @@ def initGui(self): # -- Menu - # Create a menu + # Create a menu self.createPluginMenu() # Add browser IDG provider self.registry.addProvider(self.provider) - # Create a dockable panel with a tree of resources - #self.dock = DockWidget() - #self.dock.set_tree_content(self.ressources_tree) - #self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dock) # dev def populate_browser(self): @@ -146,9 +139,7 @@ def unload(self): Removes the plugin menu """ self.iface.pluginMenu().removeAction(self.plugin_menu.menuAction()) - #self.iface.removeDockWidget(self.dock) - #del self.dock - + #Clean-up browser self.registry.removeProvider(self.provider) @@ -165,28 +156,6 @@ def createPluginMenu(self): self.plugin_menu.addAction(self.action_help) - def showPanelMenuTriggered(self): - """ - Shows the dock widget - """ - self.dock.show() - pass - - def aboutMenuTriggered(self): - """ - Shows the About box - """ - dialog = AboutBox(self.iface.mainWindow()) - dialog.exec_() - - def paramMenuTriggered(self): - """ - Shows the Param box - """ - dialog = ParamBox(self.iface.mainWindow(), self.dock) - dialog.exec_() - - def run(self): """Main process. diff --git a/plugin/idg/toolbelt/__init__.py b/plugin/idg/toolbelt/__init__.py index 0b0b401..841860d 100644 --- a/plugin/idg/toolbelt/__init__.py +++ b/plugin/idg/toolbelt/__init__.py @@ -3,7 +3,6 @@ from .preferences import PlgOptionsManager # noqa: F401 from .translator import PlgTranslator # noqa: F401 from .plugin_globals import PluginGlobals -from .plugin_icons import PluginIcons from .singleton import Singleton from .browser import IdgProvider from .remote_platforms import RemotePlatforms diff --git a/plugin/idg/toolbelt/browser.py b/plugin/idg/toolbelt/browser.py index 4cd67d6..1570c08 100644 --- a/plugin/idg/toolbelt/browser.py +++ b/plugin/idg/toolbelt/browser.py @@ -3,7 +3,7 @@ from qgis.gui import QgisInterface from qgis.PyQt.QtGui import QIcon from qgis.PyQt.Qt import QWidget -from idg.toolbelt import PluginGlobals, PlgOptionsManager, PluginIcons +from idg.toolbelt import PluginGlobals, PlgOptionsManager from .remote_platforms import RemotePlatforms from idg.__about__ import __title__ from qgis.PyQt.QtWidgets import QAction, QMenu diff --git a/plugin/idg/toolbelt/nodes.py b/plugin/idg/toolbelt/nodes.py deleted file mode 100644 index 1c47905..0000000 --- a/plugin/idg/toolbelt/nodes.py +++ /dev/null @@ -1,413 +0,0 @@ -# -*- coding: utf-8 -*- - -import os - -from idg.toolbelt import PluginGlobals -from idg.toolbelt import PluginIcons - - -class FavoritesTreeNode: - """ - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_FOLDER, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - - self.parent_node = parent_node - self.node_type = node_type - self.title = title - self.description = description - self.status = status - self.metadata_url = metadata_url - self.children = [] - self.can_be_added_to_map = False - self.icon = None - - def layer_mime_data(self): - """ - Return the mime data used by the drag and drop process - and needed by QGIS to add the right layer to the map - """ - - qgis_layer_details = self.get_qgis_layer_details() - mime_data = ':'.join([ - qgis_layer_details["type"], - qgis_layer_details["provider"], - qgis_layer_details["title"].replace(":", "\\:"), - qgis_layer_details["uri"].replace(":", "\\:")]) - - return mime_data - - def run_add_to_map_action(self): - """ - """ - - pass - - def run_show_metadata_action(self): - """ - Opens in the default user web browser the web page displaying the resource metadata - """ - - import webbrowser - if self.metadata_url: - webbrowser.open_new_tab(self.metadata_url) - - def run_report_issue_action(self): - """ - Opens the default mail client to let the user send an issue report by email - """ - - # import webbrowser - # webbrowser.open('mailto:') - pass - - -# Subclasses of FavoritesTreeNode - -class FolderTreeNode(FavoritesTreeNode): - """ - Tree node for a folder containing other nodes - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_FOLDER, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.folder_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - -class WmsLayerTreeNode(FavoritesTreeNode): - """ - Tree node for a WMS layer - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_WMS_LAYER, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.service_url = params.get("url") - self.layer_name = params.get("name") - self.layer_format = params.get("format") - self.layer_srs = params.get("srs") - self.layer_style_name = params.get("style", "") - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.wms_layer_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - qgis_layer_uri_details = { - "type": "raster", - "provider": "wms", - "title": self.title, - "uri": u"crs={}&featureCount=10&format={}&layers={}&maxHeight=256&maxWidth=256&styles={}&url={}".format( - self.layer_srs, self.layer_format, self.layer_name, self.layer_style_name, self.service_url) - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the WMS layer with the specified style to the map - """ - qgis_layer_details = self.get_qgis_layer_details() - PluginGlobals.instance().iface.addRasterLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"], - qgis_layer_details["provider"]) - - -class WmsStyleLayerTreeNode(FavoritesTreeNode): - """ - Tree node for a WMS layer with a specific style - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_WMS_LAYER_STYLE, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.layer_style_name = params.get("name") - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.wms_style_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - if self.parent_node is None: - return None - - qgis_layer_uri_details = { - "type": "raster", - "provider": "wms", - "title": self.title, - "uri": u"crs={}&featureCount=10&format={}&layers={}&maxHeight=256&maxWidth=256&styles={}&url={}".format( - self.parent_node.layer_srs, self.parent_node.layer_format, self.parent_node.layer_name, - self.layer_style_name, self.parent_node.service_url) - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the WMS layer with the specified style to the map - """ - - qgis_layer_details = self.get_qgis_layer_details() - if qgis_layer_details is not None: - PluginGlobals.instance().iface.addRasterLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"], - qgis_layer_details["provider"]) - - -class WmtsLayerTreeNode(FavoritesTreeNode): - """ - Tree node for a WMTS layer - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_WMTS_LAYER, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.service_url = params.get("url") - self.layer_tilematrixset_name = params.get("tilematrixset_name") - self.layer_name = params.get("name") - self.layer_format = params.get("format") - self.layer_srs = params.get("srs") - self.layer_style_name = params.get("style", "") - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.wms_style_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - qgis_layer_uri_details = { - "type": "raster", - "provider": "wms", - "title": self.title, - "uri": u"tileMatrixSet={}&crs={}&featureCount=10&format={}&layers={}&maxHeight=256&maxWidth=256&styles={}&url={}".format( - self.layer_tilematrixset_name, self.layer_srs, self.layer_format, self.layer_name, - self.layer_style_name, self.service_url) - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the WMTS layer to the map - """ - qgis_layer_details = self.get_qgis_layer_details() - if qgis_layer_details is not None: - PluginGlobals.instance().iface.addRasterLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"], - qgis_layer_details["provider"]) - - -class WfsFeatureTypeTreeNode(FavoritesTreeNode): - """ - Tree node for a WFS feature type - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_WFS_FEATURE_TYPE, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.service_url = params.get("url") - self.feature_type_name = params.get("name") - self.filter = params.get("filter") - self.wfs_version = params.get("version", "1.0.0") - self.layer_srs = params.get("srs") - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.wfs_layer_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - - first_param_prefix = '?' - if '?' in self.service_url: - first_param_prefix = '&' - - uri = u"{}{}SERVICE=WFS&VERSION={}&REQUEST=GetFeature&TYPENAME={}&SRSNAME={}".format( - self.service_url, first_param_prefix, self.wfs_version, self.feature_type_name, self.layer_srs) - - if self.filter: - uri += "&Filter={}".format(self.filter) - - qgis_layer_uri_details = { - "type": "vector", - "provider": "WFS", - "title": self.title, - "uri": uri - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the WFS feature type to the map - """ - qgis_layer_details = self.get_qgis_layer_details() - if qgis_layer_details is not None: - PluginGlobals.instance().iface.addVectorLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"], - qgis_layer_details["provider"]) - - -class WfsFeatureTypeFilterTreeNode(FavoritesTreeNode): - """ - Tree node for a WFS feature type filter - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_WFS_FEATURE_TYPE_FILTER, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.filter = params.get("filter") - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.wfs_layer_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - - if self.parent_node is None: - return None - - first_param_prefix = '?' - if '?' in self.parent_node.service_url: - first_param_prefix = '&' - - uri = u"{}{}SERVICE=WFS&VERSION={}&REQUEST=GetFeature&TYPENAME={}&SRSNAME={}".format( - self.parent_node.service_url, first_param_prefix, self.parent_node.wfs_version, - self.parent_node.feature_type_name, self.parent_node.layer_srs) - - if self.filter: - uri += "&Filter={}".format(self.filter) - - qgis_layer_uri_details = { - "type": "vector", - "provider": "WFS", - "title": self.title, - "uri": uri - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the WFS feature type to the map with a filter - """ - - qgis_layer_details = self.get_qgis_layer_details() - if qgis_layer_details is not None: - PluginGlobals.instance().iface.addVectorLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"], - qgis_layer_details["provider"]) - - -class GdalWmsConfigFileTreeNode(FavoritesTreeNode): - """ - Tree node for a GDAL WMS config file - """ - - def __init__(self, title, node_type=PluginGlobals.instance().NODE_TYPE_GDAL_WMS_CONFIG_FILE, - description=None, status=None, metadata_url=None, params=None, parent_node=None): - """ - """ - FavoritesTreeNode.__init__(self, title, node_type, description, status, metadata_url, params, parent_node) - - self.gdal_config_file_path = os.path.join( - PluginGlobals.instance().config_dir_path, - params.get("file_path")) - self.can_be_added_to_map = True - - # Icon - plugin_icons = PluginIcons.instance() - self.icon = plugin_icons.raster_layer_icon - if self.status == PluginGlobals.instance().NODE_STATUS_WARN: - self.icon = plugin_icons.warn_icon - - def get_qgis_layer_details(self): - """ - Return the details of the layer used by QGIS to add the layer to the map. - This dictionary is used by the run_add_to_map_action and layerMimeData methods. - """ - qgis_layer_uri_details = { - "type": "raster", - "provider": "gdal", - "title": self.title, - "uri": self.gdal_config_file_path.replace("\\", "/") - } - - return qgis_layer_uri_details - - def run_add_to_map_action(self): - """ - Add the preconfigured TMS layer to the map - """ - # PluginGlobals.instance().iface.addRasterLayer(self.gdal_config_file_path, self.title) - qgis_layer_details = self.get_qgis_layer_details() - if qgis_layer_details is not None: - PluginGlobals.instance().iface.addRasterLayer( - qgis_layer_details["uri"], - qgis_layer_details["title"]) diff --git a/plugin/idg/toolbelt/plugin_globals.py b/plugin/idg/toolbelt/plugin_globals.py index 939a61e..8107b9e 100644 --- a/plugin/idg/toolbelt/plugin_globals.py +++ b/plugin/idg/toolbelt/plugin_globals.py @@ -14,79 +14,23 @@ class PluginGlobals: iface = None plugin_path = None - - # Plugin infos PLUGIN_TAG = u"IDG" - PLUGIN_VERSION = u"0.9.1" - PLUGIN_SOURCE_REPOSITORY = u"https://github.com/geo2france/geo2france-qgis3-plugin" - - # Tree nodes types - NODE_TYPE_FOLDER = "folder" - NODE_TYPE_WS = "web_service" - NODE_TYPE_WMS_LAYER = "wms_layer" - NODE_TYPE_WMTS_LAYER = "wmts_layer" - NODE_TYPE_WMS_LAYER_STYLE = "wms_layer_style" - NODE_TYPE_WFS_FEATURE_TYPE = "wfs_feature_type" - NODE_TYPE_WFS_FEATURE_TYPE_FILTER = "wfs_feature_type_filter" - NODE_TYPE_GDAL_WMS_CONFIG_FILE = "gdal_wms_config_file" - - # Node status values - NODE_STATUS_WARN = 'warn' - - # Images dir - IMAGES_DIR_NAME = "images" - LOGO_FILE_NAME = "logo_geo2france.png" - - ICON_WARN_FILE_NAME = "mIconWarning.svg" - ICON_WMS_LAYER_FILE_NAME = "mIconWms.svg" - ICON_WMS_STYLE_FILE_NAME = "mIconWmsStyle.svg" - ICON_WFS_LAYER_FILE_NAME = "mIconWfs.svg" - ICON_RASTER_LAYER_FILE_NAME = "mIconRaster.svg" - - # Config files dir - CONFIG_FILES_DOWNLOAD_AT_STARTUP = PlgOptionsManager().get_value_from_key('config_files_download_at_startup') CONFIG_DIR_NAME = "config" CONFIG_FILE_NAMES = ["projet_idg.qgs"] - CONFIG_FILE_URLS = ["http://127.0.0.1:8000/projet_idg.qgs"] - - # Hide resources with status = warn - HIDE_RESOURCES_WITH_WARN_STATUS = PlgOptionsManager().get_value_from_key('hide_resources_with_warn_status') - - # Hide empty group in the resources tree - HIDE_EMPTY_GROUPS = PlgOptionsManager().get_value_from_key('hide_empty_groups') - + CONFIG_FILES_DOWNLOAD_AT_STARTUP = PlgOptionsManager().get_value_from_key('config_files_download_at_startup') def __init__(self): - """ - """ - self.default_qsettings = { - "CONFIG_FILES_DOWNLOAD_AT_STARTUP": self.CONFIG_FILES_DOWNLOAD_AT_STARTUP, - "CONFIG_FILE_NAMES": self.CONFIG_FILE_NAMES, - "CONFIG_FILE_URLS": self.CONFIG_FILE_URLS, - "HIDE_RESOURCES_WITH_WARN_STATUS": self.HIDE_RESOURCES_WITH_WARN_STATUS, - "HIDE_EMPTY_GROUPS": self.HIDE_EMPTY_GROUPS + "CONFIG_FILE_NAMES": self.CONFIG_FILE_NAMES } - self.config_dir_path = None self.config_file_path = None self.images_dir_path = None self.logo_file_path = None - def set_plugin_path(self, plugin_path): - """ - """ - - # system_encoding = sys.getfilesystemencoding() - # self.plugin_path = plugin_path.decode(system_encoding) + def set_plugin_path(self, plugin_path): self.plugin_path = plugin_path - def set_plugin_iface(self, iface): - """ - """ - - self.iface = iface - def reload_globals_from_qgis_settings(self): """ Reloads the global variables of the plugin @@ -103,53 +47,5 @@ def reload_globals_from_qgis_settings(self): self.CONFIG_FILE_NAMES = s.value(u"{0}/config_file_names".format(self.PLUGIN_TAG), self.CONFIG_FILE_NAMES) - self.CONFIG_FILE_URLS = s.value(u"{0}/config_file_urls".format(self.PLUGIN_TAG), self.CONFIG_FILE_URLS) - - self.HIDE_RESOURCES_WITH_WARN_STATUS = True if s.value( - u"{0}/hide_resources_with_warn_status".format(self.PLUGIN_TAG), - self.HIDE_RESOURCES_WITH_WARN_STATUS) == u"1" else False - - self.HIDE_EMPTY_GROUPS = True if s.value( - u"{0}/hide_empty_groups".format(self.PLUGIN_TAG), self.HIDE_EMPTY_GROUPS) == u"1" else False - self.config_dir_path = os.path.join(self.plugin_path, self.CONFIG_DIR_NAME) self.config_file_path = os.path.join(self.config_dir_path, self.CONFIG_FILE_NAMES[0]) - - self.images_dir_path = os.path.join(self.plugin_path, self.IMAGES_DIR_NAME) - self.logo_file_path = os.path.join(self.images_dir_path, self.LOGO_FILE_NAME) - - def reset_to_defaults(self): - """ - Reset global variables to default values - """ - - s = QSettings() - s.setValue(u"{0}/hide_resources_with_warn_status".format(self.PLUGIN_TAG), u"1") - s.setValue(u"{0}/hide_empty_groups".format(self.PLUGIN_TAG), u"1") - s.setValue(u"{0}/config_files_download_at_startup".format(self.PLUGIN_TAG), u"0") - s.setValue(u"{0}/config_file_names".format(self.PLUGIN_TAG), self.CONFIG_FILE_NAMES) - s.setValue(u"{0}/config_file_urls".format(self.PLUGIN_TAG), - self.CONFIG_FILE_URLS) - - def get_qgis_setting_default_value(self, setting): - """ - """ - - return self.default_qsettings.get(setting, None) - - def set_qgis_settings_value(self, setting, value): - """ - Update a settings value - """ - - s = QSettings() - - # Convert boolean in unicode string - if type(value) == bool: - value = u"1" if value else u"0" - - # Save the settings value - s.setValue(u"{0}/{1}".format(self.PLUGIN_TAG, setting), value) - - # Reload all settings values - self.reload_globals_from_qgis_settings() diff --git a/plugin/idg/toolbelt/plugin_icons.py b/plugin/idg/toolbelt/plugin_icons.py deleted file mode 100644 index 5bc7bd6..0000000 --- a/plugin/idg/toolbelt/plugin_icons.py +++ /dev/null @@ -1,43 +0,0 @@ -# -*- coding: utf-8 -*- - -from qgis.PyQt.QtGui import QIcon -from qgis.PyQt.QtWidgets import QStyle - -from qgis.core import QgsApplication -import os - -from .plugin_globals import PluginGlobals -from .singleton import Singleton - - -@Singleton -class PluginIcons(): - """ - """ - - def __init__(self): - """ - """ - - # Folder icon - QgsApplication.initQgis() - style = QgsApplication.style() - self.folder_icon = style.standardIcon(QStyle.SP_DirClosedIcon) - - self.warn_icon = style.standardIcon(QStyle.SP_MessageBoxCritical) - - wms_layer_icon_path = os.path.join(PluginGlobals.instance().images_dir_path, - PluginGlobals.instance().ICON_WMS_LAYER_FILE_NAME) - self.wms_layer_icon = QIcon(wms_layer_icon_path) - - wms_style_icon_path = os.path.join(PluginGlobals.instance().images_dir_path, - PluginGlobals.instance().ICON_WMS_STYLE_FILE_NAME) - self.wms_style_icon = QIcon(wms_style_icon_path) - - wfs_layer_icon_path = os.path.join(PluginGlobals.instance().images_dir_path, - PluginGlobals.instance().ICON_WFS_LAYER_FILE_NAME) - self.wfs_layer_icon = QIcon(wfs_layer_icon_path) - - raster_layer_icon_path = os.path.join(PluginGlobals.instance().images_dir_path, - PluginGlobals.instance().ICON_RASTER_LAYER_FILE_NAME) - self.raster_layer_icon = QIcon(raster_layer_icon_path) diff --git a/plugin/idg/toolbelt/remote_platforms.py b/plugin/idg/toolbelt/remote_platforms.py index 3e3d7a7..2cb9e78 100644 --- a/plugin/idg/toolbelt/remote_platforms.py +++ b/plugin/idg/toolbelt/remote_platforms.py @@ -42,15 +42,15 @@ def reset(self): os.remove(chemin_fichier) download_default_idg_list() - download_all_config_files(RemotePlatforms().stock_idgs) + download_all_config_files(RemotePlatforms().stock_idgs) # TODO Utiliser le téléchargement asynchrone #TODO remove all local files (projects & images) class Plateform: - def __init__(self, url, idg_id): + def __init__(self, url, idg_id): #TODO ajouter un paramètre "dry" ? self.url=url self.idg_id=idg_id - self.project=self.read_project() + self.project=self.read_project() #TODO pas ici, car on peut avoir besoin d'instancier un projet sans avoir télécharger le fichier projet def read_project(self): p = QgsProject() diff --git a/plugin/idg/toolbelt/tree_node_factory.py b/plugin/idg/toolbelt/tree_node_factory.py index 24ae26b..7a919c8 100644 --- a/plugin/idg/toolbelt/tree_node_factory.py +++ b/plugin/idg/toolbelt/tree_node_factory.py @@ -11,15 +11,13 @@ QgsProject, QgsNetworkAccessManager, QgsNetworkReplyContent, - QgsFileDownloader ) from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply from qgis.PyQt.QtCore import QUrl, QThread, pyqtSignal from idg.toolbelt import PluginGlobals from .network_manager import NetworkRequestsManager -from .nodes import WmsLayerTreeNode, WmsStyleLayerTreeNode, WmtsLayerTreeNode, WfsFeatureTypeTreeNode -from .nodes import WfsFeatureTypeFilterTreeNode, GdalWmsConfigFileTreeNode, FolderTreeNode + def download_default_idg_list(url='https://raw.githubusercontent.com/geo2france/idg-qgis-plugin/dev/plugin/idg/config/default_idg.json'): @@ -43,10 +41,6 @@ def download_default_idg_list(url='https://raw.githubusercontent.com/geo2france/ #TOD gérer les erreur (garder le fichier précédent + avertissement) def download_all_config_files(idgs): #remplacer la list par un dict ({idg_id:url}) - #for i in idgs: - # print('a') - # print(i) - """Download all config file in dict key = IDG_id, value = url rename local file @@ -56,16 +50,8 @@ def download_all_config_files(idgs): #remplacer la list par un dict ({idg_id:url for idg_id, url in idgs.items(): #continue si l'IDG est masquée idg_id = str(idg_id) - request = QNetworkRequest(QUrl(url)) - manager = QgsNetworkAccessManager.instance() - response: QgsNetworkReplyContent = manager.blockingGet( - request, forceRefresh=True - ) - suffix = os.path.splitext(os.path.basename(url))[-1] local_file_name = qntwk.download_file(url, os.path.join(PluginGlobals.instance().config_dir_path, idg_id + suffix)) if local_file_name : - with open(local_file_name, "wb") as local_config_file: - local_config_file.write(response.content()) # Download icon if custom TODO a factoriser project = QgsProject() project.read(local_file_name, QgsProject.ReadFlags()|QgsProject.FlagDontResolveLayers|QgsProject.FlagDontLoadLayouts) @@ -74,7 +60,6 @@ def download_all_config_files(idgs): #remplacer la list par un dict ({idg_id:url suffix = os.path.splitext(os.path.basename(l.url))[-1] qntwk.download_file(l.url, os.path.join(PluginGlobals.instance().config_dir_path, idg_id + suffix) ) break - else : short_message = "Le téléchargement du fichier projet {0} a échoué.".format(idg_id) PluginGlobals.instance().iface.messageBar().pushMessage( @@ -108,181 +93,3 @@ def run(self): self.finished.emit() -def download_tree_config_file(file_url): - """ - Download the resources tree file - """ - try: - request = QNetworkRequest(QUrl(file_url)) - manager = QgsNetworkAccessManager.instance() - response: QgsNetworkReplyContent = manager.blockingGet( - request, forceRefresh=True - ) - if response.error() != QNetworkReply.NoError: - raise Exception(f"{response.error()} - {response.errorString()}") - # replace content of local config file by content of online config file - if file_url.endswith('.json'): # utiliser plutôt le MIME ? - with open(PluginGlobals.instance().config_file_path, "w") as local_config_file: - data_raw_string = bytes(response.content()).decode("utf-8") - data = json.loads(data_raw_string) - json.dump(data, local_config_file, ensure_ascii=False, indent=2) # Ecrit dans le fichier - else: # Assuming qgs/qgz - with open(PluginGlobals.instance().config_file_path, "wb") as local_config_file: - local_config_file.write(response.content()) - except Exception as e: - short_message = "Le téléchargement du fichier de configuration du plugin {0} a échoué.".format( - PluginGlobals.instance().PLUGIN_TAG - ) - PluginGlobals.instance().iface.messageBar().pushMessage( - "Erreur", short_message, level=Qgis.Critical - ) - - long_message = "{0}\nUrl du fichier : {1}\n{2}\n{3}".format( - short_message, file_url, e.__doc__, e - ) - QgsMessageLog.logMessage( - long_message, tag=PluginGlobals.instance().PLUGIN_TAG, level=Qgis.Critical - ) - - -class TreeNodeFactory: - """ - Class used to build FavoritesTreeNode instances - """ - - def __init__(self, file_path): - print(file_path) - self.file_path = file_path - self.root_node = None - - if not os.path.isfile(self.file_path): - message = u"Le fichier de configuration du plugin {0} n'a pas pu être trouvé.".format( - PluginGlobals.instance().PLUGIN_TAG) - PluginGlobals.instance().iface.messageBar().pushMessage("Erreur", message, level=Qgis.Critical) - QgsMessageLog.logMessage(message, tag=PluginGlobals.instance().PLUGIN_TAG, level=Qgis.Critical) - return - - try: - # Read the config file - # QgsMessageLog.logMessage("Config file path: {}".format(self.file_path, - # tag=PluginGlobals.instance().PLUGIN_TAG, - # level=Qgis.Info)) - if PluginGlobals.instance().CONFIG_FILE_URLS[0].endswith('json'): # TODO parser proprement l'url - with open(self.file_path, encoding='utf-8', errors='replace') as f: - config_string = "".join(f.readlines()) - config_struct = json.loads(config_string) - self.root_node = self.build_tree(config_struct) - else : # assume qgs/qgz file - project = QgsProject() - project.read(self.file_path) - self.root_node = self.build_tree_from_project_file(project) - - except Exception as e: - short_message = u"La lecture du fichier de configuration du plugin {0} a produit des erreurs.".format( - PluginGlobals.instance().PLUGIN_TAG) - PluginGlobals.instance().iface.messageBar().pushMessage("Erreur", short_message, level=Qgis.Critical) - - long_message = u"{0}\n{1}\n{2}".format(short_message, e.__doc__, e) - QgsMessageLog.logMessage(long_message, tag=PluginGlobals.instance().PLUGIN_TAG, level=Qgis.Critical) - QgsMessageLog.logMessage( - "".join(traceback.format_exc()), tag=PluginGlobals.instance().PLUGIN_TAG, level=Qgis.Critical - ) - QgsMessageLog.logMessage( - "".join(traceback.format_stack()), tag=PluginGlobals.instance().PLUGIN_TAG, level=Qgis.Critical - ) - raise #dev - - def build_tree(self, tree_config, parent_node=None): - """ - Function that do the job - """ - - # Read the node attributes - node_title = tree_config.get('title', None) - node_description = tree_config.get('description', None) - node_type = tree_config.get('type', None) - node_status = tree_config.get('status', None) - node_metadata_url = tree_config.get('metadata_url', None) - node_params = tree_config.get('params', None) - - if node_title: - node = self.auto_node_type(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - # Creation of the node children - node_children = tree_config.get('children', []) - if len(node_children) > 0: - for child_config in node_children: - child_node = self.build_tree(child_config, node) - node.children.append(child_node) - - return node - - else: - return None - - def auto_node_type(self, node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node): - # Creation of the node - if node_type == PluginGlobals.instance().NODE_TYPE_WMS_LAYER: - node = WmsLayerTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - elif node_type == PluginGlobals.instance().NODE_TYPE_WMS_LAYER_STYLE: - node = WmsStyleLayerTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - elif node_type == PluginGlobals.instance().NODE_TYPE_WMTS_LAYER: - node = WmtsLayerTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - elif node_type == PluginGlobals.instance().NODE_TYPE_WFS_FEATURE_TYPE: - node = WfsFeatureTypeTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - elif node_type == PluginGlobals.instance().NODE_TYPE_WFS_FEATURE_TYPE_FILTER: - node = WfsFeatureTypeFilterTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - elif node_type == PluginGlobals.instance().NODE_TYPE_GDAL_WMS_CONFIG_FILE: - node = GdalWmsConfigFileTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - - else: - node = FolderTreeNode(node_title, node_type, node_description, - node_status, node_metadata_url, node_params, parent_node) - return node - def build_tree_from_project_file(self, project): - node = FolderTreeNode(title='Project title') - for element in project.layerTreeRoot().children(): - if hasattr(element,'layer'): - layer = element.layer() - params=self.extract_params_from_layer(layer) # Sortir de l'URL les paramètres nécessaire (url, version, name, srs) - node_type=self.provider_to_node_type(layer.dataProvider().name()) - node.children.append(self.auto_node_type(node_title=layer.name(), node_type=node_type, node_description=layer.metadata().abstract(), - node_status=None, node_metadata_url=next(iter(layer.metadata().links()),''), node_params=params, parent_node=node)) - return node - - def extract_params_from_layer(self, layer): - out=dict() - out['srs'] = layer.crs().authid() - if layer.dataProvider().name().lower() == 'wms': - parsed_url = urlparse('http://0.0.0.0?' + layer.source()) #Ajout d'un host fictif pour parser l'url car la source wms n'en contient pas - out['url'] = layer.source() #certains parametre sont doublés (layers, srs, etc..) mais pas gênant - out['name'] = parse_qs(parsed_url.query)['layers'][0] - out['format'] = parse_qs(parsed_url.query)['format'][0] - out['version'] = layer.dataProvider().htmlMetadata().split('WMS Version')[1][:5] - return out - elif layer.dataProvider().name().lower() == 'wfs': - parsed_url = urlparse(layer.source()) - out['url'] = layer.source() - out['name'] = parse_qs(parsed_url.query)['TYPENAME'][0] - out['version'] = parse_qs(parsed_url.query)['VERSION'][0] - return out - - def provider_to_node_type(self, provider_key): - """ - Convert qgis provider key to node_type - """ - mapping = {'wfs':'wfs_feature_type', 'wms':'wms_layer','wmts': 'wmts_layer'} - return mapping[provider_key.lower()] \ No newline at end of file From 82f2f9337c9047d294d6bc2e6e92bd99a6d5a62e Mon Sep 17 00:00:00 2001 From: JB Desbas Date: Wed, 2 Aug 2023 13:56:52 +0200 Subject: [PATCH 2/9] coquilles readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0fb9640..c8ab6a9 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Pré-requis : Créer un nouveau projet et y ajouter les couches que vous souhaitez diffuser. > **Warning** -> Les couches doivent pouvoir être accessible depuis n'importe où (fichiers distants, flux WMS/WFS, etc.), il ne doit **pas** s'agir de fichiers locaux. +> Les couches doivent pouvoir être accessibles depuis n'importe où (fichiers distants, flux WMS/WFS, etc.), il ne doit **pas** s'agir de fichiers locaux. Il est recommandé d'[organiser les couches en groupes et sous-groupes](https://docs.qgis.org/3.22/fr/docs/user_manual/introduction/general_tools.html#group-layers-interact). @@ -39,7 +39,7 @@ Dans les propriétés du projets, remplir les champs suivants : - **Métadonnées > Identification > Titre** : Le nom de la plateforme qui sera visible par l'utilisateur (ex : Geo2France) - **Métadonnées > Identification > Résumé** : Facultatif, une brève présentation qui sera visible au survol - **Métadonnées > Liens** : Vous pouvez ajouter ici des liens vers les différents services de votre plateforme (ex : contact, catalogue, etc.) - Ceux-ci seront accessibles à l'utilisateur via un clic droit sur le nom de la plateforme. Ajoutez un lien nommé `icon` pour définir une icône à la plateforme (png ou svg) + Ceux-ci seront accessibles à l'utilisateur via un clic droit sur le nom de la plateforme. Ajoutez un lien nommé `icon` pour ajouter une icône personnalisée à la plateforme (png ou svg) Pour chaque couche, vous pouvez définir : - **Métadonnées > Identification > Titre & Réumé** Un titre et un résumé From c78269be7415bb280f3a5f1ca3db851a5dc2261b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Mon, 27 Nov 2023 09:32:28 +0100 Subject: [PATCH 3/9] defaults idg: add ign geoplateforme --- plugin/idg/config/default_idg.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/idg/config/default_idg.json b/plugin/idg/config/default_idg.json index be26f01..597e140 100644 --- a/plugin/idg/config/default_idg.json +++ b/plugin/idg/config/default_idg.json @@ -1,4 +1,5 @@ { + "Géoplateforme": "https://raw.githubusercontent.com/Geoplateforme/plugin_idg_gpf/master/projet_idg_gpf.qgz", "geo2france": "https://www.geo2france.fr/public/qgis3/plugins/geo2france/geo2france.qgs", "OPenIG": "https://raw.githubusercontent.com/openig/Plugin-QGIS3-OPenIG/master/OPenIG_qgis_plugin.qgs", "DataGrandEst": "https://www.datagrandest.fr/tools/plugin-qgis-datagrandest/config-plugin-idg-datagrandest.qgz", From dd5adc93a7eaac325a782caa28a8afa29cb3bf4e Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 12:01:50 +0100 Subject: [PATCH 4/9] download all files Async --- plugin/idg/plugin_main.py | 19 ++++---- plugin/idg/toolbelt/remote_platforms.py | 8 ++-- plugin/idg/toolbelt/tree_node_factory.py | 56 +++++------------------- 3 files changed, 25 insertions(+), 58 deletions(-) diff --git a/plugin/idg/plugin_main.py b/plugin/idg/plugin_main.py index 8a868b6..e59d784 100644 --- a/plugin/idg/plugin_main.py +++ b/plugin/idg/plugin_main.py @@ -10,7 +10,7 @@ from qgis.PyQt.QtCore import QCoreApplication, Qt from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction, QMenu -from qgis.utils import showPluginHelp +from qgis.utils import showPluginHelp, active_plugins # project from idg.__about__ import __title__ @@ -20,7 +20,7 @@ from idg.toolbelt import PluginGlobals, PlgOptionsManager, IdgProvider, RemotePlatforms -from idg.toolbelt.tree_node_factory import download_all_config_files, download_default_idg_list, DownloadAllConfigFilesAsync +from idg.toolbelt.tree_node_factory import DownloadAllConfigFilesAsync, DownloadDefaultIdgListAsync import os import json @@ -41,7 +41,6 @@ def __init__(self, iface: QgisInterface): self.log = PlgLogger().log self.dock = None - # translation plg_translation_mngr = PlgTranslator() translator = plg_translation_mngr.get_translator() if translator: @@ -58,16 +57,17 @@ def __init__(self, iface: QgisInterface): self.registry = QgsApplication.dataItemProviderRegistry() self.provider = IdgProvider(self.iface) - self.iface.initializationCompleted.connect(self.post_ui_init) - + #self.iface.initializationCompleted.connect(self.post_ui_init) + self.post_ui_init() def post_ui_init(self): """Run after plugin's UI has been initialized.""" - download_default_idg_list() # TODO a passer en asynchrone aussi ? - self.task = DownloadAllConfigFilesAsync(RemotePlatforms().stock_idgs) - self.task.finished.connect(self.populate_browser) - self.task.start() + self.task1 = DownloadDefaultIdgListAsync() + self.task2 = DownloadAllConfigFilesAsync(RemotePlatforms().stock_idgs) + self.task1.finished.connect(self.task2.start) + self.task2.finished.connect(self.populate_browser) + self.task1.start() def need_download_tree_config_file(self): """ Do we need to download a new version of the resources tree file? @@ -161,6 +161,7 @@ def run(self): :raises Exception: if there is no item in the feed """ + # Jamais utilisé ? try: self.log( message=self.tr( diff --git a/plugin/idg/toolbelt/remote_platforms.py b/plugin/idg/toolbelt/remote_platforms.py index 2cb9e78..3bbe952 100644 --- a/plugin/idg/toolbelt/remote_platforms.py +++ b/plugin/idg/toolbelt/remote_platforms.py @@ -2,7 +2,7 @@ QgsLayerTreeLayer, QgsLayerTreeGroup, QgsMimeDataUtils, QgsAbstractMetadataBase, QgsApplication, QgsIconUtils from qgis.PyQt.QtGui import QIcon -from idg.toolbelt.tree_node_factory import download_default_idg_list, download_all_config_files +from idg.toolbelt.tree_node_factory import DownloadAllConfigFilesAsync, DownloadDefaultIdgListAsync from idg.toolbelt import PlgOptionsManager, PluginGlobals import json @@ -41,8 +41,10 @@ def reset(self): if os.path.isfile(chemin_fichier): os.remove(chemin_fichier) - download_default_idg_list() - download_all_config_files(RemotePlatforms().stock_idgs) # TODO Utiliser le téléchargement asynchrone + self.task1 = DownloadDefaultIdgListAsync() + self.task2 = DownloadAllConfigFilesAsync(RemotePlatforms().stock_idgs) + self.task1.finished.connect(self.task2.start) + self.task2.finished.connect(self.populate_browser) #TODO remove all local files (projects & images) diff --git a/plugin/idg/toolbelt/tree_node_factory.py b/plugin/idg/toolbelt/tree_node_factory.py index 7a919c8..4c6c7e3 100644 --- a/plugin/idg/toolbelt/tree_node_factory.py +++ b/plugin/idg/toolbelt/tree_node_factory.py @@ -18,54 +18,18 @@ from idg.toolbelt import PluginGlobals from .network_manager import NetworkRequestsManager +class DownloadDefaultIdgListAsync(QThread): + finished = pyqtSignal() + def __init__(self, url='https://raw.githubusercontent.com/geo2france/idg-qgis-plugin/dev/plugin/idg/config/default_idg.json'): + super(QThread, self).__init__() + self.url=url + def run(self): + qntwk = NetworkRequestsManager() + local_file_name = qntwk.download_file(self.url, os.path.join(PluginGlobals.instance().config_dir_path, + 'default_idg.json')) + self.finished.emit() -def download_default_idg_list(url='https://raw.githubusercontent.com/geo2france/idg-qgis-plugin/dev/plugin/idg/config/default_idg.json'): - local_file = os.path.join(PluginGlobals.instance().config_dir_path, 'default_idg.json') - request = QNetworkRequest(QUrl(url)) - manager = QgsNetworkAccessManager.instance() - request.setTransferTimeout(5000) - response: QgsNetworkReplyContent = manager.blockingGet( - request, forceRefresh=True - ) - qntwk = NetworkRequestsManager() - local_file_name = qntwk.download_file(url, os.path.join(PluginGlobals.instance().config_dir_path, 'default_idg.json')) - if local_file_name is not None: - #try: - # os.remove(local_file) - #except OSError: - # pass - with open(local_file, "r") as local_config_file: - out = json.load(local_config_file) - return out - #TOD gérer les erreur (garder le fichier précédent + avertissement) - -def download_all_config_files(idgs): #remplacer la list par un dict ({idg_id:url}) - """Download all config file in dict - key = IDG_id, value = url - rename local file - """ - #TODO a passer dans RemotePlatforms - qntwk = NetworkRequestsManager() - for idg_id, url in idgs.items(): - #continue si l'IDG est masquée - idg_id = str(idg_id) - local_file_name = qntwk.download_file(url, os.path.join(PluginGlobals.instance().config_dir_path, idg_id + suffix)) - if local_file_name : - # Download icon if custom TODO a factoriser - project = QgsProject() - project.read(local_file_name, QgsProject.ReadFlags()|QgsProject.FlagDontResolveLayers|QgsProject.FlagDontLoadLayouts) - for l in project.metadata().links(): - if l.name.lower().strip() == 'icon': - suffix = os.path.splitext(os.path.basename(l.url))[-1] - qntwk.download_file(l.url, os.path.join(PluginGlobals.instance().config_dir_path, idg_id + suffix) ) - break - else : - short_message = "Le téléchargement du fichier projet {0} a échoué.".format(idg_id) - PluginGlobals.instance().iface.messageBar().pushMessage( - "Erreur", short_message, level=Qgis.Warning - ) - class DownloadAllConfigFilesAsync(QThread): finished = pyqtSignal() def __init__(self, idgs): From 6e8fa34eb8aa84e6ba6c937123335fdf78359b9b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 13:33:25 +0100 Subject: [PATCH 5/9] RemotePlateforms est trop couteux ici, on lit directement les adresse des IDG depuis le json --- plugin/idg/plugin_main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/idg/plugin_main.py b/plugin/idg/plugin_main.py index e59d784..2534a40 100644 --- a/plugin/idg/plugin_main.py +++ b/plugin/idg/plugin_main.py @@ -40,7 +40,6 @@ def __init__(self, iface: QgisInterface): self.iface = iface self.log = PlgLogger().log self.dock = None - plg_translation_mngr = PlgTranslator() translator = plg_translation_mngr.get_translator() if translator: @@ -62,8 +61,10 @@ def __init__(self, iface: QgisInterface): def post_ui_init(self): """Run after plugin's UI has been initialized.""" + with open(os.path.join(PluginGlobals.instance().config_dir_path, 'default_idg.json')) as f: + stock_idgs = json.load(f) self.task1 = DownloadDefaultIdgListAsync() - self.task2 = DownloadAllConfigFilesAsync(RemotePlatforms().stock_idgs) + self.task2 = DownloadAllConfigFilesAsync(stock_idgs) self.task1.finished.connect(self.task2.start) self.task2.finished.connect(self.populate_browser) From dfd87872f6625ad270cfe2476fde97900fed46cd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 14:31:26 +0100 Subject: [PATCH 6/9] remove unused import & PEP --- plugin/idg/plugin_main.py | 22 +++++------- plugin/idg/toolbelt/browser.py | 43 ++++++++++++------------ plugin/idg/toolbelt/plugin_globals.py | 3 +- plugin/idg/toolbelt/remote_platforms.py | 6 ++-- plugin/idg/toolbelt/tree_node_factory.py | 38 ++++++++++----------- 5 files changed, 52 insertions(+), 60 deletions(-) diff --git a/plugin/idg/plugin_main.py b/plugin/idg/plugin_main.py index 2534a40..13bb22a 100644 --- a/plugin/idg/plugin_main.py +++ b/plugin/idg/plugin_main.py @@ -7,19 +7,19 @@ # PyQGIS from qgis.core import QgsApplication from qgis.gui import QgisInterface -from qgis.PyQt.QtCore import QCoreApplication, Qt +from qgis.PyQt.QtCore import QCoreApplication from qgis.PyQt.QtGui import QIcon from qgis.PyQt.QtWidgets import QAction, QMenu -from qgis.utils import showPluginHelp, active_plugins +from qgis.utils import showPluginHelp # project from idg.__about__ import __title__ from idg.gui.dlg_settings import PlgOptionsFactory -from idg.toolbelt import PlgLogger, PlgTranslator, PluginGlobals +from idg.toolbelt import PlgLogger, PlgTranslator -from idg.toolbelt import PluginGlobals, PlgOptionsManager, IdgProvider, RemotePlatforms +from idg.toolbelt import PluginGlobals, IdgProvider from idg.toolbelt.tree_node_factory import DownloadAllConfigFilesAsync, DownloadDefaultIdgListAsync import os @@ -56,7 +56,7 @@ def __init__(self, iface: QgisInterface): self.registry = QgsApplication.dataItemProviderRegistry() self.provider = IdgProvider(self.iface) - #self.iface.initializationCompleted.connect(self.post_ui_init) + # self.iface.initializationCompleted.connect(self.post_ui_init) self.post_ui_init() def post_ui_init(self): @@ -69,6 +69,7 @@ def post_ui_init(self): self.task2.finished.connect(self.populate_browser) self.task1.start() + def need_download_tree_config_file(self): """ Do we need to download a new version of the resources tree file? @@ -110,15 +111,12 @@ def initGui(self): # -- Menu - # Create a menu self.createPluginMenu() # Add browser IDG provider self.registry.addProvider(self.provider) - - def populate_browser(self): self.provider.root.repopulate() @@ -131,8 +129,6 @@ def unload(self): # -- Clean up preferences panel in QGIS settings self.iface.unregisterOptionsWidgetFactory(self.options_factory) - - # remove actions del self.action_settings del self.action_help @@ -141,10 +137,9 @@ def unload(self): """ self.iface.pluginMenu().removeAction(self.plugin_menu.menuAction()) - #Clean-up browser + # Clean-up browser self.registry.removeProvider(self.provider) - - + def createPluginMenu(self): """ Creates the plugin main menu @@ -156,7 +151,6 @@ def createPluginMenu(self): self.plugin_menu.addAction(self.action_settings) self.plugin_menu.addAction(self.action_help) - def run(self): """Main process. diff --git a/plugin/idg/toolbelt/browser.py b/plugin/idg/toolbelt/browser.py index 1570c08..6502f0a 100644 --- a/plugin/idg/toolbelt/browser.py +++ b/plugin/idg/toolbelt/browser.py @@ -3,7 +3,7 @@ from qgis.gui import QgisInterface from qgis.PyQt.QtGui import QIcon from qgis.PyQt.Qt import QWidget -from idg.toolbelt import PluginGlobals, PlgOptionsManager +from idg.toolbelt import PluginGlobals from .remote_platforms import RemotePlatforms from idg.__about__ import __title__ from qgis.PyQt.QtWidgets import QAction, QMenu @@ -14,15 +14,16 @@ def find_catalog_url(metadata: QgsAbstractMetadataBase): """Find and return catalog url from layer metadatabase""" - for l in metadata.links(): - if l.name.strip().lower() in ['metadata', 'métadonnées', 'métadonnée']: - return l.url + for link in metadata.links(): + if link.name.strip().lower() in ['metadata', 'métadonnées', 'métadonnée']: + return link.url return None + def project_custom_icon_url(metadata: QgsAbstractMetadataBase): - for l in metadata.links(): - if l.name.lower().strip() == 'icon': - return l.url + for link in metadata.links(): + if link.name.lower().strip() == 'icon': + return link.url return None @@ -63,18 +64,18 @@ def actions(self, parent): def menus(self, parent): menu = QMenu(title=self.tr('Plateforms'), parent=parent) menu.setEnabled(False) # dev - for pf, checked in zip(['DataGrandEst', 'GeoBretagne', 'Geo2France', 'Indigeo'], [True, False, True, False]): # pour maquette TODO boucler sur une variable de conf + for pf, checked in zip(['DataGrandEst', 'GeoBretagne', 'Geo2France', 'Indigeo'], [True, False, True, False]): # pour maquette TODO boucler sur une variable de conf action = QAction(pf, menu, checkable=True) action.setChecked(checked) - menu.addAction(action) # TODO l'action permet d'activer/désactiver une plateforme. La désactivation supprime le DataCollectionItem et désactive le download du fichier de conf + menu.addAction(action) # TODO l'action permet d'activer/désactiver une plateforme. La désactivation supprime le DataCollectionItem et désactive le download du fichier de conf menu.addSeparator() - menu.addAction(QAction(self.tr('Add URL'), menu, )) # TODO Liens vers le panneau Options de QGIS + menu.addAction(QAction(self.tr('Add URL'), menu, )) # TODO Liens vers le panneau Options de QGIS return [menu] def repopulate(self): self.refresh() - for pf in RemotePlatforms().plateforms : - if pf.is_hidden() : + for pf in RemotePlatforms().plateforms: + if pf.is_hidden(): continue pf_collection = PlatformCollection(plateform=pf) self.addChildItem(pf_collection, refresh=True) @@ -85,7 +86,7 @@ class PlatformCollection(QgsDataCollectionItem): def __init__(self, plateform, parent=None): self.url = plateform.url self.path = "/IDG/"+plateform.idg_id.lower() - QgsDataCollectionItem.__init__(self, parent, plateform.idg_id, self.path ) + QgsDataCollectionItem.__init__(self, parent, plateform.idg_id, self.path) self.setToolTip(plateform.abstract) self.project = plateform.project self.plateform = plateform @@ -93,9 +94,9 @@ def __init__(self, plateform, parent=None): if self.project is None: self.setIcon(QIcon(QgsApplication.iconPath("mIconWarning.svg"))) else: - if plateform.icon is not None : # Custom icon + if plateform.icon is not None: # Custom icon self.setIcon(plateform.icon) - else : + else: self.setIcon(QIcon(QgsApplication.iconPath("mIconFolderProject.svg"))) # Default Icon def createChildren(self): @@ -110,11 +111,11 @@ def createChildren(self): def actions(self, parent): - #parent.setToolTipsVisible(True) + # parent.setToolTipsVisible(True) def set_action_url(link): a = QAction(link.name, parent) a.triggered.connect(lambda: webbrowser.open_new_tab(link.url)) - #a.setToolTip(link.description) + # a.setToolTip(link.description) return a def hide_plateform(pf): @@ -128,8 +129,8 @@ def hide_plateform(pf): separator = QAction(QIcon(), '', parent) separator.setSeparator(True) actions.append(separator) - hide_action = QAction(self.tr('Hide'), parent ) - hide_action.triggered.connect(lambda: hide_plateform(self.plateform) ) + hide_action = QAction(self.tr('Hide'), parent) + hide_action.triggered.connect(lambda: hide_plateform(self.plateform)) actions.append(hide_action) return actions @@ -157,7 +158,7 @@ def __init__(self, parent, name, layer): self.catalog_url = find_catalog_url(layer.metadata()) self.path = os.path.join(parent.path, layer.id()) QgsDataItem.__init__(self, QgsDataItem.Custom, - parent, name, self.path ) + parent, name, self.path) self.setState(QgsDataItem.Populated) # no children self.setToolTip(self.layer.metadata().abstract()) self.setIcon(QgsIconUtils.iconForLayer(self.layer)) @@ -170,7 +171,7 @@ def mimeUris(self): return [QgsMimeDataUtils.Uri(self.layer)] def hasDragEnabled(self): - #TODO ajouter une couche via le drag fait perdre le style, car ouvre directement la couche sans passer par le projet + # TODO ajouter une couche via le drag fait perdre le style, car ouvre directement la couche sans passer par le projet return False def handleDoubleClick(self): diff --git a/plugin/idg/toolbelt/plugin_globals.py b/plugin/idg/toolbelt/plugin_globals.py index 8107b9e..a3a7cb3 100644 --- a/plugin/idg/toolbelt/plugin_globals.py +++ b/plugin/idg/toolbelt/plugin_globals.py @@ -7,6 +7,7 @@ from .preferences import PlgOptionsManager from qgis.PyQt.QtCore import QSettings + @Singleton class PluginGlobals: """ @@ -18,6 +19,7 @@ class PluginGlobals: CONFIG_DIR_NAME = "config" CONFIG_FILE_NAMES = ["projet_idg.qgs"] CONFIG_FILES_DOWNLOAD_AT_STARTUP = PlgOptionsManager().get_value_from_key('config_files_download_at_startup') + def __init__(self): self.default_qsettings = { "CONFIG_FILE_NAMES": self.CONFIG_FILE_NAMES @@ -27,7 +29,6 @@ def __init__(self): self.images_dir_path = None self.logo_file_path = None - def set_plugin_path(self, plugin_path): self.plugin_path = plugin_path diff --git a/plugin/idg/toolbelt/remote_platforms.py b/plugin/idg/toolbelt/remote_platforms.py index 3bbe952..9b06480 100644 --- a/plugin/idg/toolbelt/remote_platforms.py +++ b/plugin/idg/toolbelt/remote_platforms.py @@ -1,5 +1,4 @@ -from qgis.core import QgsDataItemProvider, QgsDataCollectionItem, QgsDataItem, QgsDataProvider, QgsProject, \ - QgsLayerTreeLayer, QgsLayerTreeGroup, QgsMimeDataUtils, QgsAbstractMetadataBase, QgsApplication, QgsIconUtils +from qgis.core import QgsProject from qgis.PyQt.QtGui import QIcon from idg.toolbelt.tree_node_factory import DownloadAllConfigFilesAsync, DownloadDefaultIdgListAsync @@ -8,9 +7,10 @@ import json import os.path + class RemotePlatforms: def __init__(self): - self.plateforms=[] + self.plateforms = [] with open(os.path.join(PluginGlobals.instance().config_dir_path,'default_idg.json')) as f : #Télécharger si non existant ? self.stock_idgs = json.load(f) self.custom_idg = PlgOptionsManager().get_plg_settings().custom_idgs.split(',') diff --git a/plugin/idg/toolbelt/tree_node_factory.py b/plugin/idg/toolbelt/tree_node_factory.py index 4c6c7e3..9c58035 100644 --- a/plugin/idg/toolbelt/tree_node_factory.py +++ b/plugin/idg/toolbelt/tree_node_factory.py @@ -1,40 +1,38 @@ # -*- coding: utf-8 -*- import os -import json -import traceback -from urllib.parse import parse_qs, urlparse from qgis.core import ( - Qgis, - QgsMessageLog, - QgsProject, - QgsNetworkAccessManager, - QgsNetworkReplyContent, + QgsProject ) -from qgis.PyQt.QtNetwork import QNetworkRequest, QNetworkReply -from qgis.PyQt.QtCore import QUrl, QThread, pyqtSignal + +from qgis.PyQt.QtCore import QThread, pyqtSignal from idg.toolbelt import PluginGlobals from .network_manager import NetworkRequestsManager + class DownloadDefaultIdgListAsync(QThread): finished = pyqtSignal() - def __init__(self, url='https://raw.githubusercontent.com/geo2france/idg-qgis-plugin/dev/plugin/idg/config/default_idg.json'): + + def __init__(self, url='https://raw.githubusercontent.com/geo2france/idg-qgis-plugin/dev/plugin/idg/config' + '/default_idg.json'): super(QThread, self).__init__() - self.url=url + self.url = url + def run(self): qntwk = NetworkRequestsManager() - local_file_name = qntwk.download_file(self.url, os.path.join(PluginGlobals.instance().config_dir_path, - 'default_idg.json')) + qntwk.download_file(self.url, os.path.join(PluginGlobals.instance().config_dir_path, 'default_idg.json')) self.finished.emit() class DownloadAllConfigFilesAsync(QThread): finished = pyqtSignal() + def __init__(self, idgs): super(QThread, self).__init__() - self.idgs=idgs + self.idgs = idgs + def run(self): qntwk = NetworkRequestsManager() @@ -48,12 +46,10 @@ def run(self): project = QgsProject() project.read(local_file_name, QgsProject.ReadFlags() | QgsProject.FlagDontResolveLayers | QgsProject.FlagDontLoadLayouts) - for l in project.metadata().links(): - if l.name.lower().strip() == 'icon': - suffix = os.path.splitext(os.path.basename(l.url))[-1] - qntwk.download_file(l.url, + for link in project.metadata().links(): + if link.name.lower().strip() == 'icon': + suffix = os.path.splitext(os.path.basename(link.url))[-1] + qntwk.download_file(link.url, os.path.join(PluginGlobals.instance().config_dir_path, idg_id + suffix)) break self.finished.emit() - - From e7a69da551317b51c85d3cdb17ff6823da217017 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 15:40:31 +0100 Subject: [PATCH 7/9] fix restore default parameters --- plugin/idg/gui/dlg_settings.py | 26 ++++++++++++------------- plugin/idg/toolbelt/remote_platforms.py | 15 -------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/plugin/idg/gui/dlg_settings.py b/plugin/idg/gui/dlg_settings.py index 354f333..9a76efa 100644 --- a/plugin/idg/gui/dlg_settings.py +++ b/plugin/idg/gui/dlg_settings.py @@ -99,16 +99,12 @@ def __init__(self, parent): ) #Lire la config pour voir quels sont les PF masquées - vbox = QtWidgets.QVBoxLayout() + self.vbox = QtWidgets.QVBoxLayout() self.checkboxes = [] - self.groupBox_stock.setLayout(vbox) - for k in RemotePlatforms().stock_idgs.keys(): + self.groupBox_stock.setLayout(self.vbox) + for k in RemotePlatforms().stock_idgs.keys(): # !Couteux cb = QtWidgets.QCheckBox(k) - if k in settings.hidden_idgs.split(','): - cb.setChecked(False) - else : - cb.setChecked(True) - vbox.addWidget(cb) + self.vbox.addWidget(cb) self.checkboxes.append(cb) # load previously saved settings @@ -147,7 +143,12 @@ def apply(self): def load_settings(self): """Load options from QgsSettings into UI form.""" settings = self.plg_settings.get_plg_settings() - # global + hidden_idg = settings.hidden_idgs.split(',') + for c in self.checkboxes: + if c.text() in hidden_idg : + c.setChecked(False) + else : + c.setChecked(True) self.idgs_list.setRowCount( len(settings.custom_idgs.split(',')) + 1 ) listToTablewidget(settings.custom_idgs.split(','), self.idgs_list, column_index=0) @@ -157,11 +158,10 @@ def reset_settings(self): # dump default settings into QgsSettings self.plg_settings.save_from_object(default_settings) - - RemotePlatforms().reset() - - # update the form self.load_settings() + provider = QgsApplication.dataItemProviderRegistry().provider('IDG Provider') + provider.root.repopulate() + class PlgOptionsFactory(QgsOptionsWidgetFactory): """Factory for options widget.""" diff --git a/plugin/idg/toolbelt/remote_platforms.py b/plugin/idg/toolbelt/remote_platforms.py index 9b06480..61dd475 100644 --- a/plugin/idg/toolbelt/remote_platforms.py +++ b/plugin/idg/toolbelt/remote_platforms.py @@ -33,21 +33,6 @@ def url_stock(self): return out - def reset(self): - rep = PluginGlobals.instance().config_dir_path - for fichier in os.listdir(rep): - chemin_fichier = os.path.join(rep, fichier) - if fichier != 'default_idg.json': - if os.path.isfile(chemin_fichier): - os.remove(chemin_fichier) - - self.task1 = DownloadDefaultIdgListAsync() - self.task2 = DownloadAllConfigFilesAsync(RemotePlatforms().stock_idgs) - self.task1.finished.connect(self.task2.start) - self.task2.finished.connect(self.populate_browser) - #TODO remove all local files (projects & images) - - class Plateform: def __init__(self, url, idg_id): #TODO ajouter un paramètre "dry" ? self.url=url From 23305126430d87c8a33394a63fc0f5368cc6b23b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 15:44:57 +0100 Subject: [PATCH 8/9] speed up open parameter --- plugin/idg/gui/dlg_settings.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/idg/gui/dlg_settings.py b/plugin/idg/gui/dlg_settings.py index 9a76efa..d8726d3 100644 --- a/plugin/idg/gui/dlg_settings.py +++ b/plugin/idg/gui/dlg_settings.py @@ -102,7 +102,9 @@ def __init__(self, parent): self.vbox = QtWidgets.QVBoxLayout() self.checkboxes = [] self.groupBox_stock.setLayout(self.vbox) - for k in RemotePlatforms().stock_idgs.keys(): # !Couteux + with open(os.path.join(PluginGlobals.instance().config_dir_path, 'default_idg.json')) as f: + stock_idgs = json.load(f) + for k in stock_idgs.keys(): cb = QtWidgets.QCheckBox(k) self.vbox.addWidget(cb) self.checkboxes.append(cb) From 86bff2d78c070d8a96002ad4d8cfa0c8e35712d3 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste DESBAS Date: Fri, 1 Dec 2023 15:47:32 +0100 Subject: [PATCH 9/9] metadata 0.2.3 --- plugin/idg/metadata.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/idg/metadata.txt b/plugin/idg/metadata.txt index ce6836e..927a97f 100644 --- a/plugin/idg/metadata.txt +++ b/plugin/idg/metadata.txt @@ -5,10 +5,10 @@ hasProcessingProvider=no description=Plugin providing easy access to data from different SDI description[fr]=Plugin fournissant un accès simple aux données de différentes IDG about=Plugin providing easy access to data from different Spatial Data Infrastructures -about[fr]=Plugin fournissant un accès simple aux données de différentes Infrastructures de Données Géographiques DataGrandEst, Géo2France, GeoBretagne et OPenIG +about[fr]=Plugin fournissant un accès simple aux données de différentes Infrastructures de Données Géographiques DataGrandEst, Géo2France, GeoBretagne, OPenIG et Géoplateforme icon=resources/images/layers-svgrepo-com.svg -tags=opendata,sdi,DataGrandEst,Géo2France,GéoBretagne,OPenIG, crige -tags[fr]=opendata,idg,DataGrandEst,Géo2France,GéoBretagne,OPenIG,crige +tags=opendata,sdi,DataGrandEst,Géo2France,GéoBretagne,OPenIG,Géoplateforme,crige +tags[fr]=opendata,idg,DataGrandEst,Géo2France,GéoBretagne,OPenIG,Géoplateforme,crige # credits and contact author=Benjamin CHARTIER, Jean-Baptiste DESBAS @@ -24,5 +24,5 @@ qgisMinimumVersion=3.00 qgisMaximumVersion=3.99 # versioning -version=0.2.2 -changelog=Amélioration performance et stabilité +version=0.2.3 +changelog=Correction de problèmes de lancement du plugin, Amélioration performances