Skip to content

Commit 8cde0d3

Browse files
committedMay 7, 2012
WMTS/WMS updates:
- larger precision in BBOX (WMS/WMS-C) - keep GetCapabilities request or document for GetCapabilities request (WMTS) - parse multiple image format and infoFormat elements in GetCapabilities response - support diffent nestings of TileMatrixSetLink/TileMatrixSet - case insesitive parsing of ResourceURL attributes
1 parent c819bf1 commit 8cde0d3

File tree

3 files changed

+115
-78
lines changed

3 files changed

+115
-78
lines changed
 

‎src/providers/wms/qgswmsprovider.cpp

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ void QgsWmsProvider::parseUri( QString uri )
234234

235235
QString QgsWmsProvider::prepareUri( QString uri ) const
236236
{
237+
if ( uri.contains( "SERVICE=WMTS" ) || uri.contains( "/WMTSCapabilities.xml" ) )
238+
{
239+
return uri;
240+
}
241+
237242
if ( !uri.contains( "?" ) )
238243
{
239244
uri.append( "?" );
@@ -548,10 +553,10 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
548553

549554
// Bounding box in WMS format (Warning: does not work with scientific notation)
550555
QString bbox = QString( changeXY ? "%2,%1,%4,%3" : "%1,%2,%3,%4" )
551-
.arg( viewExtent.xMinimum(), 0, 'f' )
552-
.arg( viewExtent.yMinimum(), 0, 'f' )
553-
.arg( viewExtent.xMaximum(), 0, 'f' )
554-
.arg( viewExtent.yMaximum(), 0, 'f' );
556+
.arg( viewExtent.xMinimum(), 0, 'f', 16 )
557+
.arg( viewExtent.yMinimum(), 0, 'f', 16 )
558+
.arg( viewExtent.xMaximum(), 0, 'f', 16 )
559+
.arg( viewExtent.yMaximum(), 0, 'f', 16 );
555560

556561
mCachedImage = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
557562
mCachedImage->fill( 0 );
@@ -702,7 +707,6 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
702707
double thMap = tm->tileHeight * tres;
703708
QgsDebugMsg( QString( "tile map size: %1,%2" ).arg( twMap, 0, 'f' ).arg( thMap, 0, 'f' ) );
704709

705-
706710
int minTileCol = 0;
707711
int maxTileCol = tm->matrixWidth - 1;
708712
int minTileRow = 0;
@@ -759,10 +763,10 @@ QImage *QgsWmsProvider::draw( QgsRectangle const &viewExtent, int pixelWidth, i
759763
QString turl;
760764
turl += url.toString();
761765
turl += QString( changeXY ? "&BBOX=%2,%1,%4,%3" : "&BBOX=%1,%2,%3,%4" )
762-
.arg( tm->topLeft.x() + col * twMap, 0, 'f' )
763-
.arg( tm->topLeft.y() - ( row + 1 ) * thMap, 0, 'f' )
764-
.arg( tm->topLeft.x() + ( col + 1 ) * twMap, 0, 'f' )
765-
.arg( tm->topLeft.y() - row * thMap, 0, 'f' );
766+
.arg( tm->topLeft.x() + col * twMap /* + twMap * 0.001 */, 0, 'f', 16 )
767+
.arg( tm->topLeft.y() - ( row + 1 ) * thMap /* - thMap * 0.001 */, 0, 'f', 16 )
768+
.arg( tm->topLeft.x() + ( col + 1 ) * twMap /* - twMap * 0.001 */, 0, 'f', 16 )
769+
.arg( tm->topLeft.y() - row * thMap /* + thMap * 0.001 */, 0, 'f', 16 );
766770

767771
QNetworkRequest request( turl );
768772
setAuthorization( request );
@@ -964,17 +968,19 @@ void QgsWmsProvider::tileReplyFinished()
964968
QRectF r = reply->request().attribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ) ).toRectF();
965969

966970
#if QT_VERSION >= 0x40500
967-
QgsDebugMsg( QString( "tile reply %1 (%2) tile:%3 rect:%4,%5 %6x%7) fromcache:%8 error:%9" )
971+
QgsDebugMsg( QString( "tile reply %1 (%2) tile:%3 rect:%4,%5 %6x%7) fromcache:%8 error:%9 url:%10" )
968972
.arg( tileReqNo ).arg( mTileReqNo ).arg( tileNo )
969973
.arg( r.left(), 0, 'f' ).arg( r.bottom(), 0, 'f' ).arg( r.width(), 0, 'f' ).arg( r.height(), 0, 'f' )
970974
.arg( fromCache )
971975
.arg( reply->errorString() )
976+
.arg( reply->url().toString() )
972977
);
973978
#else
974-
QgsDebugMsg( QString( "tile reply %1 (%2) tile:%3 rect:%4,%5 %6x%7) error:%8" )
979+
QgsDebugMsg( QString( "tile reply %1 (%2) tile:%3 rect:%4,%5 %6x%7) error:%8 url:%9" )
975980
.arg( tileReqNo ).arg( mTileReqNo ).arg( tileNo )
976981
.arg( r.left(), 0, 'f' ).arg( r.bottom(), 0, 'f' ).arg( r.width(), 0, 'f' ).arg( r.height(), 0, 'f' )
977982
.arg( reply->errorString() )
983+
.arg( reply->url().toString() )
978984
);
979985
#endif
980986

@@ -1202,7 +1208,12 @@ bool QgsWmsProvider::retrieveServerCapabilities( bool forceRefresh )
12021208

12031209
if ( mHttpCapabilitiesResponse.isNull() || forceRefresh )
12041210
{
1205-
QString url = mBaseUrl + "SERVICE=WMS&REQUEST=GetCapabilities";
1211+
QString url = mBaseUrl;
1212+
if ( !url.contains( "SERVICE=WMTS" ) &&
1213+
!url.contains( "/WMTSCapabilities.xml" ) )
1214+
{
1215+
url += "SERVICE=WMS&REQUEST=GetCapabilities";
1216+
}
12061217

12071218
mError = "";
12081219

@@ -2317,7 +2328,7 @@ void QgsWmsProvider::parseTileSetProfile( QDomElement const &e )
23172328
}
23182329
else if ( tagName == "Format" )
23192330
{
2320-
l.format = e1.text();
2331+
l.formats << e1.text();
23212332
}
23222333
else if ( tagName == "BoundingBox" )
23232334
{
@@ -2574,12 +2585,17 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
25742585
l.defaultStyle = s.identifier;
25752586
}
25762587

2577-
l.format = e0.firstChildElement( "Format" ).text();
2578-
l.infoFormat = e0.firstChildElement( "InfoFormat" ).text();
2588+
for ( QDomElement e1 = e0.firstChildElement( "Format" ); !e1.isNull(); e1 = e1.nextSiblingElement( "Format" ) )
2589+
{
2590+
l.formats << e1.text();
2591+
}
2592+
2593+
for ( QDomElement e1 = e0.firstChildElement( "InfoFormat" ); !e1.isNull(); e1 = e1.nextSiblingElement( "InfoFormat" ) )
2594+
{
2595+
l.infoFormats << e1.text();
2596+
}
25792597

2580-
for ( QDomElement e1 = e0.firstChildElement( "Dimension" );
2581-
!e1.isNull();
2582-
e1 = e1.nextSiblingElement( "Dimension" ) )
2598+
for ( QDomElement e1 = e0.firstChildElement( "Dimension" ); !e1.isNull(); e1 = e1.nextSiblingElement( "Dimension" ) )
25832599
{
25842600
QgsWmtsDimension d;
25852601

@@ -2603,49 +2619,49 @@ void QgsWmsProvider::parseWMTSContents( QDomElement const &e )
26032619
l.dimensions.insert( d.identifier, d );
26042620
}
26052621

2606-
for ( QDomElement e1 = e0.firstChildElement( "TileMatrixSetLink" ).firstChildElement( "TileMatrixSet" );
2607-
!e1.isNull();
2608-
e1 = e1.nextSiblingElement( "TileMatrixSet" ) )
2622+
for ( QDomElement e1 = e0.firstChildElement( "TileMatrixSetLink" ); !e1.isNull(); e1 = e1.nextSiblingElement( "TileMatrixSetLink" ) )
26092623
{
2610-
QgsWmtsTileMatrixSetLink sl;
2611-
2612-
sl.tileMatrixSet = e1.text();
2613-
if ( !mTileMatrixSets.contains( sl.tileMatrixSet ) )
2624+
for ( QDomElement e2 = e1.firstChildElement( "TileMatrixSet" ); !e2.isNull(); e2 = e2.nextSiblingElement( "TileMatrixSet" ) )
26142625
{
2615-
QgsDebugMsg( QString( "tileMatrixSet %1 not found." ).arg( id ) );
2616-
continue;
2617-
}
2626+
QgsWmtsTileMatrixSetLink sl;
26182627

2619-
for ( QDomElement e2 = e1.firstChildElement( "TileMatrixSetLimits" ).firstChildElement( "TileMatrixLimits" );
2620-
!e2.isNull();
2621-
e2 = e2.nextSiblingElement( "TileMatrixLimits" ) )
2622-
{
2623-
QgsWmtsTileMatrixLimits limit;
2628+
sl.tileMatrixSet = e2.text();
2629+
if ( !mTileMatrixSets.contains( sl.tileMatrixSet ) )
2630+
{
2631+
QgsDebugMsg( QString( "tileMatrixSet %1 not found." ).arg( id ) );
2632+
continue;
2633+
}
26242634

2625-
QString id = e2.firstChildElement( "TileMatrix" ).text();
2635+
for ( QDomElement e3 = e2.firstChildElement( "TileMatrixSetLimits" ); !e3.isNull(); e3 = e3.nextSiblingElement( "TileMatrixSetLimits" ) )
2636+
{
2637+
for ( QDomElement e4 = e3.firstChildElement( "TileMatrixLimits" ); !e4.isNull(); e4 = e4.nextSiblingElement( "TileMatrixLimits" ) )
2638+
{
2639+
QgsWmtsTileMatrixLimits limit;
26262640

2627-
limit.minTileRow = e2.firstChildElement( "MinTileRow" ).text().toInt();
2628-
limit.maxTileRow = e2.firstChildElement( "MaxTileRow" ).text().toInt();
2629-
limit.minTileCol = e2.firstChildElement( "MinTileCol" ).text().toInt();
2630-
limit.maxTileCol = e2.firstChildElement( "MaxTileCol" ).text().toInt();
2641+
QString id = e4.firstChildElement( "TileMatrix" ).text();
26312642

2632-
sl.limits.insert( id, limit );
2633-
}
2643+
limit.minTileRow = e4.firstChildElement( "MinTileRow" ).text().toInt();
2644+
limit.maxTileRow = e4.firstChildElement( "MaxTileRow" ).text().toInt();
2645+
limit.minTileCol = e4.firstChildElement( "MinTileCol" ).text().toInt();
2646+
limit.maxTileCol = e4.firstChildElement( "MaxTileCol" ).text().toInt();
26342647

2635-
l.setLinks.insert( id, sl );
2648+
sl.limits.insert( id, limit );
2649+
}
2650+
}
2651+
2652+
l.setLinks.insert( sl.tileMatrixSet, sl );
2653+
}
26362654
}
26372655

2638-
for ( QDomElement e1 = e0.firstChildElement( "ResourceURL" );
2639-
!e1.isNull();
2640-
e1 = e1.nextSiblingElement( "ResourceURL" ) )
2656+
for ( QDomElement e1 = e0.firstChildElement( "ResourceURL" ); !e1.isNull(); e1 = e1.nextSiblingElement( "ResourceURL" ) )
26412657
{
2642-
QString format = e1.attribute( "format" );
2643-
QString resourceType = e1.attribute( "resourceType" );
2644-
QString tmpl = e1.attribute( "template" );
2658+
QString format = nodeAttribute( e1, "format" );
2659+
QString resourceType = nodeAttribute( e1, "resourceType" );
2660+
QString tmpl = nodeAttribute( e1, "template" );
26452661

26462662
if ( format.isEmpty() || resourceType.isEmpty() || tmpl.isEmpty() )
26472663
{
2648-
QgsDebugMsg( QString( "SKIPPING ResourcURL format=%1 resourceType=%2 template=%3" )
2664+
QgsDebugMsg( QString( "SKIPPING ResourceURL format=%1 resourceType=%2 template=%3" )
26492665
.arg( format )
26502666
.arg( resourceType )
26512667
.arg( tmpl ) ) ;
@@ -3614,10 +3630,10 @@ QStringList QgsWmsProvider::identifyAs( const QgsPoint& point, QString format )
36143630

36153631
// Compose request to WMS server
36163632
QString bbox = QString( changeXY ? "%2,%1,%4,%3" : "%1,%2,%3,%4" )
3617-
.arg( mCachedViewExtent.xMinimum(), 0, 'f' )
3618-
.arg( mCachedViewExtent.yMinimum(), 0, 'f' )
3619-
.arg( mCachedViewExtent.xMaximum(), 0, 'f' )
3620-
.arg( mCachedViewExtent.yMaximum(), 0, 'f' );
3633+
.arg( mCachedViewExtent.xMinimum(), 0, 'f', 16 )
3634+
.arg( mCachedViewExtent.yMinimum(), 0, 'f', 16 )
3635+
.arg( mCachedViewExtent.xMaximum(), 0, 'f', 16 )
3636+
.arg( mCachedViewExtent.yMaximum(), 0, 'f', 16 );
36213637

36223638
// Test for which layers are suitable for querying with
36233639
for ( QStringList::const_iterator
@@ -3819,7 +3835,6 @@ QVector<QgsWmsSupportedFormat> QgsWmsProvider::supportedFormats()
38193835
QVector<QgsWmsSupportedFormat> formats;
38203836
QStringList mFormats, mLabels;
38213837

3822-
38233838
QList<QByteArray> supportedFormats = QImageReader::supportedImageFormats();
38243839

38253840
if ( supportedFormats.contains( "png" ) )
@@ -3855,6 +3870,22 @@ QVector<QgsWmsSupportedFormat> QgsWmsProvider::supportedFormats()
38553870
return formats;
38563871
}
38573872

3873+
QString QgsWmsProvider::nodeAttribute( const QDomElement &e, QString name, QString defValue )
3874+
{
3875+
if ( e.hasAttribute( name ) )
3876+
return e.attribute( name );
3877+
3878+
QDomNamedNodeMap map( e.attributes() );
3879+
for ( int i = 0; i < map.size(); i++ )
3880+
{
3881+
QDomAttr attr( map.item( i ).toElement().toAttr() );
3882+
if ( attr.name().compare( name, Qt::CaseInsensitive ) == 0 )
3883+
return attr.value();
3884+
}
3885+
3886+
return defValue;
3887+
}
3888+
38583889
void QgsWmsProvider::showMessageBox( const QString& title, const QString& text )
38593890
{
38603891
QgsMessageOutput *message = QgsMessageOutput::createMessageOutput();
@@ -3892,4 +3923,3 @@ QGISEXTERN bool isProvider()
38923923
{
38933924
return true;
38943925
}
3895-

‎src/providers/wms/qgswmsprovider.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,8 @@ struct QgsWmtsTileLayer
392392
QString title, abstract;
393393
QStringList keywords;
394394
QgsWmsBoundingBoxProperty boundingBox;
395-
QString format;
396-
QString infoFormat;
395+
QStringList formats;
396+
QStringList infoFormats;
397397
QString defaultStyle;
398398
QHash<QString, QgsWmtsDimension> dimensions;
399399
QHash<QString, QgsWmtsStyle> styles;
@@ -772,6 +772,9 @@ class QgsWmsProvider : public QgsRasterDataProvider
772772
private:
773773
void showMessageBox( const QString& title, const QString& text );
774774

775+
// case insensitive attribute value lookup
776+
static QString nodeAttribute( const QDomElement &e, QString name, QString defValue = QString::null );
777+
775778
/**
776779
* \brief Retrieve and parse the (cached) Capabilities document from the server
777780
*

‎src/providers/wms/qgswmssourceselect.cpp

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -362,30 +362,34 @@ bool QgsWMSSourceSelect::populateLayerList( QgsWmsProvider *wmsProvider )
362362
{
363363
foreach( const QgsWmtsTileMatrixSetLink &setLink, l.setLinks )
364364
{
365-
QTableWidgetItem *item = new QTableWidgetItem( l.identifier );
366-
item->setData( Qt::UserRole + 0, l.identifier );
367-
item->setData( Qt::UserRole + 1, l.format );
368-
item->setData( Qt::UserRole + 2, style.identifier );
369-
item->setData( Qt::UserRole + 3, setLink.tileMatrixSet );
370-
item->setData( Qt::UserRole + 4, tileMatrixSets[ setLink.tileMatrixSet ].crs );
371-
372-
lstTilesets->setItem( row, 0, item );
373-
lstTilesets->setItem( row, 1, new QTableWidgetItem( l.format ) );
374-
lstTilesets->setItem( row, 2, new QTableWidgetItem( style.identifier ) );
375-
QTableWidgetItem *styleItem = new QTableWidgetItem( l.title );
376-
if ( !l.abstract.isEmpty() )
377-
styleItem->setToolTip( "<p>" + l.abstract + "</p>" );
378-
lstTilesets->setItem( row, 3, styleItem );
379-
lstTilesets->setItem( row, 4, new QTableWidgetItem( setLink.tileMatrixSet ) );
380-
lstTilesets->setItem( row, 5, new QTableWidgetItem( tileMatrixSets[ setLink.tileMatrixSet ].crs ) );
381-
382-
if ( !mMimeMap.contains( l.format ) )
365+
foreach( QString format, l.formats )
383366
{
384-
for ( int i = 0; i < lstTilesets->columnCount(); i++ )
367+
QTableWidgetItem *item = new QTableWidgetItem( l.identifier );
368+
item->setData( Qt::UserRole + 0, l.identifier );
369+
370+
item->setData( Qt::UserRole + 1, format );
371+
item->setData( Qt::UserRole + 2, style.identifier );
372+
item->setData( Qt::UserRole + 3, setLink.tileMatrixSet );
373+
item->setData( Qt::UserRole + 4, tileMatrixSets[ setLink.tileMatrixSet ].crs );
374+
375+
lstTilesets->setItem( row, 0, item );
376+
lstTilesets->setItem( row, 1, new QTableWidgetItem( format ) );
377+
lstTilesets->setItem( row, 2, new QTableWidgetItem( style.identifier ) );
378+
QTableWidgetItem *styleItem = new QTableWidgetItem( l.title );
379+
if ( !l.abstract.isEmpty() )
380+
styleItem->setToolTip( "<p>" + l.abstract + "</p>" );
381+
lstTilesets->setItem( row, 3, styleItem );
382+
lstTilesets->setItem( row, 4, new QTableWidgetItem( setLink.tileMatrixSet ) );
383+
lstTilesets->setItem( row, 5, new QTableWidgetItem( tileMatrixSets[ setLink.tileMatrixSet ].crs ) );
384+
385+
if ( !mMimeMap.contains( format ) )
385386
{
386-
QTableWidgetItem *item = lstTilesets->item( row, i );
387-
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
388-
item->setToolTip( tr( "encoding %1 not supported." ).arg( l.format ) );
387+
for ( int i = 0; i < lstTilesets->columnCount(); i++ )
388+
{
389+
QTableWidgetItem *item = lstTilesets->item( row, i );
390+
item->setFlags( item->flags() & ~Qt::ItemIsEnabled );
391+
item->setToolTip( tr( "encoding %1 not supported." ).arg( format ) );
392+
}
389393
}
390394
}
391395

0 commit comments

Comments
 (0)
Please sign in to comment.