QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgsmaprenderercache.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaprenderercache.cpp
3  --------------------------------------
4  Date : December 2013
5  Copyright : (C) 2013 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsmaprenderercache.h"
17 
18 #include "qgsmaplayer.h"
19 #include "qgsmaplayerlistutils.h"
20 
22 {
23  clear();
24 }
25 
27 {
28  QMutexLocker lock( &mMutex );
29  clearInternal();
30 }
31 
32 void QgsMapRendererCache::clearInternal()
33 {
34  mExtent.setMinimal();
35  mScale = 0;
36 
37  // make sure we are disconnected from all layers
38  const auto constMConnectedLayers = mConnectedLayers;
39  for ( const QgsWeakMapLayerPointer &layer : constMConnectedLayers )
40  {
41  if ( layer.data() )
42  {
43  disconnect( layer.data(), &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
44  disconnect( layer.data(), &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
45  }
46  }
47  mCachedImages.clear();
48  mConnectedLayers.clear();
49 }
50 
51 void QgsMapRendererCache::dropUnusedConnections()
52 {
53  QSet< QgsWeakMapLayerPointer > stillDepends = dependentLayers();
54  QSet< QgsWeakMapLayerPointer > disconnects = mConnectedLayers.subtract( stillDepends );
55  const auto constDisconnects = disconnects;
56  for ( const QgsWeakMapLayerPointer &layer : constDisconnects )
57  {
58  if ( layer.data() )
59  {
60  disconnect( layer.data(), &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
61  disconnect( layer.data(), &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
62  }
63  }
64 
65  mConnectedLayers = stillDepends;
66 }
67 
68 QSet<QgsWeakMapLayerPointer > QgsMapRendererCache::dependentLayers() const
69 {
70  QSet< QgsWeakMapLayerPointer > result;
71  QMap<QString, CacheParameters>::const_iterator it = mCachedImages.constBegin();
72  for ( ; it != mCachedImages.constEnd(); ++it )
73  {
74  const auto dependentLayers { it.value().dependentLayers };
75  for ( const QgsWeakMapLayerPointer &l : dependentLayers )
76  {
77  if ( l.data() )
78  result << l;
79  }
80  }
81  return result;
82 }
83 
84 bool QgsMapRendererCache::init( const QgsRectangle &extent, double scale )
85 {
86  QMutexLocker lock( &mMutex );
87 
88  // check whether the params are the same
89  if ( extent == mExtent &&
90  qgsDoubleNear( scale, mScale ) )
91  return true;
92 
93  clearInternal();
94 
95  // set new params
96  mExtent = extent;
97  mScale = scale;
98 
99  return false;
100 }
101 
102 void QgsMapRendererCache::setCacheImage( const QString &cacheKey, const QImage &image, const QList<QgsMapLayer *> &dependentLayers )
103 {
104  QMutexLocker lock( &mMutex );
105 
106  CacheParameters params;
107  params.cachedImage = image;
108 
109  // connect to the layer to listen to layer's repaintRequested() signals
110  const auto constDependentLayers = dependentLayers;
111  for ( QgsMapLayer *layer : constDependentLayers )
112  {
113  if ( layer )
114  {
115  params.dependentLayers << layer;
116  if ( !mConnectedLayers.contains( QgsWeakMapLayerPointer( layer ) ) )
117  {
118  connect( layer, &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
119  connect( layer, &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
120  mConnectedLayers << layer;
121  }
122  }
123  }
124 
125  mCachedImages[cacheKey] = params;
126 }
127 
128 bool QgsMapRendererCache::hasCacheImage( const QString &cacheKey ) const
129 {
130  return mCachedImages.contains( cacheKey );
131 }
132 
133 QImage QgsMapRendererCache::cacheImage( const QString &cacheKey ) const
134 {
135  QMutexLocker lock( &mMutex );
136  return mCachedImages.value( cacheKey ).cachedImage;
137 }
138 
139 QList< QgsMapLayer * > QgsMapRendererCache::dependentLayers( const QString &cacheKey ) const
140 {
141  if ( mCachedImages.contains( cacheKey ) )
142  {
143  return _qgis_listQPointerToRaw( mCachedImages.value( cacheKey ).dependentLayers );
144  }
145  return QList< QgsMapLayer * >();
146 }
147 
148 void QgsMapRendererCache::layerRequestedRepaint()
149 {
150  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
151  if ( !layer )
152  return;
153 
154  QMutexLocker lock( &mMutex );
155 
156  // check through all cached images to clear any which depend on this layer
157  QMap<QString, CacheParameters>::iterator it = mCachedImages.begin();
158  for ( ; it != mCachedImages.end(); )
159  {
160  if ( !it.value().dependentLayers.contains( layer ) )
161  {
162  ++it;
163  continue;
164  }
165 
166  it = mCachedImages.erase( it );
167  }
168  dropUnusedConnections();
169 }
170 
171 void QgsMapRendererCache::clearCacheImage( const QString &cacheKey )
172 {
173  QMutexLocker lock( &mMutex );
174 
175  mCachedImages.remove( cacheKey );
176  dropUnusedConnections();
177 }
QList< QgsMapLayer *> dependentLayers(const QString &cacheKey) const
Returns a list of map layers on which an image in the cache depends.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Base class for all map layer types.
Definition: qgsmaplayer.h:78
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:151
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
void setCacheImage(const QString &cacheKey, const QImage &image, const QList< QgsMapLayer * > &dependentLayers=QList< QgsMapLayer * >())
Set the cached image for a particular cacheKey.
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:1576
bool init(const QgsRectangle &extent, double scale)
Initialize cache: set new parameters and clears the cache if any parameters have changed since last i...
QImage cacheImage(const QString &cacheKey) const
Returns the cached image for the specified cacheKey.
void repaintRequested(bool deferredUpdate=false)
By emitting this signal the layer tells that either appearance or content have been changed and any v...
bool hasCacheImage(const QString &cacheKey) const
Returns true if the cache contains an image with the specified cacheKey.
void clear()
Invalidates the cache contents, clearing all cached images.
void clearCacheImage(const QString &cacheKey)
Removes an image from the cache with matching cacheKey.