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