Skip to content

Commit a3dd380

Browse files
committedJan 18, 2017
[needs-docs] Composer maps default to a "use project CRS" setting
And overriding projection is only done if user has manually chosen a different CRS from the list. This means that templates and compositions in server can still adapt to follow the project CRS, but if desired specific map items (eg an overview map) can use the CRS override to always show in a particular CRS.
1 parent 6a4d605 commit a3dd380

File tree

7 files changed

+60
-18
lines changed

7 files changed

+60
-18
lines changed
 

‎python/core/composer/qgscomposermap.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class QgsComposerMap : QgsComposerItem
128128
// QgsRectangle* currentMapExtent();
129129

130130
QgsCoordinateReferenceSystem crs() const;
131+
QgsCoordinateReferenceSystem presetCrs() const;
131132
void setCrs( const QgsCoordinateReferenceSystem& crs );
132133

133134
PreviewMode previewMode() const;

‎src/app/composer/qgscomposermapwidget.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap )
6464
mPreviewModeComboBox->insertItem( 1, tr( "Render" ) );
6565
mPreviewModeComboBox->insertItem( 2, tr( "Rectangle" ) );
6666

67+
mCrsSelector->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, true );
68+
mCrsSelector->setNotSetText( tr( "Use project CRS" ) );
69+
6770
// follow preset combo
6871
mFollowVisibilityPresetCombo->setModel( new QStringListModel( mFollowVisibilityPresetCombo ) );
6972
connect( mFollowVisibilityPresetCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( followVisibilityPresetSelected( int ) ) );
@@ -270,7 +273,7 @@ void QgsComposerMapWidget::mapCrsChanged( const QgsCoordinateReferenceSystem& cr
270273
return;
271274
}
272275

273-
if ( mComposerMap->crs() == crs )
276+
if ( mComposerMap->presetCrs() == crs )
274277
return;
275278

276279
// try to reproject to maintain extent
@@ -280,7 +283,7 @@ void QgsComposerMapWidget::mapCrsChanged( const QgsCoordinateReferenceSystem& cr
280283
QgsRectangle newExtent;
281284
try
282285
{
283-
QgsCoordinateTransform xForm( oldCrs, crs );
286+
QgsCoordinateTransform xForm( oldCrs, crs.isValid() ? crs : QgsProject::instance()->crs() );
284287
QgsRectangle prevExtent = *mComposerMap->currentMapExtent();
285288
newExtent = xForm.transformBoundingBox( prevExtent );
286289
updateExtent = true;
@@ -605,7 +608,7 @@ void QgsComposerMapWidget::updateGuiElements()
605608

606609
blockAllSignals( true );
607610

608-
whileBlocking( mCrsSelector )->setCrs( mComposerMap->crs() );
611+
whileBlocking( mCrsSelector )->setCrs( mComposerMap->presetCrs() );
609612

610613
//width, height, scale
611614
double scale = mComposerMap->scale();

‎src/core/composer/qgscomposermap.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,6 @@ QgsComposerMap::QgsComposerMap( QgsComposition *composition )
124124

125125
void QgsComposerMap::init()
126126
{
127-
if ( mComposition && mComposition->project() )
128-
mCrs = mComposition->project()->crs();
129-
130127
mGridStack = new QgsComposerMapGridStack( this );
131128
mOverviewStack = new QgsComposerMapOverviewStack( this );
132129
connectUpdateSlot();
@@ -204,14 +201,15 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, QSizeF
204201
QgsMapSettings QgsComposerMap::mapSettings( const QgsRectangle& extent, QSizeF size, int dpi ) const
205202
{
206203
QgsExpressionContext expressionContext = createExpressionContext();
204+
QgsCoordinateReferenceSystem renderCrs = crs();
207205

208206
QgsMapSettings jobMapSettings;
209-
jobMapSettings.setDestinationCrs( mCrs );
207+
jobMapSettings.setDestinationCrs( renderCrs );
210208
jobMapSettings.setCrsTransformEnabled( true );
211209
jobMapSettings.setExtent( extent );
212210
jobMapSettings.setOutputSize( size.toSize() );
213211
jobMapSettings.setOutputDpi( dpi );
214-
jobMapSettings.setMapUnits( mCrs.mapUnits() );
212+
jobMapSettings.setMapUnits( renderCrs.mapUnits() );
215213
jobMapSettings.setBackgroundColor( Qt::transparent );
216214
jobMapSettings.setRotation( mEvaluatedMapRotation );
217215

@@ -253,7 +251,7 @@ QgsMapSettings QgsComposerMap::mapSettings( const QgsRectangle& extent, QSizeF s
253251
jobMapSettings.setFlag( QgsMapSettings::DrawSelection, false );
254252
jobMapSettings.setFlag( QgsMapSettings::UseAdvancedEffects, mComposition->useAdvancedEffects() ); // respect the composition's useAdvancedEffects flag
255253

256-
jobMapSettings.datumTransformStore().setDestinationCrs( mCrs );
254+
jobMapSettings.datumTransformStore().setDestinationCrs( renderCrs );
257255

258256
return jobMapSettings;
259257
}
@@ -873,7 +871,11 @@ QgsRectangle* QgsComposerMap::currentMapExtent()
873871

874872
QgsCoordinateReferenceSystem QgsComposerMap::crs() const
875873
{
876-
return mCrs;
874+
if ( mCrs.isValid() )
875+
return mCrs;
876+
else if ( mComposition && mComposition->project() )
877+
return mComposition->project()->crs();
878+
return QgsCoordinateReferenceSystem();
877879
}
878880

879881
void QgsComposerMap::setCrs( const QgsCoordinateReferenceSystem& crs )
@@ -1271,9 +1273,12 @@ bool QgsComposerMap::writeXml( QDomElement& elem, QDomDocument & doc ) const
12711273
extentElem.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mExtent.yMaximum() ) );
12721274
composerMapElem.appendChild( extentElem );
12731275

1274-
QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
1275-
mCrs.writeXml( crsElem, doc );
1276-
composerMapElem.appendChild( crsElem );
1276+
if ( mCrs.isValid() )
1277+
{
1278+
QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
1279+
mCrs.writeXml( crsElem, doc );
1280+
composerMapElem.appendChild( crsElem );
1281+
}
12771282

12781283
// follow map theme
12791284
composerMapElem.setAttribute( QStringLiteral( "followPreset" ), mFollowVisibilityPreset ? "true" : "false" );
@@ -1382,6 +1387,10 @@ bool QgsComposerMap::readXml( const QDomElement& itemElem, const QDomDocument& d
13821387
QDomElement crsElem = crsNodeList.at( 0 ).toElement();
13831388
mCrs.readXml( crsElem );
13841389
}
1390+
else
1391+
{
1392+
mCrs = QgsCoordinateReferenceSystem();
1393+
}
13851394

13861395
//map rotation
13871396
if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )

‎src/core/composer/qgscomposermap.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,33 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
168168
QgsRectangle* currentMapExtent();
169169

170170
/**
171-
* Returns the map's coordinate reference system.
171+
* Returns coordinate reference system used for rendering the map.
172+
* This will match the presetCrs() if that is set, or if a preset
173+
* CRS is not set then the map's CRS will follow the composition's
174+
* project's CRS.
172175
* @note added in QGIS 3.0
176+
* @see presetCrs()
173177
* @see setCrs()
174178
*/
175179
QgsCoordinateReferenceSystem crs() const;
176180

177181
/**
178-
* Sets the map's coordinate reference system.
182+
* Returns the map's preset coordinate reference system. If set, this
183+
* CRS will be used to render the map regardless of any project CRS
184+
* setting. If the returned CRS is not valid then the project CRS
185+
* will be used to render the map.
186+
* @note added in QGIS 3.0
187+
* @see crs()
188+
* @see setCrs()
189+
*/
190+
QgsCoordinateReferenceSystem presetCrs() const { return mCrs; }
191+
192+
/**
193+
* Sets the map's preset coordinate reference system. If a valid CRS is
194+
* set, this CRS will be used to render the map regardless of any project CRS
195+
* setting. If the CRS is not valid then the project CRS will be used to render the map.
179196
* @see crs()
197+
* @see presetCrs()
180198
* @note added in QGIS 3.0
181199
*/
182200
void setCrs( const QgsCoordinateReferenceSystem& crs );

‎src/gui/qgsprojectionselectionwidget.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
223223
}
224224
case QgsProjectionSelectionWidget::CrsNotSet:
225225
emit cleared();
226+
emit crsChanged( QgsCoordinateReferenceSystem() );
226227
return;
227228
}
228229
}

