Skip to content

Commit

Permalink
Ensure QgsLayerTree::layerOrder correctly respects any layer tree groups
Browse files Browse the repository at this point in the history
with QgsGroupLayers associated to them
  • Loading branch information
nyalldawson committed Nov 23, 2021
1 parent 921541d commit 9749706
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 23 deletions.
2 changes: 2 additions & 0 deletions python/core/auto_generated/layertree/qgslayertreegroup.sip.in
Expand Up @@ -128,6 +128,8 @@ Find layer node representing the map layer specified by its ID. Searches recursi
Find all layer nodes. Searches recursively the whole sub-tree.
%End



QStringList findLayerIds() const;
%Docstring
Find layer IDs used in all layer nodes. Searches recursively the whole sub-tree.
Expand Down
13 changes: 1 addition & 12 deletions src/core/layertree/qgslayertree.cpp
Expand Up @@ -80,18 +80,7 @@ QList<QgsMapLayer *> QgsLayerTree::layerOrder() const
}
else
{
QList<QgsMapLayer *> layers;
const QList< QgsLayerTreeLayer * > foundLayers = findLayers();
for ( const auto &treeLayer : foundLayers )
{
QgsMapLayer *layer = treeLayer->layer();
if ( !layer || !layer->isSpatial() )
{
continue;
}
layers.append( layer );
}
return layers;
return layerOrderRespectingGroupLayers();
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/core/layertree/qgslayertreegroup.cpp
Expand Up @@ -259,6 +259,34 @@ QList<QgsLayerTreeLayer *> QgsLayerTreeGroup::findLayers() const
return list;
}

QList<QgsMapLayer *> QgsLayerTreeGroup::layerOrderRespectingGroupLayers() const
{
QList<QgsMapLayer *> list;
for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
{
if ( QgsLayerTree::isLayer( child ) )
{
QgsMapLayer *layer = QgsLayerTree::toLayer( child )->layer();
if ( !layer || !layer->isSpatial() )
continue;
list << layer;
}
else if ( QgsLayerTree::isGroup( child ) )
{
QgsLayerTreeGroup *group = QgsLayerTree::toGroup( child );
if ( group->groupLayer() )
{
list << group->groupLayer();
}
else
{
list << group->layerOrderRespectingGroupLayers();
}
}
}
return list;
}

QgsLayerTreeGroup *QgsLayerTreeGroup::findGroup( const QString &name )
{
for ( QgsLayerTreeNode *child : std::as_const( mChildren ) )
Expand Down
9 changes: 9 additions & 0 deletions src/core/layertree/qgslayertreegroup.h
Expand Up @@ -145,6 +145,15 @@ class CORE_EXPORT QgsLayerTreeGroup : public QgsLayerTreeNode
*/
QList<QgsLayerTreeLayer *> findLayers() const;


/**
* Returns an ordered list of map layers in the group, ignoring any layers which are child layers of QgsGroupLayers. Searches recursively the whole sub-tree.
*
* \since QGIS 3.24
* \note Not available in Python bindings
*/
QList<QgsMapLayer *> layerOrderRespectingGroupLayers() const SIP_SKIP;

/**
* Find layer IDs used in all layer nodes. Searches recursively the whole sub-tree.
*/
Expand Down
54 changes: 43 additions & 11 deletions tests/src/python/test_qgslayertree.py
Expand Up @@ -246,21 +246,21 @@ def test_group_layer_updates_from_node(self):
self.assertEqual(group_layer.childLayers(), [layer])

layer2 = QgsVectorLayer("Point?field=fldtxt:string",
"layer2", "memory")
"layer2", "memory")
group_node.insertLayer(0, layer2)
self.assertEqual(group_layer.childLayers(), [layer, layer2])

layer3 = QgsVectorLayer("Point?field=fldtxt:string",
"layer3", "memory")
"layer3", "memory")
layer4 = QgsVectorLayer("Point?field=fldtxt:string",
"layer4", "memory")
"layer4", "memory")
layer3_node = QgsLayerTreeLayer(layer3)
layer4_node = QgsLayerTreeLayer(layer4)
group_node.insertChildNodes(1, [layer3_node, layer4_node])
self.assertEqual(group_layer.childLayers(), [layer, layer4, layer3, layer2])

