QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgslayoutitemmap.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutitemmap.cpp
3  ---------------------
4  begin : July 2017
5  copyright : (C) 2017 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgslayoutitemmap.h"
18 #include "qgslayout.h"
19 #include "qgslayoutrendercontext.h"
20 #include "qgslayoutreportcontext.h"
21 #include "qgslayoututils.h"
22 #include "qgslayoutmodel.h"
23 #include "qgsmapthemecollection.h"
24 #include "qgsannotationmanager.h"
25 #include "qgsannotation.h"
26 #include "qgsmapsettingsutils.h"
27 #include "qgslayertree.h"
28 #include "qgsmaplayerref.h"
29 #include "qgsmaplayerlistutils_p.h"
31 #include "qgsvectorlayer.h"
32 #include "qgsexpressioncontext.h"
33 #include "qgsapplication.h"
35 #include "qgsstyleentityvisitor.h"
36 #include "qgsannotationlayer.h"
38 #include "qgsprojoperation.h"
39 #include "qgslabelingresults.h"
40 #include "qgsvectortileutils.h"
41 
42 #include <QPainter>
43 #include <QStyleOptionGraphicsItem>
44 #include <QTimer>
45 
47  : QgsLayoutItem( layout )
48  , mAtlasClippingSettings( new QgsLayoutItemMapAtlasClippingSettings( this ) )
49  , mItemClippingSettings( new QgsLayoutItemMapItemClipPathSettings( this ) )
50 {
51  mBackgroundUpdateTimer = new QTimer( this );
52  mBackgroundUpdateTimer->setSingleShot( true );
53  connect( mBackgroundUpdateTimer, &QTimer::timeout, this, &QgsLayoutItemMap::recreateCachedImageInBackground );
54 
55  assignFreeId();
56 
57  setCacheMode( QGraphicsItem::NoCache );
58 
59  connect( this, &QgsLayoutItem::sizePositionChanged, this, [ = ]
60  {
61  shapeChanged();
62  } );
63 
64  mGridStack = std::make_unique< QgsLayoutItemMapGridStack >( this );
65  mOverviewStack = std::make_unique< QgsLayoutItemMapOverviewStack >( this );
66 
67  connect( mAtlasClippingSettings, &QgsLayoutItemMapAtlasClippingSettings::changed, this, [ = ]
68  {
69  refresh();
70  } );
71 
72  connect( mItemClippingSettings, &QgsLayoutItemMapItemClipPathSettings::changed, this, [ = ]
73  {
74  refresh();
75  } );
76 
78  {
81  if ( mCrs != crs )
82  {
83  setCrs( crs );
85  }
86  } );
87 
88  if ( layout )
89  connectUpdateSlot();
90 }
91 
93 {
94  if ( mPainterJob )
95  {
96  disconnect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsLayoutItemMap::painterJobFinished );
98  mPainterJob->cancel(); // blocks
99  mPainter->end();
100  }
101 }
102 
104 {
106 }
107 
109 {
110  return QgsApplication::getThemeIcon( QStringLiteral( "/mLayoutItemMap.svg" ) );
111 }
112 
113 QgsLayoutItem::Flags QgsLayoutItemMap::itemFlags() const
114 {
116 }
117 
119 {
120  if ( !mLayout )
121  return;
122 
123  QList<QgsLayoutItemMap *> mapsList;
124  mLayout->layoutItems( mapsList );
125 
126  int maxId = -1;
127  bool used = false;
128  for ( QgsLayoutItemMap *map : std::as_const( mapsList ) )
129  {
130  if ( map == this )
131  continue;
132 
133  if ( map->mMapId == mMapId )
134  used = true;
135 
136  maxId = std::max( maxId, map->mMapId );
137  }
138  if ( used )
139  {
140  mMapId = maxId + 1;
141  mLayout->itemsModel()->updateItemDisplayName( this );
142  }
143  updateToolTip();
144 }
145 
147 {
148  if ( !QgsLayoutItem::id().isEmpty() )
149  {
150  return QgsLayoutItem::id();
151  }
152 
153  return tr( "Map %1" ).arg( mMapId );
154 }
155 
157 {
158  return new QgsLayoutItemMap( layout );
159 }
160 
162 {
164 
165  mCachedLayerStyleOverridesPresetName.clear();
166 
167  invalidateCache();
168 
169  updateAtlasFeature();
170 }
171 
173 {
174  if ( rect().isEmpty() )
175  return 0;
176 
177  QgsScaleCalculator calculator;
178  calculator.setMapUnits( crs().mapUnits() );
179  calculator.setDpi( 25.4 ); //Using mm
180  double widthInMm = mLayout->convertFromLayoutUnits( rect().width(), QgsUnitTypes::LayoutMillimeters ).length();
181  return calculator.calculate( extent(), widthInMm );
182 }
183 
184 void QgsLayoutItemMap::setScale( double scaleDenominator, bool forceUpdate )
185 {
186  double currentScaleDenominator = scale();
187 
188  if ( qgsDoubleNear( scaleDenominator, currentScaleDenominator ) || qgsDoubleNear( scaleDenominator, 0.0 ) )
189  {
190  return;
191  }
192 
193  double scaleRatio = scaleDenominator / currentScaleDenominator;
194  mExtent.scale( scaleRatio );
195 
196  if ( mAtlasDriven && mAtlasScalingMode == Fixed )
197  {
198  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
199  //and also apply to the map's original extent (see #9602)
200  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
201  QgsScaleCalculator calculator;
202  calculator.setMapUnits( crs().mapUnits() );
203  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
204  scaleRatio = scaleDenominator / calculator.calculate( mExtent, rect().width() );
205  mExtent.scale( scaleRatio );
206  }
207 
208  invalidateCache();
209  if ( forceUpdate )
210  {
211  emit changed();
212  update();
213  }
214  emit extentChanged();
215 }
216 
218 {
219  if ( mExtent == extent )
220  {
221  return;
222  }
223  mExtent = extent;
224 
225  //recalculate data defined scale and extents, since that may override extent
226  refreshMapExtents();
227 
228  //adjust height
229  QRectF currentRect = rect();
230 
231  double newHeight = currentRect.width() * mExtent.height() / mExtent.width();
232 
233  attemptSetSceneRect( QRectF( pos().x(), pos().y(), currentRect.width(), newHeight ) );
234  update();
235 }
236 
238 {
239  QgsRectangle newExtent = extent;
240  QgsRectangle currentExtent = mExtent;
241  //Make sure the width/height ratio is the same as the current layout map extent.
242  //This is to keep the map item frame size fixed
243  double currentWidthHeightRatio = 1.0;
244  if ( !currentExtent.isNull() )
245  currentWidthHeightRatio = currentExtent.width() / currentExtent.height();
246  else
247  currentWidthHeightRatio = rect().width() / rect().height();
248  double newWidthHeightRatio = newExtent.width() / newExtent.height();
249 
250  if ( currentWidthHeightRatio < newWidthHeightRatio )
251  {
252  //enlarge height of new extent, ensuring the map center stays the same
253  double newHeight = newExtent.width() / currentWidthHeightRatio;
254  double deltaHeight = newHeight - newExtent.height();
255  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
256  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
257  }
258  else
259  {
260  //enlarge width of new extent, ensuring the map center stays the same
261  double newWidth = currentWidthHeightRatio * newExtent.height();
262  double deltaWidth = newWidth - newExtent.width();
263  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
264  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
265  }
266 
267  if ( mExtent == newExtent )
268  {
269  return;
270  }
271  mExtent = newExtent;
272 
273  //recalculate data defined scale and extents, since that may override extent
274  refreshMapExtents();
275 
276  invalidateCache();
277  emit changed();
278  emit extentChanged();
279 }
280 
282 {
283  return mExtent;
284 }
285 
286 QPolygonF QgsLayoutItemMap::calculateVisibleExtentPolygon( bool includeClipping ) const
287 {
288  QPolygonF poly;
289  mapPolygon( mExtent, poly );
290 
291  if ( includeClipping && mItemClippingSettings->isActive() )
292  {
293  const QgsGeometry geom = mItemClippingSettings->clippedMapExtent();
294  if ( !geom.isEmpty() )
295  {
296  poly = poly.intersected( geom.asQPolygonF() );
297  }
298  }
299 
300  return poly;
301 }
302 
304 {
305  return calculateVisibleExtentPolygon( true );
306 }
307 
309 {
310  if ( mCrs.isValid() )
311  return mCrs;
312  else if ( mLayout && mLayout->project() )
313  return mLayout->project()->crs();
315 }
316 
318 {
319  if ( mCrs == crs )
320  return;
321 
322  mCrs = crs;
323  emit crsChanged();
324 }
325 
326 QList<QgsMapLayer *> QgsLayoutItemMap::layers() const
327 {
328  return _qgis_listRefToRaw( mLayers );
329 }
330 
331 void QgsLayoutItemMap::setLayers( const QList<QgsMapLayer *> &layers )
332 {
333  mLayers = _qgis_listRawToRef( layers );
334 }
335 
336 void QgsLayoutItemMap::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
337 {
338  if ( overrides == mLayerStyleOverrides )
339  return;
340 
341  mLayerStyleOverrides = overrides;
342  emit layerStyleOverridesChanged(); // associated legends may listen to this
343 
344 }
345 
347 {
348  mLayerStyleOverrides.clear();
349  for ( const QgsMapLayerRef &layerRef : std::as_const( mLayers ) )
350  {
351  if ( QgsMapLayer *layer = layerRef.get() )
352  {
353  QgsMapLayerStyle style;
354  style.readFromLayer( layer );
355  mLayerStyleOverrides.insert( layer->id(), style.xmlData() );
356  }
357  }
358 }
359 
361 {
362  if ( mFollowVisibilityPreset == follow )
363  return;
364 
365  mFollowVisibilityPreset = follow;
366 
367  if ( !mFollowVisibilityPresetName.isEmpty() )
368  emit themeChanged( mFollowVisibilityPreset ? mFollowVisibilityPresetName : QString() );
369 }
370 
372 {
373  if ( name == mFollowVisibilityPresetName )
374  return;
375 
376  mFollowVisibilityPresetName = name;
377  if ( mFollowVisibilityPreset )
378  emit themeChanged( mFollowVisibilityPresetName );
379 }
380 
381 void QgsLayoutItemMap::moveContent( double dx, double dy )
382 {
383  mLastRenderedImageOffsetX -= dx;
384  mLastRenderedImageOffsetY -= dy;
385  if ( !mDrawing )
386  {
387  transformShift( dx, dy );
388  mExtent.setXMinimum( mExtent.xMinimum() + dx );
389  mExtent.setXMaximum( mExtent.xMaximum() + dx );
390  mExtent.setYMinimum( mExtent.yMinimum() + dy );
391  mExtent.setYMaximum( mExtent.yMaximum() + dy );
392 
393  //in case data defined extents are set, these override the calculated values
394  refreshMapExtents();
395 
396  invalidateCache();
397  emit changed();
398  emit extentChanged();
399  }
400 }
401 
402 void QgsLayoutItemMap::zoomContent( double factor, QPointF point )
403 {
404  if ( mDrawing )
405  {
406  return;
407  }
408 
409  //find out map coordinates of position
410  double mapX = mExtent.xMinimum() + ( point.x() / rect().width() ) * ( mExtent.xMaximum() - mExtent.xMinimum() );
411  double mapY = mExtent.yMinimum() + ( 1 - ( point.y() / rect().height() ) ) * ( mExtent.yMaximum() - mExtent.yMinimum() );
412 
413  //find out new center point
414  double centerX = ( mExtent.xMaximum() + mExtent.xMinimum() ) / 2;
415  double centerY = ( mExtent.yMaximum() + mExtent.yMinimum() ) / 2;
416 
417  centerX = mapX + ( centerX - mapX ) * ( 1.0 / factor );
418  centerY = mapY + ( centerY - mapY ) * ( 1.0 / factor );
419 
420  double newIntervalX, newIntervalY;
421 
422  if ( factor > 0 )
423  {
424  newIntervalX = ( mExtent.xMaximum() - mExtent.xMinimum() ) / factor;
425  newIntervalY = ( mExtent.yMaximum() - mExtent.yMinimum() ) / factor;
426  }
427  else //no need to zoom
428  {
429  return;
430  }
431 
432  mExtent.setXMaximum( centerX + newIntervalX / 2 );
433  mExtent.setXMinimum( centerX - newIntervalX / 2 );
434  mExtent.setYMaximum( centerY + newIntervalY / 2 );
435  mExtent.setYMinimum( centerY - newIntervalY / 2 );
436 
437  if ( mAtlasDriven && mAtlasScalingMode == Fixed )
438  {
439  //if map is atlas controlled and set to fixed scaling mode, then scale changes should be treated as permanent
440  //and also apply to the map's original extent (see #9602)
441  //we can't use the scaleRatio calculated earlier, as the scale can vary depending on extent for geographic coordinate systems
442  QgsScaleCalculator calculator;
443  calculator.setMapUnits( crs().mapUnits() );
444  calculator.setDpi( 25.4 ); //QGraphicsView units are mm
445  double scaleRatio = scale() / calculator.calculate( mExtent, rect().width() );
446  mExtent.scale( scaleRatio );
447  }
448 
449  //recalculate data defined scale and extents, since that may override zoom
450  refreshMapExtents();
451 
452  invalidateCache();
453  emit changed();
454  emit extentChanged();
455 }
456 
458 {
459  const QList< QgsMapLayer * > layers = layersToRender();
460  for ( QgsMapLayer *layer : layers )
461  {
462  if ( layer->dataProvider() && layer->providerType() == QLatin1String( "wms" ) )
463  {
464  return true;
465  }
466  }
467  return false;
468 }
469 
471 {
473  return true;
474 
475  // we MUST force the whole layout to render as a raster if any map item
476  // uses blend modes, and we are not drawing on a solid opaque background
477  // because in this case the map item needs to be rendered as a raster, but
478  // it also needs to interact with items below it
479  if ( !containsAdvancedEffects() )
480  return false;
481 
482  if ( hasBackground() && qgsDoubleNear( backgroundColor().alphaF(), 1.0 ) )
483  return false;
484 
485  return true;
486 }
487 
489 {
491  return true;
492 
493  //check easy things first
494 
495  //overviews
496  if ( mOverviewStack->containsAdvancedEffects() )
497  {
498  return true;
499  }
500 
501  //grids
502  if ( mGridStack->containsAdvancedEffects() )
503  {
504  return true;
505  }
506 
507  QgsMapSettings ms;
508  ms.setLayers( layersToRender() );
509  return ( !QgsMapSettingsUtils::containsAdvancedEffects( ms ).isEmpty() );
510 }
511 
512 void QgsLayoutItemMap::setMapRotation( double rotation )
513 {
514  mMapRotation = rotation;
515  mEvaluatedMapRotation = mMapRotation;
516  invalidateCache();
517  emit mapRotationChanged( rotation );
518  emit changed();
519 }
520 
522 {
523  return valueType == QgsLayoutObject::EvaluatedValue ? mEvaluatedMapRotation : mMapRotation;
524 
525 }
526 
528 {
529  mAtlasDriven = enabled;
530 
531  if ( !enabled )
532  {
533  //if not enabling the atlas, we still need to refresh the map extents
534  //so that data defined extents and scale are recalculated
535  refreshMapExtents();
536  }
537 }
538 
540 {
541  if ( valueType == QgsLayoutObject::EvaluatedValue )
542  {
543  //evaluate data defined atlas margin
544 
545  //start with user specified margin
546  double margin = mAtlasMargin;
548 
549  bool ok = false;
550  double ddMargin = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapAtlasMargin, context, 0.0, &ok );
551  if ( ok )
552  {
553  //divide by 100 to convert to 0 -> 1.0 range
554  margin = ddMargin / 100;
555  }
556  return margin;
557  }
558  else
559  {
560  return mAtlasMargin;
561  }
562 }
563 
565 {
566  if ( mGridStack->size() < 1 )
567  {
568  QgsLayoutItemMapGrid *grid = new QgsLayoutItemMapGrid( tr( "Grid %1" ).arg( 1 ), this );
569  mGridStack->addGrid( grid );
570  }
571  return mGridStack->grid( 0 );
572 }
573 
575 {
576  if ( mOverviewStack->size() < 1 )
577  {
578  QgsLayoutItemMapOverview *overview = new QgsLayoutItemMapOverview( tr( "Overview %1" ).arg( 1 ), this );
579  mOverviewStack->addOverview( overview );
580  }
581  return mOverviewStack->overview( 0 );
582 }
583 
585 {
586 }
587 
588 bool QgsLayoutItemMap::writePropertiesToElement( QDomElement &mapElem, QDomDocument &doc, const QgsReadWriteContext &context ) const
589 {
590  if ( mKeepLayerSet )
591  {
592  mapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "true" ) );
593  }
594  else
595  {
596  mapElem.setAttribute( QStringLiteral( "keepLayerSet" ), QStringLiteral( "false" ) );
597  }
598 
599  if ( mDrawAnnotations )
600  {
601  mapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
602  }
603  else
604  {
605  mapElem.setAttribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "false" ) );
606  }
607 
608  //extent
609  QDomElement extentElem = doc.createElement( QStringLiteral( "Extent" ) );
610  extentElem.setAttribute( QStringLiteral( "xmin" ), qgsDoubleToString( mExtent.xMinimum() ) );
611  extentElem.setAttribute( QStringLiteral( "xmax" ), qgsDoubleToString( mExtent.xMaximum() ) );
612  extentElem.setAttribute( QStringLiteral( "ymin" ), qgsDoubleToString( mExtent.yMinimum() ) );
613  extentElem.setAttribute( QStringLiteral( "ymax" ), qgsDoubleToString( mExtent.yMaximum() ) );
614  mapElem.appendChild( extentElem );
615 
616  if ( mCrs.isValid() )
617  {
618  QDomElement crsElem = doc.createElement( QStringLiteral( "crs" ) );
619  mCrs.writeXml( crsElem, doc );
620  mapElem.appendChild( crsElem );
621  }
622 
623  // follow map theme
624  mapElem.setAttribute( QStringLiteral( "followPreset" ), mFollowVisibilityPreset ? QStringLiteral( "true" ) : QStringLiteral( "false" ) );
625  mapElem.setAttribute( QStringLiteral( "followPresetName" ), mFollowVisibilityPresetName );
626 
627  //map rotation
628  mapElem.setAttribute( QStringLiteral( "mapRotation" ), QString::number( mMapRotation ) );
629 
630  //layer set
631  QDomElement layerSetElem = doc.createElement( QStringLiteral( "LayerSet" ) );
632  for ( const QgsMapLayerRef &layerRef : mLayers )
633  {
634  if ( !layerRef )
635  continue;
636  QDomElement layerElem = doc.createElement( QStringLiteral( "Layer" ) );
637  QDomText layerIdText = doc.createTextNode( layerRef.layerId );
638  layerElem.appendChild( layerIdText );
639 
640  layerElem.setAttribute( QStringLiteral( "name" ), layerRef.name );
641  layerElem.setAttribute( QStringLiteral( "source" ), layerRef.source );
642  layerElem.setAttribute( QStringLiteral( "provider" ), layerRef.provider );
643 
644  layerSetElem.appendChild( layerElem );
645  }
646  mapElem.appendChild( layerSetElem );
647 
648  // override styles
649  if ( mKeepLayerStyles )
650  {
651  QDomElement stylesElem = doc.createElement( QStringLiteral( "LayerStyles" ) );
652  for ( auto styleIt = mLayerStyleOverrides.constBegin(); styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
653  {
654  QDomElement styleElem = doc.createElement( QStringLiteral( "LayerStyle" ) );
655 
656  QgsMapLayerRef ref( styleIt.key() );
657  ref.resolve( mLayout->project() );
658 
659  styleElem.setAttribute( QStringLiteral( "layerid" ), ref.layerId );
660  styleElem.setAttribute( QStringLiteral( "name" ), ref.name );
661  styleElem.setAttribute( QStringLiteral( "source" ), ref.source );
662  styleElem.setAttribute( QStringLiteral( "provider" ), ref.provider );
663 
664  QgsMapLayerStyle style( styleIt.value() );
665  style.writeXml( styleElem );
666  stylesElem.appendChild( styleElem );
667  }
668  mapElem.appendChild( stylesElem );
669  }
670 
671  //grids
672  mGridStack->writeXml( mapElem, doc, context );
673 
674  //overviews
675  mOverviewStack->writeXml( mapElem, doc, context );
676 
677  //atlas
678  QDomElement atlasElem = doc.createElement( QStringLiteral( "AtlasMap" ) );
679  atlasElem.setAttribute( QStringLiteral( "atlasDriven" ), mAtlasDriven );
680  atlasElem.setAttribute( QStringLiteral( "scalingMode" ), mAtlasScalingMode );
681  atlasElem.setAttribute( QStringLiteral( "margin" ), qgsDoubleToString( mAtlasMargin ) );
682  mapElem.appendChild( atlasElem );
683 
684  mapElem.setAttribute( QStringLiteral( "labelMargin" ), mLabelMargin.encodeMeasurement() );
685  mapElem.setAttribute( QStringLiteral( "mapFlags" ), static_cast< int>( mMapFlags ) );
686 
687  QDomElement labelBlockingItemsElem = doc.createElement( QStringLiteral( "labelBlockingItems" ) );
688  for ( const auto &item : std::as_const( mBlockingLabelItems ) )
689  {
690  if ( !item )
691  continue;
692 
693  QDomElement blockingItemElem = doc.createElement( QStringLiteral( "item" ) );
694  blockingItemElem.setAttribute( QStringLiteral( "uuid" ), item->uuid() );
695  labelBlockingItemsElem.appendChild( blockingItemElem );
696  }
697  mapElem.appendChild( labelBlockingItemsElem );
698 
699  //temporal settings
700  mapElem.setAttribute( QStringLiteral( "isTemporal" ), isTemporal() ? 1 : 0 );
701  if ( isTemporal() )
702  {
703  mapElem.setAttribute( QStringLiteral( "temporalRangeBegin" ), temporalRange().begin().toString( Qt::ISODate ) );
704  mapElem.setAttribute( QStringLiteral( "temporalRangeEnd" ), temporalRange().end().toString( Qt::ISODate ) );
705  }
706 
707  mAtlasClippingSettings->writeXml( mapElem, doc, context );
708  mItemClippingSettings->writeXml( mapElem, doc, context );
709 
710  return true;
711 }
712 
713 bool QgsLayoutItemMap::readPropertiesFromElement( const QDomElement &itemElem, const QDomDocument &doc, const QgsReadWriteContext &context )
714 {
715  mUpdatesEnabled = false;
716 
717  //extent
718  QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral( "Extent" ) );
719  if ( !extentNodeList.isEmpty() )
720  {
721  QDomElement extentElem = extentNodeList.at( 0 ).toElement();
722  double xmin, xmax, ymin, ymax;
723  xmin = extentElem.attribute( QStringLiteral( "xmin" ) ).toDouble();
724  xmax = extentElem.attribute( QStringLiteral( "xmax" ) ).toDouble();
725  ymin = extentElem.attribute( QStringLiteral( "ymin" ) ).toDouble();
726  ymax = extentElem.attribute( QStringLiteral( "ymax" ) ).toDouble();
727  setExtent( QgsRectangle( xmin, ymin, xmax, ymax ) );
728  }
729 
730  QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral( "crs" ) );
732  if ( !crsNodeList.isEmpty() )
733  {
734  QDomElement crsElem = crsNodeList.at( 0 ).toElement();
735  crs.readXml( crsElem );
736  }
737  setCrs( crs );
738 
739  //map rotation
740  mMapRotation = itemElem.attribute( QStringLiteral( "mapRotation" ), QStringLiteral( "0" ) ).toDouble();
741  mEvaluatedMapRotation = mMapRotation;
742 
743  // follow map theme
744  mFollowVisibilityPreset = itemElem.attribute( QStringLiteral( "followPreset" ) ).compare( QLatin1String( "true" ) ) == 0;
745  mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral( "followPresetName" ) );
746 
747  //mKeepLayerSet flag
748  QString keepLayerSetFlag = itemElem.attribute( QStringLiteral( "keepLayerSet" ) );
749  if ( keepLayerSetFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
750  {
751  mKeepLayerSet = true;
752  }
753  else
754  {
755  mKeepLayerSet = false;
756  }
757 
758  QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral( "drawCanvasItems" ), QStringLiteral( "true" ) );
759  if ( drawCanvasItemsFlag.compare( QLatin1String( "true" ), Qt::CaseInsensitive ) == 0 )
760  {
761  mDrawAnnotations = true;
762  }
763  else
764  {
765  mDrawAnnotations = false;
766  }
767 
768  mLayerStyleOverrides.clear();
769 
770  //mLayers
771  mLayers.clear();
772  QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerSet" ) );
773  if ( !layerSetNodeList.isEmpty() )
774  {
775  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
776  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral( "Layer" ) );
777  mLayers.reserve( layerIdNodeList.size() );
778  for ( int i = 0; i < layerIdNodeList.size(); ++i )
779  {
780  QDomElement layerElem = layerIdNodeList.at( i ).toElement();
781  QString layerId = layerElem.text();
782  QString layerName = layerElem.attribute( QStringLiteral( "name" ) );
783  QString layerSource = layerElem.attribute( QStringLiteral( "source" ) );
784  QString layerProvider = layerElem.attribute( QStringLiteral( "provider" ) );
785 
786  QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
787  ref.resolveWeakly( mLayout->project() );
788  mLayers << ref;
789  }
790  }
791 
792  // override styles
793  QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral( "LayerStyles" ) );
794  mKeepLayerStyles = !layerStylesNodeList.isEmpty();
795  if ( mKeepLayerStyles )
796  {
797  QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
798  QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral( "LayerStyle" ) );
799  for ( int i = 0; i < layerStyleNodeList.size(); ++i )
800  {
801  const QDomElement &layerStyleElement = layerStyleNodeList.at( i ).toElement();
802  QString layerId = layerStyleElement.attribute( QStringLiteral( "layerid" ) );
803  QString layerName = layerStyleElement.attribute( QStringLiteral( "name" ) );
804  QString layerSource = layerStyleElement.attribute( QStringLiteral( "source" ) );
805  QString layerProvider = layerStyleElement.attribute( QStringLiteral( "provider" ) );
806  QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
807  ref.resolveWeakly( mLayout->project() );
808 
809  QgsMapLayerStyle style;
810  style.readXml( layerStyleElement );
811  mLayerStyleOverrides.insert( ref.layerId, style.xmlData() );
812  }
813  }
814 
815  mDrawing = false;
816  mNumCachedLayers = 0;
817  mCacheInvalidated = true;
818 
819  //overviews
820  mOverviewStack->readXml( itemElem, doc, context );
821 
822  //grids
823  mGridStack->readXml( itemElem, doc, context );
824 
825  //atlas
826  QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral( "AtlasMap" ) );
827  if ( !atlasNodeList.isEmpty() )
828  {
829  QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
830  mAtlasDriven = ( atlasElem.attribute( QStringLiteral( "atlasDriven" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) );
831  if ( atlasElem.hasAttribute( QStringLiteral( "fixedScale" ) ) ) // deprecated XML
832  {
833  mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral( "fixedScale" ), QStringLiteral( "0" ) ) != QLatin1String( "0" ) ) ? Fixed : Auto;
834  }
835  else if ( atlasElem.hasAttribute( QStringLiteral( "scalingMode" ) ) )
836  {
837  mAtlasScalingMode = static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral( "scalingMode" ) ).toInt() );
838  }
839  mAtlasMargin = atlasElem.attribute( QStringLiteral( "margin" ), QStringLiteral( "0.1" ) ).toDouble();
840  }
841 
842  setLabelMargin( QgsLayoutMeasurement::decodeMeasurement( itemElem.attribute( QStringLiteral( "labelMargin" ), QStringLiteral( "0" ) ) ) );
843 
844  mMapFlags = static_cast< MapItemFlags>( itemElem.attribute( QStringLiteral( "mapFlags" ), nullptr ).toInt() );
845 
846  // label blocking items
847  mBlockingLabelItems.clear();
848  mBlockingLabelItemUuids.clear();
849  QDomNodeList labelBlockingNodeList = itemElem.elementsByTagName( QStringLiteral( "labelBlockingItems" ) );
850  if ( !labelBlockingNodeList.isEmpty() )
851  {
852  QDomElement blockingItems = labelBlockingNodeList.at( 0 ).toElement();
853  QDomNodeList labelBlockingNodeList = blockingItems.childNodes();
854  for ( int i = 0; i < labelBlockingNodeList.size(); ++i )
855  {
856  const QDomElement &itemBlockingElement = labelBlockingNodeList.at( i ).toElement();
857  const QString itemUuid = itemBlockingElement.attribute( QStringLiteral( "uuid" ) );
858  mBlockingLabelItemUuids << itemUuid;
859  }
860  }
861 
862  mAtlasClippingSettings->readXml( itemElem, doc, context );
863  mItemClippingSettings->readXml( itemElem, doc, context );
864 
866 
867  //temporal settings
868  setIsTemporal( itemElem.attribute( QStringLiteral( "isTemporal" ) ).toInt() );
869  if ( isTemporal() )
870  {
871  const QDateTime begin = QDateTime::fromString( itemElem.attribute( QStringLiteral( "temporalRangeBegin" ) ), Qt::ISODate );
872  const QDateTime end = QDateTime::fromString( itemElem.attribute( QStringLiteral( "temporalRangeEnd" ) ), Qt::ISODate );
873  setTemporalRange( QgsDateTimeRange( begin, end, true, begin == end ) );
874  }
875 
876  mUpdatesEnabled = true;
877  return true;
878 }
879 
880 QPainterPath QgsLayoutItemMap::framePath() const
881 {
882  if ( mItemClippingSettings->isActive() )
883  {
884  const QgsGeometry g = mItemClippingSettings->clipPathInMapItemCoordinates();
885  if ( !g.isNull() )
886  return g.constGet()->asQPainterPath();
887  }
888  return QgsLayoutItem::framePath();
889 }
890 
891 void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *style, QWidget * )
892 {
893  if ( !mLayout || !painter || !painter->device() || !mUpdatesEnabled )
894  {
895  return;
896  }
897  if ( !shouldDrawItem() )
898  {
899  return;
900  }
901 
902  QRectF thisPaintRect = rect();
903  if ( qgsDoubleNear( thisPaintRect.width(), 0.0 ) || qgsDoubleNear( thisPaintRect.height(), 0 ) )
904  return;
905 
906  //TODO - try to reduce the amount of duplicate code here!
907 
908  if ( mLayout->renderContext().isPreviewRender() )
909  {
910  QgsScopedQPainterState painterState( painter );
911  painter->setClipRect( thisPaintRect );
912  if ( !mCacheFinalImage || mCacheFinalImage->isNull() )
913  {
914  // No initial render available - so draw some preview text alerting user
915  painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
916  painter->drawRect( thisPaintRect );
917  painter->setBrush( Qt::NoBrush );
918  QFont messageFont;
919  messageFont.setPointSize( 12 );
920  painter->setFont( messageFont );
921  painter->setPen( QColor( 255, 255, 255, 255 ) );
922  painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr( "Rendering map" ) );
923  if ( mPainterJob && mCacheInvalidated && !mDrawingPreview )
924  {
925  // current job was invalidated - start a new one
926  mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter );
927  mBackgroundUpdateTimer->start( 1 );
928  }
929  else if ( !mPainterJob && !mDrawingPreview )
930  {
931  // this is the map's very first paint - trigger a cache update
932  mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter );
933  mBackgroundUpdateTimer->start( 1 );
934  }
935  }
936  else
937  {
938  if ( mCacheInvalidated && !mDrawingPreview )
939  {
940  // cache was invalidated - trigger a background update
941  mPreviewScaleFactor = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter );
942  mBackgroundUpdateTimer->start( 1 );
943  }
944 
945  //Background color is already included in cached image, so no need to draw
946 
947  double imagePixelWidth = mCacheFinalImage->width(); //how many pixels of the image are for the map extent?
948  double scale = rect().width() / imagePixelWidth;
949 
950  QgsScopedQPainterState rotatedPainterState( painter );
951 
952  painter->translate( mLastRenderedImageOffsetX + mXOffset, mLastRenderedImageOffsetY + mYOffset );
953  painter->scale( scale, scale );
954  painter->drawImage( 0, 0, *mCacheFinalImage );
955 
956  //restore rotation
957  }
958 
959  painter->setClipRect( thisPaintRect, Qt::NoClip );
960 
961  mOverviewStack->drawItems( painter, false );
962  mGridStack->drawItems( painter );
963  drawAnnotations( painter );
964  drawMapFrame( painter );
965  }
966  else
967  {
968  if ( mDrawing )
969  return;
970 
971  mDrawing = true;
972  QPaintDevice *paintDevice = painter->device();
973  if ( !paintDevice )
974  return;
975 
976  QgsRectangle cExtent = extent();
977  QSizeF size( cExtent.width() * mapUnitsToLayoutUnits(), cExtent.height() * mapUnitsToLayoutUnits() );
978 
979 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
980  if ( mLayout && mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagLosslessImageRendering )
981  painter->setRenderHint( QPainter::LosslessImageRendering, true );
982 #endif
983 
984  if ( containsAdvancedEffects() && ( !mLayout || !( mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagForceVectorOutput ) ) )
985  {
986  // rasterize
987  double destinationDpi = QgsLayoutUtils::scaleFactorFromItemStyle( style, painter ) * 25.4;
988  double layoutUnitsInInches = mLayout ? mLayout->convertFromLayoutUnits( 1, QgsUnitTypes::LayoutInches ).length() : 1;
989  int widthInPixels = static_cast< int >( std::round( boundingRect().width() * layoutUnitsInInches * destinationDpi ) );
990  int heightInPixels = static_cast< int >( std::round( boundingRect().height() * layoutUnitsInInches * destinationDpi ) );
991  QImage image = QImage( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
992 
993  image.fill( Qt::transparent );
994  image.setDotsPerMeterX( static_cast< int >( std::round( 1000 * destinationDpi / 25.4 ) ) );
995  image.setDotsPerMeterY( static_cast< int >( std::round( 1000 * destinationDpi / 25.4 ) ) );
996  double dotsPerMM = destinationDpi / 25.4;
997  QPainter p( &image );
998 
999  QPointF tl = -boundingRect().topLeft();
1000  QRect imagePaintRect( static_cast< int >( std::round( tl.x() * dotsPerMM ) ),
1001  static_cast< int >( std::round( tl.y() * dotsPerMM ) ),
1002  static_cast< int >( std::round( thisPaintRect.width() * dotsPerMM ) ),
1003  static_cast< int >( std::round( thisPaintRect.height() * dotsPerMM ) ) );
1004  p.setClipRect( imagePaintRect );
1005 
1006  p.translate( imagePaintRect.topLeft() );
1007 
1008  // Fill with background color - must be drawn onto the flattened image
1009  // so that layers with opacity or blend modes can correctly interact with it
1010  if ( shouldDrawPart( Background ) )
1011  {
1012  p.scale( dotsPerMM, dotsPerMM );
1013  drawMapBackground( &p );
1014  p.scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
1015  }
1016 
1017  drawMap( &p, cExtent, imagePaintRect.size(), image.logicalDpiX() );
1018 
1019  // important - all other items, overviews, grids etc must be rendered to the
1020  // flattened image, in case these have blend modes must need to interact
1021  // with the map
1022  p.scale( dotsPerMM, dotsPerMM );
1023 
1024  if ( shouldDrawPart( OverviewMapExtent ) )
1025  {
1026  mOverviewStack->drawItems( &p, false );
1027  }
1028  if ( shouldDrawPart( Grid ) )
1029  {
1030  mGridStack->drawItems( &p );
1031  }
1032  drawAnnotations( &p );
1033 
1034  QgsScopedQPainterState painterState( painter );
1035  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1036  painter->drawImage( QPointF( -tl.x()* dotsPerMM, -tl.y() * dotsPerMM ), image );
1037  painter->scale( dotsPerMM, dotsPerMM );
1038  }
1039  else
1040  {
1041  // Fill with background color
1042  if ( shouldDrawPart( Background ) )
1043  {
1044  drawMapBackground( painter );
1045  }
1046 
1047  QgsScopedQPainterState painterState( painter );
1048  painter->setClipRect( thisPaintRect );
1049 
1050  if ( shouldDrawPart( Layer ) && !qgsDoubleNear( size.width(), 0.0 ) && !qgsDoubleNear( size.height(), 0.0 ) )
1051  {
1052  QgsScopedQPainterState stagedPainterState( painter );
1053  painter->translate( mXOffset, mYOffset );
1054 
1055  double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
1056  size *= dotsPerMM; // output size will be in dots (pixels)
1057  painter->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
1058 
1059  if ( mCurrentExportPart != NotLayered )
1060  {
1061  if ( !mStagedRendererJob )
1062  {
1063  createStagedRenderJob( cExtent, size, paintDevice->logicalDpiX() );
1064  }
1065 
1066  mStagedRendererJob->renderCurrentPart( painter );
1067  }
1068  else
1069  {
1070  drawMap( painter, cExtent, size, paintDevice->logicalDpiX() );
1071  }
1072  }
1073 
1074  painter->setClipRect( thisPaintRect, Qt::NoClip );
1075 
1076  if ( shouldDrawPart( OverviewMapExtent ) )
1077  {
1078  mOverviewStack->drawItems( painter, false );
1079  }
1080  if ( shouldDrawPart( Grid ) )
1081  {
1082  mGridStack->drawItems( painter );
1083  }
1084  drawAnnotations( painter );
1085  }
1086 
1087  if ( shouldDrawPart( Frame ) )
1088  {
1089  drawMapFrame( painter );
1090  }
1091 
1092  mDrawing = false;
1093  }
1094 }
1095 
1097 {
1098  const int layerCount = layersToRender().length();
1099  return ( hasBackground() ? 1 : 0 )
1100  + ( layerCount + ( layerCount ? 1 : 0 ) ) // +1 for label layer, if labels present
1101  + ( mGridStack->hasEnabledItems() ? 1 : 0 )
1102  + ( mOverviewStack->hasEnabledItems() ? 1 : 0 )
1103  + ( frameEnabled() ? 1 : 0 );
1104 }
1105 
1107 {
1108  mCurrentExportPart = Start;
1109  // only follow export themes if the map isn't set to follow a fixed theme
1110  mExportThemes = !mFollowVisibilityPreset ? mLayout->renderContext().exportThemes() : QStringList();
1111  mExportThemeIt = mExportThemes.begin();
1112 }
1113 
1115 {
1116  mCurrentExportPart = NotLayered;
1117  mExportThemes.clear();
1118  mExportThemeIt = mExportThemes.begin();
1119 }
1120 
1122 {
1123  switch ( mCurrentExportPart )
1124  {
1125  case Start:
1126  if ( hasBackground() )
1127  {
1128  mCurrentExportPart = Background;
1129  return true;
1130  }
1131  FALLTHROUGH
1132 
1133  case Background:
1134  mCurrentExportPart = Layer;
1135  return true;
1136 
1137  case Layer:
1138  if ( mStagedRendererJob )
1139  {
1140  if ( mStagedRendererJob->nextPart() )
1141  return true;
1142  else
1143  {
1144  mExportLabelingResults.reset( mStagedRendererJob->takeLabelingResults() );
1145  mStagedRendererJob.reset(); // no more map layer parts
1146  }
1147  }
1148 
1149  if ( mExportThemeIt != mExportThemes.end() && ++mExportThemeIt != mExportThemes.end() )
1150  {
1151  // move to next theme and continue exporting map layers
1152  return true;
1153  }
1154 
1155  if ( mGridStack->hasEnabledItems() )
1156  {
1157  mCurrentExportPart = Grid;
1158  return true;
1159  }
1160  FALLTHROUGH
1161 
1162  case Grid:
1163  for ( int i = 0; i < mOverviewStack->size(); ++i )
1164  {
1165  QgsLayoutItemMapItem *item = mOverviewStack->item( i );
1167  {
1168  mCurrentExportPart = OverviewMapExtent;
1169  return true;
1170  }
1171  }
1172  FALLTHROUGH
1173 
1174  case OverviewMapExtent:
1175  if ( frameEnabled() )
1176  {
1177  mCurrentExportPart = Frame;
1178  return true;
1179  }
1180 
1181  FALLTHROUGH
1182 
1183  case Frame:
1184  if ( isSelected() && !mLayout->renderContext().isPreviewRender() )
1185  {
1186  mCurrentExportPart = SelectionBoxes;
1187  return true;
1188  }
1189  FALLTHROUGH
1190 
1191  case SelectionBoxes:
1192  mCurrentExportPart = End;
1193  return false;
1194 
1195  case End:
1196  return false;
1197 
1198  case NotLayered:
1199  return false;
1200  }
1201  return false;
1202 }
1203 
1205 {
1206  return ItemContainsSubLayers;
1207 }
1208 
1210 {
1211  ExportLayerDetail detail;
1212 
1213  switch ( mCurrentExportPart )
1214  {
1215  case Start:
1216  break;
1217 
1218  case Background:
1219  detail.name = tr( "%1: Background" ).arg( displayName() );
1220  return detail;
1221 
1222  case Layer:
1223  if ( !mExportThemes.empty() && mExportThemeIt != mExportThemes.end() )
1224  detail.mapTheme = *mExportThemeIt;
1225 
1226  if ( mStagedRendererJob )
1227  {
1228  switch ( mStagedRendererJob->currentStage() )
1229  {
1231  {
1232  detail.mapLayerId = mStagedRendererJob->currentLayerId();
1233  detail.compositionMode = mStagedRendererJob->currentLayerCompositionMode();
1234  detail.opacity = mStagedRendererJob->currentLayerOpacity();
1235  if ( const QgsMapLayer *layer = mLayout->project()->mapLayer( detail.mapLayerId ) )
1236  {
1237  if ( !detail.mapTheme.isEmpty() )
1238  detail.name = QStringLiteral( "%1 (%2): %3" ).arg( displayName(), detail.mapTheme, layer->name() );
1239  else
1240  detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), layer->name() );
1241  }
1242  else if ( mLayout->project()->mainAnnotationLayer()->id() == detail.mapLayerId )
1243  {
1244  // master annotation layer
1245  if ( !detail.mapTheme.isEmpty() )
1246  detail.name = QStringLiteral( "%1 (%2): %3" ).arg( displayName(), detail.mapTheme, tr( "Annotations" ) );
1247  else
1248  detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), tr( "Annotations" ) );
1249  }
1250  else
1251  {
1252  // might be an item based layer
1253  const QList<QgsLayoutItemMapOverview *> res = mOverviewStack->asList();
1254  for ( QgsLayoutItemMapOverview *item : res )
1255  {
1256  if ( !item || !item->enabled() || item->stackingPosition() == QgsLayoutItemMapItem::StackAboveMapLabels )
1257  continue;
1258 
1259  if ( item->mapLayer() && detail.mapLayerId == item->mapLayer()->id() )
1260  {
1261  if ( !detail.mapTheme.isEmpty() )
1262  detail.name = QStringLiteral( "%1 (%2): %3" ).arg( displayName(), detail.mapTheme, item->mapLayer()->name() );
1263  else
1264  detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), item->mapLayer()->name() );
1265  break;
1266  }
1267  }
1268  }
1269  return detail;
1270  }
1271 
1273  detail.mapLayerId = mStagedRendererJob->currentLayerId();
1274  if ( const QgsMapLayer *layer = mLayout->project()->mapLayer( detail.mapLayerId ) )
1275  {
1276  if ( !detail.mapTheme.isEmpty() )
1277  detail.name = QStringLiteral( "%1 (%2): %3 (Labels)" ).arg( displayName(), detail.mapTheme, layer->name() );
1278  else
1279  detail.name = tr( "%1: %2 (Labels)" ).arg( displayName(), layer->name() );
1280  }
1281  else
1282  {
1283  if ( !detail.mapTheme.isEmpty() )
1284  detail.name = tr( "%1 (%2): Labels" ).arg( displayName(), detail.mapTheme );
1285  else
1286  detail.name = tr( "%1: Labels" ).arg( displayName() );
1287  }
1288  return detail;
1289 
1291  break;
1292  }
1293  }
1294  else
1295  {
1296  // we must be on the first layer, not having had a chance to create the render job yet
1297  const QList< QgsMapLayer * > layers = layersToRender();
1298  if ( !layers.isEmpty() )
1299  {
1300  const QgsMapLayer *layer = layers.constLast();
1301  if ( !detail.mapTheme.isEmpty() )
1302  detail.name = QStringLiteral( "%1 (%2): %3" ).arg( displayName(), detail.mapTheme, layer->name() );
1303  else
1304  detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), layer->name() );
1305  detail.mapLayerId = layer->id();
1306  }
1307  }
1308  break;
1309 
1310  case Grid:
1311  detail.name = tr( "%1: Grids" ).arg( displayName() );
1312  return detail;
1313 
1314  case OverviewMapExtent:
1315  detail.name = tr( "%1: Overviews" ).arg( displayName() );
1316  return detail;
1317 
1318  case Frame:
1319  detail.name = tr( "%1: Frame" ).arg( displayName() );
1320  return detail;
1321 
1322  case SelectionBoxes:
1323  case End:
1324  case NotLayered:
1325  break;
1326  }
1327 
1328  return detail;
1329 }
1330 
1332 {
1335 }
1336 
1337 void QgsLayoutItemMap::drawMap( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi )
1338 {
1339  if ( !painter )
1340  {
1341  return;
1342  }
1343  if ( qgsDoubleNear( size.width(), 0.0 ) || qgsDoubleNear( size.height(), 0.0 ) )
1344  {
1345  //don't attempt to draw if size is invalid
1346  return;
1347  }
1348 
1349  // render
1350  QgsMapSettings ms( mapSettings( extent, size, dpi, true ) );
1351  if ( shouldDrawPart( OverviewMapExtent ) )
1352  {
1353  ms.setLayers( mOverviewStack->modifyMapLayerList( ms.layers() ) );
1354  }
1355 
1356  QgsMapRendererCustomPainterJob job( ms, painter );
1357 #ifdef HAVE_SERVER_PYTHON_PLUGINS
1358  job.setFeatureFilterProvider( mLayout->renderContext().featureFilterProvider() );
1359 #endif
1360 
1361  // Render the map in this thread. This is done because of problems
1362  // with printing to printer on Windows (printing to PDF is fine though).
1363  // Raster images were not displayed - see #10599
1364  job.renderSynchronously();
1365 
1366  mExportLabelingResults.reset( job.takeLabelingResults() );
1367 
1368  mRenderingErrors = job.errors();
1369 }
1370 
1371 void QgsLayoutItemMap::recreateCachedImageInBackground()
1372 {
1373  if ( mPainterJob )
1374  {
1375  disconnect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsLayoutItemMap::painterJobFinished );
1376  QgsMapRendererCustomPainterJob *oldJob = mPainterJob.release();
1377  QPainter *oldPainter = mPainter.release();
1378  QImage *oldImage = mCacheRenderingImage.release();
1379  connect( oldJob, &QgsMapRendererCustomPainterJob::finished, this, [oldPainter, oldJob, oldImage]
1380  {
1381  oldJob->deleteLater();
1382  delete oldPainter;
1383  delete oldImage;
1384  } );
1385  oldJob->cancelWithoutBlocking();
1386  }
1387  else
1388  {
1389  mCacheRenderingImage.reset( nullptr );
1390  emit backgroundTaskCountChanged( 1 );
1391  }
1392 
1393  Q_ASSERT( !mPainterJob );
1394  Q_ASSERT( !mPainter );
1395  Q_ASSERT( !mCacheRenderingImage );
1396 
1397  QgsRectangle ext = extent();
1398  double widthLayoutUnits = ext.width() * mapUnitsToLayoutUnits();
1399  double heightLayoutUnits = ext.height() * mapUnitsToLayoutUnits();
1400 
1401  int w = static_cast< int >( std::round( widthLayoutUnits * mPreviewScaleFactor ) );
1402  int h = static_cast< int >( std::round( heightLayoutUnits * mPreviewScaleFactor ) );
1403 
1404  // limit size of image for better performance
1405  if ( w > 5000 || h > 5000 )
1406  {
1407  if ( w > h )
1408  {
1409  w = 5000;
1410  h = static_cast< int>( std::round( w * heightLayoutUnits / widthLayoutUnits ) );
1411  }
1412  else
1413  {
1414  h = 5000;
1415  w = static_cast< int >( std::round( h * widthLayoutUnits / heightLayoutUnits ) );
1416  }
1417  }
1418 
1419  if ( w <= 0 || h <= 0 )
1420  return;
1421 
1422  mCacheRenderingImage.reset( new QImage( w, h, QImage::Format_ARGB32 ) );
1423 
1424  // set DPI of the image
1425  mCacheRenderingImage->setDotsPerMeterX( static_cast< int >( std::round( 1000 * w / widthLayoutUnits ) ) );
1426  mCacheRenderingImage->setDotsPerMeterY( static_cast< int >( std::round( 1000 * h / heightLayoutUnits ) ) );
1427 
1428  //start with empty fill to avoid artifacts
1429  mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
1430  if ( hasBackground() )
1431  {
1432  //Initially fill image with specified background color. This ensures that layers with blend modes will
1433  //preview correctly
1434  if ( mItemClippingSettings->isActive() )
1435  {
1436  QPainter p( mCacheRenderingImage.get() );
1437  const QPainterPath path = framePath();
1438  p.setPen( Qt::NoPen );
1439  p.setBrush( backgroundColor() );
1440  p.scale( mCacheRenderingImage->width() / widthLayoutUnits, mCacheRenderingImage->height() / heightLayoutUnits );
1441  p.drawPath( path );
1442  p.end();
1443  }
1444  else
1445  {
1446  mCacheRenderingImage->fill( backgroundColor().rgba() );
1447  }
1448  }
1449 
1450  mCacheInvalidated = false;
1451  mPainter.reset( new QPainter( mCacheRenderingImage.get() ) );
1452  QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheRenderingImage->logicalDpiX(), true ) );
1453 
1454  if ( shouldDrawPart( OverviewMapExtent ) )
1455  {
1456  settings.setLayers( mOverviewStack->modifyMapLayerList( settings.layers() ) );
1457  }
1458 
1459  mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) );
1460  connect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsLayoutItemMap::painterJobFinished );
1461  mPainterJob->start();
1462 
1463  // from now on we can accept refresh requests again
1464  // this must be reset only after the job has been started, because
1465  // some providers (yes, it's you WCS and AMS!) during preparation
1466  // do network requests and start an internal event loop, which may
1467  // end up calling refresh() and would schedule another refresh,
1468  // deleting the one we have just started.
1469 
1470  // ^^ that comment was directly copied from a similar fix in QgsMapCanvas. And
1471  // with little surprise, both those providers are still badly behaved and causing
1472  // annoying bugs for us to deal with...
1473  mDrawingPreview = false;
1474 }
1475 
1476 QgsLayoutItemMap::MapItemFlags QgsLayoutItemMap::mapFlags() const
1477 {
1478  return mMapFlags;
1479 }
1480 
1481 void QgsLayoutItemMap::setMapFlags( QgsLayoutItemMap::MapItemFlags mapFlags )
1482 {
1483  mMapFlags = mapFlags;
1484 }
1485 
1486 QgsMapSettings QgsLayoutItemMap::mapSettings( const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings ) const
1487 {
1488  QgsExpressionContext expressionContext = createExpressionContext();
1489  QgsCoordinateReferenceSystem renderCrs = crs();
1490 
1491  QgsMapSettings jobMapSettings;
1492  jobMapSettings.setDestinationCrs( renderCrs );
1493  jobMapSettings.setExtent( extent );
1494  jobMapSettings.setOutputSize( size.toSize() );
1495  jobMapSettings.setOutputDpi( dpi );
1496  if ( layout()->renderContext().isPreviewRender() )
1497  jobMapSettings.setDpiTarget( layout()->renderContext().dpi() );
1498  jobMapSettings.setBackgroundColor( Qt::transparent );
1499  jobMapSettings.setRotation( mEvaluatedMapRotation );
1500  if ( mLayout )
1501  jobMapSettings.setEllipsoid( mLayout->project()->ellipsoid() );
1502 
1503  if ( includeLayerSettings )
1504  {
1505  //set layers to render
1506  QList<QgsMapLayer *> layers = layersToRender( &expressionContext );
1507 
1508  if ( !mLayout->project()->mainAnnotationLayer()->isEmpty() )
1509  {
1510  // render main annotation layer above all other layers
1511  layers.insert( 0, mLayout->project()->mainAnnotationLayer() );
1512  }
1513 
1514  jobMapSettings.setLayers( layers );
1515  jobMapSettings.setLayerStyleOverrides( layerStyleOverridesToRender( expressionContext ) );
1516  }
1517 
1518  if ( !mLayout->renderContext().isPreviewRender() )
1519  {
1520  //if outputting layout, we disable optimisations like layer simplification by default, UNLESS the context specifically tells us to use them
1521  jobMapSettings.setFlag( Qgis::MapSettingsFlag::UseRenderingOptimization, mLayout->renderContext().simplifyMethod().simplifyHints() != QgsVectorSimplifyMethod::NoSimplification );
1522  jobMapSettings.setSimplifyMethod( mLayout->renderContext().simplifyMethod() );
1524  }
1525  else
1526  {
1527  // preview render - always use optimization
1529  // in a preview render we disable vector masking, as that is considerably slower vs raster masking
1530  jobMapSettings.setFlag( Qgis::MapSettingsFlag::ForceRasterMasks, true );
1531  jobMapSettings.setRendererUsage( Qgis::RendererUsage::View );
1532  }
1533 
1534  jobMapSettings.setExpressionContext( expressionContext );
1535 
1536  // layout-specific overrides of flags
1537  jobMapSettings.setFlag( Qgis::MapSettingsFlag::ForceVectorOutput, true ); // force vector output (no caching of marker images etc.)
1541  jobMapSettings.setFlag( Qgis::MapSettingsFlag::DrawEditingInfo, false );
1542  jobMapSettings.setSelectionColor( mLayout->renderContext().selectionColor() );
1546  jobMapSettings.setTransformContext( mLayout->project()->transformContext() );
1547  jobMapSettings.setPathResolver( mLayout->project()->pathResolver() );
1548 
1549  QgsLabelingEngineSettings labelSettings = mLayout->project()->labelingEngineSettings();
1550 
1551  // override project "show partial labels" setting with this map's setting
1555  jobMapSettings.setLabelingEngineSettings( labelSettings );
1556 
1557  // override the default text render format inherited from the labeling engine settings using the layout's render context setting
1558  jobMapSettings.setTextRenderFormat( mLayout->renderContext().textRenderFormat() );
1559 
1560  QgsGeometry labelBoundary;
1561  if ( mEvaluatedLabelMargin.length() > 0 )
1562  {
1563  QPolygonF visiblePoly = jobMapSettings.visiblePolygon();
1564  visiblePoly.append( visiblePoly.at( 0 ) ); //close polygon
1565  const double layoutLabelMargin = mLayout->convertToLayoutUnits( mEvaluatedLabelMargin );
1566  const double layoutLabelMarginInMapUnits = layoutLabelMargin / rect().width() * jobMapSettings.extent().width();
1567  QgsGeometry mapBoundaryGeom = QgsGeometry::fromQPolygonF( visiblePoly );
1568  mapBoundaryGeom = mapBoundaryGeom.buffer( -layoutLabelMarginInMapUnits, 0 );
1569  labelBoundary = mapBoundaryGeom;
1570  }
1571 
1572  if ( !mBlockingLabelItems.isEmpty() )
1573  {
1574  jobMapSettings.setLabelBlockingRegions( createLabelBlockingRegions( jobMapSettings ) );
1575  }
1576 
1577  for ( QgsRenderedFeatureHandlerInterface *handler : std::as_const( mRenderedFeatureHandlers ) )
1578  {
1579  jobMapSettings.addRenderedFeatureHandler( handler );
1580  }
1581 
1582  if ( isTemporal() )
1583  jobMapSettings.setTemporalRange( temporalRange() );
1584 
1585  if ( mAtlasClippingSettings->enabled() && mLayout->reportContext().feature().isValid() )
1586  {
1587  QgsGeometry clipGeom( mLayout->reportContext().currentGeometry( jobMapSettings.destinationCrs() ) );
1588  QgsMapClippingRegion region( clipGeom );
1589  region.setFeatureClip( mAtlasClippingSettings->featureClippingType() );
1590  region.setRestrictedLayers( mAtlasClippingSettings->layersToClip() );
1591  region.setRestrictToLayers( mAtlasClippingSettings->restrictToLayers() );
1592  jobMapSettings.addClippingRegion( region );
1593 
1594  if ( mAtlasClippingSettings->forceLabelsInsideFeature() )
1595  {
1596  if ( !labelBoundary.isEmpty() )
1597  {
1598  labelBoundary = clipGeom.intersection( labelBoundary );
1599  }
1600  else
1601  {
1602  labelBoundary = clipGeom;
1603  }
1604  }
1605  }
1606 
1607  if ( mItemClippingSettings->isActive() )
1608  {
1609  const QgsGeometry clipGeom = mItemClippingSettings->clippedMapExtent();
1610  if ( !clipGeom.isEmpty() )
1611  {
1612  jobMapSettings.addClippingRegion( mItemClippingSettings->toMapClippingRegion() );
1613 
1614  if ( mItemClippingSettings->forceLabelsInsideClipPath() )
1615  {
1616  const double layoutLabelMargin = mLayout->convertToLayoutUnits( mEvaluatedLabelMargin );
1617  const double layoutLabelMarginInMapUnits = layoutLabelMargin / rect().width() * jobMapSettings.extent().width();
1618  QgsGeometry mapBoundaryGeom = clipGeom;
1619  mapBoundaryGeom = mapBoundaryGeom.buffer( -layoutLabelMarginInMapUnits, 0 );
1620  if ( !labelBoundary.isEmpty() )
1621  {
1622  labelBoundary = mapBoundaryGeom.intersection( labelBoundary );
1623  }
1624  else
1625  {
1626  labelBoundary = mapBoundaryGeom;
1627  }
1628  }
1629  }
1630  }
1631 
1632  if ( !labelBoundary.isNull() )
1633  jobMapSettings.setLabelBoundaryGeometry( labelBoundary );
1634 
1635  return jobMapSettings;
1636 }
1637 
1639 {
1640  assignFreeId();
1641 
1642  mBlockingLabelItems.clear();
1643  for ( const QString &uuid : std::as_const( mBlockingLabelItemUuids ) )
1644  {
1645  QgsLayoutItem *item = mLayout->itemByUuid( uuid, true );
1646  if ( item )
1647  {
1648  addLabelBlockingItem( item );
1649  }
1650  }
1651 
1652  mOverviewStack->finalizeRestoreFromXml();
1653  mGridStack->finalizeRestoreFromXml();
1654  mItemClippingSettings->finalizeRestoreFromXml();
1655 }
1656 
1657 void QgsLayoutItemMap::setMoveContentPreviewOffset( double xOffset, double yOffset )
1658 {
1659  mXOffset = xOffset;
1660  mYOffset = yOffset;
1661 }
1662 
1664 {
1665  return mCurrentRectangle;
1666 }
1667 
1669 {
1671 
1672  //Can't utilize QgsExpressionContextUtils::mapSettingsScope as we don't always
1673  //have a QgsMapSettings object available when the context is required, so we manually
1674  //add the same variables here
1675  QgsExpressionContextScope *scope = new QgsExpressionContextScope( tr( "Map Settings" ) );
1676 
1677  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_id" ), id(), true ) );
1678  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_rotation" ), mMapRotation, true ) );
1679  const double mapScale = scale();
1680  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_scale" ), mapScale, true ) );
1681 
1682  scope->setVariable( QStringLiteral( "zoom_level" ), QgsVectorTileUtils::scaleToZoomLevel( mapScale, 0, 99999 ), true );
1683  scope->setVariable( QStringLiteral( "vector_tile_zoom" ), QgsVectorTileUtils::scaleToZoom( mapScale ), true );
1684 
1685  QgsRectangle currentExtent( extent() );
1686  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent" ), QVariant::fromValue( QgsGeometry::fromRect( currentExtent ) ), true ) );
1687  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_width" ), currentExtent.width(), true ) );
1688  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_height" ), currentExtent.height(), true ) );
1689  QgsGeometry centerPoint = QgsGeometry::fromPointXY( currentExtent.center() );
1690  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_extent_center" ), QVariant::fromValue( centerPoint ), true ) );
1691 
1692  QgsCoordinateReferenceSystem mapCrs = crs();
1693  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs" ), mapCrs.authid(), true ) );
1694  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_definition" ), mapCrs.toProj(), true ) );
1695  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_description" ), mapCrs.description(), true ) );
1696  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_units" ), QgsUnitTypes::toString( mapCrs.mapUnits() ), true ) );
1697  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_acronym" ), mapCrs.projectionAcronym(), true ) );
1698  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_projection" ), mapCrs.operation().description(), true ) );
1699  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_ellipsoid" ), mapCrs.ellipsoidAcronym(), true ) );
1700  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_proj4" ), mapCrs.toProj(), true ) );
1701  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_crs_wkt" ), mapCrs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ), true ) );
1702 
1703  QVariantList layersIds;
1704  QVariantList layers;
1705  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
1706  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );
1707 
1708  context.appendScope( scope );
1709 
1710  // The scope map_layer_ids and map_layers variables have been added to the context, only now we can
1711  // call layersToRender (just in case layersToRender relies on evaluating an expression which uses
1712  // other variables contained within the map settings scope
1713  const QList<QgsMapLayer *> layersInMap = layersToRender( &context );
1714 
1715  layersIds.reserve( layersInMap.count() );
1716  layers.reserve( layersInMap.count() );
1717  for ( QgsMapLayer *layer : layersInMap )
1718  {
1719  layersIds << layer->id();
1720  layers << QVariant::fromValue<QgsWeakMapLayerPointer>( QgsWeakMapLayerPointer( layer ) );
1721  }
1722  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layer_ids" ), layersIds, true ) );
1723  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_layers" ), layers, true ) );
1724 
1725  scope->addFunction( QStringLiteral( "is_layer_visible" ), new QgsExpressionContextUtils::GetLayerVisibility( layersInMap, scale() ) );
1726 
1727  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_start_time" ), isTemporal() ? temporalRange().begin() : QVariant(), true ) );
1728  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_end_time" ), isTemporal() ? temporalRange().end() : QVariant(), true ) );
1729  scope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "map_interval" ), isTemporal() ? ( temporalRange().end() - temporalRange().begin() ) : QVariant(), true ) );
1730 
1731 #if 0 // not relevant here! (but left so as to respect all the dangerous warnings in QgsExpressionContextUtils::mapSettingsScope)
1732  if ( mapSettings.frameRate() >= 0 )
1733  scope->setVariable( QStringLiteral( "frame_rate" ), mapSettings.frameRate(), true );
1734  if ( mapSettings.currentFrame() >= 0 )
1735  scope->setVariable( QStringLiteral( "frame_number" ), mapSettings.currentFrame(), true );
1736 #endif
1737 
1738  return context;
1739 }
1740 
1742 {
1743  double extentWidth = extent().width();
1744  if ( extentWidth <= 0 )
1745  {
1746  return 1;
1747  }
1748  return rect().width() / extentWidth;
1749 }
1750 
1752 {
1753  double dx = mXOffset;
1754  double dy = mYOffset;
1755  transformShift( dx, dy );
1756  QPolygonF poly = calculateVisibleExtentPolygon( false );
1757  poly.translate( -dx, -dy );
1758  return poly;
1759 }
1760 
1762 {
1763  if ( !mBlockingLabelItems.contains( item ) )
1764  mBlockingLabelItems.append( item );
1765 
1766  connect( item, &QgsLayoutItem::sizePositionChanged, this, &QgsLayoutItemMap::invalidateCache, Qt::UniqueConnection );
1767 }
1768 
1770 {
1771  mBlockingLabelItems.removeAll( item );
1772  if ( item )
1774 }
1775 
1777 {
1778  return mBlockingLabelItems.contains( item );
1779 }
1780 
1782 {
1783  return mPreviewLabelingResults.get();
1784 }
1785 
1787 {
1788  // NOTE: if visitEnter returns false it means "don't visit the item", not "abort all further visitations"
1790  return true;
1791 
1792  if ( mOverviewStack )
1793  {
1794  for ( int i = 0; i < mOverviewStack->size(); ++i )
1795  {
1796  if ( mOverviewStack->item( i )->accept( visitor ) )
1797  return false;
1798  }
1799  }
1800 
1801  if ( mGridStack )
1802  {
1803  for ( int i = 0; i < mGridStack->size(); ++i )
1804  {
1805  if ( mGridStack->item( i )->accept( visitor ) )
1806  return false;
1807  }
1808  }
1809 
1811  return false;
1812 
1813  return true;
1814 }
1815 
1817 {
1818  mRenderedFeatureHandlers.append( handler );
1819 }
1820 
1822 {
1823  mRenderedFeatureHandlers.removeAll( handler );
1824 }
1825 
1826 QPointF QgsLayoutItemMap::mapToItemCoords( QPointF mapCoords ) const
1827 {
1828  QPolygonF mapPoly = transformedMapPolygon();
1829  if ( mapPoly.empty() )
1830  {
1831  return QPointF( 0, 0 );
1832  }
1833 
1834  QgsRectangle tExtent = transformedExtent();
1835  QgsPointXY rotationPoint( ( tExtent.xMaximum() + tExtent.xMinimum() ) / 2.0, ( tExtent.yMaximum() + tExtent.yMinimum() ) / 2.0 );
1836  double dx = mapCoords.x() - rotationPoint.x();
1837  double dy = mapCoords.y() - rotationPoint.y();
1838  QgsLayoutUtils::rotate( -mEvaluatedMapRotation, dx, dy );
1839  QgsPointXY backRotatedCoords( rotationPoint.x() + dx, rotationPoint.y() + dy );
1840 
1841  QgsRectangle unrotatedExtent = transformedExtent();
1842  double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
1843  double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
1844  return QPointF( xItem, yItem );
1845 }
1846 
1848 {
1850  QgsRectangle newExtent = mExtent;
1851  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
1852  {
1853  extent = newExtent;
1854  }
1855  else
1856  {
1857  QPolygonF poly;
1858  mapPolygon( newExtent, poly );
1859  QRectF bRect = poly.boundingRect();
1860  extent.setXMinimum( bRect.left() );
1861  extent.setXMaximum( bRect.right() );
1862  extent.setYMinimum( bRect.top() );
1863  extent.setYMaximum( bRect.bottom() );
1864  }
1865  return extent;
1866 }
1867 
1869 {
1870  if ( mDrawing )
1871  return;
1872 
1873  mCacheInvalidated = true;
1874  update();
1875 }
1876 
1878 {
1879  QRectF rectangle = rect();
1880  double frameExtension = frameEnabled() ? pen().widthF() / 2.0 : 0.0;
1881 
1882  double topExtension = 0.0;
1883  double rightExtension = 0.0;
1884  double bottomExtension = 0.0;
1885  double leftExtension = 0.0;
1886 
1887  if ( mGridStack )
1888  mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1889 
1890  topExtension = std::max( topExtension, frameExtension );
1891  rightExtension = std::max( rightExtension, frameExtension );
1892  bottomExtension = std::max( bottomExtension, frameExtension );
1893  leftExtension = std::max( leftExtension, frameExtension );
1894 
1895  rectangle.setLeft( rectangle.left() - leftExtension );
1896  rectangle.setRight( rectangle.right() + rightExtension );
1897  rectangle.setTop( rectangle.top() - topExtension );
1898  rectangle.setBottom( rectangle.bottom() + bottomExtension );
1899  if ( rectangle != mCurrentRectangle )
1900  {
1901  prepareGeometryChange();
1902  mCurrentRectangle = rectangle;
1903  }
1904 }
1905 
1907 {
1909  if ( property == QgsLayoutObject::MapCrs || property == QgsLayoutObject::AllProperties )
1910  {
1911  bool ok;
1912  const QString crsVar = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapCrs, context, QString(), &ok );
1913  if ( ok && QgsCoordinateReferenceSystem( crsVar ).isValid() )
1914  {
1915  const QgsCoordinateReferenceSystem newCrs( crsVar );
1916  if ( newCrs.isValid() )
1917  {
1918  setCrs( newCrs );
1919  }
1920  }
1921  }
1922  //updates data defined properties and redraws item to match
1923  if ( property == QgsLayoutObject::MapRotation || property == QgsLayoutObject::MapScale ||
1924  property == QgsLayoutObject::MapXMin || property == QgsLayoutObject::MapYMin ||
1925  property == QgsLayoutObject::MapXMax || property == QgsLayoutObject::MapYMax ||
1926  property == QgsLayoutObject::MapAtlasMargin ||
1927  property == QgsLayoutObject::AllProperties )
1928  {
1929  QgsRectangle beforeExtent = mExtent;
1930  refreshMapExtents( &context );
1931  emit changed();
1932  if ( mExtent != beforeExtent )
1933  {
1934  emit extentChanged();
1935  }
1936  }
1937  if ( property == QgsLayoutObject::MapLabelMargin || property == QgsLayoutObject::AllProperties )
1938  {
1939  refreshLabelMargin( false );
1940  }
1941  if ( property == QgsLayoutObject::MapStylePreset || property == QgsLayoutObject::AllProperties )
1942  {
1943  const QString previousTheme = mLastEvaluatedThemeName.isEmpty() ? mFollowVisibilityPresetName : mLastEvaluatedThemeName;
1944  mLastEvaluatedThemeName = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapStylePreset, context, mFollowVisibilityPresetName );
1945  if ( mLastEvaluatedThemeName != previousTheme )
1946  emit themeChanged( mLastEvaluatedThemeName );
1947  }
1948 
1949  if ( isTemporal() && ( property == QgsLayoutObject::StartDateTime || property == QgsLayoutObject::EndDateTime || property == QgsLayoutObject::AllProperties ) )
1950  {
1951  QDateTime begin = temporalRange().begin();
1952  QDateTime end = temporalRange().end();
1953 
1954  if ( property == QgsLayoutObject::StartDateTime || property == QgsLayoutObject::AllProperties )
1956  if ( property == QgsLayoutObject::EndDateTime || property == QgsLayoutObject::AllProperties )
1958 
1959  setTemporalRange( QgsDateTimeRange( begin, end, true, begin == end ) );
1960  }
1961 
1962  //force redraw
1963  mCacheInvalidated = true;
1964 
1966 }
1967 
1968 void QgsLayoutItemMap::layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers )
1969 {
1970  if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1971  {
1972  for ( QgsMapLayer *layer : layers )
1973  {
1974  mLayerStyleOverrides.remove( layer->id() );
1975  }
1976  _qgis_removeLayers( mLayers, layers );
1977  }
1978 }
1979 
1980 void QgsLayoutItemMap::painterJobFinished()
1981 {
1982  mPainter->end();
1983  mPreviewLabelingResults.reset( mPainterJob->takeLabelingResults() );
1984  mPainterJob.reset( nullptr );
1985  mPainter.reset( nullptr );
1986  mCacheFinalImage = std::move( mCacheRenderingImage );
1987  mLastRenderedImageOffsetX = 0;
1988  mLastRenderedImageOffsetY = 0;
1989  emit backgroundTaskCountChanged( 0 );
1990  update();
1991  emit previewRefreshed();
1992 }
1993 
1994 void QgsLayoutItemMap::shapeChanged()
1995 {
1996  // keep center as center
1997  QgsPointXY oldCenter = mExtent.center();
1998 
1999  double w = rect().width();
2000  double h = rect().height();
2001 
2002  // keep same width as before
2003  double newWidth = mExtent.width();
2004  // but scale height to match item's aspect ratio
2005  double newHeight = newWidth * h / w;
2006 
2007  mExtent = QgsRectangle::fromCenterAndSize( oldCenter, newWidth, newHeight );
2008 
2009  //recalculate data defined scale and extents
2010  refreshMapExtents();
2012  invalidateCache();
2013  emit changed();
2014  emit extentChanged();
2015 }
2016 
2017 void QgsLayoutItemMap::mapThemeChanged( const QString &theme )
2018 {
2019  if ( theme == mCachedLayerStyleOverridesPresetName )
2020  mCachedLayerStyleOverridesPresetName.clear(); // force cache regeneration at next redraw
2021 }
2022 
2023 void QgsLayoutItemMap::currentMapThemeRenamed( const QString &theme, const QString &newTheme )
2024 {
2025  if ( theme == mFollowVisibilityPresetName )
2026  {
2027  mFollowVisibilityPresetName = newTheme;
2028  }
2029 }
2030 
2031 void QgsLayoutItemMap::connectUpdateSlot()
2032 {
2033  //connect signal from layer registry to update in case of new or deleted layers
2034  QgsProject *project = mLayout->project();
2035  if ( project )
2036  {
2037  // handles updating the stored layer state BEFORE the layers are removed
2038  connect( project, static_cast < void ( QgsProject::* )( const QList<QgsMapLayer *>& layers ) > ( &QgsProject::layersWillBeRemoved ),
2039  this, &QgsLayoutItemMap::layersAboutToBeRemoved );
2040  // redraws the map AFTER layers are removed
2041  connect( project->layerTreeRoot(), &QgsLayerTree::layerOrderChanged, this, [ = ]
2042  {
2043  if ( layers().isEmpty() )
2044  {
2045  //using project layers, and layer order has changed
2046  invalidateCache();
2047  }
2048  } );
2049 
2050  connect( project, &QgsProject::crsChanged, this, [ = ]
2051  {
2052  if ( !mCrs.isValid() )
2053  {
2054  //using project CRS, which just changed....
2055  invalidateCache();
2056  emit crsChanged();
2057  }
2058  } );
2059 
2060  // If project colors change, we need to redraw the map, as layer symbols may rely on project colors
2061  connect( project, &QgsProject::projectColorsChanged, this, [ = ]
2062  {
2063  invalidateCache();
2064  } );
2065 
2066  connect( project->mapThemeCollection(), &QgsMapThemeCollection::mapThemeChanged, this, &QgsLayoutItemMap::mapThemeChanged );
2067  connect( project->mapThemeCollection(), &QgsMapThemeCollection::mapThemeRenamed, this, &QgsLayoutItemMap::currentMapThemeRenamed );
2068  }
2069  connect( mLayout, &QgsLayout::refreshed, this, &QgsLayoutItemMap::invalidateCache );
2070  connect( &mLayout->renderContext(), &QgsLayoutRenderContext::predefinedScalesChanged, this, [ = ]
2071  {
2072  if ( mAtlasScalingMode == Predefined )
2073  updateAtlasFeature();
2074  } );
2075 }
2076 
2078 {
2079  QPolygonF thisExtent = calculateVisibleExtentPolygon( false );
2080  QTransform mapTransform;
2081  QPolygonF thisRectPoly = QPolygonF( QRectF( 0, 0, rect().width(), rect().height() ) );
2082  //workaround QT Bug #21329
2083  thisRectPoly.pop_back();
2084  thisExtent.pop_back();
2085 
2086  QPolygonF thisItemPolyInLayout = mapToScene( thisRectPoly );
2087 
2088  //create transform from layout coordinates to map coordinates
2089  QTransform::quadToQuad( thisItemPolyInLayout, thisExtent, mapTransform );
2090  return mapTransform;
2091 }
2092 
2093 QList<QgsLabelBlockingRegion> QgsLayoutItemMap::createLabelBlockingRegions( const QgsMapSettings & ) const
2094 {
2095  const QTransform mapTransform = layoutToMapCoordsTransform();
2096  QList< QgsLabelBlockingRegion > blockers;
2097  blockers.reserve( mBlockingLabelItems.count() );
2098  for ( const auto &item : std::as_const( mBlockingLabelItems ) )
2099  {
2100  // invisible items don't block labels!
2101  if ( !item )
2102  continue;
2103 
2104  // layout items may be temporarily hidden during layered exports
2105  if ( item->property( "wasVisible" ).isValid() )
2106  {
2107  if ( !item->property( "wasVisible" ).toBool() )
2108  continue;
2109  }
2110  else if ( !item->isVisible() )
2111  continue;
2112 
2113  QPolygonF itemRectInMapCoordinates = mapTransform.map( item->mapToScene( item->rect() ) );
2114  itemRectInMapCoordinates.append( itemRectInMapCoordinates.at( 0 ) ); //close polygon
2115  QgsGeometry blockingRegion = QgsGeometry::fromQPolygonF( itemRectInMapCoordinates );
2116  blockers << QgsLabelBlockingRegion( blockingRegion );
2117  }
2118  return blockers;
2119 }
2120 
2122 {
2123  return mLabelMargin;
2124 }
2125 
2127 {
2128  mLabelMargin = margin;
2129  refreshLabelMargin( false );
2130 }
2131 
2132 void QgsLayoutItemMap::updateToolTip()
2133 {
2134  setToolTip( displayName() );
2135 }
2136 
2137 QString QgsLayoutItemMap::themeToRender( const QgsExpressionContext &context ) const
2138 {
2139  QString presetName;
2140 
2141  if ( mFollowVisibilityPreset )
2142  {
2143  presetName = mFollowVisibilityPresetName;
2144  // preset name can be overridden by data-defined one
2145  presetName = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapStylePreset, context, presetName );
2146  }
2147  else if ( !mExportThemes.empty() && mExportThemeIt != mExportThemes.end() )
2148  presetName = *mExportThemeIt;
2149  return presetName;
2150 }
2151 
2152 QList<QgsMapLayer *> QgsLayoutItemMap::layersToRender( const QgsExpressionContext *context ) const
2153 {
2154  QgsExpressionContext scopedContext;
2155  if ( !context )
2156  scopedContext = createExpressionContext();
2157  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
2158 
2159  QList<QgsMapLayer *> renderLayers;
2160 
2161  QString presetName = themeToRender( *evalContext );
2162  if ( !presetName.isEmpty() )
2163  {
2164  if ( mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2165  renderLayers = mLayout->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
2166  else // fallback to using map canvas layers
2167  renderLayers = mLayout->project()->mapThemeCollection()->masterVisibleLayers();
2168  }
2169  else if ( !layers().isEmpty() )
2170  {
2171  renderLayers = layers();
2172  }
2173  else
2174  {
2175  renderLayers = mLayout->project()->mapThemeCollection()->masterVisibleLayers();
2176  }
2177 
2178  bool ok = false;
2179  QString ddLayers = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapLayers, *evalContext, QString(), &ok );
2180  if ( ok )
2181  {
2182  renderLayers.clear();
2183 
2184  const QStringList layerNames = ddLayers.split( '|' );
2185  //need to convert layer names to layer ids
2186  for ( const QString &name : layerNames )
2187  {
2188  const QList< QgsMapLayer * > matchingLayers = mLayout->project()->mapLayersByName( name );
2189  for ( QgsMapLayer *layer : matchingLayers )
2190  {
2191  renderLayers << layer;
2192  }
2193  }
2194  }
2195 
2196  //remove atlas coverage layer if required
2197  if ( mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagHideCoverageLayer )
2198  {
2199  //hiding coverage layer
2200  int removeAt = renderLayers.indexOf( mLayout->reportContext().layer() );
2201  if ( removeAt != -1 )
2202  {
2203  renderLayers.removeAt( removeAt );
2204  }
2205  }
2206 
2207  // remove any invalid layers
2208  renderLayers.erase( std::remove_if( renderLayers.begin(), renderLayers.end(), []( QgsMapLayer * layer )
2209  {
2210  return !layer || !layer->isValid();
2211  } ), renderLayers.end() );
2212 
2213  return renderLayers;
2214 }
2215 
2216 QMap<QString, QString> QgsLayoutItemMap::layerStyleOverridesToRender( const QgsExpressionContext &context ) const
2217 {
2218  QString presetName = themeToRender( context );
2219  if ( !presetName.isEmpty() )
2220  {
2221  if ( mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2222  {
2223  if ( presetName != mCachedLayerStyleOverridesPresetName )
2224  {
2225  // have to regenerate cache of style overrides
2226  mCachedPresetLayerStyleOverrides = mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( presetName );
2227  mCachedLayerStyleOverridesPresetName = presetName;
2228  }
2229 
2230  return mCachedPresetLayerStyleOverrides;
2231  }
2232  else
2233  return QMap<QString, QString>();
2234  }
2235  else if ( mFollowVisibilityPreset )
2236  {
2237  QString presetName = mFollowVisibilityPresetName;
2238  // data defined preset name?
2239  presetName = mDataDefinedProperties.valueAsString( QgsLayoutObject::MapStylePreset, context, presetName );
2240  if ( mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2241  {
2242  if ( presetName.isEmpty() || presetName != mCachedLayerStyleOverridesPresetName )
2243  {
2244  // have to regenerate cache of style overrides
2245  mCachedPresetLayerStyleOverrides = mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( presetName );
2246  mCachedLayerStyleOverridesPresetName = presetName;
2247  }
2248 
2249  return mCachedPresetLayerStyleOverrides;
2250  }
2251  else
2252  return QMap<QString, QString>();
2253  }
2254  else if ( mKeepLayerStyles )
2255  {
2256  return mLayerStyleOverrides;
2257  }
2258  else
2259  {
2260  return QMap<QString, QString>();
2261  }
2262 }
2263 
2264 QgsRectangle QgsLayoutItemMap::transformedExtent() const
2265 {
2266  double dx = mXOffset;
2267  double dy = mYOffset;
2268  transformShift( dx, dy );
2269  return QgsRectangle( mExtent.xMinimum() - dx, mExtent.yMinimum() - dy, mExtent.xMaximum() - dx, mExtent.yMaximum() - dy );
2270 }
2271 
2272 void QgsLayoutItemMap::mapPolygon( const QgsRectangle &extent, QPolygonF &poly ) const
2273 {
2274  poly.clear();
2275  if ( qgsDoubleNear( mEvaluatedMapRotation, 0.0 ) )
2276  {
2277  poly << QPointF( extent.xMinimum(), extent.yMaximum() );
2278  poly << QPointF( extent.xMaximum(), extent.yMaximum() );
2279  poly << QPointF( extent.xMaximum(), extent.yMinimum() );
2280  poly << QPointF( extent.xMinimum(), extent.yMinimum() );
2281  //ensure polygon is closed by readding first point
2282  poly << QPointF( poly.at( 0 ) );
2283  return;
2284  }
2285 
2286  //there is rotation
2287  QgsPointXY rotationPoint( ( extent.xMaximum() + extent.xMinimum() ) / 2.0, ( extent.yMaximum() + extent.yMinimum() ) / 2.0 );
2288  double dx, dy; //x-, y- shift from rotation point to corner point
2289 
2290  //top left point
2291  dx = rotationPoint.x() - extent.xMinimum();
2292  dy = rotationPoint.y() - extent.yMaximum();
2293  QgsLayoutUtils::rotate( mEvaluatedMapRotation, dx, dy );
2294  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2295 
2296  //top right point
2297  dx = rotationPoint.x() - extent.xMaximum();
2298  dy = rotationPoint.y() - extent.yMaximum();
2299  QgsLayoutUtils::rotate( mEvaluatedMapRotation, dx, dy );
2300  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2301 
2302  //bottom right point
2303  dx = rotationPoint.x() - extent.xMaximum();
2304  dy = rotationPoint.y() - extent.yMinimum();
2305  QgsLayoutUtils::rotate( mEvaluatedMapRotation, dx, dy );
2306  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2307 
2308  //bottom left point
2309  dx = rotationPoint.x() - extent.xMinimum();
2310  dy = rotationPoint.y() - extent.yMinimum();
2311  QgsLayoutUtils::rotate( mEvaluatedMapRotation, dx, dy );
2312  poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2313 
2314  //ensure polygon is closed by readding first point
2315  poly << QPointF( poly.at( 0 ) );
2316 }
2317 
2318 void QgsLayoutItemMap::transformShift( double &xShift, double &yShift ) const
2319 {
2320  double mmToMapUnits = 1.0 / mapUnitsToLayoutUnits();
2321  double dxScaled = xShift * mmToMapUnits;
2322  double dyScaled = - yShift * mmToMapUnits;
2323 
2324  QgsLayoutUtils::rotate( mEvaluatedMapRotation, dxScaled, dyScaled );
2325 
2326  xShift = dxScaled;
2327  yShift = dyScaled;
2328 }
2329 
2330 void QgsLayoutItemMap::drawAnnotations( QPainter *painter )
2331 {
2332  if ( !mLayout || !mLayout->project() || !mDrawAnnotations )
2333  {
2334  return;
2335  }
2336 
2337  const QList< QgsAnnotation * > annotations = mLayout->project()->annotationManager()->annotations();
2338  if ( annotations.isEmpty() )
2339  return;
2340 
2342  rc.setForceVectorOutput( true );
2344  QList< QgsMapLayer * > layers = layersToRender( &rc.expressionContext() );
2345 
2346  for ( QgsAnnotation *annotation : annotations )
2347  {
2348  if ( !annotation || !annotation->isVisible() )
2349  {
2350  continue;
2351  }
2352  if ( annotation->mapLayer() && !layers.contains( annotation->mapLayer() ) )
2353  continue;
2354 
2355  drawAnnotation( annotation, rc );
2356  }
2357 }
2358 
2359 void QgsLayoutItemMap::drawAnnotation( const QgsAnnotation *annotation, QgsRenderContext &context )
2360 {
2361  if ( !annotation || !annotation->isVisible() || !context.painter() || !context.painter()->device() )
2362  {
2363  return;
2364  }
2365 
2366  QgsScopedQPainterState painterState( context.painter() );
2367  context.setPainterFlagsUsingContext();
2368 
2369  double itemX, itemY;
2370  if ( annotation->hasFixedMapPosition() )
2371  {
2372  QPointF mapPos = layoutMapPosForItem( annotation );
2373  itemX = mapPos.x();
2374  itemY = mapPos.y();
2375  }
2376  else
2377  {
2378  itemX = annotation->relativePosition().x() * rect().width();
2379  itemY = annotation->relativePosition().y() * rect().height();
2380  }
2381  context.painter()->translate( itemX, itemY );
2382 
2383  //setup painter scaling to dots so that symbology is drawn to scale
2384  double dotsPerMM = context.painter()->device()->logicalDpiX() / 25.4;
2385  context.painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM ); // scale painter from mm to dots
2386 
2387  annotation->render( context );
2388 }
2389 
2390 QPointF QgsLayoutItemMap::layoutMapPosForItem( const QgsAnnotation *annotation ) const
2391 {
2392  if ( !annotation )
2393  return QPointF( 0, 0 );
2394 
2395  double mapX = 0.0;
2396  double mapY = 0.0;
2397 
2398  mapX = annotation->mapPosition().x();
2399  mapY = annotation->mapPosition().y();
2400  QgsCoordinateReferenceSystem annotationCrs = annotation->mapPositionCrs();
2401 
2402  if ( annotationCrs != crs() )
2403  {
2404  //need to reproject
2405  QgsCoordinateTransform t( annotationCrs, crs(), mLayout->project() );
2406  double z = 0.0;
2407  try
2408  {
2409  t.transformInPlace( mapX, mapY, z );
2410  }
2411  catch ( const QgsCsException & )
2412  {
2413  }
2414  }
2415 
2416  return mapToItemCoords( QPointF( mapX, mapY ) );
2417 }
2418 
2419 void QgsLayoutItemMap::drawMapFrame( QPainter *p )
2420 {
2421  if ( frameEnabled() && p )
2422  {
2425 
2427  }
2428 }
2429 
2430 void QgsLayoutItemMap::drawMapBackground( QPainter *p )
2431 {
2432  if ( hasBackground() && p )
2433  {
2436 
2438  }
2439 }
2440 
2441 bool QgsLayoutItemMap::shouldDrawPart( QgsLayoutItemMap::PartType part ) const
2442 {
2443  if ( mCurrentExportPart == NotLayered )
2444  {
2445  //all parts of the map are visible
2446  return true;
2447  }
2448 
2449  switch ( part )
2450  {
2451  case NotLayered:
2452  return true;
2453 
2454  case Start:
2455  return false;
2456 
2457  case Background:
2458  return mCurrentExportPart == Background && hasBackground();
2459 
2460  case Layer:
2461  return mCurrentExportPart == Layer;
2462 
2463  case Grid:
2464  return mCurrentExportPart == Grid && mGridStack->hasEnabledItems();
2465 
2466  case OverviewMapExtent:
2467  return mCurrentExportPart == OverviewMapExtent && mOverviewStack->hasEnabledItems();
2468 
2469  case Frame:
2470  return mCurrentExportPart == Frame && frameEnabled();
2471 
2472  case SelectionBoxes:
2473  return mCurrentExportPart == SelectionBoxes && isSelected();
2474 
2475  case End:
2476  return false;
2477  }
2478 
2479  return false;
2480 }
2481 
2482 void QgsLayoutItemMap::refreshMapExtents( const QgsExpressionContext *context )
2483 {
2484  QgsExpressionContext scopedContext;
2485  if ( !context )
2486  scopedContext = createExpressionContext();
2487 
2488  bool ok = false;
2489  const QgsExpressionContext *evalContext = context ? context : &scopedContext;
2490 
2491 
2492  //data defined map extents set?
2493  QgsRectangle newExtent = extent();
2494  bool useDdXMin = false;
2495  bool useDdXMax = false;
2496  bool useDdYMin = false;
2497  bool useDdYMax = false;
2498  double minXD = 0;
2499  double minYD = 0;
2500  double maxXD = 0;
2501  double maxYD = 0;
2502 
2503  minXD = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapXMin, *evalContext, 0.0, &ok );
2504  if ( ok )
2505  {
2506  useDdXMin = true;
2507  newExtent.setXMinimum( minXD );
2508  }
2509  minYD = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapYMin, *evalContext, 0.0, &ok );
2510  if ( ok )
2511  {
2512  useDdYMin = true;
2513  newExtent.setYMinimum( minYD );
2514  }
2515  maxXD = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapXMax, *evalContext, 0.0, &ok );
2516  if ( ok )
2517  {
2518  useDdXMax = true;
2519  newExtent.setXMaximum( maxXD );
2520  }
2521  maxYD = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapYMax, *evalContext, 0.0, &ok );
2522  if ( ok )
2523  {
2524  useDdYMax = true;
2525  newExtent.setYMaximum( maxYD );
2526  }
2527 
2528  if ( newExtent != mExtent )
2529  {
2530  //calculate new extents to fit data defined extents
2531 
2532  //Make sure the width/height ratio is the same as in current map extent.
2533  //This is to keep the map item frame and the page layout fixed
2534  double currentWidthHeightRatio = mExtent.width() / mExtent.height();
2535  double newWidthHeightRatio = newExtent.width() / newExtent.height();
2536 
2537  if ( currentWidthHeightRatio < newWidthHeightRatio )
2538  {
2539  //enlarge height of new extent, ensuring the map center stays the same
2540  double newHeight = newExtent.width() / currentWidthHeightRatio;
2541  double deltaHeight = newHeight - newExtent.height();
2542  newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 );
2543  newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 );
2544  }
2545  else
2546  {
2547  //enlarge width of new extent, ensuring the map center stays the same
2548  double newWidth = currentWidthHeightRatio * newExtent.height();
2549  double deltaWidth = newWidth - newExtent.width();
2550  newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 );
2551  newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 );
2552  }
2553 
2554  mExtent = newExtent;
2555  }
2556 
2557  //now refresh scale, as this potentially overrides extents
2558 
2559  //data defined map scale set?
2560  double scaleD = mDataDefinedProperties.valueAsDouble( QgsLayoutObject::MapScale, *evalContext, 0.0, &ok );
2561  if ( ok )
2562  {
2563  setScale( scaleD, false );
2564  newExtent = mExtent;
2565  }
2566 
2567  if ( useDdXMax || useDdXMin || useDdYMax || useDdYMin )
2568  {
2569  //if only one of min/max was set for either x or y, then make sure our extent is locked on that value
2570  //as we can do this without altering the scale
2571  if ( useDdXMin && !useDdXMax )
2572  {
2573  double xMax = mExtent.xMaximum() - ( mExtent.xMinimum() - minXD );
2574  newExtent.setXMinimum( minXD );
2575  newExtent.setXMaximum( xMax );
2576  }
2577  else if ( !useDdXMin && useDdXMax )
2578  {
2579  double xMin = mExtent.xMinimum() - ( mExtent.xMaximum() - maxXD );
2580  newExtent.setXMinimum( xMin );
2581  newExtent.setXMaximum( maxXD );
2582  }
2583  if ( useDdYMin && !useDdYMax )
2584  {
2585  double yMax = mExtent.yMaximum() - ( mExtent.yMinimum() - minYD );
2586  newExtent.setYMinimum( minYD );
2587  newExtent.setYMaximum( yMax );
2588  }
2589  else if ( !useDdYMin && useDdYMax )
2590  {
2591  double yMin = mExtent.yMinimum() - ( mExtent.yMaximum() - maxYD );
2592  newExtent.setYMinimum( yMin );
2593  newExtent.setYMaximum( maxYD );
2594  }
2595 
2596  if ( newExtent != mExtent )
2597  {
2598  mExtent = newExtent;
2599  }
2600  }
2601 
2602  //lastly, map rotation overrides all
2603  double mapRotation = mMapRotation;
2604 
2605  //data defined map rotation set?
2607 
2608  if ( !qgsDoubleNear( mEvaluatedMapRotation, mapRotation ) )
2609  {
2610  mEvaluatedMapRotation = mapRotation;
2612  }
2613 }
2614 
2615 void QgsLayoutItemMap::refreshLabelMargin( bool updateItem )
2616 {
2617  //data defined label margin set?
2619  mEvaluatedLabelMargin.setLength( labelMargin );
2620  mEvaluatedLabelMargin.setUnits( mLabelMargin.units() );
2621 
2622  if ( updateItem )
2623  {
2624  update();
2625  }
2626 }
2627 
2628 void QgsLayoutItemMap::updateAtlasFeature()
2629 {
2630  if ( !atlasDriven() || !mLayout->reportContext().layer() )
2631  return; // nothing to do
2632 
2633  QgsRectangle bounds = computeAtlasRectangle();
2634  if ( bounds.isNull() )
2635  return;
2636 
2637  double xa1 = bounds.xMinimum();
2638  double xa2 = bounds.xMaximum();
2639  double ya1 = bounds.yMinimum();
2640  double ya2 = bounds.yMaximum();
2641  QgsRectangle newExtent = bounds;
2642  QgsRectangle originalExtent = mExtent;
2643 
2644  //sanity check - only allow fixed scale mode for point layers
2645  bool isPointLayer = QgsWkbTypes::geometryType( mLayout->reportContext().layer()->wkbType() ) == QgsWkbTypes::PointGeometry;
2646 
2647  if ( mAtlasScalingMode == Fixed || mAtlasScalingMode == Predefined || isPointLayer )
2648  {
2649  QgsScaleCalculator calc;
2650  calc.setMapUnits( crs().mapUnits() );
2651  calc.setDpi( 25.4 );
2652  double originalScale = calc.calculate( originalExtent, rect().width() );
2653  double geomCenterX = ( xa1 + xa2 ) / 2.0;
2654  double geomCenterY = ( ya1 + ya2 ) / 2.0;
2655  QVector<qreal> scales;
2657  if ( !mLayout->reportContext().predefinedScales().empty() ) // remove when deprecated method is removed
2658  scales = mLayout->reportContext().predefinedScales();
2659  else
2660  scales = mLayout->renderContext().predefinedScales();
2662  if ( mAtlasScalingMode == Fixed || scales.isEmpty() || ( isPointLayer && mAtlasScalingMode != Predefined ) )
2663  {
2664  // only translate, keep the original scale (i.e. width x height)
2665  double xMin = geomCenterX - originalExtent.width() / 2.0;
2666  double yMin = geomCenterY - originalExtent.height() / 2.0;
2667  newExtent = QgsRectangle( xMin,
2668  yMin,
2669  xMin + originalExtent.width(),
2670  yMin + originalExtent.height() );
2671 
2672  //scale newExtent to match original scale of map
2673  //this is required for geographic coordinate systems, where the scale varies by extent
2674  double newScale = calc.calculate( newExtent, rect().width() );
2675  newExtent.scale( originalScale / newScale );
2676  }
2677  else if ( mAtlasScalingMode == Predefined )
2678  {
2679  // choose one of the predefined scales
2680  double newWidth = originalExtent.width();
2681  double newHeight = originalExtent.height();
2682  for ( int i = 0; i < scales.size(); i++ )
2683  {
2684  double ratio = scales[i] / originalScale;
2685  newWidth = originalExtent.width() * ratio;
2686  newHeight = originalExtent.height() * ratio;
2687 
2688  // compute new extent, centered on feature
2689  double xMin = geomCenterX - newWidth / 2.0;
2690  double yMin = geomCenterY - newHeight / 2.0;
2691  newExtent = QgsRectangle( xMin,
2692  yMin,
2693  xMin + newWidth,
2694  yMin + newHeight );
2695 
2696  //scale newExtent to match desired map scale
2697  //this is required for geographic coordinate systems, where the scale varies by extent
2698  double newScale = calc.calculate( newExtent, rect().width() );
2699  newExtent.scale( scales[i] / newScale );
2700 
2701  if ( ( newExtent.width() >= bounds.width() ) && ( newExtent.height() >= bounds.height() ) )
2702  {
2703  // this is the smallest extent that embeds the feature, stop here
2704  break;
2705  }
2706  }
2707  }
2708  }
2709  else if ( mAtlasScalingMode == Auto )
2710  {
2711  // auto scale
2712 
2713  double geomRatio = bounds.width() / bounds.height();
2714  double mapRatio = originalExtent.width() / originalExtent.height();
2715 
2716  // geometry height is too big
2717  if ( geomRatio < mapRatio )
2718  {
2719  // extent the bbox's width
2720  double adjWidth = ( mapRatio * bounds.height() - bounds.width() ) / 2.0;
2721  xa1 -= adjWidth;
2722  xa2 += adjWidth;
2723  }
2724  // geometry width is too big
2725  else if ( geomRatio > mapRatio )
2726  {
2727  // extent the bbox's height
2728  double adjHeight = ( bounds.width() / mapRatio - bounds.height() ) / 2.0;
2729  ya1 -= adjHeight;
2730  ya2 += adjHeight;
2731  }
2732  newExtent = QgsRectangle( xa1, ya1, xa2, ya2 );
2733 
2734  const double evaluatedAtlasMargin = atlasMargin();
2735  if ( evaluatedAtlasMargin > 0.0 )
2736  {
2737  newExtent.scale( 1 + evaluatedAtlasMargin );
2738  }
2739  }
2740 
2741  // set the new extent (and render)
2742  setExtent( newExtent );
2743  emit preparedForAtlas();
2744 }
2745 
2746 QgsRectangle QgsLayoutItemMap::computeAtlasRectangle()
2747 {
2748  // QgsGeometry::boundingBox is expressed in the geometry"s native CRS
2749  // We have to transform the geometry to the destination CRS and ask for the bounding box
2750  // Note: we cannot directly take the transformation of the bounding box, since transformations are not linear
2751  QgsGeometry g = mLayout->reportContext().currentGeometry( crs() );
2752  // Rotating the geometry, so the bounding box is correct wrt map rotation
2753  if ( mEvaluatedMapRotation != 0.0 )
2754  {
2755  QgsPointXY prevCenter = g.boundingBox().center();
2756  g.rotate( mEvaluatedMapRotation, g.boundingBox().center() );
2757  // Rotation center will be still the bounding box center of an unrotated geometry.
2758  // Which means, if the center of bbox moves after rotation, the viewport will
2759  // also be offset, and part of the geometry will fall out of bounds.
2760  // Here we compensate for that roughly: by extending the rotated bounds
2761  // so that its center is the same as the original.
2762  QgsRectangle bounds = g.boundingBox();
2763  double dx = std::max( std::abs( prevCenter.x() - bounds.xMinimum() ),
2764  std::abs( prevCenter.x() - bounds.xMaximum() ) );
2765  double dy = std::max( std::abs( prevCenter.y() - bounds.yMinimum() ),
2766  std::abs( prevCenter.y() - bounds.yMaximum() ) );
2767  QgsPointXY center = g.boundingBox().center();
2768  return QgsRectangle( center.x() - dx, center.y() - dy,
2769  center.x() + dx, center.y() + dy );
2770  }
2771  else
2772  {
2773  return g.boundingBox();
2774  }
2775 }
2776 
2777 void QgsLayoutItemMap::createStagedRenderJob( const QgsRectangle &extent, const QSizeF size, double dpi )
2778 {
2779  QgsMapSettings settings = mapSettings( extent, size, dpi, true );
2780  settings.setLayers( mOverviewStack->modifyMapLayerList( settings.layers() ) );
2781 
2782  mStagedRendererJob = std::make_unique< QgsMapRendererStagedRenderJob >( settings,
2785  : QgsMapRendererStagedRenderJob::Flags() );
2786  mStagedRendererJob->start();
2787 }
2788 
2789 
2790 
2791 //
2792 // QgsLayoutItemMapAtlasClippingSettings
2793 //
2794 
2796  : QObject( map )
2797  , mMap( map )
2798 {
2799  if ( mMap->layout() && mMap->layout()->project() )
2800  {
2801  connect( mMap->layout()->project(), static_cast < void ( QgsProject::* )( const QList<QgsMapLayer *>& layers ) > ( &QgsProject::layersWillBeRemoved ),
2802  this, &QgsLayoutItemMapAtlasClippingSettings::layersAboutToBeRemoved );
2803  }
2804 }
2805 
2807 {
2808  return mClipToAtlasFeature;
2809 }
2810 
2812 {
2813  if ( enabled == mClipToAtlasFeature )
2814  return;
2815 
2816  mClipToAtlasFeature = enabled;
2817  emit changed();
2818 }
2819 
2821 {
2822  return mFeatureClippingType;
2823 }
2824 
2826 {
2827  if ( mFeatureClippingType == type )
2828  return;
2829 
2830  mFeatureClippingType = type;
2831  emit changed();
2832 }
2833 
2835 {
2836  return mForceLabelsInsideFeature;
2837 }
2838 
2840 {
2841  if ( forceInside == mForceLabelsInsideFeature )
2842  return;
2843 
2844  mForceLabelsInsideFeature = forceInside;
2845  emit changed();
2846 }
2847 
2849 {
2850  return mRestrictToLayers;
2851 }
2852 
2854 {
2855  if ( mRestrictToLayers == enabled )
2856  return;
2857 
2858  mRestrictToLayers = enabled;
2859  emit changed();
2860 }
2861 
2863 {
2864  return _qgis_listRefToRaw( mLayersToClip );
2865 }
2866 
2867 void QgsLayoutItemMapAtlasClippingSettings::setLayersToClip( const QList< QgsMapLayer * > &layersToClip )
2868 {
2869  mLayersToClip = _qgis_listRawToRef( layersToClip );
2870  emit changed();
2871 }
2872 
2873 bool QgsLayoutItemMapAtlasClippingSettings::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext & ) const
2874 {
2875  QDomElement settingsElem = document.createElement( QStringLiteral( "atlasClippingSettings" ) );
2876  settingsElem.setAttribute( QStringLiteral( "enabled" ), mClipToAtlasFeature ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2877  settingsElem.setAttribute( QStringLiteral( "forceLabelsInside" ), mForceLabelsInsideFeature ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2878  settingsElem.setAttribute( QStringLiteral( "clippingType" ), QString::number( static_cast<int>( mFeatureClippingType ) ) );
2879  settingsElem.setAttribute( QStringLiteral( "restrictLayers" ), mRestrictToLayers ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
2880 
2881  //layer set
2882  QDomElement layerSetElem = document.createElement( QStringLiteral( "layersToClip" ) );
2883  for ( const QgsMapLayerRef &layerRef : mLayersToClip )
2884  {
2885  if ( !layerRef )
2886  continue;
2887  QDomElement layerElem = document.createElement( QStringLiteral( "Layer" ) );
2888  QDomText layerIdText = document.createTextNode( layerRef.layerId );
2889  layerElem.appendChild( layerIdText );
2890 
2891  layerElem.setAttribute( QStringLiteral( "name" ), layerRef.name );
2892  layerElem.setAttribute( QStringLiteral( "source" ), layerRef.source );
2893  layerElem.setAttribute( QStringLiteral( "provider" ), layerRef.provider );
2894 
2895  layerSetElem.appendChild( layerElem );
2896  }
2897  settingsElem.appendChild( layerSetElem );
2898 
2899  element.appendChild( settingsElem );
2900  return true;
2901 }
2902 
2903 bool QgsLayoutItemMapAtlasClippingSettings::readXml( const QDomElement &element, const QDomDocument &, const QgsReadWriteContext & )
2904 {
2905  const QDomElement settingsElem = element.firstChildElement( QStringLiteral( "atlasClippingSettings" ) );
2906 
2907  mClipToAtlasFeature = settingsElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt();
2908  mForceLabelsInsideFeature = settingsElem.attribute( QStringLiteral( "forceLabelsInside" ), QStringLiteral( "0" ) ).toInt();
2909  mFeatureClippingType = static_cast< QgsMapClippingRegion::FeatureClippingType >( settingsElem.attribute( QStringLiteral( "clippingType" ), QStringLiteral( "0" ) ).toInt() );
2910  mRestrictToLayers = settingsElem.attribute( QStringLiteral( "restrictLayers" ), QStringLiteral( "0" ) ).toInt();
2911 
2912  mLayersToClip.clear();
2913  QDomNodeList layerSetNodeList = settingsElem.elementsByTagName( QStringLiteral( "layersToClip" ) );
2914  if ( !layerSetNodeList.isEmpty() )
2915  {
2916  QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
2917  QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral( "Layer" ) );
2918  mLayersToClip.reserve( layerIdNodeList.size() );
2919  for ( int i = 0; i < layerIdNodeList.size(); ++i )
2920  {
2921  QDomElement layerElem = layerIdNodeList.at( i ).toElement();
2922  QString layerId = layerElem.text();
2923  QString layerName = layerElem.attribute( QStringLiteral( "name" ) );
2924  QString layerSource = layerElem.attribute( QStringLiteral( "source" ) );
2925  QString layerProvider = layerElem.attribute( QStringLiteral( "provider" ) );
2926 
2927  QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
2928  if ( mMap->layout() && mMap->layout()->project() )
2929  ref.resolveWeakly( mMap->layout()->project() );
2930  mLayersToClip << ref;
2931  }
2932  }
2933 
2934  return true;
2935 }
2936 
2937 void QgsLayoutItemMapAtlasClippingSettings::layersAboutToBeRemoved( const QList<QgsMapLayer *> &layers )
2938 {
2939  if ( !mLayersToClip.isEmpty() )
2940  {
2941  _qgis_removeLayers( mLayersToClip, layers );
2942  }
2943 }
2944 
2945 //
2946 // QgsLayoutItemMapItemClipPathSettings
2947 //
2949  : QObject( map )
2950  , mMap( map )
2951 {
2952 }
2953 
2955 {
2956  return mEnabled && mClipPathSource;
2957 }
2958 
2960 {
2961  return mEnabled;
2962 }
2963 
2965 {
2966  if ( enabled == mEnabled )
2967  return;
2968 
2969  mEnabled = enabled;
2970 
2971  if ( mClipPathSource )
2972  {
2973  // may need to refresh the clip source in order to get it to render/not render depending on enabled state
2974  mClipPathSource->refresh();
2975  }
2976  emit changed();
2977 }
2978 
2980 {
2981  if ( isActive() )
2982  {
2983  QgsGeometry clipGeom( mClipPathSource->clipPath() );
2984  clipGeom.transform( mMap->layoutToMapCoordsTransform() );
2985  return clipGeom;
2986  }
2987  return QgsGeometry();
2988 }
2989 
2991 {
2992  if ( isActive() )
2993  {
2994  QgsGeometry clipGeom( mClipPathSource->clipPath() );
2995  clipGeom.transform( mMap->sceneTransform().inverted() );
2996  return clipGeom;
2997  }
2998  return QgsGeometry();
2999 }
3000 
3002 {
3004  region.setFeatureClip( mFeatureClippingType );
3005  return region;
3006 }
3007 
3009 {
3010  if ( mClipPathSource == item )
3011  return;
3012 
3013  if ( mClipPathSource )
3014  {
3015  disconnect( mClipPathSource, &QgsLayoutItem::clipPathChanged, mMap, &QgsLayoutItemMap::refresh );
3016  disconnect( mClipPathSource, &QgsLayoutItem::rotationChanged, mMap, &QgsLayoutItemMap::refresh );
3017  disconnect( mClipPathSource, &QgsLayoutItem::clipPathChanged, mMap, &QgsLayoutItemMap::extentChanged );
3018  disconnect( mClipPathSource, &QgsLayoutItem::rotationChanged, mMap, &QgsLayoutItemMap::extentChanged );
3019  }
3020 
3021  QgsLayoutItem *oldItem = mClipPathSource;
3022  mClipPathSource = item;
3023 
3024  if ( mClipPathSource )
3025  {
3026  // if item size or rotation changes, we need to redraw this map
3027  connect( mClipPathSource, &QgsLayoutItem::clipPathChanged, mMap, &QgsLayoutItemMap::refresh );
3028  connect( mClipPathSource, &QgsLayoutItem::rotationChanged, mMap, &QgsLayoutItemMap::refresh );
3029  // and if clip item size or rotation changes, then effectively we've changed the visible extent of the map
3030  connect( mClipPathSource, &QgsLayoutItem::clipPathChanged, mMap, &QgsLayoutItemMap::extentChanged );
3031  connect( mClipPathSource, &QgsLayoutItem::rotationChanged, mMap, &QgsLayoutItemMap::extentChanged );
3032  // trigger a redraw of the clip source, so that it becomes invisible
3033  mClipPathSource->refresh();
3034  }
3035 
3036  if ( oldItem )
3037  {
3038  // may need to refresh the previous item in order to get it to render
3039  oldItem->refresh();
3040  }
3041 
3042  emit changed();
3043 }
3044 
3046 {
3047  return mClipPathSource;
3048 }
3049 
3051 {
3052  return mFeatureClippingType;
3053 }
3054 
3056 {
3057  if ( mFeatureClippingType == type )
3058  return;
3059 
3060  mFeatureClippingType = type;
3061  emit changed();
3062 }
3063 
3065 {
3066  return mForceLabelsInsideClipPath;
3067 }
3068 
3070 {
3071  if ( forceInside == mForceLabelsInsideClipPath )
3072  return;
3073 
3074  mForceLabelsInsideClipPath = forceInside;
3075  emit changed();
3076 }
3077 
3078 bool QgsLayoutItemMapItemClipPathSettings::writeXml( QDomElement &element, QDomDocument &document, const QgsReadWriteContext & ) const
3079 {
3080  QDomElement settingsElem = document.createElement( QStringLiteral( "itemClippingSettings" ) );
3081  settingsElem.setAttribute( QStringLiteral( "enabled" ), mEnabled ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
3082  settingsElem.setAttribute( QStringLiteral( "forceLabelsInside" ), mForceLabelsInsideClipPath ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
3083  settingsElem.setAttribute( QStringLiteral( "clippingType" ), QString::number( static_cast<int>( mFeatureClippingType ) ) );
3084  if ( mClipPathSource )
3085  settingsElem.setAttribute( QStringLiteral( "clipSource" ), mClipPathSource->uuid() );
3086  else
3087  settingsElem.setAttribute( QStringLiteral( "clipSource" ), QString() );
3088 
3089  element.appendChild( settingsElem );
3090  return true;
3091 }
3092 
3093 bool QgsLayoutItemMapItemClipPathSettings::readXml( const QDomElement &element, const QDomDocument &, const QgsReadWriteContext & )
3094 {
3095  const QDomElement settingsElem = element.firstChildElement( QStringLiteral( "itemClippingSettings" ) );
3096 
3097  mEnabled = settingsElem.attribute( QStringLiteral( "enabled" ), QStringLiteral( "0" ) ).toInt();
3098  mForceLabelsInsideClipPath = settingsElem.attribute( QStringLiteral( "forceLabelsInside" ), QStringLiteral( "0" ) ).toInt();
3099  mFeatureClippingType = static_cast< QgsMapClippingRegion::FeatureClippingType >( settingsElem.attribute( QStringLiteral( "clippingType" ), QStringLiteral( "0" ) ).toInt() );
3100  mClipPathUuid = settingsElem.attribute( QStringLiteral( "clipSource" ) );
3101 
3102  return true;
3103 }
3104 
3106 {
3107  if ( !mClipPathUuid.isEmpty() )
3108  {
3109  if ( QgsLayoutItem *item = mMap->layout()->itemByUuid( mClipPathUuid, true ) )
3110  {
3111  setSourceItem( item );
3112  }
3113  }
3114 }
QgsLayoutRenderContext::FlagUseAdvancedEffects
@ FlagUseAdvancedEffects
Enable advanced effects such as blend modes.
Definition: qgslayoutrendercontext.h:49
QgsLayoutItem::shouldDrawItem
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
Definition: qgslayoutitem.cpp:591
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsLayoutItem::id
QString id() const
Returns the item's ID name.
Definition: qgslayoutitem.h:359
QgsExpressionContextScope::addFunction
void addFunction(const QString &name, QgsScopedExpressionFunction *function)
Adds a function to the scope.
Definition: qgsexpressioncontext.cpp:193
QgsMapSettings::setDestinationCrs
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs (coordinate reference system) for the map render.
Definition: qgsmapsettings.cpp:350
QgsLayoutObject::layout
const QgsLayout * layout() const
Returns the layout the object is attached to.
Definition: qgslayoutobject.cpp:216
QgsMapRendererStagedRenderJob::Symbology
@ Symbology
Rendering layer symbology.
Definition: qgsmaprendererstagedrenderjob.h:51
QgsLayoutItemMap::addLabelBlockingItem
void addLabelBlockingItem(QgsLayoutItem *item)
Sets the specified layout item as a "label blocking item" for this map.
Definition: qgslayoutitemmap.cpp:1761
Qgis::MapSettingsFlag::RenderPartialOutput
@ RenderPartialOutput
Whether to make extra effort to update map image with partially rendered layers (better for interacti...
QgsLayoutItemMap::grid
QgsLayoutItemMapGrid * grid()
Returns the map item's first grid.
Definition: qgslayoutitemmap.cpp:564
qgsexpressioncontextutils.h
QgsLayoutItemMap::startLayeredExport
void startLayeredExport() override
Starts a multi-layer export operation.
Definition: qgslayoutitemmap.cpp:1106
QgsLayoutItemMapGrid
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
Definition: qgslayoutitemmapgrid.h:140
QgsVectorSimplifyMethod::NoSimplification
@ NoSimplification
No simplification can be applied.
Definition: qgsvectorsimplifymethod.h:52
QgsRectangle::height
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
QgsLayoutItemMap::assignFreeId
void assignFreeId()
Sets the map id() to a number not yet used in the layout.
Definition: qgslayoutitemmap.cpp:118
QgsLayoutItemMapAtlasClippingSettings::setLayersToClip
void setLayersToClip(const QList< QgsMapLayer * > &layers)
Sets the list of map layers to clip to the atlas feature.
Definition: qgslayoutitemmap.cpp:2867
QgsLabelingEngineSettings::CollectUnplacedLabels
@ CollectUnplacedLabels
Whether unplaced labels should be collected in the labeling results (regardless of whether they are b...
Definition: qgslabelingenginesettings.h:44
QgsAbstractPropertyCollection::valueAsDouble
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double.
Definition: qgspropertycollection.cpp:66
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsLayoutRenderContext::FlagRenderLabelsByMapLayer
@ FlagRenderLabelsByMapLayer
When rendering map items to multi-layered exports, render labels belonging to different layers into s...
Definition: qgslayoutrendercontext.h:54
QgsMapSettings::setLabelBoundaryGeometry
void setLabelBoundaryGeometry(const QgsGeometry &boundary)
Sets the label boundary geometry, which restricts where in the rendered map labels are permitted to b...
Definition: qgsmapsettings.cpp:818
QgsLayoutObject::StartDateTime
@ StartDateTime
Temporal range's start DateTime.
Definition: qgslayoutobject.h:211
qgsmaplayerstylemanager.h
QgsRenderContext::setPainterFlagsUsingContext
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
Definition: qgsrendercontext.cpp:169
Qgis::MapSettingsFlag::UseRenderingOptimization
@ UseRenderingOptimization
Enable vector simplification and other rendering optimizations.
QgsMapThemeCollection::mapThemeRenamed
void mapThemeRenamed(const QString &name, const QString &newName)
Emitted when a map theme within the collection is renamed.
QgsMapClippingRegion
A map clipping region (in map coordinates and CRS).
Definition: qgsmapclippingregion.h:33
QgsProject::layersWillBeRemoved
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QgsLayoutMeasurement::setUnits
void setUnits(const QgsUnitTypes::LayoutUnit units)
Sets the units for the measurement.
Definition: qgslayoutmeasurement.h:67
QgsLayoutItem::sizePositionChanged
void sizePositionChanged()
Emitted when the item's size or position changes.
QgsLayoutItemMap::draw
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
Definition: qgslayoutitemmap.cpp:584
QgsAnnotation::mapPosition
QgsPointXY mapPosition
Definition: qgsannotation.h:73
QgsLayoutItemMap::Auto
@ Auto
The extent is adjusted so that each feature is fully visible.
Definition: qgslayoutitemmap.h:344
QgsScaleCalculator::setMapUnits
void setMapUnits(QgsUnitTypes::DistanceUnit mapUnits)
Set the map units.
Definition: qgsscalecalculator.cpp:38
QgsExpressionContextScope::setVariable
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
Definition: qgsexpressioncontext.cpp:83
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
QgsLayoutItem::frameEnabled
bool frameEnabled() const
Returns true if the item includes a frame.
Definition: qgslayoutitem.h:732
_LayerRef::resolveWeakly
TYPE * resolveWeakly(const QgsProject *project, MatchType matchType=MatchType::All)
Resolves the map layer by attempting to find a matching layer in a project using a weak match.
Definition: qgsmaplayerref.h:211
QgsLayoutItemMap::updateBoundingRect
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
Definition: qgslayoutitemmap.cpp:1877
QgsLayoutItemMapItemClipPathSettings::setFeatureClippingType
void setFeatureClippingType(QgsMapClippingRegion::FeatureClippingType type)
Sets the feature clipping type to apply when clipping to the associated item.
Definition: qgslayoutitemmap.cpp:3055
QgsReadWriteContext
The class is used as a container of context for various read/write operations on other objects.
Definition: qgsreadwritecontext.h:34
QgsScaleCalculator::setDpi
void setDpi(double dpi)
Sets the dpi (dots per inch) for the output resolution, to be used in scale calculations.
Definition: qgsscalecalculator.cpp:29
QgsAbstractGeometry::asQPainterPath
virtual QPainterPath asQPainterPath() const =0
Returns the geometry represented as a QPainterPath.
QgsMapSettings::setFlag
void setFlag(Qgis::MapSettingsFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Definition: qgsmapsettings.cpp:382
QgsCoordinateReferenceSystem::projectionAcronym
QString projectionAcronym() const
Returns the projection acronym for the projection used by the CRS.
Definition: qgscoordinatereferencesystem.cpp:1239
QgsMapSettings::setRotation
void setRotation(double rotation)
Sets the rotation of the resulting map image, in degrees clockwise.
Definition: qgsmapsettings.cpp:107
qgsmapthemecollection.h
QgsLayoutItemMap::QgsLayoutItemMapGrid
friend class QgsLayoutItemMapGrid
Definition: qgslayoutitemmap.h:1188
QgsExpressionContextScope::addVariable
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Definition: qgsexpressioncontext.cpp:97
QgsLayoutItemMap::writePropertiesToElement
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
Definition: qgslayoutitemmap.cpp:588
qgsannotation.h
QgsLayoutItemMap::mapToItemCoords
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset)
Definition: qgslayoutitemmap.cpp:1826
QgsLayoutItemMapItemClipPathSettings::forceLabelsInsideClipPath
bool forceLabelsInsideClipPath() const
Returns true if labels should only be placed inside the clip path geometry.
Definition: qgslayoutitemmap.cpp:3064
QgsLayout::itemByUuid
QgsLayoutItem * itemByUuid(const QString &uuid, bool includeTemplateUuids=false) const
Returns the layout item with matching uuid unique identifier, or nullptr if a matching item could not...
Definition: qgslayout.cpp:238
QgsLayoutItem::setFrameStrokeWidth
virtual void setFrameStrokeWidth(QgsLayoutMeasurement width)
Sets the frame stroke width.
Definition: qgslayoutitem.cpp:860
QgsGeometry::transform
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
Definition: qgsgeometry.cpp:3128
Qgis::MapSettingsFlag::UseAdvancedEffects
@ UseAdvancedEffects
Enable layer opacity and blending effects.
QgsLayoutItemMap::numberExportLayers
Q_DECL_DEPRECATED int numberExportLayers() const override
Returns the number of layers that this item requires for exporting during layered exports (e....
Definition: qgslayoutitemmap.cpp:1096
QgsLayoutMeasurement::length
double length() const
Returns the length of the measurement.
Definition: qgslayoutmeasurement.h:48
QgsLayoutItemMap::exportLayerBehavior
ExportLayerBehavior exportLayerBehavior() const override
Returns the behavior of this item during exporting to layered exports (e.g.
Definition: qgslayoutitemmap.cpp:1204
QgsCoordinateReferenceSystem::WKT_PREFERRED
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition: qgscoordinatereferencesystem.h:680
QgsScaleCalculator::calculate
double calculate(const QgsRectangle &mapExtent, double canvasWidth) const
Calculate the scale denominator.
Definition: qgsscalecalculator.cpp:50
QgsTemporalRangeObject::isTemporal
bool isTemporal() const
Returns true if the object's temporal range is enabled, and the object will be filtered when renderin...
Definition: qgstemporalrangeobject.cpp:30
QgsLayoutItemMap::refresh
void refresh() override
Definition: qgslayoutitemmap.cpp:161
QgsLayoutMeasurement::setLength
void setLength(const double length)
Sets the length of the measurement.
Definition: qgslayoutmeasurement.h:54
QgsRectangle::center
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
QgsLayoutItemMap::extentChanged
void extentChanged()
Emitted when the map's extent changes.
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsLayoutRenderContext::predefinedScalesChanged
void predefinedScalesChanged()
Emitted when the list of predefined scales changes.
QgsAnnotation::render
void render(QgsRenderContext &context) const
Renders the annotation to a target render context.
Definition: qgsannotation.cpp:141
QgsLayoutItemMap::setFollowVisibilityPresetName
void setFollowVisibilityPresetName(const QString &name)
Sets preset name for map rendering.
Definition: qgslayoutitemmap.cpp:371
QgsTemporalRangeObject::setIsTemporal
void setIsTemporal(bool enabled)
Sets whether the temporal range is enabled (i.e.
Definition: qgstemporalrangeobject.cpp:25
QgsLayoutItemMap::layerStyleOverridesChanged
void layerStyleOverridesChanged()
Emitted when layer style overrides are changed...
QgsMapThemeCollection::mapThemeChanged
void mapThemeChanged(const QString &theme)
Emitted when a map theme changes definition.
QgsCoordinateReferenceSystem::description
QString description
Definition: qgscoordinatereferencesystem.h:218
QgsMapRendererStagedRenderJob::Finished
@ Finished
Rendering is finished.
Definition: qgsmaprendererstagedrenderjob.h:53
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsGeometry::fromPointXY
static QgsGeometry fromPointXY(const QgsPointXY &point) SIP_HOLDGIL
Creates a new geometry from a QgsPointXY object.
Definition: qgsgeometry.cpp:176
QgsLayoutItemRenderContext
Contains settings and helpers relating to a render of a QgsLayoutItem.
Definition: qgslayoutitem.h:44
QgsLayoutItem::attemptSetSceneRect
void attemptSetSceneRect(const QRectF &rect, bool includesFrame=false)
Attempts to update the item's position and size to match the passed rect in layout coordinates.
Definition: qgslayoutitem.cpp:511
QgsLayoutItemMap::~QgsLayoutItemMap
~QgsLayoutItemMap() override
Definition: qgslayoutitemmap.cpp:92
QgsMapLayerStyle::readFromLayer
void readFromLayer(QgsMapLayer *layer)
Store layer's active style information in the instance.
Definition: qgsmaplayerstyle.cpp:48
QgsLayoutItem::ExportLayerDetail::mapTheme
QString mapTheme
Associated map theme, or an empty string if this export layer does not need to be associated with a m...
Definition: qgslayoutitem.h:513
QgsLabelingResults
Class that stores computed placement from labeling engine.
Definition: qgslabelingresults.h:32
QgsLayoutItemMap::atlasDriven
bool atlasDriven() const
Returns whether the map extent is set to follow the current atlas feature.
Definition: qgslayoutitemmap.h:638
QgsLayoutItemMap::mapSettings
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings) const
Returns map settings that will be used for drawing of the map.
Definition: qgslayoutitemmap.cpp:1486
QgsLayoutObject::mDataDefinedProperties
QgsPropertyCollection mDataDefinedProperties
Definition: qgslayoutobject.h:365
QgsTemporalRangeObject::temporalRange
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
Definition: qgstemporalrangeobject.cpp:43
QgsRectangle::fromCenterAndSize
static QgsRectangle fromCenterAndSize(const QgsPointXY &center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
Definition: qgsrectangle.cpp:52
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
QgsLayoutItemMap::addRenderedFeatureHandler
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map.
Definition: qgslayoutitemmap.cpp:1816
QgsLayoutItemMapItem
An item which is drawn inside a QgsLayoutItemMap, e.g., a grid or map overview.
Definition: qgslayoutitemmapitem.h:33
QgsLayoutItemMap::AtlasScalingMode
AtlasScalingMode
Scaling modes used for the serial rendering (atlas)
Definition: qgslayoutitemmap.h:327
QgsStyleEntityVisitorInterface
An interface for classes which can visit style entity (e.g. symbol) nodes (using the visitor pattern)...
Definition: qgsstyleentityvisitor.h:33
QgsLayoutItemMap::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgslayoutitemmap.cpp:1668
QgsLayoutItem::refreshDataDefinedProperty
virtual void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
Definition: qgslayoutitem.cpp:1082
QgsStyleEntityVisitorInterface::visitExit
virtual bool visitExit(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor stops visiting a node.
Definition: qgsstyleentityvisitor.h:183
qgsprojoperation.h
QgsProjOperation::description
QString description() const
Description.
Definition: qgsprojoperation.h:61
QgsLayoutItemMap::isLabelBlockingItem
bool isLabelBlockingItem(QgsLayoutItem *item) const
Returns true if the specified item is a "label blocking item".
Definition: qgslayoutitemmap.cpp:1776
QgsLayoutItemMap::drawAnnotations
bool drawAnnotations() const
Returns whether annotations are drawn within the map.
Definition: qgslayoutitemmap.h:629
QgsLayout::refreshed
void refreshed()
Emitted when the layout has been refreshed and items should also be refreshed and updated.
QgsLayoutItemMap::storeCurrentLayerStyles
void storeCurrentLayerStyles()
Stores the current project layer styles into style overrides.
Definition: qgslayoutitemmap.cpp:346
FALLTHROUGH
#define FALLTHROUGH
Definition: qgis.h:2847
QgsMapSettings::setOutputDpi
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
Definition: qgsmapsettings.cpp:272
QgsLayoutItemMap::ShowPartialLabels
@ ShowPartialLabels
Whether to draw labels which are partially outside of the map view.
Definition: qgslayoutitemmap.h:353
QgsLayoutItemMap::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the map's preset crs (coordinate reference system).
Definition: qgslayoutitemmap.cpp:317
QgsLayoutItem::drawFrame
virtual void drawFrame(QgsRenderContext &context)
Draws the frame around the item.
Definition: qgslayoutitem.cpp:1221
QgsStyleEntityVisitorInterface::NodeType::LayoutItem
@ LayoutItem
Individual item in a print layout.
QgsCoordinateReferenceSystem::readXml
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
Definition: qgscoordinatereferencesystem.cpp:1860
QgsMapSettings::frameRate
double frameRate() const
Returns the frame rate of the map (in frames per second), for maps which are part of an animation.
Definition: qgsmapsettings.cpp:868
QgsLayoutItemMap::previewLabelingResults
QgsLabelingResults * previewLabelingResults() const
Returns the labeling results of the most recent preview map render.
Definition: qgslayoutitemmap.cpp:1781
QgsLayoutObject::changed
void changed()
Emitted when the object's properties change.
QgsGeometry::buffer
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
Definition: qgsgeometry.cpp:2050
QgsLayoutItemMap::preparedForAtlas
void preparedForAtlas()
Emitted when the map has been prepared for atlas rendering, just before actual rendering.
QgsLayoutRenderContext::FlagDisableTiledRasterLayerRenders
@ FlagDisableTiledRasterLayerRenders
If set, then raster layers will not be drawn as separate tiles. This may improve the appearance in ex...
Definition: qgslayoutrendercontext.h:53
QgsLayoutItem::ExportLayerDetail::compositionMode
QPainter::CompositionMode compositionMode
Associated composition mode if this layer is associated with a map layer.
Definition: qgslayoutitem.h:504
QgsLayoutObject::MapXMin
@ MapXMin
Map extent x minimum.
Definition: qgslayoutobject.h:159
QgsLayoutItemMap::setFrameStrokeWidth
void setFrameStrokeWidth(QgsLayoutMeasurement width) override
Sets the frame stroke width.
Definition: qgslayoutitemmap.cpp:1331
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsLayoutItemMapItemClipPathSettings
Contains settings relating to clipping a layout map by another layout item.
Definition: qgslayoutitemmap.h:169
QgsLayoutItem::backgroundTaskCountChanged
void backgroundTaskCountChanged(int count)
Emitted whenever the number of background tasks an item is executing changes.
Qgis::MapSettingsFlag::Antialiasing
@ Antialiasing
Enable anti-aliasing for map rendering.
QgsLayoutItemMap::itemFlags
QgsLayoutItem::Flags itemFlags() const override
Returns the item's flags, which indicate how the item behaves.
Definition: qgslayoutitemmap.cpp:113
qgsDoubleToString
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2204
QgsProject
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition: qgsproject.h:103
QgsLayoutItemMap::previewRefreshed
void previewRefreshed()
Emitted whenever the item's map preview has been refreshed.
QgsLayoutMeasurement::encodeMeasurement
QString encodeMeasurement() const
Encodes the layout measurement to a string.
Definition: qgslayoutmeasurement.cpp:28
QgsLayoutItemMap::nextExportPart
bool nextExportPart() override
Moves to the next export part for a multi-layered export item, during a multi-layered export.
Definition: qgslayoutitemmap.cpp:1121
QgsLayerTree::layerOrderChanged
void layerOrderChanged()
Emitted when the layer order has changed.
QgsRenderedFeatureHandlerInterface
An interface for classes which provider custom handlers for features rendered as part of a map render...
Definition: qgsrenderedfeaturehandlerinterface.h:46
QgsGeometry::intersection
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
Definition: qgsgeometry.cpp:2616
QgsLayoutItemMap::paint
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
Definition: qgslayoutitemmap.cpp:891
QgsLayoutObject::MapCrs
@ MapCrs
Map CRS.
Definition: qgslayoutobject.h:210
qgsmaplayerlistutils_p.h
qgslabelingresults.h
QgsMapSettings::extent
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
Definition: qgsmapsettings.cpp:75
QgsLayoutItemMapItemClipPathSettings::readXml
bool readXml(const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context)
Sets the setting's state from a DOM document, where element is the DOM node corresponding to a 'Layou...
Definition: qgslayoutitemmap.cpp:3093
QgsLayoutItemMap::mapRotation
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
Definition: qgslayoutitemmap.cpp:521
qgsapplication.h
QgsLayoutObject::MapYMin
@ MapYMin
Map extent y minimum.
Definition: qgslayoutobject.h:160
qgslayoututils.h
QgsMapSettings::setTextRenderFormat
void setTextRenderFormat(Qgis::TextRenderFormat format)
Sets the text render format, which dictates how text is rendered (e.g.
Definition: qgsmapsettings.h:433
QgsUnitTypes::LayoutInches
@ LayoutInches
Inches.
Definition: qgsunittypes.h:186
QgsLayoutItemMap::atlasMargin
double atlasMargin(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue)
Returns the margin size (percentage) used when the map is in atlas mode.
Definition: qgslayoutitemmap.cpp:539
QgsLayoutItem::drawBackground
virtual void drawBackground(QgsRenderContext &context)
Draws the background for the item.
Definition: qgslayoutitem.cpp:1237
QgsLayoutItemMap::exportLayerDetails
QgsLayoutItem::ExportLayerDetail exportLayerDetails() const override
Returns the details for the specified current export layer.
Definition: qgslayoutitemmap.cpp:1209
QgsLayoutItemMapItemClipPathSettings::clippedMapExtent
QgsGeometry clippedMapExtent() const
Returns the geometry to use for clipping the parent map, in the map item's CRS.
Definition: qgslayoutitemmap.cpp:2979
Qgis::RendererUsage::Export
@ Export
Renderer used for printing or exporting to a file.
QgsLayoutItem::containsAdvancedEffects
virtual bool containsAdvancedEffects() const
Returns true if the item contains contents with blend modes or transparency effects which can only be...
Definition: qgslayoutitem.cpp:926
_LayerRef::layerId
QString layerId
Original layer ID.
Definition: qgsmaplayerref.h:117
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:2820
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsProject::crsChanged
void crsChanged()
Emitted when the CRS of the project has changed.
QgsMapSettings::addRenderedFeatureHandler
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map settings.
Definition: qgsmapsettings.cpp:838
QgsLayoutItem::hasBackground
bool hasBackground() const
Returns true if the item has a background.
Definition: qgslayoutitem.h:802
QgsRectangle::scale
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
Definition: qgsrectangle.h:256
QgsLayoutItemMap::requiresRasterization
bool requiresRasterization() const override
Returns true if the item is drawn in such a way that forces the whole layout to be rasterized when ex...
Definition: qgslayoutitemmap.cpp:470
QgsVectorTileUtils::scaleToZoomLevel
static int scaleToZoomLevel(double mapScale, int sourceMinZoom, int sourceMaxZoom, double z0Scale=559082264.0287178)
Finds the best fitting zoom level given a map scale denominator and allowed zoom level range.
Definition: qgsvectortileutils.cpp:71
QgsLayoutObject::AllProperties
@ AllProperties
All properties for item.
Definition: qgslayoutobject.h:135
QgsLayoutItemMapAtlasClippingSettings::readXml
bool readXml(const QDomElement &element, const QDomDocument &doc, const QgsReadWriteContext &context)
Sets the setting's state from a DOM document, where element is the DOM node corresponding to a 'Layou...
Definition: qgslayoutitemmap.cpp:2903
Qgis::MapSettingsFlag::DrawEditingInfo
@ DrawEditingInfo
Enable drawing of vertex markers for layers in editing mode.
QgsLayoutItem::framePath
virtual QPainterPath framePath() const
Returns the path to use when drawing the item's frame or background.
Definition: qgslayoutitem.cpp:1214
QgsLayoutItemMap::type
int type() const override
Definition: qgslayoutitemmap.cpp:103
QgsProject::layerTreeRoot
QgsLayerTree * layerTreeRoot() const
Returns pointer to the root (invisible) node of the project's layer tree.
Definition: qgsproject.cpp:3541
QgsGeometry::asQPolygonF
QPolygonF asQPolygonF() const SIP_HOLDGIL
Returns contents of the geometry as a QPolygonF.
Definition: qgsgeometry.cpp:2785
QgsLayoutItemMapItemClipPathSettings::writeXml
bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores settings in a DOM element, where element is the DOM element corresponding to a 'LayoutMap' tag...
Definition: qgslayoutitemmap.cpp:3078
qgsexpressioncontext.h
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsMapRendererCustomPainterJob::cancelWithoutBlocking
void cancelWithoutBlocking() override
Triggers cancellation of the rendering job without blocking.
Definition: qgsmaprenderercustompainterjob.cpp:170
QgsLayoutItemMap::layoutToMapCoordsTransform
QTransform layoutToMapCoordsTransform() const
Creates a transform from layout coordinates to map coordinates.
Definition: qgslayoutitemmap.cpp:2077
QgsAnnotation
Abstract base class for annotation items which are drawn over a map.
Definition: qgsannotation.h:53
QgsMapSettings::setBackgroundColor
void setBackgroundColor(const QColor &color)
Sets the background color of the map.
Definition: qgsmapsettings.h:381
QgsLayoutItem::backgroundColor
QColor backgroundColor() const
Returns the background color for this item.
Definition: qgslayoutitem.h:817
QgsLayoutItem::ExportLayerDetail
Contains details of a particular export layer relating to a layout item.
Definition: qgslayoutitem.h:492
Qgis::MapSettingsFlag::ForceRasterMasks
@ ForceRasterMasks
Force symbol masking to be applied using a raster method. This is considerably faster when compared t...
QgsScaleCalculator
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
Definition: qgsscalecalculator.h:34
QgsLayoutItemMap::layers
QList< QgsMapLayer * > layers() const
Returns the stored layer set.
Definition: qgslayoutitemmap.cpp:326
QgsLayoutItem::ExportLayerDetail::name
QString name
User-friendly name for the export layer.
Definition: qgslayoutitem.h:495
qgsmapsettingsutils.h
QgsLayoutItem::ExportLayerBehavior
ExportLayerBehavior
Behavior of item when exporting to layered outputs.
Definition: qgslayoutitem.h:429
QgsLayoutItemMapAtlasClippingSettings::forceLabelsInsideFeature
bool forceLabelsInsideFeature() const
Returns true if labels should only be placed inside the atlas feature geometry.
Definition: qgslayoutitemmap.cpp:2834
QgsCoordinateReferenceSystem::writeXml
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Definition: qgscoordinatereferencesystem.cpp:1980
_LayerRef::provider
QString provider
Weak reference to layer provider.
Definition: qgsmaplayerref.h:124
QgsLayoutItemMap::QgsLayoutItemMap
QgsLayoutItemMap(QgsLayout *layout)
Constructor for QgsLayoutItemMap, with the specified parent layout.
Definition: qgslayoutitemmap.cpp:46
QgsLabelingEngineSettings
Stores global configuration for labeling engine.
Definition: qgslabelingenginesettings.h:31
QgsLayoutObject::MapRotation
@ MapRotation
Map rotation.
Definition: qgslayoutobject.h:157
QgsUnitTypes::toString
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
Definition: qgsunittypes.cpp:199
QgsLayoutItem::requiresRasterization
virtual bool requiresRasterization() const
Returns true if the item is drawn in such a way that forces the whole layout to be rasterized when ex...
Definition: qgslayoutitem.cpp:931
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsLayoutObject::MapXMax
@ MapXMax
Map extent x maximum.
Definition: qgslayoutobject.h:161
QgsMapRendererStagedRenderJob::Labels
@ Labels
Rendering labels.
Definition: qgsmaprendererstagedrenderjob.h:52
QgsLayoutObject::MapYMax
@ MapYMax
Map extent y maximum.
Definition: qgslayoutobject.h:162
QgsLayoutItemMap::overview
QgsLayoutItemMapOverview * overview()
Returns the map item's first overview.
Definition: qgslayoutitemmap.cpp:574
QgsMapClippingRegion::setRestrictedLayers
void setRestrictedLayers(const QList< QgsMapLayer * > &layers)
Sets a list of layers to restrict the clipping region effects to.
Definition: qgsmapclippingregion.cpp:30
QgsApplication::coordinateReferenceSystemRegistry
static QgsCoordinateReferenceSystemRegistry * coordinateReferenceSystemRegistry()
Returns the application's coordinate reference system (CRS) registry, which handles known CRS definit...
Definition: qgsapplication.cpp:2355
QgsLayoutMeasurement::units
QgsUnitTypes::LayoutUnit units() const
Returns the units for the measurement.
Definition: qgslayoutmeasurement.h:60
QgsLayoutItem::FlagOverridesPaint
@ FlagOverridesPaint
Item overrides the default layout item painting method.
Definition: qgslayoutitem.h:305
QgsProject::projectColorsChanged
void projectColorsChanged()
Emitted whenever the project's color scheme has been changed.
QgsLayoutItemMap::setMoveContentPreviewOffset
void setMoveContentPreviewOffset(double dx, double dy) override
Sets temporary offset for the item, by a specified dx and dy in layout units.
Definition: qgslayoutitemmap.cpp:1657
QgsMapSettings::visiblePolygon
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
Definition: qgsmapsettings.cpp:416
QgsGeometry::rotate
Qgis::GeometryOperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
Definition: qgsgeometry.cpp:910
QgsLayoutItemMap::zoomToExtent
void zoomToExtent(const QgsRectangle &extent)
Zooms the map so that the specified extent is fully visible within the map item.
Definition: qgslayoutitemmap.cpp:237
_LayerRef::name
QString name
Weak reference to layer name.
Definition: qgsmaplayerref.h:122
QgsCoordinateReferenceSystem::toWkt
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Definition: qgscoordinatereferencesystem.cpp:1810
QgsLayoutItemMap::extent
QgsRectangle extent() const
Returns the current map extent.
Definition: qgslayoutitemmap.cpp:281
QgsLayoutItemMapItemClipPathSettings::QgsLayoutItemMapItemClipPathSettings
QgsLayoutItemMapItemClipPathSettings(QgsLayoutItemMap *map=nullptr)
Constructor for QgsLayoutItemMapItemClipPathSettings, with the specified map parent.
Definition: qgslayoutitemmap.cpp:2948
QgsMapSettings::setSelectionColor
void setSelectionColor(const QColor &color)
Sets the color that is used for drawing of selected vector features.
Definition: qgsmapsettings.h:395
Qgis::MapSettingsFlag::ForceVectorOutput
@ ForceVectorOutput
Vector graphics should not be cached and drawn as raster images.
QgsMapSettings::setSimplifyMethod
void setSimplifyMethod(const QgsVectorSimplifyMethod &method)
Sets the simplification setting to use when rendering vector layers.
Definition: qgsmapsettings.h:759
QgsRectangle::setXMinimum
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
QgsLayoutItemMapItemClipPathSettings::toMapClippingRegion
QgsMapClippingRegion toMapClippingRegion() const
Returns the clip path as a map clipping region.
Definition: qgslayoutitemmap.cpp:3001
QgsLayoutItemMap::invalidateCache
void invalidateCache() override
Definition: qgslayoutitemmap.cpp:1868
QgsLayoutItemMap::Fixed
@ Fixed
The current scale of the map is used for each feature of the atlas.
Definition: qgslayoutitemmap.h:329
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
QgsLayoutItemMapItemClipPathSettings::sourceItem
QgsLayoutItem * sourceItem()
Returns the source item which will provide the clipping path for the map, or nullptr if no item is se...
Definition: qgslayoutitemmap.cpp:3045
QgsLayoutItemMap::create
static QgsLayoutItemMap * create(QgsLayout *layout)
Returns a new map item for the specified layout.
Definition: qgslayoutitemmap.cpp:156
QgsLayoutItemMapAtlasClippingSettings::restrictToLayers
bool restrictToLayers() const
Returns true if clipping should be restricted to a subset of layers.
Definition: qgslayoutitemmap.cpp:2848
QgsLayoutItemMapAtlasClippingSettings::setEnabled
void setEnabled(bool enabled)
Sets whether the map content should be clipped to the current atlas feature.
Definition: qgslayoutitemmap.cpp:2811
QgsMapLayer::id
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
Definition: qgsmaplayer.cpp:169
QgsLayoutItemMap::layersToRender
QList< QgsMapLayer * > layersToRender(const QgsExpressionContext *context=nullptr) const
Returns a list of the layers which will be rendered within this map item, considering any locked laye...
Definition: qgslayoutitemmap.cpp:2152
QgsAnnotation::isVisible
bool isVisible() const
Returns true if the annotation is visible and should be rendered.
Definition: qgsannotation.h:95
QgsLayoutItemMapItemClipPathSettings::setSourceItem
void setSourceItem(QgsLayoutItem *item)
Sets the source item which will provide the clipping path for the map.
Definition: qgslayoutitemmap.cpp:3008
QgsGeometry::isEmpty
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Definition: qgsgeometry.cpp:379
QgsLayoutItem::ItemContainsSubLayers
@ ItemContainsSubLayers
Item contains multiple sublayers which must be individually exported.
Definition: qgslayoutitem.h:434
QgsMapSettingsUtils::containsAdvancedEffects
static QStringList containsAdvancedEffects(const QgsMapSettings &mapSettings, EffectsCheckFlags flags=QgsMapSettingsUtils::EffectsCheckFlags())
Checks whether any of the layers attached to a map settings object contain advanced effects.
Definition: qgsmapsettingsutils.cpp:27
QgsGeometry::isNull
bool isNull
Definition: qgsgeometry.h:127
QgsWeakMapLayerPointer
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:2146
qgsannotationmanager.h
QgsLayoutItemMapAtlasClippingSettings::layersToClip
QList< QgsMapLayer * > layersToClip() const
Returns the list of map layers to clip to the atlas feature.
Definition: qgslayoutitemmap.cpp:2862
QgsProject::mapThemeCollection
QgsMapThemeCollection mapThemeCollection
Definition: qgsproject.h:112
QgsLayoutItemMap::boundingRect
QRectF boundingRect() const override
Definition: qgslayoutitemmap.cpp:1663
QgsStyleEntityVisitorInterface::Node
Contains information relating to a node (i.e.
Definition: qgsstyleentityvisitor.h:110
QgsLayoutItem
Base class for graphical items within a QgsLayout.
Definition: qgslayoutitem.h:112
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsMapSettings::setTransformContext
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
Definition: qgsmapsettings.cpp:473
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsAnnotation::hasFixedMapPosition
bool hasFixedMapPosition
Definition: qgsannotation.h:72
QgsLayoutUtils::createRenderContextForMap
static QgsRenderContext createRenderContextForMap(QgsLayoutItemMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout map and painter destination.
Definition: qgslayoututils.cpp:97
qgsannotationlayer.h
QgsCoordinateReferenceSystem::toProj
QString toProj() const
Returns a Proj string representation of this CRS.
Definition: qgscoordinatereferencesystem.cpp:1293
QgsLayoutItemMapAtlasClippingSettings::writeXml
bool writeXml(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const
Stores settings in a DOM element, where element is the DOM element corresponding to a 'LayoutMap' tag...
Definition: qgslayoutitemmap.cpp:2873
QgsLayoutItem::ExportLayerDetail::opacity
double opacity
Associated opacity, if this layer is associated with a map layer.
Definition: qgslayoutitem.h:510
qgslayertree.h
QgsLayoutItemMap::requestedExtent
QgsRectangle requestedExtent() const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
Definition: qgslayoutitemmap.cpp:1847
QgsMapClippingRegion::FeatureClippingType
FeatureClippingType
Feature clipping behavior, which controls how features from vector layers will be clipped.
Definition: qgsmapclippingregion.h:41
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsLayoutItemMap::setMapFlags
void setMapFlags(QgsLayoutItemMap::MapItemFlags flags)
Sets the map item's flags, which control how the map content is drawn.
Definition: qgslayoutitemmap.cpp:1481
QgsCoordinateReferenceSystem::operation
QgsProjOperation operation() const
Returns information about the PROJ operation associated with the coordinate reference system,...
Definition: qgscoordinatereferencesystem.cpp:1440
qgslayout.h
Qgis::MapSettingsFlag::HighQualityImageTransforms
@ HighQualityImageTransforms
Enable high quality image transformations, which results in better appearance of scaled or rotated ra...
QgsLayoutObject::MapScale
@ MapScale
Map scale.
Definition: qgslayoutobject.h:158
QgsLayoutItem::rotationChanged
void rotationChanged(double newRotation)
Emitted on item rotation change.
QgsLayoutItemMap::crs
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
Definition: qgslayoutitemmap.cpp:308
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsRectangle::setXMaximum
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
QgsLayoutItemMap::mapUnitsToLayoutUnits
double mapUnitsToLayoutUnits() const
Returns the conversion factor from map units to layout units.
Definition: qgslayoutitemmap.cpp:1741
QgsMapClippingRegion::setRestrictToLayers
void setRestrictToLayers(bool enabled)
Sets whether clipping should be restricted to a subset of layers.
Definition: qgsmapclippingregion.cpp:60
QgsLayoutObject::MapLabelMargin
@ MapLabelMargin
Map label margin.
Definition: qgslayoutobject.h:166
QgsExpressionContextScope
Single scope for storing variables and functions for use within a QgsExpressionContext....
Definition: qgsexpressioncontext.h:113
QgsMapRendererStagedRenderJob::RenderLabelsByMapLayer
@ RenderLabelsByMapLayer
Labels should be rendered in individual stages by map layer. This allows separation of labels belongi...
Definition: qgsmaprendererstagedrenderjob.h:42
QgsMapSettings::setLabelingEngineSettings
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets the global configuration of the labeling engine.
Definition: qgsmapsettings.h:654
QgsLayoutItemMapItemClipPathSettings::finalizeRestoreFromXml
void finalizeRestoreFromXml()
To be called after all pending items have been restored from XML.
Definition: qgslayoutitemmap.cpp:3105
QgsAbstractPropertyCollection::valueAsString
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string.
Definition: qgspropertycollection.cpp:42
QgsMapSettings::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
Definition: qgsmapsettings.cpp:327
QgsAbstractPropertyCollection::valueAsDateTime
QDateTime valueAsDateTime(int key, const QgsExpressionContext &context, const QDateTime &defaultDateTime=QDateTime(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a datetime.
Definition: qgspropertycollection.cpp:30
QgsExpressionContext::appendScope
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Definition: qgsexpressioncontext.cpp:494
QgsLayoutItem::refresh
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
Definition: qgslayoutitem.cpp:1177
QgsLayoutItemMapItemClipPathSettings::isActive
bool isActive() const
Returns true if the item clipping is enabled and set to a valid source item.
Definition: qgslayoutitemmap.cpp:2954
qgsvectorlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsLayoutItemMap::transformedMapPolygon
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
Definition: qgslayoutitemmap.cpp:1751
QgsLayoutItemMapOverview
An individual overview which is drawn above the map content in a QgsLayoutItemMap,...
Definition: qgslayoutitemmapoverview.h:126
QgsStyleEntityVisitorInterface::visitEnter
virtual bool visitEnter(const QgsStyleEntityVisitorInterface::Node &node)
Called when the visitor starts visiting a node.
Definition: qgsstyleentityvisitor.h:169
QgsLayoutItemMap::setLayerStyleOverrides
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the stored overrides of styles for layers.
Definition: qgslayoutitemmap.cpp:336
QgsLayoutObject::MapAtlasMargin
@ MapAtlasMargin
Map atlas margin.
Definition: qgslayoutobject.h:163
QgsRenderContext::setForceVectorOutput
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
Definition: qgsrendercontext.cpp:330
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Definition: qgsmapsettings.cpp:358
QgsMapRendererCustomPainterJob
Job implementation that renders everything sequentially using a custom painter.
Definition: qgsmaprenderercustompainterjob.h:63
QgsLayoutItemMap
Layout graphical items for displaying a map.
Definition: qgslayoutitemmap.h:317
QgsRectangle::setYMaximum
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
QgsLayoutItemMap::crsChanged
void crsChanged()
Emitted when the map's coordinate reference system is changed.
QgsLayoutItemMap::mapFlags
QgsLayoutItemMap::MapItemFlags mapFlags() const
Returns the map item's flags, which control how the map content is drawn.
Definition: qgslayoutitemmap.cpp:1476
QgsMapSettings::setDpiTarget
void setDpiTarget(double dpi)
Sets the target dpi (dots per inch) to be taken into consideration when rendering.
Definition: qgsmapsettings.cpp:284
QgsLayoutItemMap::stopLayeredExport
void stopLayeredExport() override
Stops a multi-layer export operation.
Definition: qgslayoutitemmap.cpp:1114
QgsLabelingEngineSettings::setFlag
void setFlag(Flag f, bool enabled=true)
Sets whether a particual flag is enabled.
Definition: qgslabelingenginesettings.h:86
QgsLayoutRenderContext::FlagLosslessImageRendering
@ FlagLosslessImageRendering
Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some...
Definition: qgslayoutrendercontext.h:55
QgsLayoutItemMap::displayName
QString displayName() const override
Gets item display name.
Definition: qgslayoutitemmap.cpp:146
QgsMapSettings::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsmapsettings.h:479
QgsLayoutItemMap::QgsLayoutItemMapOverview
friend class QgsLayoutItemMapOverview
Definition: qgslayoutitemmap.h:1189
QgsLayoutItemMap::labelMargin
QgsLayoutMeasurement labelMargin() const
Returns the margin from the map edges in which no labels may be placed.
Definition: qgslayoutitemmap.cpp:2121
QgsLayoutItemMap::setLabelMargin
void setLabelMargin(const QgsLayoutMeasurement &margin)
Sets the margin from the map edges in which no labels may be placed.
Definition: qgslayoutitemmap.cpp:2126
QgsLayoutItem::uuid
virtual QString uuid() const
Returns the item identification string.
Definition: qgslayoutitem.h:345
QgsWkbTypes::PointGeometry
@ PointGeometry
Definition: qgswkbtypes.h:142
qgslayoutrendercontext.h
QgsLayoutItemMap::Predefined
@ Predefined
A scale is chosen from the predefined scales.
Definition: qgslayoutitemmap.h:337
QgsLayoutItemMapItem::stackingPosition
StackingPosition stackingPosition() const
Returns the item's stacking position, which specifies where the in the map's stack the item should be...
Definition: qgslayoutitemmapitem.h:140
QgsLayoutItemMap::themeChanged
void themeChanged(const QString &theme)
Emitted when the map's associated theme is changed.
QgsCoordinateReferenceSystem::mapUnits
QgsUnitTypes::DistanceUnit mapUnits
Definition: qgscoordinatereferencesystem.h:215
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsLayoutUtils::rotate
static void rotate(double angle, double &x, double &y)
Rotates a point / vector around the origin.
Definition: qgslayoututils.cpp:33
QgsMapSettings::addClippingRegion
void addClippingRegion(const QgsMapClippingRegion &region)
Adds a new clipping region to the map settings.
Definition: qgsmapsettings.cpp:823
QgsLayoutObject::mLayout
QPointer< QgsLayout > mLayout
Definition: qgslayoutobject.h:363
QgsRectangle::setYMinimum
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
qgslayoutreportcontext.h
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsLayoutItemMapItemClipPathSettings::changed
void changed()
Emitted when the item clipping settings are changed.
QgsLayoutItemMapItem::StackAboveMapLabels
@ StackAboveMapLabels
Render above all map layers and labels.
Definition: qgslayoutitemmapitem.h:46
QgsLabelingEngineSettings::UsePartialCandidates
@ UsePartialCandidates
Whether to use also label candidates that are partially outside of the map view.
Definition: qgslabelingenginesettings.h:38
QgsLayout
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:50
QgsMapSettings::setLayerStyleOverrides
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the map of map layer style overrides (key: layer ID, value: style name) where a different style ...
Definition: qgsmapsettings.cpp:345
_LayerRef::source
QString source
Weak reference to layer public source.
Definition: qgsmaplayerref.h:120
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
QgsLayoutItemMap::mapRotationChanged
void mapRotationChanged(double newRotation)
Emitted when the map's rotation changes.
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsLayoutItemMapItemClipPathSettings::setEnabled
void setEnabled(bool enabled)
Sets whether the map content should be clipped to the associated item.
Definition: qgslayoutitemmap.cpp:2964
QgsLayoutItemMap::setMapRotation
void setMapRotation(double rotation)
Sets the rotation for the map - this does not affect the layout item shape, only the way the map is d...
Definition: qgslayoutitemmap.cpp:512
QgsLayoutItemMapItemClipPathSettings::clipPathInMapItemCoordinates
QgsGeometry clipPathInMapItemCoordinates() const
Returns the clipping path geometry, in the map item's coordinate space.
Definition: qgslayoutitemmap.cpp:2990
QgsLayoutItemMap::containsWmsLayer
bool containsWmsLayer() const
Returns true if the map contains a WMS layer.
Definition: qgslayoutitemmap.cpp:457
QgsLayoutItemMapAtlasClippingSettings::enabled
bool enabled() const
Returns true if the map content should be clipped to the current atlas feature.
Definition: qgslayoutitemmap.cpp:2806
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsLayoutItemMap::removeRenderedFeatureHandler
void removeRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Removes a previously added rendered feature handler.
Definition: qgslayoutitemmap.cpp:1821
QgsLayoutItemMap::icon
QIcon icon() const override
Returns the item's icon.
Definition: qgslayoutitemmap.cpp:108
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:241
QgsLayoutItemRegistry::LayoutMap
@ LayoutMap
Map item.
Definition: qgslayoutitemregistry.h:347
Qgis::MapSettingsFlag::DrawSelection
@ DrawSelection
Whether vector selections should be shown in the rendered map.
QgsLayoutItemMap::scale
double scale() const
Returns the map scale.
Definition: qgslayoutitemmap.cpp:172
QgsLayoutItemMapItemClipPathSettings::setForceLabelsInsideClipPath
void setForceLabelsInsideClipPath(bool forceInside)
Sets whether labels should only be placed inside the clip path geometry.
Definition: qgslayoutitemmap.cpp:3069
QgsLayoutItemMap::setScale
void setScale(double scale, bool forceUpdate=true)
Sets new map scale and changes only the map extent.
Definition: qgslayoutitemmap.cpp:184
QgsLayoutItemMapAtlasClippingSettings::featureClippingType
QgsMapClippingRegion::FeatureClippingType featureClippingType() const
Returns the feature clipping type to apply when clipping to the current atlas feature.
Definition: qgslayoutitemmap.cpp:2820
QgsLayoutItemMap::setFollowVisibilityPreset
void setFollowVisibilityPreset(bool follow)
Sets whether the map should follow a map theme.
Definition: qgslayoutitemmap.cpp:360
QgsMapLayerStyle::xmlData
QString xmlData() const
Returns XML content of the style.
Definition: qgsmaplayerstyle.cpp:43
QgsMapLayer::name
QString name
Definition: qgsmaplayer.h:76
QgsLayoutRenderContext::FlagDrawSelection
@ FlagDrawSelection
Draw selection.
Definition: qgslayoutrendercontext.h:52
QgsLayoutItemMapItemClipPathSettings::enabled
bool enabled() const
Returns true if the map content should be clipped to the associated item.
Definition: qgslayoutitemmap.cpp:2959
QgsAnnotation::relativePosition
QPointF relativePosition() const
Returns the relative position of the annotation, if it is not attached to a fixed map position.
Definition: qgsannotation.h:155
QgsLayoutObject::PropertyValueType
PropertyValueType
Specifies whether the value returned by a function should be the original, user set value,...
Definition: qgslayoutobject.h:220
QgsWkbTypes::geometryType
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:968
QgsVectorTileUtils::scaleToZoom
static double scaleToZoom(double mapScale, double z0Scale=559082264.0287178)
Finds zoom level given map scale denominator.
Definition: qgsvectortileutils.cpp:63
QgsLayoutItemMap::refreshDataDefinedProperty
void refreshDataDefinedProperty(QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
Definition: qgslayoutitemmap.cpp:1906
QgsCoordinateReferenceSystem::authid
QString authid
Definition: qgscoordinatereferencesystem.h:217
QgsLayoutRenderContext::FlagForceVectorOutput
@ FlagForceVectorOutput
Force output in vector format where possible, even if items require rasterization to keep their corre...
Definition: qgslayoutrendercontext.h:50
QgsTemporalRangeObject::setTemporalRange
void setTemporalRange(const QgsDateTimeRange &range)
Sets the temporal range for the object.
Definition: qgstemporalrangeobject.cpp:35
QgsRenderContext::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsrendercontext.h:617
qgsmaplayerref.h
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
QgsAnnotation::mapPositionCrs
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:141
QgsLayoutItemMap::moveContent
void moveContent(double dx, double dy) override
Moves the content of the item, by a specified dx and dy in layout units.
Definition: qgslayoutitemmap.cpp:381
QgsLayoutItemMap::containsAdvancedEffects
bool containsAdvancedEffects() const override
Returns true if the item contains contents with blend modes or transparency effects which can only be...
Definition: qgslayoutitemmap.cpp:488
QgsMapSettings::setLabelBlockingRegions
void setLabelBlockingRegions(const QList< QgsLabelBlockingRegion > &regions)
Sets a list of regions to avoid placing labels within.
Definition: qgsmapsettings.h:703
QgsCoordinateReferenceSystem::ellipsoidAcronym
QString ellipsoidAcronym() const
Returns the ellipsoid acronym for the ellipsoid used by the CRS.
Definition: qgscoordinatereferencesystem.cpp:1251
QgsLabelBlockingRegion
Label blocking region (in map coordinates and CRS).
Definition: qgsmapsettings.h:54
QgsGeometry::fromQPolygonF
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
Definition: qgsgeometry.cpp:3408
_LayerRef< QgsMapLayer >
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsLayoutItemMapAtlasClippingSettings::QgsLayoutItemMapAtlasClippingSettings
QgsLayoutItemMapAtlasClippingSettings(QgsLayoutItemMap *map=nullptr)
Constructor for QgsLayoutItemMapAtlasClippingSettings, with the specified map parent.
Definition: qgslayoutitemmap.cpp:2795
QgsUnitTypes::LayoutMillimeters
@ LayoutMillimeters
Millimeters.
Definition: qgsunittypes.h:183
QgsMapLayerStyle
Stores style information (renderer, opacity, labeling, diagrams etc.) applicable to a map layer.
Definition: qgsmaplayerstyle.h:42
QgsLayoutItemMap::accept
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Definition: qgslayoutitemmap.cpp:1786
QgsMapSettings::setOutputSize
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
Definition: qgsmapsettings.cpp:244
QgsLayout::project
QgsProject * project() const
The project associated with the layout.
Definition: qgslayout.cpp:132
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsLayoutItemMap::finalizeRestoreFromXml
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
Definition: qgslayoutitemmap.cpp:1638
qgsvectortileutils.h
QgsExpressionContextScope::StaticVariable
Single variable definition for use within a QgsExpressionContextScope.
Definition: qgsexpressioncontext.h:120
QgsLayoutObject::EndDateTime
@ EndDateTime
Temporal range's end DateTime.
Definition: qgslayoutobject.h:212
QgsMapSettings::setPathResolver
void setPathResolver(const QgsPathResolver &resolver)
Sets the path resolver for conversion between relative and absolute paths during rendering operations...
Definition: qgsmapsettings.h:525
Qgis::RendererUsage::View
@ View
Renderer used for displaying on screen.
QgsMapSettings
The QgsMapSettings class contains configuration for rendering of the map. The rendering itself is don...
Definition: qgsmapsettings.h:88
QgsLayoutRenderContext::FlagAntialiasing
@ FlagAntialiasing
Use antialiasing when drawing items.
Definition: qgslayoutrendercontext.h:48
QgsLayoutItem::ExportLayerDetail::mapLayerId
QString mapLayerId
Associated map layer ID, or an empty string if this export layer is not associated with a map layer.
Definition: qgslayoutitem.h:498
QgsCoordinateReferenceSystem::updateDefinition
void updateDefinition()
Updates the definition and parameters of the coordinate reference system to their latest values.
Definition: qgscoordinatereferencesystem.cpp:1498
QgsLayoutObject::MapStylePreset
@ MapStylePreset
Layer and style map theme.
Definition: qgslayoutobject.h:165
QgsMapClippingRegion::setFeatureClip
void setFeatureClip(FeatureClippingType type)
Sets the feature clipping type.
Definition: qgsmapclippingregion.h:88
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsLayoutItemMapAtlasClippingSettings::changed
void changed()
Emitted when the atlas clipping settings are changed.
QgsLayoutItemMap::setAtlasDriven
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
Definition: qgslayoutitemmap.cpp:527
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:2819
QgsMapSettings::setExtent
void setExtent(const QgsRectangle &rect, bool magnified=true)
Sets the coordinates of the rectangle which should be rendered.
Definition: qgsmapsettings.cpp:80
QgsLayoutItemMapAtlasClippingSettings::setForceLabelsInsideFeature
void setForceLabelsInsideFeature(bool forceInside)
Sets whether labels should only be placed inside the atlas feature geometry.
Definition: qgslayoutitemmap.cpp:2839
QgsLayoutUtils::scaleFactorFromItemStyle
static Q_DECL_DEPRECATED double scaleFactorFromItemStyle(const QStyleOptionGraphicsItem *style)
Extracts the scale factor from an item style.
Definition: qgslayoututils.cpp:399
QgsMapLayerStyle::writeXml
void writeXml(QDomElement &styleElement) const
Write style configuration (for project file writing)
Definition: qgsmaplayerstyle.cpp:93
QgsMapSettings::currentFrame
long long currentFrame() const
Returns the current frame number of the map, for maps which are part of an animation.
Definition: qgsmapsettings.cpp:878
QgsLayoutItemMap::setExtent
void setExtent(const QgsRectangle &extent)
Sets a new extent for the map.
Definition: qgslayoutitemmap.cpp:217
QgsMapSettings::setRendererUsage
void setRendererUsage(Qgis::RendererUsage rendererUsage)
Sets the rendering usage.
Definition: qgsmapsettings.cpp:863
QgsLayoutObject::EvaluatedValue
@ EvaluatedValue
Return the current evaluated value for the property.
Definition: qgslayoutobject.h:222
QgsLayoutItemMapAtlasClippingSettings::setRestrictToLayers
void setRestrictToLayers(bool enabled)
Sets whether clipping should be restricted to a subset of layers.
Definition: qgslayoutitemmap.cpp:2853
qgscoordinatereferencesystemregistry.h
QgsLayoutItem::createExpressionContext
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgslayoutitem.cpp:1159
qgslayoutmodel.h
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
Qgis::MapSettingsFlag::LosslessImageRendering
@ LosslessImageRendering
Render images losslessly whenever possible, instead of the default lossy jpeg rendering used for some...
QgsLayoutItemMapItem::enabled
bool enabled() const
Returns whether the item will be drawn.
Definition: qgslayoutitemmapitem.cpp:104
QgsLayoutItemMap::ShowUnplacedLabels
@ ShowUnplacedLabels
Whether to render unplaced labels in the map view.
Definition: qgslayoutitemmap.h:354
QgsMapSettings::setEllipsoid
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
Definition: qgsmapsettings.cpp:363
QgsLayoutMeasurement
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
Definition: qgslayoutmeasurement.h:33
QgsLabelingEngineSettings::DrawUnplacedLabels
@ DrawUnplacedLabels
Whether to render unplaced labels as an indicator/warning for users.
Definition: qgslabelingenginesettings.h:43
QgsLayoutItemMap::zoomContent
void zoomContent(double factor, QPointF point) override
Zooms content of item.
Definition: qgslayoutitemmap.cpp:402
QgsMapSettings::layers
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
Definition: qgsmapsettings.cpp:299
_LayerRef::resolve
TYPE * resolve(const QgsProject *project)
Resolves the map layer by attempting to find a layer with matching ID within a project.
Definition: qgsmaplayerref.h:150
QgsLayoutItemMap::readPropertiesFromElement
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Definition: qgslayoutitemmap.cpp:713
QgsLayoutObject::DataDefinedProperty
DataDefinedProperty
Data defined properties for different item types.
Definition: qgslayoutobject.h:132
qgsstyleentityvisitor.h
QgsLayoutItemMapAtlasClippingSettings
Contains settings relating to clipping a layout map by the current atlas feature.
Definition: qgslayoutitemmap.h:39
QgsLayoutItemMap::visibleExtentPolygon
QPolygonF visibleExtentPolygon() const
Returns a polygon representing the current visible map extent, considering map extents and rotation.
Definition: qgslayoutitemmap.cpp:303
QgsLayoutItemMap::removeLabelBlockingItem
void removeLabelBlockingItem(QgsLayoutItem *item)
Removes the specified layout item from the map's "label blocking items".
Definition: qgslayoutitemmap.cpp:1769
QgsMapLayerStyle::readXml
void readXml(const QDomElement &styleElement)
Read style configuration (for project file reading)
Definition: qgsmaplayerstyle.cpp:86
QgsLayoutItemMapItemClipPathSettings::featureClippingType
QgsMapClippingRegion::FeatureClippingType featureClippingType() const
Returns the feature clipping type to apply when clipping to the associated item.
Definition: qgslayoutitemmap.cpp:3050
QgsLayoutItemMap::setLayers
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the stored layers set.
Definition: qgslayoutitemmap.cpp:331
QgsCoordinateReferenceSystemRegistry::userCrsChanged
void userCrsChanged(const QString &id)
Emitted whenever an existing user CRS definition is changed.
QgsLayoutItemMapAtlasClippingSettings::setFeatureClippingType
void setFeatureClippingType(QgsMapClippingRegion::FeatureClippingType type)
Sets the feature clipping type to apply when clipping to the current atlas feature.
Definition: qgslayoutitemmap.cpp:2825
qgslayoutitemmap.h
QgsLayoutObject::MapLayers
@ MapLayers
Map layer set.
Definition: qgslayoutobject.h:164
QgsMapRendererJob::finished
void finished()
emitted when asynchronous rendering is finished (or canceled).
QgsLayoutRenderContext::FlagHideCoverageLayer
@ FlagHideCoverageLayer
Hide coverage layer in outputs.
Definition: qgslayoutrendercontext.h:51
QgsLayoutMeasurement::decodeMeasurement
static QgsLayoutMeasurement decodeMeasurement(const QString &string)
Decodes a measurement from a string.
Definition: qgslayoutmeasurement.cpp:33
QgsLayoutItem::clipPathChanged
void clipPathChanged()
Emitted when the item's clipping path has changed.
QgsLayoutItemMap::framePath
QPainterPath framePath() const override
Returns the path to use when drawing the item's frame or background.
Definition: qgslayoutitemmap.cpp:880