From 8fe6a75b9df75314b7d0e86c59bc799d246c8bb4 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Tue, 12 Nov 2024 16:01:15 +0200 Subject: [PATCH 1/7] Improving 'test connection button --- src/qgis_geonode/gui/connection_dialog.py | 64 +++++++++++++++-------- src/qgis_geonode/ui/connection_dialog.ui | 4 +- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 10df889..6da764b 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -2,6 +2,7 @@ import re import typing import uuid +from urllib.parse import urlparse import qgis.core @@ -38,7 +39,7 @@ class ConnectionDialog(QtWidgets.QDialog, DialogUi): wfs_version_cb: QtWidgets.QComboBox detect_wfs_version_pb: QtWidgets.QPushButton network_timeout_sb: QtWidgets.QSpinBox - test_connection_pb: QtWidgets.QPushButton + connection_pb: QtWidgets.QPushButton buttonBox: QtWidgets.QDialogButtonBox options_gb: QtWidgets.QGroupBox bar: qgis.gui.QgsMessageBar @@ -57,7 +58,7 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No super().__init__() self.setupUi(self) self._widgets_to_toggle_during_connection_test = [ - self.test_connection_pb, + self.connection_pb, self.buttonBox, self.authcfg_acs, self.options_gb, @@ -92,7 +93,7 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No self.connection_id = uuid.uuid4() self.remote_geonode_version = None self.update_connection_details() - self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) + # self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) ok_signals = [ self.name_le.textChanged, self.url_le.textChanged, @@ -100,7 +101,7 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No for signal in ok_signals: signal.connect(self.update_ok_buttons) self.detect_wfs_version_pb.clicked.connect(self.detect_wfs_version) - self.test_connection_pb.clicked.connect(self.test_connection) + self.connection_pb.clicked.connect(self.test_connection) # disallow names that have a slash since that is not compatible with how we # are storing plugin state in QgsSettings self.name_le.setValidator( @@ -108,6 +109,15 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No ) self.update_ok_buttons() + def validate_geonode_url(self): + + inserted_url = self.url_le.text().strip().rstrip("#/") + parsed_url = urlparse(inserted_url) + if parsed_url.path != "": + return False + else: + return True + def _populate_wfs_version_combobox(self): self.wfs_version_cb.clear() for name, member in WfsVersion.__members__.items(): @@ -150,22 +160,29 @@ def get_connection_settings(self) -> ConnectionSettings: def test_connection(self): for widget in self._widgets_to_toggle_during_connection_test: widget.setEnabled(False) - current_settings = self.get_connection_settings() - self.discovery_task = network.NetworkRequestTask( - [ - network.RequestToPerform( - QtCore.QUrl(f"{current_settings.base_url}/version.txt") - ) - ], - network_task_timeout=current_settings.network_requests_timeout, - authcfg=current_settings.auth_config, - description="Test GeoNode connection", - ) - self.discovery_task.task_done.connect(self.handle_discovery_test) - utils.show_message( - self.bar, tr("Testing connection..."), add_loading_widget=True - ) - qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) + + url_status = self.validate_geonode_url() + + if url_status != False: + + current_settings = self.get_connection_settings() + self.discovery_task = network.NetworkRequestTask( + [ + network.RequestToPerform( + QtCore.QUrl(f"{current_settings.base_url}/version.txt") + ) + ], + network_task_timeout=current_settings.network_requests_timeout, + authcfg=current_settings.auth_config, + description="Connect to a GeoNode client", + ) + self.discovery_task.task_done.connect(self.handle_discovery_test) + utils.show_message(self.bar, tr("Connecting..."), add_loading_widget=True) + qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) + else: + message = "Please insert only the domain part from the GeoNode URL" + level = qgis.core.Qgis.Critical + utils.show_message(self.bar, message, level) def handle_discovery_test(self, task_result: bool): self.enable_post_test_connection_buttons() @@ -230,7 +247,10 @@ def update_connection_details(self): self.detected_capabilities_lw.clear() self.detected_version_le.clear() if not invalid_version: + # Enable the detected_version_db and OK button self.detected_version_gb.setEnabled(True) + self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) + current_settings = self.get_connection_settings() client: BaseGeonodeClient = apiclient.get_geonode_client(current_settings) self.detected_version_le.setText(str(current_settings.geonode_version)) @@ -239,6 +259,7 @@ def update_connection_details(self): ) else: self.detected_version_gb.setEnabled(False) + self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) def enable_post_test_connection_buttons(self): for widget in self._widgets_to_toggle_during_connection_test: @@ -269,8 +290,7 @@ def accept(self): def update_ok_buttons(self): enabled_state = self.name_le.text() != "" and self.url_le.text() != "" - self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(enabled_state) - self.test_connection_pb.setEnabled(enabled_state) + self.connection_pb.setEnabled(enabled_state) def _get_wfs_declared_versions(raw_response: QtCore.QByteArray) -> typing.List[str]: diff --git a/src/qgis_geonode/ui/connection_dialog.ui b/src/qgis_geonode/ui/connection_dialog.ui index 31426db..283f2f7 100644 --- a/src/qgis_geonode/ui/connection_dialog.ui +++ b/src/qgis_geonode/ui/connection_dialog.ui @@ -138,7 +138,7 @@ - + 0 @@ -146,7 +146,7 @@ - Test Connection + Connect From 958eced18e309a23dc216513ad4721dc88ac4ed6 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Tue, 12 Nov 2024 16:42:22 +0200 Subject: [PATCH 2/7] disable OK button during typing a wrong URL --- src/qgis_geonode/gui/connection_dialog.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 6da764b..133812f 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -180,6 +180,7 @@ def test_connection(self): utils.show_message(self.bar, tr("Connecting..."), add_loading_widget=True) qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) else: + self.enable_post_test_connection_buttons() message = "Please insert only the domain part from the GeoNode URL" level = qgis.core.Qgis.Critical utils.show_message(self.bar, message, level) @@ -289,8 +290,13 @@ def accept(self): super().accept() def update_ok_buttons(self): + + url_status = self.validate_geonode_url() + enabled_state = self.name_le.text() != "" and self.url_le.text() != "" self.connection_pb.setEnabled(enabled_state) + if url_status != True: + self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) def _get_wfs_declared_versions(raw_response: QtCore.QByteArray) -> typing.List[str]: From 251e6c49a218e7c5c8e6acfd355878eee3503491 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Tue, 12 Nov 2024 18:12:17 +0200 Subject: [PATCH 3/7] clear old error messages after selecting a different connection --- src/qgis_geonode/gui/geonode_data_source_widget.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/qgis_geonode/gui/geonode_data_source_widget.py b/src/qgis_geonode/gui/geonode_data_source_widget.py index 2d8bf54..728b805 100644 --- a/src/qgis_geonode/gui/geonode_data_source_widget.py +++ b/src/qgis_geonode/gui/geonode_data_source_widget.py @@ -286,6 +286,8 @@ def update_connections_combobox(self): def activate_connection_configuration(self, index: int): self.toggle_connection_management_buttons() + # Clear error messages from other connections + self.message_bar.clearWidgets() self.clear_search_results() self.current_page = 1 self.total_pages = 1 From 7b76fa149b432f6fc9deca47bf662cc89d78da60 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Wed, 13 Nov 2024 09:58:50 +0200 Subject: [PATCH 4/7] adding a clickable link to the help button --- src/qgis_geonode/gui/connection_dialog.py | 7 +++++++ src/qgis_geonode/gui/geonode_data_source_widget.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 133812f..5e9db99 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -107,6 +107,13 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No self.name_le.setValidator( QtGui.QRegExpValidator(QtCore.QRegExp("[^\\/]+"), self.name_le) ) + + # Plugin's docs open through the help button + self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect( + lambda: QtGui.QDesktopServices.openUrl( + QtCore.QUrl("https://geonode.org/QGISGeoNodePlugin/") + ) + ) self.update_ok_buttons() def validate_geonode_url(self): diff --git a/src/qgis_geonode/gui/geonode_data_source_widget.py b/src/qgis_geonode/gui/geonode_data_source_widget.py index 728b805..8e5c266 100644 --- a/src/qgis_geonode/gui/geonode_data_source_widget.py +++ b/src/qgis_geonode/gui/geonode_data_source_widget.py @@ -199,6 +199,13 @@ def __init__(self, parent, fl, widgetMode): self.title_le.returnPressed.connect(self.search_geonode) self._hide_core_geonode_provider() + # Plugin's docs open through the help button + self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect( + lambda: QtGui.QDesktopServices.openUrl( + QtCore.QUrl("https://geonode.org/QGISGeoNodePlugin/") + ) + ) + def _initialize_spatial_extent_box(self): # ATTENTION: the order of initialization of the self.spatial_extent_box widget # is crucial here. Only call self.spatial_extent_box.setMapCanvas() after From 785c8026f73c5c42e45aff428ff39a9c84ab5ff4 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Wed, 13 Nov 2024 10:44:26 +0200 Subject: [PATCH 5/7] using Qurl instead of urllib --- src/qgis_geonode/gui/connection_dialog.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 5e9db99..8b0a0af 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -2,8 +2,6 @@ import re import typing import uuid -from urllib.parse import urlparse - import qgis.core from qgis.gui import QgsMessageBar @@ -118,9 +116,11 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No def validate_geonode_url(self): - inserted_url = self.url_le.text().strip().rstrip("#/") - parsed_url = urlparse(inserted_url) - if parsed_url.path != "": + inserted_url = QtCore.QUrl(self.url_le.text().strip().rstrip("#/")) + + if inserted_url.isValid() == False: + return False + elif inserted_url.path() != "": return False else: return True @@ -188,7 +188,7 @@ def test_connection(self): qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) else: self.enable_post_test_connection_buttons() - message = "Please insert only the domain part from the GeoNode URL" + message = "Please insert only the domain of a valid GeoNode URL" level = qgis.core.Qgis.Critical utils.show_message(self.bar, message, level) From 74246ef4bfd1154e6687adf5b55612df34d36890 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Wed, 13 Nov 2024 11:06:25 +0200 Subject: [PATCH 6/7] adding invalid URL messages during typing --- src/qgis_geonode/gui/connection_dialog.py | 41 ++++++++++------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 8b0a0af..611d06d 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -168,29 +168,20 @@ def test_connection(self): for widget in self._widgets_to_toggle_during_connection_test: widget.setEnabled(False) - url_status = self.validate_geonode_url() - - if url_status != False: - - current_settings = self.get_connection_settings() - self.discovery_task = network.NetworkRequestTask( - [ - network.RequestToPerform( - QtCore.QUrl(f"{current_settings.base_url}/version.txt") - ) - ], - network_task_timeout=current_settings.network_requests_timeout, - authcfg=current_settings.auth_config, - description="Connect to a GeoNode client", - ) - self.discovery_task.task_done.connect(self.handle_discovery_test) - utils.show_message(self.bar, tr("Connecting..."), add_loading_widget=True) - qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) - else: - self.enable_post_test_connection_buttons() - message = "Please insert only the domain of a valid GeoNode URL" - level = qgis.core.Qgis.Critical - utils.show_message(self.bar, message, level) + current_settings = self.get_connection_settings() + self.discovery_task = network.NetworkRequestTask( + [ + network.RequestToPerform( + QtCore.QUrl(f"{current_settings.base_url}/version.txt") + ) + ], + network_task_timeout=current_settings.network_requests_timeout, + authcfg=current_settings.auth_config, + description="Connect to a GeoNode client", + ) + self.discovery_task.task_done.connect(self.handle_discovery_test) + utils.show_message(self.bar, tr("Connecting..."), add_loading_widget=True) + qgis.core.QgsApplication.taskManager().addTask(self.discovery_task) def handle_discovery_test(self, task_result: bool): self.enable_post_test_connection_buttons() @@ -304,6 +295,10 @@ def update_ok_buttons(self): self.connection_pb.setEnabled(enabled_state) if url_status != True: self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) + self.connection_pb.setEnabled(False) + message = "Please insert only the domain of a valid GeoNode URL" + level = qgis.core.Qgis.Info + utils.show_message(self.bar, message, level) def _get_wfs_declared_versions(raw_response: QtCore.QByteArray) -> typing.List[str]: From c21dbd2142a2c5f55639a37e6cd0e75b7498f031 Mon Sep 17 00:00:00 2001 From: gpetrak Date: Wed, 13 Nov 2024 15:56:50 +0200 Subject: [PATCH 7/7] adding PluginMetadata class in order to retrieve content from metadata.txt --- src/qgis_geonode/conf.py | 15 +++++++++++++++ src/qgis_geonode/gui/connection_dialog.py | 8 ++------ .../gui/geonode_data_source_widget.py | 3 ++- src/qgis_geonode/main.py | 2 ++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/qgis_geonode/conf.py b/src/qgis_geonode/conf.py index 320488d..366148c 100644 --- a/src/qgis_geonode/conf.py +++ b/src/qgis_geonode/conf.py @@ -4,6 +4,8 @@ import json import typing import uuid +from configparser import ConfigParser +from pathlib import Path from qgis.PyQt import ( QtCore, @@ -94,6 +96,18 @@ def to_json(self): ) +class PluginMetadata: + def prepare(self, plugin_dir): + self.plugin_dir = plugin_dir + _plugin_metadata = ConfigParser() + _plugin_metadata.read(Path(self.plugin_dir) / "metadata.txt") + + self.plugin_metadata = _plugin_metadata["general"] + + def get(self, attr): + return self.plugin_metadata.get(attr) + + class SettingsManager(QtCore.QObject): """Manage saving/loading settings for the plugin in QgsSettings""" @@ -303,3 +317,4 @@ def clear_current_search_filters(self): settings_manager = SettingsManager() +plugin_metadata = PluginMetadata() diff --git a/src/qgis_geonode/gui/connection_dialog.py b/src/qgis_geonode/gui/connection_dialog.py index 611d06d..1ae8034 100644 --- a/src/qgis_geonode/gui/connection_dialog.py +++ b/src/qgis_geonode/gui/connection_dialog.py @@ -15,11 +15,7 @@ from .. import apiclient, network, utils from ..apiclient.base import BaseGeonodeClient -from ..conf import ( - ConnectionSettings, - WfsVersion, - settings_manager, -) +from ..conf import ConnectionSettings, WfsVersion, settings_manager, plugin_metadata from ..utils import tr from packaging import version as packaging_version @@ -109,7 +105,7 @@ def __init__(self, connection_settings: typing.Optional[ConnectionSettings] = No # Plugin's docs open through the help button self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect( lambda: QtGui.QDesktopServices.openUrl( - QtCore.QUrl("https://geonode.org/QGISGeoNodePlugin/") + QtCore.QUrl(plugin_metadata.get("homepage")) ) ) self.update_ok_buttons() diff --git a/src/qgis_geonode/gui/geonode_data_source_widget.py b/src/qgis_geonode/gui/geonode_data_source_widget.py index 8e5c266..db833b0 100644 --- a/src/qgis_geonode/gui/geonode_data_source_widget.py +++ b/src/qgis_geonode/gui/geonode_data_source_widget.py @@ -28,6 +28,7 @@ log, tr, ) +from ..conf import plugin_metadata WidgetUi, _ = loadUiType(Path(__file__).parents[1] / "ui/geonode_datasource_widget.ui") @@ -202,7 +203,7 @@ def __init__(self, parent, fl, widgetMode): # Plugin's docs open through the help button self.buttonBox.button(QtWidgets.QDialogButtonBox.Help).clicked.connect( lambda: QtGui.QDesktopServices.openUrl( - QtCore.QUrl("https://geonode.org/QGISGeoNodePlugin/") + QtCore.QUrl(plugin_metadata.get("homepage")) ) ) diff --git a/src/qgis_geonode/main.py b/src/qgis_geonode/main.py index af51bb8..84994a5 100644 --- a/src/qgis_geonode/main.py +++ b/src/qgis_geonode/main.py @@ -23,12 +23,14 @@ from .gui.geonode_maplayer_config_widget_factory import ( GeonodeMapLayerConfigWidgetFactory, ) +from .conf import plugin_metadata class QgisGeoNode: def __init__(self, iface): self.iface = iface self.plugin_dir = os.path.dirname(__file__) + plugin_metadata.prepare(self.plugin_dir) locale = QSettings().value("locale/userLocale")[0:2] locale_path = os.path.join( self.plugin_dir, "i18n", "QgisGeoNode_{}.qm".format(locale)