Skip to content
Permalink
Browse files

Finish porting composer to expression contexts

  • Loading branch information
nyalldawson committed Aug 22, 2015
1 parent 5cb874c commit 43bcc0c2a5268fe784b258893538e499ac0c5c43
@@ -185,15 +185,16 @@ class QgsComposerHtml: QgsComposerMultiFrame
/** Reloads the html source from the url and redraws the item.
* @param useCache set to true to use a cached copy of remote html
* content
* @param context expression context for evaluating data defined urls and expressions in html
* @see setUrl
* @see url
*/
void loadHtml( const bool useCache = false );
void loadHtml( const bool useCache = false, const QgsExpressionContext* context = 0 );

/** Recalculates the frame sizes for the current viewport dimensions*/
void recalculateFrameSizes();
void refreshExpressionContext();

virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );

};
@@ -658,9 +658,10 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
* @param property data defined property to refresh. If property is set to
* QgsComposerItem::AllProperties then all data defined properties for the item will be
* refreshed.
* @param context expression context for evaluating data defined expressions
* @note this method was added in version 2.5
*/
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );

protected:

@@ -767,11 +768,12 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
* @param resizeOnly set to true if the item is only being resized. If true then
* the position of the returned rect will be adjusted to account for the item's
* position mode
* @param context expression context for evaluating data defined expressions
* @returns bounding box rectangle for item after data defined size and position have been
* set and position mode has been accounted for
* @note added in QGIS 2.5
*/
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false );
QRectF evalItemRect( const QRectF &newRect, const bool resizeOnly = false, const QgsExpressionContext* context = 0 );

/** Returns whether the item should be drawn in the current context
* @returns true if item should be drawn
@@ -777,7 +777,7 @@ class QgsComposerMap : QgsComposerItem
/** @deprecated use QgsComposerMapOverview::overviewExtentChanged instead*/
void overviewExtentChanged();

virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );

protected slots:

@@ -145,20 +145,22 @@ class QgsComposerObject : QObject
* @param property data defined property to refresh. If property is set to
* QgsComposerItem::AllProperties then all data defined properties for the item will be
* refreshed.
* @context expression context for evaluating data defined expressions
* @note this method was added in version 2.5
*/
virtual void refreshDataDefinedProperty( const DataDefinedProperty property = AllProperties );

virtual void refreshDataDefinedProperty( const DataDefinedProperty property = AllProperties, const QgsExpressionContext* context = 0 );

protected:

/** Evaluate a data defined property and return the calculated value
* @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 = QgsExpressionContext() ) const;

signals:
/** Emitted when the item changes. Signifies that the item widgets must update the
@@ -246,10 +246,11 @@ class QgsComposerPicture: QgsComposerItem

/** Recalculates the source image (if using an expression for picture's source)
* and reloads and redraws the picture.
* @param context expression context for evaluating data defined picture sources
* @note added in 2.3
*/
void refreshPicture();

void refreshPicture( const QgsExpressionContext* context = 0 );
/** Prepares the picture's source expression after it is altered or the compositions
* atlas coverage layer changes.
* @note added in 2.3
@@ -262,7 +263,7 @@ class QgsComposerPicture: QgsComposerItem
*/
void recalculateSize();

virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext *context = 0 );

signals:
/** Is emitted on picture rotation change*/
@@ -673,9 +673,10 @@ class QgsComposition : QGraphicsScene
* @param property data defined property to refresh. If property is set to
* QgsComposerItem::AllProperties then all data defined properties for the composition will be
* refreshed.
* @param context expression context for evaluating data defined expressions
* @note this method was added in version 2.5
*/
void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties );
void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 );

protected:
void init();
@@ -375,6 +375,9 @@ bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &at
return false;
}

QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
context->setFields( mVectorLayer->fields() );

attributeMaps.clear();

//prepare filter expression
@@ -421,10 +424,11 @@ bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &at