layer5 = QgsVectorLayer("Point?field=fldtxt:string",
"layer5", "memory")
"layer5", "memory")
layer5_node = QgsLayerTreeLayer(layer5)
group_node.addChildNode(layer5_node)
self.assertEqual(group_layer.childLayers(), [layer5, layer, layer4, layer3, layer2])
Expand All @@ -271,7 +271,7 @@ def test_group_layer_updates_from_node(self):
group_node.removeLayer(layer)
self.assertEqual(group_layer.childLayers(), [layer5, layer4, layer2])

group_node.removeChildren(0,2)
group_node.removeChildren(0, 2)
self.assertEqual(group_layer.childLayers(), [layer5])

group_node.removeAllChildren()
Expand All @@ -290,10 +290,10 @@ def test_group_layer_updates_from_node_visibility(self):
"layer1", "memory")
group_node.addLayer(layer)
layer2 = QgsVectorLayer("Point?field=fldtxt:string",
"layer2", "memory")
"layer2", "memory")
layer2_node = group_node.addLayer(layer2)
layer3 = QgsVectorLayer("Point?field=fldtxt:string",
"layer3", "memory")
"layer3", "memory")
group_node.addLayer(layer3)
self.assertEqual(group_layer.childLayers(), [layer3, layer2, layer])

Expand All @@ -317,21 +317,21 @@ def test_group_layer_nested(self):
group_node.addLayer(layer)
group2 = group_node.addGroup('child group 1')
layer2 = QgsVectorLayer("Point?field=fldtxt:string",
"layer2", "memory")
"layer2", "memory")
group_node.addLayer(layer2)

layer3 = QgsVectorLayer("Point?field=fldtxt:string",
"layer3", "memory")
"layer3", "memory")
layer3_node = group2.addLayer(layer3)

group3 = group2.addGroup('grand child group 1')
group4 = group2.addGroup('grand child group 2')

layer4 = QgsVectorLayer("Point?field=fldtxt:string",
"layer4", "memory")
"layer4", "memory")
layer4_node = group3.addLayer(layer4)
layer5 = QgsVectorLayer("Point?field=fldtxt:string",
"layer5", "memory")
"layer5", "memory")
layer5_node = group4.addLayer(layer5)

self.assertEqual(group_layer.childLayers(), [layer2, layer5, layer4, layer3, layer])
Expand All @@ -344,6 +344,38 @@ def test_group_layer_nested(self):
group2.setItemVisibilityCheckedRecursive(True)
self.assertEqual(group_layer.childLayers(), [layer2, layer5, layer4, layer3, layer])

def test_layer_order_with_group_layer(self):
"""
Test retrieving layer order with group layers present
"""
p = QgsProject()
layer = QgsVectorLayer("Point?field=fldtxt:string",
"layer1", "memory")
p.addMapLayer(layer, False)
layer2 = QgsVectorLayer("Point?field=fldtxt:string",
"layer2", "memory")
p.addMapLayer(layer2, False)
layer3 = QgsVectorLayer("Point?field=fldtxt:string",
"layer3", "memory")
p.addMapLayer(layer3, False)
layer4 = QgsVectorLayer("Point?field=fldtxt:string",
"layer4", "memory")
p.addMapLayer(layer4, False)

p.layerTreeRoot().addLayer(layer)
group_node = p.layerTreeRoot().addGroup('my group')
group_node.addLayer(layer2)
group_node.addLayer(layer3)
p.layerTreeRoot().addLayer(layer4)

self.assertEqual(p.layerTreeRoot().layerOrder(), [layer, layer2, layer3, layer4])

options = QgsGroupLayer.LayerOptions(QgsCoordinateTransformContext())
group_layer = group_node.convertToGroupLayer(options)
p.addMapLayer(group_layer, False)
self.assertEqual(p.layerTreeRoot().layerOrder(), [layer, group_layer, layer4])
self.assertEqual(group_layer.childLayers(), [layer3, layer2])


if __name__ == '__main__':
unittest.main()

0 comments on commit 9749706

Please sign in to comment.