Skip to content

Commit bbe974c

Browse files
committed
[layouts] Fix crash when using maps containing AMS layers
Implement a similar hack to what the canvas uses to workaround the badly behaved AMS and WCS providers Fixes #17959
1 parent c10438e commit bbe974c

File tree

2 files changed

+33
-12
lines changed

2 files changed

+33
-12
lines changed

src/core/layout/qgslayoutitemmap.cpp

+25-8
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@
3434
QgsLayoutItemMap::QgsLayoutItemMap( QgsLayout *layout )
3535
: QgsLayoutItem( layout )
3636
{
37-
assignFreeId();
37+
mBackgroundUpdateTimer = new QTimer( this );
38+
mBackgroundUpdateTimer->setSingleShot( true );
39+
connect( mBackgroundUpdateTimer, &QTimer::timeout, this, &QgsLayoutItemMap::recreateCachedImageInBackground );
3840

41+
assignFreeId();
3942

4043
if ( layout )
4144
{
@@ -774,18 +777,20 @@ void QgsLayoutItemMap::paint( QPainter *painter, const QStyleOptionGraphicsItem
774777
painter->setFont( messageFont );
775778
painter->setPen( QColor( 255, 255, 255, 255 ) );
776779
painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr( "Rendering map" ) );
777-
if ( !mPainterJob )
780+
if ( !mPainterJob && !mDrawingPreview )
778781
{
779782
// this is the map's very first paint - trigger a cache update
780-
recreateCachedImageInBackground( style->matrix.m11() );
783+
mPreviewScaleFactor = style->matrix.m11();
784+
mBackgroundUpdateTimer->start( 1 );
781785
}
782786
}
783787
else
784788
{
785-
if ( mCacheInvalidated )
789+
if ( mCacheInvalidated && !mDrawingPreview )
786790
{
787791
// cache was invalidated - trigger a background update
788-
recreateCachedImageInBackground( style->matrix.m11() );
792+
mPreviewScaleFactor = style->matrix.m11();
793+
mBackgroundUpdateTimer->start( 1 );
789794
}
790795

791796
//Background color is already included in cached image, so no need to draw
@@ -966,7 +971,7 @@ void QgsLayoutItemMap::drawMap( QPainter *painter, const QgsRectangle &extent, Q
966971
job.renderSynchronously();
967972
}
968973

969-
void QgsLayoutItemMap::recreateCachedImageInBackground( double viewScaleFactor )
974+
void QgsLayoutItemMap::recreateCachedImageInBackground()
970975
{
971976
if ( mPainterJob )
972977
{
@@ -995,8 +1000,8 @@ void QgsLayoutItemMap::recreateCachedImageInBackground( double viewScaleFactor )
9951000
double widthLayoutUnits = ext.width() * mapUnitsToLayoutUnits();
9961001
double heightLayoutUnits = ext.height() * mapUnitsToLayoutUnits();
9971002

998-
int w = widthLayoutUnits * viewScaleFactor;
999-
int h = heightLayoutUnits * viewScaleFactor;
1003+
int w = widthLayoutUnits * mPreviewScaleFactor;
1004+
int h = heightLayoutUnits * mPreviewScaleFactor;
10001005

10011006
// limit size of image for better performance
10021007
if ( w > 5000 || h > 5000 )
@@ -1040,6 +1045,18 @@ void QgsLayoutItemMap::recreateCachedImageInBackground( double viewScaleFactor )
10401045
mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) );
10411046
connect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsLayoutItemMap::painterJobFinished );
10421047
mPainterJob->start();
1048+
1049+
// from now on we can accept refresh requests again
1050+
// this must be reset only after the job has been started, because
1051+
// some providers (yes, it's you WCS and AMS!) during preparation
1052+
// do network requests and start an internal event loop, which may
1053+
// end up calling refresh() and would schedule another refresh,
1054+
// deleting the one we have just started.
1055+
1056+
// ^^ that comment was directly copied from a similar fix in QgsMapCanvas. And
1057+
// with little surprise, both those providers are still badly behaved and causing
1058+
// annoying bugs for us to deal with...
1059+
mDrawingPreview = false;
10431060
}
10441061

10451062
QgsMapSettings QgsLayoutItemMap::mapSettings( const QgsRectangle &extent, QSizeF size, double dpi, bool includeLayerSettings ) const

src/core/layout/qgslayoutitemmap.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,9 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
485485

486486
void mapThemeChanged( const QString &theme );
487487

488+
//! Create cache image
489+
void recreateCachedImageInBackground();
490+
488491
private:
489492

490493

@@ -527,6 +530,11 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
527530
//! \brief set to true if in state of drawing. Concurrent requests to draw method are returned if set to true
528531
bool mDrawing = false;
529532

533+
QTimer *mBackgroundUpdateTimer = nullptr;
534+
double mPreviewScaleFactor = 0;
535+
536+
bool mDrawingPreview = false;
537+
530538
//! Offset in x direction for showing map cache image
531539
double mXOffset = 0.0;
532540
//! Offset in y direction for showing map cache image
@@ -578,10 +586,6 @@ class CORE_EXPORT QgsLayoutItemMap : public QgsLayoutItem
578586
*/
579587
void drawMap( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi );
580588

581-
582-
//! Create cache image
583-
void recreateCachedImageInBackground( double viewScaleFactor );
584-
585589
//! Establishes signal/slot connection for update in case of layer change
586590
void connectUpdateSlot();
587591

0 commit comments

Comments
 (0)