QGIS API Documentation  3.6.0-Noosa (5873452)
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:41
Base class for all map layer types.
Definition: qgsmaplayer.h:64
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:1548
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.