‎src/server/qgswmsconfigparser.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,10 @@ QgsComposition* QgsWmsConfigParser::createPrintComposition( const QString& compo
7979
continue;
8080
}
8181

82-
// Change CRS of map to match requested CRS
83-
if ( mapSettings.destinationCrs().isValid() )
82+
// Change CRS of map set to "project CRS" to match requested CRS
83+
// (if map has a valid preset crs then we keep this crs and don't use the
84+
// requested crs for this map item)
85+
if ( mapSettings.destinationCrs().isValid() && !currentMap->presetCrs().isValid() )
8486
currentMap->setCrs( mapSettings.destinationCrs() );
8587

8688
QStringList coordList = extent.split( QStringLiteral( "," ) );

‎tests/src/python/test_qgscomposermap.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,25 +156,33 @@ def testMapCrs(self):
156156
composition.addComposerMap(map)
157157

158158
self.assertEqual(map.crs().authid(), 'EPSG:4326')
159+
self.assertFalse(map.presetCrs().isValid())
159160

160161
# overwrite CRS
161162
map.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
162163
self.assertEqual(map.crs().authid(), 'EPSG:3857')
164+
self.assertEqual(map.presetCrs().authid(), 'EPSG:3857')
163165
checker = QgsCompositionChecker('composermap_crs3857', composition)
164166
checker.setControlPathPrefix("composer_map")
165167
result, message = checker.testComposition()
166168
self.assertTrue(result, message)
167169

168170
# overwrite CRS
169171
map.setCrs(QgsCoordinateReferenceSystem('EPSG:4326'))
172+
self.assertEqual(map.presetCrs().authid(), 'EPSG:4326')
173+
self.assertEqual(map.crs().authid(), 'EPSG:4326')
170174
rectangle = QgsRectangle(-124, 17, -78, 52)
171175
map.zoomToExtent(rectangle)
172-
self.assertEqual(map.crs().authid(), 'EPSG:4326')
173176
checker = QgsCompositionChecker('composermap_crs4326', composition)
174177
checker.setControlPathPrefix("composer_map")
175178
result, message = checker.testComposition()
176179
self.assertTrue(result, message)
177180

181+
# change back to project CRS
182+
map.setCrs(QgsCoordinateReferenceSystem())
183+
self.assertEqual(map.crs().authid(), 'EPSG:4326')
184+
self.assertFalse(map.presetCrs().isValid())
185+
178186
# Fails because addItemsFromXml has been commented out in sip
179187
@unittest.expectedFailure
180188
def testuniqueId(self):

0 commit comments

Comments
 (0)
Please sign in to comment.