[composer] Fix area calculation in expressions with OTF (fix #9791)

Adds an argument to QgsExpression::replaceExpressionText to allow
passing an optional QgsDistanceArea to use during calculations.
Ensure that html and label composer items correctly specify this
argument.
This commit is contained in:
Nyall Dawson 2014-10-19 11:02:16 +11:00
parent fad44d0330
commit 0cb985465b
7 changed files with 90 additions and 13 deletions

View File

@ -97,10 +97,19 @@ class QgsExpression
Additional substitutions can be passed through the substitutionMap Additional substitutions can be passed through the substitutionMap
parameter parameter
@param action
@param feat
@param layer
@param substitutionMap
@param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
and area conversion
*/ */
static QString replaceExpressionText( const QString &action, const QgsFeature *feat, static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer, QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap = 0 ); const QMap<QString, QVariant> *substitutionMap = 0,
const QgsDistanceArea* distanceArea = 0
);
enum UnaryOperator enum UnaryOperator
{ {
uoNot, uoNot,

View File

@ -22,6 +22,8 @@
#include "qgsexpression.h" #include "qgsexpression.h"
#include "qgslogger.h" #include "qgslogger.h"
#include "qgsnetworkcontentfetcher.h" #include "qgsnetworkcontentfetcher.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QPainter> #include <QPainter>
@ -42,9 +44,11 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
, mMaxBreakDistance( 10 ) , mMaxBreakDistance( 10 )
, mExpressionFeature( 0 ) , mExpressionFeature( 0 )
, mExpressionLayer( 0 ) , mExpressionLayer( 0 )
, mDistanceArea( 0 )
, mEnableUserStylesheet( false ) , mEnableUserStylesheet( false )
, mFetcher( 0 ) , mFetcher( 0 )
{ {
mDistanceArea = new QgsDistanceArea();
mHtmlUnitsToMM = htmlUnitsToMM(); mHtmlUnitsToMM = htmlUnitsToMM();
mWebPage = new QWebPage(); mWebPage = new QWebPage();
mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff ); mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
@ -92,14 +96,17 @@ QgsComposerHtml::QgsComposerHtml()
, mMaxBreakDistance( 10 ) , mMaxBreakDistance( 10 )
, mExpressionFeature( 0 ) , mExpressionFeature( 0 )
, mExpressionLayer( 0 ) , mExpressionLayer( 0 )
, mDistanceArea( 0 )
, mFetcher( 0 ) , mFetcher( 0 )
{ {
mDistanceArea = new QgsDistanceArea();
mFetcher = new QgsNetworkContentFetcher(); mFetcher = new QgsNetworkContentFetcher();
connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) ); connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
} }
QgsComposerHtml::~QgsComposerHtml() QgsComposerHtml::~QgsComposerHtml()
{ {
delete mDistanceArea;
delete mWebPage; delete mWebPage;
delete mRenderedPage; delete mRenderedPage;
mFetcher->deleteLater(); mFetcher->deleteLater();
@ -179,7 +186,7 @@ void QgsComposerHtml::loadHtml()
//evaluate expressions //evaluate expressions
if ( mEvaluateExpressions ) if ( mEvaluateExpressions )
{ {
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer ); loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
} }
mLoaded = false; mLoaded = false;
@ -522,6 +529,22 @@ void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer*
{ {
mExpressionFeature = feature; mExpressionFeature = feature;
mExpressionLayer = layer; mExpressionLayer = layer;
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs().srsid() );
}
else if ( mComposition )
{
//set to composition's mapsettings' crs
mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
}
if ( mComposition )
{
mDistanceArea->setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
}
mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
} }
void QgsComposerHtml::refreshExpressionContext() void QgsComposerHtml::refreshExpressionContext()

View File

