Skip to content

Commit 8d15556

Browse files
authored
feat: parse and load layer tree (wms layers)
* feat: load layers * fix: load layer in tree * feat: parse and load layer tree (wms layers)
1 parent cecd6c5 commit 8d15556

3 files changed

Lines changed: 138 additions & 43 deletions

File tree

plugin_code/models/Layer.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,6 @@ def from_dict(cls, data: Dict[str, Any]) -> 'Layer':
4747
features=data.get('features'),
4848
layerType=data.get('type')
4949
)
50+
51+
def get_id(self):
52+
return self._id

plugin_code/qgis_shogun_editor.py

Lines changed: 133 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@
3131
QgsNetworkAccessManager,
3232
QgsPointXY,
3333
QgsProject,
34-
QgsRectangle,
34+
QgsRasterLayer,
3535
QgsSettings,
3636
)
3737

3838
# some things for doing http requests
3939
from qgis.PyQt.QtCore import QCoreApplication, QEventLoop, QSettings, Qt, QTranslator, QUrl
4040
from qgis.PyQt.QtGui import QDesktopServices, QIcon, QPixmap
4141
from qgis.PyQt.QtNetwork import QNetworkRequest, QSslSocket
42-
from qgis.PyQt.QtWidgets import QAction
42+
from qgis.PyQt.QtWidgets import QAction, QMessageBox, QTreeWidgetItem
4343

4444
from .models.Application import Application
4545
from .qgis_shogun_editor_dialog import QgisShogunEditorDialog
@@ -216,7 +216,7 @@ def run(self):
216216
"""Run method that performs all the real work"""
217217

218218
# Create the dialog with elements (after translation) and keep reference
219-
# Only create GUI ONCE in callback, so that it will only load when thie plugin is started
219+
# Only create GUI ONCE in callback, so that it will only load when the plugin is started
220220
if self.first_start:
221221
self.first_start = False
222222
self.dlg = QgisShogunEditorDialog()
@@ -239,8 +239,6 @@ def run(self):
239239
else:
240240
QgsMessageLog.logMessage("An error occured while try to open url: ", 'QgisShogunEditor',
241241
level=Qgis.Critical)
242-
# add link to github for help
243-
# help_icon_path = os.path.join(os.path.dirname(__file__), "questionmark.png")
244242
# show the dialog
245243
self.dlg.show()
246244
# Run the dialog event loop
@@ -251,6 +249,18 @@ def run(self):
251249
# substitute with your code.
252250
pass
253251

