336 changes: 105 additions & 231 deletions src/providers/wcs/qgswcscapabilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,6 @@
#include <QDir>
#endif

/*
QgsWcsCapabilities::QgsWcsCapabilities( QString const &theUri )
{
mUri.setEncodedUri( theUri );
QgsDebugMsg( "theUri = " + theUri );
}
*/

QgsWcsCapabilities::QgsWcsCapabilities( QgsDataSourceURI const &theUri ):
mUri( theUri ),
mCoverageCount( 0 )
Expand Down Expand Up @@ -140,7 +131,7 @@ bool QgsWcsCapabilities::supportedCoverages( QVector<QgsWcsCoverageSummary> &cov

QString QgsWcsCapabilities::getCoverageUrl() const
{
QString url = mCapabilities.operationsMetadata.getCoverage.dcp.http.get.xlinkHref;
QString url = mCapabilities.operationsMetadata.getCoverage.getUrl;
if ( url.isEmpty() )
{
url = mUri.param( "url" );
Expand Down Expand Up @@ -404,44 +395,31 @@ bool QgsWcsCapabilities::parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapa
return false;
}

// Start walking through XML.
QDomNode n = docElem.firstChild();
if ( mVersion.startsWith( "1.0" ) )
{
capabilities.title = domElementText( docElem, "Service.name" );
capabilities.abstract = domElementText( docElem, "Service.description" );
// There is also "label" in 1.0

capabilities.operationsMetadata.getCoverage.getUrl = domElement( docElem, "Capability.Request.GetCoverage.DCPType.HTTP.Get.OnlineResource" ).attribute( "xlink:href" );

while ( !n.isNull() )
parseContentMetadata( domElement( docElem, "ContentMetadata" ), capabilities.contents );
}
else if ( mVersion.startsWith( "1.1" ) )
{
QDomElement e = n.toElement();
if ( !e.isNull() )
capabilities.title = domElementText( docElem, "ServiceIdentification.Title" );
capabilities.abstract = domElementText( docElem, "ServiceIdentification.Abstract" );

QList<QDomElement> operationElements = domElements( docElem, "OperationsMetadata.Operation" );
foreach( QDomElement el, operationElements )
{
// Version 1.0
QString tagName = stripNS( e.tagName() );
QgsDebugMsg( tagName );
if ( tagName == "Service" )
{
parseService( e, capabilities.serviceIdentification );
}
else if ( tagName == "Capability" )
{
parseCapability( e, capabilities.operationsMetadata );
}
else if ( tagName == "ContentMetadata" )
if ( el.attribute( "name" ) == "GetCoverage" )
{
parseContentMetadata( e, capabilities.contents );
}
// Version 1.1
else if ( tagName == "ServiceIdentification" )
{
parseServiceIdentification( e, capabilities.serviceIdentification );
}
else if ( tagName == "OperationsMetadata" )
{
parseOperationsMetadata( e, capabilities.operationsMetadata );
}
else if ( tagName == "Contents" )
{
parseCoverageSummary( e, capabilities.contents );
capabilities.operationsMetadata.getCoverage.getUrl = domElement( el, "DCP.HTTP.Get" ).attribute( "xlink:href" );
}
}
n = n.nextSibling();

parseCoverageSummary( domElement( docElem, "Contents" ), capabilities.contents );
}

return true;
Expand All @@ -458,13 +436,11 @@ QDomElement QgsWcsCapabilities::firstChild( const QDomElement &element, const QS
QString tagName = stripNS( el.tagName() );
if ( tagName == name )
{
//QgsDebugMsg( name + " found" );
return el;
}
}
n1 = n1.nextSibling();
}
//QgsDebugMsg( name + " not found" );
return QDomElement();
}

