QGIS API Documentation  2.99.0-Master (cb63e82)
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 
198 
199  return jobMapSettings;
200 }
201 
203 {
204  if ( mPreviewMode == Rectangle )
205  {
206  return;
207  }
208 
209  if ( mDrawing )
210  {
211  return;
212  }
213 
214  mDrawing = true;
215 
216  double horizontalVScaleFactor = horizontalViewScaleFactor();
217  if ( horizontalVScaleFactor < 0 )
218  {
219  //make sure scale factor is positive
220  horizontalVScaleFactor = mLastValidViewScaleFactor > 0 ? mLastValidViewScaleFactor : 1;
221  }
222 
223  const QgsRectangle &ext = *currentMapExtent();
224  double widthMM = ext.width() * mapUnitsToMM();
225  double heightMM = ext.height() * mapUnitsToMM();
226 
227  int w = widthMM * horizontalVScaleFactor;
228  int h = heightMM * horizontalVScaleFactor;
229 
230  // limit size of image for better performance
231  if ( w > 5000 || h > 5000 )
232  {
233  if ( w > h )
234  {
235  w = 5000;
236  h = w * heightMM / widthMM;
237  }
238  else
239  {
240  h = 5000;
241  w = h * widthMM / heightMM;
242  }
243  }
244 
245  mCacheImage = QImage( w, h, QImage::Format_ARGB32 );
246 
247  // set DPI of the image
248  mCacheImage.setDotsPerMeterX( 1000 * w / widthMM );
249  mCacheImage.setDotsPerMeterY( 1000 * h / heightMM );
250 
251  if ( hasBackground() )
252  {
253  //Initially fill image with specified background color. This ensures that layers with blend modes will
254  //preview correctly
255  mCacheImage.fill( backgroundColor().rgba() );
256  }
257  else
258  {
259  //no background, but start with empty fill to avoid artifacts
260  mCacheImage.fill( QColor( 255, 255, 255, 0 ).rgba() );
261  }
262 
263  QPainter p( &mCacheImage );
264 
265  draw( &p, ext, QSizeF( w, h ), mCacheImage.logicalDpiX() );
266  p.end();
267  mCacheUpdated = true;
268 
269  mDrawing = false;
270 }
271 
272 void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *pWidget )
273 {
274  Q_UNUSED( pWidget );
275 
276  if ( !mComposition || !painter )
277  {
278  return;
279  }
280  if ( !shouldDrawItem() )
281  {
282  return;
283  }
284 
285  QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
286  painter->save();
287  painter->setClipRect( thisPaintRect );
288 
289  if ( mComposition->plotStyle() == QgsComposition::Preview && mPreviewMode == Rectangle )
290  {
291  // Fill with background color
292  drawBackground( painter );
293  QFont messageFont( QLatin1String( "" ), 12 );
294  painter->setFont( messageFont );
295  painter->setPen( QColor( 0, 0, 0, 125 ) );
296  painter->drawText( thisPaintRect, tr( "Map will be printed here" ) );
297  }
299  {
300  if ( mCacheImage.isNull() )
301  cache();
302 
303  //Background color is already included in cached image, so no need to draw
304 
305  double imagePixelWidth = mCacheImage.width(); //how many pixels of the image are for the map extent?
306  double scale = rect().width() / imagePixelWidth;
307 
308  painter->save();
309 
310  painter->translate( mXOffset, mYOffset );
311  painter->scale( scale, scale );
312  painter->drawImage( 0, 0, mCacheImage );
313 
314  //restore rotation
315  painter->restore();
316  }
317  else if ( mComposition->plotStyle() == QgsComposition::Print ||
319  {
320  if ( mDrawing )
321  {
322  return;
323  }
324 
325  mDrawing = true;
326  QPaintDevice *paintDevice = painter->device();
327  if ( !paintDevice )
328  {
329  return;
330  }
331 
332  // Fill with background color
333  if ( shouldDrawPart( Background ) )
334  {
335  drawBackground( painter );
336  }
337 
338  QgsRectangle cExtent = *currentMapExtent();
339 
340  QSizeF size( cExtent.width() * mapUnitsToMM(), cExtent.height() * mapUnitsToMM() );
341 
342  painter->save();
343  painter->translate( mXOffset, mYOffset );
344 
345  double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
346  size *= dotsPerMM; // output size will be in dots (pixels)
347  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
348  draw( painter, cExtent, size, paintDevice->logicalDpiX() );
349 
350  //restore rotation
351  painter->restore();
352  mDrawing = false;
353  }
354 
355  painter->setClipRect( thisPaintRect, Qt::NoClip );
356  if ( shouldDrawPart( OverviewMapExtent ) &&
357  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
358  {
359  mOverviewStack->drawItems( painter );
360  }
361  if ( shouldDrawPart( Grid ) &&
362  ( mComposition->plotStyle() != QgsComposition::Preview || mPreviewMode != Rectangle ) )
363  {
364  mGridStack->drawItems( painter );
365  }
366 
367  //draw canvas items
368  drawAnnotations( painter );
369 
370  if ( shouldDrawPart( Frame ) )
371  {
372  drawFrame( painter );
373  }
374  if ( isSelected() && shouldDrawPart( SelectionBoxes ) )
375  {
376  drawSelectionBoxes( painter );
377  }
378 
379  painter->restore();
380 }
381 
383 {
384  return
385  ( hasBackground() ? 1 : 0 )
386  + layersToRender().length()
387  + 1 // for grids, if they exist
388  + 1 // for overviews, if they exist
389  + ( hasFrame() ? 1 : 0 )
390  + ( isSelected() ? 1 : 0 )
391  ;
392 }
393 
394 bool QgsComposerMap::shouldDrawPart( PartType part ) const
395 {
396  if ( -1 == mCurrentExportLayer )
397  {
398  //all parts of the composer map are visible
399  return true;
400  }
401 
402  int idx = numberExportLayers();
403  if ( isSelected() )
404  {
405  --idx;
406  if ( SelectionBoxes == part )
407  {
408  return mCurrentExportLayer == idx;
409  }
410  }
411 
412  if ( hasFrame() )
413  {
414  --idx;
415  if ( Frame == part )
416  {
417  return mCurrentExportLayer == idx;
418  }
419  }
420  --idx;
421  if ( OverviewMapExtent == part )
422  {
423  return mCurrentExportLayer == idx;
424  }
425  --idx;
426  if ( Grid == part )
427  {
428  return mCurrentExportLayer == idx;
429  }
430  if ( hasBackground() )
431  {
432  if ( Background == part )
433  {
434  return mCurrentExportLayer == 0;
435  }
436  }
437 
438  return true; // for Layer
439 }
440 
442 {
443  mCacheUpdated = false;
444  cache();
445  update();
446 }
447 
449 {
450  if ( mPreviewMode == Render )
451  {
453  }
454 }
455 
457 {
458  mCacheUpdated = u;
459 }
460 
461 QList<QgsMapLayer *> QgsComposerMap::layersToRender( const QgsExpressionContext *context ) const
462 {
464  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
465 
466  QList<QgsMapLayer *> renderLayers;
467 
468  if ( mFollowVisibilityPreset )
469  {
470  QString presetName = mFollowVisibilityPresetName;
471 
472  // preset name can be overridden by data-defined one
473  presetName = mDataDefinedProperties.valueAsString( QgsComposerObject::MapStylePreset, *evalContext, presetName );
474 
475  if ( mComposition->project()->mapThemeCollection()->hasMapTheme( presetName ) )
476  renderLayers = mComposition->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
477  else // fallback to using map canvas layers
479  }
480  else if ( !layers().isEmpty() )
481  {
482  renderLayers = layers();
483  }
484  else
485  {
487  }
488 
489  bool ok = false;
490  QString ddLayers = mDataDefinedProperties.valueAsString( QgsComposerObject::MapLayers, *evalContext, QString(), &ok );
491  if ( ok )
492  {
493  renderLayers.clear();
494 
495  QStringList layerNames = ddLayers.split( '|' );
496  //need to convert layer names to layer ids
497  Q_FOREACH ( const QString &name, layerNames )
498  {
499  QList< QgsMapLayer * > matchingLayers = mComposition->project()->mapLayersByName( name );
500  Q_FOREACH ( QgsMapLayer *layer, matchingLayers )
501  {
502  renderLayers << layer;
503  }
504  }
505  }
506 
507  //remove atlas coverage layer if required
508  //TODO - move setting for hiding coverage layer to map item properties
510  {
512  {
513  //hiding coverage layer
514  int removeAt = renderLayers.indexOf( mComposition->atlasComposition().coverageLayer() );
515  if ( removeAt != -1 )
516  {
517  renderLayers.removeAt( removeAt );
518  }
519  }
520  }
521 
522  return renderLayers;
523 }
524 
525 QMap<QString, QString> QgsComposerMap::layerStyleOverridesToRender( const QgsExpressionContext &context ) const
526 {
527  if ( mFollowVisibilityPreset )
528  {
529  QString presetName = mFollowVisibilityPresetName;
530 
531  // data defined preset name?
532  presetName = mDataDefinedProperties.valueAsString( QgsComposerObject::MapStylePreset, context, presetName );
533 
534  if ( mComposition->project()->mapThemeCollection()->hasMapTheme( presetName ) )
536  else
537  return QMap<QString, QString>();
538  }
539  else if ( mKeepLayerStyles )
540  {
541  return mLayerStyleOverrides;
542  }
543  else
544  {
545  return QMap<QString, QString>();
546  }
547 }
548 
549 double QgsComposerMap::scale() const
550 {
551  QgsScaleCalculator calculator;
552  calculator.setMapUnits( crs().mapUnits() );
553  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
554  return calculator.calculate( *currentMapExtent(), rect().width() );
555 }
556 
557 void QgsComposerMap::resize( double dx, double dy )
558 {
559  //setRect
560  QRectF currentRect = rect();
561  QRectF newSceneRect = QRectF( pos().x(), pos().y(), currentRect.width() + dx, currentRect.height() + dy );
562  setSceneRect( newSceneRect );
563  updateItem();
564 }
565 
566 void QgsComposerMap::moveContent( double dx, double dy )
567 {
568  if ( !mDrawing )
569  {
570  transformShift( dx, dy );
571  currentMapExtent()->setXMinimum( currentMapExtent()->xMinimum() + dx );
572  currentMapExtent()->setXMaximum( currentMapExtent()->xMaximum() + dx );
573  currentMapExtent()->setYMinimum( currentMapExtent()->yMinimum() + dy );
574  currentMapExtent()->setYMaximum( currentMapExtent()->yMaximum() + dy );
575 
576  //in case data defined extents are set, these override the calculated values
577  refreshMapExtents();
578 
579  cache();
580  update();
581  emit itemChanged();
582  emit extentChanged();
583  }
584 }
585 
586 void QgsComposerMap::zoomContent( const double factor, const QPointF point, const ZoomMode mode )
587 {
588  if ( mDrawing )
589  {
590  return;
591  }
592 
593  if ( mode == QgsComposerItem::NoZoom )
594  {
595  //do nothing
596  return;
597  }
598 
599  //find out map coordinates of position
600  double mapX = currentMapExtent()->xMinimum() + ( point.x() / rect().width() ) * ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() );
601  double mapY = currentMapExtent()->yMinimum() + ( 1 - ( point.y() / rect().height() ) ) * ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() );
602 
603  //find out new center point
604  double centerX = ( currentMapExtent()->xMaximum() + currentMapExtent()->xMinimum() ) / 2;
605  double centerY = ( currentMapExtent()->yMaximum() + currentMapExtent()->yMinimum() ) / 2;
606 
607  if ( mode != QgsComposerItem::Zoom )
608  {
609  if ( mode == QgsComposerItem::ZoomRecenter )
610  {
611  centerX = mapX;
612  centerY = mapY;
613  }
614  else if ( mode == QgsComposerItem::ZoomToPoint )
615  {
616  centerX = mapX + ( centerX - mapX ) * ( 1.0 / factor );
617  centerY = mapY + ( centerY - mapY ) * ( 1.0 / factor );
618  }
619  }
620 
621  double newIntervalX, newIntervalY;
622 
623  if ( factor > 0 )
624  {
625  newIntervalX = ( currentMapExtent()->xMaximum() - currentMapExtent()->xMinimum() ) / factor;
626  newIntervalY = ( currentMapExtent()->yMaximum() - currentMapExtent()->yMinimum() ) / factor;
627  }
628  else //no need to zoom
629  {
630  return;
631  }
632 
633  currentMapExtent()->setXMaximum( centerX + newIntervalX / 2 );
634  currentMapExtent()->setXMinimum( centerX - newIntervalX / 2 );
635  currentMapExtent()->setYMaximum( centerY + newIntervalY / 2 );
636  currentMapExtent()->setYMinimum( centerY - newIntervalY / 2 );
637 
638  if ( mAtlasDriven && mAtlasScalingMode == Fixed && mComposition->atlasMode() != QgsComposition::AtlasOff )
639  {
640  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
641  //and also apply to the map's original extent (see #9602)
642  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
643  QgsScaleCalculator calculator;
644  calculator.setMapUnits( crs().mapUnits() );
645  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
646  double scaleRatio = scale() / calculator.calculate( mExtent, rect().width() );
647  mExtent.scale( scaleRatio );
648  }
649 
650  //recalculate data defined scale and extents, since that may override zoom
651  refreshMapExtents();
652 
653  cache();
654  update();
655  emit itemChanged();
656  emit extentChanged();
657 }
658 
659 void QgsComposerMap::setSceneRect( const QRectF &rectangle )
660 {
661  double w = rectangle.width();
662  double h = rectangle.height();
663  //prepareGeometryChange();
664 
665  QgsComposerItem::setSceneRect( rectangle );
666 
667  //QGraphicsRectItem::update();
668  double newHeight = mExtent.width() * h / w;
669  mExtent = QgsRectangle( mExtent.xMinimum(), mExtent.yMinimum(), mExtent.xMaximum(), mExtent.yMinimum() + newHeight );
670 
671  //recalculate data defined scale and extents
672  refreshMapExtents();
673  mCacheUpdated = false;
674 
676  update();
677  emit itemChanged();
678  emit extentChanged();
679 }
680 
682 {
683  if ( *currentMapExtent() == extent )
684  {
685  return;
686  }
688 
689  //recalculate data defined scale and extents, since that may override extent
690  refreshMapExtents();
691 
692  //adjust height
693  QRectF currentRect = rect();
694 
695  double newHeight = currentRect.width() * currentMapExtent()->height() / currentMapExtent()->width();
696 
697  setSceneRect( QRectF( pos().x(), pos().y(), currentRect.width(), newHeight ) );
698  updateItem();
699 }
700 
702 {
703  QgsRectangle newExtent = extent;
704  QgsRectangle currentExtent = *currentMapExtent();
705  //Make sure the width/height ratio is the same as the current composer map extent.
706  //This is to keep the map item frame size fixed
707  double currentWidthHeightRatio = 1.0;
708  if ( !currentExtent.isNull() )
709  currentWidthHeightRatio = currentExtent.width() / currentExtent.height();
710  else
711  currentWidthHeightRatio = rect().width() / rect().height();
712  double newWidthHeightRatio = newExtent.width() / newExtent.height();
713 
714  if ( currentWidthHeightRatio < newWidthHeightRatio )
715  {
716  //enlarge height of new extent, ensuring the map center stays the same
717  double newHeight = newExtent.width() / currentWidthHeightRatio;
718  double deltaHeight = newHeight - newExtent.height();
719  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
720  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
721  }
722  else
723  {
724  //enlarge width of new extent, ensuring the map center stays the same
725  double newWidth = currentWidthHeightRatio * newExtent.height();
726  double deltaWidth = newWidth - newExtent.width();
727  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
728  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
729  }
730 
731  if ( *currentMapExtent() == newExtent )
732  {
733  return;
734  }
735  *currentMapExtent() = newExtent;
736 
737  //recalculate data defined scale and extents, since that may override extent
738  refreshMapExtents();
739 
740  mCacheUpdated = false;
741  updateItem();
742  emit itemChanged();
743  emit extentChanged();
744 }
745 
747 {
748  if ( mAtlasFeatureExtent != extent )
749  {
750  //don't adjust size of item, instead adjust size of bounds to fit
751  QgsRectangle newExtent = extent;
752 
753  //Make sure the width/height ratio is the same as the map item size
754  double currentWidthHeightRatio = rect().width() / rect().height();
755  double newWidthHeightRatio = newExtent.width() / newExtent.height();
756 
757  if ( currentWidthHeightRatio < newWidthHeightRatio )
758  {
759  //enlarge height of new extent, ensuring the map center stays the same
760  double newHeight = newExtent.width() / currentWidthHeightRatio;
761  double deltaHeight = newHeight - newExtent.height();
762  newExtent.setYMinimum( extent.yMinimum() - deltaHeight / 2 );
763  newExtent.setYMaximum( extent.yMaximum() + deltaHeight / 2 );
764  }
765  else
766  {
767  //enlarge width of new extent, ensuring the map center stays the same
768  double newWidth = currentWidthHeightRatio * newExtent.height();
769  double deltaWidth = newWidth - newExtent.width();
770  newExtent.setXMinimum( extent.xMinimum() - deltaWidth / 2 );
771  newExtent.setXMaximum( extent.xMaximum() + deltaWidth / 2 );
772  }
773 
774  mAtlasFeatureExtent = newExtent;
775  }
776 
777  //recalculate data defined scale and extents, since that may override extents
778  refreshMapExtents();
779 
780  mCacheUpdated = false;
781  emit preparedForAtlas();
782  updateItem();
783  emit itemChanged();
784  emit extentChanged();
785 }
786 
788 {
789  //non-const version
790  if ( mAtlasDriven && mComposition->atlasMode() != QgsComposition::AtlasOff )
791  {
792  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
793  //return the current temporary atlas feature extent
794  return &mAtlasFeatureExtent;
795  }
796  else
797  {
798  //otherwise return permanent user set extent
799  return &mExtent;
800  }
801 }
802 
804 {
805  if ( mCrs.isValid() )
806  return mCrs;
807  else if ( mComposition && mComposition->project() )
808  return mComposition->project()->crs();
810 }
811 
813 {
814  mCrs = crs;
815 }
816 
818 {
819  //const version
820  if ( mAtlasDriven && mComposition->atlasMode() != QgsComposition::AtlasOff )
821  {
822  //if atlas is enabled, and we are either exporting the composition or previewing the atlas, then
823  //return the current temporary atlas feature extent
824  return &mAtlasFeatureExtent;
825  }
826  else
827  {
828  //otherwise return permanent user set extent
829  return &mExtent;
830  }
831 }
832 
833 void QgsComposerMap::setNewScale( double scaleDenominator, bool forceUpdate )
834 {
835  double currentScaleDenominator = scale();
836 
837  if ( qgsDoubleNear( scaleDenominator, currentScaleDenominator ) || qgsDoubleNear( scaleDenominator, 0.0 ) )
838  {
839  return;
840  }
841 
842  double scaleRatio = scaleDenominator / currentScaleDenominator;
843  currentMapExtent()->scale( scaleRatio );
844 
845  if ( mAtlasDriven && mAtlasScalingMode == Fixed && mComposition->atlasMode() != QgsComposition::AtlasOff )
846  {
847  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
848  //and also apply to the map's original extent (see #9602)
849  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
850  QgsScaleCalculator calculator;
851  calculator.setMapUnits( crs().mapUnits() );
852  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
853  scaleRatio = scaleDenominator / calculator.calculate( mExtent, rect().width() );
854  mExtent.scale( scaleRatio );
855  }
856 
857  mCacheUpdated = false;
858  if ( forceUpdate )
859  {
860  cache();
861  update();
862  emit itemChanged();
863  }
864  emit extentChanged();
865 }
866 
868 {
869  mPreviewMode = m;
870  emit itemChanged();
871 }
872 
873 void QgsComposerMap::setOffset( double xOffset, double yOffset )
874 {
875  mXOffset = xOffset;
876  mYOffset = yOffset;
877 }
878 
880 {
881  mMapRotation = r;
882  mEvaluatedMapRotation = mMapRotation;
883  emit mapRotationChanged( r );
884  emit itemChanged();
885  update();
886 }
887 
889 {
890  return valueType == QgsComposerObject::EvaluatedValue ? mEvaluatedMapRotation : mMapRotation;
891 }
892 
893 void QgsComposerMap::refreshMapExtents( const QgsExpressionContext *context )
894 {
896  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
897 
898  //data defined map extents set?
899  QVariant exprVal;
900 
901  QgsRectangle newExtent = *currentMapExtent();
902  bool useDdXMin = false;
903  bool useDdXMax = false;
904  bool useDdYMin = false;
905  bool useDdYMax = false;
906  double minXD = 0;
907  double minYD = 0;
908  double maxXD = 0;
909  double maxYD = 0;
910 
911  bool ok = false;
912  minXD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapXMin, *evalContext, 0.0, &ok );
913  if ( ok )
914  {
915  useDdXMin = true;
916  newExtent.setXMinimum( minXD );
917  }
918  minYD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapYMin, *evalContext, 0.0, &ok );
919  if ( ok )
920  {
921  useDdYMin = true;
922  newExtent.setYMinimum( minYD );
923  }
924  maxXD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapXMax, *evalContext, 0.0, &ok );
925  if ( ok )
926  {
927  useDdXMax = true;
928  newExtent.setXMaximum( maxXD );
929  }
930  maxYD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapYMax, *evalContext, 0.0, &ok );
931  if ( ok )
932  {
933  useDdYMax = true;
934  newExtent.setYMaximum( maxYD );
935  }
936 
937  if ( newExtent != *currentMapExtent() )
938  {
939  //calculate new extents to fit data defined extents
940 
941  //Make sure the width/height ratio is the same as in current map extent.
942  //This is to keep the map item frame and the page layout fixed
943  double currentWidthHeightRatio = currentMapExtent()->width() / currentMapExtent()->height();
944  double newWidthHeightRatio = newExtent.width() / newExtent.height();
945 
946  if ( currentWidthHeightRatio < newWidthHeightRatio )
947  {
948  //enlarge height of new extent, ensuring the map center stays the same
949  double newHeight = newExtent.width() / currentWidthHeightRatio;
950  double deltaHeight = newHeight - newExtent.height();
951  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
952  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
953  }
954  else
955  {
956  //enlarge width of new extent, ensuring the map center stays the same
957  double newWidth = currentWidthHeightRatio * newExtent.height();
958  double deltaWidth = newWidth - newExtent.width();
959  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
960  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
961  }
962 
963  *currentMapExtent() = newExtent;
964  }
965 
966  //now refresh scale, as this potentially overrides extents
967 
968  //data defined map scale set?
969  double scaleD = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapScale, *evalContext, 0.0, &ok );
970  if ( ok )
971  {
972  setNewScale( scaleD, false );
973  newExtent = *currentMapExtent();
974  }
975 
976  if ( useDdXMax || useDdXMin || useDdYMax || useDdYMin )
977  {
978  //if only one of min/max was set for either x or y, then make sure our extent is locked on that value
979  //as we can do this without altering the scale
980  if ( useDdXMin && !useDdXMax )
981  {
982  double xMax = currentMapExtent()->xMaximum() - ( currentMapExtent()->xMinimum() - minXD );
983  newExtent.setXMinimum( minXD );
984  newExtent.setXMaximum( xMax );
985  }
986  else if ( !useDdXMin && useDdXMax )
987  {
988  double xMin = currentMapExtent()->xMinimum() - ( currentMapExtent()->xMaximum() - maxXD );
989  newExtent.setXMinimum( xMin );
990  newExtent.setXMaximum( maxXD );
991  }
992  if ( useDdYMin && !useDdYMax )
993  {
994  double yMax = currentMapExtent()->yMaximum() - ( currentMapExtent()->yMinimum() - minYD );
995  newExtent.setYMinimum( minYD );
996  newExtent.setYMaximum( yMax );
997  }
998  else if ( !useDdYMin && useDdYMax )
999  {
1000  double yMin = currentMapExtent()->yMinimum() - ( currentMapExtent()->yMaximum() - maxYD );
1001  newExtent.setYMinimum( yMin );
1002  newExtent.setYMaximum( maxYD );
1003  }
1004 
1005  if ( newExtent != *currentMapExtent() )
1006  {
1007  *currentMapExtent() = newExtent;
1008  }
1009  }
1010 
1011  //lastly, map rotation overrides all
1012  double mapRotation = mMapRotation;
1013 
1014  //data defined map rotation set?
1015  mapRotation = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapRotation, *evalContext, mapRotation );
1016 
1017  if ( !qgsDoubleNear( mEvaluatedMapRotation, mapRotation ) )
1018  {
1019  mEvaluatedMapRotation = mapRotation;
1020  emit mapRotationChanged( mapRotation );
1021  }
1022 
1023 }
1024 
1026 {
1027  if ( !updatesEnabled() )
1028  {
1029  return;
1030  }
1031 
1032  if ( mPreviewMode != QgsComposerMap::Rectangle && !mCacheUpdated )
1033  {
1034  cache();
1035  }
1037 }
1038 
1040 {
1041  Q_FOREACH ( QgsMapLayer *layer, layersToRender() )
1042  {
1043  if ( QgsRasterLayer *currentRasterLayer = qobject_cast<QgsRasterLayer *>( layer ) )
1044  {
1045  const QgsRasterDataProvider *rasterProvider = nullptr;
1046  if ( ( rasterProvider = currentRasterLayer->dataProvider() ) )
1047  {
1048  if ( rasterProvider->name() == QLatin1String( "wms" ) )
1049  {
1050  return true;
1051  }
1052  }
1053  }
1054  }
1055  return false;
1056 }
1057 
1059 {
1060  //check easy things first
1061 
1062  //overviews
1063  if ( mOverviewStack->containsAdvancedEffects() )
1064  {
1065  return true;
1066  }
1067 
1068  //grids
1069  if ( mGridStack->containsAdvancedEffects() )
1070  {
1071  return true;
1072  }
1073 
1074  // check if map contains advanced effects like blend modes, or flattened layers for transparency
1075 
1076  QgsTextFormat layerFormat;
1077  Q_FOREACH ( QgsMapLayer *layer, layersToRender() )
1078  {
1079  if ( layer )
1080  {
1081  if ( layer->blendMode() != QPainter::CompositionMode_SourceOver )
1082  {
1083  return true;
1084  }
1085  // if vector layer, check labels and feature blend mode
1086  QgsVectorLayer *currentVectorLayer = qobject_cast<QgsVectorLayer *>( layer );
1087  if ( currentVectorLayer )
1088  {
1089  if ( currentVectorLayer->layerTransparency() != 0 )
1090  {
1091  return true;
1092  }
1093  if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
1094  {
1095  return true;
1096  }
1097  // check label blend modes
1098  if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
1099  {
1100  // Check all label blending properties
1101 
1102  layerFormat.readFromLayer( currentVectorLayer );
1103  if ( layerFormat.containsAdvancedEffects() )
1104  return true;
1105  }
1106  }
1107  }
1108  }
1109 
1110  return false;
1111 }
1112 
1113 void QgsComposerMap::connectUpdateSlot()
1114 {
1115  //connect signal from layer registry to update in case of new or deleted layers
1116  QgsProject *project = mComposition->project();
1117  if ( project )
1118  {
1119  // handles updating the stored layer state BEFORE the layers are removed
1120  connect( project, static_cast < void ( QgsProject::* )( const QList<QgsMapLayer *>& layers ) > ( &QgsProject::layersWillBeRemoved ),
1121  this, &QgsComposerMap::layersAboutToBeRemoved );
1122  // redraws the map AFTER layers are removed
1125  }
1127 }
1128 
1129 bool QgsComposerMap::writeXml( QDomElement &elem, QDomDocument &doc ) const
1130 {
1131  if ( elem.isNull() )
1132  {
1133  return false;
1134  }
1135 
1136  QDomElement composerMapElem = doc.createElement( QStringLiteral( "ComposerMap" ) );
1137  composerMapElem.setAttribute( QStringLiteral( "id" ), mId );
1138 
1139  //previewMode
1140  if ( mPreviewMode == Cache )
1141  {
1142  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Cache" ) );
1143  }
1144  else if ( mPreviewMode == Render )
1145  {
1146  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Render" ) );
1147  }
1148  else //rectangle
1149  {
1150  composerMapElem.setAttribute( QStringLiteral( "previewMode" ), QStringLiteral( "Rectangle" ) );
1151  }
1152 
1153  if ( mKeepLayerSet )
1154  {
1155  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "true" ) );
1156  }
1157  else
1158  {
1159  composerMapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "false" ) );
1160  }
1161 
1162  if ( mDrawAnnotations )
1163  {
1164  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1165  }
1166  else
1167  {
1168  composerMapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "false" ) );
1169  }
1170 
1171  //extent
1172  QDomElement extentElem = doc.createElement( QStringLiteral( "Extent" ) );
1173  extentElem.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mExtent.xMinimum() ) );
1174  extentElem.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mExtent.xMaximum() ) );
1175  extentElem.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mExtent.yMinimum() ) );
1176  extentElem.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mExtent.yMaximum() ) );
1177  composerMapElem.appendChild( extentElem );
1178 
1179  if ( mCrs.isValid() )
1180  {
1181  QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
1182  mCrs.writeXml( crsElem, doc );
1183  composerMapElem.appendChild( crsElem );
1184  }
1185 
1186  // follow map theme
1187  composerMapElem.setAttribute( QStringLiteral( "followPreset" ), mFollowVisibilityPreset ? "true" : "false" );
1188  composerMapElem.setAttribute( QStringLiteral( "followPresetName" ), mFollowVisibilityPresetName );
1189 
1190  //map rotation
1191  composerMapElem.setAttribute( QStringLiteral( "mapRotation" ), QString::number( mMapRotation ) );
1192 
1193  //layer set
1194  QDomElement layerSetElem = doc.createElement( QStringLiteral( "LayerSet" ) );
1195  Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
1196  {
1197  if ( !layerRef )
1198  continue;
1199  QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
1200  QDomText layerIdText = doc.createTextNode( layerRef.layerId );
1201  layerElem.appendChild( layerIdText );
1202 
1203  layerElem.setAttribute( QStringLiteral( "name" ), layerRef.name );
1204  layerElem.setAttribute( QStringLiteral( "source" ), layerRef.source );
1205  layerElem.setAttribute( QStringLiteral( "provider" ), layerRef.provider );
1206 
1207  layerSetElem.appendChild( layerElem );
1208  }
1209  composerMapElem.appendChild( layerSetElem );
1210 
1211  // override styles
1212  if ( mKeepLayerStyles )
1213  {
1214  QDomElement stylesElem = doc.createElement( QStringLiteral( "LayerStyles" ) );
1215  QMap<QString, QString>::const_iterator styleIt = mLayerStyleOverrides.constBegin();
1216  for ( ; styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
1217  {
1218  QDomElement styleElem = doc.createElement( QStringLiteral( "LayerStyle" ) );
1219 
1220  QgsMapLayerRef ref( styleIt.key() );
1221  ref.resolve( mComposition->project() );
1222 
1223  styleElem.setAttribute( QStringLiteral( "layerid" ), ref.layerId );
1224  styleElem.setAttribute( QStringLiteral( "name" ), ref.name );
1225  styleElem.setAttribute( QStringLiteral( "source" ), ref.source );
1226  styleElem.setAttribute( QStringLiteral( "provider" ), ref.provider );
1227 
1228  QgsMapLayerStyle style( styleIt.value() );
1229  style.writeXml( styleElem );
1230  stylesElem.appendChild( styleElem );
1231  }
1232  composerMapElem.appendChild( stylesElem );
1233  }
1234 
1235  //write a dummy "Grid" element to prevent crashes on pre 2.5 versions (refs #10905)
1236  QDomElement gridElem = doc.createElement( QStringLiteral( "Grid" ) );
1237  composerMapElem.appendChild( gridElem );
1238 
1239  //grids
1240  mGridStack->writeXml( composerMapElem, doc );
1241 
1242  //overviews
1243  mOverviewStack->writeXml( composerMapElem, doc );
1244 
1245  //atlas
1246  QDomElement atlasElem = doc.createElement( QStringLiteral( "AtlasMap" ) );
1247  atlasElem.setAttribute( QStringLiteral( "atlasDriven" ), mAtlasDriven );
1248  atlasElem.setAttribute( QStringLiteral( "scalingMode" ), mAtlasScalingMode );
1249  atlasElem.setAttribute( QStringLiteral( "margin" ), qgsDoubleToString( mAtlasMargin ) );
1250  composerMapElem.appendChild( atlasElem );
1251 
1252  elem.appendChild( composerMapElem );
1253  return _writeXml( composerMapElem, doc );
1254 }
1255 
1256 bool QgsComposerMap::readXml( const QDomElement &itemElem, const QDomDocument &doc )
1257 {
1258  if ( itemElem.isNull() )
1259  {
1260  return false;
1261  }
1262 
1263  setUpdatesEnabled( false );
1264 
1265  QString idRead = itemElem.attribute( QStringLiteral( "id" ), QStringLiteral( "not found" ) );
1266  if ( idRead != QLatin1String( "not found" ) )
1267  {
1268  mId = idRead.toInt();
1269  updateToolTip();
1270  }
1271  mPreviewMode = Rectangle;
1272 
1273  //previewMode
1274  QString previewMode = itemElem.attribute( QStringLiteral( "previewMode" ) );
1275  if ( previewMode == QLatin1String( "Cache" ) )
1276  {
1277  mPreviewMode = Cache;
1278  }
1279  else if ( previewMode == QLatin1String( "Render" ) )
1280  {
1281  mPreviewMode = Render;
1282  }
1283  else
1284  {
1285  mPreviewMode = Rectangle;
1286  }
1287 
1288  //extent
1289  QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral( "Extent" ) );
1290  if ( !extentNodeList.isEmpty() )
1291  {
1292  QDomElement extentElem = extentNodeList.at( 0 ).toElement();
1293  double xmin, xmax, ymin, ymax;
1294  xmin = extentElem.attribute( QStringLiteral( "xmin" ) ).toDouble();
1295  xmax = extentElem.attribute( QStringLiteral( "xmax" ) ).toDouble();
1296  ymin = extentElem.attribute( QStringLiteral( "ymin" ) ).toDouble();
1297  ymax = extentElem.attribute( QStringLiteral( "ymax" ) ).toDouble();
1298  setNewExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
1299  }
1300 
1301  QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral( "crs" ) );
1302  if ( !crsNodeList.isEmpty() )
1303  {
1304  QDomElement crsElem = crsNodeList.at( 0 ).toElement();
1305  mCrs.readXml( crsElem );
1306  }
1307  else
1308  {
1310  }
1311 
1312  //map rotation
1313  if ( !qgsDoubleNear( itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1314  {
1315  mMapRotation = itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble();
1316  }
1317 
1318  // follow map theme
1319  mFollowVisibilityPreset = itemElem.attribute( QStringLiteral( "followPreset" ) ).compare( QLatin1String( "true" ) ) == 0;
1320  mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral( "followPresetName" ) );
1321 
1322  //mKeepLayerSet flag
1323  QString keepLayerSetFlag = itemElem.attribute( QStringLiteral( "keepLayerSet" ) );
1324  if ( keepLayerSetFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1325  {
1326  mKeepLayerSet = true;
1327  }
1328  else
1329  {
1330  mKeepLayerSet = false;
1331  }
1332 
1333  QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
1334  if ( drawCanvasItemsFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
1335  {
1336  mDrawAnnotations = true;
1337  }
1338  else
1339  {
1340  mDrawAnnotations = false;
1341  }
1342 
1343  mLayerStyleOverrides.clear();
1344 
1345  //mLayers
1346  mLayers.clear();
1347  QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerSet" ) );
1348  if ( !layerSetNodeList.isEmpty() )
1349  {
1350  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
1351  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral( "Layer" ) );
1352  mLayers.reserve( layerIdNodeList.size() );
1353  for ( int i = 0; i < layerIdNodeList.size(); ++i )
1354  {
1355  QDomElement layerElem = layerIdNodeList.at( i ).toElement();
1356  QString layerId = layerElem.text();
1357  QString layerName = layerElem.attribute( QStringLiteral( "name" ) );
1358  QString layerSource = layerElem.attribute( QStringLiteral( "source" ) );
1359  QString layerProvider = layerElem.attribute( QStringLiteral( "provider" ) );
1360 
1361  QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
1363  mLayers << ref;
1364  }
1365  }
1366 
1367  // override styles
1368  QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerStyles" ) );
1369  mKeepLayerStyles = !layerStylesNodeList.isEmpty();
1370  if ( mKeepLayerStyles )
1371  {
1372  QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
1373  QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral( "LayerStyle" ) );
1374  for ( int i = 0; i < layerStyleNodeList.size(); ++i )
1375  {
1376  const QDomElement &layerStyleElement = layerStyleNodeList.at( i ).toElement();
1377  QString layerId = layerStyleElement.attribute( QStringLiteral( "layerid" ) );
1378  QString layerName = layerStyleElement.attribute( QStringLiteral( "name" ) );
1379  QString layerSource = layerStyleElement.attribute( QStringLiteral( "source" ) );
1380  QString layerProvider = layerStyleElement.attribute( QStringLiteral( "provider" ) );
1381  QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
1383 
1384  QgsMapLayerStyle style;
1385  style.readXml( layerStyleElement );
1386  mLayerStyleOverrides.insert( ref.layerId, style.xmlData() );
1387  }
1388  }
1389 
1390  mDrawing = false;
1391  mNumCachedLayers = 0;
1392  mCacheUpdated = false;
1393 
1394  //overviews
1395  mOverviewStack->readXml( itemElem, doc );
1396 
1397  //grids
1398  mGridStack->readXml( itemElem, doc );
1399 
1400  //load grid / grid annotation in old xml format
1401  //only do this if the grid stack didn't load any grids, otherwise this will
1402  //be the dummy element created by QGIS >= 2.5 (refs #10905)
1403  QDomNodeList gridNodeList = itemElem.elementsByTagName( QStringLiteral( "Grid" ) );
1404  if ( mGridStack->size() == 0 && !gridNodeList.isEmpty() )
1405  {
1406  QDomElement gridElem = gridNodeList.at( 0 ).toElement();
1407  QgsComposerMapGrid *mapGrid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1408  mapGrid->setEnabled( gridElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1409  mapGrid->setStyle( QgsComposerMapGrid::GridStyle( gridElem.attribute( QStringLiteral( "gridStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1410  mapGrid->setIntervalX( gridElem.attribute( QStringLiteral( "intervalX" ), QStringLiteral( "0" ) ).toDouble() );
1411  mapGrid->setIntervalY( gridElem.attribute( QStringLiteral( "intervalY" ), QStringLiteral( "0" ) ).toDouble() );
1412  mapGrid->setOffsetX( gridElem.attribute( QStringLiteral( "offsetX" ), QStringLiteral( "0" ) ).toDouble() );
1413  mapGrid->setOffsetY( gridElem.attribute( QStringLiteral( "offsetY" ), QStringLiteral( "0" ) ).toDouble() );
1414  mapGrid->setCrossLength( gridElem.attribute( QStringLiteral( "crossLength" ), QStringLiteral( "3" ) ).toDouble() );
1415  mapGrid->setFrameStyle( static_cast< QgsComposerMapGrid::FrameStyle >( gridElem.attribute( QStringLiteral( "gridFrameStyle" ), QStringLiteral( "0" ) ).toInt() ) );
1416  mapGrid->setFrameWidth( gridElem.attribute( QStringLiteral( "gridFrameWidth" ), QStringLiteral( "2.0" ) ).toDouble() );
1417  mapGrid->setFramePenSize( gridElem.attribute( QStringLiteral( "gridFramePenThickness" ), QStringLiteral( "0.5" ) ).toDouble() );
1418  mapGrid->setFramePenColor( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "framePenColor" ), QStringLiteral( "0,0,0" ) ) ) );
1419  mapGrid->setFrameFillColor1( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor1" ), QStringLiteral( "255,255,255,255" ) ) ) );
1420  mapGrid->setFrameFillColor2( QgsSymbolLayerUtils::decodeColor( gridElem.attribute( QStringLiteral( "frameFillColor2" ), QStringLiteral( "0,0,0,255" ) ) ) );
1421  mapGrid->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( itemElem.attribute( QStringLiteral( "gridBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1422  QDomElement gridSymbolElem = gridElem.firstChildElement( QStringLiteral( "symbol" ) );
1423  QgsLineSymbol *lineSymbol = nullptr;
1424  if ( gridSymbolElem.isNull() )
1425  {
1426  //old project file, read penWidth /penColorRed, penColorGreen, penColorBlue
1427  lineSymbol = QgsLineSymbol::createSimple( QgsStringMap() );
1428  lineSymbol->setWidth( gridElem.attribute( QStringLiteral( "penWidth" ), QStringLiteral( "0" ) ).toDouble() );
1429  lineSymbol->setColor( QColor( gridElem.attribute( QStringLiteral( "penColorRed" ), QStringLiteral( "0" ) ).toInt(),
1430  gridElem.attribute( QStringLiteral( "penColorGreen" ), QStringLiteral( "0" ) ).toInt(),
1431  gridElem.attribute( QStringLiteral( "penColorBlue" ), QStringLiteral( "0" ) ).toInt() ) );
1432  }
1433  else
1434  {
1435  lineSymbol = QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( gridSymbolElem );
1436  }
1437  mapGrid->setLineSymbol( lineSymbol );
1438 
1439  //annotation
1440  QDomNodeList annotationNodeList = gridElem.elementsByTagName( QStringLiteral( "Annotation" ) );
1441  if ( !annotationNodeList.isEmpty() )
1442  {
1443  QDomElement annotationElem = annotationNodeList.at( 0 ).toElement();
1444  mapGrid->setAnnotationEnabled( annotationElem.attribute( QStringLiteral( "show" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1445  mapGrid->setAnnotationFormat( QgsComposerMapGrid::AnnotationFormat( annotationElem.attribute( QStringLiteral( "format" ), QStringLiteral( "0" ) ).toInt() ) );
1446  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "leftPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1447  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "rightPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1448  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "topPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1449  mapGrid->setAnnotationPosition( QgsComposerMapGrid::AnnotationPosition( annotationElem.attribute( QStringLiteral( "bottomPosition" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1450  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "leftDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Left );
1451  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "rightDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Right );
1452  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "topDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Top );
1453  mapGrid->setAnnotationDirection( QgsComposerMapGrid::AnnotationDirection( annotationElem.attribute( QStringLiteral( "bottomDirection" ), QStringLiteral( "0" ) ).toInt() ), QgsComposerMapGrid::Bottom );
1454  mapGrid->setAnnotationFrameDistance( annotationElem.attribute( QStringLiteral( "frameDistance" ), QStringLiteral( "0" ) ).toDouble() );
1455  QFont annotationFont;
1456  annotationFont.fromString( annotationElem.attribute( QStringLiteral( "font" ), QLatin1String( "" ) ) );
1457  mapGrid->setAnnotationFont( annotationFont );
1458  mapGrid->setAnnotationFontColor( QgsSymbolLayerUtils::decodeColor( itemElem.attribute( QStringLiteral( "fontColor" ), QStringLiteral( "0,0,0,255" ) ) ) );
1459 
1460  mapGrid->setAnnotationPrecision( annotationElem.attribute( QStringLiteral( "precision" ), QStringLiteral( "3" ) ).toInt() );
1461  }
1462  mGridStack->addGrid( mapGrid );
1463  }
1464 
1465  //load overview in old xml format
1466  QDomElement overviewFrameElem = itemElem.firstChildElement( QStringLiteral( "overviewFrame" ) );
1467  if ( !overviewFrameElem.isNull() )
1468  {
1469  QgsComposerMapOverview *mapOverview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( mOverviewStack->size() + 1 ), this );
1470 
1471  mapOverview->setFrameMap( overviewFrameElem.attribute( QStringLiteral( "overviewFrameMap" ), QStringLiteral( "-1" ) ).toInt() );
1472  mapOverview->setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( overviewFrameElem.attribute( QStringLiteral( "overviewBlendMode" ), QStringLiteral( "0" ) ).toUInt() ) ) );
1473  mapOverview->setInverted( overviewFrameElem.attribute( QStringLiteral( "overviewInverted" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1474  mapOverview->setCentered( overviewFrameElem.attribute( QStringLiteral( "overviewCentered" ) ).compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 );
1475 
1476  QgsFillSymbol *fillSymbol = nullptr;
1477  QDomElement overviewFrameSymbolElem = overviewFrameElem.firstChildElement( QStringLiteral( "symbol" ) );
1478  if ( !overviewFrameSymbolElem.isNull() )
1479  {
1480  fillSymbol = QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( overviewFrameSymbolElem );
1481  mapOverview->setFrameSymbol( fillSymbol );
1482  }
1483  mOverviewStack->addOverview( mapOverview );
1484  }
1485 
1486  //atlas
1487  QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral( "AtlasMap" ) );
1488  if ( !atlasNodeList.isEmpty() )
1489  {
1490  QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
1491  mAtlasDriven = ( atlasElem.attribute( QStringLiteral( "atlasDriven" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
1492  if ( atlasElem.hasAttribute( QStringLiteral( "fixedScale" ) ) ) // deprecated XML
1493  {
1494  mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral( "fixedScale" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) ) ? Fixed : Auto;
1495  }
1496  else if ( atlasElem.hasAttribute( QStringLiteral( "scalingMode" ) ) )
1497  {
1498  mAtlasScalingMode = static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral( "scalingMode" ) ).toInt() );
1499  }
1500  mAtlasMargin = atlasElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "0.1" ) ).toDouble();
1501  }
1502 
1503  //restore general composer item properties
1504  QDomNodeList composerItemList = itemElem.elementsByTagName( QStringLiteral( "ComposerItem" ) );
1505  if ( !composerItemList.isEmpty() )
1506  {
1507  QDomElement composerItemElem = composerItemList.at( 0 ).toElement();
1508 
1509  if ( !qgsDoubleNear( composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble(), 0.0 ) )
1510  {
1511  //in versions prior to 2.1 map rotation was stored in the rotation attribute
1512  mMapRotation = composerItemElem.attribute( QStringLiteral( "rotation" ), QStringLiteral( "0" ) ).toDouble();
1513  }
1514 
1515  _readXml( composerItemElem, doc );
1516  }
1517 
1519  setUpdatesEnabled( true );
1520 
1521  emit itemChanged();
1522  return true;
1523 }
1524 
1525 QList<QgsMapLayer *> QgsComposerMap::layers() const
1526 {
1527  return _qgis_listRefToRaw( mLayers );
1528 }
1529 
1530 void QgsComposerMap::setLayers( const QList<QgsMapLayer *> &layers )
1531 {
1532  mLayers = _qgis_listRawToRef( layers );
1533 }
1534 
1535 
1536 void QgsComposerMap::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
1537 {
1538  if ( overrides == mLayerStyleOverrides )
1539  return;
1540 
1541  mLayerStyleOverrides = overrides;
1542  emit layerStyleOverridesChanged(); // associated legends may listen to this
1543 }
1544 
1545 
1547 {
1548  mLayerStyleOverrides.clear();
1549  Q_FOREACH ( const QgsMapLayerRef &layerRef, mLayers )
1550  {
1551  if ( QgsMapLayer *layer = layerRef.get() )
1552  {
1553  QgsMapLayerStyle style;
1554  style.readFromLayer( layer );
1555  mLayerStyleOverrides.insert( layer->id(), style.xmlData() );
1556  }
1557  }
1558 }
1559 
1560 void QgsComposerMap::layersAboutToBeRemoved( QList< QgsMapLayer * > layers )
1561 {
1562  if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1563  {
1564  Q_FOREACH ( QgsMapLayer *layer, layers )
1565  {
1566  mLayerStyleOverrides.remove( layer->id() );
1567  }
1568  _qgis_removeLayers( mLayers, layers );
1569  }
1570 }
1571 
1573 {
1574  if ( mGridStack->size() < 1 )
1575  {
1576  QgsComposerMapGrid *grid = new QgsComposerMapGrid( tr( "Grid %1" ).arg( 1 ), this );
1577  mGridStack->addGrid( grid );
1578  }
1579  return mGridStack->grid( 0 );
1580 }
1581 
1582 const QgsComposerMapGrid *QgsComposerMap::constFirstMapGrid() const
1583 {
1584  return const_cast<QgsComposerMap *>( this )->grid();
1585 }
1586 
1588 {
1589  if ( mOverviewStack->size() < 1 )
1590  {
1591  QgsComposerMapOverview *overview = new QgsComposerMapOverview( tr( "Overview %1" ).arg( 1 ), this );
1592  mOverviewStack->addOverview( overview );
1593  }
1594  return mOverviewStack->overview( 0 );
1595 }
1596 
1597 const QgsComposerMapOverview *QgsComposerMap::constFirstMapOverview() const
1598 {
1599  return const_cast<QgsComposerMap *>( this )->overview();
1600 }
1601 
1603 {
1604  return mCurrentRectangle;
1605 }
1606 
1608 {
1609  QRectF rectangle = rect();
1610  double frameExtension = mFrame ? pen().widthF() / 2.0 : 0.0;
1611 
1612  double topExtension = 0.0;
1613  double rightExtension = 0.0;
1614  double bottomExtension = 0.0;
1615  double leftExtension = 0.0;
1616 
1617  if ( mGridStack )
1618  mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1619 
1620  topExtension = qMax( topExtension, frameExtension );
1621  rightExtension = qMax( rightExtension, frameExtension );
1622  bottomExtension = qMax( bottomExtension, frameExtension );
1623  leftExtension = qMax( leftExtension, frameExtension );
1624 
1625  rectangle.setLeft( rectangle.left() - leftExtension );
1626  rectangle.setRight( rectangle.right() + rightExtension );
1627  rectangle.setTop( rectangle.top() - topExtension );
1628  rectangle.setBottom( rectangle.bottom() + bottomExtension );
1629  if ( rectangle != mCurrentRectangle )
1630  {
1631  prepareGeometryChange();
1632  mCurrentRectangle = rectangle;
1633  }
1634 }
1635 
1636 void QgsComposerMap::setFrameStrokeWidth( const double strokeWidth )
1637 {
1638  QgsComposerItem::setFrameStrokeWidth( strokeWidth );
1640 }
1641 
1642 QgsRectangle QgsComposerMap::transformedExtent() const
1643 {
1644  double dx = mXOffset;
1645  double dy = mYOffset;
1646  transformShift( dx, dy );
1647  return QgsRectangle( currentMapExtent()->xMinimum() - dx, currentMapExtent()->yMinimum() - dy, currentMapExtent()->xMaximum() - dx, currentMapExtent()->yMaximum() - dy );
1648 }
1649 
1651 {
1652  double dx = mXOffset;
1653  double dy = mYOffset;
1654  //qWarning("offset");
1655  //qWarning(QString::number(dx).toLocal8Bit().data());
1656  //qWarning(QString::number(dy).toLocal8Bit().data());
1657  transformShift( dx, dy );
1658  //qWarning("transformed:");
1659  //qWarning(QString::number(dx).toLocal8Bit().data());
1660  //qWarning(QString::number(dy).toLocal8Bit().data());
1661  QPolygonF poly = visibleExtentPolygon();
1662  poly.translate( -dx, -dy );
1663  return poly;
1664 }
1665 
1666 void QgsComposerMap::mapPolygon( const QgsRectangle &extent, QPolygonF &poly ) const
1667 {
1668  poly.clear();
1669  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1670  {
1671  poly << QPointF( extent.xMinimum(), extent.yMaximum() );
1672  poly << QPointF( extent.xMaximum(), extent.yMaximum() );
1673  poly << QPointF( extent.xMaximum(), extent.yMinimum() );
1674  poly << QPointF( extent.xMinimum(), extent.yMinimum() );
1675  //ensure polygon is closed by readding first point
1676  poly << QPointF( poly.at( 0 ) );
1677  return;
1678  }
1679 
1680  //there is rotation
1681  QgsPoint rotationPoint( ( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
1682  double dx, dy; //x-, y- shift from rotation point to corner point
1683 
1684  //top left point
1685  dx = rotationPoint.x() - extent.xMinimum();
1686  dy = rotationPoint.y() - extent.yMaximum();
1687  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1688  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1689 
1690  //top right point
1691  dx = rotationPoint.x() - extent.xMaximum();
1692  dy = rotationPoint.y() - extent.yMaximum();
1693  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1694  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1695 
1696  //bottom right point
1697  dx = rotationPoint.x() - extent.xMaximum();
1698  dy = rotationPoint.y() - extent.yMinimum();
1699  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1700  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1701 
1702  //bottom left point
1703  dx = rotationPoint.x() - extent.xMinimum();
1704  dy = rotationPoint.y() - extent.yMinimum();
1705  QgsComposerUtils::rotate( mEvaluatedMapRotation, dx, dy );
1706  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
1707 
1708  //ensure polygon is closed by readding first point
1709  poly << QPointF( poly.at( 0 ) );
1710 }
1711 
1713 {
1714  QPolygonF poly;
1715  mapPolygon( *currentMapExtent(), poly );
1716  return poly;
1717 }
1718 
1720 {
1721  if ( !QgsComposerItem::id().isEmpty() )
1722  {
1723  return QgsComposerItem::id();
1724  }
1725 
1726  return tr( "Map %1" ).arg( mId );
1727 }
1728 
1730 {
1731  QgsRectangle newExtent = *currentMapExtent();
1732  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1733  {
1734  extent = newExtent;
1735  }
1736  else
1737  {
1738  QPolygonF poly;
1739  mapPolygon( newExtent, poly );
1740  QRectF bRect = poly.boundingRect();
1741  extent.setXMinimum( bRect.left() );
1742  extent.setXMaximum( bRect.right() );
1743  extent.setYMinimum( bRect.top() );
1744  extent.setYMaximum( bRect.bottom() );
1745  }
1746 }
1747 
1749 {
1751 
1752  //Can't utilize QgsExpressionContextUtils::mapSettingsScope as we don't always
1753  //have a QgsMapSettings object available when the context is required, so we manually
1754  //add the same variables here
1755  QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Map Settings" ) );
1756 
1757  //use QgsComposerItem's id, not map item's ID, since that is user-definable
1758  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), QgsComposerItem::id(), true ) );
1759  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mMapRotation, true ) );
1760  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), scale(), true ) );
1761 
1763  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( QgsGeometry::fromRect( extent ) ), true ) );
1764  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), extent.width(), true ) );
1765  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), extent.height(), true ) );
1766  QgsGeometry centerPoint = QgsGeometry::fromPoint( extent.center() );
1767  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
1768 
1769  if ( mComposition )
1770  {
1771  QgsCoordinateReferenceSystem mapCrs = crs();
1772  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapCrs.authid(), true ) );
1773  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapCrs.toProj4(), true ) );
1774  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapCrs.mapUnits() ), true ) );
1775  }
1776 
1777  context.appendScope( scope );
1778 
1779  return context;
1780 }
1781 
1783 {
1784  double extentWidth = currentMapExtent()->width();
1785  if ( extentWidth <= 0 )
1786  {
1787  return 1;
1788  }
1789  return rect().width() / extentWidth;
1790 }
1791 
1793 {
1795  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
1796 
1797  //updates data defined properties and redraws item to match
1798  if ( property == QgsComposerObject::MapRotation || property == QgsComposerObject::MapScale ||
1799  property == QgsComposerObject::MapXMin || property == QgsComposerObject::MapYMin ||
1800  property == QgsComposerObject::MapXMax || property == QgsComposerObject::MapYMax ||
1801  property == QgsComposerObject::MapAtlasMargin ||
1802  property == QgsComposerObject::AllProperties )
1803  {
1804  QgsRectangle beforeExtent = *currentMapExtent();
1805  refreshMapExtents( evalContext );
1806  emit itemChanged();
1807  if ( *currentMapExtent() != beforeExtent )
1808  {
1809  emit extentChanged();
1810  }
1811  }
1812 
1813  //force redraw
1814  mCacheUpdated = false;
1815 
1816  QgsComposerItem::refreshDataDefinedProperty( property, evalContext );
1817 }
1818 
1819 void QgsComposerMap::transformShift( double &xShift, double &yShift ) const
1820 {
1821  double mmToMapUnits = 1.0 / mapUnitsToMM();
1822  double dxScaled = xShift * mmToMapUnits;
1823  double dyScaled = - yShift * mmToMapUnits;
1824 
1825  QgsComposerUtils::rotate( mEvaluatedMapRotation, dxScaled, dyScaled );
1826 
1827  xShift = dxScaled;
1828  yShift = dyScaled;
1829 }
1830 
1831 QPointF QgsComposerMap::mapToItemCoords( QPointF mapCoords ) const
1832 {
1833  QPolygonF mapPoly = transformedMapPolygon();
1834  if ( mapPoly.size() < 1 )
1835  {
1836  return QPointF( 0, 0 );
1837  }
1838 
1839  QgsRectangle tExtent = transformedExtent();
1840  QgsPoint rotationPoint( ( tExtent.xMaximum() + tExtent.xMinimum() ) / 2.0, ( tExtent.yMaximum() + tExtent.yMinimum() ) / 2.0 );
1841  double dx = mapCoords.x() - rotationPoint.x();
1842  double dy = mapCoords.y() - rotationPoint.y();
1843  QgsComposerUtils::rotate( -mEvaluatedMapRotation, dx, dy );
1844  QgsPoint backRotatedCoords( rotationPoint.x() + dx, rotationPoint.y() + dy );
1845 
1846  QgsRectangle unrotatedExtent = transformedExtent();
1847  double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
1848  double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
1849  return QPointF( xItem, yItem );
1850 }
1851 
1852 void QgsComposerMap::drawAnnotations( QPainter *painter )
1853 {
1854  if ( !mComposition || !mComposition->project() || !mDrawAnnotations )
1855  {
1856  return;
1857  }
1858 
1859  QList< QgsAnnotation * > annotations = mComposition->project()->annotationManager()->annotations();
1860  if ( annotations.isEmpty() )
1861  return;
1862 
1864  rc.setForceVectorOutput( true );
1866  QList< QgsMapLayer * > layers = layersToRender( &rc.expressionContext() );
1867 
1868  Q_FOREACH ( QgsAnnotation *annotation, annotations )
1869  {
1870  if ( !annotation || !annotation->isVisible() )
1871  {
1872  continue;
1873  }
1874  if ( annotation->mapLayer() && !layers.contains( annotation->mapLayer() ) )
1875  continue;
1876 
1877  drawAnnotation( annotation, rc );
1878  }
1879 }
1880 
1881 void QgsComposerMap::drawAnnotation( const QgsAnnotation *annotation, QgsRenderContext &context )
1882 {
1883  if ( !annotation || !annotation->isVisible() || !context.painter() || !context.painter()->device() )
1884  {
1885  return;
1886  }
1887 
1888  context.painter()->save();
1889  context.painter()->setRenderHint( QPainter::Antialiasing, context.flags() & QgsRenderContext::Antialiasing );
1890 
1891  double itemX, itemY;
1892  if ( annotation->hasFixedMapPosition() )
1893  {
1894  QPointF mapPos = composerMapPosForItem( annotation );
1895  itemX = mapPos.x();
1896  itemY = mapPos.y();
1897  }
1898  else
1899  {
1900  itemX = annotation->relativePosition().x() * rect().width();
1901  itemY = annotation->relativePosition().y() * rect().height();
1902  }
1903  context.painter()->translate( itemX, itemY );
1904 
1905  //setup painter scaling to dots so that symbology is drawn to scale
1906  double dotsPerMM = context.painter()->device()->logicalDpiX() / 25.4;
1907  context.painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1908 
1909  annotation->render( context );
1910  context.painter()->restore();
1911 }
1912 
1913 QPointF QgsComposerMap::composerMapPosForItem( const QgsAnnotation *annotation ) const
1914 {
1915  if ( !annotation )
1916  return QPointF( 0, 0 );
1917 
1918  double mapX = 0.0;
1919  double mapY = 0.0;
1920 
1921  mapX = annotation->mapPosition().x();
1922  mapY = annotation->mapPosition().y();
1923  QgsCoordinateReferenceSystem annotationCrs = annotation->mapPositionCrs();
1924 
1925  if ( annotationCrs != crs() )
1926  {
1927  //need to reproject
1928  QgsCoordinateTransform t( annotationCrs, crs() );
1929  double z = 0.0;
1930  t.transformInPlace( mapX, mapY, z );
1931  }
1932 
1933  return mapToItemCoords( QPointF( mapX, mapY ) );
1934 }
1935 
1937 {
1938  if ( !mComposition )
1939  {
1940  return;
1941  }
1942 
1943  const QgsComposerMap *existingMap = mComposition->getComposerMapById( mId );
1944  if ( !existingMap )
1945  {
1946  return; //keep mId as it is still available
1947  }
1948 
1949  int maxId = -1;
1950  QList<const QgsComposerMap *> mapList = mComposition->composerMapItems();
1951  QList<const QgsComposerMap *>::const_iterator mapIt = mapList.constBegin();
1952  for ( ; mapIt != mapList.constEnd(); ++mapIt )
1953  {
1954  if ( ( *mapIt )->id() > maxId )
1955  {
1956  maxId = ( *mapIt )->id();
1957  }
1958  }
1959  mId = maxId + 1;
1960  updateToolTip();
1961 }
1962 
1964 {
1965  mAtlasDriven = enabled;
1966 
1967  if ( !enabled )
1968  {
1969  //if not enabling the atlas, we still need to refresh the map extents
1970  //so that data defined extents and scale are recalculated
1971  refreshMapExtents();
1972  }
1973 }
1974 
1976 {
1977  if ( valueType == QgsComposerObject::EvaluatedValue )
1978  {
1979  //evaluate data defined atlas margin
1980 
1981  //start with user specified margin
1982  double margin = mAtlasMargin;
1984 
1985  bool ok = false;
1986  double ddMargin = mDataDefinedProperties.valueAsDouble( QgsComposerObject::MapAtlasMargin, context, 0.0, &ok );
1987  if ( ok )
1988  {
1989  //divide by 100 to convert to 0 -> 1.0 range
1990  margin = ddMargin / 100;
1991  }
1992  return margin;
1993  }
1994  else
1995  {
1996  return mAtlasMargin;
1997  }
1998 }
1999 
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:38
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:53
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
Returns the center point of the rectangle.
Definition: qgsrectangle.h:146
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:70
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:70
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.
TYPE * resolveWeakly(const QgsProject *project)
Resolves the map layer by attempting to find a matching layer in a project using a weak match...
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.
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:344
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:201
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.
QString provider
Weak reference to layer provider.
bool _writeXml(QDomElement &itemElem, QDomDocument &doc) const
Writes parameter that are not subclass specific in document. Usually called from writeXml methods of ...
QString layerId
Original layer ID.
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
Returns the width of the rectangle.
Definition: qgsrectangle.h:118
void setCacheUpdated(bool u=false)
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:189
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:75
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:81
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.
QString name
Weak reference to layer name.
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:75
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.
QString source
Weak reference to layer public source.
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
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:106
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
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:91
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.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets global configuration of the labeling engine.
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:80
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
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:96
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.
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
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:101
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.
TYPE * resolve(const QgsProject *project)
Resolves the map layer by attempting to find a layer with matching ID within a project.
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.
TYPE * get() const
Returns a pointer to the layer, or nullptr if the reference has not yet been matched to a layer...
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:65
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
Returns the height of the rectangle.
Definition: qgsrectangle.h:125
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
const QgsLabelingEngineSettings & labelingEngineSettings() const
Returns project&#39;s global labeling engine settings.
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.