252+
def find_all_layer_ids(self, layer_tree_json):
253+
layer_ids = []
254+
255+
if "layerId" in layer_tree_json:
256+
layer_ids.append(layer_tree_json["layerId"])
257+
258+
if "children" in layer_tree_json:
259+
for child in layer_tree_json["children"]:
260+
layer_ids.extend(self.find_all_layer_ids(child))
261+
262+
return layer_ids
263+
254264
def _handle_double_click(self, item):
255265
QgsMessageLog.logMessage(
256266
f"You selected: {item.text()} - application id is: {item.application_id}", 'QgisShogunEditor',
@@ -263,10 +273,21 @@ def _handle_double_click(self, item):
263273
if application.layer_tree is not None:
264274
try:
265275
QgsMessageLog.logMessage(
266-
f"Found layer tree {application.layer_tree}:",
276+
f"Found layer tree: {application.layer_tree}",
277+
'QgisShogunEditor',
278+
level=Qgis.Info
279+
)
280+
QgsMessageLog.logMessage(
281+
"Loading layertree to Qgis now.",
267282
'QgisShogunEditor',
268283
level=Qgis.Info
269284
)
285+
286+
root = QgsProject.instance().layerTreeRoot()
287+
root.clear()
288+
layer_ids = self.find_all_layer_ids(application.layer_tree)
289+
layers_content = self.layer_service.get_layers_by_ids(layer_ids)
290+
self.buildLayerTree(application.layer_tree, layers_content, root)
270291
except json.JSONDecodeError as e:
271292
QgsMessageLog.logMessage(
272293
f"Could not decode layer tree json: {e}", 'QgisShogunEditor',
@@ -300,42 +321,113 @@ def open_project_link(self, event):
300321
if event.button() == Qt.LeftButton:
301322
QDesktopServices.openUrl(QUrl("https://www.terrestris.de/de/"))
302323

303-
def request_public_entity(self, url):
304-
self.request.setUrl(QUrl(url))
305-
306-
# no certificate
307-
ssl_config = self.request.sslConfiguration()
308-
ssl_config.setPeerVerifyMode(QSslSocket.VerifyNone)
309-
self.request.setSslConfiguration(ssl_config)
310-
311-
# request public application
312-
self.reply = self.na_manager.get(self.request)
313-
event_loop = QEventLoop()
314-
self.reply.finished.connect(event_loop.quit)
315-
event_loop.exec_() # blocs until finished
316-
317-
if self.reply.error() == self.reply.NoError:
318-
self.response = self.reply.readAll().data().decode("utf-8")
319-
# print("Response:", self.response)
324+
def createWmsLayerFromShogun(self, layer_src_conf):
325+
layerNames = layer_src_conf['layerNames']
326+
layer_url = layer_src_conf['url']
327+
if str(layer_url).startswith('/'):
328+
layer_url = self.dlg.entryUrl.text() + layer_url
329+
330+
params = {
331+
'layers': layerNames,
332+
'styles': '',
333+
'format': 'image/png',
334+
'crs': 'EPSG:' + str(QgsProject.instance().crs().srsid()),
335+
'url': layer_url
336+
}
337+
338+
# set transparency if present
339+
try:
340+
params['transparent'] = layer_src_conf['requestParams']['TRANSPARENT']
341+
print('set transparent')
342+
except KeyError:
343+
print('no transparency')
344+
345+
uri = '&'.join([f"{k}={v}" for k, v in params.items()])
346+
layer = QgsRasterLayer(uri, layerNames, 'wms')
347+
348+
if layer.isValid():
349+
return layer
320350
else:
321-
self.response = None
322-
print("Error:", self.reply.errorString())
323-
self.reply.deleteLater()
324-
325-
return self.response
326-
327-
def find_all_layer_ids(self, layer_tree_json):
328-
layer_ids = []
329-
330-
if "layerId" in layer_tree_json:
331-
print('Found layerId', layer_tree_json["layerId"])
332-
layer_ids.append(layer_tree_json["layerId"])
333-
334-
if "children" in layer_tree_json:
335-
for child in layer_tree_json["children"]:
336-
layer_ids.extend(self.find_all_layer_ids(child))
337-
338-
return layer_ids
351+
return False
352+
353+
def createLayer(self, layer_src_conf):
354+
# layerurl = request_url
355+
356+
# dataType = layerItem.datatype
357+
358+
# every layerItem.source should have an attribute 'dataType'
359+
# if dataType == 'vector' or dataType == 'Vector':
360+
# url = layerItem.ressource.baseurl.rstrip('/shogun2-webapp/') + layerurl + '?'
361+
# return createWfsLayer(layerItem, url, epsg)
362+
363+
# elif dataType == 'Raster':
364+
# url = layerItem.ressource.baseurl.rstrip('/shogun2-webapp/') + layerurl + '?'
365+
# return createRasterLayer(layerItem, url, epsg)
366+
367+
# elif dataType == 'WMS':
368+
# if layerurl == '/shogun2-webapp/geoserver.action':
369+
# url = layerItem.ressource.baseurl.rstrip('/shogun2-webapp/') + layerurl + '?'
370+
return self.createWmsLayerFromShogun(layer_src_conf)
371+
# else:
372+
# return createWmsLayer(layerItem, layerurl, epsg)
373+
374+
# if for any reason the parameter 'dataType' is not set correctly, we check the url
375+
# of the layer to determine if it's a WFS/WCS from the shogun-geoserver
376+
# (url has'shogun2-webapp') or if it's a WMS from an outer source (other url)
377+
# elif dataType == 'unknown' or dataType == None or dataType == '':
378+
# if layerurl.startswith('/shogun2-webapp'):
379+
# url = layerItem.ressource.baseurl.rstrip('/shogun2-webapp/') + layerurl + '?'
380+
# try:
381+
# lyr = createWfsLayer(layerItem, url, epsg)
382+
# if lyr.isValid():
383+
# return lyr
384+
# except:
385+
# pass
386+
# try:
387+
# lyr = createWmsLayerFromShogun(layerItem, url, epsg)
388+
# if lyr.isValid():
389+
# return lyr
390+
# except:
391+
# pass
392+
# try:
393+
# lyr = createRasterLayer(layerItem, url, epsg)
394+
# if lyr.isValid():
395+
# return lyr
396+
# except:
397+
# pass
398+
# else:
399+
# return createWmsLayerNormal(layerItem, layerurl, epsg)
400+
401+
# else:
402+
# info = 'Layer source '+ layerurl + ' could not be loaded'
403+
# QMessageBox.warning(None, 'Warning', info, QMessageBox.Ok)
404+
405+
def addQgsLayer(self, layer_src_conf, layer_group):
406+
self.qgisLayers = []
407+
# layerutils
408+
layer = self.createLayer(layer_src_conf)
409+
if not layer:
410+
QgsMessageLog.logMessage(
411+
f"Could not create layer: {layer_src_conf}", 'QgisShogunEditor',
412+
level=Qgis.Critical
413+
)
414+
return
415+
416+
QgsProject.instance().addMapLayer(layer, False) # implicit addition
417+
layer_group.addLayer(layer) # eplicit addition
418+
419+
def buildLayerTree(self, applications_layertree, layers_content, root):
420+
if 'layerId' not in applications_layertree:
421+
new_group = root.addGroup(applications_layertree['title']) # option: take the name of the application
422+
423+
if 'layerId' in applications_layertree:
424+
result = [layer for layer in layers_content if layer.get_id() == applications_layertree['layerId']]
425+
layer_src_conf = result[0].source_config
426+
self.addQgsLayer(layer_src_conf, root)
427+
428+
if 'children' in applications_layertree:
429+
for child in applications_layertree['children']:
430+
self.buildLayerTree(child, layers_content, new_group)
339431

340432
def sanitize_shogun_url(self, shogun_url):
341433
if shogun_url.endswith('/graphql'):

plugin_code/service/LayerService.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ def get_all_layers(self) -> List[Layer]:
5151

5252
def get_layers_by_ids(self, layer_ids: List[int]) -> List[Layer]:
5353
query = """
54-
query GetLayers($id: Int) {
55-
allLayersByIds(id: $id) {
54+
query GetLayers($ids: [Int]) {
55+
allLayersByIds(ids: $ids) {
5656
id
5757
created
5858
modified

0 commit comments

Comments
 (0)