while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
{
context->setFeature( f );
//check feature against filter
if ( activeFilter && !filterExpression.isNull() )
{
QVariant result = filterExpression->evaluate( &f, mVectorLayer->fields() );
QVariant result = filterExpression->evaluate( context.data() );
// skip this feature if the filter evaluation is false
if ( !result.toBool() )
{
@@ -447,9 +451,9 @@ bool QgsComposerAttributeTable::getFeatureAttributes( QList<QgsAttributeMap> &at
{
// Lets assume it's an expression
QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() );
expression->setCurrentRowNumber( counter + 1 );
expression->prepare( mVectorLayer->fields() );
QVariant value = expression->evaluate( f );
context->lastScope()->setVariable( QString( "_rownum_" ), counter + 1 );
expression->prepare( context.data() );
QVariant value = expression->evaluate( context.data() );
attributeMaps.last().insert( i, value.toString() );
}

@@ -451,6 +451,9 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co
return false;
}

QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
context->setFields( layer->fields() );

//prepare filter expression
QScopedPointer<QgsExpression> filterExpression;
bool activeFilter = false;
@@ -511,10 +514,11 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co

while ( fit.nextFeature( f ) && counter < mMaximumNumberOfFeatures )
{
context->setFeature( f );
//check feature against filter
if ( activeFilter && !filterExpression.isNull() )
{
QVariant result = filterExpression->evaluate( &f, layer->fields() );
QVariant result = filterExpression->evaluate( context.data() );
// skip this feature if the filter evaluation is false
if ( !result.toBool() )
{
@@ -551,9 +555,9 @@ bool QgsComposerAttributeTableV2::getTableContents( QgsComposerTableContents &co
{
// Lets assume it's an expression
QgsExpression* expression = new QgsExpression(( *columnIt )->attribute() );
expression->setCurrentRowNumber( counter + 1 );
expression->prepare( layer->fields() );
QVariant value = expression->evaluate( f );
context->lastScope()->setVariable( QString( "_rownum_" ), counter + 1 );
expression->prepare( context.data() );
QVariant value = expression->evaluate( context.data() );
currentRow << value;
}
}
@@ -122,13 +122,21 @@ void QgsComposerHtml::setEvaluateExpressions( bool evaluateExpressions )
emit changed();
}

void QgsComposerHtml::loadHtml( const bool useCache )
void QgsComposerHtml::loadHtml( const bool useCache, const QgsExpressionContext *context )
{
if ( !mWebPage )
{
return;
}

const QgsExpressionContext* evalContext = context;
QScopedPointer< QgsExpressionContext > scopedContext;
if ( !evalContext )
{
scopedContext.reset( createExpressionContext() );
evalContext = scopedContext.data();
}

QString loadedHtml;
switch ( mContentMode )
{
@@ -139,7 +147,7 @@ void QgsComposerHtml::loadHtml( const bool useCache )

//data defined url set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::SourceUrl, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::SourceUrl, exprVal, *evalContext ) )
{
currentUrl = exprVal.toString().trimmed();;
QgsDebugMsg( QString( "exprVal Source Url:%1" ).arg( currentUrl ) );
@@ -168,7 +176,7 @@ void QgsComposerHtml::loadHtml( const bool useCache )
//evaluate expressions
if ( mEvaluateExpressions )
{
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, &mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, evalContext, 0, mDistanceArea );
}

mLoaded = false;
@@ -552,12 +560,20 @@ void QgsComposerHtml::refreshExpressionContext()
loadHtml( true );
}

void QgsComposerHtml::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property )
void QgsComposerHtml::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, const QgsExpressionContext* context )
{
const QgsExpressionContext* evalContext = context;
QScopedPointer< QgsExpressionContext > scopedContext;
if ( !evalContext )
{
scopedContext.reset( createExpressionContext() );
evalContext = scopedContext.data();
}

//updates data defined properties and redraws item to match
if ( property == QgsComposerObject::SourceUrl || property == QgsComposerObject::AllProperties )
{
loadHtml( true );
loadHtml( true, evalContext );
}
QgsComposerObject::refreshDataDefinedProperty( property );
QgsComposerObject::refreshDataDefinedProperty( property, context );
}
@@ -210,16 +210,17 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
/** Reloads the html source from the url and redraws the item.
* @param useCache set to true to use a cached copy of remote html
* content
* @param context expression context for evaluating data defined urls and expressions in html
* @see setUrl
* @see url
*/
void loadHtml( const bool useCache = false );
void loadHtml( const bool useCache = false, const QgsExpressionContext* context = 0 );

/** Recalculates the frame sizes for the current viewport dimensions*/
void recalculateFrameSizes() override;
void refreshExpressionContext();

virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties ) override;
virtual void refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property = QgsComposerObject::AllProperties, const QgsExpressionContext* context = 0 ) override;

private slots:
void frameLoaded( bool ok = true );
@@ -897,16 +897,17 @@ void QgsComposerItem::setBlendMode( const QPainter::CompositionMode blendMode )
{
mBlendMode = blendMode;
// Update the composer effect to use the new blend mode
refreshBlendMode();
QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
refreshBlendMode( *context.data() );
}

void QgsComposerItem::refreshBlendMode()
void QgsComposerItem::refreshBlendMode( const QgsExpressionContext& context )
{
QPainter::CompositionMode blendMode = mBlendMode;

//data defined blend mode set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::BlendMode, exprVal ) && !exprVal.isNull() )
if ( dataDefinedEvaluate( QgsComposerObject::BlendMode, exprVal, context ) && !exprVal.isNull() )
{
QString blendstr = exprVal.toString().trimmed();
QPainter::CompositionMode blendModeD = QgsSymbolLayerV2Utils::decodeBlendMode( blendstr );
@@ -922,16 +923,17 @@ void QgsComposerItem::refreshBlendMode()
void QgsComposerItem::setTransparency( const int transparency )
{
mTransparency = transparency;
refreshTransparency( true );
QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
refreshTransparency( true, *context.data() );
}

void QgsComposerItem::refreshTransparency( const bool updateItem )
void QgsComposerItem::refreshTransparency( const bool updateItem, const QgsExpressionContext& context )
{
int transparency = mTransparency;

//data defined transparency set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::Transparency, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::Transparency, exprVal, context ) )
{
bool ok;
int transparencyD = exprVal.toInt( &ok );
@@ -1072,16 +1074,17 @@ void QgsComposerItem::setItemRotation( const double r, const bool adjustPosition
mItemRotation = r;
}

refreshRotation( true, adjustPosition );
QScopedPointer< QgsExpressionContext > context( createExpressionContext() );
refreshRotation( true, adjustPosition, *context.data() );
}

void QgsComposerItem::refreshRotation( const bool updateItem, const bool adjustPosition )
void QgsComposerItem::refreshRotation( const bool updateItem, const bool adjustPosition, const QgsExpressionContext& context )
{
double rotation = mItemRotation;

//data defined rotation set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::ItemRotation, exprVal ) )
if ( dataDefinedEvaluate( QgsComposerObject::ItemRotation, exprVal, context ) )
{
bool ok;
double rotD = exprVal.toDouble( &ok );
@@ -1355,38 +1358,48 @@ void QgsComposerItem::repaint()
updateItem();
}

void QgsComposerItem::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property )
void QgsComposerItem::refreshDataDefinedProperty( const QgsComposerObject::DataDefinedProperty property, const QgsExpressionContext *context )
{
//maintain 2.10 API
//TODO QGIS 3.0 - remove this
const QgsExpressionContext* evalContext = context;
QScopedPointer< QgsExpressionContext > scopedContext;
if ( !evalContext )
{
scopedContext.reset( createExpressionContext() );
evalContext = scopedContext.data();
}

//update data defined properties and redraw item to match
if ( property == QgsComposerObject::PositionX || property == QgsComposerObject::PositionY ||
property == QgsComposerObject::ItemWidth || property == QgsComposerObject::ItemHeight ||
property == QgsComposerObject::AllProperties )
{
QRectF beforeRect = QRectF( pos().x(), pos().y(), rect().width(), rect().height() );
QRectF evaluatedRect = evalItemRect( beforeRect );
QRectF evaluatedRect = evalItemRect( beforeRect, false, evalContext );
if ( evaluatedRect != beforeRect )
{
setSceneRect( evaluatedRect );
}
}
if ( property == QgsComposerObject::ItemRotation || property == QgsComposerObject::AllProperties )
{
refreshRotation( false, true );
refreshRotation( false, true, *evalContext );
}
if ( property == QgsComposerObject::Transparency || property == QgsComposerObject::AllProperties )
{
refreshTransparency( false );
refreshTransparency( false, *evalContext );
}
if ( property == QgsComposerObject::BlendMode || property == QgsComposerObject::AllProperties )
{
refreshBlendMode();
refreshBlendMode( *evalContext );
}
if ( property == QgsComposerObject::ExcludeFromExports || property == QgsComposerObject::AllProperties )
{
bool exclude = mExcludeFromExports;
//data defined exclude from exports set?
QVariant exprVal;
if ( dataDefinedEvaluate( QgsComposerObject::ExcludeFromExports, exprVal ) && !exprVal.isNull() )
if ( dataDefinedEvaluate( QgsComposerObject::ExcludeFromExports, exprVal, *evalContext ) && !exprVal.isNull() )
{
exclude = exprVal.toBool();
}

0 comments on commit 43bcc0c

Please sign in to comment.
You can’t perform that action at this time.