Skip to content

Commit

Permalink
fix leak on loading layer definition (also fixes #12064)
Browse files Browse the repository at this point in the history
  • Loading branch information
jef-n committed Feb 9, 2015
1 parent e425372 commit ee50520
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 40 deletions.
30 changes: 16 additions & 14 deletions python/core/layertree/qgslayertreenode.sip
Expand Up @@ -72,51 +72,53 @@ class QgsLayerTreeNode : QObject
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
NodeType nodeType();
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
QgsLayerTreeNode* parent();
QgsLayerTreeNode *parent();
//! Get list of children of the node. Children are owned by the parent
QList<QgsLayerTreeNode*> children();

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

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

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

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

/** Set a custom property for the node. Properties are stored in a map and saved in project file. */
void setCustomProperty( const QString& key, const QVariant& value );
void setCustomProperty( const QString &key, const QVariant &value );
/** Read a custom property from layer. Properties are stored in a map and saved in project file. */
QVariant customProperty( const QString& key, const QVariant& defaultValue = QVariant() ) const;
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
/** Remove a custom property from layer. Properties are stored in a map and saved in project file. */
void removeCustomProperty( const QString& key );
void removeCustomProperty( const QString &key );
/** Return list of keys stored in custom properties */
QStringList customProperties() const;
/** Remove a child from a node */
bool takeChild( QgsLayerTreeNode *node );

signals:

//! Emitted when one or more nodes will be added to a node within the tree
void willAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void willAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes have been added to a node within the tree
void addedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void addedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes will be removed from a node within the tree
void willRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void willRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes has been removed from a node within the tree
void removedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when check state of a node within the tree has been changed
void visibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
//! Emitted when a custom property of a node within the tree has been changed or removed
void customPropertyChanged( QgsLayerTreeNode* node, QString key );
void customPropertyChanged( QgsLayerTreeNode *node, QString key );
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
void expandedChanged( QgsLayerTreeNode* node, bool expanded );
void expandedChanged( QgsLayerTreeNode *node, bool expanded );

protected:

Expand Down
22 changes: 18 additions & 4 deletions src/core/layertree/qgslayertreenode.cpp
Expand Up @@ -113,7 +113,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
if ( nodes.count() == 0 )
return;

foreach ( QgsLayerTreeNode* node, nodes )
foreach ( QgsLayerTreeNode *node, nodes )
{
Q_ASSERT( node->mParent == 0 );
node->mParent = this;
Expand All @@ -140,7 +140,7 @@ void QgsLayerTreeNode::insertChildrenPrivate( int index, QList<QgsLayerTreeNode*
emit addedChildren( this, index, indexTo );
}

void QgsLayerTreeNode::removeChildrenPrivate( int from, int count )
void QgsLayerTreeNode::removeChildrenPrivate( int from, int count, bool destroy )
{
if ( from < 0 || count <= 0 )
return;
Expand All @@ -151,9 +151,23 @@ void QgsLayerTreeNode::removeChildrenPrivate( int from, int count )
emit willRemoveChildren( this, from, to );
while ( --count >= 0 )
{
QgsLayerTreeNode* node = mChildren.takeAt( from );
QgsLayerTreeNode *node = mChildren.takeAt( from );
node->mParent = 0;
delete node;
if ( destroy )
delete node;
}
emit removedChildren( this, from, to );
}

bool QgsLayerTreeNode::takeChild( QgsLayerTreeNode *node )
{
int index = mChildren.indexOf( node );
if ( index < 0 )
return false;

int n = mChildren.size();

removeChildrenPrivate( index, 1, false );

return mChildren.size() < n;
}
41 changes: 21 additions & 20 deletions src/core/layertree/qgslayertreenode.h
Expand Up @@ -79,73 +79,74 @@ class CORE_EXPORT QgsLayerTreeNode : public QObject
//! Find out about type of the node. It is usually shorter to use convenience functions from QgsLayerTree namespace for that
NodeType nodeType() { return mNodeType; }
//! Get pointer to the parent. If parent is a null pointer, the node is a root node
QgsLayerTreeNode* parent() { return mParent; }
QgsLayerTreeNode *parent() { return mParent; }
//! Get list of children of the node. Children are owned by the parent
QList<QgsLayerTreeNode*> children() { return mChildren; }

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

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

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

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

/** Set a custom property for the node. Properties are stored in a map and saved in project file. */
void setCustomProperty( const QString& key, const QVariant& value );
void setCustomProperty( const QString &key, const QVariant &value );
/** Read a custom property from layer. Properties are stored in a map and saved in project file. */
QVariant customProperty( const QString& key, const QVariant& defaultValue = QVariant() ) const;
QVariant customProperty( const QString &key, const QVariant &defaultValue = QVariant() ) const;
/** Remove a custom property from layer. Properties are stored in a map and saved in project file. */
void removeCustomProperty( const QString& key );
void removeCustomProperty( const QString &key );
/** Return list of keys stored in custom properties */
QStringList customProperties() const;
/** Remove a child from a node */
bool takeChild( QgsLayerTreeNode *node );

signals:

//! Emitted when one or more nodes will be added to a node within the tree
void willAddChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void willAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes have been added to a node within the tree
void addedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void addedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes will be removed from a node within the tree
void willRemoveChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void willRemoveChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when one or more nodes has been removed from a node within the tree
void removedChildren( QgsLayerTreeNode* node, int indexFrom, int indexTo );
void removedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
//! Emitted when check state of a node within the tree has been changed
void visibilityChanged( QgsLayerTreeNode* node, Qt::CheckState state );
void visibilityChanged( QgsLayerTreeNode *node, Qt::CheckState state );
//! Emitted when a custom property of a node within the tree has been changed or removed
void customPropertyChanged( QgsLayerTreeNode* node, QString key );
void customPropertyChanged( QgsLayerTreeNode *node, QString key );
//! Emitted when the collapsed/expanded state of a node within the tree has been changed
void expandedChanged( QgsLayerTreeNode* node, bool expanded );
void expandedChanged( QgsLayerTreeNode *node, bool expanded );

protected:

QgsLayerTreeNode( NodeType t );
QgsLayerTreeNode( const QgsLayerTreeNode& other );
QgsLayerTreeNode( const QgsLayerTreeNode &other );

// low-level utility functions

void readCommonXML( QDomElement& element );
void writeCommonXML( QDomElement& element );
void readCommonXML( QDomElement &element );
void writeCommonXML( QDomElement &element );

//! Low-level insertion of children to the node. The children must not have any parent yet!
void insertChildrenPrivate( int index, QList<QgsLayerTreeNode*> nodes );
//! Low-level removal of children from the node.
void removeChildrenPrivate( int from, int count );

void removeChildrenPrivate( int from, int count, bool destroy = true );

protected:
//! type of the node - determines which subclass is used
NodeType mNodeType;
//! pointer to the parent node - null in case of root node
QgsLayerTreeNode* mParent;
QgsLayerTreeNode *mParent;
//! list of children - node is responsible for their deletion
QList<QgsLayerTreeNode*> mChildren;
//! whether the node should be shown in GUI as expanded
Expand Down
10 changes: 8 additions & 2 deletions src/core/qgslayerdefinition.cpp
Expand Up @@ -37,7 +37,8 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
{
Q_UNUSED( errorMessage );

QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
QgsLayerTreeGroup *root = new QgsLayerTreeGroup();

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

QList<QgsLayerTreeNode*> nodes = root->children();
foreach ( QgsLayerTreeNode *node, nodes )
root->takeChild( node );
delete root;

rootGroup->insertChildNodes( -1, nodes );

return true;

}
Expand All @@ -91,7 +97,7 @@ bool QgsLayerDefinition::exportLayerDefinition( QString path, QList<QgsLayerTree
QDomDocument doc( "qgis-layer-definition" );
QDomElement qgiselm = doc.createElement( "qlr" );
doc.appendChild( qgiselm );
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
QgsLayerTreeGroup* root = new QgsLayerTreeGroup;
foreach ( QgsLayerTreeNode* node, nodes )
{
Expand Down

0 comments on commit ee50520

Please sign in to comment.