Skip to content

Commit

Permalink
[WMS provider] Tolerate GetCapabilities response with several top-lev…
Browse files Browse the repository at this point in the history
…el layers

Fix #13762

Also, in case there's a single layer advertized, show it in the browser.
  • Loading branch information
rouault committed Jun 13, 2016
1 parent dfe4553 commit 1ec7ad5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 29 deletions.
15 changes: 3 additions & 12 deletions src/providers/wms/qgswmscapabilities.cpp
Expand Up @@ -570,7 +570,9 @@ void QgsWmsCapabilities::parseCapability( QDomElement const & e, QgsWmsCapabilit
}
else if ( tagName == "Layer" )
{
parseLayer( e1, capabilityProperty.layer );
QgsWmsLayerProperty layer;
parseLayer( e1, layer );
capabilityProperty.layers.push_back( layer );
}
else if ( tagName == "VendorSpecificCapabilities" )
{
Expand Down Expand Up @@ -947,10 +949,6 @@ void QgsWmsCapabilities::parseLayer( QDomElement const & e, QgsWmsLayerProperty&
// Store if the layer is queryable
mQueryableForLayer[ layerProperty.name ] = layerProperty.queryable;

// Store the available Coordinate Reference Systems for the layer so that it
// can be combined with others later in supportedCrsForLayers()
mCrsForLayer[ layerProperty.name ] = layerProperty.crs;

// Insert into the local class' registry
mLayersSupported.push_back( layerProperty );

Expand All @@ -966,13 +964,6 @@ void QgsWmsCapabilities::parseLayer( QDomElement const & e, QgsWmsLayerProperty&
mLayerParentNames[ layerProperty.orderId ] = QStringList() << layerProperty.name << layerProperty.title << layerProperty.abstract;
}

if ( !parentProperty )
{
// Why clear()? I need top level access. Seems to work in standard select dialog without clear.
//layerProperty.layer.clear();
layerProperty.crs.clear();
}

//QgsDebugMsg( "exiting." );
}

Expand Down
12 changes: 6 additions & 6 deletions src/providers/wms/qgswmscapabilities.h
Expand Up @@ -399,7 +399,12 @@ struct QgsWmsCapabilityProperty
{
QgsWmsRequestProperty request;
QgsWmsExceptionProperty exception;
QgsWmsLayerProperty layer;

// Top level layer should normally be present max once
// <element name="Capability">
// <element ref="wms:Layer" minOccurs="0"/> - default maxOccurs=1
// but there are a few non conformant capabilities around (#13762)
QList<QgsWmsLayerProperty> layers;

QList<QgsWmtsTileLayer> tileLayers;
QHash<QString, QgsWmtsTileMatrixSet> tileMatrixSets;
Expand Down Expand Up @@ -663,11 +668,6 @@ class QgsWmsCapabilities
*/
QMap<QString, bool> mQueryableForLayer;

/**
* available CRSs per layer
*/
QMap<QString, QStringList > mCrsForLayer;

/**
* layers hosted by the WMS
*/
Expand Down
38 changes: 28 additions & 10 deletions src/providers/wms/qgswmsdataitems.cpp
Expand Up @@ -86,19 +86,37 @@ QVector<QgsDataItem*> QgsWMSConnectionItem::createChildren()
QgsWmsCapabilitiesProperty capabilitiesProperty = caps.capabilitiesProperty();
const QgsWmsCapabilityProperty& capabilityProperty = capabilitiesProperty.capability;

// Top level layer is present max once
// <element name="Capability">
// <element ref="wms:Layer" minOccurs="0"/> - default maxOccurs=1
const QgsWmsLayerProperty &topLayerProperty = capabilityProperty.layer;
Q_FOREACH ( const QgsWmsLayerProperty &layerProperty, topLayerProperty.layer )
// If we have several top-level layers, or if we just have one single top-level layer,
// then use those top-level layers directly
if ( capabilityProperty.layers.size() > 1 ||
( capabilityProperty.layers.size() == 1 && capabilityProperty.layers[0].layer.size() == 0 ) )
{
// Attention, the name may be empty
QgsDebugMsg( QString::number( layerProperty.orderId ) + ' ' + layerProperty.name + ' ' + layerProperty.title );
QString pathName = layerProperty.name.isEmpty() ? QString::number( layerProperty.orderId ) : layerProperty.name;
Q_FOREACH ( const QgsWmsLayerProperty& layerProperty, capabilityProperty.layers )
{
// Attention, the name may be empty
QgsDebugMsg( QString::number( layerProperty.orderId ) + ' ' + layerProperty.name + ' ' + layerProperty.title );
QString pathName = layerProperty.name.isEmpty() ? QString::number( layerProperty.orderId ) : layerProperty.name;

QgsWMSLayerItem *layer = new QgsWMSLayerItem( this, layerProperty.title, mPath + '/' + pathName, capabilitiesProperty, uri, layerProperty );

children << layer;
}
}
// Otherwise if we have just one single top-level layers with children, then
// skip this top-level layer and iterate directly on its children
// Note (E. Rouault): this was the historical behaviour before fixing #13762
else if ( capabilityProperty.layers.size() == 1 )
{
Q_FOREACH ( const QgsWmsLayerProperty &layerProperty, capabilityProperty.layers[0].layer )
{
// Attention, the name may be empty
QgsDebugMsg( QString::number( layerProperty.orderId ) + ' ' + layerProperty.name + ' ' + layerProperty.title );
QString pathName = layerProperty.name.isEmpty() ? QString::number( layerProperty.orderId ) : layerProperty.name;

QgsWMSLayerItem *layer = new QgsWMSLayerItem( this, layerProperty.title, mPath + '/' + pathName, capabilitiesProperty, uri, layerProperty );
QgsWMSLayerItem *layer = new QgsWMSLayerItem( this, layerProperty.title, mPath + '/' + pathName, capabilitiesProperty, uri, layerProperty );

children << layer;
children << layer;
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -961,7 +961,13 @@ static const QgsWmsLayerProperty* _findNestedLayerProperty( const QString& layer

bool QgsWmsProvider::extentForNonTiledLayer( const QString& layerName, const QString& crs, QgsRectangle& extent )
{
const QgsWmsLayerProperty* layerProperty = _findNestedLayerProperty( layerName, &mCaps.mCapabilities.capability.layer );
const QgsWmsLayerProperty* layerProperty = nullptr;
Q_FOREACH ( const QgsWmsLayerProperty& toplevelLayer, mCaps.mCapabilities.capability.layers )
{
layerProperty = _findNestedLayerProperty( layerName, &toplevelLayer );
if ( layerProperty )
break;
}
if ( !layerProperty )
return false;

Expand Down

0 comments on commit 1ec7ad5

Please sign in to comment.