Skip to content

Commit

Permalink
Server WMS getPrint: fix HIGHLIGHT with follow map themes
Browse files Browse the repository at this point in the history
Fixes #34178
  • Loading branch information
elpaso authored and github-actions[bot] committed Jun 9, 2021
1 parent 752b414 commit fad88ef
Show file tree
Hide file tree
Showing 6 changed files with 1,722 additions and 15 deletions.
10 changes: 5 additions & 5 deletions src/core/layout/qgslayoutitemmap.cpp
Expand Up @@ -2110,17 +2110,17 @@ QList<QgsMapLayer *> QgsLayoutItemMap::layersToRender( const QgsExpressionContex
QList<QgsMapLayer *> renderLayers;

QString presetName = themeToRender( *evalContext );
if ( !presetName.isEmpty() )
if ( !layers().isEmpty() )
{
renderLayers = layers();
}
else if ( !presetName.isEmpty() )
{
if ( mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
renderLayers = mLayout->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
else // fallback to using map canvas layers
renderLayers = mLayout->project()->mapThemeCollection()->masterVisibleLayers();
}
else if ( !layers().isEmpty() )
{
renderLayers = layers();
}
else
{
renderLayers = mLayout->project()->mapThemeCollection()->masterVisibleLayers();
Expand Down
27 changes: 17 additions & 10 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -617,14 +617,14 @@ namespace QgsWms

if ( !map->keepLayerSet() )
{
QList<QgsMapLayer *> layerSet;
if ( cMapParams.mLayers.isEmpty() )
{
map->setLayers( mapSettings.layers() );
layerSet = mapSettings.layers();
}
else
{
QList<QgsMapLayer *> layerSet;
for ( auto layer : cMapParams.mLayers )
for ( const auto &layer : std::as_const( cMapParams.mLayers ) )
{
if ( mContext.isValidGroup( layer.mNickname ) )
{
Expand Down Expand Up @@ -660,11 +660,10 @@ namespace QgsWms
layerSet << mlayer;
}
}

layerSet << highlightLayers( cMapParams.mHighlightLayers );
std::reverse( layerSet.begin(), layerSet.end() );
map->setLayers( layerSet );
}
layerSet << highlightLayers( cMapParams.mHighlightLayers );
std::reverse( layerSet.begin(), layerSet.end() );
map->setLayers( layerSet );
map->setKeepLayerSet( true );
}

Expand Down Expand Up @@ -2639,13 +2638,21 @@ namespace QgsWms
{
// create sld document from symbology
QDomDocument sldDoc;
if ( !sldDoc.setContent( param.mSld, true ) )
{
QString errorMsg;
int errorLine;
int errorColumn;
if ( !sldDoc.setContent( param.mSld, true, &errorMsg, &errorLine, &errorColumn ) )
{
QgsMessageLog::logMessage( QStringLiteral( "Error parsing SLD for layer %1 at line %2, column %3:\n%4" )
.arg( param.mName )
.arg( errorLine )
.arg( errorColumn )
.arg( errorMsg ),
QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
continue;
}

// create renderer from sld document
QString errorMsg;
std::unique_ptr<QgsFeatureRenderer> renderer;
QDomElement el = sldDoc.documentElement();
renderer.reset( QgsFeatureRenderer::loadSld( el, param.mGeom.type(), errorMsg ) );
Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Expand Up @@ -394,6 +394,7 @@ if (WITH_SERVER)
ADD_PYTHON_TEST(PyQgsServerWMSGetPrintExtra test_qgsserver_wms_getprint_extra.py)
ADD_PYTHON_TEST(PyQgsServerWMSGetPrintOutputs test_qgsserver_wms_getprint_outputs.py)
ADD_PYTHON_TEST(PyQgsServerWMSGetPrintAtlas test_qgsserver_wms_getprint_atlas.py)
ADD_PYTHON_TEST(PyQgsServerWMSGetPrintMapTheme, test_qgsserver_wms_getprint_maptheme.py)
ADD_PYTHON_TEST(PyQgsServerWMSDimension test_qgsserver_wms_dimension.py)
ADD_PYTHON_TEST(PyQgsServerSettings test_qgsserver_settings.py)
ADD_PYTHON_TEST(PyQgsServerProjectUtils test_qgsserver_projectutils.py)
Expand Down
189 changes: 189 additions & 0 deletions tests/src/python/test_qgsserver_wms_getprint_maptheme.py
@@ -0,0 +1,189 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsServer WMS GetPrint map theme.
From build dir, run: ctest -R PyQgsServerWMSGetPrintMapTheme -V
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Alessandro Pasotti'
__date__ = '24/05/2021'
__copyright__ = 'Copyright 2021, The QGIS Project'

import os
import shutil

# Needed on Qt 5 so that the serialization of XML is consistent among all executions
os.environ['QT_HASH_SEED'] = '1'

from qgis.testing import unittest
from qgis.server import QgsBufferServerRequest, QgsBufferServerResponse
from qgis.core import QgsProject
from qgis.PyQt.QtCore import QTemporaryDir
from qgis.PyQt.QtGui import QImage


from test_qgsserver import QgsServerTestBase
from utilities import unitTestDataPath


class PyQgsServerWMSGetPrintMapTheme(QgsServerTestBase):
"""Tests for issue GH #34178 QGIS Server GetPrint:
HIGHLIGHT_GEOM is not printed if map layers are configured to follow a map theme"""

def test_wms_getprint_maptheme(self):
"""Test project has 2 layer: red and green and three templates:
red: map theme red
green: map theme green
blank: non map theme
"""

tmp_dir = QTemporaryDir()
shutil.copyfile(os.path.join(unitTestDataPath('qgis_server'), 'test_project_mapthemes.qgs'), os.path.join(tmp_dir.path(), 'test_project_mapthemes.qgs'))
shutil.copyfile(os.path.join(unitTestDataPath('qgis_server'), 'test_project_mapthemes.gpkg'), os.path.join(tmp_dir.path(), 'test_project_mapthemes.gpkg'))

project = QgsProject()
self.assertTrue(project.read(os.path.join(tmp_dir.path(), 'test_project_mapthemes.qgs')))

params = {
"SERVICE": "WMS",
"VERSION": "1.3",
"REQUEST": "GetPrint",
"TEMPLATE": "blank",
"FORMAT": "png",
"LAYERS": "",
"map0:EXTENT": "44.92867722467413216,7.097696894150993252,45.0714498943264914,7.378188333645007368",
"map0:LAYERS": "red",
"CRS": "EPSG:4326",
"DPI": '72'
}

polygon = 'POLYGON((7.09769689415099325 44.92867722467413216, 7.37818833364500737 44.92867722467413216, 7.37818833364500737 45.0714498943264914, 7.09769689415099325 45.0714498943264914, 7.09769689415099325 44.92867722467413216))'

######################################################
# Template map theme tests, no HIGHLIGHT

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 255)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 0)

params["map0:LAYERS"] = "green"
response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 255)
self.assertEqual(color.blue(), 0)

params["map0:LAYERS"] = ""
params["TEMPLATE"] = "red"
response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 255)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 0)

params["map0:LAYERS"] = ""
params["TEMPLATE"] = "green"
response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 255)
self.assertEqual(color.blue(), 0)

