Skip to content

Commit 2df8f8c

Browse files
committed
[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.
1 parent bba9a99 commit 2df8f8c

File tree

5 files changed

+108
-19
lines changed

5 files changed

+108
-19
lines changed

src/app/qgisapp.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9546,6 +9546,20 @@ void QgisApp::projectChanged( const QDomDocument &doc )
95469546

95479547
void QgisApp::writeProject( QDomDocument &doc )
95489548
{
9549+
// QGIS server does not use QgsProject for loading of QGIS project.
9550+
// In order to allow reading of new projects, let's also write the original <legend> tag to the project.
9551+
// Ideally the server should be ported to new layer tree implementation, but that requires
9552+
// non-trivial changes to the server components.
9553+
// The <legend> tag is ignored by QGIS application in >= 2.4 and this way also the new project files
9554+
// can be opened in older versions of QGIS without loosing information about layer groups.
9555+
9556+
QgsLayerTreeNode* clonedRoot = QgsProject::instance()->layerTreeRoot()->clone();
9557+
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
9558+
QDomElement oldLegendElem = QgsLayerTreeUtils::writeOldLegend( doc, QgsLayerTree::toGroup( clonedRoot ),
9559+
mLayerTreeCanvasBridge->hasCustomLayerOrder(), mLayerTreeCanvasBridge->customLayerOrder() );
9560+
delete clonedRoot;
9561+
doc.firstChildElement( "qgis" ).appendChild( oldLegendElem );
9562+
95499563
projectChanged( doc );
95509564
}
95519565

src/core/layertree/qgslayertreeutils.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,79 @@ bool QgsLayerTreeUtils::readOldLegendLayerOrder( const QDomElement& legendElem,
9999
}
100100

101101

102+
static QDomElement _writeOldLegendLayer( QDomDocument& doc, QgsLayerTreeLayer* nodeLayer, bool hasCustomOrder, const QStringList& order )
103+
{
104+
int drawingOrder = -1;
105+
if ( hasCustomOrder )
106+
drawingOrder = order.indexOf( nodeLayer->layerId() );
107+
108+
QDomElement layerElem = doc.createElement( "legendlayer" );
109+
layerElem.setAttribute( "drawingOrder", drawingOrder );
110+
layerElem.setAttribute( "open", nodeLayer->isExpanded() ? "true" : "false" );
111+
layerElem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( nodeLayer->isVisible() ) );
112+
layerElem.setAttribute( "name", nodeLayer->layerName() );
113+
layerElem.setAttribute( "showFeatureCount", nodeLayer->customProperty( "showFeatureCount" ).toInt() );
114+
115+
QDomElement fileGroupElem = doc.createElement( "filegroup" );
116+
fileGroupElem.setAttribute( "open", nodeLayer->isExpanded() ? "true" : "false" );
117+
fileGroupElem.setAttribute( "hidden", "false" );
118+
119+
QDomElement layerFileElem = doc.createElement( "legendlayerfile" );
120+
layerFileElem.setAttribute( "isInOverview", nodeLayer->customProperty( "overview" ).toInt() );
121+
layerFileElem.setAttribute( "layerid", nodeLayer->layerId() );
122+
layerFileElem.setAttribute( "visible", nodeLayer->isVisible() == Qt::Checked ? 1 : 0 );
123+
124+
layerElem.appendChild( fileGroupElem );
125+
fileGroupElem.appendChild( layerFileElem );
126+
return layerElem;
127+
}
128+
129+
// need forward declaration as write[..]Group and write[..]GroupChildren call each other
130+
static void _writeOldLegendGroupChildren( QDomDocument& doc, QDomElement& groupElem, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order );
131+
132+
static QDomElement _writeOldLegendGroup( QDomDocument& doc, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order )
133+
{
134+
QDomElement groupElem = doc.createElement( "legendgroup" );
135+
groupElem.setAttribute( "open", nodeGroup->isExpanded() ? "true" : "false" );
136+
groupElem.setAttribute( "name", nodeGroup->name() );
137+
groupElem.setAttribute( "checked", QgsLayerTreeUtils::checkStateToXml( nodeGroup->isVisible() ) );
138+
139+
if ( nodeGroup->customProperty( "embedded" ).toInt() )
140+
{
141+
groupElem.setAttribute( "embedded", 1 );
142+
groupElem.setAttribute( "project", nodeGroup->customProperty( "embedded_project" ).toString() );
143+
}
144+
145+
_writeOldLegendGroupChildren( doc, groupElem, nodeGroup, hasCustomOrder, order );
146+
return groupElem;
147+
}
148+
149+
150+
static void _writeOldLegendGroupChildren( QDomDocument& doc, QDomElement& groupElem, QgsLayerTreeGroup* nodeGroup, bool hasCustomOrder, const QStringList& order )
151+
{
152+
foreach ( QgsLayerTreeNode* node, nodeGroup->children() )
153+
{
154+
if ( QgsLayerTree::isGroup( node ) )
155+
{
156+
groupElem.appendChild( _writeOldLegendGroup( doc, QgsLayerTree::toGroup( node ), hasCustomOrder, order ) );
157+
}
158+
else if ( QgsLayerTree::isLayer( node ) )
159+
{
160+
groupElem.appendChild( _writeOldLegendLayer( doc, QgsLayerTree::toLayer( node ), hasCustomOrder, order ) );
161+
}
162+
}
163+
}
164+
165+
166+
QDomElement QgsLayerTreeUtils::writeOldLegend( QDomDocument& doc, QgsLayerTreeGroup* root, bool hasCustomOrder, const QStringList& order )
167+
{
168+
QDomElement legendElem = doc.createElement( "legend" );
169+
legendElem.setAttribute( "updateDrawingOrder", hasCustomOrder ? "false" : "true" );
170+
171+
_writeOldLegendGroupChildren( doc, legendElem, root, hasCustomOrder, order );
172+
173+
return legendElem;
174+
}
102175

