Skip to content

Commit

Permalink
Add API to "expand" out group layer children when querying QgsMapSett…
Browse files Browse the repository at this point in the history
…ings

for layers

There's two reasons why someone would be calling this method:
- to determine which layers should be rendered by a render job
- to determine which layers are actually visible in the map

Depending on which is required, we either want to expand out
groups and remove the group layer itself from the list (or not)
  • Loading branch information
nyalldawson committed Nov 23, 2021
1 parent 9749706 commit a5b9c7b
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 9 deletions.
10 changes: 8 additions & 2 deletions python/core/auto_generated/qgsmapsettings.sip.in
Expand Up @@ -234,23 +234,29 @@ Returns the magnification factor.
.. versionadded:: 2.16
%End

QStringList layerIds() const;
QStringList layerIds( bool expandGroupLayers = false ) const;
%Docstring
Returns the list of layer IDs which will be rendered in the map.

The layers are stored in the reverse order of how they are rendered (layer with index 0 will be on top).

Since QGIS 3.24, if the ``expandGroupLayers`` option is ``True`` then group layers will be converted to
all their child layers.

.. seealso:: :py:func:`layers`

.. seealso:: :py:func:`setLayers`
%End

QList<QgsMapLayer *> layers() const;
QList<QgsMapLayer *> layers( bool expandGroupLayers = false ) const;
%Docstring
Returns the list of layers which will be rendered in the map.

The layers are stored in the reverse order of how they are rendered (layer with index 0 will be on top)

Since QGIS 3.24, if the ``expandGroupLayers`` option is ``True`` then group layers will be converted to
all their child layers.

.. seealso:: :py:func:`setLayers`

.. seealso:: :py:func:`layerIds`
Expand Down
38 changes: 33 additions & 5 deletions src/core/qgsmapsettings.cpp
Expand Up @@ -27,6 +27,7 @@
#include "qgsxmlutils.h"
#include "qgsexception.h"
#include "qgsgeometry.h"
#include "qgsgrouplayer.h"

Q_GUI_EXPORT extern int qt_defaultDpiX();

Expand Down Expand Up @@ -285,15 +286,42 @@ void QgsMapSettings::setDpiTarget( double dpi )
mDpiTarget = dpi;
}

QStringList QgsMapSettings::layerIds() const
QStringList QgsMapSettings::layerIds( bool expandGroupLayers ) const
{
return _qgis_listQPointerToIDs( mLayers );
const QList<QgsMapLayer * > mapLayers = layers( expandGroupLayers );
QStringList res;
res.reserve( mapLayers.size() );
for ( const QgsMapLayer *layer : mapLayers )
res << layer->id();
return res;
}


QList<QgsMapLayer *> QgsMapSettings::layers() const
QList<QgsMapLayer *> QgsMapSettings::layers( bool expandGroupLayers ) const
{
return _qgis_listQPointerToRaw( mLayers );
const QList<QgsMapLayer *> actualLayers = _qgis_listQPointerToRaw( mLayers );
if ( !expandGroupLayers )
return actualLayers;

QList< QgsMapLayer * > result;

std::function< void( const QList< QgsMapLayer * >& layers ) > expandLayers;
expandLayers = [&result, &expandLayers]( const QList< QgsMapLayer * > &layers )
{
for ( QgsMapLayer *layer : layers )
{
if ( QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( layer ) )
{
expandLayers( groupLayer->childLayers() );
}
else
{
result << layer;
}
}
};

expandLayers( actualLayers );
return result;
}

void QgsMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
Expand Down
10 changes: 8 additions & 2 deletions src/core/qgsmapsettings.h
Expand Up @@ -244,20 +244,26 @@ class CORE_EXPORT QgsMapSettings : public QgsTemporalRangeObject
*
* The layers are stored in the reverse order of how they are rendered (layer with index 0 will be on top).
*
* Since QGIS 3.24, if the \a expandGroupLayers option is TRUE then group layers will be converted to
* all their child layers.
*
* \see layers()
* \see setLayers()
*/
QStringList layerIds() const;
QStringList layerIds( bool expandGroupLayers = false ) const;

