Skip to content

Commit

Permalink
Handle invalid layer other than vector in the legend
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry committed May 15, 2024
1 parent c556ad1 commit 91b7d83
Show file tree
Hide file tree
Showing 8 changed files with 4,965 additions and 3,986 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ test/data/*.gpkg-wal
test/data/*.qgs~
test/data/*.qgz~
test/data/*_attachments.zip
test/data/*.asc.aux.xml
26 changes: 17 additions & 9 deletions lizmap_server/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,11 @@ def find_vector_layer_from_params(params, project):
return True, layer


def find_vector_layer(layer_name: str, project: QgsProject) -> Optional[QgsVectorLayer]:
""" Find vector layer with name, short name or layer id. """
def find_layer(layer_name: str, project: QgsProject) -> Optional[QgsMapLayer]:
""" Find layer with name, short name or layer ID. """
found = None
for layer in project.mapLayers().values():

# only vector layer
if layer.type() != QgsMapLayer.VectorLayer:
continue

# check name
if layer.name() == layer_name:
found = layer
Expand All @@ -75,18 +71,30 @@ def find_vector_layer(layer_name: str, project: QgsProject) -> Optional[QgsVecto

if not found:
Logger.warning(
"The vector layer '{}' has not been found in the project '{}'".format(layer_name, project.fileName()))
"The layer '{}' has not been found in the project '{}'".format(layer_name, project.fileName()))
return None

found: QgsVectorLayer
found: QgsMapLayer
if not found.isValid():
Logger.warning(
f"The vector layer '{layer_name}' has been found but it is not valid in the project "
f"The layer '{layer_name}' has been found but it is not valid in the project "
f"'{project.fileName()}'",
)
return found


def find_vector_layer(layer_name: str, project: QgsProject) -> Optional[QgsVectorLayer]:
""" Find vector layer with name, short name or layer ID. """
layer = find_layer(layer_name, project)
if not layer:
return None

if not layer.type() == QgsMapLayer.VectorLayer:
return None

return layer


def get_server_fid(feature: QgsFeature, pk_attributes: list) -> str:
""" Build server feature ID. """
if not pk_attributes:
Expand Down
14 changes: 10 additions & 4 deletions lizmap_server/get_legend_graphic.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
from collections import namedtuple
from typing import Optional

from qgis.core import Qgis, QgsProject, QgsVectorLayer
from qgis.core import Qgis, QgsMapLayer, QgsProject, QgsVectorLayer
from qgis.PyQt.QtCore import QBuffer, QIODevice
from qgis.PyQt.QtGui import QImage
from qgis.server import QgsServerFilter

from lizmap_server.core import find_vector_layer
from lizmap_server.core import find_layer
from lizmap_server.logger import Logger, exception_handler
from lizmap_server.tools import to_bool

Expand Down Expand Up @@ -86,11 +86,11 @@ def responseComplete(self):
show_feature_count = to_bool(params.get('SHOWFEATURECOUNT'), default_value=False)

current_style = ''
layer = find_vector_layer(layer_name, project)
layer = find_layer(layer_name, project)
if not layer:
logger.info("Skipping the layer '{}' because it's not a vector layer".format(layer_name))
return

layer: QgsMapLayer
if not layer.isValid():
logger.warning(
f"Layer '{layer_name}' is not valid, returning a warning icon in the legend for project "
Expand All @@ -109,6 +109,12 @@ def responseComplete(self):
handler.appendBody(json.dumps(json_data).encode('utf8'))
return

if layer.type() != QgsMapLayer.VectorLayer:
logger.info("Skipping the layer '{}' because it's not a vector layer".format(layer_name))
return

layer: QgsVectorLayer

try:
current_style = layer.styleManager().currentStyle()

Expand Down
4,605 changes: 2,545 additions & 2,060 deletions test/data/legend.qgs

Large diffs are not rendered by default.

4,228 changes: 2,316 additions & 1,912 deletions test/data/legend_invalid.qgs

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions test/data/raster.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
NCOLS 16
NROWS 5
XLLCENTER 0
YLLCENTER 47.618
DX 0.011
DY 0.011
NODATA_VALUE -1
050 050 050 050 050 050 050 050 050 050 050 050 050 050 050 050
075 075 075 075 075 075 075 075 075 075 075 075 075 075 075 075
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
125 125 125 125 125 125 125 -1 -1 -1 -1 -1 125 125 125 125
125 125 125 125 125 125 125 -1 -1 -1 -1 -1 125 125 125 125

CRS
NOTES
58 changes: 58 additions & 0 deletions test/test_legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,34 @@ def test_simple_rule_based_feature_count(client):
assert b['nodes'][0]['title'] == 'rule_based [4]', b['nodes'][0]['title']


def test_valid_raster_layer(client):
""" Test valid raster layer. """
qs = dict(BASE_QUERY)
qs['MAP'] = PROJECT
qs['LAYER'] = 'raster'
rv = client.get(_build_query_string(qs), PROJECT)
b = _check_request(rv)

# Answer straight from QGIS Server
expected = {
'nodes': [
{
'symbols': [
{
'title': 'Band 1',
}, {
'title': '',
},
],
'title': qs['LAYER'],
'type': 'layer',
},
],
'title': '',
}
assert b == expected


def test_invalid_layer_symbol_layer(client):
""" Test unique symbol for layer. """
qs = dict(BASE_QUERY)
Expand All @@ -183,6 +211,36 @@ def test_invalid_layer_symbol_layer(client):
assert 'symbols' not in b['nodes'][0]


def test_invalid_layer_raster_layer(client):
""" Test invalid raster layer. """
qs = dict(BASE_QUERY)
qs['MAP'] = PROJECT_INVALID
qs['LAYER'] = 'raster'
rv = client.get(_build_query_string(qs), PROJECT_INVALID)
b = _check_request(rv)

expected = {
'title': '',
'nodes': [
{
'type': 'layer',
'title': qs['LAYER'],
'icon': GetLegendGraphicFilter.warning_icon(),
'valid': False,
},
],
}
assert b == expected, b

assert b['title'] == '', b
assert len(b['nodes']) == 1, b
assert b['nodes'][0]['title'] == qs['LAYER']
assert b['nodes'][0].get('valid') is False
assert b['nodes'][0].get('icon') == GetLegendGraphicFilter.warning_icon()
assert 'icon' in b['nodes'][0]
assert 'symbols' not in b['nodes'][0]


def test_invalid_layer_categorized_symbol_layer(client):
""" Test categorized symbol for layer. """
qs = dict(BASE_QUERY)
Expand Down
4 changes: 3 additions & 1 deletion test/test_lizmap_accesscontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ def test_invalid_layer(client):

layers = rv.xpath('//wms:Layer')
assert layers is not None
assert len(layers) == 4, len(layers)
assert len(layers) == 5, len(layers)

# Layer is WMS
layer = "unique_symbol"
assert layer in rv.content.decode('utf-8')

assert 'raster' in rv.content.decode('utf-8')

qs['SERVICE'] = "WFS"
rv = client.get(_build_query_string(qs), project_invalid)
_check_request(rv, 'text/xml')
Expand Down

0 comments on commit 91b7d83

Please sign in to comment.