Skip to content

Commit 0cb9854

Browse files
committed
[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.
1 parent fad44d0 commit 0cb9854

File tree

7 files changed

+90
-13
lines changed

7 files changed

+90
-13
lines changed

python/core/qgsexpression.sip

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,26 @@ class QgsExpression
9090
//! Sets the geometry calculator used in evaluation of expressions,
9191
// instead of the default.
9292
void setGeomCalculator( const QgsDistanceArea &calc );
93-
93+
9494
/** This function currently replaces each expression between [% and %]
9595
in the string with the result of its evaluation on the feature
9696
passed as argument.
9797

9898
Additional substitutions can be passed through the substitutionMap
9999
parameter
100+
@param action
101+
@param feat
102+
@param layer
103+
@param substitutionMap
104+
@param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
105+
and area conversion
100106
*/
101107
static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
102108
QgsVectorLayer *layer,
103-
const QMap<QString, QVariant> *substitutionMap = 0 );
109+
const QMap<QString, QVariant> *substitutionMap = 0,
110+
const QgsDistanceArea* distanceArea = 0
111+
);
112+
104113
enum UnaryOperator
105114
{
106115
uoNot,

src/core/composer/qgscomposerhtml.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "qgsexpression.h"
2323
#include "qgslogger.h"
2424
#include "qgsnetworkcontentfetcher.h"
25+
#include "qgsvectorlayer.h"
26+
#include "qgsproject.h"
2527

2628
#include <QCoreApplication>
2729
#include <QPainter>
@@ -42,9 +44,11 @@ QgsComposerHtml::QgsComposerHtml( QgsComposition* c, bool createUndoCommands )
4244
, mMaxBreakDistance( 10 )
4345
, mExpressionFeature( 0 )
4446
, mExpressionLayer( 0 )
47+
, mDistanceArea( 0 )
4548
, mEnableUserStylesheet( false )
4649
, mFetcher( 0 )
4750
{
51+
mDistanceArea = new QgsDistanceArea();
4852
mHtmlUnitsToMM = htmlUnitsToMM();
4953
mWebPage = new QWebPage();
5054
mWebPage->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
@@ -92,14 +96,17 @@ QgsComposerHtml::QgsComposerHtml()
9296
, mMaxBreakDistance( 10 )
9397
, mExpressionFeature( 0 )
9498
, mExpressionLayer( 0 )
99+
, mDistanceArea( 0 )
95100
, mFetcher( 0 )
96101
{
102+
mDistanceArea = new QgsDistanceArea();
97103
mFetcher = new QgsNetworkContentFetcher();
98104
connect( mFetcher, SIGNAL( finished() ), this, SLOT( frameLoaded() ) );
99105
}
100106

101107
QgsComposerHtml::~QgsComposerHtml()
102108
{
109+
delete mDistanceArea;
103110
delete mWebPage;
104111
delete mRenderedPage;
105112
mFetcher->deleteLater();
@@ -179,7 +186,7 @@ void QgsComposerHtml::loadHtml()
179186
//evaluate expressions
180187
if ( mEvaluateExpressions )
181188
{
182-
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer );
189+
loadedHtml = QgsExpression::replaceExpressionText( loadedHtml, mExpressionFeature, mExpressionLayer, 0, mDistanceArea );
183190
}
184191

185192
mLoaded = false;
@@ -522,6 +529,22 @@ void QgsComposerHtml::setExpressionContext( QgsFeature* feature, QgsVectorLayer*
522529
{
523530
mExpressionFeature = feature;
524531
mExpressionLayer = layer;
532+
533+
//setup distance area conversion
534+
if ( layer )
535+
{
536+
mDistanceArea->setSourceCrs( layer->crs().srsid() );
537+
}
538+
else if ( mComposition )
539+
{
540+
//set to composition's mapsettings' crs
541+
mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
542+
}
543+
if ( mComposition )
544+
{
545+
mDistanceArea->setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
546+
}
547+
mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
525548
}
526549

527550
void QgsComposerHtml::refreshExpressionContext()

src/core/composer/qgscomposerhtml.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QImage;
2424
class QgsFeature;
2525
class QgsVectorLayer;
2626
class QgsNetworkContentFetcher;
27+
class QgsDistanceArea;
2728

2829
class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
2930
{
@@ -242,6 +243,8 @@ class CORE_EXPORT QgsComposerHtml: public QgsComposerMultiFrame
242243

243244
QgsFeature* mExpressionFeature;
244245
QgsVectorLayer* mExpressionLayer;
246+
QgsDistanceArea* mDistanceArea;
247+
245248
QString mUserStylesheet;
246249
bool mEnableUserStylesheet;
247250

src/core/composer/qgscomposerlabel.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "qgsexpression.h"
2222
#include "qgsnetworkaccessmanager.h"
2323
#include "qgscomposermodel.h"
24+
#include "qgsvectorlayer.h"
25+
#include "qgsproject.h"
2426

2527
#include <QCoreApplication>
2628
#include <QDate>
@@ -32,12 +34,20 @@
3234
#include <QWebPage>
3335
#include <QEventLoop>
3436

35-
QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ):
36-
QgsComposerItem( composition ), mHtmlState( 0 ), mHtmlUnitsToMM( 1.0 ),
37-
mHtmlLoaded( false ), mMargin( 1.0 ), mFontColor( QColor( 0, 0, 0 ) ),
38-
mHAlignment( Qt::AlignLeft ), mVAlignment( Qt::AlignTop ),
39-
mExpressionFeature( 0 ), mExpressionLayer( 0 )
37+
QgsComposerLabel::QgsComposerLabel( QgsComposition *composition )
38+
: QgsComposerItem( composition )
39+
, mHtmlState( 0 )
40+
, mHtmlUnitsToMM( 1.0 )
41+
, mHtmlLoaded( false )
42+
, mMargin( 1.0 )
43+
, mFontColor( QColor( 0, 0, 0 ) )
44+
, mHAlignment( Qt::AlignLeft )
45+
, mVAlignment( Qt::AlignTop )
46+
, mExpressionFeature( 0 )
47+
, mExpressionLayer( 0 )
48+
, mDistanceArea( 0 )
4049
{
50+
mDistanceArea = new QgsDistanceArea();
4151
mHtmlUnitsToMM = htmlUnitsToMM();
4252

4353
//get default composer font from settings
@@ -71,6 +81,7 @@ QgsComposerLabel::QgsComposerLabel( QgsComposition *composition ):
7181

7282
QgsComposerLabel::~QgsComposerLabel()
7383
{
84+
delete mDistanceArea;
7485
}
7586

7687
void QgsComposerLabel::paint( QPainter* painter, const QStyleOptionGraphicsItem* itemStyle, QWidget* pWidget )
@@ -221,6 +232,23 @@ void QgsComposerLabel::setExpressionContext( QgsFeature* feature, QgsVectorLayer
221232
mExpressionFeature = feature;
222233
mExpressionLayer = layer;
223234
mSubstitutions = substitutions;
235+
236+
//setup distance area conversion
237+
if ( layer )
238+
{
239+
mDistanceArea->setSourceCrs( layer->crs().srsid() );
240+
}
241+
else if ( mComposition )
242+
{
243+
//set to composition's mapsettings' crs
244+
mDistanceArea->setSourceCrs( mComposition->mapSettings().destinationCrs().srsid() );
245+
}
246+
if ( mComposition )
247+
{
248+
mDistanceArea->setEllipsoidalMode( mComposition->mapSettings().hasCrsTransformEnabled() );
249+
}
250+
mDistanceArea->setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
251+
224252
// Force label to redraw -- fixes label printing for labels with blend modes when used with atlas
225253
update();
226254
}
@@ -248,7 +276,7 @@ QString QgsComposerLabel::displayText() const
248276
replaceDateText( displayText );
249277
QMap<QString, QVariant> subs = mSubstitutions;
250278
subs[ "$page" ] = QVariant(( int )mComposition->itemPageNumber( this ) + 1 );
251-
return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer, &subs );
279+
return QgsExpression::replaceExpressionText( displayText, mExpressionFeature, mExpressionLayer, &subs, mDistanceArea );
252280
}
253281

254282
void QgsComposerLabel::replaceDateText( QString& text ) const

src/core/composer/qgscomposerlabel.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
class QgsVectorLayer;
2424
class QgsFeature;
25+
class QgsDistanceArea;
2526

2627
/** \ingroup MapComposer
2728
* A label that can be placed onto a map composition.
@@ -143,8 +144,7 @@ class CORE_EXPORT QgsComposerLabel: public QgsComposerItem
143144
QgsFeature* mExpressionFeature;
144145
QgsVectorLayer* mExpressionLayer;
145146
QMap<QString, QVariant> mSubstitutions;
146-
147-
147+
QgsDistanceArea* mDistanceArea;
148148
};
149149

150150
#endif

src/core/qgsexpression.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1989,7 +1989,7 @@ void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const
19891989

19901990
QString QgsExpression::replaceExpressionText( const QString &action, const QgsFeature *feat,
19911991
QgsVectorLayer *layer,
1992-
const QMap<QString, QVariant> *substitutionMap )
1992+
const QMap<QString, QVariant> *substitutionMap , const QgsDistanceArea *distanceArea )
19931993
{
19941994
QString expr_action;
19951995

@@ -2030,6 +2030,12 @@ QString QgsExpression::replaceExpressionText( const QString &action, const QgsFe
20302030
continue;
20312031
}
20322032

2033+
if ( distanceArea )
2034+
{
2035+
//if QgsDistanceArea specified for area/distance conversion, use it
2036+
exp.setGeomCalculator( *distanceArea );
2037+
}
2038+
20332039
QVariant result;
20342040
if ( layer )
20352041
{

src/core/qgsexpression.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,18 @@ class CORE_EXPORT QgsExpression
183183
184184
Additional substitutions can be passed through the substitutionMap
185185
parameter
186+
@param action
187+
@param feat
188+
@param layer
189+
@param substitutionMap
190+
@param distanceArea optional QgsDistanceArea. If specified, the QgsDistanceArea is used for distance
191+
and area conversion
186192
*/
187193
static QString replaceExpressionText( const QString &action, const QgsFeature *feat,
188194
QgsVectorLayer *layer,
189-
const QMap<QString, QVariant> *substitutionMap = 0 );
195+
const QMap<QString, QVariant> *substitutionMap = 0,
196+
const QgsDistanceArea* distanceArea = 0
197+
);
190198
enum UnaryOperator
191199
{
192200
uoNot,

0 commit comments

Comments
 (0)