QGIS/src/mapserver/qgsserverprojectparser.cpp
2014-04-07 14:28:28 +02:00

1163 lines
34 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 "qgsconfigcache.h"
#include "qgsconfigparserutils.h"
#include "qgscrscache.h"
#include "qgsdatasourceuri.h"
#include "qgsmaplayerregistry.h"
#include "qgsmslayercache.h"
#include "qgsrasterlayer.h"
#include <QDomDocument>
#include <QFileInfo>
#include <QStringList>
#include <QUrl>
QgsServerProjectParser::QgsServerProjectParser( QDomDocument* xmlDoc, const QString& filePath ):
mXMLDoc( xmlDoc ), mProjectPath( filePath )
{
//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 );
mProjectLayerElementsByName.insert( layerName( currentElement ), currentElement );
mProjectLayerElementsById.insert( layerId( currentElement ), currentElement );
}
QDomElement legendElement = mXMLDoc->documentElement().firstChildElement( "legend" );
if ( !legendElement.isNull() )
{
QDomNodeList groupNodeList = legendElement.elementsByTagName( "legendgroup" );
for ( int i = 0; i < groupNodeList.size(); ++i )
{
mLegendGroupElements.push_back( groupNodeList.at( i ).toElement() );
}
}
mRestrictedLayers = findRestrictedLayers();
}
}
QgsServerProjectParser::QgsServerProjectParser(): mXMLDoc( 0 )
{
}
QgsServerProjectParser::~QgsServerProjectParser()
{
delete mXMLDoc;
}
void QgsServerProjectParser::projectLayerMap( QMap<QString, QgsMapLayer*>& layerMap ) const
{
layerMap.clear();
QList<QDomElement>::const_iterator layerElemIt = mProjectLayerElements.constBegin();
for ( ; layerElemIt != mProjectLayerElements.constEnd(); ++layerElemIt )
{
addJoinLayersForElement( *layerElemIt );
addValueRelationLayersForElement( *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 = file.split( "/", QString::SkipEmptyParts );
QStringList projElems = mProjectPath.split( "/", QString::SkipEmptyParts );
#if defined(Q_OS_WIN)
if ( uncPath )
{
projElems.insert( 0, "" );
projElems.insert( 0, "" );
}
#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 0;
}
QDomElement dataSourceElem = elem.firstChildElement( "datasource" );
QString uri = dataSourceElem.text();
QString absoluteUri;
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 = 0;
if ( useCache )
{
layer = QgsMSLayerCache::instance()->searchLayer( absoluteUri, id );
}
if ( 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
{
//todo: fixme
/*
QString project = convertToAbsolutePath( elem.attribute( "project" ) );
QgsDebugMsg( QString( "Project path: %1" ).arg( project ) );
QgsProjectParser* otherConfig = dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( project ) );
if ( !otherConfig )
{
return 0;
}
QHash< QString, QDomElement >::const_iterator layerIt = otherConfig->mProjectLayerElementsById.find( elem.attribute( "id" ) );
if ( layerIt == otherConfig->mProjectLayerElementsById.constEnd() )
{
return 0;
}
return otherConfig->createLayerFromElement( layerIt.value() );
*/
}
if ( layer )
{
layer->readLayerXML( const_cast<QDomElement&>( elem ) ); //should be changed to const in QgsMapLayer
layer->setLayerName( layerName( elem ) );
if ( useCache )
{
QgsMSLayerCache::instance()->insertLayer( absoluteUri, id, layer, mProjectPath );
}
else
{
//todo: fixme
//mLayersToRemove.push_back( 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 0;
}
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();
}
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();
}
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;
}
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() );
const QgsCoordinateReferenceSystem& groupCRS = projectCRS();
if ( considerMapExtent )
{
QgsRectangle mapRect = mapRectangle();
if ( !mapRect.isEmpty() )
{
combinedBBox = mapRect;
}
}
QgsConfigParserUtils::appendLayerBoundingBoxes( groupElem, doc, combinedBBox, groupCRS );
}
void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QDomDocument& doc, QgsMapLayer* currentLayer ) const
{
if ( !currentLayer )
{
return;
}
if ( currentLayer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( currentLayer );
const QSet<QString>& excludedAttributes = vLayer->excludeAttributesWMS();
QString displayField = vLayer->displayField();
//attributes
QDomElement attributesElem = doc.createElement( "Attributes" );
const QgsFields& layerFields = vLayer->pendingFields();
for ( int idx = 0; idx < layerFields.count(); ++idx )
{
const QgsField& field = layerFields[idx];
if ( excludedAttributes.contains( field.name() ) )
{
continue;
}
// field alias in case of displayField
if ( field.name() == displayField )
{
displayField = vLayer->attributeDisplayName( idx );
}
QDomElement attributeElem = doc.createElement( "Attribute" );
attributeElem.setAttribute( "name", vLayer->attributeDisplayName( idx ) );
attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) );
attributeElem.setAttribute( "typeName", field.typeName() );
//edit type to text
QgsVectorLayer::EditType typeEnum = vLayer->editType( idx );
attributeElem.setAttribute( "editType", editTypeString( typeEnum ) );
attributeElem.setAttribute( "comment", field.comment() );
attributeElem.setAttribute( "length", field.length() );
attributeElem.setAttribute( "precision", field.precision() );
attributesElem.appendChild( attributeElem );
}
//displayfield
layerElem.setAttribute( "displayField", displayField );
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
const QgsCoordinateReferenceSystem& layerCrs = QgsCRSCache::instance()->crsByAuthId( 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.axisInverted() )
{
BBox.invert();
}
//get project crs
const QgsCoordinateReferenceSystem& projectCrs = projectCRS();
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;
}
const 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 QgsCRSCache::instance()->crsByAuthId( authIdElem.text() );
}
}
return QgsCRSCache::instance()->crsByEpsgId( 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() )
{
return crsList;
}
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 ) );
}
}
}
return crsList;
}
//not very nice, needs to be kept in sync with QgsVectorLayer class...
QString QgsServerProjectParser::editTypeString( QgsVectorLayer::EditType type )
{
switch ( type )
{
case QgsVectorLayer::LineEdit:
return "LineEdit";
case QgsVectorLayer::UniqueValues:
return "UniqueValues";
case QgsVectorLayer::UniqueValuesEditable:
return "UniqueValuesEditable";
case QgsVectorLayer::ValueMap:
return "ValueMap";
case QgsVectorLayer::Classification:
return "Classification";
case QgsVectorLayer::EditRange:
return "EditRange";
case QgsVectorLayer::SliderRange:
return "SliderRange";
case QgsVectorLayer::CheckBox:
return "CheckBox";
case QgsVectorLayer::FileName:
return "FileName";
case QgsVectorLayer::Enumeration:
return "Enumeration";
case QgsVectorLayer::Immutable:
return "Immutable";
case QgsVectorLayer::Hidden:
return "Hidden";
case QgsVectorLayer::TextEdit:
return "TextEdit";
case QgsVectorLayer::Calendar:
return "Calendar";
case QgsVectorLayer::DialRange:
return "DialRange";
case QgsVectorLayer::ValueRelation:
return "ValueRelation";
case QgsVectorLayer::UuidGenerator:
return "UuidGenerator";
default:
return "Unknown";
}
}
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" ) );
}
}
}
}
return restrictedLayerSet;
}
void QgsServerProjectParser::addLayersFromGroup( const QDomElement& legendGroupElem, QList<QgsMapLayer*>& layerList, bool useCache ) const
{
if ( legendGroupElem.attribute( "embedded" ) == "1" ) //embedded group
{
//get project parser
//get group elements from project parser, find the group
//iterate over layers and add them (embedding in embedded groups does not work)
QString groupName = legendGroupElem.attribute( "name" );
QString project = convertToAbsolutePath( legendGroupElem.attribute( "project" ) );
#if 0 //todo: fixme
QgsProjectParser* p = 0; //dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( project ) );
if ( !p )
{
return;
}
QList<QDomElement> pLegendGroupElems = p->mLegendGroupElements;
QList<QDomElement>::const_iterator pGroupIt = pLegendGroupElems.constBegin();
for ( ; pGroupIt != pLegendGroupElems.constEnd(); ++pGroupIt )
{
if ( pGroupIt->attribute( "name" ) == groupName )
{
p->addLayersFromGroup( *pGroupIt, layerList, useCache );
return;
}
}
#endif //0
}
else //normal group
{
bool updateDrawingOrder = ( legendGroupElem.parentNode().toElement().attribute( "updateDrawingOrder" ) == "true" );
QMap< int, QDomElement > layerOrderList;
QDomNodeList groupElemChildren = legendGroupElem.childNodes();
for ( int i = 0; i < groupElemChildren.size(); ++i )
{
QDomElement elem = groupElemChildren.at( i ).toElement();
if ( elem.tagName() == "legendgroup" )
{
addLayersFromGroup( elem, layerList, useCache );
}
else if ( elem.tagName() == "legendlayer" )
{
int drawingOrder = updateDrawingOrder ? -1 : elem.attribute( "drawingOrder", "-1" ).toInt();
if ( drawingOrder == -1 )
{
addLayerFromLegendLayer( elem, layerList, useCache );
}
else
{
layerOrderList.insert( drawingOrder, elem );
}
}
}
QMap< int, QDomElement >::const_iterator layerOrderIt = layerOrderList.constBegin();
for ( ; layerOrderIt != layerOrderList.constEnd(); ++layerOrderIt )
{
addLayerFromLegendLayer( layerOrderIt.value(), layerList, useCache );
}
}
}
void QgsServerProjectParser::addLayerFromLegendLayer( const QDomElement& legendLayerElem, QList<QgsMapLayer*>& layerList, bool useCache ) const
{
QString id = legendLayerElem.firstChild().firstChild().toElement().attribute( "layerid" );
QHash< QString, QDomElement >::const_iterator layerIt = mProjectLayerElementsById.find( id );
if ( layerIt != mProjectLayerElementsById.constEnd() )
{
addJoinLayersForElement( layerIt.value(), useCache );
addValueRelationLayersForElement( layerIt.value(), useCache );
QgsMapLayer* layer = createLayerFromElement( layerIt.value(), useCache );
if ( layer )
{
layerList.append( layer );
}
}
}
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 = 0;
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( 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();
}
return composerElem.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 ( unsigned int i = 0; i < composerNodeList.length(); ++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;
}
void QgsServerProjectParser::addJoinLayersForElement( const QDomElement& layerElem, bool useCache ) const
{
QDomElement vectorJoinsElem = layerElem.firstChildElement( "vectorjoins" );
if ( vectorJoinsElem.isNull() )
{
return;
}
QDomNodeList joinNodeList = vectorJoinsElem.elementsByTagName( "join" );
if ( joinNodeList.size() > 1 )
{
return;
}
for ( int i = 0; i < joinNodeList.size(); ++i )
{
QString id = joinNodeList.at( i ).toElement().attribute( "joinLayerId" );
QgsMapLayer* layer = mapLayerFromLayerId( id, useCache );
if ( layer )
{
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
}
}
}
void QgsServerProjectParser::addValueRelationLayersForElement( const QDomElement& layerElem, bool useCache ) const
{
QDomElement editTypesElem = layerElem.firstChildElement( "edittypes" );
if ( editTypesElem.isNull() )
{
return;
}
QDomNodeList editTypeNodeList = editTypesElem.elementsByTagName( "edittype" );
for ( int i = 0; i < editTypeNodeList.size(); ++i )
{
QDomElement editTypeElem = editTypeNodeList.at( i ).toElement();
int type = editTypeElem.attribute( "type" ).toInt();
if ( type == QgsVectorLayer::ValueRelation )
{
QString layerId = editTypeElem.attribute( "layer" );
/*QString keyAttribute = editTypeEleml.attribute( "id" ); //relation attribute in other layer
QString valueAttribute = editTypeElem.attribute( "value" ); //value attribute in other layer
QString relationAttribute = editTypeElem.attribute( "name" );*/
QgsMapLayer* layer = mapLayerFromLayerId( layerId, useCache );
if ( layer )
{
QgsMapLayerRegistry::instance()->addMapLayer( layer, false, false );
}
}
}
}