/*************************************************************************** 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 #include #include #include 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& layerMap ) const { layerMap.clear(); QList::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( 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( 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 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 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( currentLayer ); const QSet& 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 &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 QgsServerProjectParser::findRestrictedLayers() const { QSet 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& 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( QgsConfigCache::instance()->searchConfiguration( project ) ); if ( !p ) { return; } QList pLegendGroupElems = p->mLegendGroupElements; QList::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& 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& 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 layerMap; projectLayerMap( layerMap ); QgsMapLayer* currentLayer = 0; QStringList wfsIdList = wfsLayers(); QStringList::const_iterator wfsIdIt = wfsIdList.constBegin(); for ( ; wfsIdIt != wfsIdList.constEnd(); ++wfsIdIt ) { QMap::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 QgsServerProjectParser::publishedComposerElements() const { QList 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 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 ); } } } }