Add atlas expression context scope to layouts

This commit is contained in:
Nyall Dawson 2017-12-20 17:37:10 +10:00
parent 3318bfbb4d
commit 5d1d25b36b
26 changed files with 110 additions and 42 deletions

View File

@ -38,6 +38,8 @@ Constructor for new QgsLayoutAtlas.
virtual QgsLayout *layout();
virtual bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const;
virtual bool readXml( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context );

View File

@ -35,6 +35,8 @@ Returns the print layout's atlas.
virtual bool readXml( const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context );
virtual QgsExpressionContext createExpressionContext() const;
};

View File

@ -1045,11 +1045,19 @@ with the variables specified.
.. versionadded:: 3.0
%End
static QgsExpressionContextScope *atlasScope( const QgsAtlasComposition *atlas ) /Factory/;
static QgsExpressionContextScope *compositionAtlasScope( const QgsAtlasComposition *atlas ) /Factory/;
%Docstring
Creates a new scope which contains variables and functions relating to a :py:class:`QgsAtlasComposition`.
For instance, current page name and number.
:param atlas: source atlas. If null, a set of default atlas variables will be added to the scope.
%End
static QgsExpressionContextScope *atlasScope( const QgsLayoutAtlas *atlas ) /Factory/;
%Docstring
Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
For instance, current page name and number.
:param atlas: source atlas. If null, a set of default atlas variables will be added to the scope.
%End

View File

@ -52,7 +52,7 @@ QgsExpressionContext QgsDiagramProperties::createExpressionContext() const
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
<< QgsExpressionContextUtils::layerScope( mLayer );
@ -931,7 +931,7 @@ QString QgsDiagramProperties::showExpressionBuilder( const QString &initialExpre
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )
<< QgsExpressionContextUtils::layerScope( mLayer );

View File

@ -29,7 +29,7 @@ QgsExpressionContext QgsLabelingGui::createExpressionContext() const
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() );
if ( mLayer )

View File

@ -255,7 +255,7 @@ void QgsLabelPropertyDialog::setDataDefinedValues( QgsVectorLayer *vlayer )
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
<< QgsExpressionContextUtils::layerScope( vlayer );
context.setFeature( mCurLabelFeat );

View File

@ -33,7 +33,7 @@ QgsRenderContext QgsPointMarkerItem::renderContext( QPainter *painter )
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mMapCanvas )
{
context << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )

View File

@ -35,7 +35,7 @@ static QList<QgsExpressionContextScope *> _globalProjectAtlasMapLayerScopes( Qgs
QList<QgsExpressionContextScope *> scopes;
scopes << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mapCanvas )
{
scopes << QgsExpressionContextUtils::mapSettingsScope( mapCanvas->mapSettings() )

View File

@ -130,7 +130,7 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
mContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::mapSettingsScope( QgisApp::instance()->mapCanvas()->mapSettings() )
<< QgsExpressionContextUtils::layerScope( mLayer );

View File

@ -723,7 +723,7 @@ QgsExpressionContext QgsAtlasComposition::createExpressionContext()
expressionContext << QgsExpressionContextUtils::projectScope( mComposition->project() )
<< QgsExpressionContextUtils::compositionScope( mComposition );
expressionContext.appendScope( QgsExpressionContextUtils::atlasScope( this ) );
expressionContext.appendScope( QgsExpressionContextUtils::compositionAtlasScope( this ) );
if ( mCoverageLayer )
expressionContext.lastScope()->setFields( mCoverageLayer->fields() );
if ( mComposition && mComposition->atlasMode() != QgsComposition::AtlasOff )

View File

@ -3284,7 +3284,7 @@ QgsExpressionContext QgsComposition::createExpressionContext() const
context.appendScope( QgsExpressionContextUtils::compositionScope( this ) );
if ( mAtlasComposition.enabled() )
{
context.appendScope( QgsExpressionContextUtils::atlasScope( &mAtlasComposition ) );
context.appendScope( QgsExpressionContextUtils::compositionAtlasScope( &mAtlasComposition ) );
}
return context;
}

View File

@ -325,12 +325,6 @@ QgsExpressionContext QgsLayout::createExpressionContext() const
context.appendScope( QgsExpressionContextUtils::globalScope() );
context.appendScope( QgsExpressionContextUtils::projectScope( mProject ) );
context.appendScope( QgsExpressionContextUtils::layoutScope( this ) );
#if 0 //TODO
if ( mAtlasComposition.enabled() )
{
context.appendScope( QgsExpressionContextUtils::atlasScope( &mAtlasComposition ) );
}
#endif
return context;
}

