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