|
| 1 | +/*************************************************************************** |
| 2 | + qgsconfigparserutils.cpp |
| 3 | + ------------------------ |
| 4 | + begin : March 28, 2014 |
| 5 | + copyright : (C) 2014 by Marco Hugentobler |
| 6 | + email : marco dot hugentobler at sourcepole dot ch |
| 7 | + ***************************************************************************/ |
| 8 | + |
| 9 | +/*************************************************************************** |
| 10 | + * * |
| 11 | + * This program is free software; you can redistribute it and/or modify * |
| 12 | + * it under the terms of the GNU General Public License as published by * |
| 13 | + * the Free Software Foundation; either version 2 of the License, or * |
| 14 | + * (at your option) any later version. * |
| 15 | + * * |
| 16 | + ***************************************************************************/ |
| 17 | + |
| 18 | +#include "qgsconfigparserutils.h" |
| 19 | +#include "qgsapplication.h" |
| 20 | +#include "qgscoordinatereferencesystem.h" |
| 21 | +#include "qgscoordinatetransform.h" |
| 22 | +#include "qgscrscache.h" |
| 23 | +#include "qgsmaplayer.h" |
| 24 | +#include "qgsrectangle.h" |
| 25 | + |
| 26 | +#include <QDomDocument> |
| 27 | +#include <QDomElement> |
| 28 | +#include <QString> |
| 29 | + |
| 30 | +#include <sqlite3.h> |
| 31 | + |
| 32 | +class QgsCoordinateReferenceSystem; |
| 33 | +class QgsRectangle; |
| 34 | +class QDomDocument; |
| 35 | +class QDomElement; |
| 36 | +class QString; |
| 37 | +class QStringList; |
| 38 | + |
| 39 | +void QgsConfigParserUtils::appendCRSElementsToLayer( QDomElement& layerElement, QDomDocument& doc, |
| 40 | + const QStringList &crsList, const QStringList& constrainedCrsList ) |
| 41 | +{ |
| 42 | + if ( layerElement.isNull() ) |
| 43 | + { |
| 44 | + return; |
| 45 | + } |
| 46 | + |
| 47 | + //insert the CRS elements after the title element to be in accordance with the WMS 1.3 specification |
| 48 | + QDomElement titleElement = layerElement.firstChildElement( "Title" ); |
| 49 | + QDomElement abstractElement = layerElement.firstChildElement( "Abstract" ); |
| 50 | + QDomElement CRSPrecedingElement = abstractElement.isNull() ? titleElement : abstractElement; //last element before the CRS elements |
| 51 | + |
| 52 | + //In case the number of advertised CRS is constrained |
| 53 | + if ( constrainedCrsList.size() > 0 ) |
| 54 | + { |
| 55 | + for ( int i = constrainedCrsList.size() - 1; i >= 0; --i ) |
| 56 | + { |
| 57 | + appendCRSElementToLayer( layerElement, CRSPrecedingElement, constrainedCrsList.at( i ), doc ); |
| 58 | + } |
| 59 | + } |
| 60 | + else //no crs constraint |
| 61 | + { |
| 62 | + foreach ( QString crs, crsList ) |
| 63 | + { |
| 64 | + appendCRSElementToLayer( layerElement, CRSPrecedingElement, crs, doc ); |
| 65 | + } |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +void QgsConfigParserUtils::appendCRSElementToLayer( QDomElement& layerElement, const QDomElement& precedingElement, |
| 70 | + const QString& crsText, QDomDocument& doc ) |
| 71 | +{ |
| 72 | + QString version = doc.documentElement().attribute( "version" ); |
| 73 | + QDomElement crsElement = doc.createElement( version == "1.1.1" ? "SRS" : "CRS" ); |
| 74 | + QDomText crsTextNode = doc.createTextNode( crsText ); |
| 75 | + crsElement.appendChild( crsTextNode ); |
| 76 | + layerElement.insertAfter( crsElement, precedingElement ); |
| 77 | +} |
| 78 | + |
| 79 | +void QgsConfigParserUtils::appendLayerBoundingBoxes( QDomElement& layerElem, QDomDocument& doc, const QgsRectangle& layerExtent, |
| 80 | + const QgsCoordinateReferenceSystem& layerCRS ) |
| 81 | +{ |
| 82 | + if ( layerElem.isNull() ) |
| 83 | + { |
| 84 | + return; |
| 85 | + } |
| 86 | + |
| 87 | + const QgsCoordinateReferenceSystem& wgs84 = QgsCRSCache::instance()->crsByAuthId( GEO_EPSG_CRS_AUTHID ); |
| 88 | + |
| 89 | + QString version = doc.documentElement().attribute( "version" ); |
| 90 | + |
| 91 | + //Ex_GeographicBoundingBox |
| 92 | + QDomElement ExGeoBBoxElement; |
| 93 | + //transform the layers native CRS into WGS84 |
| 94 | + QgsCoordinateTransform exGeoTransform( layerCRS, wgs84 ); |
| 95 | + QgsRectangle wgs84BoundingRect = exGeoTransform.transformBoundingBox( layerExtent ); |
| 96 | + if ( version == "1.1.1" ) // WMS Version 1.1.1 |
| 97 | + { |
| 98 | + ExGeoBBoxElement = doc.createElement( "LatLonBoundingBox" ); |
| 99 | + ExGeoBBoxElement.setAttribute( "minx", QString::number( wgs84BoundingRect.xMinimum() ) ); |
| 100 | + ExGeoBBoxElement.setAttribute( "maxx", QString::number( wgs84BoundingRect.xMaximum() ) ); |
| 101 | + ExGeoBBoxElement.setAttribute( "miny", QString::number( wgs84BoundingRect.yMinimum() ) ); |
| 102 | + ExGeoBBoxElement.setAttribute( "maxy", QString::number( wgs84BoundingRect.yMaximum() ) ); |
| 103 | + } |
| 104 | + else // WMS Version 1.3.0 |
| 105 | + { |
| 106 | + ExGeoBBoxElement = doc.createElement( "EX_GeographicBoundingBox" ); |
| 107 | + QDomElement wBoundLongitudeElement = doc.createElement( "westBoundLongitude" ); |
| 108 | + QDomText wBoundLongitudeText = doc.createTextNode( QString::number( wgs84BoundingRect.xMinimum() ) ); |
| 109 | + wBoundLongitudeElement.appendChild( wBoundLongitudeText ); |
| 110 | + ExGeoBBoxElement.appendChild( wBoundLongitudeElement ); |
| 111 | + QDomElement eBoundLongitudeElement = doc.createElement( "eastBoundLongitude" ); |
| 112 | + QDomText eBoundLongitudeText = doc.createTextNode( QString::number( wgs84BoundingRect.xMaximum() ) ); |
| 113 | + eBoundLongitudeElement.appendChild( eBoundLongitudeText ); |
| 114 | + ExGeoBBoxElement.appendChild( eBoundLongitudeElement ); |
| 115 | + QDomElement sBoundLatitudeElement = doc.createElement( "southBoundLatitude" ); |
| 116 | + QDomText sBoundLatitudeText = doc.createTextNode( QString::number( wgs84BoundingRect.yMinimum() ) ); |
| 117 | + sBoundLatitudeElement.appendChild( sBoundLatitudeText ); |
| 118 | + ExGeoBBoxElement.appendChild( sBoundLatitudeElement ); |
| 119 | + QDomElement nBoundLatitudeElement = doc.createElement( "northBoundLatitude" ); |
| 120 | + QDomText nBoundLatitudeText = doc.createTextNode( QString::number( wgs84BoundingRect.yMaximum() ) ); |
| 121 | + nBoundLatitudeElement.appendChild( nBoundLatitudeText ); |
| 122 | + ExGeoBBoxElement.appendChild( nBoundLatitudeElement ); |
| 123 | + } |
| 124 | + |
| 125 | + |
| 126 | + //BoundingBox element |
| 127 | + QDomElement bBoxElement = doc.createElement( "BoundingBox" ); |
| 128 | + if ( layerCRS.isValid() ) |
| 129 | + { |
| 130 | + bBoxElement.setAttribute( version == "1.1.1" ? "SRS" : "CRS", layerCRS.authid() ); |
| 131 | + } |
| 132 | + |
| 133 | + QgsRectangle r( layerExtent ); |
| 134 | + if ( version != "1.1.1" && layerCRS.axisInverted() ) |
| 135 | + { |
| 136 | + r.invert(); |
| 137 | + } |
| 138 | + |
| 139 | + bBoxElement.setAttribute( "minx", QString::number( r.xMinimum() ) ); |
| 140 | + bBoxElement.setAttribute( "miny", QString::number( r.yMinimum() ) ); |
| 141 | + bBoxElement.setAttribute( "maxx", QString::number( r.xMaximum() ) ); |
| 142 | + bBoxElement.setAttribute( "maxy", QString::number( r.yMaximum() ) ); |
| 143 | + |
| 144 | + QDomElement lastCRSElem = layerElem.lastChildElement( version == "1.1.1" ? "SRS" : "CRS" ); |
| 145 | + if ( !lastCRSElem.isNull() ) |
| 146 | + { |
| 147 | + layerElem.insertAfter( ExGeoBBoxElement, lastCRSElem ); |
| 148 | + layerElem.insertAfter( bBoxElement, ExGeoBBoxElement ); |
| 149 | + } |
| 150 | + else |
| 151 | + { |
| 152 | + layerElem.appendChild( ExGeoBBoxElement ); |
| 153 | + layerElem.appendChild( bBoxElement ); |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +QStringList QgsConfigParserUtils::createCRSListForLayer( QgsMapLayer* theMapLayer ) |
| 158 | +{ |
| 159 | + QStringList crsNumbers; |
| 160 | + QString myDatabaseFileName = QgsApplication::srsDbFilePath(); |
| 161 | + sqlite3 *myDatabase; |
| 162 | + const char *myTail; |
| 163 | + sqlite3_stmt *myPreparedStatement; |
| 164 | + int myResult; |
| 165 | + |
| 166 | + //check the db is available |
| 167 | + myResult = sqlite3_open( myDatabaseFileName.toLocal8Bit().data(), &myDatabase ); |
| 168 | + if ( myResult && theMapLayer ) |
| 169 | + { |
| 170 | + //if the database cannot be opened, add at least the epsg number of the source coordinate system |
| 171 | + crsNumbers.push_back( theMapLayer->crs().authid() ); |
| 172 | + return crsNumbers; |
| 173 | + }; |
| 174 | + QString mySql = "select upper(auth_name||':'||auth_id) from tbl_srs"; |
| 175 | + myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.length(), &myPreparedStatement, &myTail ); |
| 176 | + if ( myResult == SQLITE_OK ) |
| 177 | + { |
| 178 | + while ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW ) |
| 179 | + { |
| 180 | + crsNumbers.push_back( QString::fromUtf8(( char * )sqlite3_column_text( myPreparedStatement, 0 ) ) ); |
| 181 | + } |
| 182 | + } |
| 183 | + sqlite3_finalize( myPreparedStatement ); |
| 184 | + sqlite3_close( myDatabase ); |
| 185 | + return crsNumbers; |
| 186 | +} |
0 commit comments