QGIS API Documentation  2.99.0-Master (314842d)
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.setExtent( extent );
152  jobMapSettings.setOutputSize( size.toSize() );
153  jobMapSettings.setOutputDpi( dpi );
154  jobMapSettings.setBackgroundColor( Qt::transparent );
155  jobMapSettings.setRotation( mEvaluatedMapRotation );
156 
157  //set layers to render
158  QList<QgsMapLayer *> layers = layersToRender( &expressionContext );
159  if ( -1 != mCurrentExportLayer )
160  {
161  const int layerIdx = mCurrentExportLayer - ( hasBackground() ? 1 : 0 );
162  if ( layerIdx >= 0 && layerIdx < layers.length() )
163  {
164  // exporting with separate layers (e.g., to svg layers), so we only want to render a single map layer
165  QgsMapLayer *ml = layers[ layers.length() - layerIdx - 1 ];
166  layers.clear();
167  layers << ml;
168  }
169  else
170  {
171  // exporting decorations such as map frame/grid/overview, so no map layers required
172  layers.clear();
173  }
174  }
175  jobMapSettings.setLayers( layers );
176  jobMapSettings.setLayerStyleOverrides( layerStyleOverridesToRender( expressionContext ) );
177 
180  {
181  //if outputting composer, disable optimisations like layer simplification
182  jobMapSettings.setFlag( QgsMapSettings::UseRenderingOptimization, false );
183  }
184 
186  jobMapSettings.setExpressionContext( context );
187 
188  // composer-specific overrides of flags
189  jobMapSettings.setFlag( QgsMapSettings::ForceVectorOutput, true ); // force vector output (no caching of marker images etc.)
190  jobMapSettings.setFlag( QgsMapSettings::Antialiasing, true );
191  jobMapSettings.setFlag( QgsMapSettings::DrawEditingInfo, false );
192  jobMapSettings.setFlag( QgsMapSettings::DrawSelection, false );
193  jobMapSettings.setFlag( QgsMapSettings::UseAdvancedEffects, mComposition->useAdvancedEffects() ); // respect the composition's useAdvancedEffects flag
194 
195  jobMapSettings.datumTransformStore().setDestinationCrs( renderCrs );
196 
197  return jobMapSettings;
198 }
199 
201 {
202  if ( mPreviewMode == Rectangle )
203  {
204  return;
205  }
206 
207  if ( mDrawing )
208  {
209  return;
210  }
211 
212  mDrawing = true;
213 
214  double horizontalVScaleFactor = horizontalViewScaleFactor();
215  if ( horizontalVScaleFactor < 0 )
216  {
217  //make sure scale factor is positive
218  horizontalVScaleFactor = mLastValidViewScaleFactor > 0 ? mLastValidViewScaleFactor : 1;
219  }
220 
221  const QgsRectangle &ext = *currentMapExtent();
222  double widthMM = ext.width() * mapUnitsToMM();
223  double heightMM = ext.height() * mapUnitsToMM();
224 
225  int w = widthMM * horizontalVScaleFactor;
226  int h = heightMM * horizontalVScaleFactor;
227 
228  // limit size of image for better performance
229  if ( w > 5000 || h > 5000 )
230  {
231  if ( w > h )
232  {
233  w = 5000;
234  h = w * heightMM / widthMM;
235  }
236  else
237  {
238  h = 5000;
239  w = h * widthMM / heightMM;
240  }
241  }
242 
243  mCacheImage = QImage( w, h, QImage::Format_ARGB32 );
244 
245  // set DPI of the image
246  mCacheImage.setDotsPerMeterX( 1000 * w / widthMM );
247  mCacheImage.setDotsPerMeterY( 1000 * h / heightMM );
248 
249  if ( hasBackground() )
250  {
251  //Initially fill image with specified background color. This ensures that layers with blend modes will
252  //preview correctly
253  mCacheImage.fill( backgroundColor().rgba() );
254  }
255  else
256  {
257  //no background, but start with empty fill to avoid artifacts
258  mCacheImage.fill( QColor( 255, 255, 255, 0 ).rgba() );
259  }
260 
261  QPainter p( &mCacheImage );
262 
263  draw( &p, ext, QSizeF( w, h ), mCacheImage.logicalDpiX() );
264  p.end();
265  mCacheUpdated = true;
266 
267  mDrawing = false;
268 }
269 
270 void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *pWidget )
271 {
272  Q_UNUSED( pWidget );
273 
274  if ( !mComposition || !painter )
275  {
276  return;
277  }
278  if ( !shouldDrawItem() )
279  {
280  return;
281  }
282 
283  QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
284  painter->save();
285  painter->setClipRect( thisPaintRect );
286 
287  if ( mComposition->plotStyle() == QgsComposition::Preview && mPreviewMode == Rectangle )
288  {
289  // Fill with background color
290  drawBackground( painter );
291  QFont messageFont( QLatin1String( "" ), 12 );
292  painter->setFont( messageFont );
293  painter->setPen( QColor( 0, 0, 0, 125 ) );
294  painter->drawText( thisPaintRect, tr( "Map will be printed here" ) );
295  }
297  {
298  if ( mCacheImage.isNull() )
299  cache();
300 
301  //Background color is already included in cached image, so no need to draw
302 
303  double imagePixelWidth = mCacheImage.width(); //how many pixels of the image are for the map extent?
304  double scale = rect().width() / imagePixelWidth;
305 
306  painter->save();
307 
308  painter->translate( mXOffset, mYOffset );
309  painter->scale( scale, scale );
310  painter->drawImage( 0, 0, mCacheImage );
311 
312  //restore rotation
313  painter->restore();
314  }
315  else if ( mComposition->plotStyle() == QgsComposition::Print ||
317  {
318  if ( mDrawing )
319  {
320  return;
321  }
322 
323  mDrawing = true;
324  QPaintDevice *paintDevice = painter->device();
325  if ( !paintDevice )
326  {
327  return;
328  }
329 
330  // Fill with background color
331  if ( shouldDrawPart( Background ) )
332  {
333  drawBackground( painter );
334  }
335 
336  QgsRectangle cExtent = *currentMapExtent();
337 
338  QSizeF size( cExtent.width() * mapUnitsToMM(), cExtent.height() * mapUnitsToMM() );
339 
340  painter->save();
341  painter->translate( mXOffset, mYOffset );
342 
343  double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
344  size *= dotsPerMM; // output size will be in dots (pixels)
345  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
346  draw( painter, cExtent, size, paintDevice->logicalDpiX() );
347 
348  //restore rotation
349  painter->restore();
350  mDrawing = false;
351  }
352 
353  painter->setClipRect( thisPaintRect, Qt::NoClip );
354  if ( shouldDrawPart( OverviewMapExtent ) &&
355  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
356  {
357  mOverviewStack->drawItems( painter );
358  }
359  if ( shouldDrawPart( Grid ) &&
360  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
361  {
362  mGridStack->drawItems( painter );
363  }
364 
365  //draw canvas items
366  drawAnnotations( painter );
367 
368  if ( shouldDrawPart( Frame ) )
369  {
370  drawFrame( painter );
371  }
372  if ( isSelected() && shouldDrawPart( SelectionBoxes ) )
373  {
374  drawSelectionBoxes( painter );
375  }
376 
377  painter->restore();
378 }
379 
381 {
382  return
383  ( hasBackground() ? 1 : 0 )
384  + layersToRender().length()
385  + 1 // for grids, if they exist
386  + 1 // for overviews, if they exist
387  + ( hasFrame() ? 1 : 0 )
388  + ( isSelected() ? 1 : 0 )
389  ;
390 }
391 
392 bool QgsComposerMap::shouldDrawPart( PartType part ) const
393 {
394  if ( -1 == mCurrentExportLayer )
395  {
396  //all parts of the composer map are visible
397  return true;
398  }
399 
400  int idx = numberExportLayers();
401  if ( isSelected() )
402  {
403  --idx;
404  if ( SelectionBoxes == part )
405  {
406  return mCurrentExportLayer == idx;
407  }
408  }
409 
410  if ( hasFrame() )
411  {
412  --idx;
413  if ( Frame == part )
414  {
415  return mCurrentExportLayer == idx;
416  }
417  }
418  --idx;
419  if ( OverviewMapExtent == part )
420  {
421  return mCurrentExportLayer == idx;
422  }
423  --idx;
424  if ( Grid == part )
425  {
426  return mCurrentExportLayer == idx;
427  }
428  if ( hasBackground() )
429  {
430  if ( Background == part )
431  {
432  return mCurrentExportLayer == 0;
433  }
434  }
435 
436  return true; // for Layer
437 }
438 
440 {
441  mCacheUpdated = false;
442  cache();
443  update();
444 }
445 
447 {
448  if ( mPreviewMode == Render )
449  {
451  }
452 }
453 
455 {
456  mCacheUpdated = u;
457 }
458 
459 QList<QgsMapLayer *> QgsComposerMap::layersToRender( const QgsExpressionContext *context ) const
460 {
462  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
463 
464  QList<QgsMapLayer *> renderLayers;
465 
466  if ( mFollowVisibilityPreset )
467  {
468  QString presetName = mFollowVisibilityPresetName;
469 
470  // preset name can be overridden by data-defined one
471  presetName = mDataDefinedProperties.valueAsString( QgsComposerObject::MapStylePreset, *evalContext, presetName );
472 
473  if ( mComposition->project()->mapThemeCollection()->hasMapTheme( presetName ) )
474  renderLayers = mComposition->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
475  else // fallback to using map canvas layers
477  }
478  else if ( !layers().isEmpty() )
479  {
480  renderLayers = layers();
481  }
482  else
483  {
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 ( !updatesEnabled() )
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  }
1125 }
1126 
1127 bool QgsComposerMap::writeXml( QDomElement &elem, QDomDocument &doc ) const
1128 {
1129  if ( elem.isNull() )
1130  {
1131  return false;
1132  }
1133 
1134  QDomElement composerMapElem = doc.createElement( QStringLiteral( "ComposerMap" ) );
1135  composerMapElem.setAttribute( QStringLiteral( "id" ), mId );
1136 
1137  //previewMode
1138  if ( mPreviewMode == Cache )
1139  {
1140  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Cache" ) );
1141  }
1142  else if ( mPreviewMode == Render )
1143  {
1144  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Render" ) );
1145  }
1146  else //rectangle
1147  {
1148  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Rectangle" ) );
1149  }
1150 
1151  if ( mKeepLayerSet )
1152  {
1153  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "true" ) );
1154  }
1155  else
1156  {
1157  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "false" ) );
1158  }
1159 
1160  if ( mDrawAnnotations )
1161  {
1162  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1163  }
1164  else
1165  {
1166  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "false" ) );
1167  }
1168 
1169  //extent
1170  QDomElement extentElem = doc.createElement( QStringLiteral( "Extent" ) );
1171  extentElem.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mExtent.xMinimum() ) );
1172  extentElem.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mExtent.xMaximum() ) );
1173  extentElem.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mExtent.yMinimum() ) );
1174  extentElem.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mExtent.yMaximum() ) );
1175  composerMapElem.appendChild( extentElem );
1176 
1177  if ( mCrs.isValid() )
1178  {
1179  QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
1180  mCrs.writeXml( crsElem, doc );
1181  composerMapElem.appendChild( crsElem );
1182  }
1183 
1184  // follow map theme
1185  composerMapElem.setAttribute( QStringLiteral( "followPreset" ), mFollowVisibilityPreset ? "true" : "false" );
1186  composerMapElem.setAttribute( QStringLiteral( "followPresetName" ), mFollowVisibilityPresetName );
1187 
1188  //map rotation
1189  composerMapElem.setAttribute( QStringLiteral( "mapRotation" ), QString::number( mMapRotation ) );
1190 
1191  //layer set
1192  QDomElement layerSetElem = doc.createElement( QStringLiteral( "LayerSet" ) );
1193  Q_FOREACH ( const QgsWeakMapLayerPointer &layerPtr, mLayers )
1194  {
1195  QgsMapLayer *layer = layerPtr.data();
1196  if ( !layer )
1197  continue;
1198  QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
1199  QDomText layerIdText = doc.createTextNode( layer->id() );
1200  layerElem.appendChild( layerIdText );
1201  layerSetElem.appendChild( layerElem );
1202  }
1203  composerMapElem.appendChild( layerSetElem );
1204 
1205  // override styles
1206  if ( mKeepLayerStyles )
1207  {
1208  QDomElement stylesElem = doc.createElement( QStringLiteral( "LayerStyles" ) );
1209  QMap<QString, QString>::const_iterator styleIt = mLayerStyleOverrides.constBegin();
1210  for ( ; styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
1211  {
1212  QDomElement styleElem = doc.createElement( QStringLiteral( "LayerStyle" ) );
1213  styleElem.setAttribute( QStringLiteral( "layerid" ), styleIt.key() );
1214  QgsMapLayerStyle style( styleIt.value() );
1215  style.writeXml( styleElem );
1216  stylesElem.appendChild( styleElem );
1217  }
1218  composerMapElem.appendChild( stylesElem );
1219  }
1220 
1221  //write a dummy "Grid" element to prevent crashes on pre 2.5 versions (refs #10905)
1222  QDomElement gridElem = doc.createElement( QStringLiteral( "Grid" ) );
1223  composerMapElem.appendChild( gridElem );
1224 
1225  //grids
1226  mGridStack->writeXml( composerMapElem, doc );
1227 
1228  //overviews
1229  mOverviewStack->writeXml( composerMapElem, doc );
1230 
1231  //atlas
1232  QDomElement atlasElem = doc.createElement( QStringLiteral( "AtlasMap" ) );
1233  atlasElem.setAttribute( QStringLiteral( "atlasDriven" ), mAtlasDriven );
1234  atlasElem.setAttribute( QStringLiteral( "scalingMode" ), mAtlasScalingMode );
1235  atlasElem.setAttribute( QStringLiteral( "margin" ), qgsDoubleToString( mAtlasMargin ) );
1236  composerMapElem.appendChild( atlasElem );
1237 
1238  elem.appendChild( composerMapElem );
1239  return _writeXml( composerMapElem, doc );
1240 }
1241 
1242 bool QgsComposerMap::readXml( const QDomElement &itemElem, const QDomDocument &doc )
1243 {
1244  if ( itemElem.isNull() )
1245  {
1246  return false;
1247  }
1248 
1249  setUpdatesEnabled( false );
1250 
1251  QString idRead = itemElem.attribute( QStringLiteral( "id" ), QStringLiteral( "not found" ) );
1252  if ( idRead != QLatin1String( "not found" ) )
1253  {
1254  mId = idRead.toInt();
1255  updateToolTip();
1256  }
1257  mPreviewMode = Rectangle;
1258 
1259  //previewMode
1260  QString previewMode = itemElem.attribute( QStringLiteral( "previewMode" ) );
1261  if ( previewMode == QLatin1String( "Cache" ) )
1262  {
1263  mPreviewMode = Cache;
1264  }
1265  else if ( previewMode == QLatin1String( "Render" ) )
1266  {
1267  mPreviewMode = Render;
1268  }
1269  else
1270  {
1271  mPreviewMode = Rectangle;
1272  }
1273 
1274  //extent
1275  QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral( "Extent" ) );
1276  if ( !extentNodeList.isEmpty() )
1277  {
1278  QDomElement extentElem = extentNodeList.at( 0 ).toElement();
1279  double xmin, xmax, ymin, ymax;
1280  xmin = extentElem.attribute( QStringLiteral( "xmin" ) ).toDouble();
1281  xmax = extentElem.attribute( QStringLiteral( "xmax" ) ).toDouble();
1282  ymin = extentElem.attribute( QStringLiteral( "ymin" ) ).toDouble();
1283  ymax = extentElem.attribute( QStringLiteral( "ymax" ) ).toDouble();
1284  setNewExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
1285  }
1286 
1287  QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral( "crs" ) );
1288  if ( !crsNodeList.isEmpty() )
1289  {
1290  QDomElement crsElem = crsNodeList.at( 0 ).toElement();
1291  mCrs.readXml( crsElem );
1292  }
1293  else
1294  {
1296  }
1297 
1298  //map rotation
1299  if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1300  {
1301  mMapRotation = itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble();
1302  }
1303 
1304  // follow map theme
1305  mFollowVisibilityPreset = itemElem.attribute( QStringLiteral( "followPreset" ) ).compare( QLatin1String( "true" ) ) == 0;
1306  mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral( "followPresetName" ) );
1307 
1308  //mKeepLayerSet flag
1309  QString keepLayerSetFlag = itemElem.attribute( QStringLiteral( "keepLayerSet" ) );
1310  if ( keepLayerSetFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1311  {
1312  mKeepLayerSet = true;
1313  }
1314  else
1315  {
1316  mKeepLayerSet = false;
1317  }
1318 
1319  QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1320  if ( drawCanvasItemsFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1321  {
1322  mDrawAnnotations = true;
1323  }
1324  else
1325  {
1326  mDrawAnnotations = false;
1327  }
1328 
1329  mLayerStyleOverrides.clear();
1330 
1331  //mLayers
1332  mLayers.clear();
1333  QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerSet" ) );
1334  if ( !layerSetNodeList.isEmpty() )
1335  {
1336  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
1337  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral( "Layer" ) );
1338  mLayers.reserve( layerIdNodeList.size() );
1339  for ( int i = 0; i < layerIdNodeList.size(); ++i )
1340  {
1341  QString layerId = layerIdNodeList.at( i ).toElement().text();
1342  if ( QgsMapLayer *ml = mComposition->project()->mapLayer( layerId ) )
1343  mLayers << ml;
1344  }
1345  }
1346 
1347  // override styles
1348  QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerStyles" ) );
1349  mKeepLayerStyles = !layerStylesNodeList.isEmpty();
1350  if ( mKeepLayerStyles )
1351  {
1352  QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
1353  QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral( "LayerStyle" ) );
1354  for ( int i = 0; i < layerStyleNodeList.size(); ++i )
1355  {
1356  const QDomElement &layerStyleElement = layerStyleNodeList.at( i ).toElement();
1357  QString layerId = layerStyleElement.attribute( QStringLiteral( "layerid" ) );
1358  QgsMapLayerStyle style;
1359  style.readXml( layerStyleElement );
1360  mLayerStyleOverrides.insert( layerId, style.xmlData() );
1361  }
1362  }
1363 
1364  mDrawing = false;
1365  mNumCachedLayers = 0;
1366  mCacheUpdated = false;
1367 
1368  //overviews
1369  mOverviewStack->readXml( itemElem, doc );
1370 
1371  //grids
1372  mGridStack->readXml( itemElem, doc );
1373 
1374  //load grid / grid annotation in old xml format
1375  //only do this if the grid stack didn't load any grids, otherwise this will
1376  //be the dummy element created by QGIS >= 2.5 (refs #10905)
1377  QDomNodeList gridNodeList = itemElem.elementsByTagName( QStringLiteral( "Grid" ) );
1378  if ( mGridStack->size() == 0 && !gridNodeList.isEmpty() )
1379  {
1380  QDomElement gridElem = gridNodeList.at( 0 ).toElement();
1381  QgsComposerMapGrid *mapGrid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1382  mapGrid->setEnabled( gridElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1383  mapGrid->setStyle( QgsComposerMapGrid::GridStyle( gridElem.attribute( QStringLiteral( "gridStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1384  mapGrid->setIntervalX( gridElem.attribute( QStringLiteral( "intervalX" ), QStringLiteral( "0" ) ).toDouble() );
1385  mapGrid->setIntervalY( gridElem.attribute( QStringLiteral( "intervalY" ), QStringLiteral( "0" ) ).toDouble() );
1386  mapGrid->setOffsetX( gridElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
1387  mapGrid->setOffsetY( gridElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
1388  mapGrid->setCrossLength( gridElem.attribute( QStringLiteral( "crossLength" ), QStringLiteral( "3" ) ).toDouble() );
1389  mapGrid->setFrameStyle( static_cast< QgsComposerMapGrid::FrameStyle >( gridElem.attribute( QStringLiteral( "gridFrameStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1390  mapGrid->setFrameWidth( gridElem.attribute( QStringLiteral( "gridFrameWidth" ), QStringLiteral( "2.0" ) ).toDouble() );
1391  mapGrid->setFramePenSize( gridElem.attribute( QStringLiteral( "gridFramePenThickness" ), QStringLiteral( "0.5" ) ).toDouble() );
1392  mapGrid->setFramePenColor( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "framePenColor" ), QStringLiteral( "0,0,0" ) ) ) );
1393  mapGrid->setFrameFillColor1( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor1" ), QStringLiteral( "255,255,255,255" ) ) ) );
1394  mapGrid->setFrameFillColor2( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor2" ), QStringLiteral( "0,0,0,255" ) ) ) );
1395  mapGrid->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( itemElem.attribute( QStringLiteral( "gridBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1396  QDomElement gridSymbolElem = gridElem.firstChildElement( QStringLiteral( "symbol" ) );
1397  QgsLineSymbol *lineSymbol = nullptr;
1398  if ( gridSymbolElem.isNull() )
1399  {
1400  //old project file, read penWidth /penColorRed, penColorGreen, penColorBlue
1401  lineSymbol = QgsLineSymbol::createSimple( QgsStringMap() );
1402  lineSymbol->setWidth( gridElem.attribute( QStringLiteral( "penWidth" ), QStringLiteral( "0" ) ).toDouble() );
1403  lineSymbol->setColor( QColor( gridElem.attribute( QStringLiteral( "penColorRed" ), QStringLiteral( "0" ) ).toInt(),
1404  gridElem.attribute( QStringLiteral( "penColorGreen" ), QStringLiteral( "0" ) ).toInt(),
1405  gridElem.attribute( QStringLiteral( "penColorBlue" ), QStringLiteral( "0" ) ).toInt() ) );
1406  }
1407  else
1408  {
1409  lineSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( gridSymbolElem );
1410  }
1411  mapGrid->setLineSymbol( lineSymbol );
1412 
1413  //annotation
1414  QDomNodeList annotationNodeList = gridElem.elementsByTagName( QStringLiteral( "Annotation" ) );
1415  if ( !annotationNodeList.isEmpty() )
1416  {
1417  QDomElement annotationElem = annotationNodeList.at( 0 ).toElement();
1418  mapGrid->setAnnotationEnabled( annotationElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1419  mapGrid->setAnnotationFormat( QgsComposerMapGrid::AnnotationFormat( annotationElem.attribute( QStringLiteral( "format" ), QStringLiteral( "0" ) ).toInt() ) );
1420  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "leftPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1421  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "rightPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1422  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "topPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1423  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "bottomPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1424  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "leftDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1425  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "rightDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1426  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "topDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1427  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "bottomDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1428  mapGrid->setAnnotationFrameDistance( annotationElem.attribute( QStringLiteral( "frameDistance" ), QStringLiteral( "0" ) ).toDouble() );
1429  QFont annotationFont;
1430  annotationFont.fromString( annotationElem.attribute( QStringLiteral( "font" ), QLatin1String( "" ) ) );
1431  mapGrid->setAnnotationFont( annotationFont );
1432  mapGrid->setAnnotationFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "0,0,0,255" ) ) ) );
1433 
1434  mapGrid->setAnnotationPrecision( annotationElem.attribute( QStringLiteral( "precision" ), QStringLiteral( "3" ) ).toInt() );
1435  }
1436  mGridStack->addGrid( mapGrid );
1437  }
1438 
1439  //load overview in old xml format
1440  QDomElement overviewFrameElem = itemElem.firstChildElement( QStringLiteral( "overviewFrame" ) );
1441  if ( !overviewFrameElem.isNull() )
1442  {
1443  QgsComposerMapOverview *mapOverview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( mOverviewStack->size() + 1 ), this );
1444 
1445  mapOverview->setFrameMap( overviewFrameElem.attribute( QStringLiteral( "overviewFrameMap" ), QStringLiteral( "-1" ) ).toInt() );
1446  mapOverview->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( overviewFrameElem.attribute( QStringLiteral( "overviewBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1447  mapOverview->setInverted( overviewFrameElem.attribute( QStringLiteral( "overviewInverted" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1448  mapOverview->setCentered( overviewFrameElem.attribute( QStringLiteral( "overviewCentered" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1449 
1450  QgsFillSymbol *fillSymbol = nullptr;
1451  QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( QStringLiteral( "symbol" ) );
1452  if ( !overviewFrameSymbolElem.isNull() )
1453  {
1454  fillSymbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( overviewFrameSymbolElem );
1455  mapOverview->setFrameSymbol( fillSymbol );
1456  }
1457  mOverviewStack->addOverview( mapOverview );
1458  }
1459 
1460  //atlas
1461  QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral( "AtlasMap" ) );
1462  if ( !atlasNodeList.isEmpty() )
1463  {
1464  QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
1465  mAtlasDriven = ( atlasElem.attribute( QStringLiteral( "atlasDriven" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1466  if ( atlasElem.hasAttribute( QStringLiteral( "fixedScale" ) ) ) // deprecated XML
1467  {
1468  mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral( "fixedScale" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) ) ? Fixed : Auto;
1469  }
1470  else if ( atlasElem.hasAttribute( QStringLiteral( "scalingMode" ) ) )
1471  {
1472  mAtlasScalingMode = static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral( "scalingMode" ) ).toInt() );
1473  }
1474  mAtlasMargin = atlasElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "0.1" ) ).toDouble();
1475  }
1476 
1477  //restore general composer item properties
1478  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
1479  if ( !composerItemList.isEmpty() )
1480  {
1481  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
1482 
1483  if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1484  {
1485  //in versions prior to 2.1 map rotation was stored in the rotation attribute
1486  mMapRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
1487  }
1488 
1489  _readXml( composerItemElem, doc );
1490  }
1491 
1493  setUpdatesEnabled( true );
1494 
1495  emit itemChanged();
1496  return true;
1497 }
1498 
1499 QList<QgsMapLayer *> QgsComposerMap::layers() const
1500 {
1501  return _qgis_listQPointerToRaw( mLayers );
1502 }
1503 
1504 void QgsComposerMap::setLayers( const QList<QgsMapLayer *> &layers )
1505 {
1506  mLayers = _qgis_listRawToQPointer( layers );
1507 }
1508 
1509 
1510 void QgsComposerMap::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
1511 {
1512  if ( overrides == mLayerStyleOverrides )
1513  return;
1514 
1515  mLayerStyleOverrides = overrides;
1516  emit layerStyleOverridesChanged(); // associated legends may listen to this
1517 }
1518 
1519 
1521 {
1522  mLayerStyleOverrides.clear();
1523  Q_FOREACH ( const QgsWeakMapLayerPointer &layerPtr, mLayers )
1524  {
1525  if ( QgsMapLayer *layer = layerPtr.data() )
1526  {
1527  QgsMapLayerStyle style;
1528  style.readFromLayer( layer );
1529  mLayerStyleOverrides.insert( layer->id(), style.xmlData() );
1530  }
1531  }
1532 }
1533 
1534 void QgsComposerMap::layersAboutToBeRemoved( QList< QgsMapLayer * > layers )
1535 {
1536  if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1537  {
1538  Q_FOREACH ( QgsMapLayer *layer, layers )
1539  {
1540  mLayerStyleOverrides.remove( layer->id() );
1541  mLayers.removeAll( layer );
1542  }
1543  }
1544 }
1545 
1547 {
1548  if ( mGridStack->size() < 1 )
1549  {
1550  QgsComposerMapGrid *grid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1551  mGridStack->addGrid( grid );
1552  }
1553  return mGridStack->grid( 0 );
1554 }
1555 
1556 const QgsComposerMapGrid *QgsComposerMap::constFirstMapGrid() const
1557 {
1558  return const_cast<QgsComposerMap *>( this )->grid();
1559 }
1560 
1562 {
1563  if ( mOverviewStack->size() < 1 )
1564  {
1565  QgsComposerMapOverview *overview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( 1 ), this );
1566  mOverviewStack->addOverview( overview );
1567  }
1568  return mOverviewStack->overview( 0 );
1569 }
1570 
1571 const QgsComposerMapOverview *QgsComposerMap::constFirstMapOverview() const
1572 {
1573  return const_cast<QgsComposerMap *>( this )->overview();
1574 }
1575 
1577 {
1578  return mCurrentRectangle;
1579 }
1580 
1582 {
1583  QRectF rectangle = rect();
1584  double frameExtension = mFrame ? pen().widthF() / 2.0 : 0.0;
1585 
1586  double topExtension = 0.0;
1587  double rightExtension = 0.0;
1588  double bottomExtension = 0.0;
1589  double leftExtension = 0.0;
1590 
1591  if ( mGridStack )
1592  mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1593 
1594  topExtension = qMax( topExtension, frameExtension );
1595  rightExtension = qMax( rightExtension, frameExtension );
1596  bottomExtension = qMax( bottomExtension, frameExtension );
1597  leftExtension = qMax( leftExtension, frameExtension );
1598 
1599  rectangle.setLeft( rectangle.left() - leftExtension );
1600  rectangle.setRight( rectangle.right() + rightExtension );
1601  rectangle.setTop( rectangle.top() - topExtension );
1602  rectangle.setBottom( rectangle.bottom() + bottomExtension );
1603  if ( rectangle != mCurrentRectangle )
1604  {
1605  prepareGeometryChange();
1606  mCurrentRectangle = rectangle;
1607  }
1608 }
1609 
1610 void QgsComposerMap::setFrameStrokeWidth( const double strokeWidth )
1611 {
1612  QgsComposerItem::setFrameStrokeWidth( strokeWidth );
1614 }
1615 
1616 QgsRectangle QgsComposerMap::transformedExtent() const
1617 {
1618  double dx = mXOffset;
1619  double dy = mYOffset;
1620  transformShift( dx, dy );
1621  return QgsRectangle( currentMapExtent()->xMinimum() - dx, currentMapExtent()->yMinimum() - dy, currentMapExtent()->xMaximum() - dx, currentMapExtent()->yMaximum() - dy );
1622 }
1623 
1625 {
1626  double dx = mXOffset;
1627  double dy = mYOffset;
1628  //qWarning("offset");
1629  //qWarning(QString::number(dx).toLocal8Bit().data());
1630  //qWarning(QString::number(dy).toLocal8Bit().data());
1631  transformShift( dx, dy );
1632  //qWarning("transformed:");
1633  //qWarning(QString::number(dx).toLocal8Bit().data());
1634  //qWarning(QString::number(dy).toLocal8Bit().data());
1635  QPolygonF poly = visibleExtentPolygon();
1636  poly.translate( -dx, -dy );
1637  return poly;
1638 }
1639 
1640 void QgsComposerMap::mapPolygon( const QgsRectangle &extent, QPolygonF &poly ) const
1641 {
1642  poly.clear();
1643  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1644  {
1645  poly << QPointF( extent.xMinimum(), extent.yMaximum() );
1646  poly << QPointF( extent.xMaximum(), extent.yMaximum() );
1647  poly << QPointF( extent.xMaximum(), extent.yMinimum() );
1648  poly << QPointF( extent.xMinimum(), extent.yMinimum() );
1649  //ensure polygon is closed by readding first point
1650  poly << QPointF( poly.at( 0 ) );
1651  return;
1652  }
1653 
1654  //there is rotation
1655  QgsPoint rotationPoint( ( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
1656  double dx, dy; //x-, y- shift from rotation point to corner point
1657 
1658  //top left point
1659  dx = rotationPoint.x() - extent.xMinimum();
1660  dy = rotationPoint.y() - extent.yMaximum();
1661  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1662  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1663 
1664  //top right point
1665  dx = rotationPoint.x() - extent.xMaximum();
1666  dy = rotationPoint.y() - extent.yMaximum();
1667  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1668  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1669 
1670  //bottom right point
1671  dx = rotationPoint.x() - extent.xMaximum();
1672  dy = rotationPoint.y() - extent.yMinimum();
1673  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1674  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1675 
1676  //bottom left point
1677  dx = rotationPoint.x() - extent.xMinimum();
1678  dy = rotationPoint.y() - extent.yMinimum();
1679  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1680  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1681 
1682  //ensure polygon is closed by readding first point
1683  poly << QPointF( poly.at( 0 ) );
1684 }
1685 
1687 {
1688  QPolygonF poly;
1689  mapPolygon( *currentMapExtent(), poly );
1690  return poly;
1691 }
1692 
1694 {
1695  if ( !QgsComposerItem::id().isEmpty() )
1696  {
1697  return QgsComposerItem::id();
1698  }
1699 
1700  return tr( "Map %1" ).arg( mId );
1701 }
1702 
1704 {
1705  QgsRectangle newExtent = *currentMapExtent();
1706  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1707  {
1708  extent = newExtent;
1709  }
1710  else
1711  {
1712  QPolygonF poly;
1713  mapPolygon( newExtent, poly );
1714  QRectF bRect = poly.boundingRect();
1715  extent.setXMinimum( bRect.left() );
1716  extent.setXMaximum( bRect.right() );
1717  extent.setYMinimum( bRect.top() );
1718  extent.setYMaximum( bRect.bottom() );
1719  }
1720 }
1721 
1723 {
1725 
1726  //Can't utilize QgsExpressionContextUtils::mapSettingsScope as we don't always
1727  //have a QgsMapSettings object available when the context is required, so we manually
1728  //add the same variables here
1729  QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Map Settings" ) );
1730 
1731  //use QgsComposerItem's id, not map item's ID, since that is user-definable
1732  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), QgsComposerItem::id(), true ) );
1733  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mMapRotation, true ) );
1734  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), scale(), true ) );
1735 
1737  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( QgsGeometry::fromRect( extent ) ), true ) );
1738  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), extent.width(), true ) );
1739  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), extent.height(), true ) );
1740  QgsGeometry centerPoint = QgsGeometry::fromPoint( extent.center() );
1741  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
1742 
1743  if ( mComposition )
1744  {
1745  QgsCoordinateReferenceSystem mapCrs = crs();
1746  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapCrs.authid(), true ) );
1747  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapCrs.toProj4(), true ) );
1748  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapCrs.mapUnits() ), true ) );
1749  }
1750 
1751  context.appendScope( scope );
1752 
1753  return context;
1754 }
1755 
1757 {
1758  double extentWidth = currentMapExtent()->width();
1759  if ( extentWidth <= 0 )
1760  {
1761  return 1;
1762  }
1763  return rect().width() / extentWidth;
1764 }
1765 
1767 {
1769  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
1770 
1771  //updates data defined properties and redraws item to match
1772  if ( property == QgsComposerObject::MapRotation || property == QgsComposerObject::MapScale ||
1773  property == QgsComposerObject::MapXMin || property == QgsComposerObject::MapYMin ||
1774  property == QgsComposerObject::MapXMax || property == QgsComposerObject::MapYMax ||
1775  property == QgsComposerObject::MapAtlasMargin ||
1776  property == QgsComposerObject::AllProperties )
1777  {
1778  QgsRectangle beforeExtent = *currentMapExtent();
1779  refreshMapExtents( evalContext );
1780  emit itemChanged();
1781  if ( *currentMapExtent() != beforeExtent )
1782  {
1783  emit extentChanged();
1784  }
1785  }
1786 
1787  //force redraw
1788  mCacheUpdated = false;
1789 
1790  QgsComposerItem::refreshDataDefinedProperty( property, evalContext );
1791 }
1792 
1793 void QgsComposerMap::transformShift( double &xShift, double &yShift ) const
1794 {
1795  double mmToMapUnits = 1.0 / mapUnitsToMM();
1796  double dxScaled = xShift * mmToMapUnits;
1797  double dyScaled = - yShift * mmToMapUnits;
1798 
1799  QgsComposerUtils::rotate( mEvaluatedMapRotation, dxScaled, dyScaled );
1800 
1801  xShift = dxScaled;
1802  yShift = dyScaled;
1803 }
1804 
1805 QPointF QgsComposerMap::mapToItemCoords( QPointF mapCoords ) const
1806 {
1807  QPolygonF mapPoly = transformedMapPolygon();
1808  if ( mapPoly.size() < 1 )
1809  {
1810  return QPointF( 0, 0 );
1811  }
1812 
1813  QgsRectangle tExtent = transformedExtent();
1814  QgsPoint rotationPoint( ( tExtent.xMaximum() + tExtent.xMinimum() ) / 2.0, ( tExtent.yMaximum() + tExtent.yMinimum() ) / 2.0 );
1815  double dx = mapCoords.x() - rotationPoint.x();
1816  double dy = mapCoords.y() - rotationPoint.y();
1817  QgsComposerUtils::rotate( -mEvaluatedMapRotation, dx, dy );
1818  QgsPoint backRotatedCoords( rotationPoint.x() + dx, rotationPoint.y() + dy );
1819 
1820  QgsRectangle unrotatedExtent = transformedExtent();
1821  double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
1822  double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
1823  return QPointF( xItem, yItem );
1824 }
1825 
1826 void QgsComposerMap::drawAnnotations( QPainter *painter )
1827 {
1828  if ( !mComposition || !mComposition->project() || !mDrawAnnotations )
1829  {
1830  return;
1831  }
1832 
1833  QList< QgsAnnotation * > annotations = mComposition->project()->annotationManager()->annotations();
1834  if ( annotations.isEmpty() )
1835  return;
1836 
1838  rc.setForceVectorOutput( true );
1840  QList< QgsMapLayer * > layers = layersToRender( &rc.expressionContext() );
1841 
1842  Q_FOREACH ( QgsAnnotation *annotation, annotations )
1843  {
1844  if ( !annotation || !annotation->isVisible() )
1845  {
1846  continue;
1847  }
1848  if ( annotation->mapLayer() && !layers.contains( annotation->mapLayer() ) )
1849  continue;
1850 
1851  drawAnnotation( annotation, rc );
1852  }
1853 }
1854 
1855 void QgsComposerMap::drawAnnotation( const QgsAnnotation *annotation, QgsRenderContext &context )
1856 {
1857  if ( !annotation || !annotation->isVisible() || !context.painter() || !context.painter()->device() )
1858  {
1859  return;
1860  }
1861 
1862  context.painter()->save();
1863  context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing );
1864 
1865  double itemX, itemY;
1866  if ( annotation->hasFixedMapPosition() )
1867  {
1868  QPointF mapPos = composerMapPosForItem( annotation );
1869  itemX = mapPos.x();
1870  itemY = mapPos.y();
1871  }
1872  else
1873  {
1874  itemX = annotation->relativePosition().x() * rect().width();
1875  itemY = annotation->relativePosition().y() * rect().height();
1876  }
1877  context.painter()->translate( itemX, itemY );
1878 
1879  //setup painter scaling to dots so that symbology is drawn to scale
1880  double dotsPerMM = context.painter()->device()->logicalDpiX() / 25.4;
1881  context.painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1882 
1883  annotation->render( context );
1884  context.painter()->restore();
1885 }
1886 
1887 QPointF QgsComposerMap::composerMapPosForItem( const QgsAnnotation *annotation ) const
1888 {
1889  if ( !annotation )
1890  return QPointF( 0, 0 );
1891 
1892  double mapX = 0.0;
1893  double mapY = 0.0;
1894 
1895  mapX = annotation->mapPosition().x();
1896  mapY = annotation->mapPosition().y();
1897  QgsCoordinateReferenceSystem annotationCrs = annotation->mapPositionCrs();
1898 
1899  if ( annotationCrs != crs() )
1900  {
1901  //need to reproject
1902  QgsCoordinateTransform t( annotationCrs, crs() );
1903  double z = 0.0;
1904  t.transformInPlace( mapX, mapY, z );
1905  }
1906 
1907  return mapToItemCoords( QPointF( mapX, mapY ) );
1908 }
1909 
1911 {
1912  if ( !mComposition )
1913  {
1914  return;
1915  }
1916 
1917  const QgsComposerMap *existingMap = mComposition->getComposerMapById( mId );
1918  if ( !existingMap )
1919  {
1920  return; //keep mId as it is still available
1921  }
1922 
1923  int maxId = -1;
1924  QList<const QgsComposerMap *> mapList = mComposition->composerMapItems();
1925  QList<const QgsComposerMap *>::const_iterator mapIt = mapList.constBegin();
1926  for ( ; mapIt != mapList.constEnd(); ++mapIt )
1927  {
1928  if ( ( *mapIt )->id() > maxId )
1929  {
1930  maxId = ( *mapIt )->id();
1931  }
1932  }
1933  mId = maxId + 1;
1934  updateToolTip();
1935 }
1936 
1938 {
1939  mAtlasDriven = enabled;
1940 
1941  if ( !enabled )
1942  {
1943  //if not enabling the atlas, we still need to refresh the map extents
1944  //so that data defined extents and scale are recalculated
1945  refreshMapExtents();
1946  }
1947 }
1948 
1950 {
1951  if ( valueType == QgsComposerObject::EvaluatedValue )
1952  {
1953  //evaluate data defined atlas margin
1954 
1955  //start with user specified margin
1956  double margin = mAtlasMargin;
1958 
1959  bool ok = false;
1960  double ddMargin = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapAtlasMargin, context, 0.0, &ok );
1961  if ( ok )
1962  {
1963  //divide by 100 to convert to 0 -> 1.0 range
1964  margin = ddMargin / 100;
1965  }
1966  return margin;
1967  }
1968  else
1969  {
1970  return mAtlasMargin;
1971  }
1972 }
1973 
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 (redraws) the 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:42
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:225
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:180
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...
bool updatesEnabled() const
Returns whether updates to the item are enabled.
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:341
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.
QList< QgsMapLayer *> masterVisibleLayers() const
Returns the master list of visible layers.
void refreshItemsTriggered()
Is emitted when item in the composition must be refreshed.
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:83
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
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:215
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:185
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:82
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:76
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:37
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:210
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:195
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:190
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:200
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)
virtual void updateItem()
Updates (redraws) the item, with the possibility to do custom update for subclasses.
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()
void setUpdatesEnabled(bool enabled)
Sets whether updates to the item are enabled.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:205
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:175
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.
All properties for item.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:220
int size() const
Returns the number of items in the stack.
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:41
A collection of overviews which are drawn above the map content in a QgsComposerMap.