######################################################
# Start HIGHLIGHT tests

params["TEMPLATE"] = "blank"
params["map0:LAYERS"] = "red"
params["map0:HIGHLIGHT_GEOM"] = polygon
params["map0:HIGHLIGHT_SYMBOL"] = r'<StyledLayerDescriptor><UserStyle><FeatureTypeStyle><Rule><PolygonSymbolizer><Fill><CssParameter name="fill">%230000FF</CssParameter></Fill></PolygonSymbolizer></Rule></FeatureTypeStyle></UserStyle></StyledLayerDescriptor>'

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 255)

# Test highlight without layers
params["TEMPLATE"] = "blank"
params["map0:LAYERS"] = ""

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 255)

# Test highlight on follow theme (issue GH #34178)
params["TEMPLATE"] = "red"

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 255)

# Test highlight on follow theme (issue GH #34178)
params["TEMPLATE"] = "green"

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 255)

# Test highlight on follow theme, but add LAYERS (issue GH #34178)
params["TEMPLATE"] = "green"
params["LAYERS"] = "red"

response = QgsBufferServerResponse()
request = QgsBufferServerRequest('?' + '&'.join(["%s=%s" % i for i in params.items()]))
self.server.handleRequest(request, response, project)

image = QImage.fromData(response.body(), "PNG")
color = image.pixelColor(100, 100)
self.assertEqual(color.red(), 0)
self.assertEqual(color.green(), 0)
self.assertEqual(color.blue(), 255)


if __name__ == '__main__':
unittest.main()
Binary file not shown.

0 comments on commit fad88ef

Please sign in to comment.