Skip to content

Commit

Permalink
Fix missing indicators after they are moved to a different group
Browse files Browse the repository at this point in the history
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 8831f19
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 9 deletions.
15 changes: 15 additions & 0 deletions python/core/auto_generated/layertree/qgslayertreeutils.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand Down
9 changes: 4 additions & 5 deletions src/app/qgslayertreeviewfilterindicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreeutils.h"
#include "qgslayertreeview.h"
#include "qgsquerybuilder.h"
#include "qgsvectorlayer.h"
Expand Down Expand Up @@ -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() )
{
Expand Down Expand Up @@ -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 );
}
}
Expand Down
6 changes: 4 additions & 2 deletions src/app/qgslayertreeviewmemoryindicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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() )
Expand Down Expand Up @@ -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 );
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/app/qgslayertreeviewnonremovableindicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

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


Expand Down Expand Up @@ -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() )
Expand Down Expand Up @@ -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 );
}
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/core/layertree/qgslayertreeutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
14 changes: 14 additions & 0 deletions src/core/layertree/qgslayertreeutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 20 additions & 0 deletions tests/src/core/testqgslayertree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class TestQgsLayerTree : public QObject
void testLayerDeleted();
void testFindGroups();
void testUtilsCollectMapLayers();
void testUtilsCountMapLayers();

private:

Expand Down Expand Up @@ -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.