Add quick hasCacheImage method to QgsMapRendererCache

This commit is contained in:
Nyall Dawson 2017-02-01 10:55:35 +10:00
parent d0e6e17816
commit 0aa085d41f
5 changed files with 42 additions and 1 deletions

View File

@ -14,6 +14,8 @@ class QgsMapRendererCache : QObject
void setCacheImage( const QString& cacheKey, const QImage& image, const QStringList& dependentLayerIds = QStringList() );
bool hasCacheImage( const QString& cacheKey ) const;
QImage cacheImage( const QString& cacheKey ) const;
void clearCacheImage( const QString& cacheKey );

View File

@ -121,6 +121,11 @@ void QgsMapRendererCache::setCacheImage( const QString& cacheKey, const QImage&
mCachedImages[cacheKey] = params;
}
bool QgsMapRendererCache::hasCacheImage( const QString& cacheKey ) const
{
return mCachedImages.contains( cacheKey );
}
QImage QgsMapRendererCache::cacheImage( const QString& cacheKey ) const
{
QMutexLocker lock( &mMutex );

View File

@ -68,11 +68,19 @@ class CORE_EXPORT QgsMapRendererCache : public QObject
*/
void setCacheImage( const QString& cacheKey, const QImage& image, const QStringList& dependentLayerIds = QStringList() );
/**
* Returns true if the cache contains an image with the specified \a cacheKey.
* @note added in QGIS 3.0
* @see cacheImage()
*/
bool hasCacheImage( const QString& cacheKey ) const;
/**
* Returns the cached image for the specified \a cacheKey. The \a cacheKey usually
* matches the QgsMapLayer::id() which the image is a render of.
* Returns a null image if it is not cached.
* @see setCacheImage()
* @see hasCacheImage()
*/
QImage cacheImage( const QString& cacheKey ) const;

View File

@ -257,7 +257,7 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsLabelingEn
job.context.setFeatureFilterProvider( mFeatureFilterProvider );
// if we can use the cache, let's do it and avoid rendering!
if ( mCache && !mCache->cacheImage( ml->id() ).isNull() )
if ( mCache && mCache->hasCacheImage( ml->id() ) )
{
job.cached = true;
job.img = new QImage( mCache->cacheImage( ml->id() ) );

View File

@ -30,29 +30,35 @@ class TestQgsMapRendererCache(unittest.TestCase):
# not set image
im = cache.cacheImage('littlehands')
self.assertTrue(im.isNull())
self.assertFalse(cache.hasCacheImage('littlehands'))
# set image
im = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('littlehands', im)
self.assertFalse(im.isNull())
self.assertEqual(cache.cacheImage('littlehands'), im)
self.assertTrue(cache.hasCacheImage('littlehands'))
# test another not set image when cache has images
self.assertTrue(cache.cacheImage('bad').isNull())
self.assertFalse(cache.hasCacheImage('bad'))
# clear cache image
cache.clearCacheImage('not in cache') # no crash!
cache.clearCacheImage('littlehands')
im = cache.cacheImage('littlehands')
self.assertTrue(im.isNull())
self.assertFalse(cache.hasCacheImage('littlehands'))
# clear whole cache
im = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('littlehands', im)
self.assertFalse(im.isNull())
self.assertTrue(cache.hasCacheImage('littlehands'))
cache.clear()
im = cache.cacheImage('littlehands')
self.assertTrue(im.isNull())
self.assertFalse(cache.hasCacheImage('littlehands'))
def testInit(self):
cache = QgsMapRendererCache()
@ -63,26 +69,31 @@ class TestQgsMapRendererCache(unittest.TestCase):
im = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('layer', im)
self.assertFalse(cache.cacheImage('layer').isNull())
self.assertTrue(cache.hasCacheImage('layer'))
# re init, without changing extent or scale
self.assertTrue(cache.init(extent, 1000))
# image should still be in cache
self.assertFalse(cache.cacheImage('layer').isNull())
self.assertTrue(cache.hasCacheImage('layer'))
# reinit with different scale
self.assertFalse(cache.init(extent, 2000))
# cache should be cleared
self.assertTrue(cache.cacheImage('layer').isNull())
self.assertFalse(cache.hasCacheImage('layer'))
# readd image to cache
cache.setCacheImage('layer', im)
self.assertFalse(cache.cacheImage('layer').isNull())
self.assertTrue(cache.hasCacheImage('layer'))
# change extent
self.assertFalse(cache.init(QgsRectangle(11, 12, 13, 14), 2000))
# cache should be cleared
self.assertTrue(cache.cacheImage('layer').isNull())
self.assertFalse(cache.hasCacheImage('layer'))
def testRequestRepaintSimple(self):
""" test requesting repaint with a single dependent layer """
@ -96,11 +107,13 @@ class TestQgsMapRendererCache(unittest.TestCase):
im = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('xxx', im, [layer.id()])
self.assertFalse(cache.cacheImage('xxx').isNull())
self.assertTrue(cache.hasCacheImage('xxx'))
# trigger repaint on layer
layer.triggerRepaint()
# cache image should be cleared
self.assertTrue(cache.cacheImage('xxx').isNull())
self.assertFalse(cache.hasCacheImage('xxx'))
QgsProject.instance().removeMapLayer(layer.id())
def testRequestRepaintMultiple(self):
@ -118,6 +131,7 @@ class TestQgsMapRendererCache(unittest.TestCase):
im1 = QImage(200, 200, QImage.Format_RGB32)
cache.setCacheImage('nolayer', im1)
self.assertFalse(cache.cacheImage('nolayer').isNull())
self.assertTrue(cache.hasCacheImage('nolayer'))
# trigger repaint on layer
layer1.triggerRepaint()
@ -126,6 +140,7 @@ class TestQgsMapRendererCache(unittest.TestCase):
layer2.triggerRepaint()
# cache image should still exist - it's not dependent on layers
self.assertFalse(cache.cacheImage('nolayer').isNull())
self.assertTrue(cache.hasCacheImage('nolayer'))
# image depends on 1 layer
im_l1 = QImage(200, 200, QImage.Format_RGB32)
@ -140,18 +155,25 @@ class TestQgsMapRendererCache(unittest.TestCase):
cache.setCacheImage('im2', im_l2, [layer2.id()])
self.assertFalse(cache.cacheImage('im1').isNull())
self.assertTrue(cache.hasCacheImage('im1'))
self.assertFalse(cache.cacheImage('im1_im2').isNull())
self.assertTrue(cache.hasCacheImage('im1_im2'))
self.assertFalse(cache.cacheImage('im2').isNull())
self.assertTrue(cache.hasCacheImage('im2'))
# trigger repaint layer 1 (check twice - don't want disconnect errors)
for i in range(2):
layer1.triggerRepaint()
#should be cleared
self.assertTrue(cache.cacheImage('im1').isNull())
self.assertFalse(cache.hasCacheImage('im1'))
self.assertTrue(cache.cacheImage('im1_im2').isNull())
self.assertFalse(cache.hasCacheImage('im1_im2'))
# should be retained
self.assertTrue(cache.hasCacheImage('im2'))
self.assertFalse(cache.cacheImage('im2').isNull())
self.assertEqual(cache.cacheImage('im2'), im_l2)
self.assertTrue(cache.hasCacheImage('nolayer'))
self.assertFalse(cache.cacheImage('nolayer').isNull())
self.assertEqual(cache.cacheImage('nolayer'), im1)
@ -159,10 +181,14 @@ class TestQgsMapRendererCache(unittest.TestCase):
for i in range(2):
layer2.triggerRepaint()
#should be cleared
self.assertFalse(cache.hasCacheImage('im1'))
self.assertTrue(cache.cacheImage('im1').isNull())
self.assertFalse(cache.hasCacheImage('im1_im2'))
self.assertTrue(cache.cacheImage('im1_im2').isNull())
self.assertFalse(cache.hasCacheImage('im2'))
self.assertTrue(cache.cacheImage('im2').isNull())
# should be retained
self.assertTrue(cache.hasCacheImage('nolayer'))
self.assertFalse(cache.cacheImage('nolayer').isNull())
self.assertEqual(cache.cacheImage('nolayer'), im1)