Skip to content

Commit 7e17a84

Browse files
committed
WMS: improve support for legend graphics
1 parent 36630af commit 7e17a84

File tree

2 files changed

+170
-104
lines changed

2 files changed

+170
-104
lines changed

src/providers/wms/qgswmsprovider.cpp

Lines changed: 158 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ QgsWmsProvider::QgsWmsProvider( QString const &uri )
8888
, mHttpCapabilitiesResponse( 0 )
8989
, mHttpGetLegendGraphicResponse( 0 )
9090
, mGetLegendGraphicImage()
91-
, mGetLegendGraphicScale( 0 )
91+
, mGetLegendGraphicScale( 0.0 )
9292
, mImageCrs( DEFAULT_LATLON_CRS )
9393
, mCachedImage( 0 )
9494
, mCacheReply( 0 )
@@ -370,6 +370,44 @@ QString QgsWmsProvider::getTileUrl() const
370370
}
371371
}
372372

373+
QString QgsWmsProvider::getLegendGraphicUrl() const
374+
{
375+
QString url;
376+
377+
for ( int i = 0; i < mLayersSupported.size() && url.isEmpty(); i++ )
378+
{
379+
const QgsWmsLayerProperty &l = mLayersSupported[i];
380+
381+
if ( l.name != mActiveSubLayers[0] )
382+
continue;
383+
384+
for ( int j = 0; j < l.style.size() && url.isEmpty(); j++ )
385+
{
386+
const QgsWmsStyleProperty &s = l.style[j];
387+
388+
if ( s.name != mActiveSubStyles[0] )
389+
continue;
390+
391+
for ( int k = 0; k < s.legendUrl.size() && url.isEmpty(); k++ )
392+
{
393+
const QgsWmsLegendUrlProperty &l = s.legendUrl[k];
394+
395+
if ( l.format != mImageMimeType )
396+
continue;
397+
398+
url = l.onlineResource.xlinkHref;
399+
}
400+
}
401+
}
402+
403+
if ( url.isEmpty() && mCapabilities.capability.request.getLegendGraphic.dcpType.size() > 0 )
404+
{
405+
url = mCapabilities.capability.request.getLegendGraphic.dcpType.front().http.get.onlineResource.xlinkHref;
406+
}
407+
408+
return url.isEmpty() ? url : prepareUri( url );
409+
}
410+
373411
void QgsWmsProvider::addLayers( QStringList const &layers,
374412
QStringList const &styles )
375413
{
@@ -411,14 +449,46 @@ void QgsWmsProvider::setLayerOrder( QStringList const &layers )
411449
{
412450
QgsDebugMsg( "Entering." );
413451

452+
if ( layers.size() != mActiveSubLayers.size() )
453+
{
454+
QgsDebugMsg( "Invalid layer list length" );
455+
return;
456+
}
457+
458+
QMap<QString, QString> styleMap;
459+
for ( int i = 0; i < mActiveSubLayers.size(); i++ )
460+
{
461+
styleMap.insert( mActiveSubLayers[i], mActiveSubStyles[i] );
462+
}
463+
464+
for ( int i = 0; i < layers.size(); i++ )
465+
{
466+
if ( !styleMap.contains( layers[i] ) )
467+
{
468+
QgsDebugMsg( QString( "Layer %1 not found" ).arg( layers[i] ) );
469+
return;
470+
}
471+
}
472+
414473
mActiveSubLayers = layers;
474+
mActiveSubStyles.clear();
475+
for ( int i = 0; i < layers.size(); i++ )
476+
{
477+
mActiveSubStyles.append( styleMap[ layers[i] ] );
478+
}
415479

416480
QgsDebugMsg( "Exiting." );
417481
}
418482

419483

420484
void QgsWmsProvider::setSubLayerVisibility( QString const & name, bool vis )
421485
{
486+
if ( !mActiveSubLayerVisibility.contains( name ) )
487+
{
488+
QgsDebugMsg( QString( "Layer %1 not found." ).arg( name ) );
489+
return;
490+
}
491+
422492
mActiveSubLayerVisibility[name] = vis;
423493
}
424494

@@ -1822,6 +1892,10 @@ void QgsWmsProvider::parseCapability( QDomElement const & e, QgsWmsCapabilityPro
18221892
{
18231893
ot = &capabilityProperty.request.getFeatureInfo;
18241894
}
1895+
else if ( name == "GetLegendGraphic" || name == "sld:GetLegendGraphic" )
1896+
{
1897+
ot = &capabilityProperty.request.getLegendGraphic;
1898+
}
18251899
else
18261900
{
18271901
QgsDebugMsg( QString( "ows:Operation %1 ignored" ).arg( name ) );
@@ -2197,6 +2271,11 @@ void QgsWmsProvider::parseRequest( QDomElement const & e, QgsWmsRequestProperty&
21972271
QgsDebugMsg( " GetFeatureInfo." );
21982272
parseOperationType( e1, requestProperty.getFeatureInfo );
21992273
}
2274+
else if ( operation == "GetLegendGraphic" || operation == "sld:GetLegendGraphic" )
2275+
{
2276+
QgsDebugMsg( " GetLegendGraphic." );
2277+
parseOperationType( e1, requestProperty.getLegendGraphic );
2278+
}
22002279
}
22012280
n1 = n1.nextSibling();
22022281
}
@@ -2266,7 +2345,8 @@ void QgsWmsProvider::parseStyle( QDomElement const & e, QgsWmsStyleProperty& sty
22662345
}
22672346
else if ( tagName == "LegendURL" )
22682347
{
2269-
// TODO
2348+
styleProperty.legendUrl << QgsWmsLegendUrlProperty();
2349+
parseLegendUrl( e1, styleProperty.legendUrl.last() );
22702350
}
22712351
else if ( tagName == "StyleSheetURL" )
22722352
{
@@ -3556,6 +3636,8 @@ QString QgsWmsProvider::layerMetadata( QgsWmsLayerProperty &layer )
35563636
// Layer Styles
35573637
for ( int j = 0; j < layer.style.size(); j++ )
35583638
{
3639+
const QgsWmsStyleProperty &style = layer.style[j];
3640+
35593641
metadata += "<tr><td>";
35603642
metadata += tr( "Available in style" );
35613643
metadata += "</td>";
@@ -3569,25 +3651,41 @@ QString QgsWmsProvider::layerMetadata( QgsWmsLayerProperty &layer )
35693651
metadata += tr( "Name" );
35703652
metadata += "</th>";
35713653
metadata += "<td>";
3572-
metadata += layer.style[j].name;
3654+
metadata += style.name;
35733655
metadata += "</td></tr>";
35743656

35753657
// Layer Style Title
35763658
metadata += "<tr><th class=\"glossy\">";
35773659
metadata += tr( "Title" );
35783660
metadata += "</th>";
35793661
metadata += "<td>";
3580-
metadata += layer.style[j].title;
3662+
metadata += style.title;
35813663
metadata += "</td></tr>";
35823664

35833665
// Layer Style Abstract
35843666
metadata += "<tr><th class=\"glossy\">";
35853667
metadata += tr( "Abstract" );
35863668
metadata += "</th>";
35873669
metadata += "<td>";
3588-
metadata += layer.style[j].abstract;
3670+
metadata += style.abstract;
35893671
metadata += "</td></tr>";
35903672

3673+
// LegendURLs
3674+
if ( !style.legendUrl.isEmpty() )
3675+
{
3676+
metadata += "<tr><th class=\"glossy\">";
3677+
metadata += tr( "LegendURLs" );
3678+
metadata += "</th>";
3679+
metadata += "<td><table>";
3680+
metadata += "<tr><th>Format</th><th>URL</th></tr>";
3681+
for ( int k = 0; k < style.legendUrl.size(); k++ )
3682+
{
3683+
const QgsWmsLegendUrlProperty &l = style.legendUrl[k];
3684+
metadata += "<tr><td>" + l.format + "</td><td>" + l.onlineResource.xlinkHref + "</td></tr>";
3685+
}
3686+
metadata += "</table></td></tr>";
3687+
}
3688+
35913689
// Close the nested table
35923690
metadata += "</table>";
35933691
metadata += "</td></tr>";
@@ -3773,6 +3871,13 @@ QString QgsWmsProvider::metadata()
37733871
metadata += getFeatureInfoUrl() + ( mIgnoreGetFeatureInfoUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" );
37743872
metadata += "</td></tr>";
37753873

3874+
metadata += "<tr><td>";
3875+
metadata += tr( "GetLegendGraphic" );
3876+
metadata += "</td>";
3877+
metadata += "<td>";
3878+
metadata += getLegendGraphicUrl() + ( mIgnoreGetMapUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" );
3879+
metadata += "</td></tr>";
3880+
37763881
if ( mTiled )
37773882
{
37783883
metadata += "<tr><td>";
@@ -3821,7 +3926,7 @@ QString QgsWmsProvider::metadata()
38213926

38223927
for ( int i = 0; i < mLayersSupported.size(); i++ )
38233928
{
3824-
if ( !mTiled && mActiveSubLayers.indexOf( mLayersSupported[i].name ) >= 0 )
3929+
if ( !mTiled && mActiveSubLayers.contains( mLayersSupported[i].name ) )
38253930
{
38263931
metadata += layerMetadata( mLayersSupported[i] );
38273932
}
@@ -3834,7 +3939,7 @@ QString QgsWmsProvider::metadata()
38343939

38353940
for ( int i = 0; i < mLayersSupported.size(); i++ )
38363941
{
3837-
if ( mActiveSubLayers.indexOf( mLayersSupported[i].name ) < 0 )
3942+
if ( !mActiveSubLayers.contains( mLayersSupported[i].name ) )
38383943
{
38393944
metadata += layerMetadata( mLayersSupported[i] );
38403945
}
@@ -4102,7 +4207,7 @@ QgsRasterIdentifyResult QgsWmsProvider::identify( const QgsPoint & thePoint, Qgs
41024207
int count = -1;
41034208
// Test for which layers are suitable for querying with
41044209
for ( QStringList::const_iterator
4105-
layers = mActiveSubLayers.begin(),
4210+
layers = mActiveSubLayers.begin(),
41064211
styles = mActiveSubStyles.begin();
41074212
layers != mActiveSubLayers.end();
41084213
++layers, ++styles )
@@ -4603,116 +4708,70 @@ QImage QgsWmsProvider::getLegendGraphic( double scale, bool forceRefresh )
46034708
// the layer tags inside capabilities
46044709
QgsDebugMsg( "entering." );
46054710

4606-
if ( !scale && !mGetLegendGraphicScale )
4607-
{
4608-
QgsDebugMsg( QString( "No scale factor set" ) );
4609-
return QImage();
4610-
}
4711+
QString lurl = getLegendGraphicUrl();
46114712

4612-
if ( scale && scale != mGetLegendGraphicScale )
4713+
if ( lurl.isEmpty() )
46134714
{
4614-
forceRefresh = true;
4615-
QgsDebugMsg( QString( "Download again due to scale change from: %1 to: %2" ).arg( mGetLegendGraphicScale ).arg( scale ) );
4715+
QgsDebugMsg( "getLegendGraphic url is empty" );
4716+
return QImage();
46164717
}
46174718

4618-
if ( forceRefresh )
4619-
{
4620-
if ( scale )
4621-
{
4622-
mGetLegendGraphicScale = scale;
4623-
}
4624-
4625-
// if style is not defined, set as "default"
4626-
QString currentStyle( "default" );
4627-
if ( mActiveSubStyles[0] != "" )
4628-
{
4629-
currentStyle = mActiveSubStyles[0];
4630-
}
4719+
forceRefresh |= mGetLegendGraphicImage.isNull() || mGetLegendGraphicScale != scale;
4720+
if ( !forceRefresh )
4721+
return mGetLegendGraphicImage;
46314722

4632-
#if 0
4633-
// add WMS GetGraphicLegend request
4634-
// TODO set sld version using instance var something like mSldVersion
4635-
// TODO at this moment LSD version can be get from LegendURL in getCapability,but parsing of
4636-
// this tag is not complete. Below the code that should work if parsing would correct
4723+
QUrl url( lurl );
46374724

4638-
if ( mActiveSubLayers[0] == mCapabilities.capability.layer.name )
4639-
{
4640-
foreach ( QgsWmsStyleProperty style, mCapabilities.capability.layer.style )
4641-
{
4642-
if ( currentStyle == style.name )
4643-
{
4644-
url.setUrl( style.legendUrl[0].onlineResource.xlinkHref, QUrl::StrictMode );
4645-
}
4646-
}
4647-
} // is a sublayer
4648-
else if ( mActiveSubLayers[0].contains( mCapabilities.capability.layer.name ) )
4649-
{
4650-
foreach ( QgsWmsLayerProperty layerProperty, mCapabilities.capability.layer.layer )
4651-
{
4652-
if ( mActiveSubLayers[0] == layerProperty.name )
4653-
{
4654-
foreach ( QgsWmsStyleProperty style, layerProperty.style )
4655-
{
4656-
if ( currentStyle == style.name )
4657-
{
4658-
url.setUrl( style.legendUrl[0].onlineResource.xlinkHref, QUrl::StrictMode );
4659-
}
4660-
}
4661-
}
4662-
}
4663-
}
4664-
#endif
4665-
QUrl url( mIgnoreGetMapUrl ? mBaseUrl : getMapUrl(), QUrl::StrictMode );
4725+
if ( !url.hasQueryItem( "SERVICE" ) )
46664726
setQueryItem( url, "SERVICE", "WMS" );
4727+
if ( !url.hasQueryItem( "VERSION" ) )
46674728
setQueryItem( url, "VERSION", mCapabilities.version );
4729+
if ( !url.hasQueryItem( "SLD_VERSION" ) )
46684730
setQueryItem( url, "SLD_VERSION", "1.1.0" ); // can not determine SLD_VERSION
4731+
if ( !url.hasQueryItem( "REQUEST" ) )
46694732
setQueryItem( url, "REQUEST", "GetLegendGraphic" );
4670-
setQueryItem( url, "LAYER", mActiveSubLayers[0] );
4671-
setQueryItem( url, "STYLE", currentStyle );
4672-
setQueryItem( url, "SCALE", QString::number( scale, 'f' ) );
4733+
if ( !url.hasQueryItem( "FORMAT" ) )
46734734
setQueryItem( url, "FORMAT", mImageMimeType );
4735+
if ( !url.hasQueryItem( "LAYER" ) )
4736+
setQueryItem( url, "LAYER", mActiveSubLayers[0] );
4737+
if ( !url.hasQueryItem( "STYLE" ) )
4738+
setQueryItem( url, "STYLE", mActiveSubStyles[0] );
46744739

4675-
// add config parameter related to resolution
4676-
QSettings s;
4677-
int defaultLegendGraphicResolution = s.value( "/qgis/defaultLegendGraphicResolution", 0 ).toInt();
4678-
QgsDebugMsg( QString( "defaultLegendGraphicResolution: %1" ).arg( defaultLegendGraphicResolution ) );
4679-
if ( defaultLegendGraphicResolution )
4740+
// add config parameter related to resolution
4741+
QSettings s;
4742+
int defaultLegendGraphicResolution = s.value( "/qgis/defaultLegendGraphicResolution", 0 ).toInt();
4743+
QgsDebugMsg( QString( "defaultLegendGraphicResolution: %1" ).arg( defaultLegendGraphicResolution ) );
4744+
if ( defaultLegendGraphicResolution )
4745+
{
4746+
if ( mDpiMode & dpiQGIS )
4747+
setQueryItem( url, "DPI", QString::number( defaultLegendGraphicResolution ) );
4748+
if ( mDpiMode & dpiUMN )
4749+
setQueryItem( url, "MAP_RESOLUTION", QString::number( defaultLegendGraphicResolution ) );
4750+
if ( mDpiMode & dpiGeoServer )
46804751
{
4681-
if ( url.queryItemValue( "map_resolution" ) != "" )
4682-
{
4683-
setQueryItem( url, "map_resolution", QString::number( defaultLegendGraphicResolution ) );
4684-
}
4685-
else if ( url.queryItemValue( "dpi" ) != "" )
4686-
{
4687-
setQueryItem( url, "dpi", QString::number( defaultLegendGraphicResolution ) );
4688-
}
4689-
else
4690-
{
4691-
QgsLogger::warning( tr( "getLegendGraphic: Can not determine resolution uri parameter [map_resolution | dpi]. No resolution parameter will be used" ) );
4692-
}
4752+
setQueryItem( url, "FORMAT_OPTIONS", QString( "dpi:%1" ).arg( defaultLegendGraphicResolution ) );
4753+
setQueryItem( url, "SCALE", QString::number( scale, 'f' ) );
46934754
}
4755+
}
46944756

4695-
mError = "";
4757+
mGetLegendGraphicScale = scale;
46964758

4697-
QNetworkRequest request( url );
4698-
setAuthorization( request );
4699-
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
4700-
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
4759+
mError = "";
4760+
4761+
QNetworkRequest request( url );
4762+
setAuthorization( request );
4763+
request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork );
4764+
request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
47014765

4702-
QgsDebugMsg( QString( "getlegendgraphics: %1" ).arg( url.toString() ) );
4703-
mGetLegendGraphicReply = QgsNetworkAccessManager::instance()->get( request );
4766+
QgsDebugMsg( QString( "getlegendgraphics: %1" ).arg( url.toString() ) );
4767+
mGetLegendGraphicReply = QgsNetworkAccessManager::instance()->get( request );
47044768

4705-
connect( mGetLegendGraphicReply, SIGNAL( finished() ), this, SLOT( getLegendGraphicReplyFinished() ) );
4706-
connect( mGetLegendGraphicReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( getLegendGraphicReplyProgress( qint64, qint64 ) ) );
4769+
connect( mGetLegendGraphicReply, SIGNAL( finished() ), this, SLOT( getLegendGraphicReplyFinished() ) );
4770+
connect( mGetLegendGraphicReply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( getLegendGraphicReplyProgress( qint64, qint64 ) ) );
47074771

4708-
while ( mGetLegendGraphicReply )
4709-
{
4710-
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, WMS_THRESHOLD );
4711-
}
4712-
}
4713-
else
4772+
while ( mGetLegendGraphicReply )
47144773
{
4715-
QgsDebugMsg( "get cached pixmap." );
4774+
QCoreApplication::processEvents( QEventLoop::ExcludeUserInputEvents, WMS_THRESHOLD );
47164775
}
47174776

47184777
QgsDebugMsg( "exiting." );
@@ -4723,6 +4782,7 @@ QImage QgsWmsProvider::getLegendGraphic( double scale, bool forceRefresh )
47234782
void QgsWmsProvider::getLegendGraphicReplyFinished()
47244783
{
47254784
QgsDebugMsg( "entering." );
4785+
47264786
if ( mGetLegendGraphicReply->error() == QNetworkReply::NoError )
47274787
{
47284788
QgsDebugMsg( "reply ok" );

0 commit comments

Comments
 (0)