[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.
This commit is contained in:
Martin Dobias 2014-05-27 12:39:41 +07:00
parent bba9a99d32
commit 2df8f8c11e
5 changed files with 108 additions and 19 deletions

View File

@ -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 );
}

View File

@ -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 ) );
}
}
}

View File

@ -20,6 +20,7 @@
#include <QList>
class QDomElement;
class QDomDocument;
class QStringList;
class QgsLayerTreeGroup;
@ -38,6 +39,8 @@ 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 );
@ -45,7 +48,9 @@ class CORE_EXPORT QgsLayerTreeUtils
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 );

View File

@ -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;

View File

@ -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 & );