View File

@ -42,6 +42,11 @@ QgsLayout *QgsLayoutAtlas::layout()
return mLayout;
}
const QgsLayout *QgsLayoutAtlas::layout() const
{
return mLayout.data();
}
bool QgsLayoutAtlas::writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext & ) const
{
QDomElement atlasElem = document.createElement( QStringLiteral( "Atlas" ) );

View File

@ -46,6 +46,13 @@ class CORE_EXPORT QgsLayoutAtlas : public QObject, public QgsAbstractLayoutItera
QString stringType() const override;
QgsLayout *layout() override;
/**
* Returns the atlas' layout.
* \note Not available in Python bindings.
*/
const QgsLayout *layout() const SIP_SKIP;
bool writeXml( QDomElement &parentElement, QDomDocument &document, const QgsReadWriteContext &context ) const override;
bool readXml( const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context ) override;

View File

@ -29,7 +29,7 @@
#include "qgsfontutils.h"
#include "qgsexpressioncontext.h"
#include "qgsmapsettings.h"
#include "qgscomposermap.h"
#include "qgslayoutitemmap.h"
#include "qgssettings.h"
#include "qgswebview.h"
@ -69,11 +69,9 @@ QgsLayoutItemLabel::QgsLayoutItemLabel( QgsLayout *layout )
if ( mLayout )
{
#if 0 //TODO
//connect to atlas feature changes
//connect to context feature changes
//to update the expression context
connect( &mLayout->atlasComposition(), &QgsAtlasComposition::featureChanged, this, &QgsLayoutItemLabel::refreshExpressionContext );
#endif
connect( &mLayout->context(), &QgsLayoutContext::changed, this, &QgsLayoutItemLabel::refreshExpressionContext );
}
mWebPage.reset( new QgsWebPage( this ) );
@ -244,14 +242,7 @@ void QgsLayoutItemLabel::refreshExpressionContext()
if ( !mLayout )
return;
QgsVectorLayer *layer = nullptr;
#if 0 //TODO
if ( mComposition->atlasComposition().enabled() )
{
layer = mComposition->atlasComposition().coverageLayer();
}
#endif
QgsVectorLayer *layer = mLayout->context().layer();
//setup distance area conversion
if ( layer )
{
@ -259,12 +250,10 @@ void QgsLayoutItemLabel::refreshExpressionContext()
}
else
{
#if 0 //TODO
//set to composition's reference map's crs
QgsLayoutItemMap *referenceMap = mComposition->referenceMap();
QgsLayoutItemMap *referenceMap = mLayout->referenceMap();
if ( referenceMap )
mDistanceArea->setSourceCrs( referenceMap->crs() );
#endif
}
mDistanceArea->setEllipsoid( mLayout->project()->ellipsoid() );
contentChanged();

View File

@ -44,3 +44,15 @@ bool QgsPrintLayout::readXml( const QDomElement &layoutElement, const QDomDocume
mAtlas->readXml( atlasElem, document, context );
return true;
}
QgsExpressionContext QgsPrintLayout::createExpressionContext() const
{
QgsExpressionContext context = QgsLayout::createExpressionContext();
if ( mAtlas->enabled() )
{
context.appendScope( QgsExpressionContextUtils::atlasScope( mAtlas ) );
}
return context;
}

View File

@ -45,6 +45,7 @@ class CORE_EXPORT QgsPrintLayout : public QgsLayout
QDomElement writeXml( QDomDocument &document, const QgsReadWriteContext &context ) const override;
bool readXml( const QDomElement &layoutElement, const QDomDocument &document, const QgsReadWriteContext &context ) override;
QgsExpressionContext createExpressionContext() const override;
private:

View File

@ -31,6 +31,7 @@
#include "qgsmaplayerlistutils.h"
#include "qgsprocessingcontext.h"
#include "qgsprocessingalgorithm.h"
#include "qgslayoutatlas.h"
#include "qgslayout.h"
#include <QSettings>
@ -1127,7 +1128,7 @@ void QgsExpressionContextUtils::setLayoutVariables( QgsLayout *layout, const QVa
layout->setCustomProperty( QStringLiteral( "variableValues" ), variableValues );
}
QgsExpressionContextScope *QgsExpressionContextUtils::atlasScope( const QgsAtlasComposition *atlas )
QgsExpressionContextScope *QgsExpressionContextUtils::compositionAtlasScope( const QgsAtlasComposition *atlas )
{
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
if ( !atlas )
@ -1166,6 +1167,45 @@ QgsExpressionContextScope *QgsExpressionContextUtils::atlasScope( const QgsAtlas
return scope;
}
QgsExpressionContextScope *QgsExpressionContextUtils::atlasScope( const QgsLayoutAtlas *atlas )
{
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
if ( !atlas )
{
//add some dummy atlas variables. This is done so that as in certain contexts we want to show
//users that these variables are available even if they have no current value
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), QString(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( QgsFeature() ), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), 0, true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( QgsGeometry() ), true ) );
return scope;
}
//add known atlas variables
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_totalfeatures" ), atlas->count(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featurenumber" ), atlas->currentFeatureNumber() + 1, true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_filename" ), atlas->currentFilename(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_pagename" ), atlas->nameForPage( atlas->currentFeatureNumber() ), true ) );
if ( atlas->enabled() && atlas->coverageLayer() )
{
scope->setFields( atlas->coverageLayer()->fields() );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layerid" ), atlas->coverageLayer()->id(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_layername" ), atlas->coverageLayer()->name(), true ) );
}
if ( atlas->enabled() )
{
QgsFeature atlasFeature = atlas->layout()->context().feature();
scope->setFeature( atlasFeature );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_feature" ), QVariant::fromValue( atlasFeature ), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_featureid" ), atlasFeature.id(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "atlas_geometry" ), QVariant::fromValue( atlasFeature.geometry() ), true ) );
}
return scope;
}
QgsExpressionContextScope *QgsExpressionContextUtils::composerItemScope( const QgsComposerItem *composerItem )
{
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Composer Item" ) );

View File

@ -40,6 +40,7 @@ class QgsProject;
class QgsSymbol;
class QgsProcessingAlgorithm;
class QgsProcessingContext;
class QgsLayoutAtlas;
/**
* \ingroup core
@ -926,7 +927,14 @@ class CORE_EXPORT QgsExpressionContextUtils
* For instance, current page name and number.
* \param atlas source atlas. If null, a set of default atlas variables will be added to the scope.
*/
static QgsExpressionContextScope *atlasScope( const QgsAtlasComposition *atlas ) SIP_FACTORY;
static QgsExpressionContextScope *compositionAtlasScope( const QgsAtlasComposition *atlas ) SIP_FACTORY;
/**
* Creates a new scope which contains variables and functions relating to a QgsLayoutAtlas.
* For instance, current page name and number.
* \param atlas source atlas. If null, a set of default atlas variables will be added to the scope.
*/
static QgsExpressionContextScope *atlasScope( const QgsLayoutAtlas *atlas ) SIP_FACTORY;
/**
* Creates a new scope which contains variables and functions relating to a QgsComposerItem.

View File

@ -635,7 +635,7 @@ void QgsCategorizedSymbolRendererWidget::addCategories()
QgsExpressionContext context;
context << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr )
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr )
<< QgsExpressionContextUtils::layerScope( mLayer );
expression->prepare( &context );
@ -1014,7 +1014,7 @@ QgsExpressionContext QgsCategorizedSymbolRendererWidget::createExpressionContext
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mContext.mapCanvas() )
{

View File

@ -178,7 +178,7 @@ void QgsDataDefinedSizeLegendWidget::changeSymbol()
QgsExpressionContext ec;
ec << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mMapCanvas )
ec << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() );
context.setExpressionContext( &ec );

View File

@ -396,7 +396,7 @@ QgsExpressionContext QgsGraduatedSymbolRendererWidget::createExpressionContext()
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mContext.mapCanvas() )
{

View File

@ -38,7 +38,7 @@ QgsExpressionContext QgsHeatmapRendererWidget::createExpressionContext() const
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mContext.mapCanvas() )
{

View File

@ -217,7 +217,7 @@ QgsExpressionContext QgsLayerPropertiesWidget::createExpressionContext() const
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mContext.mapCanvas() )
{

View File

@ -327,7 +327,7 @@ QgsExpressionContext QgsDataDefinedValueDialog::createExpressionContext() const
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mContext.mapCanvas() )
{
expContext << QgsExpressionContextUtils::mapSettingsScope( mContext.mapCanvas()->mapSettings() )

View File

@ -79,7 +79,7 @@ QList<QgsExpressionContextScope *> QgsSymbolWidgetContext::globalProjectAtlasMap
QList<QgsExpressionContextScope *> scopes;
scopes << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::atlasScope( nullptr );
<< QgsExpressionContextUtils::compositionAtlasScope( nullptr );
if ( mMapCanvas )
{
scopes << QgsExpressionContextUtils::mapSettingsScope( mMapCanvas->mapSettings() )