diff --git a/python/core/auto_generated/layout/qgslayoutatlas.sip.in b/python/core/auto_generated/layout/qgslayoutatlas.sip.in index d0df00ebc25..5f4d357dcc4 100644 --- a/python/core/auto_generated/layout/qgslayoutatlas.sip.in +++ b/python/core/auto_generated/layout/qgslayoutatlas.sip.in @@ -8,7 +8,7 @@ -class QgsLayoutAtlas : QObject, QgsAbstractLayoutIterator, QgsLayoutSerializableObject +class QgsLayoutAtlas : QObject, QgsAbstractLayoutIterator, QgsLayoutSerializableObject, QgsExpressionContextGenerator { %Docstring Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector layer. @@ -277,6 +277,9 @@ number of matching features. Returns the current feature number, where a value of 0 corresponds to the first feature. %End + virtual QgsExpressionContext createExpressionContext() const; + + public slots: virtual bool next(); diff --git a/src/core/layout/qgslayoutatlas.cpp b/src/core/layout/qgslayoutatlas.cpp index 4d760f2b5a0..ee1baac2197 100644 --- a/src/core/layout/qgslayoutatlas.cpp +++ b/src/core/layout/qgslayoutatlas.cpp @@ -439,7 +439,7 @@ QString QgsLayoutAtlas::currentFilename() const return mCurrentFilename; } -QgsExpressionContext QgsLayoutAtlas::createExpressionContext() +QgsExpressionContext QgsLayoutAtlas::createExpressionContext() const { QgsExpressionContext expressionContext; expressionContext << QgsExpressionContextUtils::globalScope(); @@ -447,10 +447,10 @@ QgsExpressionContext QgsLayoutAtlas::createExpressionContext() expressionContext << QgsExpressionContextUtils::projectScope( mLayout->project() ) << QgsExpressionContextUtils::layoutScope( mLayout ); - expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) ); + expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( const_cast< QgsLayoutAtlas * >( this ) ) ); if ( mCoverageLayer ) - expressionContext.lastScope()->setFields( mCoverageLayer->fields() ); + expressionContext.appendScope( mCoverageLayer->createExpressionContextScope() ); if ( mLayout && mEnabled ) expressionContext.lastScope()->setFeature( mCurrentFeature ); diff --git a/src/core/layout/qgslayoutatlas.h b/src/core/layout/qgslayoutatlas.h index d907cdd7435..2807b33ba31 100644 --- a/src/core/layout/qgslayoutatlas.h +++ b/src/core/layout/qgslayoutatlas.h @@ -20,6 +20,7 @@ #include "qgsvectorlayerref.h" #include "qgslayoutserializableobject.h" #include "qgsabstractlayoutiterator.h" +#include "qgsexpressioncontextgenerator.h" #include class QgsLayout; @@ -37,7 +38,7 @@ class QgsLayout; * * \since QGIS 3.0 */ -class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutIterator, public QgsLayoutSerializableObject +class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutIterator, public QgsLayoutSerializableObject, public QgsExpressionContextGenerator { Q_OBJECT public: @@ -252,6 +253,8 @@ class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutItera */ int currentFeatureNumber() const { return mCurrentFeatureNo; } + QgsExpressionContext createExpressionContext() const override; + public slots: bool next() override; @@ -390,7 +393,6 @@ class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutItera int mCurrentFeatureNo = -1; QgsFeature mCurrentFeature; - QgsExpressionContext createExpressionContext(); friend class AtlasFeatureSorter; }; diff --git a/tests/src/core/testqgslayoutatlas.cpp b/tests/src/core/testqgslayoutatlas.cpp index 82207b5b3e7..9235dcc788d 100644 --- a/tests/src/core/testqgslayoutatlas.cpp +++ b/tests/src/core/testqgslayoutatlas.cpp @@ -67,6 +67,8 @@ class TestQgsLayoutAtlas : public QObject // test removing coverage layer while atlas is enabled void test_remove_layer(); + void context(); + private: QgsPrintLayout *mLayout = nullptr; QgsLayoutItemLabel *mLabel1 = nullptr; @@ -426,5 +428,27 @@ void TestQgsLayoutAtlas::test_remove_layer() QVERIFY( spyToggled.count() == 1 ); } +void TestQgsLayoutAtlas::context() +{ + std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( QStringLiteral( "Point?crs=epsg:4326&field=id:integer&field=labelx:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) ) ); + QgsFeature f; + QVERIFY( vl2->dataProvider()->addFeature( f ) ); + QgsFeature f2; + QVERIFY( vl2->dataProvider()->addFeature( f2 ) ); + + mAtlas->setCoverageLayer( vl2.get() ); + mAtlas->setEnabled( true ); + + QgsExpressionContext context = mAtlas->createExpressionContext(); + QVERIFY( context.hasVariable( QStringLiteral( "project_title" ) ) ); + QVERIFY( context.hasVariable( QStringLiteral( "layout_name" ) ) ); + QVERIFY( context.hasVariable( QStringLiteral( "atlas_totalfeatures" ) ) ); + QVERIFY( context.hasVariable( QStringLiteral( "layer_id" ) ) ); + QCOMPARE( context.fields().at( 1 ).name(), QStringLiteral( "labelx" ) ); + QVERIFY( context.hasFeature() ); + + mAtlas->setCoverageLayer( nullptr ); +} + QGSTEST_MAIN( TestQgsLayoutAtlas ) #include "testqgslayoutatlas.moc"