32 #include <QStyleOptionGraphicsItem> 37 mBackgroundUpdateTimer =
new QTimer(
this );
38 mBackgroundUpdateTimer->setSingleShot(
true );
39 connect( mBackgroundUpdateTimer, &QTimer::timeout,
this, &QgsLayoutItemMap::recreateCachedImageInBackground );
48 mGridStack = qgis::make_unique< QgsLayoutItemMapGridStack >( this );
49 mOverviewStack = qgis::make_unique< QgsLayoutItemMapOverviewStack >( this );
60 mPainterJob->cancel();
80 QList<QgsLayoutItemMap *> mapsList;
81 mLayout->layoutItems( mapsList );
90 if ( map->mMapId == mMapId )
93 maxId = std::max( maxId, map->mMapId );
98 mLayout->itemsModel()->updateItemDisplayName(
this );
110 return tr(
"Map %1" ).arg( mMapId );
122 mCachedLayerStyleOverridesPresetName.clear();
126 updateAtlasFeature();
133 calculator.
setDpi( 25.4 );
140 double currentScaleDenominator =
scale();
147 double scaleRatio = scaleDenominator / currentScaleDenominator;
148 mExtent.
scale( scaleRatio );
150 if ( mAtlasDriven && mAtlasScalingMode ==
Fixed )
157 calculator.
setDpi( 25.4 );
158 scaleRatio = scaleDenominator / calculator.
calculate( mExtent, rect().width() );
159 mExtent.
scale( scaleRatio );
173 if ( mExtent == extent )
183 QRectF currentRect = rect();
185 double newHeight = currentRect.width() * mExtent.
height() / mExtent.
width();
197 double currentWidthHeightRatio = 1.0;
198 if ( !currentExtent.
isNull() )
199 currentWidthHeightRatio = currentExtent.
width() / currentExtent.
height();
201 currentWidthHeightRatio = rect().width() / rect().height();
202 double newWidthHeightRatio = newExtent.
width() / newExtent.
height();
204 if ( currentWidthHeightRatio < newWidthHeightRatio )
207 double newHeight = newExtent.
width() / currentWidthHeightRatio;
208 double deltaHeight = newHeight - newExtent.
height();
215 double newWidth = currentWidthHeightRatio * newExtent.
height();
216 double deltaWidth = newWidth - newExtent.
width();
221 if ( mExtent == newExtent )
243 mapPolygon( mExtent, poly );
252 return mLayout->project()->crs();
263 return _qgis_listRefToRaw( mLayers );
268 mLayers = _qgis_listRawToRef( layers );
273 if ( overrides == mLayerStyleOverrides )
276 mLayerStyleOverrides = overrides;
283 mLayerStyleOverrides.clear();
284 for (
const QgsMapLayerRef &layerRef : qgis::as_const( mLayers ) )
290 mLayerStyleOverrides.insert( layer->id(), style.
xmlData() );
297 mLastRenderedImageOffsetX -= dx;
298 mLastRenderedImageOffsetY -= dy;
301 transformShift( dx, dy );
325 double mapY = mExtent.
yMinimum() + ( 1 - ( point.y() / rect().height() ) ) * ( mExtent.
yMaximum() - mExtent.
yMinimum() );
331 centerX = mapX + ( centerX - mapX ) * ( 1.0 / factor );
332 centerY = mapY + ( centerY - mapY ) * ( 1.0 / factor );
334 double newIntervalX, newIntervalY;
351 if ( mAtlasDriven && mAtlasScalingMode ==
Fixed )
358 calculator.
setDpi( 25.4 );
359 double scaleRatio =
scale() / calculator.
calculate( mExtent, rect().width() );
360 mExtent.
scale( scaleRatio );
373 const QList< QgsMapLayer * >
layers = layersToRender();
376 if ( layer->dataProvider() && layer->dataProvider()->name() == QLatin1String(
"wms" ) )
412 if ( mOverviewStack->containsAdvancedEffects() )
418 if ( mGridStack->containsAdvancedEffects() )
430 mMapRotation = rotation;
431 mEvaluatedMapRotation = mMapRotation;
445 mAtlasDriven = enabled;
462 double margin = mAtlasMargin;
470 margin = ddMargin / 100;
482 if ( mGridStack->size() < 1 )
485 mGridStack->addGrid( grid );
487 return mGridStack->grid( 0 );
492 if ( mOverviewStack->size() < 1 )
495 mOverviewStack->addOverview( overview );
497 return mOverviewStack->overview( 0 );
508 mapElem.setAttribute( QStringLiteral(
"keepLayerSet" ), QStringLiteral(
"true" ) );
512 mapElem.setAttribute( QStringLiteral(
"keepLayerSet" ), QStringLiteral(
"false" ) );
515 if ( mDrawAnnotations )
517 mapElem.setAttribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"true" ) );
521 mapElem.setAttribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"false" ) );
525 QDomElement extentElem = doc.createElement( QStringLiteral(
"Extent" ) );
530 mapElem.appendChild( extentElem );
534 QDomElement crsElem = doc.createElement( QStringLiteral(
"crs" ) );
536 mapElem.appendChild( crsElem );
540 mapElem.setAttribute( QStringLiteral(
"followPreset" ), mFollowVisibilityPreset ?
"true" :
"false" );
541 mapElem.setAttribute( QStringLiteral(
"followPresetName" ), mFollowVisibilityPresetName );
544 mapElem.setAttribute( QStringLiteral(
"mapRotation" ), QString::number( mMapRotation ) );
547 QDomElement layerSetElem = doc.createElement( QStringLiteral(
"LayerSet" ) );
552 QDomElement layerElem = doc.createElement( QStringLiteral(
"Layer" ) );
553 QDomText layerIdText = doc.createTextNode( layerRef.layerId );
554 layerElem.appendChild( layerIdText );
556 layerElem.setAttribute( QStringLiteral(
"name" ), layerRef.name );
557 layerElem.setAttribute( QStringLiteral(
"source" ), layerRef.source );
558 layerElem.setAttribute( QStringLiteral(
"provider" ), layerRef.provider );
560 layerSetElem.appendChild( layerElem );
562 mapElem.appendChild( layerSetElem );
565 if ( mKeepLayerStyles )
567 QDomElement stylesElem = doc.createElement( QStringLiteral(
"LayerStyles" ) );
568 for (
auto styleIt = mLayerStyleOverrides.constBegin(); styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
570 QDomElement styleElem = doc.createElement( QStringLiteral(
"LayerStyle" ) );
575 styleElem.setAttribute( QStringLiteral(
"layerid" ), ref.layerId );
576 styleElem.setAttribute( QStringLiteral(
"name" ), ref.name );
577 styleElem.setAttribute( QStringLiteral(
"source" ), ref.source );
578 styleElem.setAttribute( QStringLiteral(
"provider" ), ref.provider );
582 stylesElem.appendChild( styleElem );
584 mapElem.appendChild( stylesElem );
588 mGridStack->writeXml( mapElem, doc, context );
591 mOverviewStack->writeXml( mapElem, doc, context );
594 QDomElement atlasElem = doc.createElement( QStringLiteral(
"AtlasMap" ) );
595 atlasElem.setAttribute( QStringLiteral(
"atlasDriven" ), mAtlasDriven );
596 atlasElem.setAttribute( QStringLiteral(
"scalingMode" ), mAtlasScalingMode );
597 atlasElem.setAttribute( QStringLiteral(
"margin" ),
qgsDoubleToString( mAtlasMargin ) );
598 mapElem.appendChild( atlasElem );
605 mUpdatesEnabled =
false;
608 QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral(
"Extent" ) );
609 if ( !extentNodeList.isEmpty() )
611 QDomElement extentElem = extentNodeList.at( 0 ).toElement();
612 double xmin, xmax, ymin, ymax;
613 xmin = extentElem.attribute( QStringLiteral(
"xmin" ) ).toDouble();
614 xmax = extentElem.attribute( QStringLiteral(
"xmax" ) ).toDouble();
615 ymin = extentElem.attribute( QStringLiteral(
"ymin" ) ).toDouble();
616 ymax = extentElem.attribute( QStringLiteral(
"ymax" ) ).toDouble();
620 QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral(
"crs" ) );
621 if ( !crsNodeList.isEmpty() )
623 QDomElement crsElem = crsNodeList.at( 0 ).toElement();
632 mMapRotation = itemElem.attribute( QStringLiteral(
"mapRotation" ), QStringLiteral(
"0" ) ).toDouble();
635 mFollowVisibilityPreset = itemElem.attribute( QStringLiteral(
"followPreset" ) ).compare( QLatin1String(
"true" ) ) == 0;
636 mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral(
"followPresetName" ) );
639 QString keepLayerSetFlag = itemElem.attribute( QStringLiteral(
"keepLayerSet" ) );
640 if ( keepLayerSetFlag.compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0 )
642 mKeepLayerSet =
true;
646 mKeepLayerSet =
false;
649 QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"true" ) );
650 if ( drawCanvasItemsFlag.compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0 )
652 mDrawAnnotations =
true;
656 mDrawAnnotations =
false;
659 mLayerStyleOverrides.clear();
663 QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral(
"LayerSet" ) );
664 if ( !layerSetNodeList.isEmpty() )
666 QDomElement layerSetElem = layerSetNodeList.at( 0 ).toElement();
667 QDomNodeList layerIdNodeList = layerSetElem.elementsByTagName( QStringLiteral(
"Layer" ) );
668 mLayers.reserve( layerIdNodeList.size() );
669 for (
int i = 0; i < layerIdNodeList.size(); ++i )
671 QDomElement layerElem = layerIdNodeList.at( i ).toElement();
672 QString layerId = layerElem.text();
673 QString layerName = layerElem.attribute( QStringLiteral(
"name" ) );
674 QString layerSource = layerElem.attribute( QStringLiteral(
"source" ) );
675 QString layerProvider = layerElem.attribute( QStringLiteral(
"provider" ) );
677 QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
684 QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral(
"LayerStyles" ) );
685 mKeepLayerStyles = !layerStylesNodeList.isEmpty();
686 if ( mKeepLayerStyles )
688 QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
689 QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral(
"LayerStyle" ) );
690 for (
int i = 0; i < layerStyleNodeList.size(); ++i )
692 const QDomElement &layerStyleElement = layerStyleNodeList.at( i ).toElement();
693 QString layerId = layerStyleElement.attribute( QStringLiteral(
"layerid" ) );
694 QString layerName = layerStyleElement.attribute( QStringLiteral(
"name" ) );
695 QString layerSource = layerStyleElement.attribute( QStringLiteral(
"source" ) );
696 QString layerProvider = layerStyleElement.attribute( QStringLiteral(
"provider" ) );
697 QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
701 style.
readXml( layerStyleElement );
707 mNumCachedLayers = 0;
708 mCacheInvalidated =
true;
711 mOverviewStack->readXml( itemElem, doc, context );
714 mGridStack->readXml( itemElem, doc, context );
717 QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral(
"AtlasMap" ) );
718 if ( !atlasNodeList.isEmpty() )
720 QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
721 mAtlasDriven = ( atlasElem.attribute( QStringLiteral(
"atlasDriven" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
722 if ( atlasElem.hasAttribute( QStringLiteral(
"fixedScale" ) ) )
724 mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral(
"fixedScale" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) ) ?
Fixed :
Auto;
726 else if ( atlasElem.hasAttribute( QStringLiteral(
"scalingMode" ) ) )
728 mAtlasScalingMode =
static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral(
"scalingMode" ) ).toInt() );
730 mAtlasMargin = atlasElem.attribute( QStringLiteral(
"margin" ), QStringLiteral(
"0.1" ) ).toDouble();
735 mUpdatesEnabled =
true;
741 if ( !
mLayout || !painter || !painter->device() || !mUpdatesEnabled )
750 QRectF thisPaintRect = rect();
751 if ( thisPaintRect.width() == 0 || thisPaintRect.height() == 0 )
756 if (
mLayout->renderContext().isPreviewRender() )
759 painter->setClipRect( thisPaintRect );
760 if ( !mCacheFinalImage || mCacheFinalImage->isNull() )
763 painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
764 painter->drawRect( thisPaintRect );
765 painter->setBrush( Qt::NoBrush );
767 messageFont.setPointSize( 12 );
768 painter->setFont( messageFont );
769 painter->setPen( QColor( 255, 255, 255, 255 ) );
770 painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr(
"Rendering map" ) );
771 if ( !mPainterJob && !mDrawingPreview )
775 mBackgroundUpdateTimer->start( 1 );
780 if ( mCacheInvalidated && !mDrawingPreview )
784 mBackgroundUpdateTimer->start( 1 );
789 double imagePixelWidth = mCacheFinalImage->width();
790 double scale = rect().width() / imagePixelWidth;
794 painter->translate( mLastRenderedImageOffsetX + mXOffset, mLastRenderedImageOffsetY + mYOffset );
795 painter->scale( scale, scale );
796 painter->drawImage( 0, 0, *mCacheFinalImage );
802 painter->setClipRect( thisPaintRect, Qt::NoClip );
804 if ( shouldDrawPart( OverviewMapExtent ) )
806 mOverviewStack->drawItems( painter );
808 if ( shouldDrawPart( Grid ) )
810 mGridStack->drawItems( painter );
813 if ( shouldDrawPart( Frame ) )
815 drawMapFrame( painter );
825 QPaintDevice *paintDevice = painter->device();
837 int widthInPixels = std::round(
boundingRect().width() * layoutUnitsInInches * destinationDpi );
838 int heightInPixels = std::round(
boundingRect().height() * layoutUnitsInInches * destinationDpi );
839 QImage image = QImage( widthInPixels, heightInPixels, QImage::Format_ARGB32 );
841 image.fill( Qt::transparent );
842 image.setDotsPerMeterX( 1000 * destinationDpi / 25.4 );
843 image.setDotsPerMeterY( 1000 * destinationDpi / 25.4 );
844 double dotsPerMM = destinationDpi / 25.4;
845 QPainter p( &image );
848 QRect imagePaintRect( std::round( tl.x() * dotsPerMM ),
849 std::round( tl.y() * dotsPerMM ),
850 std::round( thisPaintRect.width() * dotsPerMM ),
851 std::round( thisPaintRect.height() * dotsPerMM ) );
852 p.setClipRect( imagePaintRect );
854 p.translate( imagePaintRect.topLeft() );
858 if ( shouldDrawPart( Background ) )
860 p.scale( dotsPerMM, dotsPerMM );
861 drawMapBackground( &p );
862 p.scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
865 drawMap( &p, cExtent, imagePaintRect.size(), image.logicalDpiX() );
870 p.scale( dotsPerMM, dotsPerMM );
872 if ( shouldDrawPart( OverviewMapExtent ) )
874 mOverviewStack->drawItems( &p );
876 if ( shouldDrawPart( Grid ) )
878 mGridStack->drawItems( &p );
883 painter->scale( 1 / dotsPerMM, 1 / dotsPerMM );
884 painter->drawImage( std::round( -tl.x()* dotsPerMM ), std::round( -tl.y() * dotsPerMM ), image );
885 painter->scale( dotsPerMM, dotsPerMM );
891 if ( shouldDrawPart( Background ) )
893 drawMapBackground( painter );
897 painter->setClipRect( thisPaintRect );
899 painter->translate( mXOffset, mYOffset );
901 double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
903 painter->scale( 1 / dotsPerMM, 1 / dotsPerMM );
904 drawMap( painter, cExtent, size, paintDevice->logicalDpiX() );
908 painter->setClipRect( thisPaintRect, Qt::NoClip );
910 if ( shouldDrawPart( OverviewMapExtent ) )
912 mOverviewStack->drawItems( painter );
914 if ( shouldDrawPart( Grid ) )
916 mGridStack->drawItems( painter );
922 if ( shouldDrawPart( Frame ) )
924 drawMapFrame( painter );
933 + layersToRender().length()
945 void QgsLayoutItemMap::drawMap( QPainter *painter,
const QgsRectangle &
extent, QSizeF size,
double dpi )
965 void QgsLayoutItemMap::recreateCachedImageInBackground()
971 QPainter *oldPainter = mPainter.release();
972 QImage *oldImage = mCacheRenderingImage.release();
975 oldJob->deleteLater();
979 oldJob->cancelWithoutBlocking();
983 mCacheRenderingImage.reset(
nullptr );
986 Q_ASSERT( !mPainterJob );
987 Q_ASSERT( !mPainter );
988 Q_ASSERT( !mCacheRenderingImage );
994 int w = widthLayoutUnits * mPreviewScaleFactor;
995 int h = heightLayoutUnits * mPreviewScaleFactor;
998 if ( w > 5000 || h > 5000 )
1003 h = w * heightLayoutUnits / widthLayoutUnits;
1008 w = h * widthLayoutUnits / heightLayoutUnits;
1012 if ( w <= 0 || h <= 0 )
1015 mCacheRenderingImage.reset(
new QImage( w, h, QImage::Format_ARGB32 ) );
1018 mCacheRenderingImage->setDotsPerMeterX( 1000 * w / widthLayoutUnits );
1019 mCacheRenderingImage->setDotsPerMeterY( 1000 * h / heightLayoutUnits );
1030 mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
1033 mCacheInvalidated =
false;
1034 mPainter.reset(
new QPainter( mCacheRenderingImage.get() ) );
1038 mPainterJob->start();
1050 mDrawingPreview =
false;
1064 jobMapSettings.
setRotation( mEvaluatedMapRotation );
1068 if ( includeLayerSettings )
1071 QList<QgsMapLayer *>
layers = layersToRender( &expressionContext );
1072 if (
mLayout && -1 !=
mLayout->renderContext().currentExportLayer() )
1074 const int layerIdx =
mLayout->renderContext().currentExportLayer() - (
hasBackground() ? 1 : 0 );
1075 if ( layerIdx >= 0 && layerIdx < layers.length() )
1078 QgsMapLayer *ml = layers[ layers.length() - layerIdx - 1 ];
1092 if ( !
mLayout->renderContext().isPreviewRender() )
1111 return jobMapSettings;
1118 mOverviewStack->finalizeRestoreFromXml();
1119 mGridStack->finalizeRestoreFromXml();
1130 return mCurrentRectangle;
1166 if ( extentWidth <= 0 )
1170 return rect().width() / extentWidth;
1175 double dx = mXOffset;
1176 double dy = mYOffset;
1177 transformShift( dx, dy );
1179 poly.translate( -dx, -dy );
1186 if ( mapPoly.empty() )
1188 return QPointF( 0, 0 );
1193 double dx = mapCoords.x() - rotationPoint.
x();
1194 double dy = mapCoords.y() - rotationPoint.
y();
1196 QgsPointXY backRotatedCoords( rotationPoint.
x() + dx, rotationPoint.
y() + dy );
1199 double xItem = rect().width() * ( backRotatedCoords.x() - unrotatedExtent.xMinimum() ) / unrotatedExtent.width();
1200 double yItem = rect().height() * ( 1 - ( backRotatedCoords.y() - unrotatedExtent.yMinimum() ) / unrotatedExtent.height() );
1201 return QPointF( xItem, yItem );
1215 mapPolygon( newExtent, poly );
1216 QRectF bRect = poly.boundingRect();
1230 mCacheInvalidated =
true;
1236 QRectF rectangle = rect();
1237 double frameExtension =
frameEnabled() ? pen().widthF() / 2.0 : 0.0;
1239 double topExtension = 0.0;
1240 double rightExtension = 0.0;
1241 double bottomExtension = 0.0;
1242 double leftExtension = 0.0;
1245 mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1247 topExtension = std::max( topExtension, frameExtension );
1248 rightExtension = std::max( rightExtension, frameExtension );
1249 bottomExtension = std::max( bottomExtension, frameExtension );
1250 leftExtension = std::max( leftExtension, frameExtension );
1252 rectangle.setLeft( rectangle.left() - leftExtension );
1253 rectangle.setRight( rectangle.right() + rightExtension );
1254 rectangle.setTop( rectangle.top() - topExtension );
1255 rectangle.setBottom( rectangle.bottom() + bottomExtension );
1256 if ( rectangle != mCurrentRectangle )
1258 prepareGeometryChange();
1259 mCurrentRectangle = rectangle;
1275 refreshMapExtents( &context );
1277 if ( mExtent != beforeExtent )
1284 mCacheInvalidated =
true;
1289 void QgsLayoutItemMap::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &
layers )
1291 if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1295 mLayerStyleOverrides.remove( layer->id() );
1297 _qgis_removeLayers( mLayers, layers );
1301 void QgsLayoutItemMap::painterJobFinished()
1304 mPainterJob.reset(
nullptr );
1305 mPainter.reset(
nullptr );
1306 mCacheFinalImage = std::move( mCacheRenderingImage );
1307 mLastRenderedImageOffsetX = 0;
1308 mLastRenderedImageOffsetY = 0;
1312 void QgsLayoutItemMap::shapeChanged()
1317 double w = rect().width();
1318 double h = rect().height();
1321 double newWidth = mExtent.
width();
1323 double newHeight = newWidth * h / w;
1328 refreshMapExtents();
1335 void QgsLayoutItemMap::mapThemeChanged(
const QString &theme )
1337 if ( theme == mCachedLayerStyleOverridesPresetName )
1338 mCachedLayerStyleOverridesPresetName.clear();
1341 void QgsLayoutItemMap::connectUpdateSlot()
1349 this, &QgsLayoutItemMap::layersAboutToBeRemoved );
1353 if (
layers().isEmpty() )
1375 void QgsLayoutItemMap::updateToolTip()
1380 QList<QgsMapLayer *> QgsLayoutItemMap::layersToRender(
const QgsExpressionContext *context )
const 1387 QList<QgsMapLayer *> renderLayers;
1389 if ( mFollowVisibilityPreset )
1391 QString presetName = mFollowVisibilityPresetName;
1396 if (
mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
1397 renderLayers =
mLayout->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
1399 renderLayers =
mLayout->project()->mapThemeCollection()->masterVisibleLayers();
1401 else if ( !
layers().isEmpty() )
1407 renderLayers =
mLayout->project()->mapThemeCollection()->masterVisibleLayers();
1414 renderLayers.clear();
1416 const QStringList layerNames = ddLayers.split(
'|' );
1418 for (
const QString &name : layerNames )
1420 const QList< QgsMapLayer * > matchingLayers =
mLayout->project()->mapLayersByName( name );
1423 renderLayers << layer;
1432 int removeAt = renderLayers.indexOf(
mLayout->reportContext().layer() );
1433 if ( removeAt != -1 )
1435 renderLayers.removeAt( removeAt );
1439 return renderLayers;
1442 QMap<QString, QString> QgsLayoutItemMap::layerStyleOverridesToRender(
const QgsExpressionContext &context )
const 1444 if ( mFollowVisibilityPreset )
1446 QString presetName = mFollowVisibilityPresetName;
1451 if (
mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
1453 if ( presetName.isEmpty() || presetName != mCachedLayerStyleOverridesPresetName )
1456 mCachedPresetLayerStyleOverrides =
mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( presetName );
1457 mCachedLayerStyleOverridesPresetName = presetName;
1460 return mCachedPresetLayerStyleOverrides;
1463 return QMap<QString, QString>();
1465 else if ( mKeepLayerStyles )
1467 return mLayerStyleOverrides;
1471 return QMap<QString, QString>();
1475 QgsRectangle QgsLayoutItemMap::transformedExtent()
const 1477 double dx = mXOffset;
1478 double dy = mYOffset;
1479 transformShift( dx, dy );
1483 void QgsLayoutItemMap::mapPolygon(
const QgsRectangle &extent, QPolygonF &poly )
const 1493 poly << QPointF( poly.at( 0 ) );
1502 dx = rotationPoint.
x() - extent.
xMinimum();
1503 dy = rotationPoint.
y() - extent.
yMaximum();
1505 poly << QPointF( rotationPoint.
x() - dx, rotationPoint.
y() - dy );
1508 dx = rotationPoint.
x() - extent.
xMaximum();
1509 dy = rotationPoint.
y() - extent.
yMaximum();
1511 poly << QPointF( rotationPoint.
x() - dx, rotationPoint.
y() - dy );
1514 dx = rotationPoint.
x() - extent.
xMaximum();
1515 dy = rotationPoint.
y() - extent.
yMinimum();
1517 poly << QPointF( rotationPoint.
x() - dx, rotationPoint.
y() - dy );
1520 dx = rotationPoint.
x() - extent.
xMinimum();
1521 dy = rotationPoint.
y() - extent.
yMinimum();
1523 poly << QPointF( rotationPoint.
x() - dx, rotationPoint.
y() - dy );
1526 poly << QPointF( poly.at( 0 ) );
1529 void QgsLayoutItemMap::transformShift(
double &xShift,
double &yShift )
const 1532 double dxScaled = xShift * mmToMapUnits;
1533 double dyScaled = - yShift * mmToMapUnits;
1548 const QList< QgsAnnotation * > annotations =
mLayout->project()->annotationManager()->annotations();
1549 if ( annotations.isEmpty() )
1559 if ( !annotation || !annotation->isVisible() )
1563 if ( annotation->mapLayer() && !layers.contains( annotation->mapLayer() ) )
1566 drawAnnotation( annotation, rc );
1580 double itemX, itemY;
1583 QPointF mapPos = layoutMapPosForItem( annotation );
1592 context.
painter()->translate( itemX, itemY );
1595 double dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
1596 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1598 annotation->
render( context );
1602 QPointF QgsLayoutItemMap::layoutMapPosForItem(
const QgsAnnotation *annotation )
const 1605 return QPointF( 0, 0 );
1614 if ( annotationCrs !=
crs() )
1631 void QgsLayoutItemMap::drawMapFrame( QPainter *p )
1637 p->setBrush( Qt::NoBrush );
1638 p->setRenderHint( QPainter::Antialiasing,
true );
1639 p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
1644 void QgsLayoutItemMap::drawMapBackground( QPainter *p )
1649 p->setBrush( brush() );
1650 p->setPen( Qt::NoPen );
1651 p->setRenderHint( QPainter::Antialiasing,
true );
1652 p->drawRect( QRectF( 0, 0, rect().width(), rect().height() ) );
1657 bool QgsLayoutItemMap::shouldDrawPart( QgsLayoutItemMap::PartType part )
const 1659 int currentExportLayer =
mLayout->renderContext().currentExportLayer();
1661 if ( -1 == currentExportLayer )
1671 if ( SelectionBoxes == part )
1673 return currentExportLayer == idx;
1680 if ( Frame == part )
1682 return currentExportLayer == idx;
1686 if ( OverviewMapExtent == part )
1688 return currentExportLayer == idx;
1693 return currentExportLayer == idx;
1697 if ( Background == part )
1699 return currentExportLayer == 0;
1715 bool useDdXMin =
false;
1716 bool useDdXMax =
false;
1717 bool useDdYMin =
false;
1718 bool useDdYMax =
false;
1750 if ( newExtent != mExtent )
1756 double currentWidthHeightRatio = mExtent.
width() / mExtent.
height();
1757 double newWidthHeightRatio = newExtent.
width() / newExtent.
height();
1759 if ( currentWidthHeightRatio < newWidthHeightRatio )
1762 double newHeight = newExtent.
width() / currentWidthHeightRatio;
1763 double deltaHeight = newHeight - newExtent.
height();
1770 double newWidth = currentWidthHeightRatio * newExtent.
height();
1771 double deltaWidth = newWidth - newExtent.
width();
1776 mExtent = newExtent;
1786 newExtent = mExtent;
1789 if ( useDdXMax || useDdXMin || useDdYMax || useDdYMin )
1793 if ( useDdXMin && !useDdXMax )
1799 else if ( !useDdXMin && useDdXMax )
1805 if ( useDdYMin && !useDdYMax )
1811 else if ( !useDdYMin && useDdYMax )
1818 if ( newExtent != mExtent )
1820 mExtent = newExtent;
1837 void QgsLayoutItemMap::updateAtlasFeature()
1856 if ( mAtlasScalingMode ==
Fixed || mAtlasScalingMode ==
Predefined || isPointLayer )
1861 double originalScale = calc.
calculate( originalExtent, rect().width() );
1862 double geomCenterX = ( xa1 + xa2 ) / 2.0;
1863 double geomCenterY = ( ya1 + ya2 ) / 2.0;
1865 if ( mAtlasScalingMode ==
Fixed || isPointLayer )
1868 double xMin = geomCenterX - originalExtent.
width() / 2.0;
1869 double yMin = geomCenterY - originalExtent.
height() / 2.0;
1872 xMin + originalExtent.
width(),
1873 yMin + originalExtent.
height() );
1877 double newScale = calc.
calculate( newExtent, rect().width() );
1878 newExtent.
scale( originalScale / newScale );
1883 double newWidth = originalExtent.
width();
1884 double newHeight = originalExtent.
height();
1885 QVector<qreal> scales =
mLayout->reportContext().predefinedScales();
1886 for (
int i = 0; i < scales.size(); i++ )
1888 double ratio = scales[i] / originalScale;
1889 newWidth = originalExtent.
width() * ratio;
1890 newHeight = originalExtent.
height() * ratio;
1893 double xMin = geomCenterX - newWidth / 2.0;
1894 double yMin = geomCenterY - newHeight / 2.0;
1902 double newScale = calc.
calculate( newExtent, rect().width() );
1903 newExtent.
scale( scales[i] / newScale );
1913 else if ( mAtlasScalingMode ==
Auto )
1917 double geomRatio = bounds.
width() / bounds.
height();
1918 double mapRatio = originalExtent.
width() / originalExtent.
height();
1921 if ( geomRatio < mapRatio )
1924 double adjWidth = ( mapRatio * bounds.
height() - bounds.
width() ) / 2.0;
1929 else if ( geomRatio > mapRatio )
1932 double adjHeight = ( bounds.
width() / mapRatio - bounds.
height() ) / 2.0;
1938 if ( mAtlasMargin > 0.0 )
1940 newExtent.
scale( 1 + mAtlasMargin );
1956 if ( mEvaluatedMapRotation != 0.0 )
1966 double dx = std::max( std::abs( prevCenter.
x() - bounds.
xMinimum() ),
1967 std::abs( prevCenter.
x() - bounds.
xMaximum() ) );
1968 double dy = std::max( std::abs( prevCenter.
y() - bounds.
yMinimum() ),
1969 std::abs( prevCenter.
y() - bounds.
yMaximum() ) );
1972 center.
x() + dx, center.
y() + dy );
double atlasMargin(const QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue)
Returns the margin size (percentage) used when the map is in atlas mode.
QIcon icon() const override
Returns the item's icon.
QString displayName() const override
Get item display name.
void setForceVectorOutput(bool force)
The class is used as a container of context for various read/write operations on other objects...
static double scaleFactorFromItemStyle(const QStyleOptionGraphicsItem *style)
Extracts the scale factor from an item style.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
void finished()
emitted when asynchronous rendering is finished (or canceled).
Single variable definition for use within a QgsExpressionContextScope.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
A rectangle specified with double values.
Base class for all map layer types.
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
Job implementation that renders everything sequentially using a custom painter.
bool isVisible() const
Returns true if the annotation is visible and should be rendered.
void refreshDataDefinedProperty(const QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties) override
QPointF mapToItemCoords(QPointF mapCoords) const
Transforms map coordinates to item coordinates (considering rotation and move offset) ...
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
bool containsAdvancedEffects() const override
Returns true if the item contains contents with blend modes or transparency effects which can only be...
Base class for graphical items within a QgsLayout.
An individual overview which is drawn above the map content in a QgsLayoutItemMap, and shows the extent of another QgsLayoutItemMap.
virtual bool containsAdvancedEffects() const
Returns true if the item contains contents with blend modes or transparency effects which can only be...
static Q_INVOKABLE QString toString(QgsUnitTypes::DistanceUnit unit)
Returns a translated string representing a distance unit.
QgsLayoutItemMap(QgsLayout *layout)
Constructor for QgsLayoutItemMap, with the specified parent layout.
void moveContent(double dx, double dy) override
Moves the content of the item, by a specified dx and dy in layout units.
double valueAsDouble(int key, const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a double...
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setXMaximum(double x)
Set the maximum x value.
int type() const override
Use antialiasing while drawing.
QString xmlData() const
Return XML content of the style.
void readXml(const QDomElement &styleElement)
Read style configuration (for project file reading)
Layer and style map theme.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void setExtent(const QgsRectangle &extent)
Sets a new extent for the map.
void layerOrderChanged()
Emitted when the layer order has changed.
A class to represent a 2D point.
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
QgsMapSettings mapSettings(const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings) const
Return map settings that will be used for drawing of the map.
void extentChanged()
Is emitted when the map's extent changes.
OperationResult rotate(double rotation, const QgsPointXY ¢er)
Rotate this geometry around the Z axis.
static QgsLayoutItemMap * create(QgsLayout *layout)
Returns a new map item for the specified layout.
bool frameEnabled() const
Returns true if the item includes a frame.
TYPE * resolveWeakly(const QgsProject *project)
Resolves the map layer by attempting to find a matching layer in a project using a weak match...
void setOutputDpi(double dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
QString toProj4() const
Returns a Proj4 string representation of this CRS.
void crsChanged()
Emitted when the CRS of the project has changed.
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
void zoomContent(double factor, QPointF point) override
Zooms content of item.
A geometry is the spatial representation of a feature.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
static const QStringList containsAdvancedEffects(const QgsMapSettings &mapSettings)
Checks whether any of the layers attached to a map settings object contain advanced effects...
bool drawAnnotations() const
Returns whether annotations are drawn within the map.
Flags flags() const
Return combination of flags used for rendering.
QgsUnitTypes::DistanceUnit mapUnits
void invalidateCache() override
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...
void preparedForAtlas()
Is emitted when the map has been prepared for atlas rendering, just before actual rendering...
Enable layer opacity and blending effects.
QPolygonF transformedMapPolygon() const
Returns extent that considers rotation and shift with mOffsetX / mOffsetY.
friend class QgsLayoutItemMapOverview
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
QPointF relativePosition() const
Returns the relative position of the annotation, if it is not attached to a fixed map position...
Vector graphics should not be cached and drawn as raster images.
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
Abstract base class for annotation items which are drawn over a map.
The QgsMapSettings class contains configuration for rendering of the map.
PropertyValueType
Specifies whether the value returned by a function should be the original, user set value...
void readFromLayer(QgsMapLayer *layer)
Store layer's active style information in the instance.
void storeCurrentLayerStyles()
Stores the current project layer styles into style overrides.
void sizePositionChanged()
Emitted when the item's size or position changes.
Stores style information (renderer, opacity, labeling, diagrams etc.) applicable to a map layer...
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
void mapThemeChanged(const QString &theme)
Emitted when a map theme changes definition.
static QgsRectangle fromCenterAndSize(QgsPointXY center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
QList< QgsMapLayer * > layers() const
Returns the stored layer set.
QgsRectangle extent() const
Returns the current map extent.
Layout graphical items for displaying a map.
void setOutputSize(QSize size)
Set the size of the resulting map image.
QString layerId
Original layer ID.
QgsPropertyCollection mDataDefinedProperties
const QgsLayout * layout() const
Returns the layout the object is attached to.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
QgsMapThemeCollection mapThemeCollection
void setLayers(const QList< QgsMapLayer *> &layers)
Sets the stored layers set.
This class provides a method of storing measurements for use in QGIS layouts using a variety of diffe...
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...
bool hasBackground() const
Returns true if the item has a background.
Whether vector selections should be shown in the rendered map.
double width() const
Returns the width of the rectangle.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
~QgsLayoutItemMap() override
void setYMinimum(double y)
Set the minimum y value.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
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...
static QgsRenderContext createRenderContextForMap(QgsLayoutItemMap *map, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout map and painter destination.
QColor backgroundColor() const
Returns the background color for this item.
Enable anti-aliasing for map rendering.
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
void render(QgsRenderContext &context) const
Renders the annotation to a target render context.
double mapUnitsToLayoutUnits() const
Returns the conversion factor from map units to layout units.
QPointer< QgsLayout > mLayout
void setMapUnits(QgsUnitTypes::DistanceUnit mapUnits)
Set the map units.
void setFrameStrokeWidth(const QgsLayoutMeasurement &width) override
Sets the frame stroke width.
QgsExpressionContext createExpressionContext() const override
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Hide coverage layer in outputs.
void setMoveContentPreviewOffset(double dx, double dy) override
Sets temporary offset for the item, by a specified dx and dy in layout units.
Reads and writes project states.
virtual void setFrameStrokeWidth(const QgsLayoutMeasurement &width)
Sets the frame stroke width.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the map's preset crs (coordinate reference system).
QString id() const
Returns the item's ID name.
QgsRectangle requestedExtent() const
Calculates the extent to request and the yShift of the top-left point in case of rotation.
Single scope for storing variables and functions for use within a QgsExpressionContext.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
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...
static void rotate(double angle, double &x, double &y)
Rotates a point / vector around the origin.
Enable drawing of vertex markers for layers in editing mode.
The extent is adjusted so that each feature is fully visible.
An individual grid which is drawn above the map content in a QgsLayoutItemMap.
QPolygonF visibleExtentPolygon() const
Returns a polygon representing the current visible map extent, considering map extents and rotation...
void mapRotationChanged(double newRotation)
Is emitted when the map's rotation changes.
Use antialiasing when drawing items.
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the stored overrides of styles for layers.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
void setRotation(double rotation)
Sets the rotation of the resulting map image, in degrees clockwise.
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsExpressionContext & expressionContext()
Gets the expression context.
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
void setAtlasDriven(bool enabled)
Sets whether the map extent will follow the current atlas feature.
QgsLayerTree * layerTreeRoot() const
Return pointer to the root (invisible) node of the project's layer tree.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
void paint(QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget) override
QString valueAsString(int key, const QgsExpressionContext &context, const QString &defaultString=QString(), bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as a string...
void setBackgroundColor(const QColor &color)
Set the background color of the map.
double mapRotation(QgsLayoutObject::PropertyValueType valueType=QgsLayoutObject::EvaluatedValue) const
Returns the rotation used for drawing the map within the layout item, in degrees clockwise.
Return the current evaluated value for the property.
void setLabelingEngineSettings(const QgsLabelingEngineSettings &settings)
Sets global configuration of the labeling engine.
QgsCoordinateReferenceSystem mapPositionCrs() const
Returns the CRS of the map position, or an invalid CRS if the annotation does not have a fixed map po...
Contains information about the context of a rendering operation.
Force output in vector format where possible, even if items require rasterization to keep their corre...
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
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...
QPainter * painter()
Returns the destination QPainter for the render operation.
void layersWillBeRemoved(const QStringList &layerIds)
Emitted when one or more layers are about to be removed from the registry.
QgsCoordinateReferenceSystem crs() const
Returns coordinate reference system used for rendering the map.
bool containsWmsLayer() const
Returns true if the map contains a WMS layer.
void writeXml(QDomElement &styleElement) const
Write style configuration (for project file writing)
QgsLayoutItemMapOverview * overview()
Returns the map item's first overview.
Enable advanced effects such as blend modes.
bool shouldDrawItem() const
Returns whether the item should be drawn in the current context.
void updateBoundingRect()
Updates the bounding rect of this item. Call this function before doing any changes related to annota...
void refreshed()
Is emitted when the layout has been refreshed and items should also be refreshed and updated...
void setYMaximum(double y)
Set the maximum y value.
The current scale of the map is used for each feature of the atlas.
double scale() const
Returns the map scale.
friend class QgsLayoutItemMapGrid
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
This class represents a coordinate reference system (CRS).
void assignFreeId()
Sets the map id() to a number not yet used in the layout.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
virtual void refreshDataDefinedProperty(const QgsLayoutObject::DataDefinedProperty property=QgsLayoutObject::AllProperties)
Refreshes a data defined property for the item by reevaluating the property's value and redrawing the...
double xMinimum() const
Returns the x minimum value (left side of rectangle).
void setLayers(const QList< QgsMapLayer *> &layers)
Set list of layers for map rendering.
void setPathResolver(const QgsPathResolver &resolver)
Sets the path resolver for conversion between relative and absolute paths during rendering operations...
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void layerStyleOverridesChanged()
Emitted when layer style overrides are changed...
Enable vector simplification and other rendering optimizations.
Custom exception class for Coordinate Reference System related exceptions.
bool atlasDriven() const
Returns whether the map extent is set to follow the current atlas feature.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
QgsPointXY center() const
Returns the center point of the rectangle.
void zoomToExtent(const QgsRectangle &extent)
Zooms the map so that the specified extent is fully visible within the map item.
AtlasScalingMode
Scaling modes used for the serial rendering (atlas)
int numberExportLayers() const override
Returns the number of layers that this item requires for exporting during layered exports (e...
TYPE * resolve(const QgsProject *project)
Resolves the map layer by attempting to find a layer with matching ID within a project.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
void changed()
Emitted when the object's properties change.
DataDefinedProperty
Data defined properties for different item types.
void setScale(double scale, bool forceUpdate=true)
Sets new map scale and changes only the map extent.
void refresh() override
Refreshes the item, causing a recalculation of any property overrides and recalculation of its positi...
void finalizeRestoreFromXml() override
Called after all pending items have been restored from XML.
QRectF boundingRect() const override
void renderSynchronously()
Render the map synchronously in this thread.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
QString authid() const
Returns the authority identifier for the CRS.
void setXMinimum(double x)
Set the minimum x value.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
double height() const
Returns the height of the rectangle.
A scale is chosen from the predefined scales.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QgsLayoutItemMapGrid * grid()
Returns the map item's first grid.