Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
More composer porting
  • Loading branch information
nyalldawson committed Aug 22, 2015
1 parent cf22025 commit 5cb874c
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 54 deletions.
33 changes: 16 additions & 17 deletions src/core/composer/qgscomposeritem.cpp
Expand Up @@ -709,14 +709,24 @@ void QgsComposerItem::setSceneRect( const QRectF& rectangle )
emit sizeChanged();
}

QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOnly )
QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOnly, const QgsExpressionContext* context )
{
QRectF result = newRect;

//TODO QGIS 3.0
//maintain pre 2.12 API. remove when API break allowed
QScopedPointer< QgsExpressionContext > scopedContext;
const QgsExpressionContext* evalContext = context;
if ( !evalContext )
{
scopedContext.reset( createExpressionContext() );
evalContext = scopedContext.data();
}

//data defined position or size set? if so, update rect with data defined values
QVariant exprVal;
//evaulate width and height first, since they may affect position if non-top-left reference point set
if ( dataDefinedEvaluate( QgsComposerObject::ItemWidth, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::ItemWidth, exprVal, *evalContext ) )
{
bool ok;
double width = exprVal.toDouble( &ok );
Expand All @@ -726,7 +736,7 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOn
result.setWidth( width );
}
}
if ( dataDefinedEvaluate( QgsComposerObject::ItemHeight, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::ItemHeight, exprVal, *evalContext ) )
{
bool ok;
double height = exprVal.toDouble( &ok );
Expand Down Expand Up @@ -762,7 +772,7 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOn
x += rect().width();
}
}
if ( dataDefinedEvaluate( QgsComposerObject::PositionX, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::PositionX, exprVal, *evalContext ) )
{
bool ok;
double positionX = exprVal.toDouble( &ok );
Expand Down Expand Up @@ -798,7 +808,7 @@ QRectF QgsComposerItem::evalItemRect( const QRectF &newRect, const bool resizeOn
y += rect().height();
}
}
if ( dataDefinedEvaluate( QgsComposerObject::PositionY, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::PositionY, exprVal, *evalContext ) )
{
bool ok;
double positionY = exprVal.toDouble( &ok );
Expand Down Expand Up @@ -849,18 +859,7 @@ bool QgsComposerItem::shouldDrawItem() const

QgsExpressionContext* QgsComposerItem::createExpressionContext() const
{
QgsExpressionContext* context = new QgsExpressionContext();
context->appendScope( QgsExpressionContextUtils::globalScope() );
context->appendScope( QgsExpressionContextUtils::projectScope() );
if ( mComposition )
{
context->appendScope( QgsExpressionContextUtils::compositionScope( mComposition ) );
if ( mComposition->atlasComposition().enabled() )
{
context->appendScope( QgsExpressionContextUtils::atlasScope( &mComposition->atlasComposition() ) );
}
}

QgsExpressionContext* context = QgsComposerObject::createExpressionContext();
context->appendScope( QgsExpressionContextUtils::composerItemScope( this ) );
return context;
}
Expand Down
6 changes: 1 addition & 5 deletions src/core/composer/qgscomposeritem.h
Expand Up @@ -583,11 +583,7 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
*/
virtual void setCurrentExportLayer( const int layerIdx = -1 ) { mCurrentExportLayer = layerIdx; }

/** Creates an expression context relating to the item's current state. The context includes
* scopes for global, project, composition, atlas and item properties.
* @note added in QGIS 2.12
*/
QgsExpressionContext* createExpressionContext() const;
virtual QgsExpressionContext* createExpressionContext() const override;

public slots:
/** Sets the item rotation
Expand Down
34 changes: 21 additions & 13 deletions src/core/composer/qgscomposerobject.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgscomposerutils.h"
#include "qgscomposerobject.h"
#include "qgsdatadefined.h"
#include "qgsexpressioncontext.h"

#define FONT_WORKAROUND_SCALE 10 //scale factor for upscaling fontsize and downscaling painter

Expand Down Expand Up @@ -151,33 +152,24 @@ void QgsComposerObject::refreshDataDefinedProperty( const DataDefinedProperty pr
//nothing to do in base class for now
}

bool QgsComposerObject::dataDefinedEvaluate( const DataDefinedProperty property, QVariant &expressionValue ) const
bool QgsComposerObject::dataDefinedEvaluate( const DataDefinedProperty property, QVariant &expressionValue, const QgsExpressionContext& context ) const
{
if ( !mComposition )
{
return false;
}
return mComposition->dataDefinedEvaluate( property, expressionValue, &mDataDefinedProperties );
return mComposition->dataDefinedEvaluate( property, expressionValue, context, &mDataDefinedProperties );
}

void QgsComposerObject::prepareDataDefinedExpressions() const
{
//use atlas coverage layer if set
QgsVectorLayer* atlasLayer = 0;
if ( mComposition )
{
QgsAtlasComposition* atlas = &mComposition->atlasComposition();
if ( atlas && atlas->enabled() )
{
atlasLayer = atlas->coverageLayer();
}
}
QScopedPointer< QgsExpressionContext > context( createExpressionContext() );

//prepare all QgsDataDefineds
QMap< DataDefinedProperty, QgsDataDefined* >::const_iterator it = mDataDefinedProperties.constBegin();
if ( it != mDataDefinedProperties.constEnd() )
{
it.value()->prepareExpression( atlasLayer );
it.value()->prepareExpression( *context.data() );
}
}

Expand All @@ -200,3 +192,19 @@ QStringList QgsComposerObject::customProperties() const
{
return mCustomProperties.keys();
}

QgsExpressionContext* QgsComposerObject::createExpressionContext() const
{
QgsExpressionContext* context = 0;
if ( mComposition )
{
context = mComposition->createExpressionContext();
}
else
{
context = new QgsExpressionContext();
context->appendScope( QgsExpressionContextUtils::globalScope() );
context->appendScope( QgsExpressionContextUtils::projectScope() );
}
return context;
}
11 changes: 10 additions & 1 deletion src/core/composer/qgscomposerobject.h
Expand Up @@ -25,6 +25,7 @@
class QgsComposition;
class QPainter;
class QgsDataDefined;
class QgsExpressionContext;

/** \ingroup MapComposer
* A base class for objects which belong to a map composition.
Expand Down Expand Up @@ -161,6 +162,12 @@ class CORE_EXPORT QgsComposerObject: public QObject
*/
QStringList customProperties() const;

/** Creates an expression context relating to the objects's current state. The context includes
* scopes for global, project and composition properties.
* @note added in QGIS 2.12
*/
virtual QgsExpressionContext* createExpressionContext() const;

public slots:

/** Triggers a redraw for the item*/
Expand Down Expand Up @@ -189,9 +196,11 @@ class CORE_EXPORT QgsComposerObject: public QObject
* @returns true if data defined property could be successfully evaluated
* @param property data defined property to evaluate
* @param expressionValue QVariant for storing the evaluated value
* @param context expression context for evaluating expressions. Must have feature and fields set to current
* atlas feature and coverage layer fields prior to calling this method.
* @note this method was added in version 2.5
*/
bool dataDefinedEvaluate( const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue ) const;
bool dataDefinedEvaluate( const QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue, const QgsExpressionContext& context ) const;

signals:
/** Emitted when the item changes. Signifies that the item widgets must update the
Expand Down
42 changes: 26 additions & 16 deletions src/core/composer/qgscomposition.cpp
Expand Up @@ -3062,7 +3062,9 @@ QStringList QgsComposition::customProperties() const
return mCustomProperties.keys();
}

bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue,
const QgsExpressionContext& context,
QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties )
{
if ( property == QgsComposerObject::NoProperty || property == QgsComposerObject::AllProperties )
{
Expand Down Expand Up @@ -3092,7 +3094,7 @@ bool QgsComposition::dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty
}

//evaluate data defined property using current atlas context
QVariant result = dataDefinedValue( property, useFeature ? &currentFeature : 0, layerFields, dataDefinedProperties );
QVariant result = dataDefinedValue( property, useFeature ? &currentFeature : 0, layerFields, context, dataDefinedProperties );

if ( result.isValid() )
{
Expand Down Expand Up @@ -3132,7 +3134,7 @@ bool QgsComposition::dataDefinedActive( const QgsComposerObject::DataDefinedProp
return dd->isActive();
}

QVariant QgsComposition::dataDefinedValue( QgsComposerObject::DataDefinedProperty property, const QgsFeature *feature, const QgsFields& fields, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties ) const
QVariant QgsComposition::dataDefinedValue( QgsComposerObject::DataDefinedProperty property, const QgsFeature *feature, const QgsFields& fields, const QgsExpressionContext& context, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties ) const
{
if ( property == QgsComposerObject::AllProperties || property == QgsComposerObject::NoProperty )
{
Expand Down Expand Up @@ -3168,14 +3170,14 @@ QVariant QgsComposition::dataDefinedValue( QgsComposerObject::DataDefinedPropert

if ( !dd->expressionIsPrepared() )
{
prepareDataDefinedExpression( dd, dataDefinedProperties );
prepareDataDefinedExpression( dd, dataDefinedProperties, context );
}

if ( useExpression && dd->expressionIsPrepared() )
{
QgsExpression* expr = dd->expression();

result = expr->evaluate( feature );
result = expr->evaluate( &context );
if ( expr->hasEvalError() )
{
QgsDebugMsgLevel( QString( "Evaluate error:" ) + expr->evalErrorString(), 4 );
Expand All @@ -3198,34 +3200,42 @@ QVariant QgsComposition::dataDefinedValue( QgsComposerObject::DataDefinedPropert
return result;
}

void QgsComposition::prepareDataDefinedExpression( QgsDataDefined *dd, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties ) const
void QgsComposition::prepareDataDefinedExpression( QgsDataDefined *dd, QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties,
const QgsExpressionContext& context ) const
{
QgsVectorLayer* atlasLayer = 0;

if ( mAtlasComposition.enabled() )
{
atlasLayer = mAtlasComposition.coverageLayer();
}

//if specific QgsDataDefined passed, prepare it
//otherwise prepare all QgsDataDefineds
if ( dd )
{
dd->prepareExpression( atlasLayer );
dd->prepareExpression( context );
}
else
{
QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >::const_iterator it = dataDefinedProperties->constBegin();
for ( ; it != dataDefinedProperties->constEnd(); ++it )
{
it.value()->prepareExpression( atlasLayer );
it.value()->prepareExpression( context );
}
}
}

QgsExpressionContext* QgsComposition::createExpressionContext() const
{
QgsExpressionContext* context = new QgsExpressionContext();
context->appendScope( QgsExpressionContextUtils::globalScope() );
context->appendScope( QgsExpressionContextUtils::projectScope() );
context->appendScope( QgsExpressionContextUtils::compositionScope( this ) );
if ( mAtlasComposition.enabled() )
{
context->appendScope( QgsExpressionContextUtils::atlasScope( &mAtlasComposition ) );
}
return context;
}

void QgsComposition::prepareAllDataDefinedExpressions()
{
prepareDataDefinedExpression( 0, &mDataDefinedProperties );
QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
prepareDataDefinedExpression( 0, &mDataDefinedProperties, *context.data() );
}

void QgsComposition::relativeResizeRect( QRectF& rectToResize, const QRectF& boundsBefore, const QRectF& boundsAfter )
Expand Down
17 changes: 15 additions & 2 deletions src/core/composer/qgscomposition.h
Expand Up @@ -858,10 +858,13 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
* @returns true if data defined property could be successfully evaluated
* @param property data defined property to evaluate
* @param expressionValue QVariant for storing the evaluated value
* @param context expression context for evaluating expressions. Must have feature and fields set
* to corresponding atlas feature and coverage layer fields prior to calling this method.
* @param dataDefinedProperties map of data defined properties to QgsDataDefined
* @note this method was added in version 2.5
*/
bool dataDefinedEvaluate( QgsComposerObject::DataDefinedProperty property, QVariant &expressionValue,
const QgsExpressionContext& context,
QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >* dataDefinedProperties );

/** Returns whether a data defined property has been set and is currently active.
Expand All @@ -876,19 +879,29 @@ class CORE_EXPORT QgsComposition : public QGraphicsScene
* @param property data defined property to evaluate
* @param feature current atlas feature to evaluate property for
* @param fields fields from atlas layer
* @param context expression context for evaluating expressions (note, must have fields and feature set)
* @param dataDefinedProperties map of data defined properties to QgsDataDefined
* @note this method was added in version 2.5
*/
QVariant dataDefinedValue( QgsComposerObject::DataDefinedProperty property, const QgsFeature *feature, const QgsFields& fields,
const QgsExpressionContext& context,
QMap<QgsComposerObject::DataDefinedProperty, QgsDataDefined *> *dataDefinedProperties ) const;


/** Prepares the expression for a data defined property, using the current atlas layer if set.
/** Prepares the expression for a data defined property.
* @param dd data defined to prepare. If no data defined is set, all data defined expressions will be prepared
* @param dataDefinedProperties map of data defined properties to QgsDataDefined
* @param context expression context for expression preparation. Should have fields set to match the current atlas layer if required prior
* to calling this method.
* @note this method was added in version 2.5
*/
void prepareDataDefinedExpression( QgsDataDefined *dd, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >* dataDefinedProperties ) const;
void prepareDataDefinedExpression( QgsDataDefined *dd, QMap< QgsComposerObject::DataDefinedProperty, QgsDataDefined* >* dataDefinedProperties, const QgsExpressionContext& context ) const;

/** Creates an expression context relating to the compositions's current state. The context includes
* scopes for global, project, composition and atlas properties.
* @note added in QGIS 2.12
*/
QgsExpressionContext* createExpressionContext() const;

/** Check whether any data defined page settings are active.
* @returns true if any data defined page settings are active.
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsexpressioncontext.cpp
Expand Up @@ -676,6 +676,7 @@ QgsExpressionContextScope* QgsExpressionContextUtils::atlasScope( const QgsAtlas
{
QgsFeature atlasFeature = atlas->feature();
scope->setFeature( atlasFeature );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_feature", QVariant::fromValue( atlasFeature ), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_featureid", atlasFeature.id(), true ) );
}

Expand Down

0 comments on commit 5cb874c

Please sign in to comment.