103176

104177
QString QgsLayerTreeUtils::checkStateToXml( Qt::CheckState state )
@@ -223,3 +296,17 @@ void QgsLayerTreeUtils::removeInvalidLayers( QgsLayerTreeGroup* group )
223296
foreach ( QgsLayerTreeNode* node, nodesToRemove )
224297
group->removeChildNode( node );
225298
}
299+
300+
void QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
301+
{
302+
foreach ( QgsLayerTreeNode* child, group->children() )
303+
{
304+
if ( QgsLayerTree::isGroup( child ) )
305+
{
306+
if ( child->customProperty( "embedded" ).toInt() )
307+
QgsLayerTree::toGroup( child )->removeAllChildren();
308+
else
309+
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
310+
}
311+
}
312+
}

src/core/layertree/qgslayertreeutils.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <QList>
2121

2222
class QDomElement;
23+
class QDomDocument;
2324
class QStringList;
2425

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

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

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

48-
static void removeInvalidLayers(QgsLayerTreeGroup* group );
51+
static void removeInvalidLayers( QgsLayerTreeGroup* group );
52+
53+
static void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
4954

5055
protected:
5156
static void addLegendGroupToTreeWidget( const QDomElement& groupElem, QgsLayerTreeGroup* parent );

src/core/qgsproject.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -995,21 +995,6 @@ void QgsProject::loadEmbeddedNodes( QgsLayerTreeGroup* group )
995995
}
996996
}
997997

998-
void QgsProject::removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group )
999-
{
1000-
foreach ( QgsLayerTreeNode* child, group->children() )
1001-
{
1002-
if ( QgsLayerTree::isGroup( child ) )
1003-
{
1004-
if ( child->customProperty( "embedded" ).toInt() )
1005-
QgsLayerTree::toGroup( child )->removeAllChildren();
1006-
else
1007-
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( child ) );
1008-
}
1009-
}
1010-
}
1011-
1012-
1013998

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

10911076
// write layer tree - make sure it is without embedded subgroups
10921077
QgsLayerTreeNode* clonedRoot = mRootGroup->clone();
1093-
removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
1078+
QgsLayerTreeUtils::removeChildrenOfEmbeddedGroups( QgsLayerTree::toGroup( clonedRoot ) );
10941079
clonedRoot->writeXML( qgisNode );
10951080
delete clonedRoot;
10961081

src/core/qgsproject.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,6 @@ class CORE_EXPORT QgsProject : public QObject
357357

358358
void loadEmbeddedNodes( QgsLayerTreeGroup* group );
359359

360-
void removeChildrenOfEmbeddedGroups( QgsLayerTreeGroup* group );
361-
362360
signals:
363361
//! emitted when project is being read
364362
void readProject( const QDomDocument & );

0 commit comments

Comments
 (0)