Skip to content

Commit

Permalink
Merge branch 'main' into ISSUE_297
Browse files Browse the repository at this point in the history
  • Loading branch information
giohappy authored Nov 27, 2024
2 parents a55a7b7 + 83da353 commit 57c70eb
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 43 deletions.
30 changes: 15 additions & 15 deletions src/qgis_geonode/apiclient/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,28 +123,28 @@ def get_dataset_detail(
self,
dataset: typing.Union[models.BriefDataset, models.Dataset],
get_style_too: bool = False,
authenticated: bool = False,
) -> None:
requests_to_perform = [
network.RequestToPerform(url=self.get_dataset_detail_url(dataset.pk))
]
if get_style_too:
is_vector = (
dataset.dataset_sub_type == models.GeonodeResourceType.VECTOR_LAYER
)
should_load_vector_style = (
models.ApiClientCapability.LOAD_VECTOR_LAYER_STYLE in self.capabilities
)
if is_vector and should_load_vector_style:
sld_url = QtCore.QUrl(dataset.default_style.sld_url)
requests_to_perform.append(network.RequestToPerform(url=sld_url))

auth_manager = qgis.core.QgsApplication.authManager()
auth_provider_name = auth_manager.configAuthMethodKey(self.auth_config).lower()

if auth_provider_name == "basic":
authenticated = True

self.network_fetcher_task = network.NetworkRequestTask(
requests_to_perform,
[network.RequestToPerform(url=self.get_dataset_detail_url(dataset.pk))],
self.network_requests_timeout,
self.auth_config,
description="Get dataset detail",
)
self.network_fetcher_task.task_done.connect(self.handle_dataset_detail)
self.network_fetcher_task.task_done.connect(
partial(
self.handle_dataset_detail,
get_style_too=get_style_too,
authenticated=authenticated,
)
)
qgis.core.QgsApplication.taskManager().addTask(self.network_fetcher_task)

def handle_dataset_detail(self, result: bool):
Expand Down
35 changes: 21 additions & 14 deletions src/qgis_geonode/apiclient/geonode_api_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,12 @@ def handle_dataset_list(self, task_result: bool) -> None:
)
self.dataset_list_received.emit(brief_datasets, pagination_info)