/**
* Returns the list of layers which will be rendered in the map.
*
* The layers are stored in the reverse order of how they are rendered (layer with index 0 will be on top)
*
* Since QGIS 3.24, if the \a expandGroupLayers option is TRUE then group layers will be converted to
* all their child layers.
*
* \see setLayers()
* \see layerIds()
*/
QList<QgsMapLayer *> layers() const;
QList<QgsMapLayer *> layers( bool expandGroupLayers = false ) const;

/**
* Sets the list of \a layers to render in the map.
Expand Down
37 changes: 37 additions & 0 deletions tests/src/core/testqgsmapsettings.cpp
Expand Up @@ -31,6 +31,7 @@
#include "qgsexpressioncontextutils.h"
#include "qgsrenderedfeaturehandlerinterface.h"
#include "qgsrendercontext.h"
#include "qgsgrouplayer.h"

class TestHandler : public QgsRenderedFeatureHandlerInterface
{
Expand Down Expand Up @@ -66,6 +67,7 @@ class TestQgsMapSettings: public QObject
void testClippingRegions();
void testComputeExtentForScale();
void testComputeScaleForExtent();
void testLayersWithGroupLayers();

private:
QString toString( const QPolygonF &p, int decimalPlaces = 2 ) const;
Expand Down Expand Up @@ -685,5 +687,40 @@ void TestQgsMapSettings::testComputeScaleForExtent()
QGSCOMPARENEAR( scale, testScale, 0.001 );
}

void TestQgsMapSettings::testLayersWithGroupLayers()
{
// test retrieving layers from map settings when a QgsGroupLayer is present
QgsMapSettings settings;

std::unique_ptr< QgsVectorLayer > vlA = std::make_unique< QgsVectorLayer >( QStringLiteral( "Point" ), QStringLiteral( "a" ), QStringLiteral( "memory" ) );
std::unique_ptr< QgsVectorLayer > vlB = std::make_unique< QgsVectorLayer >( QStringLiteral( "Point" ), QStringLiteral( "b" ), QStringLiteral( "memory" ) );
std::unique_ptr< QgsVectorLayer > vlC = std::make_unique< QgsVectorLayer >( QStringLiteral( "Point" ), QStringLiteral( "c" ), QStringLiteral( "memory" ) );

QgsGroupLayer::LayerOptions options( ( QgsCoordinateTransformContext() ) );
QgsGroupLayer groupLayer( QStringLiteral( "group" ), options );
groupLayer.setChildLayers( { vlB.get(), vlC.get() } );
settings.setLayers( { vlA.get(), &groupLayer } );

// without expanding groups
QCOMPARE( settings.layers().size(), 2 );
QCOMPARE( settings.layers().at( 0 ), vlA.get() );
QCOMPARE( settings.layers().at( 1 ), &groupLayer );

QCOMPARE( settings.layerIds().size(), 2 );
QCOMPARE( settings.layerIds().at( 0 ), vlA->id() );
QCOMPARE( settings.layerIds().at( 1 ), groupLayer.id() );

// with expanding groups
QCOMPARE( settings.layers( true ).size(), 3 );
QCOMPARE( settings.layers( true ).at( 0 ), vlA.get() );
QCOMPARE( settings.layers( true ).at( 1 ), vlB.get() );
QCOMPARE( settings.layers( true ).at( 2 ), vlC.get() );

QCOMPARE( settings.layerIds( true ).size(), 3 );
QCOMPARE( settings.layerIds( true ).at( 0 ), vlA->id() );
QCOMPARE( settings.layerIds( true ).at( 1 ), vlB->id() );
QCOMPARE( settings.layerIds( true ).at( 2 ), vlC->id() );
}

QGSTEST_MAIN( TestQgsMapSettings )
#include "testqgsmapsettings.moc"

0 comments on commit a5b9c7b

Please sign in to comment.