Skip to content

Commit ee50520

Browse files
committed
fix leak on loading layer definition (also fixes #12064)
1 parent e425372 commit ee50520

File tree

4 files changed

+63
-40
lines changed

4 files changed

+63
-40
lines changed

python/core/layertree/qgslayertreenode.sip

+16-14
Original file line numberDiff line numberDiff line change
@@ -72,51 +72,53 @@ class QgsLayerTreeNode : QObject
7272
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
7373
NodeType nodeType();
7474
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
75-
QgsLayerTreeNode* parent();
75+
QgsLayerTreeNode *parent();
7676
//! Get list of children of the node. Children are owned by the parent
7777
QList<QgsLayerTreeNode*> children();
7878

7979
//! Read layer tree from XML. Returns new instance
80-
static QgsLayerTreeNode* readXML( QDomElement& element );
80+
static QgsLayerTreeNode *readXML( QDomElement &element );
8181
//! Write layer tree to XML
82-
virtual void writeXML( QDomElement& parentElement ) = 0;
82+
virtual void writeXML( QDomElement &parentElement ) = 0;
8383

8484
//! Return string with layer tree structure. For debug purposes only
8585
virtual QString dump() const = 0;
8686

8787
//! Create a copy of the node. Returns new instance
88-
virtual QgsLayerTreeNode* clone() const = 0 /Factory/;
88+
virtual QgsLayerTreeNode *clone() const = 0 /Factory/;
8989

9090
//! Return whether the node should be shown as expanded or collapsed in GUI
9191
bool isExpanded() const;
9292
//! Set whether the node should be shown as expanded or collapsed in GUI
9393
void setExpanded( bool expanded );
9494

9595
/** Set a custom property for the node. Properties are stored in a map and saved in project file. */
96-
void setCustomProperty( const QString& key, const QVariant& value );
96+
void setCustomProperty( const QString &key, const QVariant &value );
9797
/** Read a custom property from layer. Properties are stored in a map and saved in project file. */
98-
QVariant customProperty( const QString& key, const QVariant& defaultValue = QVariant() ) const;
98+
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
9999
/** Remove a custom property from layer. Properties are stored in a map and saved in project file. */
100-
void removeCustomProperty( const QString& key );
100+
void removeCustomProperty( const QString &key );
101101
/** Return list of keys stored in custom properties */
102102
QStringList customProperties() const;
103+
/** Remove a child from a node */
104+
bool takeChild( QgsLayerTreeNode *node );
103105

104106
signals:
105107

106108
//! Emitted when one or more nodes will be added to a node within the tree
107-
void willAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
109+
void willAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
108110
//! Emitted when one or more nodes have been added to a node within the tree
109-
void addedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
111+
void addedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
110112
//! Emitted when one or more nodes will be removed from a node within the tree
111-
void willRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
113+
void willRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
112114
//! Emitted when one or more nodes has been removed from a node within the tree
113-
void removedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
115+
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
114116
//! Emitted when check state of a node within the tree has been changed
115-
void visibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
117+
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
116118
//! Emitted when a custom property of a node within the tree has been changed or removed
117-
void customPropertyChanged( QgsLayerTreeNode* node, QString key );
119+
void customPropertyChanged( QgsLayerTreeNode *node, QString key );
118120
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
119-
void expandedChanged( QgsLayerTreeNode* node, bool expanded );
121+
void expandedChanged( QgsLayerTreeNode *node, bool expanded );
120122

121123
protected:
122124

src/core/layertree/qgslayertreenode.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
113113
if ( nodes.count() == 0 )
114114
return;
115115

116-
foreach ( QgsLayerTreeNode* node, nodes )
116+
foreach ( QgsLayerTreeNode *node, nodes )
117117
{
118118
Q_ASSERT( node->mParent == 0 );
119119
node->mParent = this;
@@ -140,7 +140,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
140140
emit addedChildren( this, index, indexTo );
141141
}
142142

143-
void QgsLayerTreeNode::removeChildrenPrivate( int from, int count )
143+
void QgsLayerTreeNode::removeChildrenPrivate( int from, int count, bool destroy )
144144
{
145145
if ( from < 0 || count <= 0 )
146146
return;
@@ -151,9 +151,23 @@ void QgsLayerTreeNode::removeChildrenPrivate( int from, int count )
151151
emit willRemoveChildren( this, from, to );
152152
while ( --count >= 0 )
153153
{
154-
QgsLayerTreeNode* node = mChildren.takeAt( from );
154+
QgsLayerTreeNode *node = mChildren.takeAt( from );
155155
node->mParent = 0;
156-
delete node;
156+
if ( destroy )
157+
delete node;
157158
}
158159
emit removedChildren( this, from, to );
159160
}
161+
162+
bool QgsLayerTreeNode::takeChild( QgsLayerTreeNode *node )
163+
{
164+
int index = mChildren.indexOf( node );
165+
if ( index < 0 )
166+
return false;
167+
168+
int n = mChildren.size();
169+
170+
removeChildrenPrivate( index, 1, false );
171+
172+
return mChildren.size() < n;
173+
}

src/core/layertree/qgslayertreenode.h

+21-20
Original file line numberDiff line numberDiff line change
@@ -79,73 +79,74 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
7979
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
8080
NodeType nodeType() { return mNodeType; }
8181
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
82-
QgsLayerTreeNode* parent() { return mParent; }
82+
QgsLayerTreeNode *parent() { return mParent; }
8383
//! Get list of children of the node. Children are owned by the parent
8484
QList<QgsLayerTreeNode*> children() { return mChildren; }
8585

8686
//! Read layer tree from XML. Returns new instance
87-
static QgsLayerTreeNode* readXML( QDomElement& element );
87+
static QgsLayerTreeNode *readXML( QDomElement &element );
8888
//! Write layer tree to XML
89-
virtual void writeXML( QDomElement& parentElement ) = 0;
89+
virtual void writeXML( QDomElement &parentElement ) = 0;
9090

9191
//! Return string with layer tree structure. For debug purposes only
9292
virtual QString dump() const = 0;
9393

9494
//! Create a copy of the node. Returns new instance
95-
virtual QgsLayerTreeNode* clone() const = 0;
95+
virtual QgsLayerTreeNode *clone() const = 0;
9696

9797
//! Return whether the node should be shown as expanded or collapsed in GUI
9898
bool isExpanded() const;
9999
//! Set whether the node should be shown as expanded or collapsed in GUI
100100
void setExpanded( bool expanded );
101101

102102
/** Set a custom property for the node. Properties are stored in a map and saved in project file. */
103-
void setCustomProperty( const QString& key, const QVariant& value );
103+
void setCustomProperty( const QString &key, const QVariant &value );
104104
/** Read a custom property from layer. Properties are stored in a map and saved in project file. */
105-
QVariant customProperty( const QString& key, const QVariant& defaultValue = QVariant() ) const;
105+
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
106106
/** Remove a custom property from layer. Properties are stored in a map and saved in project file. */
107-
void removeCustomProperty( const QString& key );
107+
void removeCustomProperty( const QString &key );
108108
/** Return list of keys stored in custom properties */
109109
QStringList customProperties() const;
110+
/** Remove a child from a node */
111+
bool takeChild( QgsLayerTreeNode *node );
110112

111113
signals:
112114

113115
//! Emitted when one or more nodes will be added to a node within the tree
114-
void willAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
116+
void willAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
115117
//! Emitted when one or more nodes have been added to a node within the tree
116-
void addedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
118+
void addedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
117119
//! Emitted when one or more nodes will be removed from a node within the tree
118-
void willRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
120+
void willRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
119121
//! Emitted when one or more nodes has been removed from a node within the tree
120-
void removedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
122+
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
121123
//! Emitted when check state of a node within the tree has been changed
122-
void visibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
124+
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
123125
//! Emitted when a custom property of a node within the tree has been changed or removed
124-
void customPropertyChanged( QgsLayerTreeNode* node, QString key );
126+
void customPropertyChanged( QgsLayerTreeNode *node, QString key );
125127
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
126-
void expandedChanged( QgsLayerTreeNode* node, bool expanded );
128+
void expandedChanged( QgsLayerTreeNode *node, bool expanded );
127129

128130
protected:
129131

130132
QgsLayerTreeNode( NodeType t );
131-
QgsLayerTreeNode( const QgsLayerTreeNode& other );
133+
QgsLayerTreeNode( const QgsLayerTreeNode &other );
132134

133135
// low-level utility functions
134136

135-
void readCommonXML( QDomElement& element );
136-
void writeCommonXML( QDomElement& element );
137+
void readCommonXML( QDomElement &element );
138+
void writeCommonXML( QDomElement &element );
137139

138140
//! Low-level insertion of children to the node. The children must not have any parent yet!
139141
void insertChildrenPrivate( int index, QList<QgsLayerTreeNode*> nodes );
140142
//! Low-level removal of children from the node.
141-
void removeChildrenPrivate( int from, int count );
142-
143+
void removeChildrenPrivate( int from, int count, bool destroy = true );
143144

144145
protected:
145146
//! type of the node - determines which subclass is used
146147
NodeType mNodeType;
147148
//! pointer to the parent node - null in case of root node
148-
QgsLayerTreeNode* mParent;
149+
QgsLayerTreeNode *mParent;
149150
//! list of children - node is responsible for their deletion
150151
QList<QgsLayerTreeNode*> mChildren;
151152
//! whether the node should be shown in GUI as expanded

src/core/qgslayerdefinition.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
3737
{
3838
Q_UNUSED( errorMessage );
3939

40-
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
40+
QgsLayerTreeGroup *root = new QgsLayerTreeGroup();
41+
4142
// We have to replace the IDs before we load them because it's too late once they are loaded
4243
QDomNodeList ids = doc.elementsByTagName( "id" );
4344
for ( int i = 0; i < ids.size(); ++i )
@@ -75,7 +76,12 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
7576
QgsMapLayerRegistry::instance()->addMapLayers( layers, loadInLegend );
7677

7778
QList<QgsLayerTreeNode*> nodes = root->children();
79+
foreach ( QgsLayerTreeNode *node, nodes )
80+
root->takeChild( node );
81+
delete root;
82+
7883
rootGroup->insertChildNodes( -1, nodes );
84+
7985
return true;
8086

8187
}
@@ -91,7 +97,7 @@ bool QgsLayerDefinition::exportLayerDefinition( QString path, QList<QgsLayerTree
9197
QDomDocument doc( "qgis-layer-definition" );
9298
QDomElement qgiselm = doc.createElement( "qlr" );
9399
doc.appendChild( qgiselm );
94-
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
100+
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
95101
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
96102
foreach ( QgsLayerTreeNode* node, nodes )
97103
{

0 commit comments

Comments
 (0)