def handle_dataset_detail(self, task_result: bool) -> None:
def handle_dataset_detail(
self,
task_result: bool,
get_style_too: bool = False,
authenticated: bool = False,
) -> None:
log("inside the API client's handle_dataset_detail")
deserialized_resource = self._retrieve_response(
task_result, 0, self.dataset_detail_error_received
Expand All @@ -267,21 +272,23 @@ def handle_dataset_detail(self, task_result: bool) -> None:
debug=False,
)
else:
try:
style_response_contents = (
self.network_fetcher_task.response_contents[1]
# check if the request is from a WFS to see if it will retrieve the style
if get_style_too and authenticated:
is_vector = (
dataset.dataset_sub_type
== models.GeonodeResourceType.VECTOR_LAYER
)
except IndexError:
pass
should_load_vector_style = (
models.ApiClientCapability.LOAD_VECTOR_LAYER_STYLE
in self.capabilities
)
# Check if the layer is vector and if it has the permissions to read the style
if is_vector and should_load_vector_style:
self.get_dataset_style(
dataset, emit_dataset_detail_received=True
)
else:
(
sld_named_layer,
error_message,
) = geonode_styles.get_usable_sld(style_response_contents)
if sld_named_layer is None:
raise RuntimeError(error_message)
dataset.default_style.sld = sld_named_layer
self.dataset_detail_received.emit(dataset)
self.dataset_detail_received.emit(dataset)

def handle_dataset_style(
self,
Expand Down
10 changes: 9 additions & 1 deletion src/qgis_geonode/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
import typing
import uuid
import urllib.parse
from configparser import ConfigParser
from pathlib import Path

Expand Down Expand Up @@ -104,8 +105,15 @@ def prepare(self, plugin_dir):

self.plugin_metadata = _plugin_metadata["general"]

homepage = urllib.parse.urlparse(self.plugin_metadata.get("homepage"))
self.homepage_root = f"{homepage.scheme}://{homepage.hostname}/"
self.help_page = homepage.path.strip("/")

def get(self, attr):
return self.plugin_metadata.get(attr)
try:
return getattr(self, attr)
except ValueError:
return self.plugin_metadata.get(attr)


class SettingsManager(QtCore.QObject):
Expand Down
50 changes: 39 additions & 11 deletions src/qgis_geonode/gui/geonode_map_layer_config_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def connection_settings(self) -> typing.Optional[conf.ConnectionSettings]:
def __init__(self, layer, canvas, parent):
super().__init__(layer, canvas, parent)
self.setupUi(self)
self.setProperty("helpPage", conf.plugin_metadata.get("help_page"))
self.open_detail_url_pb.setIcon(
QtGui.QIcon(":/plugins/qgis_geonode/mIconGeonode.svg")
)
Expand Down Expand Up @@ -314,8 +315,8 @@ def _apply_metadata(self) -> None:
dataset = self.get_dataset()
updated_metadata = populate_metadata(self.layer.metadata(), dataset)
self.layer.setMetadata(updated_metadata)
layer_properties_dialog = self._get_layer_properties_dialog()
layer_properties_dialog.syncToLayer()
# sync layer properties with the reloaded SLD and/or Metadata from GeoNode
self.sync_layer_properties()

# FIXME: rather use the api_client to perform the metadata upload
def upload_metadata(self) -> None:
Expand Down Expand Up @@ -433,8 +434,7 @@ def _apply_sld(self) -> None:
dataset.default_style.sld, sld_load_error_msg
)
if sld_load_result:
layer_properties_dialog = self._get_layer_properties_dialog()
layer_properties_dialog.syncToLayer()
self.sync_layer_properties()
else:
self._show_message(
message=f"Could not load GeoNode style: {sld_load_error_msg}",
Expand All @@ -449,10 +449,33 @@ def _show_message(
) -> None:
utils.show_message(self.message_bar, message, level, add_loading_widget)

def _get_layer_properties_dialog(self):
# FIXME: This is a very hacky way to get the layer properties dialog
# but I've not been able to find a more elegant way to retrieve it yet
return self.parent().parent().parent().parent()
def find_parent_by_type(self, obj, target_type):
# Find the desired object by type
# from a structure: self.parent().parent()...
current_obj = obj
while current_obj is not None:
if isinstance(current_obj, target_type):
return current_obj
if hasattr(current_obj, "parent"):
current_obj = current_obj.parent()
else:
break
return None

def sync_layer_properties(self):
# get layer properties dialog
# We need to find QDialog object from a structure like:
# self.parent().parent()...
properties_dialog = self.find_parent_by_type(self, QtWidgets.QDialog)

if properties_dialog is not None:
# Sync GeoNode's SLD or / and metadata with the layer properties dialog
properties_dialog.syncToLayer()
else:
self._show_message(
"The corresponding layer properties from GeoNode cannot be loaded correctly...",
level=qgis.core.Qgis.Critical,
)

def _toggle_link_controls(self, enabled: bool) -> None:
self.links_gb.setEnabled(enabled)
Expand All @@ -472,12 +495,17 @@ def _toggle_style_controls(self, enabled: bool) -> None:
models.GeonodePermission.CHANGE_DATASET_STYLE in dataset.permissions
)
is_service = self.layer.dataProvider().name().lower() in ("wfs", "wcs")
has_style_url = dataset.default_style.sld_url is not None
if can_load_style and has_style_url and is_service:
has_geonode_style = dataset.default_style.sld is not None
if can_load_style and has_geonode_style and is_service:
widgets.append(self.download_style_pb)
else:
self.download_style_pb.setEnabled(False)
if allowed_to_modify and can_modify_style and has_style_url and is_service:
if (
allowed_to_modify
and can_modify_style
and has_geonode_style
and is_service
):
widgets.append(self.upload_style_pb)
else:
self.upload_style_pb.setEnabled(False)
Expand Down
17 changes: 15 additions & 2 deletions src/qgis_geonode/gui/search_result_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,14 @@ def prepare_loaded_layer(self):
self.layer = self.dataset_loader_task.layer
self.api_client.dataset_detail_received.connect(self.handle_layer_detail)
self.api_client.dataset_detail_error_received.connect(self.handle_loading_error)
self.api_client.style_detail_error_received.connect(self.handle_style_error)
self.api_client.get_dataset_detail(
self.brief_dataset, get_style_too=self.layer.dataProvider().name() != "wms"
)

def handle_layer_detail(self, dataset: typing.Optional[models.Dataset]):
def handle_layer_detail(
self, dataset: typing.Optional[models.Dataset], retrieved_style: bool = False
):
self.api_client.dataset_detail_received.disconnect(self.handle_layer_detail)
self.layer.setCustomProperty(
models.DATASET_CUSTOM_PROPERTY_KEY,
Expand All @@ -245,7 +248,11 @@ def handle_layer_detail(self, dataset: typing.Optional[models.Dataset]):
can_load_style = models.loading_style_supported(
self.layer.type(), self.api_client.capabilities
)
if can_load_style and dataset.default_style:

if dataset.default_style.sld is not None:
retrieved_style = True

if can_load_style and retrieved_style:
error_message = ""
loaded_sld = self.layer.readSld(dataset.default_style.sld, error_message)
if not loaded_sld:
Expand All @@ -257,10 +264,16 @@ def handle_loading_error(self):
self.data_source_widget.show_message(message, level=qgis.core.Qgis.Critical)
self.handle_layer_load_end(clear_message_bar=False)

def handle_style_error(self):
message = f"Unable to retrieve the style of {self.brief_dataset.title}"
self.data_source_widget.show_message(message, level=qgis.core.Qgis.Critical)
self.handle_layer_load_end(clear_message_bar=False)

def add_layer_to_project(self):
self.api_client.dataset_detail_error_received.disconnect(
self.handle_loading_error
)
self.api_client.style_detail_error_received.disconnect(self.handle_style_error)
self.project.addMapLayer(self.layer)
self.handle_layer_load_end()

Expand Down
12 changes: 12 additions & 0 deletions src/qgis_geonode/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import os.path

from qgis.core import QgsSettings
from qgis.gui import QgsGui
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
Expand All @@ -36,6 +37,17 @@ def __init__(self, iface):
self.plugin_dir, "i18n", "QgisGeoNode_{}.qm".format(locale)
)

settings = QgsSettings()
help_paths = settings.value("help/helpSearchPath")
homepage_root = plugin_metadata.get("homepage_root")

if isinstance(help_paths, str):
help_paths = [homepage_root, help_paths]
elif isinstance(help_paths, list) and not homepage_root in help_paths:
help_paths = [homepage_root] + help_paths

settings.setValue("help/helpSearchPath", help_paths)

if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
Expand Down

0 comments on commit 57c70eb

Please sign in to comment.