diff --git a/python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in b/python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in index 523ca86c8ed..5ea1247d472 100644 --- a/python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in +++ b/python/core/auto_generated/layout/qgslayoutitemmapitem.sip.in @@ -243,9 +243,13 @@ map item after restoration from XML. .. seealso:: :py:func:`readXml` %End - void drawItems( QPainter *painter ); + void drawItems( QPainter *painter, bool ignoreStacking = true ); %Docstring Draws the items from the stack on a specified ``painter``. + +If ``ignoreStacking`` is true, then all items will be drawn, regardless +of their actual stacking position settings. If it is false, only items +which are set to stack above the map item will be drawn. %End bool containsAdvancedEffects() const; diff --git a/src/core/layout/qgslayoutitemmap.cpp b/src/core/layout/qgslayoutitemmap.cpp index 016e5e19090..848db02feba 100644 --- a/src/core/layout/qgslayoutitemmap.cpp +++ b/src/core/layout/qgslayoutitemmap.cpp @@ -854,7 +854,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem if ( shouldDrawPart( OverviewMapExtent ) ) { - mOverviewStack->drawItems( painter ); + mOverviewStack->drawItems( painter, false ); } if ( shouldDrawPart( Grid ) ) { @@ -922,7 +922,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem if ( shouldDrawPart( OverviewMapExtent ) ) { - mOverviewStack->drawItems( &p ); + mOverviewStack->drawItems( &p, false ); } if ( shouldDrawPart( Grid ) ) { @@ -960,7 +960,7 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem if ( shouldDrawPart( OverviewMapExtent ) ) { - mOverviewStack->drawItems( painter ); + mOverviewStack->drawItems( painter, false ); } if ( shouldDrawPart( Grid ) ) { @@ -1006,7 +1006,13 @@ void QgsLayoutItemMap::drawMap( QPainter *painter, const QgsRectangle &extent, Q } // render - QgsMapRendererCustomPainterJob job( mapSettings( extent, size, dpi, true ), painter ); + QgsMapSettings ms( mapSettings( extent, size, dpi, true ) ); + if ( shouldDrawPart( OverviewMapExtent ) ) + { + ms.setLayers( mOverviewStack->modifyMapLayerList( ms.layers() ) ); + } + + QgsMapRendererCustomPainterJob job( ms, painter ); // Render the map in this thread. This is done because of problems // with printing to printer on Windows (printing to PDF is fine though). // Raster images were not displayed - see #10599 @@ -1084,6 +1090,12 @@ void QgsLayoutItemMap::recreateCachedImageInBackground() mCacheInvalidated = false; mPainter.reset( new QPainter( mCacheRenderingImage.get() ) ); QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheRenderingImage->logicalDpiX(), true ) ); + + if ( shouldDrawPart( OverviewMapExtent ) ) + { + settings.setLayers( mOverviewStack->modifyMapLayerList( settings.layers() ) ); + } + mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) ); connect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsLayoutItemMap::painterJobFinished ); mPainterJob->start(); diff --git a/src/core/layout/qgslayoutitemmapitem.cpp b/src/core/layout/qgslayoutitemmapitem.cpp index 4f9793aeb00..c48152ebd17 100644 --- a/src/core/layout/qgslayoutitemmapitem.cpp +++ b/src/core/layout/qgslayoutitemmapitem.cpp @@ -239,7 +239,7 @@ void QgsLayoutItemMapItemStack::finalizeRestoreFromXml() } } -void QgsLayoutItemMapItemStack::drawItems( QPainter *painter ) +void QgsLayoutItemMapItemStack::drawItems( QPainter *painter, bool ignoreStacking ) { if ( !painter ) { @@ -248,7 +248,21 @@ void QgsLayoutItemMapItemStack::drawItems( QPainter *painter ) for ( QgsLayoutItemMapItem *item : qgis::as_const( mItems ) ) { - item->draw( painter ); + switch ( item->stackingPosition() ) + { + case QgsLayoutItemMapItem::StackBelowMap: + case QgsLayoutItemMapItem::StackAboveMapLayer: + case QgsLayoutItemMapItem::StackBelowMapLayer: + case QgsLayoutItemMapItem::StackBelowMapLabels: + if ( !ignoreStacking ) + break; + + FALLTHROUGH + case QgsLayoutItemMapItem::StackAboveMapLabels: + item->draw( painter ); + break; + + } } } diff --git a/src/core/layout/qgslayoutitemmapitem.h b/src/core/layout/qgslayoutitemmapitem.h index db9bb5b9067..602105d62a9 100644 --- a/src/core/layout/qgslayoutitemmapitem.h +++ b/src/core/layout/qgslayoutitemmapitem.h @@ -250,8 +250,12 @@ class CORE_EXPORT QgsLayoutItemMapItemStack /** * Draws the items from the stack on a specified \a painter. + * + * If \a ignoreStacking is true, then all items will be drawn, regardless + * of their actual stacking position settings. If it is false, only items + * which are set to stack above the map item will be drawn. */ - void drawItems( QPainter *painter ); + void drawItems( QPainter *painter, bool ignoreStacking = true ); /** * Returns whether any items within the stack contain advanced effects, diff --git a/src/core/layout/qgslayoutitemmapoverview.cpp b/src/core/layout/qgslayoutitemmapoverview.cpp index 77e991ea3b0..9cad50412fb 100644 --- a/src/core/layout/qgslayoutitemmapoverview.cpp +++ b/src/core/layout/qgslayoutitemmapoverview.cpp @@ -230,7 +230,7 @@ void QgsLayoutItemMapOverview::setLinkedMap( QgsLayoutItemMap *map ) mFrameMap = map; //connect to new map signals connectSignals(); - mMap->update(); + mMap->invalidateCache(); } QgsLayoutItemMap *QgsLayoutItemMapOverview::linkedMap() @@ -358,13 +358,10 @@ void QgsLayoutItemMapOverview::overviewExtentChanged() center.x() - extent.width() / 2 + extent.width(), center.y() - extent.height() / 2 + extent.height() ); mMap->setExtent( movedExtent ); - - //must invalidate cache so that map gets redrawn - mMap->invalidateCache(); } //repaint map so that overview gets updated - mMap->update(); + mMap->invalidateCache(); } diff --git a/tests/src/python/test_qgslayoutmapoverview.py b/tests/src/python/test_qgslayoutmapoverview.py index 77424f3bb9f..e3fca29fb52 100644 --- a/tests/src/python/test_qgslayoutmapoverview.py +++ b/tests/src/python/test_qgslayoutmapoverview.py @@ -289,6 +289,47 @@ class TestQgsLayoutMap(unittest.TestCase, LayoutItemTestCase): self.assertEqual(overviewMap.overviews().modifyMapLayerList([self.raster_layer, self.vector_layer]), [overviewMap.overviews().overview(1).asMapLayer(), self.raster_layer, self.vector_layer, overviewMap.overview().asMapLayer()]) + def testOverviewStacking(self): + l = QgsLayout(QgsProject.instance()) + l.initializeDefaults() + map = QgsLayoutItemMap(l) + map.attemptSetSceneRect(QRectF(20, 20, 200, 100)) + map.setFrameEnabled(True) + map.setLayers([self.raster_layer]) + l.addLayoutItem(map) + + overviewMap = QgsLayoutItemMap(l) + overviewMap.attemptSetSceneRect(QRectF(20, 130, 70, 70)) + l.addLayoutItem(overviewMap) + overviewMap.setFrameEnabled(True) + overviewMap.setLayers([self.raster_layer]) + # zoom in + myRectangle = QgsRectangle(96, -152, 160, -120) + map.setExtent(myRectangle) + myRectangle2 = QgsRectangle(-20, -276, 276, 20) + overviewMap.setExtent(myRectangle2) + overviewMap.overview().setLinkedMap(map) + overviewMap.overview().setInverted(True) + overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackBelowMapLayer) + overviewMap.overview().setStackingLayer(self.raster_layer) + + checker = QgsLayoutChecker('composermap_overview_belowmap', l) + checker.setColorTolerance(6) + checker.setControlPathPrefix("composer_mapoverview") + myTestResult, myMessage = checker.testLayout() + self.report += checker.report() + self.assertTrue(myTestResult, myMessage) + + overviewMap.overview().setStackingPosition(QgsLayoutItemMapItem.StackAboveMapLayer) + overviewMap.overview().setStackingLayer(self.raster_layer) + + checker = QgsLayoutChecker('composermap_overview_abovemap', l) + checker.setColorTolerance(6) + checker.setControlPathPrefix("composer_mapoverview") + myTestResult, myMessage = checker.testLayout() + self.report += checker.report() + self.assertTrue(myTestResult, myMessage) + if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap.png b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap.png new file mode 100644 index 00000000000..409aad1f441 Binary files /dev/null and b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap.png differ diff --git a/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap_mask.png b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap_mask.png new file mode 100644 index 00000000000..36f95c242a2 Binary files /dev/null and b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_abovemap/expected_composermap_overview_abovemap_mask.png differ diff --git a/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap.png b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap.png new file mode 100644 index 00000000000..d670b331b3d Binary files /dev/null and b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap.png differ diff --git a/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap_mask.png b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap_mask.png new file mode 100644 index 00000000000..36f95c242a2 Binary files /dev/null and b/tests/testdata/control_images/composer_mapoverview/expected_composermap_overview_belowmap/expected_composermap_overview_belowmap_mask.png differ