Skip to content

Commit

Permalink
Support embedded layers and groups in server
Browse files Browse the repository at this point in the history
  • Loading branch information
Marco Hugentobler authored and mhugent committed Jun 9, 2011
1 parent 71d96a2 commit 0735436
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 34 deletions.
3 changes: 1 addition & 2 deletions src/mapserver/qgis_map_serv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ int main( int argc, char * argv[] )

//create config cache and search for config files in the current directory.
//These configurations are used if no mapfile parameter is present in the request
QgsConfigCache configCache;
QString defaultConfigFilePath;
QFileInfo projectFileInfo = defaultProjectFile(); //try to find a .qgs file in the server directory
if ( projectFileInfo.exists() )
Expand Down Expand Up @@ -245,7 +244,7 @@ int main( int argc, char * argv[] )
configFilePath = mapFileIt->second;
}

QgsConfigParser* adminConfigParser = configCache.searchConfiguration( configFilePath );
QgsConfigParser* adminConfigParser = QgsConfigCache::instance()->searchConfiguration( configFilePath );
if ( !adminConfigParser )
{
QgsMSDebugMsg( "parse error on config file " + configFilePath );
Expand Down
11 changes: 11 additions & 0 deletions src/mapserver/qgsconfigcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@
#include "qgssldparser.h"
#include <QCoreApplication>

QgsConfigCache* QgsConfigCache::mInstance = 0;

QgsConfigCache* QgsConfigCache::instance()
{
if ( !mInstance )
{
mInstance = new QgsConfigCache();
}
return mInstance;
}

QgsConfigCache::QgsConfigCache()
{
QObject::connect( &mFileSystemWatcher, SIGNAL( fileChanged( const QString& ) ), this, SLOT( removeChangedEntry( const QString& ) ) );
Expand Down
7 changes: 6 additions & 1 deletion src/mapserver/qgsconfigcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ class QgsConfigCache: public QObject
{
Q_OBJECT
public:
QgsConfigCache();
static QgsConfigCache* instance();
~QgsConfigCache();

/**Returns configuration for given config file path. The calling function does _not_ take ownership*/
QgsConfigParser* searchConfiguration( const QString& filePath );

protected:
QgsConfigCache();

private:
static QgsConfigCache* mInstance;

/**Creates configuration parser depending on the file type and, if successfull, inserts it to the cached configuration map
@param filePath path of the configuration file
@return the inserted config parser or 0 in case of error*/
Expand Down
194 changes: 163 additions & 31 deletions src/mapserver/qgsprojectparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsprojectparser.h"
#include "qgsconfigcache.h"
#include "qgsepsgcache.h"
#include "qgsmslayercache.h"
#include "qgsmapserverlogger.h"
Expand Down Expand Up @@ -143,7 +144,43 @@ void QgsProjectParser::addLayers( QDomDocument &doc,
titleElem.appendChild( titleText );
layerElem.appendChild( titleElem );

addLayers( doc, layerElem, currentChildElem, layerMap, nonIdentifiableLayers, mapExtent, mapCRS );
if( currentChildElem.attribute("embedded") == "1" )
{
//add layers from other project files and embed into this group
QString project = convertToAbsolutePath( currentChildElem.attribute("project") );
QString embeddedGroupName = currentChildElem.attribute("name");
QgsProjectParser* p = dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( project ) );
if( p )
{
QStringList pIdDisabled = p->identifyDisabledLayers();

QDomElement embeddedGroupElem;
QList<QDomElement> pLegendElems = p->legendGroupElements();
QList<QDomElement>::const_iterator pLegendIt = pLegendElems.constBegin();
for(; pLegendIt != pLegendElems.constEnd(); ++pLegendIt )
{
if( pLegendIt->attribute("name") == embeddedGroupName )
{
embeddedGroupElem = *pLegendIt;
break;
}
}

QList<QDomElement> pLayerElems = p->projectLayerElements();
QMap<QString, QgsMapLayer *> pLayerMap;
QList<QDomElement>::const_iterator pLayerIt = pLayerElems.constBegin();
for(; pLayerIt != pLayerElems.constEnd(); ++pLayerIt )
{
pLayerMap.insert( layerId( *pLayerIt ), p->createLayerFromElement( *pLayerIt ) );
}

p->addLayers( doc, layerElem, embeddedGroupElem, pLayerMap, pIdDisabled, mapExtent, mapCRS);
}
}
else //normal (not embedded) legend group
{
addLayers( doc, layerElem, currentChildElem, layerMap, nonIdentifiableLayers, mapExtent, mapCRS );
}

// combine bounding boxes of childs (groups/layers)

Expand Down Expand Up @@ -283,7 +320,6 @@ void QgsProjectParser::addLayers( QDomDocument &doc,
QList<QgsMapLayer*> QgsProjectParser::mapLayerFromStyle( const QString& lName, const QString& styleName, bool allowCaching ) const
{
QList<QgsMapLayer*> layerList;
bool layerFound = false;

//first assume lName refers to a leaf layer
QMap< QString, QDomElement > layerElemMap = projectLayerElementsByName();
Expand All @@ -294,18 +330,11 @@ QList<QgsMapLayer*> QgsProjectParser::mapLayerFromStyle( const QString& lName, c
if ( layer )
{
layerList.push_back( layer );
return layerList;
}
layerFound = true;
}

if ( layerFound )
{
return layerList;
}

//Check if layer name refers to the top level group for the project.
//The project group is not contained in the groupLayerRelationship list
//because the list (and the qgis legend) does not support nested groups
if ( lName == projectTitle() )
{
QList<QDomElement> layerElemList = projectLayerElements();
Expand All @@ -326,18 +355,110 @@ QList<QgsMapLayer*> QgsProjectParser::mapLayerFromStyle( const QString& lName, c
{
if ( groupIt->attribute( "name" ) == lName )
{
QDomNodeList layerFileList = groupIt->elementsByTagName( "legendlayerfile" );
for ( int i = 0; i < layerFileList.size(); ++i )
if( groupIt->attribute("embedded") == "1") //requested group is embedded from another project
{
QMap< QString, QDomElement >::const_iterator layerEntry = idLayerMap.find( layerFileList.at( i ).toElement().attribute( "layerid" ) );
if ( layerEntry != idLayerMap.constEnd() )
QgsProjectParser* p = dynamic_cast<QgsProjectParser*>(QgsConfigCache::instance()->searchConfiguration( convertToAbsolutePath(groupIt->attribute("project") ) ) );
if( p )
{
layerList.push_back( createLayerFromElement( layerEntry.value() ) );
QList<QDomElement> pGroupElems = p->legendGroupElements();
QList<QDomElement>::const_iterator pGroupIt = pGroupElems.constBegin();
QDomElement embeddedGroupElem;

for(; pGroupIt != pGroupElems.constEnd(); ++pGroupIt )
{
if( pGroupIt->attribute("name") == lName )
{
embeddedGroupElem = *pGroupIt;
break;
}
}

if( !embeddedGroupElem.isNull() )
{
//add all the layers under the group
QMap< QString, QDomElement > pLayerElems = p->projectLayerElementsById();
QDomNodeList pLayerNodes = embeddedGroupElem.elementsByTagName("legendlayer");
for( int i = 0; i < pLayerNodes.size(); ++i )
{
QString pLayerId = pLayerNodes.at(i).toElement().firstChildElement("filegroup").firstChildElement("legendlayerfile").attribute("layerid");
QgsMapLayer* pLayer = p->createLayerFromElement( pLayerElems[pLayerId] );
if( pLayer )
{
layerList.push_back( pLayer );
}
}
}
}
}
else //normal (not embedded) group
{
QDomNodeList layerFileList = groupIt->elementsByTagName( "legendlayerfile" );
for ( int i = 0; i < layerFileList.size(); ++i )
{
QMap< QString, QDomElement >::const_iterator layerEntry = idLayerMap.find( layerFileList.at( i ).toElement().attribute( "layerid" ) );
if ( layerEntry != idLayerMap.constEnd() )
{
layerList.push_back( createLayerFromElement( layerEntry.value() ) );
}
}
}
return layerList;
}
}

//maybe the layer is embedded from another project
QMap< QString, QDomElement >::const_iterator layerIt = idLayerMap.constBegin();
for(; layerIt != idLayerMap.constEnd(); ++layerIt )
{
if( layerIt.value().attribute("embedded") == "1" )
{
QString id = layerIt.value().attribute("id");
QString project = layerIt.value().attribute("project");

//get config parser from cache
QgsProjectParser* otherParser = dynamic_cast<QgsProjectParser*>(QgsConfigCache::instance()->searchConfiguration( project ) );
if( otherParser )
{
//get element by id
QMap< QString, QDomElement > otherLayerElems = otherParser->projectLayerElementsById();
QMap< QString, QDomElement >::const_iterator otherLayerIt = otherLayerElems.find( id );
if( otherLayerIt != otherLayerElems.constEnd() )
{
if( otherLayerIt.value().firstChildElement("layername").text() == lName )
{
layerList.push_back( otherParser->createLayerFromElement( otherLayerIt.value() ) );
return layerList;
}
}
}
}
}

//layer still not found. Check if it is a single layer contained in a embedded layer group
groupIt = legendGroups.constBegin();
for(; groupIt != legendGroups.constEnd(); ++groupIt )
{
if( groupIt->attribute("embedded") == "1")
{
QgsProjectParser* p = dynamic_cast<QgsProjectParser*>(QgsConfigCache::instance()->searchConfiguration( convertToAbsolutePath(groupIt->attribute("project") ) ) );
if( p )
{
QMap< QString, QDomElement > pLayers = p->projectLayerElementsByName();
QMap< QString, QDomElement >::const_iterator pLayerIt = pLayers.find( lName );
if( pLayerIt != pLayers.constEnd() )
{
QgsMapLayer* layer = p->createLayerFromElement( pLayerIt.value() );
if( layer )
{
layerList.push_back( layer );
return layerList;
}
}
}
}
}

//layer not found, return empty list
return layerList;
}

Expand Down Expand Up @@ -728,27 +849,22 @@ QgsMapLayer* QgsProjectParser::createLayerFromElement( const QDomElement& elem )
return 0;
}

QString uri;
QString absoluteUri;
QDomElement dataSourceElem = elem.firstChildElement( "datasource" );
if ( dataSourceElem.isNull() )
if ( !dataSourceElem.isNull() )
{
return 0;
}

//convert relative pathes to absolute ones if necessary
QString uri = dataSourceElem.text();
QString absoluteUri = convertToAbsolutePath( uri );
if ( uri != absoluteUri )
{
QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
//convert relative pathes to absolute ones if necessary
uri = dataSourceElem.text();
absoluteUri = convertToAbsolutePath( uri );
if ( uri != absoluteUri )
{
QDomText absoluteTextNode = mXMLDoc->createTextNode( absoluteUri );
dataSourceElem.replaceChild( absoluteTextNode, dataSourceElem.firstChild() );
}
}

QString id = layerId( elem );
if ( id.isNull() )
{
return 0;
}

QgsMapLayer* layer = QgsMSLayerCache::instance()->searchLayer( absoluteUri, id );
if ( layer )
{
Expand All @@ -767,6 +883,22 @@ QgsMapLayer* QgsProjectParser::createLayerFromElement( const QDomElement& elem )
{
layer = new QgsRasterLayer();
}
else if ( elem.attribute("embedded") == "1" ) //layer is embedded from another project file
{
QgsProjectParser* otherConfig = dynamic_cast<QgsProjectParser*>( QgsConfigCache::instance()->searchConfiguration( convertToAbsolutePath( elem.attribute( "project" ) ) ) );
if( !otherConfig )
{
return 0;
}

QMap< QString, QDomElement > layerMap = otherConfig->projectLayerElementsById();
QMap< QString, QDomElement >::const_iterator layerIt = layerMap.find( elem.attribute( "id" ) );
if( layerIt == layerMap.constEnd() )
{
return 0;
}
return otherConfig->createLayerFromElement( layerIt.value() );
}

if ( layer )
{
Expand Down

0 comments on commit 0735436

Please sign in to comment.