Skip to content
Permalink
Browse files

Fix missing indicators after they are moved to a different group

The issue was that during drag&drop, we first connect to layer's signal
for the second time, but then the disconnect() call on removal of the original
layer node would disconnect all connections (not just one). For that reason
now we only connect/disconnect when the layer is in the tree only once.
  • Loading branch information
wonder-sk committed Sep 26, 2018
1 parent 5157406 commit 8831f19b79f4f05d8d82fe8ab41327b694d6f9b3
@@ -103,6 +103,21 @@ Insert a QgsMapLayer just below another one
Returns map layers from the given list of layer tree nodes. Also recursively visits
child nodes of groups.

.. versionadded:: 3.4
%End

static int countMapLayerInTree( QgsLayerTreeNode *tree, QgsMapLayer *layer );
%Docstring
Returns how many occurences of a map layer are there in a layer tree.
In normal situations there is at most one occurence, but sometimes there
may be temporarily more: for example, during drag&drop, upon drop a new layer
node is created while the original dragged node is still in the tree, resulting
in two occurences.

This is useful when deciding whether to start or stop listening to a signal
of a map layer within a layer tree and only connecting/disconnecting when
there is only one occurence of that layer.

.. versionadded:: 3.4
%End
};
@@ -17,6 +17,7 @@

#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgsquerybuilder.h"
#include "qgsvectorlayer.h"
@@ -54,12 +55,10 @@ void QgsLayerTreeViewFilterIndicatorProvider::onAddedChildren( QgsLayerTreeNode
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
{
if ( vlayer )
{
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
connect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );

addOrRemoveIndicator( childLayerNode, vlayer );
}
addOrRemoveIndicator( childLayerNode, vlayer );
}
else if ( !childLayerNode->layer() )
{
@@ -89,7 +88,7 @@ void QgsLayerTreeViewFilterIndicatorProvider::onWillRemoveChildren( QgsLayerTree
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
{
if ( vlayer )
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
disconnect( vlayer, &QgsVectorLayer::subsetStringChanged, this, &QgsLayerTreeViewFilterIndicatorProvider::onSubsetStringChanged );
}
}
@@ -16,6 +16,7 @@
#include "qgslayertreeviewmemoryindicator.h"
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgsvectorlayer.h"
#include "qgisapp.h"
@@ -51,7 +52,8 @@ void QgsLayerTreeViewMemoryIndicatorProvider::onAddedChildren( QgsLayerTreeNode
{
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layerNode->layer() ) )
{
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), vlayer ) == 1 )
connect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
addOrRemoveIndicator( childNode, vlayer );
}
else if ( !layerNode->layer() )
@@ -82,7 +84,7 @@ void QgsLayerTreeViewMemoryIndicatorProvider::onWillRemoveChildren( QgsLayerTree
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( childLayerNode->layer() ) )
{
if ( vlayer )
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
disconnect( vlayer, &QgsVectorLayer::dataSourceChanged, this, &QgsLayerTreeViewMemoryIndicatorProvider::onDataSourceChanged );
}
}
@@ -17,6 +17,7 @@

#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"


@@ -51,7 +52,8 @@ void QgsLayerTreeViewNonRemovableIndicatorProvider::onAddedChildren( QgsLayerTre
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( QgsMapLayer *layer = childLayerNode->layer() )
{
connect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), layer ) == 1 )
connect( layer, &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
addOrRemoveIndicator( childLayerNode, layer );
}
else if ( !childLayerNode->layer() )
@@ -81,7 +83,10 @@ void QgsLayerTreeViewNonRemovableIndicatorProvider::onWillRemoveChildren( QgsLay
{
QgsLayerTreeLayer *childLayerNode = QgsLayerTree::toLayer( childNode );
if ( childLayerNode->layer() )
disconnect( childLayerNode->layer(), &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
{
if ( QgsLayerTreeUtils::countMapLayerInTree( mLayerTreeView->layerTreeModel()->rootGroup(), childLayerNode->layer() ) == 1 )
disconnect( childLayerNode->layer(), &QgsMapLayer::flagsChanged, this, &QgsLayerTreeViewNonRemovableIndicatorProvider::onFlagsChanged );
}
}
}
}
@@ -437,3 +437,19 @@ QSet<QgsMapLayer *> QgsLayerTreeUtils::collectMapLayersRecursive( const QList<Qg
_collectMapLayers( nodes, layersSet );
return layersSet;
}

int QgsLayerTreeUtils::countMapLayerInTree( QgsLayerTreeNode *tree, QgsMapLayer *layer )
{
if ( QgsLayerTree::isLayer( tree ) )
{
if ( QgsLayerTree::toLayer( tree )->layer() == layer )
return 1;
return 0;
}

int cnt = 0;
const QList<QgsLayerTreeNode *> children = tree->children();
for ( QgsLayerTreeNode *child : children )
cnt += countMapLayerInTree( child, layer );
return cnt;
}
@@ -94,6 +94,20 @@ class CORE_EXPORT QgsLayerTreeUtils
* \since QGIS 3.4
*/
static QSet<QgsMapLayer *> collectMapLayersRecursive( const QList<QgsLayerTreeNode *> &nodes );

/**
* Returns how many occurences of a map layer are there in a layer tree.
* In normal situations there is at most one occurence, but sometimes there
* may be temporarily more: for example, during drag&drop, upon drop a new layer
* node is created while the original dragged node is still in the tree, resulting
* in two occurences.
*
* This is useful when deciding whether to start or stop listening to a signal
* of a map layer within a layer tree and only connecting/disconnecting when
* there is only one occurence of that layer.
* \since QGIS 3.4
*/
static int countMapLayerInTree( QgsLayerTreeNode *tree, QgsMapLayer *layer );
};

#endif // QGSLAYERTREEUTILS_H
@@ -52,6 +52,7 @@ class TestQgsLayerTree : public QObject
void testLayerDeleted();
void testFindGroups();
void testUtilsCollectMapLayers();
void testUtilsCountMapLayers();

private:

@@ -687,6 +688,25 @@ void TestQgsLayerTree::testUtilsCollectMapLayers()
QCOMPARE( set3, QSet<QgsMapLayer *>() << vl2 );
}

void TestQgsLayerTree::testUtilsCountMapLayers()
{
QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );

QgsProject project;
project.addMapLayer( vl );

QgsLayerTree root;
QgsLayerTreeGroup *nodeGrp = root.addGroup( "grp" );

QCOMPARE( QgsLayerTreeUtils::countMapLayerInTree( &root, vl ), 0 );

root.addLayer( vl );
QCOMPARE( QgsLayerTreeUtils::countMapLayerInTree( &root, vl ), 1 );

nodeGrp->addLayer( vl );
QCOMPARE( QgsLayerTreeUtils::countMapLayerInTree( &root, vl ), 2 );
}


QGSTEST_MAIN( TestQgsLayerTree )
#include "testqgslayertree.moc"

0 comments on commit 8831f19

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