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