Skip to content
Permalink
Browse files

Merge pull request #9385 from pblottiere/server_external_clean

[server] Update external layer management
  • Loading branch information
pblottiere committed Mar 19, 2019
2 parents 477ec2a + 63c0278 commit 1e8aec45a01db7d58a978afc7e5882f0e952bc96
@@ -19,6 +19,8 @@
#include "qgsdatasourceuri.h"
#include "qgsmessagelog.h"

const QString EXTERNAL_LAYER_PREFIX = QStringLiteral( "EXTERNAL_WMS:" );

namespace QgsWms
{
//
@@ -1408,6 +1410,10 @@ namespace QgsWms
for ( int i = 0; i < layers.size(); i++ )
{
QString layer = layers[i];

if ( isExternalLayer( layer ) )
continue;

QgsWmsParametersLayer param;
param.mNickname = layer;

@@ -1492,6 +1498,21 @@ namespace QgsWms
return params;
}

QList<QgsWmsParametersExternalLayer> QgsWmsParameters::externalLayersParameters() const
{
QList<QgsWmsParametersExternalLayer> externalLayers;

QStringList layers = allLayersNickname();
QStringList::const_iterator rit = std::remove_if( layers.begin(), layers.end(), QgsWmsParameters::isExternalLayer );

for ( QStringList::const_iterator it = layers.begin(); it != rit; ++it )
{
externalLayers << externalLayerParameter( *it );
}

return externalLayers;
}

QString QgsWmsParameters::backgroundColor() const
{
return mWmsParameters[ QgsWmsParameter::BGCOLOR ].toString();
@@ -1577,13 +1598,30 @@ namespace QgsWms
}

//layers
QStringList layers;
QStringList allLayers;
wmsParam = idParameter( QgsWmsParameter::LAYERS, mapId );
if ( wmsParam.isValid() )
{
layers = wmsParam.toStringList();
allLayers = wmsParam.toStringList();
}

// external layers
QStringList layers;
QList<QgsWmsParametersExternalLayer> eParams;

for ( const auto &layer : qgis::as_const( allLayers ) )
{
if ( isExternalLayer( layer ) )
{
eParams << externalLayerParameter( layer );
}
else
{
layers << layer;
}
}
param.mExternalLayers = eParams;

QStringList styles;
wmsParam = idParameter( QgsWmsParameter::STYLES, mapId );
if ( wmsParam.isValid() )
@@ -1763,4 +1801,20 @@ namespace QgsWms

return p;
}

QgsWmsParametersExternalLayer QgsWmsParameters::externalLayerParameter( const QString &name ) const
{
QgsWmsParametersExternalLayer param;

param.mName = name;
param.mName.remove( 0, EXTERNAL_LAYER_PREFIX.size() );
param.mUri = externalWMSUri( param.mName );

return param;
}

bool QgsWmsParameters::isExternalLayer( const QString &name )
{
return name.startsWith( EXTERNAL_LAYER_PREFIX );
}
}
@@ -55,6 +55,12 @@ namespace QgsWms
QString mStyle;
};

struct QgsWmsParametersExternalLayer
{
QString mName;
QString mUri;
};

struct QgsWmsParametersHighlightLayer
{
QString mName;
@@ -79,6 +85,7 @@ namespace QgsWms
float mGridX = 0;
float mGridY = 0;
QList<QgsWmsParametersLayer> mLayers; // list of layers for this composer map
QList<QgsWmsParametersExternalLayer> mExternalLayers; // list of external layers for this composer map
QList<QgsWmsParametersHighlightLayer> mHighlightLayers; // list of highlight layers for this composer map
};

@@ -944,6 +951,12 @@ namespace QgsWms
*/
QList<QgsWmsParametersHighlightLayer> highlightLayersParameters() const;

/**
* Returns parameters for each external layer.
* \since QGIS 3.8
*/
QList<QgsWmsParametersExternalLayer> externalLayersParameters() const;

