[layouts] Add API allowing drawing map overviews under map layers

or under map labels
This commit is contained in:
Nyall Dawson 2018-12-28 17:12:46 +10:00
parent 12da3afa85
commit a441e2b14b
10 changed files with 85 additions and 13 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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;
}
}
}

View File

@ -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,

View File

@ -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();
}

View File

@ -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()