QGIS API Documentation  2.99.0-Master (a18066b)
qgscomposermap.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscomposermap.cpp
3  -------------------
4  begin : January 2005
5  copyright : (C) 2005 by Radim Blazek
6  email : [email protected]
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgscomposermap.h"
19 #include "qgscomposermapgrid.h"
20 #include "qgscomposermapoverview.h"
21 #include "qgscomposition.h"
22 #include "qgscomposerutils.h"
23 #include "qgslogger.h"
25 #include "qgsmaplayerlistutils.h"
27 #include "qgsmaptopixel.h"
28 #include "qgspainting.h"
29 #include "qgsproject.h"
30 #include "qgsrasterdataprovider.h"
31 #include "qgsrasterlayer.h"
32 #include "qgsrendercontext.h"
33 #include "qgsscalecalculator.h"
34 #include "qgsvectorlayer.h"
35 #include "qgspallabeling.h"
36 #include "qgsexpression.h"
37 #include "qgsmapthemecollection.h"
38 #include "qgsannotation.h"
39 #include "qgsannotationmanager.h"
40 
41 #include "qgssymbollayerutils.h" //for pointOnLineWithDistance
42 
43 #include <QGraphicsScene>
44 #include <QGraphicsView>
45 #include <QPainter>
46 #include <QSettings>
47 #include <cmath>
48 
49 QgsComposerMap::QgsComposerMap( QgsComposition *composition, int x, int y, int width, int height )
50  : QgsComposerItem( x, y, width, height, composition )
51 {
52  assignFreeId();
53 
54  mCurrentRectangle = rect();
55 
56  QgsProject* project = mComposition->project();
57 
58  //get the color for map canvas background and set map background color accordingly
59  int bgRedInt = project->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorRedPart" ), 255 );
60  int bgGreenInt = project->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorGreenPart" ), 255 );
61  int bgBlueInt = project->readNumEntry( QStringLiteral( "Gui" ), QStringLiteral( "/CanvasColorBluePart" ), 255 );
62  setBackgroundColor( QColor( bgRedInt, bgGreenInt, bgBlueInt ) );
63 
64  init();
65 
66  setSceneRect( QRectF( x, y, width, height ) );
67 }
68 
70  : QgsComposerItem( 0, 0, 10, 10, composition )
71 {
72  mId = mComposition->composerMapItems().size();
73  mCurrentRectangle = rect();
74 
75  init();
76  updateToolTip();
77 }
78 
79 void QgsComposerMap::init()
80 {
81  mGridStack = new QgsComposerMapGridStack( this );
82  mOverviewStack = new QgsComposerMapOverviewStack( this );
83  connectUpdateSlot();
84 }
85 
86 void QgsComposerMap::updateToolTip()
87 {
88  setToolTip( tr( "Map %1" ).arg( mId ) );
89 }
90 
91 void QgsComposerMap::adjustExtentToItemShape( double itemWidth, double itemHeight, QgsRectangle& extent ) const
92 {
93  double itemWidthHeightRatio = itemWidth / itemHeight;
94  double newWidthHeightRatio = extent.width() / extent.height();
95 
96  if ( itemWidthHeightRatio <= newWidthHeightRatio )
97  {
98  //enlarge height of new extent, ensuring the map center stays the same
99  double newHeight = extent.width() / itemWidthHeightRatio;
100  double deltaHeight = newHeight - extent.height();
101  extent.setYMinimum( extent.yMinimum() - deltaHeight / 2 );
102  extent.setYMaximum( extent.yMaximum() + deltaHeight / 2 );
103  }
104  else
105  {
106  //enlarge width of new extent, ensuring the map center stays the same
107  double newWidth = itemWidthHeightRatio * extent.height();
108  double deltaWidth = newWidth - extent.width();
109  extent.setXMinimum( extent.xMinimum() - deltaWidth / 2 );
110  extent.setXMaximum( extent.xMaximum() + deltaWidth / 2 );
111  }
112 }
113 
115 {
116  delete mOverviewStack;
117  delete mGridStack;
118 }
119 
120 /* This function is called by paint() and cache() to render the map. It does not override any functions
121 from QGraphicsItem. */
122 void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, QSizeF size, double dpi, double* forceWidthScale )
123 {
124  Q_UNUSED( forceWidthScale );
125 
126  if ( !painter )
127  {
128  return;
129  }
130  if ( qgsDoubleNear( size.width(), 0.0 ) || qgsDoubleNear( size.height(), 0.0 ) )
131  {
132  //don't attempt to draw if size is invalid
133  return;
134  }
135 
136  // render
137  QgsMapRendererCustomPainterJob job( mapSettings( extent, size, dpi ), painter );
138  // Render the map in this thread. This is done because of problems
139  // with printing to printer on Windows (printing to PDF is fine though).
140  // Raster images were not displayed - see #10599
141  job.renderSynchronously();
142 }
143 
144 QgsMapSettings QgsComposerMap::mapSettings( const QgsRectangle& extent, QSizeF size, int dpi ) const
145 {
146  QgsExpressionContext expressionContext = createExpressionContext();
147  QgsCoordinateReferenceSystem renderCrs = crs();
148 
149  QgsMapSettings jobMapSettings;
150  jobMapSettings.setDestinationCrs( renderCrs );
151  jobMapSettings.setCrsTransformEnabled( true );
152  jobMapSettings.setExtent( extent );
153  jobMapSettings.setOutputSize( size.toSize() );
154  jobMapSettings.setOutputDpi( dpi );
155  jobMapSettings.setMapUnits( renderCrs.mapUnits() );
156  jobMapSettings.setBackgroundColor( Qt::transparent );
157  jobMapSettings.setRotation( mEvaluatedMapRotation );
158 
159  //set layers to render
160  QList<QgsMapLayer*> layers = layersToRender( &expressionContext );
161  if ( -1 != mCurrentExportLayer )
162  {
163  const int layerIdx = mCurrentExportLayer - ( hasBackground() ? 1 : 0 );
164  if ( layerIdx >= 0 && layerIdx < layers.length() )
165  {
166  // exporting with separate layers (e.g., to svg layers), so we only want to render a single map layer
167  QgsMapLayer* ml = layers[ layers.length() - layerIdx - 1 ];
168  layers.clear();
169  layers << ml;
170  }
171  else
172  {
173  // exporting decorations such as map frame/grid/overview, so no map layers required
174  layers.clear();
175  }
176  }
177  jobMapSettings.setLayers( layers );
178  jobMapSettings.setLayerStyleOverrides( layerStyleOverridesToRender( expressionContext ) );
179 
182  {
183  //if outputting composer, disable optimisations like layer simplification
184  jobMapSettings.setFlag( QgsMapSettings::UseRenderingOptimization, false );
185  }
186 
188  jobMapSettings.setExpressionContext( context );
189 
190  // composer-specific overrides of flags
191  jobMapSettings.setFlag( QgsMapSettings::ForceVectorOutput, true ); // force vector output (no caching of marker images etc.)
192  jobMapSettings.setFlag( QgsMapSettings::Antialiasing, true );
193  jobMapSettings.setFlag( QgsMapSettings::DrawEditingInfo, false );
194  jobMapSettings.setFlag( QgsMapSettings::DrawSelection, false );
195  jobMapSettings.setFlag( QgsMapSettings::UseAdvancedEffects, mComposition->useAdvancedEffects() ); // respect the composition's useAdvancedEffects flag
196 
197  jobMapSettings.datumTransformStore().setDestinationCrs( renderCrs );
198 
199  return jobMapSettings;
200 }
201 
203 {
204  if ( mPreviewMode == Rectangle )
205  {
206  return;
207  }
208 
209  if ( mDrawing )
210  {
211  return;
212  }
213 
214  mDrawing = true;
215 
216  double horizontalVScaleFactor = horizontalViewScaleFactor();
217  if ( horizontalVScaleFactor < 0 )
218  {
219  //make sure scale factor is positive
220  horizontalVScaleFactor = mLastValidViewScaleFactor > 0 ? mLastValidViewScaleFactor : 1;
221  }
222 
223  const QgsRectangle &ext = *currentMapExtent();
224  double widthMM = ext.width() * mapUnitsToMM();
225  double heightMM = ext.height() * mapUnitsToMM();
226 
227  int w = widthMM * horizontalVScaleFactor;
228  int h = heightMM * horizontalVScaleFactor;
229 
230  // limit size of image for better performance
231  if ( w > 5000 || h > 5000 )
232  {
233  if ( w > h )
234  {
235  w = 5000;
236  h = w * heightMM / widthMM;
237  }
238  else
239  {
240  h = 5000;
241  w = h * widthMM / heightMM;
242  }
243  }
244 
245  mCacheImage = QImage( w, h, QImage::Format_ARGB32 );
246 
247  // set DPI of the image
248  mCacheImage.setDotsPerMeterX( 1000 * w / widthMM );
249  mCacheImage.setDotsPerMeterY( 1000 * h / heightMM );
250 
251  if ( hasBackground() )
252  {
253  //Initially fill image with specified background color. This ensures that layers with blend modes will
254  //preview correctly
255  mCacheImage.fill( backgroundColor().rgba() );
256  }
257  else
258  {
259  //no background, but start with empty fill to avoid artifacts
260  mCacheImage.fill( QColor( 255, 255, 255, 0 ).rgba() );
261  }
262 
263  QPainter p( &mCacheImage );
264 
265  draw( &p, ext, QSizeF( w, h ), mCacheImage.logicalDpiX() );
266  p.end();
267  mCacheUpdated = true;
268 
269  mDrawing = false;
270 }
271 
272 void QgsComposerMap::paint( QPainter* painter, const QStyleOptionGraphicsItem*, QWidget* pWidget )
273 {
274  Q_UNUSED( pWidget );
275 
276  if ( !mComposition || !painter )
277  {
278  return;
279  }
280  if ( !shouldDrawItem() )
281  {
282  return;
283  }
284 
285  QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
286  painter->save();
287  painter->setClipRect( thisPaintRect );
288 
289  if ( mComposition->plotStyle() == QgsComposition::Preview && mPreviewMode == Rectangle )
290  {
291  // Fill with background color
292  drawBackground( painter );
293  QFont messageFont( QLatin1String( "" ), 12 );
294  painter->setFont( messageFont );
295  painter->setPen( QColor( 0, 0, 0, 125 ) );
296  painter->drawText( thisPaintRect, tr( "Map will be printed here" ) );
297  }
299  {
300  //draw cached pixmap. This function does not call cache() any more because
301  //Qt 4.4.0 and 4.4.1 have problems with recursive paintings
302  //QgsComposerMap::cache() and QgsComposerMap::update() need to be called by
303  //client functions
304 
305  //Background color is already included in cached image, so no need to draw
306 
307  double imagePixelWidth = mCacheImage.width(); //how many pixels of the image are for the map extent?
308  double scale = rect().width() / imagePixelWidth;
309 
310  painter->save();
311 
312  painter->translate( mXOffset, mYOffset );
313  painter->scale( scale, scale );
314  painter->drawImage( 0, 0, mCacheImage );
315 
316  //restore rotation
317  painter->restore();
318  }
319  else if ( mComposition->plotStyle() == QgsComposition::Print ||
321  {
322  if ( mDrawing )
323  {
324  return;
325  }
326 
327  mDrawing = true;
328  QPaintDevice* paintDevice = painter->device();
329  if ( !paintDevice )
330  {
331  return;
332  }
333 
334  // Fill with background color
335  if ( shouldDrawPart( Background ) )
336  {
337  drawBackground( painter );
338  }
339 
340  QgsRectangle cExtent = *currentMapExtent();
341 
342  QSizeF size( cExtent.width() * mapUnitsToMM(), cExtent.height() * mapUnitsToMM() );
343 
344  painter->save();
345  painter->translate( mXOffset, mYOffset );
346 
347  double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
348  size *= dotsPerMM; // output size will be in dots (pixels)
349  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
350  draw( painter, cExtent, size, paintDevice->logicalDpiX() );
351 
352  //restore rotation
353  painter->restore();
354  mDrawing = false;
355  }
356 
357  painter->setClipRect( thisPaintRect, Qt::NoClip );
358  if ( shouldDrawPart( OverviewMapExtent ) &&
359  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
360  {
361  mOverviewStack->drawItems( painter );
362  }
363  if ( shouldDrawPart( Grid ) &&
364  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
365  {
366  mGridStack->drawItems( painter );
367  }
368 
369  //draw canvas items
370  drawAnnotations( painter );
371 
372  if ( shouldDrawPart( Frame ) )
373  {
374  drawFrame( painter );
375  }
376  if ( isSelected() && shouldDrawPart( SelectionBoxes ) )
377  {
378  drawSelectionBoxes( painter );
379  }
380 
381  painter->restore();
382 }
383 
385 {
386  return
387  ( hasBackground() ? 1 : 0 )
388  + layersToRender().length()
389  + 1 // for grids, if they exist
390  + 1 // for overviews, if they exist
391  + ( hasFrame() ? 1 : 0 )
392  + ( isSelected() ? 1 : 0 )
393  ;
394 }
395 
396 bool QgsComposerMap::shouldDrawPart( PartType part ) const
397 {
398  if ( -1 == mCurrentExportLayer )
399  {
400  //all parts of the composer map are visible
401  return true;
402  }
403 
404  int idx = numberExportLayers();
405  if ( isSelected() )
406  {
407  --idx;
408  if ( SelectionBoxes == part )
409  {
410  return mCurrentExportLayer == idx;
411  }
412  }
413 
414  if ( hasFrame() )
415  {
416  --idx;
417  if ( Frame == part )
418  {
419  return mCurrentExportLayer == idx;
420  }
421  }
422  --idx;
423  if ( OverviewMapExtent == part )
424  {
425  return mCurrentExportLayer == idx;
426  }
427  --idx;
428  if ( Grid == part )
429  {
430  return mCurrentExportLayer == idx;
431  }
432  if ( hasBackground() )
433  {
434  if ( Background == part )
435  {
436  return mCurrentExportLayer == 0;
437  }
438  }
439 
440  return true; // for Layer
441 }
442 
444 {
445  mCacheUpdated = false;
446  cache();
447  update();
448 }
449 
451 {
452  if ( mPreviewMode == Render )
453  {
455  }
456 }
457 
459 {
460  mCacheUpdated = u;
461 }
462 
463 QList<QgsMapLayer*> QgsComposerMap::layersToRender( const QgsExpressionContext* context ) const
464 {
466  const QgsExpressionContext* evalContext = context ? context : &scopedContext;
467 
468  QList<QgsMapLayer*> renderLayers;
469 
470  if ( mFollowVisibilityPreset )
471  {
472  QString presetName = mFollowVisibilityPresetName;
473 
474  // preset name can be overridden by data-defined one
475  presetName = mDataDefinedProperties.valueAsString( QgsComposerObject::MapStylePreset, *evalContext, presetName );
476 
477  if ( mComposition->project()->mapThemeCollection()->hasMapTheme( presetName ) )
478  renderLayers = mComposition->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
479  else // fallback to using map canvas layers
480  renderLayers = layers();
481  }
482  else
483  {
484  renderLayers = layers();
485  }
486 
487  bool ok = false;
488  QString ddLayers = mDataDefinedProperties.valueAsString( QgsComposerObject::MapLayers, *evalContext, QString(), &ok );
489  if ( ok )
490  {
491  renderLayers.clear();
492 
493  QStringList layerNames = ddLayers.split( '|' );
494  //need to convert layer names to layer ids
495  Q_FOREACH ( const QString& name, layerNames )
496  {
497  QList< QgsMapLayer* > matchingLayers = mComposition->project()->mapLayersByName( name );
498  Q_FOREACH ( QgsMapLayer* layer, matchingLayers )
499  {
500  renderLayers << layer;
501  }
502  }
503  }
504 
505  //remove atlas coverage layer if required
506  //TODO - move setting for hiding coverage layer to map item properties
508  {
510  {
511  //hiding coverage layer
512  int removeAt = renderLayers.indexOf( mComposition->atlasComposition().coverageLayer() );
513  if ( removeAt != -1 )
514  {
515  renderLayers.removeAt( removeAt );
516  }
517  }
518  }
519 
520  return renderLayers;
521 }
522 
523 QMap<QString, QString> QgsComposerMap::layerStyleOverridesToRender( const QgsExpressionContext& context ) const
524 {
525  if ( mFollowVisibilityPreset )
526  {
527  QString presetName = mFollowVisibilityPresetName;
528 
529  // data defined preset name?
530  presetName = mDataDefinedProperties.valueAsString( QgsComposerObject::MapStylePreset, context, presetName );
531 
532  if ( mComposition->project()->mapThemeCollection()->hasMapTheme( presetName ) )
534  else
535  return QMap<QString, QString>();
536  }
537  else if ( mKeepLayerStyles )
538  {
539  return mLayerStyleOverrides;
540  }
541  else
542  {
543  return QMap<QString, QString>();
544  }
545 }
546 
547 double QgsComposerMap::scale() const
548 {
549  QgsScaleCalculator calculator;
550  calculator.setMapUnits( crs().mapUnits() );
551  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
552  return calculator.calculate( *currentMapExtent(), rect().width() );
553 }
554 
555 void QgsComposerMap::resize( double dx, double dy )
556 {
557  //setRect
558  QRectF currentRect = rect();
559  QRectF newSceneRect = QRectF( pos().x(), pos().y(), currentRect.width() + dx, currentRect.height() + dy );
560  setSceneRect( newSceneRect );
561  updateItem();
562 }
563 
564 void QgsComposerMap::moveContent( double dx, double dy )
565 {
566  if ( !mDrawing )
567  {
568  transformShift( dx, dy );
569  currentMapExtent()->setXMinimum( currentMapExtent()->xMinimum() + dx );
570  currentMapExtent()->setXMaximum( currentMapExtent()->xMaximum() + dx );
571  currentMapExtent()->setYMinimum( currentMapExtent()->yMinimum() + dy );
572  currentMapExtent()->setYMaximum( currentMapExtent()->yMaximum() + dy );
573 
574  //in case data defined extents are set, these override the calculated values
575  refreshMapExtents();
576 
577  cache();
578  update();
579  emit itemChanged();
580  emit extentChanged();
581  }
582 }
583 
584 void QgsComposerMap::zoomContent( const double factor, const QPointF point, const ZoomMode mode )
585 {
586  if ( mDrawing )
587  {
588  return;
589  }
590 
591  if ( mode == QgsComposerItem::NoZoom )
592  {
593  //do nothing
594  return;
595  }
596 
597  //find out map coordinates of position
598  double mapX = currentMapExtent()->xMinimum() + ( point.x() / rect().width() ) * ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() );
599  double mapY = currentMapExtent()->yMinimum() + ( 1 - ( point.y() / rect().height() ) ) * ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() );
600 
601  //find out new center point
602  double centerX = ( currentMapExtent()->xMaximum() + currentMapExtent()->xMinimum() ) / 2;
603  double centerY = ( currentMapExtent()->yMaximum() + currentMapExtent()->yMinimum() ) / 2;
604 
605  if ( mode != QgsComposerItem::Zoom )
606  {
607  if ( mode == QgsComposerItem::ZoomRecenter )
608  {
609  centerX = mapX;
610  centerY = mapY;
611  }
612  else if ( mode == QgsComposerItem::ZoomToPoint )
613  {
614  centerX = mapX + ( centerX - mapX ) * ( 1.0 / factor );
615  centerY = mapY + ( centerY - mapY ) * ( 1.0 / factor );
616  }
617  }
618 
619  double newIntervalX, newIntervalY;
620 
621  if ( factor > 0 )
622  {
623  newIntervalX = ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() ) / factor;
624  newIntervalY = ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() ) / factor;
625  }
626  else //no need to zoom
627  {
628  return;
629  }
630 
631  currentMapExtent()->setXMaximum( centerX + newIntervalX / 2 );
632  currentMapExtent()->setXMinimum( centerX - newIntervalX / 2 );
633  currentMapExtent()->setYMaximum( centerY + newIntervalY / 2 );
634  currentMapExtent()->setYMinimum( centerY - newIntervalY / 2 );
635 
636  if ( mAtlasDriven && mAtlasScalingMode == Fixed && mComposition->atlasMode() != QgsComposition::AtlasOff )
637  {
638  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
639  //and also apply to the map's original extent (see #9602)
640  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
641  QgsScaleCalculator calculator;
642  calculator.setMapUnits( crs().mapUnits() );
643  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
644  double scaleRatio = scale() / calculator.calculate( mExtent, rect().width() );
645  mExtent.scale( scaleRatio );
646  }
647 
648  //recalculate data defined scale and extents, since that may override zoom
649  refreshMapExtents();
650 
651  cache();
652  update();
653  emit itemChanged();
654  emit extentChanged();
655 }
656 
657 void QgsComposerMap::setSceneRect( const QRectF& rectangle )
658 {
659  double w = rectangle.width();
660  double h = rectangle.height();
661  //prepareGeometryChange();
662 
663  QgsComposerItem::setSceneRect( rectangle );
664 
665  //QGraphicsRectItem::update();
666  double newHeight = mExtent.width() * h / w;
667  mExtent = QgsRectangle( mExtent.xMinimum(), mExtent.yMinimum(), mExtent.xMaximum(), mExtent.yMinimum() + newHeight );
668 
669  //recalculate data defined scale and extents
670  refreshMapExtents();
671  mCacheUpdated = false;
672 
674  update();
675  emit itemChanged();
676  emit extentChanged();
677 }
678 
680 {
681  if ( *currentMapExtent() == extent )
682  {
683  return;
684  }
686 
687  //recalculate data defined scale and extents, since that may override extent
688  refreshMapExtents();
689 
690  //adjust height
691  QRectF currentRect = rect();
692 
693  double newHeight = currentRect.width() * currentMapExtent()->height() / currentMapExtent()->width();
694 
695  setSceneRect( QRectF( pos().x(), pos().y(), currentRect.width(), newHeight ) );
696  updateItem();
697 }
698 
700 {
701  QgsRectangle newExtent = extent;
702  QgsRectangle currentExtent = *currentMapExtent();
703  //Make sure the width/height ratio is the same as the current composer map extent.
704  //This is to keep the map item frame size fixed
705  double currentWidthHeightRatio = 1.0;
706  if ( !currentExtent.isNull() )
707  currentWidthHeightRatio = currentExtent.width() / currentExtent.height();
708  else
709  currentWidthHeightRatio = rect().width() / rect().height();
710  double newWidthHeightRatio = newExtent.width() / newExtent.height();
711 
712  if ( currentWidthHeightRatio < newWidthHeightRatio )
713  {
714  //enlarge height of new extent, ensuring the map center stays the same
715  double newHeight = newExtent.width() / currentWidthHeightRatio;
716  double deltaHeight = newHeight - newExtent.height();
717  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
718  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
719  }
720  else
721  {
722  //enlarge width of new extent, ensuring the map center stays the same
723  double newWidth = currentWidthHeightRatio * newExtent.height();
724  double deltaWidth = newWidth - newExtent.width();
725  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
726  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
727  }
728 
729  if ( *currentMapExtent() == newExtent )
730  {
731  return;
732  }
733  *currentMapExtent() = newExtent;
734 
735  //recalculate data defined scale and extents, since that may override extent
736  refreshMapExtents();
737 
738  mCacheUpdated = false;
739  updateItem();
740  emit itemChanged();
741  emit extentChanged();
742 }
743 
745 {
746  if ( mAtlasFeatureExtent != extent )
747  {
748  //don't adjust size of item, instead adjust size of bounds to fit
749  QgsRectangle newExtent = extent;
750 
751  //Make sure the width/height ratio is the same as the map item size
752  double currentWidthHeightRatio = rect().width() / rect().height();
753  double newWidthHeightRatio = newExtent.width() / newExtent.height();
754 
755  if ( currentWidthHeightRatio < newWidthHeightRatio )
756  {
757  //enlarge height of new extent, ensuring the map center stays the same
758  double newHeight = newExtent.width() / currentWidthHeightRatio;
759  double deltaHeight = newHeight - newExtent.height();
760  newExtent.setYMinimum( extent.yMinimum() - deltaHeight / 2 );
761  newExtent.setYMaximum( extent.yMaximum() + deltaHeight / 2 );
762  }
763  else
764  {
765  //enlarge width of new extent, ensuring the map center stays the same
766  double newWidth = currentWidthHeightRatio * newExtent.height();
767  double deltaWidth = newWidth - newExtent.width();
768  newExtent.setXMinimum( extent.xMinimum() - deltaWidth / 2 );
769  newExtent.setXMaximum( extent.xMaximum() + deltaWidth / 2 );
770  }
771 
772  mAtlasFeatureExtent = newExtent;
773  }
774 
775  //recalculate data defined scale and extents, since that may override extents
776  refreshMapExtents();
777 
778  mCacheUpdated = false;
779  emit preparedForAtlas();
780  updateItem();
781  emit itemChanged();
782  emit extentChanged();
783 }
784 
786 {
787  //non-const version
788  if ( mAtlasDriven && mComposition->atlasMode() != QgsComposition::AtlasOff )
789  {
790  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
791  //return the current temporary atlas feature extent
792  return &mAtlasFeatureExtent;
793  }
794  else
795  {
796  //otherwise return permanent user set extent
797  return &mExtent;
798  }
799 }
800 
802 {
803  if ( mCrs.isValid() )
804  return mCrs;
805  else if ( mComposition && mComposition->project() )
806  return mComposition->project()->crs();
808 }
809 
811 {
812  mCrs = crs;
813 }
814 
816 {
817  //const version
818  if ( mAtlasDriven && mComposition->atlasMode() != QgsComposition::AtlasOff )
819  {
820  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
821  //return the current temporary atlas feature extent
822  return &mAtlasFeatureExtent;
823  }
824  else
825  {
826  //otherwise return permanent user set extent
827  return &mExtent;
828  }
829 }
830 
831 void QgsComposerMap::setNewScale( double scaleDenominator, bool forceUpdate )
832 {
833  double currentScaleDenominator = scale();
834 
835  if ( qgsDoubleNear( scaleDenominator, currentScaleDenominator ) || qgsDoubleNear( scaleDenominator, 0.0 ) )
836  {
837  return;
838  }
839 
840  double scaleRatio = scaleDenominator / currentScaleDenominator;
841  currentMapExtent()->scale( scaleRatio );
842 
843  if ( mAtlasDriven && mAtlasScalingMode == Fixed && mComposition->atlasMode() != QgsComposition::AtlasOff )
844  {
845  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
846  //and also apply to the map's original extent (see #9602)
847  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
848  QgsScaleCalculator calculator;
849  calculator.setMapUnits( crs().mapUnits() );
850  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
851  scaleRatio = scaleDenominator / calculator.calculate( mExtent, rect().width() );
852  mExtent.scale( scaleRatio );
853  }
854 
855  mCacheUpdated = false;
856  if ( forceUpdate )
857  {
858  cache();
859  update();
860  emit itemChanged();
861  }
862  emit extentChanged();
863 }
864 
866 {
867  mPreviewMode = m;
868  emit itemChanged();
869 }
870 
871 void QgsComposerMap::setOffset( double xOffset, double yOffset )
872 {
873  mXOffset = xOffset;
874  mYOffset = yOffset;
875 }
876 
878 {
879  mMapRotation = r;
880  mEvaluatedMapRotation = mMapRotation;
881  emit mapRotationChanged( r );
882  emit itemChanged();
883  update();
884 }
885 
887 {
888  return valueType == QgsComposerObject::EvaluatedValue ? mEvaluatedMapRotation : mMapRotation;
889 }
890 
891 void QgsComposerMap::refreshMapExtents( const QgsExpressionContext* context )
892 {
894  const QgsExpressionContext* evalContext = context ? context : &scopedContext;
895 
896  //data defined map extents set?
897  QVariant exprVal;
898 
899  QgsRectangle newExtent = *currentMapExtent();
900  bool useDdXMin = false;
901  bool useDdXMax = false;
902  bool useDdYMin = false;
903  bool useDdYMax = false;
904  double minXD = 0;
905  double minYD = 0;
906  double maxXD = 0;
907  double maxYD = 0;
908 
909  bool ok = false;
910  minXD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapXMin, *evalContext, 0.0, &ok );
911  if ( ok )
912  {
913  useDdXMin = true;
914  newExtent.setXMinimum( minXD );
915  }
916  minYD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapYMin, *evalContext, 0.0, &ok );
917  if ( ok )
918  {
919  useDdYMin = true;
920  newExtent.setYMinimum( minYD );
921  }
922  maxXD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapXMax, *evalContext, 0.0, &ok );
923  if ( ok )
924  {
925  useDdXMax = true;
926  newExtent.setXMaximum( maxXD );
927  }
928  maxYD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapYMax, *evalContext, 0.0, &ok );
929  if ( ok )
930  {
931  useDdYMax = true;
932  newExtent.setYMaximum( maxYD );
933  }
934 
935  if ( newExtent != *currentMapExtent() )
936  {
937  //calculate new extents to fit data defined extents
938 
939  //Make sure the width/height ratio is the same as in current map extent.
940  //This is to keep the map item frame and the page layout fixed
941  double currentWidthHeightRatio = currentMapExtent()->width() / currentMapExtent()->height();
942  double newWidthHeightRatio = newExtent.width() / newExtent.height();
943 
944  if ( currentWidthHeightRatio < newWidthHeightRatio )
945  {
946  //enlarge height of new extent, ensuring the map center stays the same
947  double newHeight = newExtent.width() / currentWidthHeightRatio;
948  double deltaHeight = newHeight - newExtent.height();
949  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
950  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
951  }
952  else
953  {
954  //enlarge width of new extent, ensuring the map center stays the same
955  double newWidth = currentWidthHeightRatio * newExtent.height();
956  double deltaWidth = newWidth - newExtent.width();
957  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
958  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
959  }
960 
961  *currentMapExtent() = newExtent;
962  }
963 
964  //now refresh scale, as this potentially overrides extents
965 
966  //data defined map scale set?
967  double scaleD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapScale, *evalContext, 0.0, &ok );
968  if ( ok )
969  {
970  setNewScale( scaleD, false );
971  newExtent = *currentMapExtent();
972  }
973 
974  if ( useDdXMax || useDdXMin || useDdYMax || useDdYMin )
975  {
976  //if only one of min/max was set for either x or y, then make sure our extent is locked on that value
977  //as we can do this without altering the scale
978  if ( useDdXMin && !useDdXMax )
979  {
980  double xMax = currentMapExtent()->xMaximum() - ( currentMapExtent()->xMinimum() - minXD );
981  newExtent.setXMinimum( minXD );
982  newExtent.setXMaximum( xMax );
983  }
984  else if ( !useDdXMin && useDdXMax )
985  {
986  double xMin = currentMapExtent()->xMinimum() - ( currentMapExtent()->xMaximum() - maxXD );
987  newExtent.setXMinimum( xMin );
988  newExtent.setXMaximum( maxXD );
989  }
990  if ( useDdYMin && !useDdYMax )
991  {
992  double yMax = currentMapExtent()->yMaximum() - ( currentMapExtent()->yMinimum() - minYD );
993  newExtent.setYMinimum( minYD );
994  newExtent.setYMaximum( yMax );
995  }
996  else if ( !useDdYMin && useDdYMax )
997  {
998  double yMin = currentMapExtent()->yMinimum() - ( currentMapExtent()->yMaximum() - maxYD );
999  newExtent.setYMinimum( yMin );
1000  newExtent.setYMaximum( maxYD );
1001  }
1002 
1003  if ( newExtent != *currentMapExtent() )
1004  {
1005  *currentMapExtent() = newExtent;
1006  }
1007  }
1008 
1009  //lastly, map rotation overrides all
1010  double mapRotation = mMapRotation;
1011 
1012  //data defined map rotation set?
1013  mapRotation = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapRotation, *evalContext, mapRotation );
1014 
1015  if ( !qgsDoubleNear( mEvaluatedMapRotation, mapRotation ) )
1016  {
1017  mEvaluatedMapRotation = mapRotation;
1018  emit mapRotationChanged( mapRotation );
1019  }
1020 
1021 }
1022 
1024 {
1025  if ( !mUpdatesEnabled )
1026  {
1027  return;
1028  }
1029 
1030  if ( mPreviewMode != QgsComposerMap::Rectangle && !mCacheUpdated )
1031  {
1032  cache();
1033  }
1035 }
1036 
1038 {
1039  Q_FOREACH ( QgsMapLayer* layer, layersToRender() )
1040  {
1041  if ( QgsRasterLayer* currentRasterLayer = qobject_cast<QgsRasterLayer *>( layer ) )
1042  {
1043  const QgsRasterDataProvider* rasterProvider = nullptr;
1044  if (( rasterProvider = currentRasterLayer->dataProvider() ) )
1045  {
1046  if ( rasterProvider->name() == QLatin1String( "wms" ) )
1047  {
1048  return true;
1049  }
1050  }
1051  }
1052  }
1053  return false;
1054 }
1055 
1057 {
1058  //check easy things first
1059 
1060  //overviews
1061  if ( mOverviewStack->containsAdvancedEffects() )
1062  {
1063  return true;
1064  }
1065 
1066  //grids
1067  if ( mGridStack->containsAdvancedEffects() )
1068  {
1069  return true;
1070  }
1071 
1072  // check if map contains advanced effects like blend modes, or flattened layers for transparency
1073 
1074  QgsTextFormat layerFormat;
1075  Q_FOREACH ( QgsMapLayer* layer, layersToRender() )
1076  {
1077  if ( layer )
1078  {
1079  if ( layer->blendMode() != QPainter::CompositionMode_SourceOver )
1080  {
1081  return true;
1082  }
1083  // if vector layer, check labels and feature blend mode
1084  QgsVectorLayer* currentVectorLayer = qobject_cast<QgsVectorLayer *>( layer );
1085  if ( currentVectorLayer )
1086  {
1087  if ( currentVectorLayer->layerTransparency() != 0 )
1088  {
1089  return true;
1090  }
1091  if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
1092  {
1093  return true;
1094  }
1095  // check label blend modes
1096  if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
1097  {
1098  // Check all label blending properties
1099 
1100  layerFormat.readFromLayer( currentVectorLayer );
1101  if ( layerFormat.containsAdvancedEffects() )
1102  return true;
1103  }
1104  }
1105  }
1106  }
1107 
1108  return false;
1109 }
1110 
1111 void QgsComposerMap::connectUpdateSlot()
1112 {
1113  //connect signal from layer registry to update in case of new or deleted layers
1114  QgsProject* project = mComposition->project();
1115  if ( project )
1116  {
1117  // handles updating the stored layer state BEFORE the layers are removed
1118  connect( project, static_cast < void ( QgsProject::* )( const QList<QgsMapLayer*>& layers ) > ( &QgsProject::layersWillBeRemoved ),
1119  this, &QgsComposerMap::layersAboutToBeRemoved );
1120  // redraws the map AFTER layers are removed
1123  }
1124 }
1125 
1126 bool QgsComposerMap::writeXml( QDomElement& elem, QDomDocument & doc ) const
1127 {
1128  if ( elem.isNull() )
1129  {
1130  return false;
1131  }
1132 
1133  QDomElement composerMapElem = doc.createElement( QStringLiteral( "ComposerMap" ) );
1134  composerMapElem.setAttribute( QStringLiteral( "id" ), mId );
1135 
1136  //previewMode
1137  if ( mPreviewMode == Cache )
1138  {
1139  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Cache" ) );
1140  }
1141  else if ( mPreviewMode == Render )
1142  {
1143  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Render" ) );
1144  }
1145  else //rectangle
1146  {
1147  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Rectangle" ) );
1148  }
1149 
1150  if ( mKeepLayerSet )
1151  {
1152  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "true" ) );
1153  }
1154  else
1155  {
1156  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "false" ) );
1157  }
1158 
1159  if ( mDrawAnnotations )
1160  {
1161  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1162  }
1163  else
1164  {
1165  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "false" ) );
1166  }
1167 
1168  //extent
1169  QDomElement extentElem = doc.createElement( QStringLiteral( "Extent" ) );
1170  extentElem.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mExtent.xMinimum() ) );
1171  extentElem.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mExtent.xMaximum() ) );
1172  extentElem.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mExtent.yMinimum() ) );
1173  extentElem.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mExtent.yMaximum() ) );
1174  composerMapElem.appendChild( extentElem );
1175 
1176  if ( mCrs.isValid() )
1177  {
1178  QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
1179  mCrs.writeXml( crsElem, doc );
1180  composerMapElem.appendChild( crsElem );
1181  }
1182 
1183  // follow map theme
1184  composerMapElem.setAttribute( QStringLiteral( "followPreset" ), mFollowVisibilityPreset ? "true" : "false" );
1185  composerMapElem.setAttribute( QStringLiteral( "followPresetName" ), mFollowVisibilityPresetName );
1186 
1187  //map rotation
1188  composerMapElem.setAttribute( QStringLiteral( "mapRotation" ), QString::number( mMapRotation ) );
1189 
1190  //layer set
1191  QDomElement layerSetElem = doc.createElement( QStringLiteral( "LayerSet" ) );
1192  Q_FOREACH ( const QgsWeakMapLayerPointer& layerPtr, mLayers )
1193  {
1194  QgsMapLayer* layer = layerPtr.data();
1195  if ( !layer )
1196  continue;
1197  QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
1198  QDomText layerIdText = doc.createTextNode( layer->id() );
1199  layerElem.appendChild( layerIdText );
1200  layerSetElem.appendChild( layerElem );
1201  }
1202  composerMapElem.appendChild( layerSetElem );
1203 
1204  // override styles
1205  if ( mKeepLayerStyles )
1206  {
1207  QDomElement stylesElem = doc.createElement( QStringLiteral( "LayerStyles" ) );
1208  QMap<QString, QString>::const_iterator styleIt = mLayerStyleOverrides.constBegin();
1209  for ( ; styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
1210  {
1211  QDomElement styleElem = doc.createElement( QStringLiteral( "LayerStyle" ) );
1212  styleElem.setAttribute( QStringLiteral( "layerid" ), styleIt.key() );
1213  QgsMapLayerStyle style( styleIt.value() );
1214  style.writeXml( styleElem );
1215  stylesElem.appendChild( styleElem );
1216  }
1217  composerMapElem.appendChild( stylesElem );
1218  }
1219 
1220  //write a dummy "Grid" element to prevent crashes on pre 2.5 versions (refs #10905)
1221  QDomElement gridElem = doc.createElement( QStringLiteral( "Grid" ) );
1222  composerMapElem.appendChild( gridElem );
1223 
1224  //grids
1225  mGridStack->writeXml( composerMapElem, doc );
1226 
1227  //overviews
1228  mOverviewStack->writeXml( composerMapElem, doc );
1229 
1230  //atlas
1231  QDomElement atlasElem = doc.createElement( QStringLiteral( "AtlasMap" ) );
1232  atlasElem.setAttribute( QStringLiteral( "atlasDriven" ), mAtlasDriven );
1233  atlasElem.setAttribute( QStringLiteral( "scalingMode" ), mAtlasScalingMode );
1234  atlasElem.setAttribute( QStringLiteral( "margin" ), qgsDoubleToString( mAtlasMargin ) );
1235  composerMapElem.appendChild( atlasElem );
1236 
1237  elem.appendChild( composerMapElem );
1238  return _writeXml( composerMapElem, doc );
1239 }
1240 
1241 bool QgsComposerMap::readXml( const QDomElement& itemElem, const QDomDocument& doc )
1242 {
1243  if ( itemElem.isNull() )
1244  {
1245  return false;
1246  }
1247 
1248  QString idRead = itemElem.attribute( QStringLiteral( "id" ), QStringLiteral( "not found" ) );
1249  if ( idRead != QLatin1String( "not found" ) )
1250  {
1251  mId = idRead.toInt();
1252  updateToolTip();
1253  }
1254  mPreviewMode = Rectangle;
1255 
1256  //previewMode
1257  QString previewMode = itemElem.attribute( QStringLiteral( "previewMode" ) );
1258  if ( previewMode == QLatin1String( "Cache" ) )
1259  {
1260  mPreviewMode = Cache;
1261  }
1262  else if ( previewMode == QLatin1String( "Render" ) )
1263  {
1264  mPreviewMode = Render;
1265  }
1266  else
1267  {
1268  mPreviewMode = Rectangle;
1269  }
1270 
1271  //extent
1272  QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral( "Extent" ) );
1273  if ( !extentNodeList.isEmpty() )
1274  {
1275  QDomElement extentElem = extentNodeList.at( 0 ).toElement();
1276  double xmin, xmax, ymin, ymax;
1277  xmin = extentElem.attribute( QStringLiteral( "xmin" ) ).toDouble();
1278  xmax = extentElem.attribute( QStringLiteral( "xmax" ) ).toDouble();
1279  ymin = extentElem.attribute( QStringLiteral( "ymin" ) ).toDouble();
1280  ymax = extentElem.attribute( QStringLiteral( "ymax" ) ).toDouble();
1281  setNewExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
1282  }
1283 
1284  QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral( "crs" ) );
1285  if ( !crsNodeList.isEmpty() )
1286  {
1287  QDomElement crsElem = crsNodeList.at( 0 ).toElement();
1288  mCrs.readXml( crsElem );
1289  }
1290  else
1291  {
1293  }
1294 
1295  //map rotation
1296  if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1297  {
1298  mMapRotation = itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble();
1299  }
1300 
1301  // follow map theme
1302  mFollowVisibilityPreset = itemElem.attribute( QStringLiteral( "followPreset" ) ).compare( QLatin1String( "true" ) ) == 0;
1303  mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral( "followPresetName" ) );
1304 
1305  //mKeepLayerSet flag
1306  QString keepLayerSetFlag = itemElem.attribute( QStringLiteral( "keepLayerSet" ) );
1307  if ( keepLayerSetFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1308  {
1309  mKeepLayerSet = true;
1310  }
1311  else
1312  {
1313  mKeepLayerSet = false;
1314  }
1315 
1316  QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1317  if ( drawCanvasItemsFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1318  {
1319  mDrawAnnotations = true;
1320  }
1321  else
1322  {
1323  mDrawAnnotations = false;
1324  }
1325 
1326  mLayerStyleOverrides.clear();
1327 
1328  //mLayers
1329  mLayers.clear();
1330  QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerSet" ) );
1331  if ( !layerSetNodeList.isEmpty() )
1332  {
1333  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
1334  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral( "Layer" ) );
1335  mLayers.reserve( layerIdNodeList.size() );
1336  for ( int i = 0; i < layerIdNodeList.size(); ++i )
1337  {
1338  QString layerId = layerIdNodeList.at( i ).toElement().text();
1339  if ( QgsMapLayer* ml = mComposition->project()->mapLayer( layerId ) )
1340  mLayers << ml;
1341  }
1342  }
1343 
1344  // override styles
1345  QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerStyles" ) );
1346  mKeepLayerStyles = !layerStylesNodeList.isEmpty();
1347  if ( mKeepLayerStyles )
1348  {
1349  QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
1350  QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral( "LayerStyle" ) );
1351  for ( int i = 0; i < layerStyleNodeList.size(); ++i )
1352  {
1353  const QDomElement& layerStyleElement = layerStyleNodeList.at( i ).toElement();
1354  QString layerId = layerStyleElement.attribute( QStringLiteral( "layerid" ) );
1355  QgsMapLayerStyle style;
1356  style.readXml( layerStyleElement );
1357  mLayerStyleOverrides.insert( layerId, style.xmlData() );
1358  }
1359  }
1360 
1361  mDrawing = false;
1362  mNumCachedLayers = 0;
1363  mCacheUpdated = false;
1364 
1365  //overviews
1366  mOverviewStack->readXml( itemElem, doc );
1367 
1368  //grids
1369  mGridStack->readXml( itemElem, doc );
1370 
1371  //load grid / grid annotation in old xml format
1372  //only do this if the grid stack didn't load any grids, otherwise this will
1373  //be the dummy element created by QGIS >= 2.5 (refs #10905)
1374  QDomNodeList gridNodeList = itemElem.elementsByTagName( QStringLiteral( "Grid" ) );
1375  if ( mGridStack->size() == 0 && !gridNodeList.isEmpty() )
1376  {
1377  QDomElement gridElem = gridNodeList.at( 0 ).toElement();
1378  QgsComposerMapGrid* mapGrid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1379  mapGrid->setEnabled( gridElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1380  mapGrid->setStyle( QgsComposerMapGrid::GridStyle( gridElem.attribute( QStringLiteral( "gridStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1381  mapGrid->setIntervalX( gridElem.attribute( QStringLiteral( "intervalX" ), QStringLiteral( "0" ) ).toDouble() );
1382  mapGrid->setIntervalY( gridElem.attribute( QStringLiteral( "intervalY" ), QStringLiteral( "0" ) ).toDouble() );
1383  mapGrid->setOffsetX( gridElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
1384  mapGrid->setOffsetY( gridElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
1385  mapGrid->setCrossLength( gridElem.attribute( QStringLiteral( "crossLength" ), QStringLiteral( "3" ) ).toDouble() );
1386  mapGrid->setFrameStyle( static_cast< QgsComposerMapGrid::FrameStyle >( gridElem.attribute( QStringLiteral( "gridFrameStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1387  mapGrid->setFrameWidth( gridElem.attribute( QStringLiteral( "gridFrameWidth" ), QStringLiteral( "2.0" ) ).toDouble() );
1388  mapGrid->setFramePenSize( gridElem.attribute( QStringLiteral( "gridFramePenThickness" ), QStringLiteral( "0.5" ) ).toDouble() );
1389  mapGrid->setFramePenColor( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "framePenColor" ), QStringLiteral( "0,0,0" ) ) ) );
1390  mapGrid->setFrameFillColor1( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor1" ), QStringLiteral( "255,255,255,255" ) ) ) );
1391  mapGrid->setFrameFillColor2( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor2" ), QStringLiteral( "0,0,0,255" ) ) ) );
1392  mapGrid->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( itemElem.attribute( QStringLiteral( "gridBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1393  QDomElement gridSymbolElem = gridElem.firstChildElement( QStringLiteral( "symbol" ) );
1394  QgsLineSymbol* lineSymbol = nullptr;
1395  if ( gridSymbolElem.isNull() )
1396  {
1397  //old project file, read penWidth /penColorRed, penColorGreen, penColorBlue
1398  lineSymbol = QgsLineSymbol::createSimple( QgsStringMap() );
1399  lineSymbol->setWidth( gridElem.attribute( QStringLiteral( "penWidth" ), QStringLiteral( "0" ) ).toDouble() );
1400  lineSymbol->setColor( QColor( gridElem.attribute( QStringLiteral( "penColorRed" ), QStringLiteral( "0" ) ).toInt(),
1401  gridElem.attribute( QStringLiteral( "penColorGreen" ), QStringLiteral( "0" ) ).toInt(),
1402  gridElem.attribute( QStringLiteral( "penColorBlue" ), QStringLiteral( "0" ) ).toInt() ) );
1403  }
1404  else
1405  {
1406  lineSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( gridSymbolElem );
1407  }
1408  mapGrid->setLineSymbol( lineSymbol );
1409 
1410  //annotation
1411  QDomNodeList annotationNodeList = gridElem.elementsByTagName( QStringLiteral( "Annotation" ) );
1412  if ( !annotationNodeList.isEmpty() )
1413  {
1414  QDomElement annotationElem = annotationNodeList.at( 0 ).toElement();
1415  mapGrid->setAnnotationEnabled( annotationElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1416  mapGrid->setAnnotationFormat( QgsComposerMapGrid::AnnotationFormat( annotationElem.attribute( QStringLiteral( "format" ), QStringLiteral( "0" ) ).toInt() ) );
1417  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "leftPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1418  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "rightPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1419  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "topPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1420  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "bottomPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1421  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "leftDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1422  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "rightDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1423  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "topDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1424  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "bottomDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1425  mapGrid->setAnnotationFrameDistance( annotationElem.attribute( QStringLiteral( "frameDistance" ), QStringLiteral( "0" ) ).toDouble() );
1426  QFont annotationFont;
1427  annotationFont.fromString( annotationElem.attribute( QStringLiteral( "font" ), QLatin1String( "" ) ) );
1428  mapGrid->setAnnotationFont( annotationFont );
1429  mapGrid->setAnnotationFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "0,0,0,255" ) ) ) );
1430 
1431  mapGrid->setAnnotationPrecision( annotationElem.attribute( QStringLiteral( "precision" ), QStringLiteral( "3" ) ).toInt() );
1432  }
1433  mGridStack->addGrid( mapGrid );
1434  }
1435 
1436  //load overview in old xml format
1437  QDomElement overviewFrameElem = itemElem.firstChildElement( QStringLiteral( "overviewFrame" ) );
1438  if ( !overviewFrameElem.isNull() )
1439  {
1440  QgsComposerMapOverview* mapOverview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( mOverviewStack->size() + 1 ), this );
1441 
1442  mapOverview->setFrameMap( overviewFrameElem.attribute( QStringLiteral( "overviewFrameMap" ), QStringLiteral( "-1" ) ).toInt() );
1443  mapOverview->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( overviewFrameElem.attribute( QStringLiteral( "overviewBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1444  mapOverview->setInverted( overviewFrameElem.attribute( QStringLiteral( "overviewInverted" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1445  mapOverview->setCentered( overviewFrameElem.attribute( QStringLiteral( "overviewCentered" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1446 
1447  QgsFillSymbol* fillSymbol = nullptr;
1448  QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( QStringLiteral( "symbol" ) );
1449  if ( !overviewFrameSymbolElem.isNull() )
1450  {
1451  fillSymbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( overviewFrameSymbolElem );
1452  mapOverview->setFrameSymbol( fillSymbol );
1453  }
1454  mOverviewStack->addOverview( mapOverview );
1455  }
1456 
1457  //atlas
1458  QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral( "AtlasMap" ) );
1459  if ( !atlasNodeList.isEmpty() )
1460  {
1461  QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
1462  mAtlasDriven = ( atlasElem.attribute( QStringLiteral( "atlasDriven" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1463  if ( atlasElem.hasAttribute( QStringLiteral( "fixedScale" ) ) ) // deprecated XML
1464  {
1465  mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral( "fixedScale" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) ) ? Fixed : Auto;
1466  }
1467  else if ( atlasElem.hasAttribute( QStringLiteral( "scalingMode" ) ) )
1468  {
1469  mAtlasScalingMode = static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral( "scalingMode" ) ).toInt() );
1470  }
1471  mAtlasMargin = atlasElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "0.1" ) ).toDouble();
1472  }
1473 
1474  //restore general composer item properties
1475  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
1476  if ( !composerItemList.isEmpty() )
1477  {
1478  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
1479 
1480  if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1481  {
1482  //in versions prior to 2.1 map rotation was stored in the rotation attribute
1483  mMapRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
1484  }
1485 
1486  _readXml( composerItemElem, doc );
1487  }
1488 
1490  emit itemChanged();
1491  return true;
1492 }
1493 
1494 QList<QgsMapLayer*> QgsComposerMap::layers() const
1495 {
1496  return _qgis_listQPointerToRaw( mLayers );
1497 }
1498 
1499 void QgsComposerMap::setLayers( const QList<QgsMapLayer*>& layers )
1500 {
1501  mLayers = _qgis_listRawToQPointer( layers );
1502 }
1503 
1504 
1505 void QgsComposerMap::setLayerStyleOverrides( const QMap<QString, QString>& overrides )
1506 {
1507  if ( overrides == mLayerStyleOverrides )
1508  return;
1509 
1510  mLayerStyleOverrides = overrides;
1511  emit layerStyleOverridesChanged(); // associated legends may listen to this
1512 }
1513 
1514 
1516 {
1517  mLayerStyleOverrides.clear();
1518  Q_FOREACH ( const QgsWeakMapLayerPointer& layerPtr, mLayers )
1519  {
1520  if ( QgsMapLayer* layer = layerPtr.data() )
1521  {
1522  QgsMapLayerStyle style;
1523  style.readFromLayer( layer );
1524  mLayerStyleOverrides.insert( layer->id(), style.xmlData() );
1525  }
1526  }
1527 }
1528 
1529 void QgsComposerMap::layersAboutToBeRemoved( QList< QgsMapLayer* > layers )
1530 {
1531  if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1532  {
1533  Q_FOREACH ( QgsMapLayer* layer, layers )
1534  {
1535  mLayerStyleOverrides.remove( layer->id() );
1536  mLayers.removeAll( layer );
1537  }
1538  }
1539 }
1540 
1542 {
1543  if ( mGridStack->size() < 1 )
1544  {
1545  QgsComposerMapGrid* grid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1546  mGridStack->addGrid( grid );
1547  }
1548  return mGridStack->grid( 0 );
1549 }
1550 
1551 const QgsComposerMapGrid* QgsComposerMap::constFirstMapGrid() const
1552 {
1553  return const_cast<QgsComposerMap*>( this )->grid();
1554 }
1555 
1557 {
1558  if ( mOverviewStack->size() < 1 )
1559  {
1560  QgsComposerMapOverview* overview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( 1 ), this );
1561  mOverviewStack->addOverview( overview );
1562  }
1563  return mOverviewStack->overview( 0 );
1564 }
1565 
1566 const QgsComposerMapOverview *QgsComposerMap::constFirstMapOverview() const
1567 {
1568  return const_cast<QgsComposerMap*>( this )->overview();
1569 }
1570 
1572 {
1573  return mCurrentRectangle;
1574 }
1575 
1577 {
1578  QRectF rectangle = rect();
1579  double frameExtension = mFrame ? pen().widthF() / 2.0 : 0.0;
1580 
1581  double topExtension = 0.0;
1582  double rightExtension = 0.0;
1583  double bottomExtension = 0.0;
1584  double leftExtension = 0.0;
1585 
1586  if ( mGridStack )
1587  mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1588 
1589  topExtension = qMax( topExtension, frameExtension );
1590  rightExtension = qMax( rightExtension, frameExtension );
1591  bottomExtension = qMax( bottomExtension, frameExtension );
1592  leftExtension = qMax( leftExtension, frameExtension );
1593 
1594  rectangle.setLeft( rectangle.left() - leftExtension );
1595  rectangle.setRight( rectangle.right() + rightExtension );
1596  rectangle.setTop( rectangle.top() - topExtension );
1597  rectangle.setBottom( rectangle.bottom() + bottomExtension );
1598  if ( rectangle != mCurrentRectangle )
1599  {
1600  prepareGeometryChange();
1601  mCurrentRectangle = rectangle;
1602  }
1603 }
1604 
1605 void QgsComposerMap::setFrameStrokeWidth( const double strokeWidth )
1606 {
1607  QgsComposerItem::setFrameStrokeWidth( strokeWidth );
1609 }
1610 
1611 QgsRectangle QgsComposerMap::transformedExtent() const
1612 {
1613  double dx = mXOffset;
1614  double dy = mYOffset;
1615  transformShift( dx, dy );
1616  return QgsRectangle( currentMapExtent()->xMinimum() - dx, currentMapExtent()->yMinimum() - dy, currentMapExtent()->xMaximum() - dx, currentMapExtent()->yMaximum() - dy );
1617 }
1618 
1620 {
1621  double dx = mXOffset;
1622  double dy = mYOffset;
1623  //qWarning("offset");
1624  //qWarning(QString::number(dx).toLocal8Bit().data());
1625  //qWarning(QString::number(dy).toLocal8Bit().data());
1626  transformShift( dx, dy );
1627  //qWarning("transformed:");
1628  //qWarning(QString::number(dx).toLocal8Bit().data());
1629  //qWarning(QString::number(dy).toLocal8Bit().data());
1630  QPolygonF poly = visibleExtentPolygon();
1631  poly.translate( -dx, -dy );
1632  return poly;
1633 }
1634 
1635 void QgsComposerMap::mapPolygon( const QgsRectangle& extent, QPolygonF& poly ) const
1636 {
1637  poly.clear();
1638  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1639  {
1640  poly << QPointF( extent.xMinimum(), extent.yMaximum() );
1641  poly << QPointF( extent.xMaximum(), extent.yMaximum() );
1642  poly << QPointF( extent.xMaximum(), extent.yMinimum() );
1643  poly << QPointF( extent.xMinimum(), extent.yMinimum() );
1644  //ensure polygon is closed by readding first point
1645  poly << QPointF( poly.at( 0 ) );
1646  return;
1647  }
1648 
1649  //there is rotation
1650  QgsPoint rotationPoint(( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
1651  double dx, dy; //x-, y- shift from rotation point to corner point
1652 
1653  //top left point
1654  dx = rotationPoint.x() - extent.xMinimum();
1655  dy = rotationPoint.y() - extent.yMaximum();
1656  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1657  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1658 
1659  //top right point
1660  dx = rotationPoint.x() - extent.xMaximum();
1661  dy = rotationPoint.y() - extent.yMaximum();
1662  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1663  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1664 
1665  //bottom right point
1666  dx = rotationPoint.x() - extent.xMaximum();
1667  dy = rotationPoint.y() - extent.yMinimum();
1668  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1669  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1670 
1671  //bottom left point
1672  dx = rotationPoint.x() - extent.xMinimum();
1673  dy = rotationPoint.y() - extent.yMinimum();
1674  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1675  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1676 
1677  //ensure polygon is closed by readding first point
1678  poly << QPointF( poly.at( 0 ) );
1679 }
1680 
1682 {
1683  QPolygonF poly;
1684  mapPolygon( *currentMapExtent(), poly );
1685  return poly;
1686 }
1687 
1689 {
1690  if ( !QgsComposerItem::id().isEmpty() )
1691  {
1692  return QgsComposerItem::id();
1693  }
1694 
1695  return tr( "Map %1" ).arg( mId );
1696 }
1697 
1699 {
1700  QgsRectangle newExtent = *currentMapExtent();
1701  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1702  {
1703  extent = newExtent;
1704  }
1705  else
1706  {
1707  QPolygonF poly;
1708  mapPolygon( newExtent, poly );
1709  QRectF bRect = poly.boundingRect();
1710  extent.setXMinimum( bRect.left() );
1711  extent.setXMaximum( bRect.right() );
1712  extent.setYMinimum( bRect.top() );
1713  extent.setYMaximum( bRect.bottom() );
1714  }
1715 }
1716 
1718 {
1720 
1721  //Can't utilise QgsExpressionContextUtils::mapSettingsScope as we don't always
1722  //have a QgsMapSettings object available when the context is required, so we manually
1723  //add the same variables here
1724  QgsExpressionContextScope* scope = new QgsExpressionContextScope( tr( "Map Settings" ) );
1725 
1726  //use QgsComposerItem's id, not map item's ID, since that is user-definable
1727  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), QgsComposerItem::id(), true ) );
1728  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mMapRotation, true ) );
1729  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), scale(), true ) );
1730 
1732  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( QgsGeometry::fromRect( extent ) ), true ) );
1733  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), extent.width(), true ) );
1734  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), extent.height(), true ) );
1735  QgsGeometry centerPoint = QgsGeometry::fromPoint( extent.center() );
1736  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
1737 
1738  if ( mComposition )
1739  {
1740  QgsCoordinateReferenceSystem mapCrs = crs();
1741  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapCrs.authid(), true ) );
1742  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapCrs.toProj4(), true ) );
1743  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapCrs.mapUnits() ), true ) );
1744  }
1745 
1746  context.appendScope( scope );
1747 
1748  return context;
1749 }
1750 
1752 {
1753  double extentWidth = currentMapExtent()->width();
1754  if ( extentWidth <= 0 )
1755  {
1756  return 1;
1757  }
1758  return rect().width() / extentWidth;
1759 }
1760 
1762 {
1764  const QgsExpressionContext* evalContext = context ? context : &scopedContext;
1765 
1766  //updates data defined properties and redraws item to match
1767  if ( property == QgsComposerObject::MapRotation || property == QgsComposerObject::MapScale ||
1768  property == QgsComposerObject::MapXMin || property == QgsComposerObject::MapYMin ||
1769  property == QgsComposerObject::MapXMax || property == QgsComposerObject::MapYMax ||
1770  property == QgsComposerObject::MapAtlasMargin ||
1771  property == QgsComposerObject::AllProperties )
1772  {
1773  QgsRectangle beforeExtent = *currentMapExtent();
1774  refreshMapExtents( evalContext );
1775  emit itemChanged();
1776  if ( *currentMapExtent() != beforeExtent )
1777  {
1778  emit extentChanged();
1779  }
1780  }
1781 
1782  //force redraw
1783  mCacheUpdated = false;
1784 
1785  QgsComposerItem::refreshDataDefinedProperty( property, evalContext );
1786 }
1787 
1788 void QgsComposerMap::transformShift( double& xShift, double& yShift ) const
1789 {
1790  double mmToMapUnits = 1.0 / mapUnitsToMM();
1791  double dxScaled = xShift * mmToMapUnits;
1792  double dyScaled = - yShift * mmToMapUnits;
1793 
1794  QgsComposerUtils::rotate( mEvaluatedMapRotation, dxScaled, dyScaled );
1795 
1796  xShift = dxScaled;
1797  yShift = dyScaled;
1798 }
1799 
1800 QPointF QgsComposerMap::mapToItemCoords( QPointF mapCoords ) const
1801 {
1802  QPolygonF mapPoly = transformedMapPolygon();
1803  if ( mapPoly.size() < 1 )
1804  {
1805  return QPointF( 0, 0 );
1806  }
1807 
1808  QgsRectangle tExtent = transformedExtent();
1809  QgsPoint rotationPoint(( tExtent.xMaximum() + tExtent.xMinimum() ) / 2.0, ( tExtent.yMaximum() + tExtent.yMinimum() ) / 2.0 );
1810  double dx = mapCoords.x() - rotationPoint.x();
1811  double dy = mapCoords.y() - rotationPoint.y();
1812  QgsComposerUtils::rotate( -mEvaluatedMapRotation, dx, dy );
1813  QgsPoint backRotatedCoords( rotationPoint.x() + dx, rotationPoint.y() + dy );
1814 
1815  QgsRectangle unrotatedExtent = transformedExtent();
1816  double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
1817  double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
1818  return QPointF( xItem, yItem );
1819 }
1820 
1821 void QgsComposerMap::drawAnnotations( QPainter* painter )
1822 {
1823  if ( !mComposition || !mComposition->project() || !mDrawAnnotations )
1824  {
1825  return;
1826  }
1827 
1828  QList< QgsAnnotation* > annotations = mComposition->project()->annotationManager()->annotations();
1829  if ( annotations.isEmpty() )
1830  return;
1831 
1833  rc.setForceVectorOutput( true );
1835  QList< QgsMapLayer* > layers = layersToRender( &rc.expressionContext() );
1836 
1837  Q_FOREACH ( QgsAnnotation* annotation, annotations )
1838  {
1839  if ( !annotation || !annotation->isVisible() )
1840  {
1841  continue;
1842  }
1843  if ( annotation->mapLayer() && !layers.contains( annotation->mapLayer() ) )
1844  continue;
1845 
1846  drawAnnotation( annotation, rc );
1847  }
1848 }
1849 
1850 void QgsComposerMap::drawAnnotation( const QgsAnnotation* annotation, QgsRenderContext& context )
1851 {
1852  if ( !annotation || !annotation->isVisible() || !context.painter() || !context.painter()->device() )
1853  {
1854  return;
1855  }
1856 
1857  context.painter()->save();
1858  context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing );
1859 
1860  double itemX, itemY;
1861  if ( annotation->hasFixedMapPosition() )
1862  {
1863  QPointF mapPos = composerMapPosForItem( annotation );
1864  itemX = mapPos.x();
1865  itemY = mapPos.y();
1866  }
1867  else
1868  {
1869  itemX = annotation->relativePosition().x() * rect().width();
1870  itemY = annotation->relativePosition().y() * rect().height();
1871  }
1872  context.painter()->translate( itemX, itemY );
1873 
1874  //setup painter scaling to dots so that symbology is drawn to scale
1875  double dotsPerMM = context.painter()->device()->logicalDpiX() / 25.4;
1876  context.painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1877 
1878  annotation->render( context );
1879  context.painter()->restore();
1880 }
1881 
1882 QPointF QgsComposerMap::composerMapPosForItem( const QgsAnnotation* annotation ) const
1883 {
1884  if ( !annotation )
1885  return QPointF( 0, 0 );
1886 
1887  double mapX = 0.0;
1888  double mapY = 0.0;
1889 
1890  mapX = annotation->mapPosition().x();
1891  mapY = annotation->mapPosition().y();
1892  QgsCoordinateReferenceSystem annotationCrs = annotation->mapPositionCrs();
1893 
1894  if ( annotationCrs != crs() )
1895  {
1896  //need to reproject
1897  QgsCoordinateTransform t( annotationCrs, crs() );
1898  double z = 0.0;
1899  t.transformInPlace( mapX, mapY, z );
1900  }
1901 
1902  return mapToItemCoords( QPointF( mapX, mapY ) );
1903 }
1904 
1906 {
1907  if ( !mComposition )
1908  {
1909  return;
1910  }
1911 
1912  const QgsComposerMap* existingMap = mComposition->getComposerMapById( mId );
1913  if ( !existingMap )
1914  {
1915  return; //keep mId as it is still available
1916  }
1917 
1918  int maxId = -1;
1919  QList<const QgsComposerMap*> mapList = mComposition->composerMapItems();
1920  QList<const QgsComposerMap*>::const_iterator mapIt = mapList.constBegin();
1921  for ( ; mapIt != mapList.constEnd(); ++mapIt )
1922  {
1923  if (( *mapIt )->id() > maxId )
1924  {
1925  maxId = ( *mapIt )->id();
1926  }
1927  }
1928  mId = maxId + 1;
1929  updateToolTip();
1930 }
1931 
1933 {
1934  mAtlasDriven = enabled;
1935 
1936  if ( !enabled )
1937  {
1938  //if not enabling the atlas, we still need to refresh the map extents
1939  //so that data defined extents and scale are recalculated
1940  refreshMapExtents();
1941  }
1942 }
1943 
1945 {
1946  if ( valueType == QgsComposerObject::EvaluatedValue )
1947  {
1948  //evaluate data defined atlas margin
1949 
1950  //start with user specified margin
1951  double margin = mAtlasMargin;
1953 
1954  bool ok = false;
1955  double ddMargin = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapAtlasMargin, context, 0.0, &ok );
1956  if ( ok )
1957  {
1958  //divide by 100 to convert to 0 -> 1.0 range
1959  margin = ddMargin / 100;
1960  }
1961  return margin;
1962  }
1963  else
1964  {
1965  return mAtlasMargin;
1966  }
1967 }
1968 
double scale() const
Scale.
void setStyle(const GridStyle style)
Sets the grid style, which controls how the grid is drawn over the map&#39;s contents.
void setForceVectorOutput(bool force)
void preparedForAtlas()
Is emitted when the map has been prepared for atlas rendering, just before actual rendering...
void updateItem() override
Updates item, with the possibility to do custom update for subclasses.
void addGrid(QgsComposerMapGrid *grid)
Adds a new map grid to the stack and takes ownership of the grid.
AtlasScalingMode
Scaling modes used for the serial rendering (atlas)
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, int dpi) const
Return map settings that would be used for drawing of the map.
Single variable definition for use within a QgsExpressionContextScope.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
A rectangle specified with double values.
Definition: qgsrectangle.h:36
void calculateMaxGridExtension(double &top, double &right, double &bottom, double &left) const
Calculates the maximum distance grids within the stack extend beyond the QgsComposerMap&#39;s item rect...
Base class for all map layer types.
Definition: qgsmaplayer.h:52
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
double y
Definition: qgspoint.h:41
Job implementation that renders everything sequentially using a custom painter.
double horizontalViewScaleFactor() const
Returns the zoom factor of the graphics view.
double mapUnitsToMM() const
Returns the conversion factor map units -> mm.
QgsPoint center() const
Center point of the rectangle.
Definition: qgsrectangle.h:222
void setAnnotationDirection(const AnnotationDirection direction, const BorderSide border)
Sets the direction for drawing frame annotations.
bool hasMapTheme(const QString &name) const
Returns whether a map theme with a matching name exists.
const QgsComposerMap * getComposerMapById(const int id) const
Returns the composer map with specified id.
bool isVisible() const
Returns true if the annotation is visible and should be rendered.
Definition: qgsannotation.h:64
void setBlendMode(const QPainter::CompositionMode mode)
Sets the blending mode used for drawing the grid.
QgsPoint mapPosition
Definition: qgsannotation.h:50
double atlasMargin(const QgsComposerObject::PropertyValueType valueType=QgsComposerObject::EvaluatedValue)
Returns the margin size (percentage) used when the map is in atlas mode.
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
GridStyle
Grid drawing style.
virtual void setFrameStrokeWidth(const double strokeWidth)
Sets frame stroke width.
QList< QgsMapLayer * > mapThemeVisibleLayers(const QString &name) const
Returns the list of layers that are visible for the specified map theme.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double...
void setOffsetY(const double offset)
Sets the offset for grid lines in the y-direction.
QMap< QString, QString > mapThemeStyleOverrides(const QString &name)
Get layer style overrides (for QgsMapSettings) of the visible layers for given map theme...
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:177
Use antialiasing while drawing.
void setFramePenSize(const double width)
Sets the width of the stroke drawn in the grid frame.
void assignFreeId()
Sets mId to a number not yet used in the composition.
QString xmlData() const
Return XML content of the style.
bool readXml(const QDomElement &elem, const QDomDocument &doc) override
Sets the grid stack&#39;s state from a DOM document.
void setNewAtlasFeatureExtent(const QgsRectangle &extent)
Sets new Extent for the current atlas preview and changes width, height (and implicitly also scale)...
void readXml(const QDomElement &styleElement)
Read style configuration (for project file reading)
void setOffset(double xOffset, double yOffset)
Sets offset values to shift image (useful for live updates when moving item content) ...
void setFrameSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used for drawing the overview extent.
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
Definition: qgssymbol.cpp:1041
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
void itemChanged()
Emitted when the item changes.
void setLayers(const QList< QgsMapLayer *> &layers)
Setter for stored layer set.
void addOverview(QgsComposerMapOverview *overview)
Adds a new map overview to the stack and takes ownership of the overview.
QPolygonF visibleExtentPolygon() const
Returns a polygon representing the current visible map extent, considering map extents and rotation...
QgsRectangle extent() const
virtual bool writeXml(QDomElement &elem, QDomDocument &doc) const
Stores the state of the item stack in a DOM node.
ZoomMode
Modes for zooming item content.
A collection of grids which is drawn above the map content in a QgsComposerMap.
void layersRemoved(const QStringList &layerIds)
Emitted after one or more layers were removed from the registry.
void cache()
Create cache image.
Layer and style map theme.
A item that forms part of a map composition.
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
Zoom to center of content.
void setOutputDpi(double dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
const QgsDatumTransformStore & datumTransformStore() const
void setDestinationCrs(const QgsCoordinateReferenceSystem &destCrs)
double mLastValidViewScaleFactor
Backup to restore item appearance if no view scale factor is available.
void drawItems(QPainter *painter)
Draws the items from the stack on a specified painter.
void mapRotationChanged(double newRotation)
Is emitted on rotation change to notify north arrow pictures.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:79
QColor backgroundColor() const
Gets the background color for this item.
Flags flags() const
Return combination of flags used for rendering.
The current scale of the map is used for each feature of the atlas.
virtual void drawFrame(QPainter *p)
Draw black frame around item.
void updateCachedImage()
Forces an update of the cached map image.
void setAnnotationFont(const QFont &font)
Sets the font used for drawing grid annotations.
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Set map of map layer style overrides (key: layer ID, value: style name) where a different style shoul...
Map extent x maximum.
Map extent x minimum.
void legendLayersAdded(const QList< QgsMapLayer *> &layers)
Emitted, when a layer was added to the registry and the legend.
AnnotationDirection
Direction of grid annotations.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:976
Enable layer transparency and blending effects.
bool hasFixedMapPosition
Definition: qgsannotation.h:49
static QPainter::CompositionMode getCompositionMode(BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:6
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the map&#39;s preset coordinate reference system.
QMap< QString, QString > QgsStringMap
Definition: qgis.h:330
QList< const QgsComposerMap * > composerMapItems() const
Returns pointers to all composer maps in the scene.
AnnotationFormat
Format for displaying grid annotations.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:198
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QgsComposition::AtlasMode atlasMode() const
Returns the current atlas mode of the composition.
QPointF relativePosition() const
Returns the relative position of the annotation, if it is not attached to a fixed map position...
DataDefinedProperty
Data defined properties for different item types.
virtual QString name() const =0
Return a provider name.
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
void setCrossLength(const double length)
Sets the length of the cross segments drawn for the grid.
Vector graphics should not be cached and drawn as raster images.
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:45
QgsComposition::PlotStyle plotStyle() const
The QgsMapSettings class contains configuration for rendering of the map.
static bool staticWillUseLayer(QgsVectorLayer *layer)
called to find out whether the layer is used for labeling
void readFromLayer(QgsMapLayer *layer)
Store layer&#39;s active style information in the instance.
bool readXml(const QDomElement &elem, const QDomDocument &doc) override
Sets the overview stack&#39;s state from a DOM document.
static QgsRenderContext createRenderContextForMap(QgsComposerMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified composer map and painter destination.
void zoomToExtent(const QgsRectangle &extent)
Zooms the map so that the specified extent is fully visible within the map item.
bool containsAdvancedEffects() const
Returns whether any items within the stack contain advanced effects, such as blending modes...
bool readXml(const QDomElement &itemElem, const QDomDocument &doc) override
Sets state from Dom document.
Stores style information (renderer, transparency, labeling, diagrams etc.) applicable to a map layer...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
void setOutputSize(QSize size)
Set the size of the resulting map image.
bool _writeXml(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document. Usually called from writeXml methods of ...
An individual overview which is drawn above the map content in a QgsComposerMap, and shows the extent...
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
QgsMapThemeCollection mapThemeCollection
Definition: qgsproject.h:81
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
virtual void updateItem()
Updates item, with the possibility to do custom update for subclasses.
virtual void drawSelectionBoxes(QPainter *p)
Draws additional graphics on selected items.
void setRotation(double degrees)
Set the rotation of the resulting map image Units are clockwise degrees.
friend class QgsComposerMapOverview
void setNewScale(double scaleDenominator, bool forceUpdate=true)
Sets new scale and changes only mExtent.
bool mFrame
True if item fram needs to be painted.
Whether vector selections should be shown in the rendered map.
void setWidth(double width)
Definition: qgssymbol.cpp:1494
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:212
void setCacheUpdated(bool u=false)
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:186
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:182
bool useAdvancedEffects() const
Returns true if a composition should use advanced effects such as blend modes.
virtual void setEnabled(const bool enabled)
Controls whether the item will be drawn.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setAnnotationFormat(const AnnotationFormat format)
Sets the format for drawing grid annotations.
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:80
bool hideCoverage() const
Returns true if the atlas is set to hide the coverage layer.
static QgsGeometry fromPoint(const QgsPoint &point)
Creates a new geometry from a QgsPoint object.
AnnotationPosition
Position for grid annotations.
Map extent y minimum.
Enable anti-aliasing for map rendering.
void render(QgsRenderContext &context) const
Renders the annotation to a target render context.
void setCentered(const bool centered)
Sets whether the extent of the map is forced to center on the overview.
void setMapUnits(QgsUnitTypes::DistanceUnit mapUnits)
Set the map units.
void setAnnotationEnabled(const bool enabled)
Sets whether annotations should be shown for the grid.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties, const QgsExpressionContext *context=nullptr) override
Refreshes a data defined property for the item by reevaluating the property&#39;s value and redrawing the...
void setNewExtent(const QgsRectangle &extent)
Sets new extent for the map.
bool drawAnnotations() const
Returns whether annotations are drawn within the composer map.
QgsPropertyCollection mDataDefinedProperties
Reads and writes project states.
Definition: qgsproject.h:74
bool hasBackground() const
Whether this item has a Background or not.
int layerTransparency() const
Returns the current transparency for the vector layer.
void moveContent(double dx, double dy) override
Move content of map.
An individual grid which is drawn above the map content in a QgsComposerMap.
PropertyValueType
Specifies whether the value returned by a function should be the original, user set value...
Single scope for storing variables and functions for use within a QgsExpressionContext.
bool _readXml(const QDomElement &itemElem, const QDomDocument &doc)
Reads parameter that are not subclass specific in document. Usually called from readXml methods of su...
PreviewMode
Preview style.
QList< QgsMapLayer * > mapLayersByName(const QString &layerName) const
Retrieve a list of matching registered layers by layer name.
A class to represent a point.
Definition: qgspoint.h:36
void setFrameWidth(const double width)
Sets the grid frame width.
void setAnnotationFontColor(const QColor &color)
Sets the font color used for drawing grid annotations.
Graphics scene for map printing.
QList< QgsMapLayer * > layers() const
Getter for stored layer set.
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
Object representing map window.
Enable drawing of vertex markers for layers in editing mode.
QgsAnnotationManager * annotationManager()
Returns pointer to the project&#39;s annotation manager.
static void rotate(const double angle, double &x, double &y)
Rotates a point / vector around the origin.
Return the current evaluated value for the property.
QgsMapLayer * mapLayer() const
Returns the map layer associated with the annotation.
void setLineSymbol(QgsLineSymbol *symbol)
Sets the line symbol used for drawing grid lines.
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Reimplementation of QCanvasItem::paint - draw on canvas.
void renderModeUpdateCachedImage()
Updates the cached map image if the map is set to Render mode.
void draw(QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi, double *forceWidthScale=nullptr)
Draw to paint device.
void setFrameFillColor1(const QColor &color)
Sets the first fill color used for the grid frame.
void setFramePenColor(const QColor &color)
Sets the color of the stroke drawn in the grid frame.
void setAnnotationPosition(const AnnotationPosition position, const BorderSide border)
Sets the position for the grid annotations on a specified side of the map frame.
virtual ~QgsComposerMap()
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:207
QgsExpressionContext & expressionContext()
Gets the expression context.
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
virtual QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the item&#39;s current state.
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:192
Map extent y maximum.
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset) ...
QgsComposerMapOverview * overview(const QString &overviewId) const
Returns a reference to an overview within the stack.
QgsComposition * mComposition
void layerStyleOverridesChanged()
Emitted when layer style overrides are changed...
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string...
void setBackgroundColor(const QColor &color)
Set the background color of the map.
QgsCoordinateReferenceSystem mapPositionCrs() const
Returns the CRS of the map position, or an invalid CRS if the annotation does not have a fixed map po...
Contains information about the context of a rendering operation.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
virtual void refreshDataDefinedProperty(const QgsComposerObject::DataDefinedProperty property=QgsComposerObject::AllProperties, const QgsExpressionContext *context=nullptr) override
QPainter * painter()
Returns the destination QPainter for the render operation.
int numberExportLayers() const override
Get the number of layers that this item requires for exporting as layers.
QList< QgsAnnotation *> annotations() const
Returns a list of all annotations contained in the manager.
void setBackgroundColor(const QColor &backgroundColor)
Sets the background color for this item.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
int mCurrentExportLayer
The layer that needs to be exported.
const QgsComposition * composition() const
Returns the composition the item is attached to.
virtual QString displayName() const override
Get item display name.
void writeXml(QDomElement &styleElement) const
Write style configuration (for project file writing)
PreviewMode previewMode() const
QgsProject * project() const
The project associated with the composition.
bool writeXml(QDomElement &elem, QDomDocument &doc) const override
Stores state in Dom node.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:187
virtual void setFrameStrokeWidth(const double strokeWidth) override
Sets frame stroke width.
virtual void drawBackground(QPainter *p)
Draw background.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
void requestedExtent(QgsRectangle &extent) const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
This class represents a coordinate reference system (CRS).
void setMapRotation(double r)
Sets rotation for the map - this does not affect the composer item shape, only the way the map is dra...
virtual void setSceneRect(const QRectF &rectangle)
Sets this items bound in scene coordinates such that 1 item size units corresponds to 1 scene size un...
void setAnnotationPrecision(const int precision)
Sets the coordinate precision for grid annotations.
virtual QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the item&#39;s current state.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
bool containsWmsLayer() const
True if composer map renders a WMS layer.
void setIntervalY(const double interval)
Sets the interval between grid lines in the y-direction.
Class for doing transforms between two map coordinate systems.
QgsComposerMap(QgsComposition *composition, int x, int y, int width, int height)
Constructor.
void setInverted(const bool inverted)
Sets whether the overview frame is inverted, ie, whether the shaded area is drawn outside the extent ...
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:197
void setLayers(const QList< QgsMapLayer *> &layers)
Set list of layers for map rendering.
void setFrameMap(const int mapId)
Sets overview frame map.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
void resize(double dx, double dy)
Resizes an item in x- and y direction (canvas coordinates)
QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
void setSceneRect(const QRectF &rectangle) override
Sets new scene rectangle bounds and recalculates hight and extent.
QgsVectorLayer * coverageLayer() const
Returns the coverage layer used for the atlas features.
QgsAtlasComposition & atlasComposition()
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:202
Enable vector simplification and other rendering optimizations.
bool hasFrame() const
Whether this item has a frame or not.
bool containsAdvancedEffects() const
True if composer map contains layers with blend modes or flattened layers for vectors.
void extentChanged()
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
void setFrameFillColor2(const QColor &color)
Sets the second fill color used for the grid frame.
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Setter for stored overrides of styles for layers.
void setFrameStyle(const FrameStyle style)
Sets the grid frame style.
Container for all settings relating to text rendering.
double mapRotation(QgsComposerObject::PropertyValueType valueType=QgsComposerObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the composer item.
void setPreviewMode(PreviewMode m)
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
QRectF boundingRect() const override
In case of annotations, the bounding rectangle can be larger than the map item rectangle.
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
Represents a vector layer which manages a vector based data sets.
void storeCurrentLayerStyles()
Stores the current layer styles into style overrides.
virtual void zoomContent(const double factor, const QPointF point, const ZoomMode mode=QgsComposerItem::Zoom) override
Zoom content of item.
bool containsAdvancedEffects() const
Returns true if any component of the font format requires advanced effects such as blend modes...
void renderSynchronously()
Render the map synchronously in this thread.
void setIntervalX(const double interval)
Sets the interval between grid lines in the x-direction.
QString id() const
Get item&#39;s id (which is not necessarly unique)
const QgsRectangle * currentMapExtent() const
Returns a pointer to the current map extent, which is either the original user specified extent or th...
Zoom and recenter content to point.
QgsComposerMapGrid * grid(const QString &gridId) const
Returns a reference to a grid within the stack.
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
void setOffsetX(const double offset)
Sets the offset for grid lines in the x-direction.
QString authid() const
Returns the authority identifier for the CRS.
void setBlendMode(const QPainter::CompositionMode blendMode)
Sets the blending mode used for drawing the overview.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:172
QgsComposerMapGrid * grid()
Returns the map item&#39;s first grid.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setAnnotationFrameDistance(const double distance)
Sets the distance between the map frame and annotations.
static QColor decodeColor(const QString &str)
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void setMapUnits(QgsUnitTypes::DistanceUnit u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
All properties for item.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:217
int size() const
Returns the number of items in the stack.
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
Base class for raster data providers.
void setColor(const QColor &color)
Definition: qgssymbol.cpp:419
Zoom while maintaining relative position of point.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QgsComposerMapOverview * overview()
Returns the map item&#39;s first overview.
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer&#39;s custom properties.
double x
Definition: qgspoint.h:40
A collection of overviews which are drawn above the map content in a QgsComposerMap.