@ -24,6 +24,7 @@ class QImage;
class QgsFeature; class QgsFeature;
class QgsVectorLayer; class QgsVectorLayer;
class QgsNetworkContentFetcher; class QgsNetworkContentFetcher;
class QgsDistanceArea;
class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
{ {
@ -242,6 +243,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
QgsFeature* mExpressionFeature; QgsFeature* mExpressionFeature;
QgsVectorLayer* mExpressionLayer; QgsVectorLayer* mExpressionLayer;
QgsDistanceArea* mDistanceArea;
QString mUserStylesheet; QString mUserStylesheet;
bool mEnableUserStylesheet; bool mEnableUserStylesheet;

View File

@ -21,6 +21,8 @@
#include "qgsexpression.h" #include "qgsexpression.h"
#include "qgsnetworkaccessmanager.h" #include "qgsnetworkaccessmanager.h"
#include "qgscomposermodel.h" #include "qgscomposermodel.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDate> #include <QDate>
@ -32,12 +34,20 @@
#include <QWebPage> #include <QWebPage>
#include <QEventLoop> #include <QEventLoop>
QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ): QgsComposerLabel::QgsComposerLabel( QgsComposition *composition )
QgsComposerItem( composition ), mHtmlState( 0 ), mHtmlUnitsToMM( 1.0 ), : QgsComposerItem( composition )
mHtmlLoaded( false ), mMargin( 1.0 ), mFontColor( QColor( 0, 0, 0 ) ), , mHtmlState( 0 )
mHAlignment( Qt::AlignLeft ), mVAlignment( Qt::AlignTop ), , mHtmlUnitsToMM( 1.0 )
mExpressionFeature( 0 ), mExpressionLayer( 0 ) , mHtmlLoaded( false )
, mMargin( 1.0 )
, mFontColor( QColor( 0, 0, 0 ) )
, mHAlignment( Qt::AlignLeft )
, mVAlignment( Qt::AlignTop )
, mExpressionFeature( 0 )
, mExpressionLayer( 0 )
, mDistanceArea( 0 )
{ {
mDistanceArea = new QgsDistanceArea();
mHtmlUnitsToMM = htmlUnitsToMM(); mHtmlUnitsToMM = htmlUnitsToMM();
//get default composer font from settings //get default composer font from settings
@ -71,6 +81,7 @@ QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ):
QgsComposerLabel::~QgsComposerLabel() QgsComposerLabel::~QgsComposerLabel()
{ {
delete mDistanceArea;
} }
void QgsComposerLabel::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget ) void QgsComposerLabel::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
@ -221,6 +232,23 @@ void QgsComposerLabel::setExpressionContext( QgsFeature* feature, QgsVectorLayer
mExpressionFeature = feature; mExpressionFeature = feature;
mExpressionLayer = layer; mExpressionLayer = layer;
mSubstitutions = substitutions; mSubstitutions = substitutions;
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs().srsid() );
}
else if ( mComposition )
{
//set to composition's mapsettings' crs
mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
}
if ( mComposition )
{
mDistanceArea->setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
}
mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
// Force label to redraw -- fixes label printing for labels with blend modes when used with atlas // Force label to redraw -- fixes label printing for labels with blend modes when used with atlas
update(); update();
} }
@ -248,7 +276,7 @@ QString QgsComposerLabel::displayText() const
replaceDateText( displayText ); replaceDateText( displayText );
QMap<QString, QVariant> subs = mSubstitutions; QMap<QString, QVariant> subs = mSubstitutions;
subs[ "$page" ] = QVariant(( int )mComposition->itemPageNumber( this ) + 1 ); subs[ "$page" ] = QVariant(( int )mComposition->itemPageNumber( this ) + 1 );
return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer, &subs ); return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer, &subs, mDistanceArea );
} }
void QgsComposerLabel::replaceDateText( QString& text ) const void QgsComposerLabel::replaceDateText( QString& text ) const

View File

@ -22,6 +22,7 @@
class QgsVectorLayer; class QgsVectorLayer;
class QgsFeature; class QgsFeature;
class QgsDistanceArea;
/** \ingroup MapComposer /** \ingroup MapComposer
* A label that can be placed onto a map composition. * A label that can be placed onto a map composition.
@ -143,8 +144,7 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem
QgsFeature* mExpressionFeature; QgsFeature* mExpressionFeature;
QgsVectorLayer* mExpressionLayer; QgsVectorLayer* mExpressionLayer;
QMap<QString, QVariant> mSubstitutions; QMap<QString, QVariant> mSubstitutions;
QgsDistanceArea* mDistanceArea;
}; };
#endif #endif

View File

@ -1989,7 +1989,7 @@ void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const
QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat, QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer, QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap ) const QMap<QString, QVariant> *substitutionMap , const QgsDistanceArea *distanceArea )
{ {
QString expr_action; QString expr_action;
@ -2030,6 +2030,12 @@ QString QgsExpression::replaceExpressionText( const QString &action, const QgsFe
continue; continue;
} }
if ( distanceArea )
{
//if QgsDistanceArea specified for area/distance conversion, use it
exp.setGeomCalculator( *distanceArea );
}
QVariant result; QVariant result;
if ( layer ) if ( layer )
{ {

View File

@ -183,10 +183,18 @@ class CORE_EXPORT QgsExpression
Additional substitutions can be passed through the substitutionMap Additional substitutions can be passed through the substitutionMap
parameter parameter
@param action
@param feat
@param layer
@param substitutionMap
@param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
and area conversion
*/ */
static QString replaceExpressionText( const QString &action, const QgsFeature *feat, static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
QgsVectorLayer *layer, QgsVectorLayer *layer,
const QMap<QString, QVariant> *substitutionMap = 0 ); const QMap<QString, QVariant> *substitutionMap = 0,
const QgsDistanceArea* distanceArea = 0
);
enum UnaryOperator enum UnaryOperator
{ {
uoNot, uoNot,