/**
* Returns HIGHLIGHT_GEOM as a list of string in WKT.
* \returns highlight geometries
@@ -1165,6 +1178,8 @@ namespace QgsWms
QStringList atlasPk() const;

private:
static bool isExternalLayer( const QString &name );

bool loadParameter( const QString &name, const QString &value ) override;

void save( const QgsWmsParameter &parameter, bool multi = false );
@@ -1174,6 +1189,8 @@ namespace QgsWms
void raiseError( const QString &msg ) const;
void log( const QString &msg ) const;

QgsWmsParametersExternalLayer externalLayerParameter( const QString &name ) const;

QMultiMap<QString, QgsWmsParametersFilter> layerFilters( const QStringList &layers ) const;

QMap<QgsWmsParameter::Name, QgsWmsParameter> mWmsParameters;
@@ -653,13 +653,14 @@ namespace QgsWms

if ( !map->keepLayerSet() )
{
if ( cMapParams.mLayers.isEmpty() )
if ( cMapParams.mLayers.isEmpty() && cMapParams.mExternalLayers.isEmpty() )
{
map->setLayers( mapSettings.layers() );
}
else
{
QList<QgsMapLayer *> layerSet = stylizedLayers( cMapParams.mLayers );
layerSet << externalLayers( cMapParams.mExternalLayers );
layerSet << highlightLayers( cMapParams.mHighlightLayers );
std::reverse( layerSet.begin(), layerSet.end() );
map->setLayers( layerSet );
@@ -856,6 +857,9 @@ namespace QgsWms
setLayerAccessControlFilter( layer );
}

// add external layers
layers = layers << externalLayers( mWmsParameters.externalLayersParameters() );

// add highlight layers above others
layers = layers << highlightLayers( mWmsParameters.highlightLayersParameters() );

@@ -2914,6 +2918,25 @@ namespace QgsWms
return highlightLayers;
}

QList<QgsMapLayer *> QgsRenderer::externalLayers( const QList<QgsWmsParametersExternalLayer> &params )
{
QList<QgsMapLayer *> layers;

for ( const QgsWmsParametersExternalLayer &param : params )
{
std::unique_ptr<QgsMapLayer> layer = qgis::make_unique< QgsRasterLayer >( param.mUri, param.mName, QStringLiteral( "wms" ) );

if ( layer->isValid() )
{
// to delete later
mTemporaryLayers.append( layer.release() );
layers << mTemporaryLayers.last();
}
}

return layers;
}

QList<QgsMapLayer *> QgsRenderer::sldStylizedLayers( const QString &sld ) const
{
QList<QgsMapLayer *> layers;
@@ -2976,19 +2999,7 @@ namespace QgsWms
{
QString nickname = param.mNickname;
QString style = param.mStyle;
if ( nickname.startsWith( "EXTERNAL_WMS:" ) )
{
QString externalLayerId = nickname;
externalLayerId.remove( 0, 13 );
QgsMapLayer *externalWMSLayer = createExternalWMSLayer( externalLayerId );
if ( externalWMSLayer )
{
layers.append( externalWMSLayer );
mNicknameLayers[nickname] = externalWMSLayer; //might be used later in GetPrint request
mTemporaryLayers.append( externalWMSLayer );
}
}
else if ( mNicknameLayers.contains( nickname ) && !mRestrictedLayers.contains( nickname ) )
if ( mNicknameLayers.contains( nickname ) && !mRestrictedLayers.contains( nickname ) )
{
if ( !style.isEmpty() )
{
@@ -3032,19 +3043,6 @@ namespace QgsWms
return layers;
}

QgsMapLayer *QgsRenderer::createExternalWMSLayer( const QString &externalLayerId ) const
{
QString wmsUri = mWmsParameters.externalWMSUri( externalLayerId.toUpper() );
QgsMapLayer *wmsLayer = new QgsRasterLayer( wmsUri, externalLayerId, QStringLiteral( "wms" ) );
if ( !wmsLayer->isValid() )
{
delete wmsLayer;
return nullptr;
}

return wmsLayer;
}

void QgsRenderer::removeTemporaryLayers()
{
qDeleteAll( mTemporaryLayers );
@@ -122,6 +122,9 @@ namespace QgsWms
// Build and returns highlight layers
QList<QgsMapLayer *> highlightLayers( QList<QgsWmsParametersHighlightLayer> params );

// Build and returns external layers
QList<QgsMapLayer *> externalLayers( const QList<QgsWmsParametersExternalLayer> &params );

// Init a map with nickname for layers' project
void initNicknameLayers();

@@ -289,9 +292,6 @@ namespace QgsWms
* */
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint = false );

//! Creates external WMS layer. Caller takes ownership
QgsMapLayer *createExternalWMSLayer( const QString &externalLayerId ) const;

void removeTemporaryLayers();

void handlePrintErrors( const QgsLayout *layout ) const;
@@ -1457,6 +1457,32 @@ def test_wms_getmap_datasource_error(self):

self.assertTrue('ServerException' in str(r))

@unittest.skipIf(os.environ.get('TRAVIS', '') == 'true', 'Can\'t rely on external resources for continuous integration')
def test_wms_getmap_external(self):
# 1 bits
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"REQUEST": "GetMap",
"LAYERS": "EXTERNAL_WMS:landsat",
"landsat:layers": "GEBCO_LATEST",
"landsat:dpiMode": "7",
"landsat:url": "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv",
"landsat:crs": "EPSG:4326",
"landsat:styles": "default",
"landsat:format": "image/jpeg",
"landsat:bbox": "-90,-180,90,180",
"landsat:version": "1.3.0",
"STYLES": "",
"BBOX": "-90,-180,90,180",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:4326"
}.items())])

r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetMap_External", 20000)


if __name__ == '__main__':
unittest.main()
@@ -437,6 +437,30 @@ def test_wms_getprint_atlas_getProjectSettings(self):
self.assertTrue('atlasEnabled="1"' in str(r))
self.assertTrue('<PrimaryKeyAttribute>' in str(r))

@unittest.skipIf(os.environ.get('TRAVIS', '') == 'true', 'Can\'t rely on external resources for continuous integration')
def test_wms_getprint_external(self):
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"map0:EXTENT": "-90,-180,90,180",
"map0:LAYERS": "EXTERNAL_WMS:landsat",
"landsat:layers": "GEBCO_LATEST",
"landsat:dpiMode": "7",
"landsat:url": "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv",
"landsat:crs": "EPSG:4326",
"landsat:styles": "default",
"landsat:format": "image/jpeg",
"landsat:bbox": "-90,-180,90,180",
"landsat:version": "1.3.0",
"CRS": "EPSG:4326"
}.items())])

r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetPrint_External")


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

0 comments on commit 1e8aec4

Please sign in to comment.
You can’t perform that action at this time.