39 #include <QStyleOptionGraphicsItem>
46 mBackgroundUpdateTimer =
new QTimer(
this );
47 mBackgroundUpdateTimer->setSingleShot(
true );
48 connect( mBackgroundUpdateTimer, &QTimer::timeout,
this, &QgsLayoutItemMap::recreateCachedImageInBackground );
52 setCacheMode( QGraphicsItem::NoCache );
59 mGridStack = qgis::make_unique< QgsLayoutItemMapGridStack >(
this );
60 mOverviewStack = qgis::make_unique< QgsLayoutItemMapOverviewStack >(
this );
82 mPainterJob->cancel();
107 QList<QgsLayoutItemMap *> mapsList;
108 mLayout->layoutItems( mapsList );
117 if ( map->mMapId == mMapId )
120 maxId = std::max( maxId, map->mMapId );
125 mLayout->itemsModel()->updateItemDisplayName(
this );
137 return tr(
"Map %1" ).arg( mMapId );
149 mCachedLayerStyleOverridesPresetName.clear();
153 updateAtlasFeature();
158 if ( rect().isEmpty() )
163 calculator.
setDpi( 25.4 );
170 double currentScaleDenominator =
scale();
177 double scaleRatio = scaleDenominator / currentScaleDenominator;
178 mExtent.
scale( scaleRatio );
180 if ( mAtlasDriven && mAtlasScalingMode ==
Fixed )
187 calculator.
setDpi( 25.4 );
188 scaleRatio = scaleDenominator / calculator.
calculate( mExtent, rect().width() );
189 mExtent.
scale( scaleRatio );
213 QRectF currentRect = rect();
215 double newHeight = currentRect.width() * mExtent.
height() / mExtent.
width();
227 double currentWidthHeightRatio = 1.0;
228 if ( !currentExtent.
isNull() )
229 currentWidthHeightRatio = currentExtent.
width() / currentExtent.
height();
231 currentWidthHeightRatio = rect().width() / rect().height();
232 double newWidthHeightRatio = newExtent.
width() / newExtent.
height();
234 if ( currentWidthHeightRatio < newWidthHeightRatio )
237 double newHeight = newExtent.
width() / currentWidthHeightRatio;
238 double deltaHeight = newHeight - newExtent.
height();
245 double newWidth = currentWidthHeightRatio * newExtent.
height();
246 double deltaWidth = newWidth - newExtent.
width();
251 if ( mExtent == newExtent )
270 QPolygonF QgsLayoutItemMap::calculateVisibleExtentPolygon(
bool includeClipping )
const
273 mapPolygon( mExtent, poly );
275 if ( includeClipping && mItemClippingSettings->
isActive() )
289 return calculateVisibleExtentPolygon(
true );
297 return mLayout->project()->crs();
308 return _qgis_listRefToRaw( mLayers );
313 mLayers = _qgis_listRawToRef(
layers );
318 if ( overrides == mLayerStyleOverrides )
321 mLayerStyleOverrides = overrides;
328 mLayerStyleOverrides.clear();
329 for (
const QgsMapLayerRef &layerRef : qgis::as_const( mLayers ) )
335 mLayerStyleOverrides.insert( layer->id(), style.
xmlData() );
342 if ( mFollowVisibilityPreset == follow )
345 mFollowVisibilityPreset = follow;
346 if ( !mFollowVisibilityPresetName.isEmpty() )
347 emit
themeChanged( mFollowVisibilityPreset ? mFollowVisibilityPresetName : QString() );
352 if ( name == mFollowVisibilityPresetName )
355 mFollowVisibilityPresetName = name;
356 if ( mFollowVisibilityPreset )
362 mLastRenderedImageOffsetX -= dx;
363 mLastRenderedImageOffsetY -= dy;
366 transformShift( dx, dy );
390 double mapY = mExtent.
yMinimum() + ( 1 - ( point.y() / rect().height() ) ) * ( mExtent.
yMaximum() - mExtent.
yMinimum() );
396 centerX = mapX + ( centerX - mapX ) * ( 1.0 / factor );
397 centerY = mapY + ( centerY - mapY ) * ( 1.0 / factor );
399 double newIntervalX, newIntervalY;
416 if ( mAtlasDriven && mAtlasScalingMode ==
Fixed )
423 calculator.
setDpi( 25.4 );
424 double scaleRatio =
scale() / calculator.
calculate( mExtent, rect().width() );
425 mExtent.
scale( scaleRatio );
441 if ( layer->dataProvider() && layer->providerType() == QLatin1String(
"wms" ) )
475 if ( mOverviewStack->containsAdvancedEffects() )
481 if ( mGridStack->containsAdvancedEffects() )
493 mMapRotation = rotation;
494 mEvaluatedMapRotation = mMapRotation;
508 mAtlasDriven = enabled;
525 double margin = mAtlasMargin;
533 margin = ddMargin / 100;
545 if ( mGridStack->size() < 1 )
548 mGridStack->addGrid(
grid );
550 return mGridStack->grid( 0 );
555 if ( mOverviewStack->size() < 1 )
558 mOverviewStack->addOverview(
overview );
560 return mOverviewStack->overview( 0 );
571 mapElem.setAttribute( QStringLiteral(
"keepLayerSet" ), QStringLiteral(
"true" ) );
575 mapElem.setAttribute( QStringLiteral(
"keepLayerSet" ), QStringLiteral(
"false" ) );
578 if ( mDrawAnnotations )
580 mapElem.setAttribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"true" ) );
584 mapElem.setAttribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"false" ) );
588 QDomElement extentElem = doc.createElement( QStringLiteral(
"Extent" ) );
593 mapElem.appendChild( extentElem );
597 QDomElement crsElem = doc.createElement( QStringLiteral(
"crs" ) );
599 mapElem.appendChild( crsElem );
603 mapElem.setAttribute( QStringLiteral(
"followPreset" ), mFollowVisibilityPreset ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ) );
604 mapElem.setAttribute( QStringLiteral(
"followPresetName" ), mFollowVisibilityPresetName );
607 mapElem.setAttribute( QStringLiteral(
"mapRotation" ), QString::number( mMapRotation ) );
610 QDomElement layerSetElem = doc.createElement( QStringLiteral(
"LayerSet" ) );
615 QDomElement layerElem = doc.createElement( QStringLiteral(
"Layer" ) );
616 QDomText layerIdText = doc.createTextNode( layerRef.layerId );
617 layerElem.appendChild( layerIdText );
619 layerElem.setAttribute( QStringLiteral(
"name" ), layerRef.name );
620 layerElem.setAttribute( QStringLiteral(
"source" ), layerRef.source );
621 layerElem.setAttribute( QStringLiteral(
"provider" ), layerRef.provider );
623 layerSetElem.appendChild( layerElem );
625 mapElem.appendChild( layerSetElem );
628 if ( mKeepLayerStyles )
630 QDomElement stylesElem = doc.createElement( QStringLiteral(
"LayerStyles" ) );
631 for (
auto styleIt = mLayerStyleOverrides.constBegin(); styleIt != mLayerStyleOverrides.constEnd(); ++styleIt )
633 QDomElement styleElem = doc.createElement( QStringLiteral(
"LayerStyle" ) );
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 );
645 stylesElem.appendChild( styleElem );
647 mapElem.appendChild( stylesElem );
651 mGridStack->writeXml( mapElem, doc, context );
654 mOverviewStack->writeXml( mapElem, doc, context );
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 );
663 mapElem.setAttribute( QStringLiteral(
"labelMargin" ), mLabelMargin.
encodeMeasurement() );
664 mapElem.setAttribute( QStringLiteral(
"mapFlags" ),
static_cast< int>( mMapFlags ) );
666 QDomElement labelBlockingItemsElem = doc.createElement( QStringLiteral(
"labelBlockingItems" ) );
667 for (
const auto &item : qgis::as_const( mBlockingLabelItems ) )
672 QDomElement blockingItemElem = doc.createElement( QStringLiteral(
"item" ) );
673 blockingItemElem.setAttribute( QStringLiteral(
"uuid" ), item->uuid() );
674 labelBlockingItemsElem.appendChild( blockingItemElem );
676 mapElem.appendChild( labelBlockingItemsElem );
679 mapElem.setAttribute( QStringLiteral(
"isTemporal" ),
isTemporal() ? 1 : 0 );
682 mapElem.setAttribute( QStringLiteral(
"temporalRangeBegin" ),
temporalRange().begin().toString( Qt::ISODate ) );
683 mapElem.setAttribute( QStringLiteral(
"temporalRangeEnd" ),
temporalRange().end().toString( Qt::ISODate ) );
686 mAtlasClippingSettings->
writeXml( mapElem, doc, context );
687 mItemClippingSettings->
writeXml( mapElem, doc, context );
694 mUpdatesEnabled =
false;
697 QDomNodeList extentNodeList = itemElem.elementsByTagName( QStringLiteral(
"Extent" ) );
698 if ( !extentNodeList.isEmpty() )
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();
709 QDomNodeList crsNodeList = itemElem.elementsByTagName( QStringLiteral(
"crs" ) );
710 if ( !crsNodeList.isEmpty() )
712 QDomElement crsElem = crsNodeList.at( 0 ).toElement();
721 mMapRotation = itemElem.attribute( QStringLiteral(
"mapRotation" ), QStringLiteral(
"0" ) ).toDouble();
722 mEvaluatedMapRotation = mMapRotation;
725 mFollowVisibilityPreset = itemElem.attribute( QStringLiteral(
"followPreset" ) ).compare( QLatin1String(
"true" ) ) == 0;
726 mFollowVisibilityPresetName = itemElem.attribute( QStringLiteral(
"followPresetName" ) );
729 QString keepLayerSetFlag = itemElem.attribute( QStringLiteral(
"keepLayerSet" ) );
730 if ( keepLayerSetFlag.compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0 )
732 mKeepLayerSet =
true;
736 mKeepLayerSet =
false;
739 QString drawCanvasItemsFlag = itemElem.attribute( QStringLiteral(
"drawCanvasItems" ), QStringLiteral(
"true" ) );
740 if ( drawCanvasItemsFlag.compare( QLatin1String(
"true" ), Qt::CaseInsensitive ) == 0 )
742 mDrawAnnotations =
true;
746 mDrawAnnotations =
false;
749 mLayerStyleOverrides.clear();
753 QDomNodeList layerSetNodeList = itemElem.elementsByTagName( QStringLiteral(
"LayerSet" ) );
754 if ( !layerSetNodeList.isEmpty() )
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 )
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" ) );
767 QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
774 QDomNodeList layerStylesNodeList = itemElem.elementsByTagName( QStringLiteral(
"LayerStyles" ) );
775 mKeepLayerStyles = !layerStylesNodeList.isEmpty();
776 if ( mKeepLayerStyles )
778 QDomElement layerStylesElem = layerStylesNodeList.at( 0 ).toElement();
779 QDomNodeList layerStyleNodeList = layerStylesElem.elementsByTagName( QStringLiteral(
"LayerStyle" ) );
780 for (
int i = 0; i < layerStyleNodeList.size(); ++i )
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 );
791 style.
readXml( layerStyleElement );
797 mNumCachedLayers = 0;
798 mCacheInvalidated =
true;
801 mOverviewStack->readXml( itemElem, doc, context );
804 mGridStack->readXml( itemElem, doc, context );
807 QDomNodeList atlasNodeList = itemElem.elementsByTagName( QStringLiteral(
"AtlasMap" ) );
808 if ( !atlasNodeList.isEmpty() )
810 QDomElement atlasElem = atlasNodeList.at( 0 ).toElement();
811 mAtlasDriven = ( atlasElem.attribute( QStringLiteral(
"atlasDriven" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) );
812 if ( atlasElem.hasAttribute( QStringLiteral(
"fixedScale" ) ) )
814 mAtlasScalingMode = ( atlasElem.attribute( QStringLiteral(
"fixedScale" ), QStringLiteral(
"0" ) ) != QLatin1String(
"0" ) ) ?
Fixed :
Auto;
816 else if ( atlasElem.hasAttribute( QStringLiteral(
"scalingMode" ) ) )
818 mAtlasScalingMode =
static_cast<AtlasScalingMode>( atlasElem.attribute( QStringLiteral(
"scalingMode" ) ).toInt() );
820 mAtlasMargin = atlasElem.attribute( QStringLiteral(
"margin" ), QStringLiteral(
"0.1" ) ).toDouble();
825 mMapFlags =
static_cast< MapItemFlags
>( itemElem.attribute( QStringLiteral(
"mapFlags" ),
nullptr ).toInt() );
828 mBlockingLabelItems.clear();
829 mBlockingLabelItemUuids.clear();
830 QDomNodeList labelBlockingNodeList = itemElem.elementsByTagName( QStringLiteral(
"labelBlockingItems" ) );
831 if ( !labelBlockingNodeList.isEmpty() )
833 QDomElement blockingItems = labelBlockingNodeList.at( 0 ).toElement();
834 QDomNodeList labelBlockingNodeList = blockingItems.childNodes();
835 for (
int i = 0; i < labelBlockingNodeList.size(); ++i )
837 const QDomElement &itemBlockingElement = labelBlockingNodeList.at( i ).toElement();
838 const QString itemUuid = itemBlockingElement.attribute( QStringLiteral(
"uuid" ) );
839 mBlockingLabelItemUuids << itemUuid;
843 mAtlasClippingSettings->
readXml( itemElem, doc, context );
844 mItemClippingSettings->
readXml( itemElem, doc, context );
849 setIsTemporal( itemElem.attribute( QStringLiteral(
"isTemporal" ) ).toInt() );
852 QDateTime begin = QDateTime::fromString( itemElem.attribute( QStringLiteral(
"temporalRangeBegin" ) ), Qt::ISODate );
853 QDateTime end = QDateTime::fromString( itemElem.attribute( QStringLiteral(
"temporalRangeEnd" ) ), Qt::ISODate );
857 mUpdatesEnabled =
true;
863 if ( mItemClippingSettings->
isActive() )
874 if ( !
mLayout || !painter || !painter->device() || !mUpdatesEnabled )
883 QRectF thisPaintRect = rect();
889 if (
mLayout->renderContext().isPreviewRender() )
892 painter->setClipRect( thisPaintRect );
893 if ( !mCacheFinalImage || mCacheFinalImage->isNull() )
896 painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
897 painter->drawRect( thisPaintRect );
898 painter->setBrush( Qt::NoBrush );
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 )
908 mBackgroundUpdateTimer->start( 1 );
910 else if ( !mPainterJob && !mDrawingPreview )
914 mBackgroundUpdateTimer->start( 1 );
919 if ( mCacheInvalidated && !mDrawingPreview )
923 mBackgroundUpdateTimer->start( 1 );
928 double imagePixelWidth = mCacheFinalImage->width();
929 double scale = rect().width() / imagePixelWidth;
933 painter->translate( mLastRenderedImageOffsetX + mXOffset, mLastRenderedImageOffsetY + mYOffset );
935 painter->drawImage( 0, 0, *mCacheFinalImage );
940 painter->setClipRect( thisPaintRect, Qt::NoClip );
942 mOverviewStack->drawItems( painter,
false );
943 mGridStack->drawItems( painter );
945 drawMapFrame( painter );
953 QPaintDevice *paintDevice = painter->device();
960 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
962 painter->setRenderHint( QPainter::LosslessImageRendering,
true );
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 );
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 );
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 );
987 p.translate( imagePaintRect.topLeft() );
991 if ( shouldDrawPart( Background ) )
993 p.scale( dotsPerMM, dotsPerMM );
994 drawMapBackground( &p );
995 p.scale( 1.0 / dotsPerMM, 1.0 / dotsPerMM );
998 drawMap( &p, cExtent, imagePaintRect.size(), image.logicalDpiX() );
1003 p.scale( dotsPerMM, dotsPerMM );
1005 if ( shouldDrawPart( OverviewMapExtent ) )
1007 mOverviewStack->drawItems( &p,
false );
1009 if ( shouldDrawPart( Grid ) )
1011 mGridStack->drawItems( &p );
1016 painter->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1017 painter->drawImage( QPointF( -tl.x()* dotsPerMM, -tl.y() * dotsPerMM ), image );
1018 painter->scale( dotsPerMM, dotsPerMM );
1023 if ( shouldDrawPart( Background ) )
1025 drawMapBackground( painter );
1029 painter->setClipRect( thisPaintRect );
1034 painter->translate( mXOffset, mYOffset );
1036 double dotsPerMM = paintDevice->logicalDpiX() / 25.4;
1038 painter->scale( 1 / dotsPerMM, 1 / dotsPerMM );
1040 if ( mCurrentExportPart != NotLayered )
1042 if ( !mStagedRendererJob )
1044 createStagedRenderJob( cExtent, size, paintDevice->logicalDpiX() );
1047 mStagedRendererJob->renderCurrentPart( painter );
1051 drawMap( painter, cExtent, size, paintDevice->logicalDpiX() );
1055 painter->setClipRect( thisPaintRect, Qt::NoClip );
1057 if ( shouldDrawPart( OverviewMapExtent ) )
1059 mOverviewStack->drawItems( painter,
false );
1061 if ( shouldDrawPart( Grid ) )
1063 mGridStack->drawItems( painter );
1068 if ( shouldDrawPart( Frame ) )
1070 drawMapFrame( painter );
1081 + ( layerCount + ( layerCount ? 1 : 0 ) )
1082 + ( mGridStack->hasEnabledItems() ? 1 : 0 )
1083 + ( mOverviewStack->hasEnabledItems() ? 1 : 0 )
1089 mCurrentExportPart = Start;
1091 mExportThemes = !mFollowVisibilityPreset ?
mLayout->renderContext().exportThemes() : QStringList();
1092 mExportThemeIt = mExportThemes.begin();
1097 mCurrentExportPart = NotLayered;
1098 mExportThemes.clear();
1099 mExportThemeIt = mExportThemes.begin();
1104 switch ( mCurrentExportPart )
1109 mCurrentExportPart = Background;
1115 mCurrentExportPart = Layer;
1119 if ( mStagedRendererJob )
1121 if ( mStagedRendererJob->nextPart() )
1124 mStagedRendererJob.reset();
1127 if ( mExportThemeIt != mExportThemes.end() && ++mExportThemeIt != mExportThemes.end() )
1133 if ( mGridStack->hasEnabledItems() )
1135 mCurrentExportPart = Grid;
1141 for (
int i = 0; i < mOverviewStack->size(); ++i )
1146 mCurrentExportPart = OverviewMapExtent;
1152 case OverviewMapExtent:
1155 mCurrentExportPart = Frame;
1162 if ( isSelected() && !
mLayout->renderContext().isPreviewRender() )
1164 mCurrentExportPart = SelectionBoxes;
1169 case SelectionBoxes:
1170 mCurrentExportPart = End;
1191 switch ( mCurrentExportPart )
1201 if ( !mExportThemes.empty() && mExportThemeIt != mExportThemes.end() )
1204 if ( mStagedRendererJob )
1206 switch ( mStagedRendererJob->currentStage() )
1210 detail.
mapLayerId = mStagedRendererJob->currentLayerId();
1211 detail.
compositionMode = mStagedRendererJob->currentLayerCompositionMode();
1212 detail.
opacity = mStagedRendererJob->currentLayerOpacity();
1218 detail.
name = QStringLiteral(
"%1: %2" ).arg(
displayName(), layer->name() );
1220 else if (
mLayout->project()->mainAnnotationLayer()->id() == detail.
mapLayerId )
1226 detail.
name = QStringLiteral(
"%1: %2" ).arg(
displayName(), tr(
"Annotations" ) );
1231 const QList<QgsLayoutItemMapOverview *> res = mOverviewStack->asList();
1237 if ( item->mapLayer() && detail.
mapLayerId == item->mapLayer()->id() )
1240 detail.
name = QStringLiteral(
"%1 (%2): %3" ).arg(
displayName(), detail.
mapTheme, item->mapLayer()->name() );
1242 detail.
name = QStringLiteral(
"%1: %2" ).arg(
displayName(), item->mapLayer()->name() );
1251 detail.
mapLayerId = mStagedRendererJob->currentLayerId();
1257 detail.
name = tr(
"%1: %2 (Labels)" ).arg(
displayName(), layer->name() );
1292 case OverviewMapExtent:
1300 case SelectionBoxes:
1315 void QgsLayoutItemMap::drawMap( QPainter *painter,
const QgsRectangle &extent, QSizeF size,
double dpi )
1329 if ( shouldDrawPart( OverviewMapExtent ) )
1331 ms.setLayers( mOverviewStack->modifyMapLayerList( ms.layers() ) );
1338 job.renderSynchronously();
1340 mRenderingErrors = job.errors();
1343 void QgsLayoutItemMap::recreateCachedImageInBackground()
1349 QPainter *oldPainter = mPainter.release();
1350 QImage *oldImage = mCacheRenderingImage.release();
1353 oldJob->deleteLater();
1361 mCacheRenderingImage.reset(
nullptr );
1365 Q_ASSERT( !mPainterJob );
1366 Q_ASSERT( !mPainter );
1367 Q_ASSERT( !mCacheRenderingImage );
1373 int w =
static_cast< int >( std::round( widthLayoutUnits * mPreviewScaleFactor ) );
1374 int h =
static_cast< int >( std::round( heightLayoutUnits * mPreviewScaleFactor ) );
1377 if ( w > 5000 || h > 5000 )
1382 h =
static_cast< int>( std::round( w * heightLayoutUnits / widthLayoutUnits ) );
1387 w =
static_cast< int >( std::round( h * widthLayoutUnits / heightLayoutUnits ) );
1391 if ( w <= 0 || h <= 0 )
1394 mCacheRenderingImage.reset(
new QImage( w, h, QImage::Format_ARGB32 ) );
1397 mCacheRenderingImage->setDotsPerMeterX(
static_cast< int >( std::round( 1000 * w / widthLayoutUnits ) ) );
1398 mCacheRenderingImage->setDotsPerMeterY(
static_cast< int >( std::round( 1000 * h / heightLayoutUnits ) ) );
1401 mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
1406 if ( mItemClippingSettings->
isActive() )
1408 QPainter p( mCacheRenderingImage.get() );
1410 p.setPen( Qt::NoPen );
1412 p.scale( mCacheRenderingImage->width() / widthLayoutUnits, mCacheRenderingImage->height() / heightLayoutUnits );
1422 mCacheInvalidated =
false;
1423 mPainter.reset(
new QPainter( mCacheRenderingImage.get() ) );
1426 if ( shouldDrawPart( OverviewMapExtent ) )
1428 settings.setLayers( mOverviewStack->modifyMapLayerList( settings.layers() ) );
1433 mPainterJob->start();
1445 mDrawingPreview =
false;
1469 jobMapSettings.
setRotation( mEvaluatedMapRotation );
1473 if ( includeLayerSettings )
1478 if ( !
mLayout->project()->mainAnnotationLayer()->isEmpty() )
1481 layers.insert( 0,
mLayout->project()->mainAnnotationLayer() );
1488 if ( !
mLayout->renderContext().isPreviewRender() )
1525 if ( mEvaluatedLabelMargin.
length() > 0 )
1528 visiblePoly.append( visiblePoly.at( 0 ) );
1529 const double layoutLabelMargin =
mLayout->convertToLayoutUnits( mEvaluatedLabelMargin );
1530 const double layoutLabelMarginInMapUnits = layoutLabelMargin / rect().width() * jobMapSettings.
extent().
width();
1532 mapBoundaryGeom = mapBoundaryGeom.
buffer( -layoutLabelMarginInMapUnits, 0 );
1533 labelBoundary = mapBoundaryGeom;
1536 if ( !mBlockingLabelItems.isEmpty() )
1549 if ( mAtlasClippingSettings->
enabled() &&
mLayout->reportContext().feature().isValid() )
1560 if ( !labelBoundary.
isEmpty() )
1562 labelBoundary = clipGeom.
intersection( labelBoundary );
1566 labelBoundary = clipGeom;
1571 if ( mItemClippingSettings->
isActive() )
1580 const double layoutLabelMargin =
mLayout->convertToLayoutUnits( mEvaluatedLabelMargin );
1581 const double layoutLabelMarginInMapUnits = layoutLabelMargin / rect().width() * jobMapSettings.
extent().
width();
1583 mapBoundaryGeom = mapBoundaryGeom.
buffer( -layoutLabelMarginInMapUnits, 0 );
1584 if ( !labelBoundary.
isEmpty() )
1586 labelBoundary = mapBoundaryGeom.
intersection( labelBoundary );
1590 labelBoundary = mapBoundaryGeom;
1596 if ( !labelBoundary.
isNull() )
1599 return jobMapSettings;
1606 mBlockingLabelItems.clear();
1607 for (
const QString &
uuid : qgis::as_const( mBlockingLabelItemUuids ) )
1616 mOverviewStack->finalizeRestoreFromXml();
1617 mGridStack->finalizeRestoreFromXml();
1629 return mCurrentRectangle;
1662 QVariantList layersIds;
1672 const QList<QgsMapLayer *> layersInMap =
layersToRender( &context );
1674 layersIds.reserve( layersInMap.count() );
1675 layers.reserve( layersInMap.count() );
1678 layersIds << layer->id();
1684 scope->
addFunction( QStringLiteral(
"is_layer_visible" ),
new QgsExpressionContextUtils::GetLayerVisibility( layersInMap,
scale() ) );
1696 if ( extentWidth <= 0 )
1700 return rect().width() / extentWidth;
1705 double dx = mXOffset;
1706 double dy = mYOffset;
1707 transformShift( dx, dy );
1708 QPolygonF poly = calculateVisibleExtentPolygon(
false );
1709 poly.translate( -dx, -dy );
1715 if ( !mBlockingLabelItems.contains( item ) )
1716 mBlockingLabelItems.append( item );
1723 mBlockingLabelItems.removeAll( item );
1730 return mBlockingLabelItems.contains( item );
1739 if ( mOverviewStack )
1741 for (
int i = 0; i < mOverviewStack->size(); ++i )
1743 if ( mOverviewStack->item( i )->accept( visitor ) )
1750 for (
int i = 0; i < mGridStack->size(); ++i )
1752 if ( mGridStack->item( i )->accept( visitor ) )
1765 mRenderedFeatureHandlers.append( handler );
1770 mRenderedFeatureHandlers.removeAll( handler );
1776 if ( mapPoly.empty() )
1778 return QPointF( 0, 0 );
1783 double dx = mapCoords.x() - rotationPoint.
x();
1784 double dy = mapCoords.y() - rotationPoint.
y();
1786 QgsPointXY backRotatedCoords( rotationPoint.
x() + dx, rotationPoint.
y() + dy );
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 );
1805 mapPolygon( newExtent, poly );
1806 QRectF bRect = poly.boundingRect();
1820 mCacheInvalidated =
true;
1826 QRectF rectangle = rect();
1827 double frameExtension =
frameEnabled() ? pen().widthF() / 2.0 : 0.0;
1829 double topExtension = 0.0;
1830 double rightExtension = 0.0;
1831 double bottomExtension = 0.0;
1832 double leftExtension = 0.0;
1835 mGridStack->calculateMaxGridExtension( topExtension, rightExtension, bottomExtension, leftExtension );
1837 topExtension = std::max( topExtension, frameExtension );
1838 rightExtension = std::max( rightExtension, frameExtension );
1839 bottomExtension = std::max( bottomExtension, frameExtension );
1840 leftExtension = std::max( leftExtension, frameExtension );
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 )
1848 prepareGeometryChange();
1849 mCurrentRectangle = rectangle;
1871 refreshMapExtents( &context );
1873 if ( mExtent != beforeExtent )
1880 refreshLabelMargin(
false );
1884 const QString previousTheme = mLastEvaluatedThemeName.isEmpty() ? mFollowVisibilityPresetName : mLastEvaluatedThemeName;
1886 if ( mLastEvaluatedThemeName != previousTheme )
1904 mCacheInvalidated =
true;
1909 void QgsLayoutItemMap::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
1911 if ( !mLayers.isEmpty() || mLayerStyleOverrides.isEmpty() )
1915 mLayerStyleOverrides.remove( layer->id() );
1917 _qgis_removeLayers( mLayers,
layers );
1921 void QgsLayoutItemMap::painterJobFinished()
1924 mPainterJob.reset(
nullptr );
1925 mPainter.reset(
nullptr );
1926 mCacheFinalImage = std::move( mCacheRenderingImage );
1927 mLastRenderedImageOffsetX = 0;
1928 mLastRenderedImageOffsetY = 0;
1933 void QgsLayoutItemMap::shapeChanged()
1938 double w = rect().width();
1939 double h = rect().height();
1942 double newWidth = mExtent.
width();
1944 double newHeight = newWidth * h / w;
1949 refreshMapExtents();
1956 void QgsLayoutItemMap::mapThemeChanged(
const QString &theme )
1958 if ( theme == mCachedLayerStyleOverridesPresetName )
1959 mCachedLayerStyleOverridesPresetName.clear();
1962 void QgsLayoutItemMap::currentMapThemeRenamed(
const QString &theme,
const QString &newTheme )
1964 if ( theme == mFollowVisibilityPresetName )
1966 mFollowVisibilityPresetName = newTheme;
1970 void QgsLayoutItemMap::connectUpdateSlot()
1978 this, &QgsLayoutItemMap::layersAboutToBeRemoved );
1982 if ( layers().isEmpty() )
2010 if ( mAtlasScalingMode == Predefined )
2011 updateAtlasFeature();
2017 QPolygonF thisExtent = calculateVisibleExtentPolygon(
false );
2018 QTransform mapTransform;
2019 QPolygonF thisRectPoly = QPolygonF( QRectF( 0, 0, rect().width(), rect().height() ) );
2021 thisRectPoly.pop_back();
2022 thisExtent.pop_back();
2024 QPolygonF thisItemPolyInLayout = mapToScene( thisRectPoly );
2027 QTransform::quadToQuad( thisItemPolyInLayout, thisExtent, mapTransform );
2028 return mapTransform;
2031 QList<QgsLabelBlockingRegion> QgsLayoutItemMap::createLabelBlockingRegions(
const QgsMapSettings & )
const
2034 QList< QgsLabelBlockingRegion > blockers;
2035 blockers.reserve( mBlockingLabelItems.count() );
2036 for (
const auto &item : qgis::as_const( mBlockingLabelItems ) )
2043 if ( item->property(
"wasVisible" ).isValid() )
2045 if ( !item->property(
"wasVisible" ).toBool() )
2048 else if ( !item->isVisible() )
2051 QPolygonF itemRectInMapCoordinates = mapTransform.map( item->mapToScene( item->rect() ) );
2052 itemRectInMapCoordinates.append( itemRectInMapCoordinates.at( 0 ) );
2061 return mLabelMargin;
2066 mLabelMargin = margin;
2067 refreshLabelMargin(
false );
2070 void QgsLayoutItemMap::updateToolTip()
2079 if ( mFollowVisibilityPreset )
2081 presetName = mFollowVisibilityPresetName;
2085 else if ( !mExportThemes.empty() && mExportThemeIt != mExportThemes.end() )
2086 presetName = *mExportThemeIt;
2097 QList<QgsMapLayer *> renderLayers;
2099 QString presetName = themeToRender( *evalContext );
2100 if ( !presetName.isEmpty() )
2102 if (
mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2103 renderLayers =
mLayout->project()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
2105 renderLayers =
mLayout->project()->mapThemeCollection()->masterVisibleLayers();
2107 else if ( !
layers().isEmpty() )
2113 renderLayers =
mLayout->project()->mapThemeCollection()->masterVisibleLayers();
2120 renderLayers.clear();
2122 const QStringList layerNames = ddLayers.split(
'|' );
2124 for (
const QString &name : layerNames )
2126 const QList< QgsMapLayer * > matchingLayers =
mLayout->project()->mapLayersByName( name );
2129 renderLayers << layer;
2138 int removeAt = renderLayers.indexOf(
mLayout->reportContext().layer() );
2139 if ( removeAt != -1 )
2141 renderLayers.removeAt( removeAt );
2146 renderLayers.erase( std::remove_if( renderLayers.begin(), renderLayers.end(), [](
QgsMapLayer * layer )
2148 return !layer || !layer->isValid();
2149 } ), renderLayers.end() );
2151 return renderLayers;
2154 QMap<QString, QString> QgsLayoutItemMap::layerStyleOverridesToRender(
const QgsExpressionContext &context )
const
2156 QString presetName = themeToRender( context );
2157 if ( !presetName.isEmpty() )
2159 if (
mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2161 if ( presetName != mCachedLayerStyleOverridesPresetName )
2164 mCachedPresetLayerStyleOverrides =
mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( presetName );
2165 mCachedLayerStyleOverridesPresetName = presetName;
2168 return mCachedPresetLayerStyleOverrides;
2171 return QMap<QString, QString>();
2173 else if ( mFollowVisibilityPreset )
2175 QString presetName = mFollowVisibilityPresetName;
2178 if (
mLayout->project()->mapThemeCollection()->hasMapTheme( presetName ) )
2180 if ( presetName.isEmpty() || presetName != mCachedLayerStyleOverridesPresetName )
2183 mCachedPresetLayerStyleOverrides =
mLayout->project()->mapThemeCollection()->mapThemeStyleOverrides( presetName );
2184 mCachedLayerStyleOverridesPresetName = presetName;
2187 return mCachedPresetLayerStyleOverrides;
2190 return QMap<QString, QString>();
2192 else if ( mKeepLayerStyles )
2194 return mLayerStyleOverrides;
2198 return QMap<QString, QString>();
2202 QgsRectangle QgsLayoutItemMap::transformedExtent()
const
2204 double dx = mXOffset;
2205 double dy = mYOffset;
2206 transformShift( dx, dy );
2210 void QgsLayoutItemMap::mapPolygon(
const QgsRectangle &extent, QPolygonF &poly )
const
2220 poly << QPointF( poly.at( 0 ) );
2232 poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2238 poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2244 poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2250 poly << QPointF( rotationPoint.x() - dx, rotationPoint.y() - dy );
2253 poly << QPointF( poly.at( 0 ) );
2256 void QgsLayoutItemMap::transformShift(
double &xShift,
double &yShift )
const
2259 double dxScaled = xShift * mmToMapUnits;
2260 double dyScaled = - yShift * mmToMapUnits;
2275 const QList< QgsAnnotation * > annotations =
mLayout->project()->annotationManager()->annotations();
2276 if ( annotations.isEmpty() )
2286 if ( !annotation || !annotation->isVisible() )
2290 if ( annotation->mapLayer() && !
layers.contains( annotation->mapLayer() ) )
2293 drawAnnotation( annotation, rc );
2307 double itemX, itemY;
2310 QPointF mapPos = layoutMapPosForItem( annotation );
2319 context.
painter()->translate( itemX, itemY );
2322 double dotsPerMM = context.
painter()->device()->logicalDpiX() / 25.4;
2323 context.
painter()->scale( 1 / dotsPerMM, 1 / dotsPerMM );
2325 annotation->
render( context );
2328 QPointF QgsLayoutItemMap::layoutMapPosForItem(
const QgsAnnotation *annotation )
const
2331 return QPointF( 0, 0 );
2340 if ( annotationCrs !=
crs() )
2347 t.transformInPlace( mapX, mapY, z );
2357 void QgsLayoutItemMap::drawMapFrame( QPainter *p )
2368 void QgsLayoutItemMap::drawMapBackground( QPainter *p )
2379 bool QgsLayoutItemMap::shouldDrawPart( QgsLayoutItemMap::PartType part )
const
2381 if ( mCurrentExportPart == NotLayered )
2399 return mCurrentExportPart == Layer;
2402 return mCurrentExportPart == Grid && mGridStack->hasEnabledItems();
2404 case OverviewMapExtent:
2405 return mCurrentExportPart == OverviewMapExtent && mOverviewStack->hasEnabledItems();
2410 case SelectionBoxes:
2411 return mCurrentExportPart == SelectionBoxes && isSelected();
2432 bool useDdXMin =
false;
2433 bool useDdXMax =
false;
2434 bool useDdYMin =
false;
2435 bool useDdYMax =
false;
2466 if ( newExtent != mExtent )
2472 double currentWidthHeightRatio = mExtent.
width() / mExtent.
height();
2473 double newWidthHeightRatio = newExtent.
width() / newExtent.
height();
2475 if ( currentWidthHeightRatio < newWidthHeightRatio )
2478 double newHeight = newExtent.
width() / currentWidthHeightRatio;
2479 double deltaHeight = newHeight - newExtent.
height();
2486 double newWidth = currentWidthHeightRatio * newExtent.
height();
2487 double deltaWidth = newWidth - newExtent.
width();
2492 mExtent = newExtent;
2502 newExtent = mExtent;
2505 if ( useDdXMax || useDdXMin || useDdYMax || useDdYMin )
2509 if ( useDdXMin && !useDdXMax )
2515 else if ( !useDdXMin && useDdXMax )
2521 if ( useDdYMin && !useDdYMax )
2527 else if ( !useDdYMin && useDdYMax )
2534 if ( newExtent != mExtent )
2536 mExtent = newExtent;
2553 void QgsLayoutItemMap::refreshLabelMargin(
bool updateItem )
2566 void QgsLayoutItemMap::updateAtlasFeature()
2585 if ( mAtlasScalingMode ==
Fixed || mAtlasScalingMode ==
Predefined || isPointLayer )
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() )
2596 scales =
mLayout->reportContext().predefinedScales();
2598 scales =
mLayout->renderContext().predefinedScales();
2600 if ( mAtlasScalingMode ==
Fixed || isPointLayer || scales.isEmpty() )
2603 double xMin = geomCenterX - originalExtent.
width() / 2.0;
2604 double yMin = geomCenterY - originalExtent.
height() / 2.0;
2607 xMin + originalExtent.
width(),
2608 yMin + originalExtent.
height() );
2612 double newScale = calc.
calculate( newExtent, rect().width() );
2613 newExtent.
scale( originalScale / newScale );
2618 double newWidth = originalExtent.
width();
2619 double newHeight = originalExtent.
height();
2620 for (
int i = 0; i < scales.size(); i++ )
2622 double ratio = scales[i] / originalScale;
2623 newWidth = originalExtent.
width() * ratio;
2624 newHeight = originalExtent.
height() * ratio;
2627 double xMin = geomCenterX - newWidth / 2.0;
2628 double yMin = geomCenterY - newHeight / 2.0;
2636 double newScale = calc.
calculate( newExtent, rect().width() );
2637 newExtent.
scale( scales[i] / newScale );
2647 else if ( mAtlasScalingMode ==
Auto )
2651 double geomRatio = bounds.
width() / bounds.
height();
2652 double mapRatio = originalExtent.
width() / originalExtent.
height();
2655 if ( geomRatio < mapRatio )
2658 double adjWidth = ( mapRatio * bounds.
height() - bounds.
width() ) / 2.0;
2663 else if ( geomRatio > mapRatio )
2666 double adjHeight = ( bounds.
width() / mapRatio - bounds.
height() ) / 2.0;
2672 const double evaluatedAtlasMargin =
atlasMargin();
2673 if ( evaluatedAtlasMargin > 0.0 )
2675 newExtent.
scale( 1 + evaluatedAtlasMargin );
2691 if ( mEvaluatedMapRotation != 0.0 )
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() ) );
2707 center.
x() + dx, center.
y() + dy );
2715 void QgsLayoutItemMap::createStagedRenderJob(
const QgsRectangle &extent,
const QSizeF size,
double dpi )
2718 settings.
setLayers( mOverviewStack->modifyMapLayerList( settings.
layers() ) );
2720 mStagedRendererJob = qgis::make_unique< QgsMapRendererStagedRenderJob >( settings,
2723 : QgsMapRendererStagedRenderJob::Flags() );
2724 mStagedRendererJob->start();
2740 this, &QgsLayoutItemMapAtlasClippingSettings::layersAboutToBeRemoved );
2746 return mClipToAtlasFeature;
2751 if (
enabled == mClipToAtlasFeature )
2754 mClipToAtlasFeature =
enabled;
2760 return mFeatureClippingType;
2765 if ( mFeatureClippingType == type )
2768 mFeatureClippingType = type;
2774 return mForceLabelsInsideFeature;
2779 if ( forceInside == mForceLabelsInsideFeature )
2782 mForceLabelsInsideFeature = forceInside;
2788 return mRestrictToLayers;
2793 if ( mRestrictToLayers ==
enabled )
2802 return _qgis_listRefToRaw( mLayersToClip );
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" ) );
2820 QDomElement layerSetElem = document.createElement( QStringLiteral(
"layersToClip" ) );
2825 QDomElement layerElem = document.createElement( QStringLiteral(
"Layer" ) );
2826 QDomText layerIdText = document.createTextNode( layerRef.layerId );
2827 layerElem.appendChild( layerIdText );
2829 layerElem.setAttribute( QStringLiteral(
"name" ), layerRef.name );
2830 layerElem.setAttribute( QStringLiteral(
"source" ), layerRef.source );
2831 layerElem.setAttribute( QStringLiteral(
"provider" ), layerRef.provider );
2833 layerSetElem.appendChild( layerElem );
2835 settingsElem.appendChild( layerSetElem );
2837 element.appendChild( settingsElem );
2843 const QDomElement settingsElem = element.firstChildElement( QStringLiteral(
"atlasClippingSettings" ) );
2845 mClipToAtlasFeature = settingsElem.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt();
2846 mForceLabelsInsideFeature = settingsElem.attribute( QStringLiteral(
"forceLabelsInside" ), QStringLiteral(
"0" ) ).toInt();
2848 mRestrictToLayers = settingsElem.attribute( QStringLiteral(
"restrictLayers" ), QStringLiteral(
"0" ) ).toInt();
2850 mLayersToClip.clear();
2851 QDomNodeList layerSetNodeList = settingsElem.elementsByTagName( QStringLiteral(
"layersToClip" ) );
2852 if ( !layerSetNodeList.isEmpty() )
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 )
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" ) );
2865 QgsMapLayerRef ref( layerId, layerName, layerSource, layerProvider );
2868 mLayersToClip << ref;
2875 void QgsLayoutItemMapAtlasClippingSettings::layersAboutToBeRemoved(
const QList<QgsMapLayer *> &layers )
2877 if ( !mLayersToClip.isEmpty() )
2879 _qgis_removeLayers( mLayersToClip, layers );
2894 return mEnabled && mClipPathSource;
2909 if ( mClipPathSource )
2912 mClipPathSource->refresh();
2921 QgsGeometry clipGeom( mClipPathSource->clipPath() );
2932 QgsGeometry clipGeom( mClipPathSource->clipPath() );
2933 clipGeom.
transform( mMap->sceneTransform().inverted() );
2948 if ( mClipPathSource == item )
2951 if ( mClipPathSource )
2960 mClipPathSource = item;
2962 if ( mClipPathSource )
2971 mClipPathSource->refresh();
2985 return mClipPathSource;
2990 return mFeatureClippingType;
2995 if ( mFeatureClippingType == type )
2998 mFeatureClippingType = type;
3004 return mForceLabelsInsideClipPath;
3009 if ( forceInside == mForceLabelsInsideClipPath )
3012 mForceLabelsInsideClipPath = forceInside;
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() );
3025 settingsElem.setAttribute( QStringLiteral(
"clipSource" ), QString() );
3027 element.appendChild( settingsElem );
3033 const QDomElement settingsElem = element.firstChildElement( QStringLiteral(
"itemClippingSettings" ) );
3035 mEnabled = settingsElem.attribute( QStringLiteral(
"enabled" ), QStringLiteral(
"0" ) ).toInt();
3036 mForceLabelsInsideClipPath = settingsElem.attribute( QStringLiteral(
"forceLabelsInside" ), QStringLiteral(
"0" ) ).toInt();
3038 mClipPathUuid = settingsElem.attribute( QStringLiteral(
"clipSource" ) );
3045 if ( !mClipPathUuid.isEmpty() )