mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-27 00:03:38 -04:00
1611 lines
49 KiB
C++
1611 lines
49 KiB
C++
/***************************************************************************
|
|
qgsserverprojectparser.cpp
|
|
--------------------------
|
|
begin : March 25, 2014
|
|
copyright : (C) 2014 by Marco Hugentobler
|
|
email : marco dot hugentobler at sourcepole dot ch
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsserverprojectparser.h"
|
|
#include "qgsapplication.h"
|
|
#include "qgsproject.h"
|
|
#include "qgsconfigcache.h"
|
|
#include "qgsconfigparserutils.h"
|
|
#include "qgsdatasourceuri.h"
|
|
#include "qgsmaplayerregistry.h"
|
|
#include "qgsmslayercache.h"
|
|
#include "qgsrasterlayer.h"
|
|
#include "qgseditorwidgetregistry.h"
|
|
#include "qgslayertreegroup.h"
|
|
|
|
#include <QDomDocument>
|
|
#include <QFileInfo>
|
|
#include <QStringList>
|
|
#include <QTextStream>
|
|
#include <QUrl>
|
|
|
|
QgsServerProjectParser::QgsServerProjectParser( QDomDocument* xmlDoc, const QString& filePath )
|
|
: mXMLDoc( xmlDoc )
|
|
, mProjectPath( filePath )
|
|
, mUseLayerIDs( false )
|
|
{
|
|
//accelerate the search for layers, groups and the creation of annotation items
|
|
if ( mXMLDoc )
|
|
{
|
|
QDomNodeList layerNodeList = mXMLDoc->elementsByTagName( "maplayer" );
|
|
QDomElement currentElement;
|
|
int nNodes = layerNodeList.size();
|
|
for ( int i = 0; i < nNodes; ++i )
|
|
{
|
|
currentElement = layerNodeList.at( i ).toElement();
|
|
mProjectLayerElements.push_back( currentElement );
|
|
QString lName = layerShortName( currentElement );
|
|
if ( lName.isEmpty() )
|
|
lName = layerName( currentElement );
|
|
mProjectLayerElementsByName.insert( lName, currentElement );
|
|
mProjectLayerElementsById.insert( layerId( currentElement ), currentElement );
|
|
}
|
|
|
|
mLegendGroupElements = findLegendGroupElements();
|
|
|
|
mUseLayerIDs = findUseLayerIds();
|
|
mRestrictedLayers = findRestrictedLayers();
|
|
|
|
mCustomLayerOrder.clear();
|
|
|
|
QDomElement customOrder = mXMLDoc->documentElement().firstChildElement( "layer-tree-canvas" ).firstChildElement( "custom-order" );
|
|
if ( customOrder.attribute( "enabled" ) == "1" )
|
|
{
|
|
QDomNodeList items = customOrder.childNodes();
|
|
for ( int i = 0; i < items.size(); ++i )
|
|
{
|
|
mCustomLayerOrder << items.item( i ).toElement().text();
|
|
}
|
|
}
|
|
}
|
|
// Setting the QgsProject instance fileName
|
|
// to help converting relative pathes to absolute
|
|
if ( !mProjectPath.isEmpty() )
|
|
{
|
|
QgsProject::instance()->setFileName( mProjectPath );
|
|
}
|
|
}
|
|
|
|
QgsServerProjectParser::QgsServerProjectParser()
|
|
: mXMLDoc( nullptr )
|
|
, mUseLayerIDs( false )
|
|
{
|
|
}
|
|
|
|
QgsServerProjectParser::~QgsServerProjectParser()
|
|
{
|
|
|
|
}
|
|
|
|
void QgsServerProjectParser::projectLayerMap( QMap<QString, QgsMapLayer*>& layerMap ) const
|
|
{
|
|
layerMap.clear();
|
|
|
|
QList<QDomElement>::const_iterator layerElemIt = mProjectLayerElements.constBegin();
|
|
for ( ; layerElemIt != mProjectLayerElements.constEnd(); ++layerElemIt )
|
|
{
|
|
QgsMapLayer *layer = createLayerFromElement( *layerElemIt );
|
|
if ( layer )
|
|
{
|
|
layerMap.insert( layer->id(), layer );
|
|
}
|
|
}
|
|
}
|
|
|
|
QString QgsServerProjectParser::convertToAbsolutePath( const QString& file ) const
|
|
{
|
|
if ( !file.startsWith( "./" ) && !file.startsWith( "../" ) )
|
|
{
|
|
return file;
|
|
}
|
|
|
|
QString srcPath = file;
|
|
QString projPath = mProjectPath;
|
|
|
|
#if defined(Q_OS_WIN)
|
|
srcPath.replace( "\\", "/" );
|
|
projPath.replace( "\\", "/" );
|
|
|
|
bool uncPath = projPath.startsWith( "//" );
|
|
#endif
|
|
|
|
QStringList srcElems = srcPath.split( "/", QString::SkipEmptyParts );
|
|
QStringList projElems = projPath.split( "/", QString::SkipEmptyParts );
|
|
|
|
#if defined(Q_OS_WIN)
|
|
if ( uncPath )
|
|
{
|
|
projElems.prepend( "" );
|
|
projElems.prepend( "" );
|
|
}
|
|
#endif
|
|
|
|
// remove project file element
|
|
projElems.removeLast();
|
|
|
|
// append source path elements
|
|
projElems << srcElems;
|
|
projElems.removeAll( "." );
|
|
|
|
// resolve ..
|
|
int pos;
|
|
while (( pos = projElems.indexOf( ".." ) ) > 0 )
|
|
{
|
|
// remove preceding element and ..
|
|
projElems.removeAt( pos - 1 );
|
|
projElems.removeAt( pos - 1 );
|
|
}
|
|
|
|
#if !defined(Q_OS_WIN)
|
|
// make path absolute
|
|
projElems.prepend( "" );
|
|
#endif
|
|
|
|
return projElems.join( "/" );
|
|
}
|
|
|
|
QgsMapLayer* QgsServerProjectParser::createLayerFromElement( const QDomElement& elem, bool useCache ) const
|
|
{
|
|
if ( elem.isNull() || !mXMLDoc )
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
addJoinLayersForElement( elem );
|
|
addGetFeatureLayers( elem );
|
|
|
|
QDomElement dataSourceElem = elem.firstChildElement( "datasource" );
|
|
QString uri = dataSourceElem.text();
|
|
QString absoluteUri;
|
|
// If QgsProject instance fileName is set,
|
|
// Is converting relative pathes to absolute still relevant ?
|
|
if ( !dataSourceElem.isNull() )
|
|
{
|
|
//convert relative pathes to absolute ones if necessary
|
|
if ( uri.startsWith( "dbname" ) ) //database
|
|
{
|
|
QgsDataSourceUri dsUri( uri );
|
|
if ( dsUri.host().isEmpty() ) //only convert path for file based databases
|
|
{
|
|
QString dbnameUri = dsUri.database();
|
|
QString dbNameUriAbsolute = convertToAbsolutePath( dbnameUri );
|
|
if ( dbnameUri != dbNameUriAbsolute )
|
|
{
|
|
dsUri.setDatabase( dbNameUriAbsolute );
|
|
absoluteUri = dsUri.uri();
|
|
QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
|
|
dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
|
|
}
|
|
}
|
|
}
|
|
else if ( uri.startsWith( "file:" ) ) //a file based datasource in url notation (e.g. delimited text layer)
|
|
{
|
|
QString filePath = uri.mid( 5, uri.indexOf( "?" ) - 5 );
|
|
QString absoluteFilePath = convertToAbsolutePath( filePath );
|
|
if ( filePath != absoluteFilePath )
|
|
{
|
|
QUrl destUrl = QUrl::fromEncoded( uri.toAscii() );
|
|
destUrl.setScheme( "file" );
|
|
destUrl.setPath( absoluteFilePath );
|
|
absoluteUri = destUrl.toEncoded();
|
|
QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
|
|
dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
|
|
}
|
|
else
|
|
{
|
|
absoluteUri = uri;
|
|
}
|
|
}
|
|
else //file based data source
|
|
{
|
|
absoluteUri = convertToAbsolutePath( uri );
|
|
if ( uri != absoluteUri )
|
|
{
|
|
QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
|
|
dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
|
|
}
|
|
}
|
|
}
|
|
|
|
QString id = layerId( elem );
|
|
QgsMapLayer* layer = nullptr;
|
|
if ( useCache )
|
|
{
|
|
layer = QgsMSLayerCache::instance()->searchLayer( absoluteUri, id, mProjectPath );
|
|
}
|
|
|
|
if ( layer )
|
|
{
|
|
if ( !QgsMapLayerRegistry::instance()->mapLayer( id ) )
|
|
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
|
|
if ( layer->type() == QgsMapLayer::VectorLayer )
|
|
addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );
|
|
|
|
return layer;
|
|
}
|
|
|
|
QString type = elem.attribute( "type" );
|
|
if ( type == "vector" )
|
|
{
|
|
layer = new QgsVectorLayer();
|
|
}
|
|
else if ( type == "raster" )
|
|
{
|
|
layer = new QgsRasterLayer();
|
|
}
|
|
else if ( elem.attribute( "embedded" ) == "1" ) //layer is embedded from another project file
|
|
{
|
|
QString project = convertToAbsolutePath( elem.attribute( "project" ) );
|
|
QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );
|
|
|
|
QgsServerProjectParser* otherConfig = QgsConfigCache::instance()->serverConfiguration( project );
|
|
if ( !otherConfig )
|
|
{
|
|
return nullptr;
|
|
}
|
|
return otherConfig->mapLayerFromLayerId( elem.attribute( "id" ), useCache );
|
|
}
|
|
|
|
if ( layer )
|
|
{
|
|
if ( layer->type() == QgsMapLayer::VectorLayer )
|
|
{
|
|
// see QgsEditorWidgetRegistry::mapLayerAdded()
|
|
QObject::connect( layer, SIGNAL( readCustomSymbology( const QDomElement&, QString& ) ), QgsEditorWidgetRegistry::instance(), SLOT( readSymbology( const QDomElement&, QString& ) ) );
|
|
}
|
|
|
|
layer->readLayerXml( const_cast<QDomElement&>( elem ) ); //should be changed to const in QgsMapLayer
|
|
//layer->setLayerName( layerName( elem ) );
|
|
|
|
// Insert layer in registry and cache before addValueRelationLayersForLayer
|
|
if ( !QgsMapLayerRegistry::instance()->mapLayer( id ) )
|
|
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
|
|
if ( useCache )
|
|
{
|
|
QgsMSLayerCache::instance()->insertLayer( absoluteUri, id, layer, mProjectPath );
|
|
}
|
|
else
|
|
{
|
|
//todo: fixme
|
|
//mLayersToRemove.push_back( layer );
|
|
}
|
|
|
|
if ( layer->type() == QgsMapLayer::VectorLayer )
|
|
{
|
|
addValueRelationLayersForLayer( dynamic_cast<QgsVectorLayer *>( layer ) );
|
|
}
|
|
}
|
|
return layer;
|
|
}
|
|
|
|
QgsMapLayer* QgsServerProjectParser::mapLayerFromLayerId( const QString& lId, bool useCache ) const
|
|
{
|
|
QHash< QString, QDomElement >::const_iterator layerIt = mProjectLayerElementsById.find( lId );
|
|
if ( layerIt != mProjectLayerElementsById.constEnd() )
|
|
{
|
|
return createLayerFromElement( layerIt.value(), useCache );
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
QString QgsServerProjectParser::layerIdFromLegendLayer( const QDomElement& legendLayer ) const
|
|
{
|
|
if ( legendLayer.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomNodeList legendLayerFileList = legendLayer.elementsByTagName( "legendlayerfile" );
|
|
if ( legendLayerFileList.size() < 1 )
|
|
{
|
|
return QString();
|
|
}
|
|
return legendLayerFileList.at( 0 ).toElement().attribute( "layerid" );
|
|
}
|
|
|
|
QString QgsServerProjectParser::layerId( const QDomElement& layerElem ) const
|
|
{
|
|
if ( layerElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomElement idElem = layerElem.firstChildElement( "id" );
|
|
if ( idElem.isNull() )
|
|
{
|
|
//embedded layer have id attribute instead of id child element
|
|
return layerElem.attribute( "id" );
|
|
}
|
|
return idElem.text();
|
|
}
|
|
|
|
QString QgsServerProjectParser::layerShortName( const QDomElement& layerElem ) const
|
|
{
|
|
if ( layerElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomElement nameElem = layerElem.firstChildElement( "shortname" );
|
|
if ( nameElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
return nameElem.text().replace( ",", "%60" );
|
|
}
|
|
|
|
QgsRectangle QgsServerProjectParser::projectExtent() const
|
|
{
|
|
QgsRectangle extent;
|
|
if ( !mXMLDoc )
|
|
{
|
|
return extent;
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
QDomElement mapCanvasElem = qgisElem.firstChildElement( "mapcanvas" );
|
|
if ( mapCanvasElem.isNull() )
|
|
{
|
|
return extent;
|
|
}
|
|
|
|
QDomElement extentElem = mapCanvasElem.firstChildElement( "extent" );
|
|
bool xminOk, xmaxOk, yminOk, ymaxOk;
|
|
double xMin = extentElem.firstChildElement( "xmin" ).text().toDouble( &xminOk );
|
|
double xMax = extentElem.firstChildElement( "xmax" ).text().toDouble( &xmaxOk );
|
|
double yMin = extentElem.firstChildElement( "ymin" ).text().toDouble( &yminOk );
|
|
double yMax = extentElem.firstChildElement( "ymax" ).text().toDouble( &ymaxOk );
|
|
|
|
if ( xminOk && xmaxOk && yminOk && ymaxOk )
|
|
{
|
|
extent = QgsRectangle( xMin, yMin, xMax, yMax );
|
|
}
|
|
|
|
return extent;
|
|
}
|
|
|
|
int QgsServerProjectParser::numberOfLayers() const
|
|
{
|
|
return mProjectLayerElements.size();
|
|
}
|
|
|
|
bool QgsServerProjectParser::updateLegendDrawingOrder() const
|
|
{
|
|
return !mCustomLayerOrder.isEmpty();
|
|
}
|
|
|
|
void QgsServerProjectParser::serviceCapabilities( QDomElement& parentElement, QDomDocument& doc, const QString& service, bool sia2045 ) const
|
|
{
|
|
QDomElement propertiesElement = propertiesElem();
|
|
if ( propertiesElement.isNull() )
|
|
{
|
|
QgsConfigParserUtils::fallbackServiceCapabilities( parentElement, doc );
|
|
return;
|
|
}
|
|
QDomElement serviceElem = doc.createElement( "Service" );
|
|
|
|
QDomElement serviceCapabilityElem = propertiesElement.firstChildElement( "WMSServiceCapabilities" );
|
|
if ( serviceCapabilityElem.isNull() || serviceCapabilityElem.text().compare( "true", Qt::CaseInsensitive ) != 0 )
|
|
{
|
|
QgsConfigParserUtils::fallbackServiceCapabilities( parentElement, doc );
|
|
return;
|
|
}
|
|
|
|
//Service name
|
|
QDomElement wmsNameElem = doc.createElement( "Name" );
|
|
QDomText wmsNameText = doc.createTextNode( service );
|
|
wmsNameElem.appendChild( wmsNameText );
|
|
serviceElem.appendChild( wmsNameElem );
|
|
|
|
//WMS title
|
|
//why not use project title ?
|
|
QDomElement titleElem = propertiesElement.firstChildElement( "WMSServiceTitle" );
|
|
if ( !titleElem.isNull() )
|
|
{
|
|
QDomElement wmsTitleElem = doc.createElement( "Title" );
|
|
QDomText wmsTitleText = doc.createTextNode( titleElem.text() );
|
|
wmsTitleElem.appendChild( wmsTitleText );
|
|
serviceElem.appendChild( wmsTitleElem );
|
|
}
|
|
|
|
//WMS abstract
|
|
QDomElement abstractElem = propertiesElement.firstChildElement( "WMSServiceAbstract" );
|
|
if ( !abstractElem.isNull() )
|
|
{
|
|
QDomElement wmsAbstractElem = doc.createElement( "Abstract" );
|
|
QDomText wmsAbstractText = doc.createTextNode( abstractElem.text() );
|
|
wmsAbstractElem.appendChild( wmsAbstractText );
|
|
serviceElem.appendChild( wmsAbstractElem );
|
|
}
|
|
|
|
//keyword list
|
|
QDomElement keywordListElem = propertiesElement.firstChildElement( "WMSKeywordList" );
|
|
if ( service.compare( "WMS", Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
QDomElement wmsKeywordElem = doc.createElement( "KeywordList" );
|
|
//add default keyword
|
|
QDomElement keywordElem = doc.createElement( "Keyword" );
|
|
keywordElem.setAttribute( "vocabulary", "ISO" );
|
|
QDomText keywordText = doc.createTextNode( "infoMapAccessService" );
|
|
/* If WFS and WCS 2.0 is implemented
|
|
if ( service.compare( "WFS", Qt::CaseInsensitive ) == 0 )
|
|
keywordText = doc.createTextNode( "infoFeatureAccessService" );
|
|
else if ( service.compare( "WCS", Qt::CaseInsensitive ) == 0 )
|
|
keywordText = doc.createTextNode( "infoCoverageAccessService" );*/
|
|
keywordElem.appendChild( keywordText );
|
|
wmsKeywordElem.appendChild( keywordElem );
|
|
serviceElem.appendChild( wmsKeywordElem );
|
|
//add config keywords
|
|
if ( !keywordListElem.isNull() && !keywordListElem.text().isEmpty() )
|
|
{
|
|
QDomNodeList keywordList = keywordListElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < keywordList.size(); ++i )
|
|
{
|
|
keywordElem = doc.createElement( "Keyword" );
|
|
keywordText = doc.createTextNode( keywordList.at( i ).toElement().text() );
|
|
keywordElem.appendChild( keywordText );
|
|
if ( sia2045 )
|
|
{
|
|
keywordElem.setAttribute( "vocabulary", "SIA_Geo405" );
|
|
}
|
|
wmsKeywordElem.appendChild( keywordElem );
|
|
}
|
|
}
|
|
}
|
|
else if ( !keywordListElem.isNull() && !keywordListElem.text().isEmpty() )
|
|
{
|
|
QDomNodeList keywordNodeList = keywordListElem.elementsByTagName( "value" );
|
|
QStringList keywordList;
|
|
for ( int i = 0; i < keywordNodeList.size(); ++i )
|
|
{
|
|
keywordList.push_back( keywordNodeList.at( i ).toElement().text() );
|
|
}
|
|
QDomElement wmsKeywordElem = doc.createElement( "Keywords" );
|
|
if ( service.compare( "WCS", Qt::CaseInsensitive ) == 0 )
|
|
wmsKeywordElem = doc.createElement( "keywords" );
|
|
QDomText keywordText = doc.createTextNode( keywordList.join( ", " ) );
|
|
wmsKeywordElem.appendChild( keywordText );
|
|
serviceElem.appendChild( wmsKeywordElem );
|
|
}
|
|
|
|
//OnlineResource element is mandatory according to the WMS specification
|
|
QDomElement wmsOnlineResourceElem = propertiesElement.firstChildElement( "WMSOnlineResource" );
|
|
if ( !wmsOnlineResourceElem.isNull() )
|
|
{
|
|
QDomElement onlineResourceElem = doc.createElement( "OnlineResource" );
|
|
if ( service.compare( "WFS", Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
QDomText onlineResourceText = doc.createTextNode( wmsOnlineResourceElem.text() );
|
|
onlineResourceElem.appendChild( onlineResourceText );
|
|
}
|
|
else
|
|
{
|
|
onlineResourceElem.setAttribute( "xmlns:xlink", "http://www.w3.org/1999/xlink" );
|
|
onlineResourceElem.setAttribute( "xlink:type", "simple" );
|
|
onlineResourceElem.setAttribute( "xlink:href", wmsOnlineResourceElem.text() );
|
|
}
|
|
serviceElem.appendChild( onlineResourceElem );
|
|
}
|
|
|
|
if ( service.compare( "WMS", Qt::CaseInsensitive ) == 0 ) //no contact information in WFS 1.0 and WCS 1.0
|
|
{
|
|
//Contact information
|
|
QDomElement contactInfoElem = doc.createElement( "ContactInformation" );
|
|
|
|
//Contact person primary
|
|
QDomElement contactPersonPrimaryElem = doc.createElement( "ContactPersonPrimary" );
|
|
|
|
//Contact person
|
|
QDomElement contactPersonElem = propertiesElement.firstChildElement( "WMSContactPerson" );
|
|
QString contactPersonString;
|
|
if ( !contactPersonElem.isNull() )
|
|
{
|
|
contactPersonString = contactPersonElem.text();
|
|
}
|
|
QDomElement wmsContactPersonElem = doc.createElement( "ContactPerson" );
|
|
QDomText contactPersonText = doc.createTextNode( contactPersonString );
|
|
wmsContactPersonElem.appendChild( contactPersonText );
|
|
contactPersonPrimaryElem.appendChild( wmsContactPersonElem );
|
|
|
|
|
|
//Contact organisation
|
|
QDomElement contactOrganizationElem = propertiesElement.firstChildElement( "WMSContactOrganization" );
|
|
QString contactOrganizationString;
|
|
if ( !contactOrganizationElem.isNull() )
|
|
{
|
|
contactOrganizationString = contactOrganizationElem.text();
|
|
}
|
|
QDomElement wmsContactOrganizationElem = doc.createElement( "ContactOrganization" );
|
|
QDomText contactOrganizationText = doc.createTextNode( contactOrganizationString );
|
|
wmsContactOrganizationElem.appendChild( contactOrganizationText );
|
|
contactPersonPrimaryElem.appendChild( wmsContactOrganizationElem );
|
|
|
|
//Contact position
|
|
QDomElement contactPositionElem = propertiesElement.firstChildElement( "WMSContactPosition" );
|
|
QString contactPositionString;
|
|
if ( !contactPositionElem.isNull() )
|
|
{
|
|
contactPositionString = contactPositionElem.text();
|
|
}
|
|
QDomElement wmsContactPositionElem = doc.createElement( "ContactPosition" );
|
|
QDomText contactPositionText = doc.createTextNode( contactPositionString );
|
|
wmsContactPositionElem.appendChild( contactPositionText );
|
|
contactPersonPrimaryElem.appendChild( wmsContactPositionElem );
|
|
contactInfoElem.appendChild( contactPersonPrimaryElem );
|
|
|
|
//phone
|
|
QDomElement phoneElem = propertiesElement.firstChildElement( "WMSContactPhone" );
|
|
if ( !phoneElem.isNull() )
|
|
{
|
|
QDomElement wmsPhoneElem = doc.createElement( "ContactVoiceTelephone" );
|
|
QDomText wmsPhoneText = doc.createTextNode( phoneElem.text() );
|
|
wmsPhoneElem.appendChild( wmsPhoneText );
|
|
contactInfoElem.appendChild( wmsPhoneElem );
|
|
}
|
|
|
|
//mail
|
|
QDomElement mailElem = propertiesElement.firstChildElement( "WMSContactMail" );
|
|
if ( !mailElem.isNull() )
|
|
{
|
|
QDomElement wmsMailElem = doc.createElement( "ContactElectronicMailAddress" );
|
|
QDomText wmsMailText = doc.createTextNode( mailElem.text() );
|
|
wmsMailElem.appendChild( wmsMailText );
|
|
contactInfoElem.appendChild( wmsMailElem );
|
|
}
|
|
|
|
serviceElem.appendChild( contactInfoElem );
|
|
}
|
|
|
|
//Fees
|
|
QDomElement feesElem = propertiesElement.firstChildElement( "WMSFees" );
|
|
QDomElement wmsFeesElem = doc.createElement( "Fees" );
|
|
QDomText wmsFeesText = doc.createTextNode( "conditions unknown" ); // default value if access conditions are unknown
|
|
if ( !feesElem.isNull() && !feesElem.text().isEmpty() )
|
|
{
|
|
wmsFeesText = doc.createTextNode( feesElem.text() );
|
|
}
|
|
wmsFeesElem.appendChild( wmsFeesText );
|
|
serviceElem.appendChild( wmsFeesElem );
|
|
|
|
//AccessConstraints
|
|
QDomElement accessConstraintsElem = propertiesElement.firstChildElement( "WMSAccessConstraints" );
|
|
QDomElement wmsAccessConstraintsElem = doc.createElement( "AccessConstraints" );
|
|
QDomText wmsAccessConstraintsText = doc.createTextNode( "None" ); // default value if access constraints are unknown
|
|
if ( !accessConstraintsElem.isNull() && !accessConstraintsElem.text().isEmpty() )
|
|
{
|
|
wmsAccessConstraintsText = doc.createTextNode( accessConstraintsElem.text() );
|
|
}
|
|
wmsAccessConstraintsElem.appendChild( wmsAccessConstraintsText );
|
|
serviceElem.appendChild( wmsAccessConstraintsElem );
|
|
|
|
//max width, max height for WMS
|
|
if ( service.compare( "WMS", Qt::CaseInsensitive ) == 0 )
|
|
{
|
|
QString version = doc.documentElement().attribute( "version" );
|
|
if ( version != "1.1.1" )
|
|
{
|
|
//max width
|
|
QDomElement mwElem = propertiesElement.firstChildElement( "WMSMaxWidth" );
|
|
if ( !mwElem.isNull() )
|
|
{
|
|
QDomElement maxWidthElem = doc.createElement( "MaxWidth" );
|
|
QDomText maxWidthText = doc.createTextNode( mwElem.text() );
|
|
maxWidthElem.appendChild( maxWidthText );
|
|
serviceElem.appendChild( maxWidthElem );
|
|
}
|
|
//max height
|
|
QDomElement mhElem = propertiesElement.firstChildElement( "WMSMaxHeight" );
|
|
if ( !mhElem.isNull() )
|
|
{
|
|
QDomElement maxHeightElem = doc.createElement( "MaxHeight" );
|
|
QDomText maxHeightText = doc.createTextNode( mhElem.text() );
|
|
maxHeightElem.appendChild( maxHeightText );
|
|
serviceElem.appendChild( maxHeightElem );
|
|
}
|
|
}
|
|
}
|
|
parentElement.appendChild( serviceElem );
|
|
}
|
|
|
|
QString QgsServerProjectParser::layerName( const QDomElement& layerElem ) const
|
|
{
|
|
if ( layerElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomElement nameElem = layerElem.firstChildElement( "layername" );
|
|
if ( nameElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
return nameElem.text().replace( ",", "%60" ); //commas are not allowed in layer names
|
|
}
|
|
|
|
QString QgsServerProjectParser::serviceUrl() const
|
|
{
|
|
QString url;
|
|
|
|
if ( !mXMLDoc )
|
|
{
|
|
return url;
|
|
}
|
|
|
|
QDomElement propertiesElement = propertiesElem();
|
|
if ( !propertiesElement.isNull() )
|
|
{
|
|
QDomElement wmsUrlElem = propertiesElement.firstChildElement( "WMSUrl" );
|
|
if ( !wmsUrlElem.isNull() )
|
|
{
|
|
url = wmsUrlElem.text();
|
|
}
|
|
}
|
|
return url;
|
|
}
|
|
|
|
QString QgsServerProjectParser::wfsServiceUrl() const
|
|
{
|
|
QString url;
|
|
|
|
if ( !mXMLDoc )
|
|
{
|
|
return url;
|
|
}
|
|
|
|
QDomElement propertiesElement = propertiesElem();
|
|
if ( !propertiesElement.isNull() )
|
|
{
|
|
QDomElement wfsUrlElem = propertiesElement.firstChildElement( "WFSUrl" );
|
|
if ( !wfsUrlElem.isNull() )
|
|
{
|
|
url = wfsUrlElem.text();
|
|
}
|
|
}
|
|
return url;
|
|
}
|
|
|
|
QString QgsServerProjectParser::wcsServiceUrl() const
|
|
{
|
|
QString url;
|
|
|
|
if ( !mXMLDoc )
|
|
{
|
|
return url;
|
|
}
|
|
|
|
QDomElement propertiesElement = propertiesElem();
|
|
if ( !propertiesElement.isNull() )
|
|
{
|
|
QDomElement wcsUrlElem = propertiesElement.firstChildElement( "WCSUrl" );
|
|
if ( !wcsUrlElem.isNull() )
|
|
{
|
|
url = wcsUrlElem.text();
|
|
}
|
|
}
|
|
return url;
|
|
}
|
|
|
|
void QgsServerProjectParser::combineExtentAndCrsOfGroupChildren( QDomElement& groupElem, QDomDocument& doc, bool considerMapExtent ) const
|
|
{
|
|
QgsRectangle combinedBBox;
|
|
QSet<QString> combinedCRSSet;
|
|
bool firstBBox = true;
|
|
bool firstCRSSet = true;
|
|
|
|
QDomNodeList layerChildren = groupElem.childNodes();
|
|
for ( int j = 0; j < layerChildren.size(); ++j )
|
|
{
|
|
QDomElement childElem = layerChildren.at( j ).toElement();
|
|
|
|
if ( childElem.tagName() != "Layer" )
|
|
continue;
|
|
|
|
QgsRectangle bbox = layerBoundingBoxInProjectCrs( childElem, doc );
|
|
if ( !bbox.isEmpty() )
|
|
{
|
|
if ( firstBBox )
|
|
{
|
|
combinedBBox = bbox;
|
|
firstBBox = false;
|
|
}
|
|
else
|
|
{
|
|
combinedBBox.combineExtentWith( bbox );
|
|
}
|
|
}
|
|
|
|
//combine crs set
|
|
QSet<QString> crsSet;
|
|
if ( crsSetForLayer( childElem, crsSet ) )
|
|
{
|
|
if ( firstCRSSet )
|
|
{
|
|
combinedCRSSet = crsSet;
|
|
firstCRSSet = false;
|
|
}
|
|
else
|
|
{
|
|
combinedCRSSet.intersect( crsSet );
|
|
}
|
|
}
|
|
}
|
|
|
|
QgsConfigParserUtils::appendCrsElementsToLayer( groupElem, doc, combinedCRSSet.toList(), supportedOutputCrsList() );
|
|
|
|
QgsCoordinateReferenceSystem groupCRS = projectCrs();
|
|
if ( considerMapExtent )
|
|
{
|
|
QgsRectangle mapRect = mapRectangle();
|
|
if ( !mapRect.isEmpty() )
|
|
{
|
|
combinedBBox = mapRect;
|
|
}
|
|
}
|
|
QgsConfigParserUtils::appendLayerBoundingBoxes( groupElem, doc, combinedBBox, groupCRS, combinedCRSSet.toList(), supportedOutputCrsList() );
|
|
}
|
|
|
|
void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QDomDocument& doc, QgsMapLayer* currentLayer ) const
|
|
{
|
|
if ( !currentLayer )
|
|
{
|
|
return;
|
|
}
|
|
// Layer tree name
|
|
QDomElement treeNameElem = doc.createElement( "TreeName" );
|
|
QDomText treeNameText = doc.createTextNode( currentLayer->name() );
|
|
treeNameElem.appendChild( treeNameText );
|
|
layerElem.appendChild( treeNameElem );
|
|
|
|
if ( currentLayer->type() == QgsMapLayer::VectorLayer )
|
|
{
|
|
QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( currentLayer );
|
|
const QSet<QString>& excludedAttributes = vLayer->excludeAttributesWms();
|
|
|
|
int displayFieldIdx = -1;
|
|
QString displayField = "maptip";
|
|
QgsExpression exp( vLayer->displayExpression() );
|
|
if ( exp.isField() )
|
|
{
|
|
displayField = static_cast<const QgsExpression::NodeColumnRef*>( exp.rootNode() )->name();
|
|
displayFieldIdx = vLayer->fieldNameIndex( displayField );
|
|
}
|
|
|
|
//attributes
|
|
QDomElement attributesElem = doc.createElement( "Attributes" );
|
|
const QgsFields& layerFields = vLayer->pendingFields();
|
|
for ( int idx = 0; idx < layerFields.count(); ++idx )
|
|
{
|
|
QgsField field = layerFields.at( idx );
|
|
if ( excludedAttributes.contains( field.name() ) )
|
|
{
|
|
continue;
|
|
}
|
|
// field alias in case of displayField
|
|
if ( idx == displayFieldIdx )
|
|
{
|
|
displayField = vLayer->attributeDisplayName( idx );
|
|
}
|
|
QDomElement attributeElem = doc.createElement( "Attribute" );
|
|
attributeElem.setAttribute( "name", field.name() );
|
|
attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) );
|
|
attributeElem.setAttribute( "typeName", field.typeName() );
|
|
QString alias = vLayer->attributeAlias( idx );
|
|
if ( !alias.isEmpty() )
|
|
{
|
|
attributeElem.setAttribute( "alias", alias );
|
|
}
|
|
|
|
//edit type to text
|
|
attributeElem.setAttribute( "editType", vLayer->editFormConfig()->widgetType( idx ) );
|
|
attributeElem.setAttribute( "comment", field.comment() );
|
|
attributeElem.setAttribute( "length", field.length() );
|
|
attributeElem.setAttribute( "precision", field.precision() );
|
|
attributesElem.appendChild( attributeElem );
|
|
}
|
|
//displayfield
|
|
layerElem.setAttribute( "displayField", displayField );
|
|
|
|
//geometry type
|
|
layerElem.setAttribute( "geometryType", QgsWkbTypes::displayString( vLayer->wkbType() ) );
|
|
|
|
layerElem.appendChild( attributesElem );
|
|
}
|
|
}
|
|
|
|
QgsRectangle QgsServerProjectParser::layerBoundingBoxInProjectCrs( const QDomElement& layerElem, const QDomDocument &doc ) const
|
|
{
|
|
QgsRectangle BBox;
|
|
if ( layerElem.isNull() )
|
|
{
|
|
return BBox;
|
|
}
|
|
|
|
//read box coordinates and layer auth. id
|
|
QDomElement boundingBoxElem = layerElem.firstChildElement( "BoundingBox" );
|
|
if ( boundingBoxElem.isNull() )
|
|
{
|
|
return BBox;
|
|
}
|
|
|
|
double minx, miny, maxx, maxy;
|
|
bool conversionOk;
|
|
minx = boundingBoxElem.attribute( "minx" ).toDouble( &conversionOk );
|
|
if ( !conversionOk )
|
|
{
|
|
return BBox;
|
|
}
|
|
miny = boundingBoxElem.attribute( "miny" ).toDouble( &conversionOk );
|
|
if ( !conversionOk )
|
|
{
|
|
return BBox;
|
|
}
|
|
maxx = boundingBoxElem.attribute( "maxx" ).toDouble( &conversionOk );
|
|
if ( !conversionOk )
|
|
{
|
|
return BBox;
|
|
}
|
|
maxy = boundingBoxElem.attribute( "maxy" ).toDouble( &conversionOk );
|
|
if ( !conversionOk )
|
|
{
|
|
return BBox;
|
|
}
|
|
|
|
|
|
QString version = doc.documentElement().attribute( "version" );
|
|
|
|
//create layer crs
|
|
QgsCoordinateReferenceSystem layerCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( boundingBoxElem.attribute( version == "1.1.1" ? "SRS" : "CRS" ) );
|
|
if ( !layerCrs.isValid() )
|
|
{
|
|
return BBox;
|
|
}
|
|
|
|
BBox.setXMinimum( minx );
|
|
BBox.setXMaximum( maxx );
|
|
BBox.setYMinimum( miny );
|
|
BBox.setYMaximum( maxy );
|
|
|
|
if ( version != "1.1.1" && layerCrs.hasAxisInverted() )
|
|
{
|
|
BBox.invert();
|
|
}
|
|
|
|
//get project crs
|
|
QgsCoordinateTransform t( layerCrs, projectCrs() );
|
|
|
|
//transform
|
|
BBox = t.transformBoundingBox( BBox );
|
|
return BBox;
|
|
}
|
|
|
|
bool QgsServerProjectParser::crsSetForLayer( const QDomElement& layerElement, QSet<QString> &crsSet ) const
|
|
{
|
|
if ( layerElement.isNull() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
crsSet.clear();
|
|
|
|
QDomNodeList crsNodeList;
|
|
crsNodeList = layerElement.elementsByTagName( "CRS" ); // WMS 1.3.0
|
|
for ( int i = 0; i < crsNodeList.size(); ++i )
|
|
{
|
|
crsSet.insert( crsNodeList.at( i ).toElement().text() );
|
|
}
|
|
|
|
crsNodeList = layerElement.elementsByTagName( "SRS" ); // WMS 1.1.1
|
|
for ( int i = 0; i < crsNodeList.size(); ++i )
|
|
{
|
|
crsSet.insert( crsNodeList.at( i ).toElement().text() );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
QgsCoordinateReferenceSystem QgsServerProjectParser::projectCrs() const
|
|
{
|
|
//mapcanvas->destinationsrs->spatialrefsys->authid
|
|
if ( mXMLDoc )
|
|
{
|
|
QDomElement authIdElem = mXMLDoc->documentElement().firstChildElement( "mapcanvas" ).firstChildElement( "destinationsrs" ).
|
|
firstChildElement( "spatialrefsys" ).firstChildElement( "authid" );
|
|
if ( !authIdElem.isNull() )
|
|
{
|
|
return QgsCoordinateReferenceSystem::fromOgcWmsCrs( authIdElem.text() );
|
|
}
|
|
}
|
|
return QgsCoordinateReferenceSystem::fromEpsgId( GEO_EPSG_CRS_ID );
|
|
}
|
|
|
|
QgsRectangle QgsServerProjectParser::mapRectangle() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
if ( qgisElem.isNull() )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
|
|
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
|
|
if ( propertiesElem.isNull() )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
|
|
QDomElement extentElem = propertiesElem.firstChildElement( "WMSExtent" );
|
|
if ( extentElem.isNull() )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
|
|
QDomNodeList valueNodeList = extentElem.elementsByTagName( "value" );
|
|
if ( valueNodeList.size() < 4 )
|
|
{
|
|
return QgsRectangle();
|
|
}
|
|
|
|
//order of value elements must be xmin, ymin, xmax, ymax
|
|
double xmin = valueNodeList.at( 0 ).toElement().text().toDouble();
|
|
double ymin = valueNodeList.at( 1 ).toElement().text().toDouble();
|
|
double xmax = valueNodeList.at( 2 ).toElement().text().toDouble();
|
|
double ymax = valueNodeList.at( 3 ).toElement().text().toDouble();
|
|
return QgsRectangle( xmin, ymin, xmax, ymax );
|
|
}
|
|
|
|
QStringList QgsServerProjectParser::supportedOutputCrsList() const
|
|
{
|
|
QStringList crsList;
|
|
if ( !mXMLDoc )
|
|
{
|
|
return crsList;
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
if ( qgisElem.isNull() )
|
|
{
|
|
return crsList;
|
|
}
|
|
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
|
|
if ( propertiesElem.isNull() )
|
|
{
|
|
return crsList;
|
|
}
|
|
QDomElement wmsCrsElem = propertiesElem.firstChildElement( "WMSCrsList" );
|
|
if ( !wmsCrsElem.isNull() )
|
|
{
|
|
QDomNodeList valueList = wmsCrsElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < valueList.size(); ++i )
|
|
{
|
|
crsList.append( valueList.at( i ).toElement().text() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QDomElement wmsEpsgElem = propertiesElem.firstChildElement( "WMSEpsgList" );
|
|
if ( !wmsEpsgElem.isNull() )
|
|
{
|
|
QDomNodeList valueList = wmsEpsgElem.elementsByTagName( "value" );
|
|
bool conversionOk;
|
|
for ( int i = 0; i < valueList.size(); ++i )
|
|
{
|
|
int epsgNr = valueList.at( i ).toElement().text().toInt( &conversionOk );
|
|
if ( conversionOk )
|
|
{
|
|
crsList.append( QString( "EPSG:%1" ).arg( epsgNr ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//no CRS restriction defined in the project. Provide project CRS, wgs84 and pseudo mercator
|
|
QString projectCrsId = projectCrs().authid();
|
|
crsList.append( projectCrsId );
|
|
if ( projectCrsId.compare( "EPSG:4326", Qt::CaseInsensitive ) != 0 )
|
|
{
|
|
crsList.append( QString( "EPSG:%1" ).arg( 4326 ) );
|
|
}
|
|
if ( projectCrsId.compare( "EPSG:3857", Qt::CaseInsensitive ) != 0 )
|
|
{
|
|
crsList.append( QString( "EPSG:%1" ).arg( 3857 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
return crsList;
|
|
}
|
|
|
|
QString QgsServerProjectParser::projectTitle() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
if ( qgisElem.isNull() )
|
|
{
|
|
return QString();
|
|
}
|
|
|
|
QDomElement titleElem = qgisElem.firstChildElement( "title" );
|
|
if ( !titleElem.isNull() )
|
|
{
|
|
QString title = titleElem.text();
|
|
if ( !title.isEmpty() )
|
|
{
|
|
return title;
|
|
}
|
|
}
|
|
|
|
//no title element or not project title set. Use project filename without extension
|
|
QFileInfo projectFileInfo( mProjectPath );
|
|
return projectFileInfo.baseName();
|
|
}
|
|
|
|
QDomElement QgsServerProjectParser::legendElem() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
return mXMLDoc->documentElement().firstChildElement( "legend" );
|
|
}
|
|
|
|
QDomElement QgsServerProjectParser::propertiesElem() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
|
|
return mXMLDoc->documentElement().firstChildElement( "properties" );
|
|
}
|
|
|
|
QSet<QString> QgsServerProjectParser::findRestrictedLayers() const
|
|
{
|
|
QSet<QString> restrictedLayerSet;
|
|
|
|
if ( !mXMLDoc )
|
|
{
|
|
return restrictedLayerSet;
|
|
}
|
|
|
|
//names of unpublished layers / groups
|
|
QDomElement propertiesElem = mXMLDoc->documentElement().firstChildElement( "properties" );
|
|
if ( !propertiesElem.isNull() )
|
|
{
|
|
QDomElement wmsLayerRestrictionElem = propertiesElem.firstChildElement( "WMSRestrictedLayers" );
|
|
if ( !wmsLayerRestrictionElem.isNull() )
|
|
{
|
|
QStringList restrictedLayersAndGroups;
|
|
QDomNodeList wmsLayerRestrictionValues = wmsLayerRestrictionElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < wmsLayerRestrictionValues.size(); ++i )
|
|
{
|
|
restrictedLayerSet.insert( wmsLayerRestrictionValues.at( i ).toElement().text() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//get legend dom element
|
|
if ( restrictedLayerSet.size() < 1 || !mXMLDoc )
|
|
{
|
|
return restrictedLayerSet;
|
|
}
|
|
|
|
QDomElement legendElem = mXMLDoc->documentElement().firstChildElement( "legend" );
|
|
if ( legendElem.isNull() )
|
|
{
|
|
return restrictedLayerSet;
|
|
}
|
|
|
|
//go through all legend groups and insert names of subgroups / sublayers if there is a match
|
|
QDomNodeList legendGroupList = legendElem.elementsByTagName( "legendgroup" );
|
|
for ( int i = 0; i < legendGroupList.size(); ++i )
|
|
{
|
|
//get name
|
|
QDomElement groupElem = legendGroupList.at( i ).toElement();
|
|
QString groupName = groupElem.attribute( "name" );
|
|
if ( restrictedLayerSet.contains( groupName ) ) //match: add names of subgroups and sublayers to set
|
|
{
|
|
//embedded group? -> also get names of subgroups and sublayers from embedded projects
|
|
if ( groupElem.attribute( "embedded" ) == "1" )
|
|
{
|
|
sublayersOfEmbeddedGroup( convertToAbsolutePath( groupElem.attribute( "project" ) ), groupName, restrictedLayerSet );
|
|
}
|
|
else //local group
|
|
{
|
|
QDomNodeList subgroupList = groupElem.elementsByTagName( "legendgroup" );
|
|
for ( int j = 0; j < subgroupList.size(); ++j )
|
|
{
|
|
restrictedLayerSet.insert( subgroupList.at( j ).toElement().attribute( "name" ) );
|
|
}
|
|
QDomNodeList sublayerList = groupElem.elementsByTagName( "legendlayer" );
|
|
for ( int k = 0; k < sublayerList.size(); ++k )
|
|
{
|
|
restrictedLayerSet.insert( sublayerList.at( k ).toElement().attribute( "name" ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// wmsLayerRestrictionValues contains LayerIDs
|
|
if ( mUseLayerIDs )
|
|
{
|
|
QDomNodeList legendLayerList = legendElem.elementsByTagName( "legendlayer" );
|
|
for ( int i = 0; i < legendLayerList.size(); ++i )
|
|
{
|
|
//get name
|
|
QDomElement layerElem = legendLayerList.at( i ).toElement();
|
|
QString layerName = layerElem.attribute( "name" );
|
|
if ( restrictedLayerSet.contains( layerName ) ) //match: add layer id
|
|
{
|
|
// get legend layer file element
|
|
QDomNodeList layerfileList = layerElem.elementsByTagName( "legendlayerfile" );
|
|
if ( !layerfileList.isEmpty() )
|
|
{
|
|
// add layer id
|
|
restrictedLayerSet.insert( layerfileList.at( 0 ).toElement().attribute( "layerid" ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return restrictedLayerSet;
|
|
}
|
|
|
|
bool QgsServerProjectParser::findUseLayerIds() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
return false;
|
|
|
|
QDomElement propertiesElem = mXMLDoc->documentElement().firstChildElement( "properties" );
|
|
if ( propertiesElem.isNull() )
|
|
return false;
|
|
|
|
QDomElement wktElem = propertiesElem.firstChildElement( "WMSUseLayerIDs" );
|
|
if ( wktElem.isNull() )
|
|
return false;
|
|
|
|
return wktElem.text().compare( "true", Qt::CaseInsensitive ) == 0;
|
|
}
|
|
|
|
void QgsServerProjectParser::layerFromLegendLayer( const QDomElement& legendLayerElem, QMap< int, QgsMapLayer*>& layers, bool useCache ) const
|
|
{
|
|
QString id = legendLayerElem.firstChild().firstChild().toElement().attribute( "layerid" );
|
|
int drawingOrder = updateLegendDrawingOrder() ? -1 : mCustomLayerOrder.indexOf( id );
|
|
|
|
QHash< QString, QDomElement >::const_iterator layerIt = mProjectLayerElementsById.find( id );
|
|
if ( layerIt != mProjectLayerElementsById.constEnd() )
|
|
{
|
|
QgsMapLayer* layer = createLayerFromElement( layerIt.value(), useCache );
|
|
if ( layer )
|
|
{
|
|
layers.insertMulti( drawingOrder, layer );
|
|
}
|
|
}
|
|
}
|
|
|
|
QList<QDomElement> QgsServerProjectParser::findLegendGroupElements() const
|
|
{
|
|
QList<QDomElement> LegendGroupElemList;
|
|
QgsLayerTreeGroup* rootLayerTreeGroup = new QgsLayerTreeGroup;
|
|
|
|
QDomElement layerTreeElem = mXMLDoc->documentElement().firstChildElement( "layer-tree-group" );
|
|
if ( !layerTreeElem.isNull() )
|
|
{
|
|
rootLayerTreeGroup = QgsLayerTreeGroup::readXml( layerTreeElem );
|
|
}
|
|
|
|
QDomElement legendElement = mXMLDoc->documentElement().firstChildElement( "legend" );
|
|
if ( !legendElement.isNull() && rootLayerTreeGroup )
|
|
{
|
|
LegendGroupElemList.append( setLegendGroupElementsWithLayerTree( rootLayerTreeGroup, legendElement ) );
|
|
}
|
|
|
|
if ( !legendElement.isNull() )
|
|
{
|
|
QDomNodeList groupNodeList = legendElement.elementsByTagName( "legendgroup" );
|
|
for ( int i = 0; i < groupNodeList.size(); ++i )
|
|
{
|
|
LegendGroupElemList.push_back( groupNodeList.at( i ).toElement() );
|
|
}
|
|
return LegendGroupElemList;
|
|
}
|
|
return LegendGroupElemList;
|
|
}
|
|
|
|
QList<QDomElement> QgsServerProjectParser::setLegendGroupElementsWithLayerTree( QgsLayerTreeGroup* layerTreeGroup, const QDomElement& legendElement ) const
|
|
{
|
|
QList<QDomElement> LegendGroupElemList;
|
|
QList< QgsLayerTreeNode * > layerTreeGroupChildren = layerTreeGroup->children();
|
|
QDomNodeList legendElementChildNodes = legendElement.childNodes();
|
|
int g = 0; // index of the last child layer tree group
|
|
for ( int i = 0; i < legendElementChildNodes.size(); ++i )
|
|
{
|
|
QDomNode legendElementNode = legendElementChildNodes.at( i );
|
|
if ( !legendElementNode.isElement() )
|
|
continue;
|
|
QDomElement legendElement = legendElementNode.toElement();
|
|
if ( legendElement.tagName() != "legendgroup" )
|
|
continue;
|
|
for ( int j = g; j < i + 1; ++j )
|
|
{
|
|
QgsLayerTreeNode* layerTreeNode = layerTreeGroupChildren.at( j );
|
|
if ( layerTreeNode->nodeType() != QgsLayerTreeNode::NodeGroup )
|
|
continue;
|
|
QgsLayerTreeGroup* layerTreeGroup = static_cast<QgsLayerTreeGroup *>( layerTreeNode );
|
|
if ( layerTreeGroup->name() == legendElement.attribute( "name" ) )
|
|
{
|
|
g = j;
|
|
QString shortName = layerTreeGroup->customProperty( "wmsShortName" ).toString();
|
|
if ( !shortName.isEmpty() )
|
|
legendElement.setAttribute( "shortName", shortName );
|
|
QString title = layerTreeGroup->customProperty( "wmsTitle" ).toString();
|
|
if ( !title.isEmpty() )
|
|
legendElement.setAttribute( "title", title );
|
|
LegendGroupElemList.append( setLegendGroupElementsWithLayerTree( layerTreeGroup, legendElement ) );
|
|
}
|
|
}
|
|
LegendGroupElemList.push_back( legendElement );
|
|
}
|
|
return LegendGroupElemList;
|
|
}
|
|
|
|
void QgsServerProjectParser::sublayersOfEmbeddedGroup( const QString& projectFilePath, const QString& groupName, QSet<QString>& layerSet )
|
|
{
|
|
QFile projectFile( projectFilePath );
|
|
if ( !projectFile.open( QIODevice::ReadOnly ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QDomDocument xmlDoc;
|
|
if ( !xmlDoc.setContent( &projectFile ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//go to legend node
|
|
QDomElement legendElem = xmlDoc.documentElement().firstChildElement( "legend" );
|
|
if ( legendElem.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//get group node list of embedded project
|
|
QDomNodeList groupNodes = legendElem.elementsByTagName( "legendgroup" );
|
|
QDomElement groupElem;
|
|
for ( int i = 0; i < groupNodes.size(); ++i )
|
|
{
|
|
groupElem = groupNodes.at( i ).toElement();
|
|
if ( groupElem.attribute( "name" ) == groupName )
|
|
{
|
|
//get all subgroups and sublayers and add to layerSet
|
|
QDomElement subElem;
|
|
QDomNodeList subGroupList = groupElem.elementsByTagName( "legendgroup" );
|
|
for ( int j = 0; j < subGroupList.size(); ++j )
|
|
{
|
|
subElem = subGroupList.at( j ).toElement();
|
|
layerSet.insert( subElem.attribute( "name" ) );
|
|
}
|
|
QDomNodeList subLayerList = groupElem.elementsByTagName( "legendlayer" );
|
|
for ( int j = 0; j < subLayerList.size(); ++j )
|
|
{
|
|
subElem = subLayerList.at( j ).toElement();
|
|
layerSet.insert( subElem.attribute( "name" ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
QStringList QgsServerProjectParser::wfsLayerNames() const
|
|
{
|
|
QStringList layerNameList;
|
|
|
|
QMap<QString, QgsMapLayer*> layerMap;
|
|
projectLayerMap( layerMap );
|
|
|
|
QgsMapLayer* currentLayer = nullptr;
|
|
QStringList wfsIdList = wfsLayers();
|
|
QStringList::const_iterator wfsIdIt = wfsIdList.constBegin();
|
|
for ( ; wfsIdIt != wfsIdList.constEnd(); ++wfsIdIt )
|
|
{
|
|
QMap<QString, QgsMapLayer*>::const_iterator layerMapIt = layerMap.find( *wfsIdIt );
|
|
if ( layerMapIt != layerMap.constEnd() )
|
|
{
|
|
currentLayer = layerMapIt.value();
|
|
if ( currentLayer )
|
|
{
|
|
layerNameList.append( mUseLayerIDs ? currentLayer->id() : currentLayer->name() );
|
|
}
|
|
}
|
|
}
|
|
|
|
return layerNameList;
|
|
}
|
|
|
|
QStringList QgsServerProjectParser::wcsLayerNames() const
|
|
{
|
|
QStringList layerNameList;
|
|
|
|
QMap<QString, QgsMapLayer*> layerMap;
|
|
projectLayerMap( layerMap );
|
|
|
|
QgsMapLayer* currentLayer = nullptr;
|
|
QStringList wcsIdList = wcsLayers();
|
|
QStringList::const_iterator wcsIdIt = wcsIdList.constBegin();
|
|
for ( ; wcsIdIt != wcsIdList.constEnd(); ++wcsIdIt )
|
|
{
|
|
QMap<QString, QgsMapLayer*>::const_iterator layerMapIt = layerMap.find( *wcsIdIt );
|
|
if ( layerMapIt != layerMap.constEnd() )
|
|
{
|
|
currentLayer = layerMapIt.value();
|
|
if ( currentLayer )
|
|
{
|
|
layerNameList.append( mUseLayerIDs ? currentLayer->id() : currentLayer->name() );
|
|
}
|
|
}
|
|
}
|
|
|
|
return layerNameList;
|
|
}
|
|
|
|
QDomElement QgsServerProjectParser::firstComposerLegendElement() const
|
|
{
|
|
if ( !mXMLDoc )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
|
|
QDomElement documentElem = mXMLDoc->documentElement();
|
|
if ( documentElem.isNull() )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
|
|
QDomElement composerElem = documentElem.firstChildElement( "Composer" );
|
|
if ( composerElem.isNull() )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
QDomElement compositionElem = composerElem.firstChildElement( "Composition" );
|
|
if ( compositionElem.isNull() )
|
|
{
|
|
return QDomElement();
|
|
}
|
|
return compositionElem.firstChildElement( "ComposerLegend" );
|
|
}
|
|
|
|
QList<QDomElement> QgsServerProjectParser::publishedComposerElements() const
|
|
{
|
|
QList<QDomElement> composerElemList;
|
|
if ( !mXMLDoc )
|
|
{
|
|
return composerElemList;
|
|
}
|
|
|
|
QDomNodeList composerNodeList = mXMLDoc->elementsByTagName( "Composer" );
|
|
|
|
QDomElement propertiesElem = mXMLDoc->documentElement().firstChildElement( "properties" );
|
|
QDomElement wmsRestrictedComposersElem = propertiesElem.firstChildElement( "WMSRestrictedComposers" );
|
|
if ( wmsRestrictedComposersElem.isNull() )
|
|
{
|
|
for ( int i = 0; i < composerNodeList.size(); ++i )
|
|
{
|
|
composerElemList.push_back( composerNodeList.at( i ).toElement() );
|
|
}
|
|
return composerElemList;
|
|
}
|
|
|
|
QSet<QString> restrictedComposerNames;
|
|
QDomNodeList valueList = wmsRestrictedComposersElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < valueList.size(); ++i )
|
|
{
|
|
restrictedComposerNames.insert( valueList.at( i ).toElement().text() );
|
|
}
|
|
|
|
//remove unpublished composers from list
|
|
QString currentComposerName;
|
|
QDomElement currentElem;
|
|
for ( int i = 0; i < composerNodeList.size(); ++i )
|
|
{
|
|
currentElem = composerNodeList.at( i ).toElement();
|
|
currentComposerName = currentElem.attribute( "title" );
|
|
if ( !restrictedComposerNames.contains( currentComposerName ) )
|
|
{
|
|
composerElemList.push_back( currentElem );
|
|
}
|
|
}
|
|
|
|
return composerElemList;
|
|
}
|
|
|
|
QList< QPair< QString, QgsLayerCoordinateTransform > > QgsServerProjectParser::layerCoordinateTransforms() const
|
|
{
|
|
QList< QPair< QString, QgsLayerCoordinateTransform > > layerTransformList;
|
|
|
|
QDomElement coordTransformInfoElem = mXMLDoc->documentElement().firstChildElement( "mapcanvas" ).firstChildElement( "layer_coordinate_transform_info" );
|
|
if ( coordTransformInfoElem.isNull() )
|
|
{
|
|
return layerTransformList;
|
|
}
|
|
|
|
QDomNodeList layerTransformNodeList = coordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
|
|
for ( int i = 0; i < layerTransformNodeList.size(); ++i )
|
|
{
|
|
QPair< QString, QgsLayerCoordinateTransform > layerEntry;
|
|
QDomElement layerTransformElem = layerTransformNodeList.at( i ).toElement();
|
|
layerEntry.first = layerTransformElem.attribute( "layerid" );
|
|
QgsLayerCoordinateTransform t;
|
|
t.srcAuthId = layerTransformElem.attribute( "srcAuthId" );
|
|
t.destAuthId = layerTransformElem.attribute( "destAuthId" );
|
|
t.srcDatumTransform = layerTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
|
|
t.destDatumTransform = layerTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
|
|
layerEntry.second = t;
|
|
layerTransformList.push_back( layerEntry );
|
|
}
|
|
return layerTransformList;
|
|
}
|
|
|
|
QStringList QgsServerProjectParser::wfsLayers() const
|
|
{
|
|
QStringList wfsList;
|
|
if ( !mXMLDoc )
|
|
{
|
|
return wfsList;
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
if ( qgisElem.isNull() )
|
|
{
|
|
return wfsList;
|
|
}
|
|
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
|
|
if ( propertiesElem.isNull() )
|
|
{
|
|
return wfsList;
|
|
}
|
|
QDomElement wfsLayersElem = propertiesElem.firstChildElement( "WFSLayers" );
|
|
if ( wfsLayersElem.isNull() )
|
|
{
|
|
return wfsList;
|
|
}
|
|
QDomNodeList valueList = wfsLayersElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < valueList.size(); ++i )
|
|
{
|
|
wfsList << valueList.at( i ).toElement().text();
|
|
}
|
|
return wfsList;
|
|
}
|
|
|
|
QStringList QgsServerProjectParser::wcsLayers() const
|
|
{
|
|
QStringList wcsList;
|
|
if ( !mXMLDoc )
|
|
{
|
|
return wcsList;
|
|
}
|
|
|
|
QDomElement qgisElem = mXMLDoc->documentElement();
|
|
if ( qgisElem.isNull() )
|
|
{
|
|
return wcsList;
|
|
}
|
|
QDomElement propertiesElem = qgisElem.firstChildElement( "properties" );
|
|
if ( propertiesElem.isNull() )
|
|
{
|
|
return wcsList;
|
|
}
|
|
QDomElement wcsLayersElem = propertiesElem.firstChildElement( "WCSLayers" );
|
|
if ( wcsLayersElem.isNull() )
|
|
{
|
|
return wcsList;
|
|
}
|
|
QDomNodeList valueList = wcsLayersElem.elementsByTagName( "value" );
|
|
for ( int i = 0; i < valueList.size(); ++i )
|
|
{
|
|
wcsList << valueList.at( i ).toElement().text();
|
|
}
|
|
return wcsList;
|
|
}
|
|
|
|
void QgsServerProjectParser::addJoinLayersForElement( const QDomElement& layerElem ) const
|
|
{
|
|
QDomElement vectorJoinsElem = layerElem.firstChildElement( "vectorjoins" );
|
|
if ( vectorJoinsElem.isNull() )
|
|
{
|
|
return;
|
|
}
|
|
|
|
QDomNodeList joinNodeList = vectorJoinsElem.elementsByTagName( "join" );
|
|
for ( int i = 0; i < joinNodeList.size(); ++i )
|
|
{
|
|
QString id = joinNodeList.at( i ).toElement().attribute( "joinLayerId" );
|
|
QgsMapLayer* layer = mapLayerFromLayerId( id );
|
|
if ( layer )
|
|
{
|
|
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void QgsServerProjectParser::addValueRelationLayersForLayer( const QgsVectorLayer *vl ) const
|
|
{
|
|
if ( !vl )
|
|
return;
|
|
|
|
for ( int idx = 0; idx < vl->pendingFields().size(); idx++ )
|
|
{
|
|
if ( vl->editFormConfig()->widgetType( idx ) != "ValueRelation" )
|
|
continue;
|
|
|
|
QgsEditorWidgetConfig cfg( vl->editFormConfig()->widgetConfig( idx ) );
|
|
if ( !cfg.contains( "Layer" ) )
|
|
continue;
|
|
|
|
QString layerId = cfg.value( "Layer" ).toString();
|
|
if ( QgsMapLayerRegistry::instance()->mapLayer( layerId ) )
|
|
continue;
|
|
|
|
QgsMapLayer *layer = mapLayerFromLayerId( layerId );
|
|
if ( !layer )
|
|
continue;
|
|
|
|
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
|
|
}
|
|
}
|
|
|
|
void QgsServerProjectParser::addGetFeatureLayers( const QDomElement& layerElem ) const
|
|
{
|
|
QString str;
|
|
QTextStream stream( &str );
|
|
layerElem.save( stream, 2 );
|
|
|
|
QRegExp rx( "getFeature\\('([^']*)'" );
|
|
int idx = 0;
|
|
while (( idx = rx.indexIn( str, idx ) ) != -1 )
|
|
{
|
|
QString name = rx.cap( 1 );
|
|
QgsMapLayer* ml = nullptr;
|
|
QHash< QString, QDomElement >::const_iterator layerElemIt = mProjectLayerElementsById.find( name );
|
|
if ( layerElemIt != mProjectLayerElementsById.constEnd() )
|
|
{
|
|
ml = createLayerFromElement( layerElemIt.value() );
|
|
}
|
|
else
|
|
{
|
|
layerElemIt = mProjectLayerElementsByName.find( name );
|
|
if ( layerElemIt != mProjectLayerElementsByName.constEnd() )
|
|
{
|
|
ml = createLayerFromElement( layerElemIt.value() );
|
|
}
|
|
}
|
|
|
|
if ( ml )
|
|
{
|
|
QgsMapLayerRegistry::instance()->addMapLayer( ml, false, false );
|
|
}
|
|
idx += rx.matchedLength();
|
|
}
|
|
}
|
|
|
|
|