Skip to content

Commit ce2891b

Browse files
committedApr 11, 2016
Fix missing map settings expression variables in composer maps
Missing map extent related variables were causing stacking order issues with the 25d renderer (fix #14604)
1 parent 1ed39c4 commit ce2891b

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed
 

‎src/core/composer/qgscomposermap.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2151,6 +2151,14 @@ QgsExpressionContext* QgsComposerMap::createExpressionContext() const
21512151
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_id", QgsComposerItem::id(), true ) );
21522152
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_rotation", mMapRotation, true ) );
21532153
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_scale", scale(), true ) );
2154+
2155+
QgsRectangle extent( *currentMapExtent() );
2156+
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_width", extent.width(), true ) );
2157+
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_height", extent.height(), true ) );
2158+
QgsGeometry* centerPoint = QgsGeometry::fromPoint( extent.center() );
2159+
scope->addVariable( QgsExpressionContextScope::StaticVariable( "map_extent_center", QVariant::fromValue( *centerPoint ), true ) );
2160+
delete centerPoint;
2161+
21542162
context->appendScope( scope );
21552163

21562164
return context;

‎src/core/qgsexpressioncontext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,9 @@ void QgsExpressionContextUtils::setLayerVariables( QgsMapLayer* layer, const Qgs
713713

714714
QgsExpressionContextScope* QgsExpressionContextUtils::mapSettingsScope( const QgsMapSettings& mapSettings )
715715
{
716+
// IMPORTANT: ANY CHANGES HERE ALSO NEED TO BE MADE TO QgsComposerMap::createExpressionContext()
717+
// (rationale is described in QgsComposerMap::createExpressionContext() )
718+
716719
QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Map Settings" ) );
717720

718721
//add known map settings context variables

‎tests/src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ ENDMACRO (ADD_QGIS_TEST)
8484
#############################################################
8585
# Tests:
8686

87+
ADD_QGIS_TEST(25drenderertest testqgs25drenderer.cpp)
8788
ADD_QGIS_TEST(applicationtest testqgsapplication.cpp)
8889
ADD_QGIS_TEST(atlascompositiontest testqgsatlascomposition.cpp)
8990
ADD_QGIS_TEST(authcryptotest testqgsauthcrypto.cpp)

‎tests/src/core/testqgs25drenderer.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/***************************************************************************
2+
testqgs25drenderer.cpp
3+
--------------------------------------
4+
Date : April 2016
5+
Copyright : (C) 2016 by Nyall Dawson
6+
Email : nyall dot dawson at gmail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
#include <QtTest/QtTest>
16+
#include <QObject>
17+
#include <QString>
18+
#include <QStringList>
19+
#include <QApplication>
20+
#include <QFileInfo>
21+
#include <QDir>
22+
#include <QDesktopServices>
23+
24+
//qgis includes...
25+
#include <qgsmapsettings.h>
26+
#include <qgsmaplayer.h>
27+
#include <qgsvectorlayer.h>
28+
#include <qgsapplication.h>
29+
#include <qgsproviderregistry.h>
30+
#include <qgsmaplayerregistry.h>
31+
#include <qgssymbolv2.h>
32+
#include <qgs25drenderer.h>
33+
#include "qgscomposition.h"
34+
#include "qgscomposermap.h"
35+
#include "qgsmultirenderchecker.h"
36+
37+
/** \ingroup UnitTests
38+
* This is a unit test for 25d renderer.
39+
*/
40+
class TestQgs25DRenderer : public QObject
41+
{
42+
Q_OBJECT
43+
public:
44+
TestQgs25DRenderer()
45+
: mpPolysLayer( nullptr )
46+
{}
47+
48+
private slots:
49+
void initTestCase();// will be called before the first testfunction is executed.
50+
void cleanupTestCase();// will be called after the last testfunction was executed.
51+
void init() {} // will be called before each testfunction is executed.
52+
void cleanup() {} // will be called after every testfunction.
53+
54+
void render();
55+
void renderComposition();
56+
57+
private:
58+
bool imageCheck( const QString& theType );
59+
QgsMapSettings mMapSettings;
60+
QgsVectorLayer * mpPolysLayer;
61+
QString mTestDataDir;
62+
QString mReport;
63+
};
64+
65+
66+
void TestQgs25DRenderer::initTestCase()
67+
{
68+
// init QGIS's paths - true means that all path will be inited from prefix
69+
QgsApplication::init();
70+
QgsApplication::initQgis();
71+
QgsApplication::showSettings();
72+
73+
//create some objects that will be used in all tests...
74+
QString myDataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
75+
mTestDataDir = myDataDir + '/';
76+
77+
//
78+
//create a poly layer that will be used in all tests...
79+
//
80+
QString myPolysFileName = mTestDataDir + "polys.shp";
81+
QFileInfo myPolyFileInfo( myPolysFileName );
82+
mpPolysLayer = new QgsVectorLayer( myPolyFileInfo.filePath(),
83+
myPolyFileInfo.completeBaseName(), "ogr" );
84+
85+
QgsVectorSimplifyMethod simplifyMethod;
86+
simplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
87+
mpPolysLayer->setSimplifyMethod( simplifyMethod );
88+
89+
//need a very high height to check for stacking
90+
QgsExpressionContextUtils::setLayerVariable( mpPolysLayer, "qgis_25d_height", 8 );
91+
QgsExpressionContextUtils::setLayerVariable( mpPolysLayer, "qgis_25d_angle", 45 );
92+
93+
// Register the layer with the registry
94+
QgsMapLayerRegistry::instance()->addMapLayers(
95+
QList<QgsMapLayer *>() << mpPolysLayer );
96+
97+
mMapSettings.setLayers( QStringList() << mpPolysLayer->id() );
98+
mReport += "<h1>25D Renderer Tests</h1>\n";
99+
100+
}
101+
void TestQgs25DRenderer::cleanupTestCase()
102+
{
103+
QString myReportFile = QDir::tempPath() + "/qgistest.html";
104+
QFile myFile( myReportFile );
105+
if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
106+
{
107+
QTextStream myQTextStream( &myFile );
108+
myQTextStream << mReport;
109+
myFile.close();
110+
}
111+
112+
QgsApplication::exitQgis();
113+
}
114+
115+
void TestQgs25DRenderer::render()
116+
{
117+
mReport += "<h2>Render</h2>\n";
118+
119+
//setup 25d renderer
120+
Qgs25DRenderer* renderer = new Qgs25DRenderer( );
121+
renderer->setShadowEnabled( false );
122+
renderer->setWallShadingEnabled( false );
123+
mpPolysLayer->setRendererV2( renderer );
124+
125+
QVERIFY( imageCheck( "25d_render" ) );
126+
}
127+
128+
void TestQgs25DRenderer::renderComposition()
129+
{
130+
QgsComposition* composition = new QgsComposition( mMapSettings );
131+
composition->setPaperSize( 297, 210 ); //A4 landscape
132+
QgsComposerMap* map = new QgsComposerMap( composition, 20, 20, 200, 100 );
133+
map->setFrameEnabled( true );
134+
composition->addComposerMap( map );
135+
136+
map->setNewExtent( mpPolysLayer->extent() );
137+
QgsCompositionChecker checker( "25d_composer", composition );
138+
checker.setControlPathPrefix( "25d_renderer" );
139+
140+
QVERIFY( checker.testComposition( mReport, 0, 100 ) );
141+
}
142+
143+
bool TestQgs25DRenderer::imageCheck( const QString& theTestType )
144+
{
145+
//use the QgsRenderChecker test utility class to
146+
//ensure the rendered output matches our control image
147+
mMapSettings.setExtent( mpPolysLayer->extent() );
148+
mMapSettings.setOutputDpi( 96 );
149+
QgsExpressionContext context;
150+
context << QgsExpressionContextUtils::mapSettingsScope( mMapSettings );
151+
mMapSettings.setExpressionContext( context );
152+
QgsMultiRenderChecker myChecker;
153+
myChecker.setControlPathPrefix( "25d_renderer" );
154+
myChecker.setControlName( "expected_" + theTestType );
155+
myChecker.setMapSettings( mMapSettings );
156+
myChecker.setColorTolerance( 20 );
157+
bool myResultFlag = myChecker.runTest( theTestType, 500 );
158+
mReport += myChecker.report();
159+
return myResultFlag;
160+
}
161+
162+
QTEST_MAIN( TestQgs25DRenderer )
163+
#include "testqgs25drenderer.moc"
Loading
Loading

0 commit comments

Comments
 (0)
Failed to load comments.