Skip to content
Permalink
Browse files

[layertree] Fix #10347 - save also old <legend> tag

QGIS server does not use QgsProject for loading of QGIS project.
In order to allow reading of new projects, let's also write the original <legend> tag to the project.
Ideally the server should be ported to new layer tree implementation, but that requires
non-trivial changes to the server components.
The <legend> tag is ignored by QGIS application in >= 2.4 and this way also the new project files
can be opened in older versions of QGIS without loosing information about layer groups.
  • Loading branch information
wonder-sk committed May 27, 2014
1 parent bba9a99 commit 2df8f8c11ec3c3923a14c36114e06f3ef141458a
@@ -9546,6 +9546,20 @@ void QgisApp::projectChanged( const QDomDocument &doc )

void QgisApp::writeProject( QDomDocument &doc )
{
// QGIS server does not use QgsProject for loading of QGIS project.
// In order to allow reading of new projects, let's also write the original <legend> tag to the project.
// Ideally the server should be ported to new layer tree implementation, but that requires
// non-trivial changes to the server components.
// The <legend> tag is ignored by QGIS application in >= 2.4 and this way also the new project files
// can be opened in older versions of QGIS without loosing information about layer groups.

QgsLayerTreeNode* clonedRoot = QgsProject::instance()->layerTreeRoot()->clone();
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QDomElement oldLegendElem = QgsLayerTreeUtils::writeOldLegend( doc, QgsLayerTree::toGroup( clonedRoot ),
mLayerTreeCanvasBridge->hasCustomLayerOrder(), mLayerTreeCanvasBridge->customLayerOrder() );
delete clonedRoot;
doc.firstChildElement( "qgis" ).appendChild( oldLegendElem );

projectChanged( doc );
}

@@ -99,6 +99,79 @@ bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement& legendElem,
}


static QDomElement _writeOldLegendLayer( QDomDocument& doc, QgsLayerTreeLayer* nodeLayer, bool hasCustomOrder, const QStringList& order )
{
int drawingOrder = -1;
if ( hasCustomOrder )
drawingOrder = order.indexOf( nodeLayer->layerId() );

QDomElement layerElem = doc.createElement( "legendlayer" );
layerElem.setAttribute( "drawingOrder", drawingOrder );
layerElem.setAttribute( "open", nodeLayer->isExpanded() ? "true" : "false" );
layerElem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( nodeLayer->isVisible() ) );
layerElem.setAttribute( "name", nodeLayer->layerName() );
layerElem.setAttribute( "showFeatureCount", nodeLayer->customProperty( "showFeatureCount" ).toInt() );

QDomElement fileGroupElem = doc.createElement( "filegroup" );
fileGroupElem.setAttribute( "open", nodeLayer->isExpanded() ? "true" : "false" );
fileGroupElem.setAttribute( "hidden", "false" );

QDomElement layerFileElem = doc.createElement( "legendlayerfile" );
layerFileElem.setAttribute( "isInOverview", nodeLayer->customProperty( "overview" ).toInt() );
layerFileElem.setAttribute( "layerid", nodeLayer->layerId() );
layerFileElem.setAttribute( "visible", nodeLayer->isVisible() == Qt::Checked ? 1 : 0 );

layerElem.appendChild( fileGroupElem );
fileGroupElem.appendChild( layerFileElem );
return layerElem;
}

// need forward declaration as write[..]Group and write[..]GroupChildren call each other
static void _writeOldLegendGroupChildren( QDomDocument& doc, QDomElement& groupElem, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order );

static QDomElement _writeOldLegendGroup( QDomDocument& doc, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order )
{
QDomElement groupElem = doc.createElement( "legendgroup" );
groupElem.setAttribute( "open", nodeGroup->isExpanded() ? "true" : "false" );
groupElem.setAttribute( "name", nodeGroup->name() );
groupElem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( nodeGroup->isVisible() ) );

if ( nodeGroup->customProperty( "embedded" ).toInt() )
{
groupElem.setAttribute( "embedded", 1 );
groupElem.setAttribute( "project", nodeGroup->customProperty( "embedded_project" ).toString() );
}

_writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
return groupElem;
}


static void _writeOldLegendGroupChildren( QDomDocument& doc, QDomElement& groupElem, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order )
{
foreach ( QgsLayerTreeNode* node, nodeGroup->children() )
{
if ( QgsLayerTree::isGroup( node ) )
{
groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
}
else if ( QgsLayerTree::isLayer( node ) )
{
groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
}
}
}


QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument& doc, QgsLayerTreeGroup* root, bool hasCustomOrder, const QStringList& order )
{
QDomElement legendElem = doc.createElement( "legend" );
legendElem.setAttribute( "updateDrawingOrder", hasCustomOrder ? "false" : "true" );

_writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );

return legendElem;
}


QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
@@ -223,3 +296,17 @@ void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup* group )
foreach ( QgsLayerTreeNode* node, nodesToRemove )
group->removeChildNode( node );
}

void QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
{
foreach ( QgsLayerTreeNode* child, group->children() )
{
if ( QgsLayerTree::isGroup( child ) )
{
if ( child->customProperty( "embedded" ).toInt() )
QgsLayerTree::toGroup( child )->removeAllChildren();
else
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
}
}
}
@@ -20,6 +20,7 @@
#include <QList>

class QDomElement;
class QDomDocument;
class QStringList;

class QgsLayerTreeGroup;
@@ -38,14 +39,18 @@ class CORE_EXPORT QgsLayerTreeUtils
static bool readOldLegend( QgsLayerTreeGroup* root, const QDomElement& legendElem );
//! Try to load custom layer order from <legend> tag from project files from QGIS 2.2 and below
static bool readOldLegendLayerOrder( const QDomElement& legendElem, bool& hasCustomOrder, QStringList& order );
//! Return <legend> tag used in QGIS 2.2 and below
static QDomElement writeOldLegend( QDomDocument& doc, QgsLayerTreeGroup* root, bool hasCustomOrder, const QStringList& order );

static QString checkStateToXml( Qt::CheckState state );
static Qt::CheckState checkStateFromXml( QString txt );

static bool layersEditable( const QList<QgsLayerTreeLayer*>& layerNodes );
static bool layersModified( const QList<QgsLayerTreeLayer*>& layerNodes );

static void removeInvalidLayers(QgsLayerTreeGroup* group );
static void removeInvalidLayers( QgsLayerTreeGroup* group );

static void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );

protected:
static void addLegendGroupToTreeWidget( const QDomElement& groupElem, QgsLayerTreeGroup* parent );
@@ -995,21 +995,6 @@ void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup* group )
}
}

void QgsProject::removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
{
foreach ( QgsLayerTreeNode* child, group->children() )
{
if ( QgsLayerTree::isGroup( child ) )
{
if ( child->customProperty( "embedded" ).toInt() )
QgsLayerTree::toGroup( child )->removeAllChildren();
else
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
}
}
}



bool QgsProject::read( QDomNode & layerNode )
{
@@ -1090,7 +1075,7 @@ bool QgsProject::write()

// write layer tree - make sure it is without embedded subgroups
QgsLayerTreeNode* clonedRoot = mRootGroup->clone();
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
clonedRoot->writeXML( qgisNode );
delete clonedRoot;

@@ -357,8 +357,6 @@ class CORE_EXPORT QgsProject : public QObject

void loadEmbeddedNodes( QgsLayerTreeGroup* group );

void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );

signals:
//! emitted when project is being read
void readProject( const QDomDocument & );

0 comments on commit 2df8f8c

Please sign in to comment.
You can’t perform that action at this time.