Skip to content
Permalink
Browse files

When the canvas temporal range is changed, we need to invalidate any

cached images we have of temporal enabled layers

Otherwise these will not be re-rendered using the update temporal range
when the canvas is redrawn (and we want to avoid a full map redraw during
animations, which is expensive, so we want to be able to reuse as many
cached images as possible!)
  • Loading branch information
nyalldawson committed Mar 5, 2020
1 parent c307f0e commit 9bbfe81540ecd438c84e0898e262faa42227b2a5
@@ -91,6 +91,13 @@ Returns a list of map layers on which an image in the cache depends.
Removes an image from the cache with matching ``cacheKey``.

.. seealso:: :py:func:`clear`
%End

void invalidateCacheForLayer( QgsMapLayer *layer );
%Docstring
Invalidates cached images which relate to the specified map ``layer``.

.. versionadded:: 3.14
%End

};
@@ -145,9 +145,15 @@ QList< QgsMapLayer * > QgsMapRendererCache::dependentLayers( const QString &cach
return QList< QgsMapLayer * >();
}


void QgsMapRendererCache::layerRequestedRepaint()
{
QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
invalidateCacheForLayer( layer );
}

void QgsMapRendererCache::invalidateCacheForLayer( QgsMapLayer *layer )
{
if ( !layer )
return;

@@ -175,3 +181,4 @@ void QgsMapRendererCache::clearCacheImage( const QString &cacheKey )
mCachedImages.remove( cacheKey );
dropUnusedConnections();
}

@@ -97,6 +97,13 @@ class CORE_EXPORT QgsMapRendererCache : public QObject
*/
void clearCacheImage( const QString &cacheKey );

/**
* Invalidates cached images which relate to the specified map \a layer.
*
* \since QGIS 3.14
*/
void invalidateCacheForLayer( QgsMapLayer *layer );

private slots:
//! Remove layer (that emitted the signal) from the cache
void layerRequestedRepaint();
@@ -75,6 +75,7 @@ email : sherman at mrcc.com
#include "qgscustomdrophandler.h"
#include "qgsreferencedgeometry.h"
#include "qgsprojectviewsettings.h"
#include "qgsmaplayertemporalproperties.h"

/**
* \ingroup gui
@@ -734,6 +735,19 @@ void QgsMapCanvas::setTemporalRange( const QgsDateTimeRange &dateTimeRange )
return;

mSettings.setTemporalRange( dateTimeRange );

if ( mCache )
{
// we need to discard any previously cached images which have temporal properties enabled, so that these will be updated when
// the canvas is redrawn
const QList<QgsMapLayer *> layers;
for ( QgsMapLayer *layer : layers )
{
if ( layer->temporalProperties() && layer->temporalProperties()->isActive() )
mCache->invalidateCacheForLayer( layer );
}
}

emit temporalRangeChanged();
}

@@ -123,6 +123,27 @@ def testRequestRepaintSimple(self):
layer.triggerRepaint(True)
self.assertFalse(cache.hasCacheImage('xxx'))

def testInvalidateCacheForLayer(self):
""" test invalidating the cache for a layer """
layer = QgsVectorLayer("Point?field=fldtxt:string",
"layer", "memory")
QgsProject.instance().addMapLayers([layer])
self.assertTrue(layer.isValid())

# add image to cache
cache = QgsMapRendererCache()
im = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('xxx', im, [layer])
self.assertFalse(cache.cacheImage('xxx').isNull())
self.assertTrue(cache.hasCacheImage('xxx'))

# invalidate cache for layer
cache.invalidateCacheForLayer(layer)
# cache image should be cleared
self.assertTrue(cache.cacheImage('xxx').isNull())
self.assertFalse(cache.hasCacheImage('xxx'))
QgsProject.instance().removeMapLayer(layer.id())

def testRequestRepaintMultiple(self):
""" test requesting repaint with multiple dependent layers """
layer1 = QgsVectorLayer("Point?field=fldtxt:string",

0 comments on commit 9bbfe81

Please sign in to comment.
You can’t perform that action at this time.