QGIS API Documentation  3.0.2-Girona (307d082)
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  Q_FOREACH ( const QgsWeakMapLayerPointer &layer, mConnectedLayers )
39  {
40  if ( layer.data() )
41  {
42  disconnect( layer.data(), &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
43  disconnect( layer.data(), &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
44  }
45  }
46  mCachedImages.clear();
47  mConnectedLayers.clear();
48 }
49 
50 void QgsMapRendererCache::dropUnusedConnections()
51 {
52  QSet< QgsWeakMapLayerPointer > stillDepends = dependentLayers();
53  QSet< QgsWeakMapLayerPointer > disconnects = mConnectedLayers.subtract( stillDepends );
54  Q_FOREACH ( const QgsWeakMapLayerPointer &layer, disconnects )
55  {
56  if ( layer.data() )
57  {
58  disconnect( layer.data(), &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
59  disconnect( layer.data(), &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
60  }
61  }
62 
63  mConnectedLayers = stillDepends;
64 }
65 
66 QSet<QgsWeakMapLayerPointer > QgsMapRendererCache::dependentLayers() const
67 {
68  QSet< QgsWeakMapLayerPointer > result;
69  QMap<QString, CacheParameters>::const_iterator it = mCachedImages.constBegin();
70  for ( ; it != mCachedImages.constEnd(); ++it )
71  {
72  Q_FOREACH ( const QgsWeakMapLayerPointer &l, it.value().dependentLayers )
73  {
74  if ( l.data() )
75  result << l;
76  }
77  }
78  return result;
79 }
80 
81 bool QgsMapRendererCache::init( const QgsRectangle &extent, double scale )
82 {
83  QMutexLocker lock( &mMutex );
84 
85  // check whether the params are the same
86  if ( extent == mExtent &&
87  qgsDoubleNear( scale, mScale ) )
88  return true;
89 
90  clearInternal();
91 
92  // set new params
93  mExtent = extent;
94  mScale = scale;
95 
96  return false;
97 }
98 
99 void QgsMapRendererCache::setCacheImage( const QString &cacheKey, const QImage &image, const QList<QgsMapLayer *> &dependentLayers )
100 {
101  QMutexLocker lock( &mMutex );
102 
103  CacheParameters params;
104  params.cachedImage = image;
105 
106  // connect to the layer to listen to layer's repaintRequested() signals
107  Q_FOREACH ( QgsMapLayer *layer, dependentLayers )
108  {
109  if ( layer )
110  {
111  params.dependentLayers << layer;
112  if ( !mConnectedLayers.contains( QgsWeakMapLayerPointer( layer ) ) )
113  {
114  connect( layer, &QgsMapLayer::repaintRequested, this, &QgsMapRendererCache::layerRequestedRepaint );
115  connect( layer, &QgsMapLayer::willBeDeleted, this, &QgsMapRendererCache::layerRequestedRepaint );
116  mConnectedLayers << layer;
117  }
118  }
119  }
120 
121  mCachedImages[cacheKey] = params;
122 }
123 
124 bool QgsMapRendererCache::hasCacheImage( const QString &cacheKey ) const
125 {
126  return mCachedImages.contains( cacheKey );
127 }
128 
129 QImage QgsMapRendererCache::cacheImage( const QString &cacheKey ) const
130 {
131  QMutexLocker lock( &mMutex );
132  return mCachedImages.value( cacheKey ).cachedImage;
133 }
134 
135 QList< QgsMapLayer * > QgsMapRendererCache::dependentLayers( const QString &cacheKey ) const
136 {
137  if ( mCachedImages.contains( cacheKey ) )
138  {
139  return _qgis_listQPointerToRaw( mCachedImages.value( cacheKey ).dependentLayers );
140  }
141  return QList< QgsMapLayer * >();
142 }
143 
144 void QgsMapRendererCache::layerRequestedRepaint()
145 {
146  QgsMapLayer *layer = qobject_cast<QgsMapLayer *>( sender() );
147  if ( !layer )
148  return;
149 
150  QMutexLocker lock( &mMutex );
151 
152  // check through all cached images to clear any which depend on this layer
153  QMap<QString, CacheParameters>::iterator it = mCachedImages.begin();
154  for ( ; it != mCachedImages.end(); )
155  {
156  if ( !it.value().dependentLayers.contains( layer ) )
157  {
158  ++it;
159  continue;
160  }
161 
162  it = mCachedImages.erase( it );
163  }
164  dropUnusedConnections();
165 }
166 
167 void QgsMapRendererCache::clearCacheImage( const QString &cacheKey )
168 {
169  QMutexLocker lock( &mMutex );
170 
171  mCachedImages.remove( cacheKey );
172  dropUnusedConnections();
173 }
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:39
Base class for all map layer types.
Definition: qgsmaplayer.h:56
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void willBeDeleted()
Emitted in the destructor when the layer is about to be deleted, but it is still in a perfectly valid...
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:1349
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:251
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.