[layouts] Ensure overview frames are correctly exporting during layer

based exports when the stacking position is set not set to above labels

Fixes #32763
This commit is contained in:
Nyall Dawson 2019-11-26 10:34:36 +10:00
parent 9fba322a73
commit 078f8451e0
9 changed files with 264 additions and 7 deletions

View File

@ -185,6 +185,13 @@ Returns ``True`` if the visitor should continue visiting other objects, or ``Fal
should be canceled.
.. versionadded:: 3.10
%End
virtual QgsMapLayer *mapLayer();
%Docstring
Returns the internal map layer used by this item, if available.
.. versionadded:: 3.10.1
%End
virtual QgsExpressionContext createExpressionContext() const;

View File

@ -238,6 +238,9 @@ Ownership of the layer remain with the overview item.
.. versionadded:: 3.6
%End
virtual QgsMapLayer *mapLayer();
virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;

View File

@ -1599,7 +1599,7 @@ bool QgsLayoutExporter::georeferenceOutputPrivate( const QString &file, QgsLayou
return true;
}
QString nameForLayerWithItems( const QList< QGraphicsItem * > items, unsigned int layerId )
QString nameForLayerWithItems( const QList< QGraphicsItem * > &items, unsigned int layerId )
{
if ( items.count() == 1 )
{

View File

@ -1059,10 +1059,14 @@ bool QgsLayoutItemMap::nextExportPart()
FALLTHROUGH
case Grid:
if ( mOverviewStack->hasEnabledItems() )
for ( int i = 0; i < mOverviewStack->size(); ++i )
{
mCurrentExportPart = OverviewMapExtent;
return true;
QgsLayoutItemMapItem *item = mOverviewStack->item( i );
if ( item->enabled() && item->stackingPosition() == QgsLayoutItemMapItem::StackAboveMapLabels )
{
mCurrentExportPart = OverviewMapExtent;
return true;
}
}
FALLTHROUGH
@ -1132,6 +1136,25 @@ QgsLayoutItem::ExportLayerDetail QgsLayoutItemMap::exportLayerDetails() const
else
detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), layer->name() );
}
else
{
// might be an item based layer
const QList<QgsLayoutItemMapOverview *> res = mOverviewStack->asList();
for ( QgsLayoutItemMapOverview *item : res )
{
if ( !item || !item->enabled() || item->stackingPosition() == QgsLayoutItemMapItem::StackAboveMapLabels )
continue;
if ( item->mapLayer() && detail.mapLayerId == item->mapLayer()->id() )
{
if ( !detail.mapTheme.isEmpty() )
detail.name = QStringLiteral( "%1 (%2): %3" ).arg( displayName(), detail.mapTheme, item->mapLayer()->name() );
else
detail.name = QStringLiteral( "%1: %2" ).arg( displayName(), item->mapLayer()->name() );
break;
}
}
}
return detail;
}
@ -2493,8 +2516,10 @@ QgsRectangle QgsLayoutItemMap::computeAtlasRectangle()
void QgsLayoutItemMap::createStagedRenderJob( const QgsRectangle &extent, const QSizeF size, double dpi )
{
// TODO - overview?
mStagedRendererJob = qgis::make_unique< QgsMapRendererStagedRenderJob >( mapSettings( extent, size, dpi, true ),
QgsMapSettings settings = mapSettings( extent, size, dpi, true );
settings.setLayers( mOverviewStack->modifyMapLayerList( settings.layers() ) );
mStagedRendererJob = qgis::make_unique< QgsMapRendererStagedRenderJob >( settings,
mLayout && mLayout->renderContext().flags() & QgsLayoutRenderContext::FlagRenderLabelsByMapLayer
? QgsMapRendererStagedRenderJob::RenderLabelsByMapLayer
: QgsMapRendererStagedRenderJob::Flags( nullptr ) );

View File

@ -134,6 +134,11 @@ bool QgsLayoutItemMapItem::accept( QgsStyleEntityVisitorInterface * ) const
return true;
}
QgsMapLayer *QgsLayoutItemMapItem::mapLayer()
{
return nullptr;
}
//
// QgsLayoutItemMapItemStack
//

View File

@ -189,6 +189,13 @@ class CORE_EXPORT QgsLayoutItemMapItem : public QgsLayoutObject
*/
virtual bool accept( QgsStyleEntityVisitorInterface *visitor ) const;
/**
* Returns the internal map layer used by this item, if available.
*
* \since QGIS 3.10.1
*/
virtual QgsMapLayer *mapLayer();
QgsExpressionContext createExpressionContext() const override;
protected:

View File

@ -34,7 +34,7 @@
QgsLayoutItemMapOverview::QgsLayoutItemMapOverview( const QString &name, QgsLayoutItemMap *map )
: QgsLayoutItemMapItem( name, map )
, mExtentLayer( qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=EPSG:4326" ), QStringLiteral( "overview" ), QStringLiteral( "memory" ), QgsVectorLayer::LayerOptions( map && map->layout() && map->layout()->project() ? map->layout()->project()->transformContext() : QgsCoordinateTransformContext() ) ) )
, mExtentLayer( qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=EPSG:4326" ), tr( "Overview" ), QStringLiteral( "memory" ), QgsVectorLayer::LayerOptions( map && map->layout() && map->layout()->project() ? map->layout()->project()->transformContext() : QgsCoordinateTransformContext() ) ) )
{
createDefaultFrameSymbol();
}
@ -309,6 +309,11 @@ QgsVectorLayer *QgsLayoutItemMapOverview::asMapLayer()
return mExtentLayer.get();
}
QgsMapLayer *QgsLayoutItemMapOverview::mapLayer()
{
return mExtentLayer.get();
}
bool QgsLayoutItemMapOverview::accept( QgsStyleEntityVisitorInterface *visitor ) const
{
if ( mFrameSymbol )

View File

@ -230,6 +230,8 @@ class CORE_EXPORT QgsLayoutItemMapOverview : public QgsLayoutItemMapItem
*/
QgsVectorLayer *asMapLayer();
QgsMapLayer *mapLayer() override;
bool accept( QgsStyleEntityVisitorInterface *visitor ) const override;
public slots:

View File

@ -1065,6 +1065,7 @@ void TestQgsLayoutMap::testLayeredExport()
map->setBackgroundEnabled( false );
map->overview()->setEnabled( true );
map->overview()->setStackingPosition( QgsLayoutItemMapItem::StackAboveMapLabels );
map->startLayeredExport();
QVERIFY( map->nextExportPart() );
map->createStagedRenderJob( map->extent(), QSize( 512, 512 ), 72 );
@ -1117,6 +1118,67 @@ void TestQgsLayoutMap::testLayeredExport()
QVERIFY( !map->nextExportPart() );
map->stopLayeredExport();
map->overview()->setStackingPosition( QgsLayoutItemMapItem::StackBelowMapLabels );
QgsLayoutItemMap *map2 = new QgsLayoutItemMap( &l );
map2->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) );
map2->setFrameEnabled( false );
map2->setBackgroundEnabled( false );
map2->setCrs( linesLayer->crs() );
map2->zoomToExtent( linesLayer->extent() );
map2->setLayers( QList<QgsMapLayer *>() << linesLayer );
l.addLayoutItem( map2 );
map->overview()->setLinkedMap( map2 );
map->startLayeredExport();
QVERIFY( map->nextExportPart() );
map->createStagedRenderJob( map->extent(), QSize( 512, 512 ), 72 );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: lines" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, linesLayer->id() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Overview" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, map->overview()->mapLayer()->id() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
// labels
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Labels" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Grids" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Frame" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
map->overview()->setStackingPosition( QgsLayoutItemMapItem::StackAboveMapLabels );
// add second layer
map->setLayers( QList<QgsMapLayer *>() << linesLayer << pointsLayer );
map->startLayeredExport();
@ -1390,6 +1452,147 @@ void TestQgsLayoutMap::testLayeredExport()
QVERIFY( !map->nextExportPart() );
map->stopLayeredExport();
map->overview()->setStackingPosition( QgsLayoutItemMapItem::StackBelowMapLabels );
map->startLayeredExport();
QVERIFY( map->nextExportPart() );
map->createStagedRenderJob( map->extent(), QSize( 512, 512 ), 72 );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Background" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset2): lines" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, linesLayer->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset2" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset2" ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset2): points" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, pointsLayer->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset2" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset2" ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset2): Overview" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, map->overview()->mapLayer()->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset2" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
// labels
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset2): Labels" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset2" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset2" ) );
QVERIFY( map->nextExportPart() );
// "test preset"
map->createStagedRenderJob( map->extent(), QSize( 512, 512 ), 72 );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset): lines" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, linesLayer->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset" ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset): Overview" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, map->overview()->mapLayer()->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
// labels
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset): Labels" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset" ) );
QVERIFY( map->nextExportPart() );
map->createStagedRenderJob( map->extent(), QSize( 512, 512 ), 72 );
// "test preset 3"
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset3): points" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, pointsLayer->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset3" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset3" ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset3): Overview" ) );
QCOMPARE( map->exportLayerDetails().mapLayerId, map->overview()->mapLayer()->id() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset3" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->nextExportPart() );
// labels
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1 (test preset3): Labels" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QCOMPARE( map->exportLayerDetails().mapTheme, QStringLiteral( "test preset3" ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QCOMPARE( map->themeToRender( QgsExpressionContext() ), QStringLiteral( "test preset3" ) );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Grids" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( map->themeToRender( QgsExpressionContext() ).isEmpty() );
QVERIFY( map->nextExportPart() );
QCOMPARE( map->exportLayerDetails().name, QStringLiteral( "Map 1: Frame" ) );
QVERIFY( map->exportLayerDetails().mapLayerId.isEmpty() );
QVERIFY( map->exportLayerDetails().mapTheme.isEmpty() );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Grid ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::OverviewMapExtent ) );
QVERIFY( map->shouldDrawPart( QgsLayoutItemMap::Frame ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Background ) );
QVERIFY( !map->shouldDrawPart( QgsLayoutItemMap::Layer ) );
QVERIFY( !map->nextExportPart() );
map->stopLayeredExport();
map->overview()->setStackingPosition( QgsLayoutItemMapItem::StackAboveMapLabels );
// but if map is already set to a particular map theme, it DOESN'T follow the theme iteration
map->setFollowVisibilityPreset( true );
map->setFollowVisibilityPresetName( QStringLiteral( "test preset" ) );