Expand All @@ -473,7 +449,6 @@ QString QgsWcsCapabilities::firstChildText( const QDomElement &element, const QS
QDomElement el = firstChild( element, name );
if ( !el.isNull() )
{
//QgsDebugMsg( name + " : " + el.text() );
return el.text();
}
return QString();
Expand All @@ -497,7 +472,6 @@ QList<QDomElement> QgsWcsCapabilities::domElements( const QDomElement &element,
QString tagName = stripNS( el.tagName() );
if ( tagName == name )
{
//QgsDebugMsg( name + " found" );
if ( names.size() == 0 )
{
list.append( el );
Expand All @@ -514,6 +488,18 @@ QList<QDomElement> QgsWcsCapabilities::domElements( const QDomElement &element,
return list;
}

QStringList QgsWcsCapabilities::domElementsTexts( const QDomElement &element, const QString &path )
{
QStringList list;
QList<QDomElement> elems = domElements( element, path );

foreach( QDomElement el, elems )
{
list << el.text();
}
return list;
}

QDomElement QgsWcsCapabilities::domElement( const QDomElement &element, const QString & path )
{
QStringList names = path.split( "." );
Expand Down Expand Up @@ -568,42 +554,23 @@ QList<double> QgsWcsCapabilities::parseDoubles( const QString &text )
return list;
}

QString QgsWcsCapabilities::crsUrnToAuthId ( const QString &text )
QString QgsWcsCapabilities::crsUrnToAuthId( const QString &text )
{
QString urnCrs = text;

QString authid;

// example: urn:ogc:def:crs:EPSG::4326
QStringList split = urnCrs.remove("urn:ogc:def:crs:").split(":");
if ( split.size() == 3 )
// URN format: urn:ogc:def:objectType:authority:version:code
// URN example: urn:ogc:def:crs:EPSG::4326
QStringList urn = text.split( ":" );
if ( urn.size() == 7 )
{
authid = QString("%1:%2").arg( split.value(0) ).arg(split.value(2) );
authid = urn.value( 4 ) + ":" + urn.value( 6 );
}

return authid;
}

// ------------------------ 1.0 ----------------------------------------------
void QgsWcsCapabilities::parseService( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.0
{
serviceIdentification.title = firstChildText( e, "name" );
serviceIdentification.abstract = firstChildText( e, "description" );
// 1.0 has also "label"
}

void QgsWcsCapabilities::parseCapability( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
{
QDomElement requestElement = firstChild( e, "Request" );
QDomElement getCoverageElement = firstChild( requestElement, "GetCoverage" );
QDomElement dcpTypeElement = firstChild( getCoverageElement, "DCPType" );
QDomElement httpElement = firstChild( dcpTypeElement, "HTTP" );
QDomElement getElement = firstChild( httpElement, "Get" );
QDomElement onlineResourceElement = firstChild( getElement, "OnlineResource" );

operationsMetadata.getCoverage.dcp.http.get.xlinkHref = onlineResourceElement.attribute( "xlink:href" );

QgsDebugMsg( "getCoverage.dcp.http.get.xlinkHref = " + operationsMetadata.getCoverage.dcp.http.get.xlinkHref );
}

void QgsWcsCapabilities::parseContentMetadata( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary )
{
Expand All @@ -619,13 +586,12 @@ void QgsWcsCapabilities::parseContentMetadata( QDomElement const & e, QgsWcsCove
{
QgsWcsCoverageSummary subCoverageSummary;

subCoverageSummary.described = false;
subCoverageSummary.width = 0;
subCoverageSummary.height = 0;
subCoverageSummary.hasSize = false;
initCoverageSummary( subCoverageSummary );

parseCoverageOfferingBrief( el, subCoverageSummary, &coverageSummary );

subCoverageSummary.valid = true;

coverageSummary.coverageSummary.push_back( subCoverageSummary );
}
}
Expand All @@ -643,44 +609,20 @@ void QgsWcsCapabilities::parseCoverageOfferingBrief( QDomElement const & e, QgsW
coverageSummary.title = firstChildText( e, "label" );
coverageSummary.abstract = firstChildText( e, "description" );

QDomElement lonLatEnvelopeElement = firstChild( e, "lonLatEnvelope" );

QDomNodeList posNodes = lonLatEnvelopeElement.elementsByTagName( "gml:pos" );
QList<double> lon, lat;
for ( int i = 0; i < posNodes.size(); i++ )
QList<QDomElement> posElements = domElements( e, "lonLatEnvelope.pos" );
if ( posElements.size() != 2 )
{
QDomNode posNode = posNodes.at( i );
QString lonLatText = posNode.toElement().text();
QStringList lonLat = lonLatText.split( QRegExp( " +" ) );
if ( lonLat.size() != 2 )
{
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
continue;
}
double lo, la;
bool loOk, laOk;
lo = lonLat.value( 0 ).toDouble( &loOk );
la = lonLat.value( 1 ).toDouble( &laOk );
if ( loOk && laOk )
{
lon << lo;
lat << la;
}
else
{
QgsDebugMsg( "Cannot parse lonLatEnvelope: " + lonLatText );
}
QgsDebugMsg( "Wrong number of pos elements" );
}
if ( lon.size() == 2 )
else
{
double w, e, s, n;
w = qMin( lon[0], lon[1] );
e = qMax( lon[0], lon[1] );
n = qMax( lat[0], lat[1] );
s = qMin( lat[0], lat[1] );

coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
QgsDebugMsg( "wgs84BoundingBox = " + coverageSummary.wgs84BoundingBox.toString() );
QList<double> low = parseDoubles( posElements.value( 0 ).text() );
QList<double> high = parseDoubles( posElements.value( 1 ).text() );
if ( low.size() == 2 && high.size() == 2 )
{
coverageSummary.wgs84BoundingBox = QgsRectangle( low[0], low[1], high[0], high[1] ) ;
QgsDebugMsg( "wgs84BoundingBox = " + coverageSummary.wgs84BoundingBox.toString() );
}
}

if ( !coverageSummary.identifier.isEmpty() )
Expand Down Expand Up @@ -751,46 +693,15 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
if ( coverageOfferingElement.isNull() ) return false;
QDomElement supportedCRSsElement = firstChild( coverageOfferingElement, "supportedCRSs" );

QDomNode n1 = supportedCRSsElement.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );

if ( tagName == "requestResponseCRSs" ) // requestCRSs + responseCRSs alternative
{
coverage->supportedCrs << el.text();
}
else if ( tagName == "nativeCRSs" ) // optional
{
coverage->nativeCrs = el.text();
}
// TODO: requestCRSs, responseCRSs - must be then implemented also in provider
}
n1 = n1.nextSibling();
}
// requestResponseCRSs and requestCRSs + responseCRSs are alternatives
coverage->supportedCrs = domElementsTexts( coverageOfferingElement, "supportedCRSs.requestResponseCRSs" );
// TODO: requestCRSs, responseCRSs - must be then implemented also in provider
QgsDebugMsg( "supportedCrs = " + coverage->supportedCrs.join( "," ) );

QDomElement supportedFormatsElement = firstChild( coverageOfferingElement, "supportedFormats" );

n1 = supportedFormatsElement.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );
coverage->nativeCrs = domElementText( coverageOfferingElement, "supportedCRSs.nativeCRSs" );

if ( tagName == "formats" )
{
// may be GTiff, GeoTIFF, TIFF, GIF, ....
coverage->supportedFormat << el.text();
}
}
n1 = n1.nextSibling();
}
// may be GTiff, GeoTIFF, TIFF, GIF, ....
coverage->supportedFormat = domElementsTexts( coverageOfferingElement, "supportedFormats.formats" );
QgsDebugMsg( "supportedFormat = " + coverage->supportedFormat.join( "," ) );

// spatialDomain and Grid/RectifiedGrid are optional according to specificationi.
Expand Down Expand Up @@ -822,7 +733,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
// it should contain gml:Point but mapserver 6.0.3 / WCS 1.0.0 is using gml:pos instead)
// RectifiedGrid also contains 2 gml:offsetVector which could be used to get resolution
// but it should be sufficient to calc resolution from size

// TODO: check if coverage is rotated, in that case probably treat as without size
// or recalc resolution from rotated grid to base CRS
}
Expand All @@ -836,28 +747,28 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom10( QByteArray const &xml, QgsW
QString srsName = el.attribute( "srsName" );

QList<QDomElement> posElements = domElements( el, "pos" );
if ( posElements.size() != 2 )
if ( posElements.size() != 2 )
{
QgsDebugMsg ("Wrong number of pos elements");
QgsDebugMsg( "Wrong number of pos elements" );
continue;
}

QList<double> low = parseDoubles( posElements.value(0).text() );
QList<double> high = parseDoubles( posElements.value(1).text() );
QList<double> low = parseDoubles( posElements.value( 0 ).text() );
QList<double> high = parseDoubles( posElements.value( 1 ).text() );
if ( low.size() == 2 && high.size() == 2 )
{
QgsRectangle box ( low[0], low[1], high[0], high[1] ) ;
QgsRectangle box( low[0], low[1], high[0], high[1] ) ;
coverage->boundingBoxes.insert( srsName, box );
QgsDebugMsg ( "Envelope: " + srsName + " : " + box.toString() );
QgsDebugMsg( "Envelope: " + srsName + " : " + box.toString() );
}
}

// Find native bounding box
if ( !coverage->nativeCrs.isEmpty() )
{
foreach ( QString srsName, coverage->boundingBoxes.keys() )
foreach( QString srsName, coverage->boundingBoxes.keys() )
{
if ( srsName == coverage->nativeCrs )
if ( srsName == coverage->nativeCrs )
{
coverage->nativeBoundingBox = coverage->boundingBoxes.value( srsName );
}
Expand Down Expand Up @@ -903,23 +814,23 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW

foreach( QDomElement el, boundingBoxElements )
{
QString authid = crsUrnToAuthId ( el.attribute( "crs" ) );
QString authid = crsUrnToAuthId( el.attribute( "crs" ) );
QList<double> low = parseDoubles( domElementText( el, "LowerCorner" ) );
QList<double> high = parseDoubles( domElementText( el, "UpperCorner" ) );

if ( low.size() != 2 && high.size() != 2 ) continue;

if ( el.attribute( "crs" ) == "urn:ogc:def:crs:OGC::imageCRS" )
{
coverage->width = (int) ( high[0] - low[0] + 1 );
coverage->height = (int) ( high[1] - low[1] + 1 );
coverage->width = ( int )( high[0] - low[0] + 1 );
coverage->height = ( int )( high[1] - low[1] + 1 );
coverage->hasSize = true;
}
else
{
QgsRectangle box ( low[0], low[1], high[0], high[1] ) ;
QgsRectangle box( low[0], low[1], high[0], high[1] ) ;
coverage->boundingBoxes.insert( authid, box );
QgsDebugMsg ( "BoundingBox: " + authid + " : " + box.toString() );
QgsDebugMsg( "BoundingBox: " + authid + " : " + box.toString() );
}
}
QgsDebugMsg( QString( "width = %1 height = %2" ).arg( coverage->width ).arg( coverage->height ) );
Expand All @@ -929,7 +840,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW

if ( !gridCRSElement.isNull() )
{
QString crsUrn = firstChildText ( gridCRSElement, "GridBaseCRS" );
QString crsUrn = firstChildText( gridCRSElement, "GridBaseCRS" );
coverage->nativeCrs = crsUrnToAuthId( crsUrn );
QgsDebugMsg( "nativeCrs = " + coverage->nativeCrs );

Expand All @@ -941,48 +852,7 @@ bool QgsWcsCapabilities::parseDescribeCoverageDom11( QByteArray const &xml, QgsW

return true;
}
void QgsWcsCapabilities::parseServiceIdentification( const QDomElement &e, QgsWcsServiceIdentification &serviceIdentification ) // 1.1
{
serviceIdentification.title = firstChildText( e, "Title" );
serviceIdentification.abstract = firstChildText( e, "Abstract" );
}

void QgsWcsCapabilities::parseHttp( QDomElement const & e, QgsWcsHTTP& http )
{
http.get.xlinkHref = firstChild( e, "Get" ).attribute( "xlink:href" );
QgsDebugMsg( "http.get.xlinkHref = " + http.get.xlinkHref );
}

void QgsWcsCapabilities::parseDcp( QDomElement const & e, QgsWcsDCP& dcp )
{
QDomElement el = firstChild( e, "HTTP" );
parseHttp( el, dcp.http );
}

void QgsWcsCapabilities::parseOperation( QDomElement const & e, QgsWcsOperation& operation )
{
QDomElement el = firstChild( e, "DCP" );
parseDcp( el, operation.dcp );
}

void QgsWcsCapabilities::parseOperationsMetadata( QDomElement const & e, QgsWcsOperationsMetadata &operationsMetadata )
{
QDomNode n1 = e.firstChild();
while ( !n1.isNull() )
{
QDomElement el = n1.toElement();
if ( !el.isNull() )
{
QString tagName = stripNS( el.tagName() );

if ( tagName == "Operation" && el.attribute( "name" ) == "GetCoverage" )
{
parseOperation( el, operationsMetadata.getCoverage );
}
}
n1 = n1.nextSibling();
}
}

void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCoverageSummary &coverageSummary, QgsWcsCoverageSummary *parent )
{
Expand All @@ -1009,35 +879,22 @@ void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCove
else if ( tagName == "SupportedCRS" )
{
// TODO: SupportedCRS may be URL referencing a document
// URN format: urn:ogc:def:objectType:authority:version:code
// URN example: urn:ogc:def:crs:EPSG::4326
QStringList urn = el.text().split( ":" );
if ( urn.size() == 7 )
{
coverageSummary.supportedCrs << urn.value( 4 ) + ":" + urn.value( 6 );
}
coverageSummary.supportedCrs << crsUrnToAuthId( el.text() );
}
else if ( tagName == "WGS84BoundingBox" )
{
QDomElement wBoundLongitudeElem, eBoundLongitudeElem, sBoundLatitudeElem, nBoundLatitudeElem;

QStringList lower = n1.namedItem( "ows:LowerCorner" ).toElement().text().split( QRegExp( " +" ) );
QStringList upper = n1.namedItem( "ows:UpperCorner" ).toElement().text().split( QRegExp( " +" ) );

double w, e, s, n;
bool wOk, eOk, sOk, nOk;
w = lower.value( 0 ).toDouble( &wOk );
s = lower.value( 1 ).toDouble( &sOk );
e = upper.value( 0 ).toDouble( &eOk );
n = upper.value( 1 ).toDouble( &nOk );
if ( wOk && eOk && sOk && nOk )
QList<double> low = parseDoubles( domElementText( el, "LowerCorner" ) );
QList<double> high = parseDoubles( domElementText( el, "UpperCorner" ) );

if ( low.size() == 2 && high.size() == 2 )
{
coverageSummary.wgs84BoundingBox = QgsRectangle( w, s, e, n );
coverageSummary.wgs84BoundingBox = QgsRectangle( low[0], low[1], high[0], high[1] );
}
}
}
n1 = n1.nextSibling();
}
QgsDebugMsg( "supportedFormat = " + coverageSummary.supportedFormat.join( "," ) );

// We collected params to be inherited, do children
n1 = e.firstChild();
Expand All @@ -1054,16 +911,14 @@ void QgsWcsCapabilities::parseCoverageSummary( QDomElement const & e, QgsWcsCove

QgsWcsCoverageSummary subCoverageSummary;

subCoverageSummary.described = false;
subCoverageSummary.width = 0;
subCoverageSummary.height = 0;
subCoverageSummary.hasSize = false;
initCoverageSummary( subCoverageSummary );

// Inherit
subCoverageSummary.supportedCrs = coverageSummary.supportedCrs;
subCoverageSummary.supportedFormat = coverageSummary.supportedFormat;

parseCoverageSummary( el, subCoverageSummary, &coverageSummary );
subCoverageSummary.valid = true;

coverageSummary.coverageSummary.push_back( subCoverageSummary );
}
Expand Down Expand Up @@ -1097,6 +952,15 @@ void QgsWcsCapabilities::coverageParents( QMap<int, int> &parents, QMap<int, QSt
parentNames = mCoverageParentIdentifiers;
}

void QgsWcsCapabilities::initCoverageSummary( QgsWcsCoverageSummary &coverageSummary )
{
coverageSummary.valid = false;
coverageSummary.described = false;
coverageSummary.width = 0;
coverageSummary.height = 0;
coverageSummary.hasSize = false;
}

QString QgsWcsCapabilities::lastErrorTitle()
{
return mErrorTitle;
Expand Down Expand Up @@ -1131,18 +995,28 @@ void QgsWcsCapabilities::showMessageBox( const QString& title, const QString& te
message->showMessage();
}

QgsWcsCoverageSummary QgsWcsCapabilities::coverage( QString const & theIdentifier )
{
QgsWcsCoverageSummary * cp = coverageSummary( theIdentifier );
QgsDebugMsg( "supportedFormat = " + ( *cp ).supportedFormat.join( "," ) );
if ( cp ) return *cp;

QgsWcsCoverageSummary c;
initCoverageSummary( c );
QgsDebugMsg( "supportedFormat = " + c.supportedFormat.join( "," ) );
return c;
}

QgsWcsCoverageSummary* QgsWcsCapabilities::coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent )
{
//QgsDebugMsg( "theIdentifier = " + theIdentifier );
QgsDebugMsgLevel( "theIdentifier = " + theIdentifier, 5 );
if ( !parent )
{
parent = &( mCapabilities.contents );
}

//foreach( const QgsWcsCoverageSummary &c, parent->coverageSummary )
for ( QVector<QgsWcsCoverageSummary>::iterator c = parent->coverageSummary.begin(); c != parent->coverageSummary.end(); ++c )
{
//QgsDebugMsg( "c->identifier = " + c->identifier );
if ( c->identifier == theIdentifier )
{
return c;
Expand Down
143 changes: 44 additions & 99 deletions src/providers/wcs/qgswcscapabilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#ifndef QGSWCSCAPABILITIES_H
#define QGSWCSCAPABILITIES_H

//#include "qgsrasterdataprovider.h"
#include "qgsdatasourceuri.h"
#include "qgsrectangle.h"

Expand All @@ -31,45 +30,15 @@
#include <QVector>
#include <QUrl>

class QgsCoordinateTransform;
//class QgsCoordinateTransform;
class QNetworkAccessManager;
class QNetworkReply;
class QNetworkRequest;

/*
* The following structs reflect the WCS XML schema,
* as illustrated in ... the Web Coverage Service standard, version x.x xxxx-xx-xx.
*/

/** Get Property structure */
struct QgsWcsGet
{
QString xlinkHref;
};

/** HTTP Property structure */
struct QgsWcsHTTP
{
QgsWcsGet get;
};

/** DCP Type Property structure */
struct QgsWcsDCP
{
QgsWcsHTTP http;
};

/** Version parameter */
struct QgsWcsVersion
{
QStringList allowedValues;
};

/** Operation type structure */
struct QgsWcsOperation
{
QgsWcsVersion version;
QgsWcsDCP dcp;
QString getUrl;
};

/** OperationsMetadata */
Expand All @@ -81,8 +50,8 @@ struct QgsWcsOperationsMetadata
/** ServiceerviceIdentification structure */
struct QgsWcsServiceIdentification
{
QString title;
QString abstract;
QString title;
QString abstract;
};

/** CoverageSummary structure */
Expand All @@ -95,44 +64,33 @@ struct QgsWcsCoverageSummary
QStringList supportedCrs;
QStringList supportedFormat;
QgsRectangle wgs84BoundingBox; // almost useless, we need the native
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326
QString nativeCrs;
QMap<QString, QgsRectangle> boundingBoxes;
// Map of bounding boxes, key is CRS name (srsName), e.g. EPSG:4326
QMap<QString, QgsRectangle> boundingBoxes;
QgsRectangle nativeBoundingBox;
QVector<QgsWcsCoverageSummary> coverageSummary;
bool described; // 1.0
// non reflecting directly Capabilities structure:
// non reflecting Capabilities structure:
bool valid;
bool described;
// native size
int width;
int width;
int height;
bool hasSize;
};

/** Contents structure */
/*
struct QgsWcsContents
{
QStringList supportedCrs;
QStringList supportedFormat;
QVector<QgsWcsCoverageSummary> coverageSummary;
};
*/

/** Capability Property structure */
struct QgsWcsCapabilitiesProperty
{
QString version;
QgsWcsServiceIdentification serviceIdentification;
QString title;
QString abstract;
QgsWcsOperationsMetadata operationsMetadata;
// QgsWcsContents contents;
// using QgsWcsCoverageSummary for contents for simplification
QgsWcsCoverageSummary contents;
};

/**
\brief Data provider for OGC WCS layers.
\brief WCS Capabilities.
*/
class QgsWcsCapabilities : public QObject
{
Expand Down Expand Up @@ -172,8 +130,8 @@ class QgsWcsCapabilities : public QObject
*/
void coverageParents( QMap<int, int> &parents, QMap<int, QStringList> &parentNames ) const;

//! Get coverage summare for identifier
QgsWcsCoverageSummary * coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent = 0 );
//! Get coverage summary for identifier
QgsWcsCoverageSummary coverage( QString const & theIdentifier );

/**
* \brief Prepare the URI so that we can later simply append param=value
Expand Down Expand Up @@ -228,6 +186,29 @@ class QgsWcsCapabilities : public QObject
*/
QString lastErrorFormat();

//! Get tag name without namespace
static QString stripNS( const QString &name );

//! Get text of first child of specified name, NS is ignored
static QString firstChildText( const QDomElement &element, const QString &name );

//! Get first child of specified name, NS is ignored
static QDomElement firstChild( const QDomElement &element, const QString &name );

/** Find sub elements by path which is string of dot separated tag names.
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
static QList<QDomElement> domElements( const QDomElement &element, const QString &path );

/** Find first sub element by path which is string of dot separated tag names.
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
static QDomElement domElement( const QDomElement &element, const QString &path );

/** Get text of element specified by path */
static QString domElementText( const QDomElement &element, const QString &path );

/** Get sub elements texts by path */
static QStringList domElementsTexts( const QDomElement &element, const QString &path );

signals:

/** \brief emit a signal to notify of a progress event */
Expand All @@ -241,33 +222,18 @@ class QgsWcsCapabilities : public QObject
void capabilitiesReplyProgress( qint64, qint64 );

private:
void clear();

void showMessageBox( const QString &title, const QString &text );

//! Get tag name without namespace
QString stripNS( const QString &name );

//! Get text of first child of specified name, NS is ignored
QString firstChildText( const QDomElement &element, const QString &name );

//! Get first child of specified name, NS is ignored
QDomElement firstChild( const QDomElement &element, const QString &name );
//! Get coverage summary for identifier
QgsWcsCoverageSummary * coverageSummary( QString const & theIdentifier, QgsWcsCoverageSummary* parent = 0 );

/** Find sub elements by path which is string of dot separated tag names.
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
QList<QDomElement> domElements( const QDomElement &element, const QString &path );
void initCoverageSummary( QgsWcsCoverageSummary &coverageSummary );

/** Find first sub element by path which is string of dot separated tag names.
* NS is ignored. Example path: domainSet.spatialDomain.RectifiedGrid */
QDomElement domElement( const QDomElement &element, const QString &path );
void clear();

/** Get text of element specified by path */
QString domElementText( const QDomElement &element, const QString &path );
void showMessageBox( const QString &title, const QString &text );

QList<int> parseInts( const QString &text );
QList<double> parseDoubles( const QString &text );
QString crsUrnToAuthId ( const QString &text );
QString crsUrnToAuthId( const QString &text );
/**
* \brief Retrieve and parse the (cached) Capabilities document from the server
*
Expand All @@ -289,12 +255,6 @@ class QgsWcsCapabilities : public QObject
bool parseCapabilitiesDom( QByteArray const &xml, QgsWcsCapabilitiesProperty &capabilities );

// ------------- 1.0 --------------------
//! parse the WCS Service XML element
void parseService( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );

//! parse the WCS Capability XML element
void parseCapability( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );

//! parse the WCS Layer XML element
void parseContentMetadata( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary );

Expand All @@ -303,21 +263,6 @@ class QgsWcsCapabilities : public QObject
QgsWcsCoverageSummary *parent = 0 );

// ------------- 1.1 --------------------
//! parse the WCS ServiceIdentificatio XML element
void parseServiceIdentification( QDomElement const &e, QgsWcsServiceIdentification &serviceIdentification );

//! parse the WCS OperationsMetadata XML element
void parseOperationsMetadata( QDomElement const &e, QgsWcsOperationsMetadata &operationsMetadata );

//! parse the WCS GetCoverage
void parseOperation( QDomElement const & e, QgsWcsOperation& operation );

//! parse the WCS HTTP XML element
void parseHttp( QDomElement const &e, QgsWcsHTTP &http );

//! parse the WCS DCPType XML element
void parseDcp( QDomElement const &e, QgsWcsDCP &dcp );

//! parse the WCS Layer XML element
void parseCoverageSummary( QDomElement const &e, QgsWcsCoverageSummary &coverageSummary,
QgsWcsCoverageSummary *parent = 0 );
Expand Down
259 changes: 125 additions & 134 deletions src/providers/wcs/qgswcsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
, mErrors( 0 )
, mUserName( QString::null )
, mPassword( QString::null )
, mCoverageSummary( 0 )
, mCoverageSummary()
, mCachedGdalDataset( 0 )
, mCachedMemFile( 0 )
, mWidth( 0 )
Expand Down Expand Up @@ -113,67 +113,67 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
// 1.0 get additional coverage info
if ( !mCapabilities.describeCoverage( mIdentifier ) )
{
QgsDebugMsg( "Cannot describe coverage" );
QgsMessageLog::logMessage( tr( "Cannot describe coverage" ), tr( "WCS" ) );
return;
}

mCoverageSummary = mCapabilities.coverageSummary( mIdentifier );
if ( !mCoverageSummary )
mCoverageSummary = mCapabilities.coverage( mIdentifier );
if ( !mCoverageSummary.valid )
{
QgsDebugMsg( "coverage not found" );
// Should not happen if describeCoverage() did not fail
QgsMessageLog::logMessage( tr( "Coverage not found" ), tr( "WCS" ) );
return;
}

// It could happen (usually not with current QgsWCSSourceSelect if at least
// one CRS is available) that crs is not set in uri, in that case we
// It could happen (usually not with current QgsWCSSourceSelect if at least
// one CRS is available) that crs is not set in uri, in that case we
// use the native, if available, or the first supported
if ( mCoverageCrs.isEmpty() )
{
if ( !mCoverageSummary->nativeCrs.isEmpty() )
if ( !mCoverageSummary.nativeCrs.isEmpty() )
{
setCoverageCrs( mCoverageSummary->nativeCrs );
setCoverageCrs( mCoverageSummary.nativeCrs );
}
else if ( mCoverageSummary->supportedCrs.size() > 0 )
else if ( mCoverageSummary.supportedCrs.size() > 0 )
{
setCoverageCrs( mCoverageSummary->supportedCrs.value(0) );
setCoverageCrs( mCoverageSummary.supportedCrs.value( 0 ) );
}
}

mWidth = mCoverageSummary->width;
mHeight = mCoverageSummary->height;
mHasSize = mCoverageSummary->hasSize;
mWidth = mCoverageSummary.width;
mHeight = mCoverageSummary.height;
mHasSize = mCoverageSummary.hasSize;

QgsDebugMsg( QString( "mWidth = %1 mHeight = %2" ).arg( mWidth ).arg( mHeight ) ) ;

if ( !calculateExtent() )
{
QgsDebugMsg( "Cannot calculate extent" );
QgsMessageLog::logMessage( tr( "Cannot calculate extent" ), tr( "WCS" ) );
return;
}

mCachedMemFilename = QString( "/vsimem/qgis/wcs/%0.dat" ).arg(( qlonglong )this );

// Get small piece of coverage to find GDAL data type and nubmer of bands
// Using non native CRS (if we don't know which is native) it could easily happen,
// that a small part of bbox in request CRS near margin falls outside
// Using non native CRS (if we don't know which is native) it could easily happen,
// that a small part of bbox in request CRS near margin falls outside
// coverage native bbox and server reports error => take a piece from center

int bandNo = 0; // All bands
// just a number to get smaller piece of coverage
int width;
int width;
int height;
QString crs;
QgsRectangle box; // box to use to calc extent
QgsRectangle box; // box to use to calc extent
// Prefer native CRS
if ( !mCoverageSummary->nativeCrs.isEmpty() &&
!mCoverageSummary->nativeBoundingBox.isEmpty() &&
mCoverageSummary->supportedCrs.contains ( mCoverageSummary->nativeCrs ) &&
if ( !mCoverageSummary.nativeCrs.isEmpty() &&
!mCoverageSummary.nativeBoundingBox.isEmpty() &&
mCoverageSummary.supportedCrs.contains( mCoverageSummary.nativeCrs ) &&
mHasSize )
{
box = mCoverageSummary->nativeBoundingBox;
box = mCoverageSummary.nativeBoundingBox;
width = mWidth;
height = mHeight;
crs = mCoverageSummary->nativeCrs;
crs = mCoverageSummary.nativeCrs;
}
else
{
Expand All @@ -185,7 +185,8 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )
}
else
{
width = 1000;
// just a number to get smaller piece of coverage
width = 1000;
height = 1000;
}
}
Expand All @@ -195,14 +196,14 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )

int half = 2; // to be requested

// extent to be used for test request
QgsRectangle extent = QgsRectangle ( p.x() - half * xRes, p.y() - half * yRes, p.x() + half * xRes, p.y() + half * yRes );
// extent to be used for test request
QgsRectangle extent = QgsRectangle( p.x() - half * xRes, p.y() - half * yRes, p.x() + half * xRes, p.y() + half * yRes );

getCache( bandNo, extent, 2*half, 2*half, crs );

if ( !mCachedGdalDataset )
{
QgsDebugMsg( "Cannot get test dataset." );
QgsMessageLog::logMessage( tr( "Cannot get test dataset." ), tr( "WCS" ) );
return;
}

Expand Down Expand Up @@ -276,7 +277,7 @@ QgsWcsProvider::QgsWcsProvider( QString const &uri )

// Create and store color table
// TODO: never tested because mapserver (6.0.3) does not support color tables
mColorTables.append ( QgsGdalProviderBase::colorTable( mCachedGdalDataset, i ) );
mColorTables.append( QgsGdalProviderBase::colorTable( mCachedGdalDataset, i ) );
}

clearCache();
Expand Down Expand Up @@ -311,7 +312,7 @@ void QgsWcsProvider::parseUri( QString uriString )
mBaseUrl = prepareUri( mHttpUri );
QgsDebugMsg( "mBaseUrl = " + mBaseUrl );

mIgnoreGetMapUrl = uri.hasParam( "IgnoreGetMapUrl" );
mIgnoreGetCoverageUrl = uri.hasParam( "IgnoreGetMapUrl" );
mIgnoreAxisOrientation = uri.hasParam( "IgnoreAxisOrientation" ); // must be before parsing!
mInvertAxisOrientation = uri.hasParam( "InvertAxisOrientation" ); // must be before parsing!

Expand Down Expand Up @@ -409,13 +410,14 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
{
QgsDebugMsg( "Entered" );

// TODO: set block to null values, move that to function and call only if fails
memset( block, 0, pixelWidth * pixelHeight * typeSize( dataType( bandNo ) ) / 8 );

// Requested extent must at least partialy overlap coverage extent, otherwise
// server gives error. QGIS usually does not request blocks outside raster extent
// (higher level checks) but it is better to do check here as well
if ( !viewExtent.intersects( mCoverageExtent ) )
{
// TODO: set block to null values
memset( block, 0, pixelWidth * pixelHeight * typeSize( dataType( bandNo ) ) / 8 );
return;
}

Expand Down Expand Up @@ -463,7 +465,7 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
// delete cached data
clearCache();

if ( crs.isEmpty() )
if ( crs.isEmpty() )
{
crs = mCoverageCrs;
}
Expand Down Expand Up @@ -508,7 +510,7 @@ void QgsWcsProvider::getCache( int bandNo, QgsRectangle const & viewExtent, int
.arg( extent.xMaximum(), 0, 'f', 16 )
.arg( extent.yMaximum(), 0, 'f', 16 );

QUrl url( mIgnoreGetMapUrl ? mBaseUrl : mCapabilities.getCoverageUrl() );
QUrl url( mIgnoreGetCoverageUrl ? mBaseUrl : mCapabilities.getCoverageUrl() );

// Version 1.0.0, 1.1.0, 1.1.2
setQueryItem( url, "SERVICE", "WCS" );
Expand Down Expand Up @@ -654,9 +656,9 @@ void QgsWcsProvider::cacheReplyFinished()
if ( contentType.startsWith( "text/", Qt::CaseInsensitive ) ||
contentType.toLower() == "application/vnd.ogc.se_xml" )
{
// TODO: test also if it is really exception (from content)
QByteArray text = mCacheReply->readAll();
if ( contentType.toLower() == "text/xml" && parseServiceExceptionReportDom( text ) )
if (( contentType.toLower() == "text/xml" || contentType.toLower() == "application/vnd.ogc.se_xml" )
&& parseServiceExceptionReportDom( text ) )
{
QgsMessageLog::logMessage( tr( "Map request error (Title:%1; Error:%2; URL: %3)" )
.arg( mErrorCaption ).arg( mError )
Expand Down Expand Up @@ -941,33 +943,22 @@ bool QgsWcsProvider::parseServiceExceptionReportDom( QByteArray const & xml )

QDomElement docElem = mServiceExceptionReportDom.documentElement();

// TODO: Assert the docElem.tagName() is "ServiceExceptionReport"
// TODO: Assert the docElem.tagName() is
// ServiceExceptionReport // 1.0
// ows:ExceptionReport // 1.1

// serviceExceptionProperty.version = docElem.attribute("version");
//QString version = docElem.attribute("version");

// Start walking through XML.
QDomNode n = docElem.firstChild();

while ( !n.isNull() )
QDomElement e;
if ( mCapabilities.version().startsWith( "1.0" ) )
{
QDomElement e = n.toElement(); // try to convert the node to an element.
if ( !e.isNull() )
{
//QgsDebugMsg(e.tagName() ); // the node really is an element.

QString tagName = e.tagName();
if ( tagName.startsWith( "wcs:" ) )
tagName = tagName.mid( 4 );

if ( tagName == "ServiceException" )
{
QgsDebugMsg( " ServiceException." );
parseServiceException( e );
}

}
n = n.nextSibling();
e = QgsWcsCapabilities::domElement( docElem, "ServiceException" );
}
else // 1.1
{
e = QgsWcsCapabilities::domElement( docElem, "Exception" );
}
parseServiceException( e );

QgsDebugMsg( "exiting." );

Expand All @@ -978,67 +969,58 @@ void QgsWcsProvider::parseServiceException( QDomElement const & e )
{
QgsDebugMsg( "entering." );

QString seCode = e.attribute( "code" );
QString seText = e.text();

mErrorFormat = "text/plain";
QMap<QString, QString> exceptions;

// Some codes are in both 1.0 and 1.1, in that case the 'meaning of code' is
// taken from 1.0 specification

// set up friendly descriptions for the service exception
if ( seCode == "InvalidFormat" )
{
mError = tr( "Request contains a format not offered by the server." );
}
else if ( seCode == "InvalidCRS" )
{
mError = tr( "Request contains a CRS not offered by the server for one or more of the Layers in the request." );
}
else if ( seCode == "InvalidSRS" ) // legacy WCS < 1.3.0
{
mError = tr( "Request contains a SRS not offered by the server for one or more of the Layers in the request." );
}
else if ( seCode == "LayerNotDefined" )
{
mError = tr( "GetMap request is for a Layer not offered by the server, "
"or GetFeatureInfo request is for a Layer not shown on the map." );
}
else if ( seCode == "StyleNotDefined" )
{
mError = tr( "Request is for a Layer in a Style not offered by the server." );
}
else if ( seCode == "LayerNotQueryable" )
{
mError = tr( "GetFeatureInfo request is applied to a Layer which is not declared queryable." );
}
else if ( seCode == "InvalidPoint" )
{
mError = tr( "GetFeatureInfo request contains invalid X or Y value." );
}
else if ( seCode == "CurrentUpdateSequence" )
{
mError = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to "
"current value of service metadata update sequence number." );
}
else if ( seCode == "InvalidUpdateSequence" )
{
mError = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is greater "
"than current value of service metadata update sequence number." );
}
else if ( seCode == "MissingDimensionValue" )
// 1.0
exceptions["InvalidFormat"] = tr( "Request contains a format not offered by the server." );
exceptions["CoverageNotDefined"] = tr( "Request is for a Coverage not offered by the service instance." );
exceptions["CurrentUpdateSequence"] = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is equal to current value of service metadata update sequence number." );
exceptions["InvalidUpdateSequence"] = tr( "Value of (optional) UpdateSequence parameter in GetCapabilities request is greater than current value of service metadata update sequence number." );
// 1.0, 1.1
exceptions["MissingParameterValue"] = tr( "Request does not include a parameter value, and the servervice instance did not declare a default value for that dimension." );
exceptions["InvalidParameterValue"] = tr( "Request contains an invalid parameter value." );
// 1.1
exceptions["NoApplicableCode"] = tr( "No other exceptionCode specified by this service and server applies to this exception." );
exceptions["UnsupportedCombination"] = tr( "Operation request contains an output CRS that can not be used within the output format." );
exceptions["NotEnoughStorage"] = tr( "Operation request specifies \"store\" the result, but not enough storage is available to do this." );

QString seCode;
QString seText;
if ( mCapabilities.version().startsWith( "1.0" ) )
{
mError = tr( "Request does not include a sample dimension value, and the server did not declare a "
"default value for that dimension." );
seCode = e.attribute( "code" );
seText = e.text();
}
else if ( seCode == "InvalidDimensionValue" )
else
{
mError = tr( "Request contains an invalid sample dimension value." );
QStringList codes;
seCode = e.attribute( "exceptionCode" );
// UMN Mapserver (6.0.3) has messed/switched 'locator' and 'exceptionCode'
if ( ! exceptions.contains( seCode ) )
{
seCode = e.attribute( "locator" );
if ( ! exceptions.contains( seCode ) )
{
seCode = "";
}
}
seText = QgsWcsCapabilities::firstChildText( e, "ExceptionText" );
}
else if ( seCode == "OperationNotSupported" )

mErrorFormat = "text/plain";

if ( seCode.isEmpty() )
{
mError = tr( "Request is for an optional operation that is not supported by the server." );
mError = tr( "(No error code was reported)" );
}
else if ( seCode.isEmpty() )
else if ( exceptions.contains( seCode ) )
{
mError = tr( "(No error code was reported)" );
mError = exceptions.value( seCode );
}
else
{
Expand All @@ -1048,8 +1030,6 @@ void QgsWcsProvider::parseServiceException( QDomElement const & e )
mError += "\n" + tr( "The WCS vendor also reported: " );
mError += seText;

// TODO = e.attribute("locator");

QgsMessageLog::logMessage( tr( "composed error message '%1'." ).arg( mError ), tr( "WCS" ) );
QgsDebugMsg( "exiting." );
}
Expand Down Expand Up @@ -1077,20 +1057,28 @@ bool QgsWcsProvider::isValid()

QString QgsWcsProvider::wcsVersion()
{
// TODO
return NULL;
return mCapabilities.version();
}

bool QgsWcsProvider::calculateExtent()
{
QgsDebugMsg( "entered." );

// Make sure we know what extents are available
if ( !mCoverageSummary )
if ( !mCoverageSummary.described )
{
return false;
}

// Prefer to use extent from capabilities / coverage description because
// transformation from WGS84 increases the extent
mCoverageExtent = mCoverageSummary.boundingBoxes.value( mCoverageCrs );
if ( !mCoverageExtent.isEmpty() && !mCoverageExtent.isFinite() )
{
QgsDebugMsg( "mCoverageExtent = " + mCoverageExtent.toString() );
return true;
}

// Set up the coordinate transform from the WCS standard CRS:84 bounding
// box to the user's selected CRS
if ( !mCoordinateTransform )
Expand All @@ -1107,11 +1095,11 @@ bool QgsWcsProvider::calculateExtent()
mCoordinateTransform = new QgsCoordinateTransform( qgisSrsSource, qgisSrsDest );
}

QgsDebugMsg( "mCoverageSummary->wgs84BoundingBox= " + mCoverageSummary->wgs84BoundingBox.toString() );
QgsDebugMsg( "mCoverageSummary.wgs84BoundingBox= " + mCoverageSummary.wgs84BoundingBox.toString() );
// Convert to the user's CRS as required
try
{
mCoverageExtent = mCoordinateTransform->transformBoundingBox( mCoverageSummary->wgs84BoundingBox, QgsCoordinateTransform::ForwardTransform );
mCoverageExtent = mCoordinateTransform->transformBoundingBox( mCoverageSummary.wgs84BoundingBox, QgsCoordinateTransform::ForwardTransform );
}
catch ( QgsCsException &cse )
{
Expand Down Expand Up @@ -1160,18 +1148,21 @@ QString QgsWcsProvider::coverageMetadata( QgsWcsCoverageSummary coverage )
metadata += tr( "Value" );
metadata += "</th></tr>";

metadata += htmlRow ( tr( "Name (identifier)" ), coverage.identifier );
metadata += htmlRow ( tr( "Title" ), coverage.title );
metadata += htmlRow ( tr( "Abstract" ), coverage.abstract );
metadata += htmlRow( tr( "Name (identifier)" ), coverage.identifier );
metadata += htmlRow( tr( "Title" ), coverage.title );
metadata += htmlRow( tr( "Abstract" ), coverage.abstract );
// We dont have size, nativeCrs, nativeBoundingBox etc. until describe coverage which would be heavy for all coverages
//metadata += htmlRow ( tr( "Fixed Width" ), QString::number( coverage.width ) );
//metadata += htmlRow ( tr( "Fixed Height" ), QString::number( coverage.height ) );
//metadata += htmlRow ( tr( "Native CRS" ), coverage.nativeCrs );
//metadata += htmlRow ( tr( "Native Bounding Box" ), coverage.nativeBoundingBox.toString() );

metadata += htmlRow ( tr( "WGS 84 Bounding Box" ), coverage.wgs84BoundingBox.toString() );
metadata += htmlRow( tr( "WGS 84 Bounding Box" ), coverage.wgs84BoundingBox.toString() );

// Layer Coordinate Reference Systems
// TODO(?): supportedCrs and supportedFormat are not available in 1.0
// until coverage is described - it would be confusing to show it only if available
/*
for ( int j = 0; j < qMin( coverage.supportedCrs.size(), 10 ); j++ )
{
metadata += htmlRow ( tr( "Available in CRS" ), coverage.supportedCrs.value(j) );
Expand All @@ -1191,6 +1182,7 @@ QString QgsWcsProvider::coverageMetadata( QgsWcsCoverageSummary coverage )
{
metadata += htmlRow ( tr( "Available in format" ), tr( "(and %n more)", "crs", coverage.supportedFormat.size() - 10 ) );
}
*/

// Close the nested table
metadata += "</table>";
Expand Down Expand Up @@ -1235,22 +1227,21 @@ QString QgsWcsProvider::metadata()
metadata += tr( "Value" );
metadata += "</th></tr>";

metadata += htmlRow ( ( "Coverage" ), mIdentifier );
metadata += htmlRow ( ( "WCS Version" ), mCapabilities.version() );
metadata += htmlRow ( tr( "Title" ), mCapabilities.capabilities().serviceIdentification.title );
metadata += htmlRow ( tr( "Abstract" ), mCapabilities.capabilities().serviceIdentification.abstract );
// TODO
metadata += htmlRow(( "WCS Version" ), mCapabilities.version() );
metadata += htmlRow( tr( "Title" ), mCapabilities.capabilities().title );
metadata += htmlRow( tr( "Abstract" ), mCapabilities.capabilities().abstract );
// TODO
//metadata += htmlRow ( tr( "Keywords" ), mCapabilities.service.keywordList.join( "<br />" ) );
//metadata += htmlRow ( tr( "Online Resource" ), "-" );
//metadata += htmlRow ( tr( "Contact Person" ),
//metadata += htmlRow ( tr( "Contact Person" ),
// mCapabilities.service.contactInformation.contactPersonPrimary.contactPerson
// + "<br />" + mCapabilities.service.contactInformation.contactPosition;
// + "<br />" + mCapabilities.service.contactInformation.contactPersonPrimary.contactOrganization );
//metadata += htmlRow ( tr( "Fees" ), mCapabilities.service.fees );
//metadata += htmlRow ( tr( "Access Constraints" ), mCapabilities.service.accessConstraints );
//metadata += htmlRow ( tr( "Image Formats" ), mCapabilities.capability.request.getMap.format.join( "<br />" ) );
//metadata += htmlRow ( tr( "GetCapabilitiesUrl" ), mBaseUrl );
//metadata += htmlRow ( tr( "GetMapUrl" ), getMapUrl() + ( mIgnoreGetMapUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" ) );
metadata += htmlRow( tr( "Get Coverage Url" ), mCapabilities.capabilities().operationsMetadata.getCoverage.getUrl + ( mIgnoreGetCoverageUrl ? tr( "&nbsp;<font color=\"red\">(advertised but ignored)</font>" ) : "" ) );

// Close the nested table
metadata += "</table>";
Expand All @@ -1263,7 +1254,7 @@ QString QgsWcsProvider::metadata()

for ( int i = 0; i < mCapabilities.capabilities().contents.coverageSummary.size(); i++ )
{
QgsWcsCoverageSummary c = mCapabilities.capabilities().contents.coverageSummary.value(i);
QgsWcsCoverageSummary c = mCapabilities.capabilities().contents.coverageSummary.value( i );
metadata += coverageMetadata( c );
}

Expand All @@ -1274,14 +1265,14 @@ QString QgsWcsProvider::metadata()
return metadata;
}

QString QgsWcsProvider::htmlCell ( const QString &text )
QString QgsWcsProvider::htmlCell( const QString &text )
{
return "<td>" + text + "</td>";
}

QString QgsWcsProvider:: htmlRow ( const QString &text1, const QString &text2 )
QString QgsWcsProvider:: htmlRow( const QString &text1, const QString &text2 )
{
return "<tr>" + htmlCell ( text1 ) + htmlCell ( text2 ) + "</tr>";
return "<tr>" + htmlCell( text1 ) + htmlCell( text2 ) + "</tr>";
}

bool QgsWcsProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>& theResults )
Expand Down
9 changes: 4 additions & 5 deletions src/providers/wcs/qgswcsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,10 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
void clearCache();

//! Create html cell (used by metadata)
QString htmlCell ( const QString &text );
QString htmlCell( const QString &text );

//! Create html row with 2 cells (used by metadata)
QString htmlRow ( const QString &text1, const QString &text2 );
QString htmlRow( const QString &text1, const QString &text2 );

//! Data source URI of the WCS for this layer
QString mHttpUri;
Expand All @@ -264,7 +264,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase
QgsWcsCapabilities mCapabilities;

/** Coverage summary */
QgsWcsCoverageSummary * mCoverageSummary;
QgsWcsCoverageSummary mCoverageSummary;

/** Spatial reference id of the layer */
QString mSrid;
Expand Down Expand Up @@ -400,8 +400,7 @@ class QgsWcsProvider : public QgsRasterDataProvider, QgsGdalProviderBase

//! whether to use hrefs from GetCapabilities (default) or
// the given base urls for GetMap and GetFeatureInfo
bool mIgnoreGetMapUrl;
bool mIgnoreGetFeatureInfoUrl;
bool mIgnoreGetCoverageUrl;
bool mIgnoreAxisOrientation;
bool mInvertAxisOrientation;

Expand Down
16 changes: 8 additions & 8 deletions src/providers/wcs/qgswcssourceselect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void QgsWCSSourceSelect::addClicked( )
// without that param user is asked for CRS
//if ( selectedLayersCRSs().size() > 1 )
//{
uri.setParam( "crs", selectedCRS() );
uri.setParam( "crs", selectedCRS() );
//}

QgsDebugMsg( "selectedFormat = " + selectedFormat() );
Expand Down Expand Up @@ -219,11 +219,11 @@ QStringList QgsWCSSourceSelect::selectedLayersFormats()
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return QStringList(); }

QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
if ( !c ) { return QStringList(); }
QgsWcsCoverageSummary c = mCapabilities.coverage( identifier );
if ( !c.valid ) { return QStringList(); }

QgsDebugMsg( "supportedFormat = " + c->supportedFormat.join( "," ) );
return c->supportedFormat;
QgsDebugMsg( "supportedFormat = " + c.supportedFormat.join( "," ) );
return c.supportedFormat;
}

QStringList QgsWCSSourceSelect::selectedLayersCRSs()
Expand All @@ -233,10 +233,10 @@ QStringList QgsWCSSourceSelect::selectedLayersCRSs()
QString identifier = selectedIdentifier();
if ( identifier.isEmpty() ) { return QStringList(); }

QgsWcsCoverageSummary * c = mCapabilities.coverageSummary( identifier );
if ( !c ) { return QStringList(); }
QgsWcsCoverageSummary c = mCapabilities.coverage( identifier );
if ( !c.valid ) { return QStringList(); }

return c->supportedCrs;
return c.supportedCrs;
}

void QgsWCSSourceSelect::enableLayersForCrs( QTreeWidgetItem * )
Expand Down