QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsfeaturepool.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * qgsfeaturepool.cpp *
3  * ------------------- *
4  * copyright : (C) 2014 by Sandro Mani / Sourcepole AG *
5  * email : [email protected] *
6  ***************************************************************************/
7 
8 /***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 
17 #include "qgsfeaturepool.h"
18 #include "qgsfeature.h"
19 #include "qgsfeatureiterator.h"
20 #include "qgsgeometry.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsvectordataprovider.h"
23 #include "qgsvectorlayerutils.h"
24 #include "qgsreadwritelocker.h"
25 
26 #include <QMutexLocker>
27 
28 
30  : mFeatureCache( CACHE_SIZE )
31  , mLayer( layer )
32  , mGeometryType( layer->geometryType() )
33  , mFeatureSource( qgis::make_unique<QgsVectorLayerFeatureSource>( layer ) )
34  , mLayerName( layer->name() )
35 {
36 
37 }
38 
40 {
41  // Why is there a write lock acquired here? Weird, we only want to read a feature from the cache, right?
42  // A method like `QCache::object(const Key &key) const` certainly would not modify its internals.
43  // Mmmh. What if reality was different?
44  // If one reads the docs very, very carefully one will find the term "reentrant" in the
45  // small print of the QCache docs. This is the hint that reality is different.
46  //
47  // https://bugreports.qt.io/browse/QTBUG-19794
48 
49  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
50  QgsFeature *cachedFeature = mFeatureCache.object( id );
51  if ( cachedFeature )
52  {
53  //feature was cached
54  feature = *cachedFeature;
55  }
56  else
57  {
58  // Feature not in cache, retrieve from layer
59  // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
60  if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
61  {
62  return false;
63  }
65  mFeatureCache.insert( id, new QgsFeature( feature ) );
66  mIndex.addFeature( feature );
67  }
68  return true;
69 }
70 
72 {
74  Q_UNUSED( feedback )
75  Q_ASSERT( QThread::currentThread() == qApp->thread() );
76 
77  mFeatureCache.clear();
78  mIndex = QgsSpatialIndex();
79 
80  QgsFeatureIds fids;
81 
82  mFeatureSource = qgis::make_unique<QgsVectorLayerFeatureSource>( mLayer );
83 
84  QgsFeatureIterator it = mFeatureSource->getFeatures( request );
85  QgsFeature feature;
86  while ( it.nextFeature( feature ) )
87  {
88  insertFeature( feature, true );
89  fids << feature.id();
90  }
91 
92  return fids;
93 }
94 
96 {
97  return mFeatureIds;
98 }
99 
101 {
102  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
103  QgsFeatureIds ids = qgis::listToSet( mIndex.intersects( rect ) );
104  return ids;
105 }
106 
108 {
109  Q_ASSERT( QThread::currentThread() == qApp->thread() );
110 
111  return mLayer.data();
112 }
113 
114 QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
115 {
116  return mLayer;
117 }
118 
119 void QgsFeaturePool::insertFeature( const QgsFeature &feature, bool skipLock )
120 {
121  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Unlocked );
122  if ( !skipLock )
124  mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
125  QgsFeature indexFeature( feature );
126  mIndex.addFeature( indexFeature );
127 }
128 
130 {
131  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
132  mFeatureCache.remove( feature.id() );
133  mIndex.deleteFeature( feature );
134  locker.unlock();
135 
136  QgsFeature tempFeature;
137  getFeature( feature.id(), tempFeature );
138 }
139 
141 {
142  QgsFeature origFeature;
143  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Unlocked );
144  if ( getFeature( featureId, origFeature ) )
145  {
147  mIndex.deleteFeature( origFeature );
148  }
150  mFeatureCache.remove( origFeature.id() );
151 }
152 
154 {
155  mFeatureIds = ids;
156 }
157 
159 {
160  QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
161  return mFeatureCache.contains( fid );
162 }
163 
165 {
166  return mLayerName;
167 }
168 
170 {
172  return mFeatureSource->crs();
173 }
174 
176 {
177  return mGeometryType;
178 }
179 
180 QString QgsFeaturePool::layerId() const
181 {
183  return mFeatureSource->id();
184 }
QgsReadWriteLocker::changeMode
void changeMode(Mode mode)
Change the mode of the lock to mode.
Definition: qgsreadwritelocker.cpp:30
qgsreadwritelocker.h
QgsReadWriteLocker::Read
@ Read
Lock for read.
Definition: qgsreadwritelocker.h:75
QgsSpatialIndex::deleteFeature
bool deleteFeature(const QgsFeature &feature)
Removes a feature from the index.
Definition: qgsspatialindex.cpp:474
QgsFeaturePool::getFeatures
QgsFeatureIds getFeatures(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Gets features for the provided request.
Definition: qgsfeaturepool.cpp:71
QgsFeaturePool::setFeatureIds
void setFeatureIds(const QgsFeatureIds &ids)
Sets all the feature ids governed by this feature pool.
Definition: qgsfeaturepool.cpp:153
QgsFeaturePool::layerPtr
QPointer< QgsVectorLayer > layerPtr() const
Gets a QPointer to the underlying layer.
Definition: qgsfeaturepool.cpp:114
qgsfeatureiterator.h
qgsfeature.h
QgsFeaturePool::getFeature
bool getFeature(QgsFeatureId id, QgsFeature &feature)
Retrieves the feature with the specified id into feature.
Definition: qgsfeaturepool.cpp:39
QgsReadWriteLocker::unlock
void unlock()
Unlocks the lock.
Definition: qgsreadwritelocker.cpp:45
QgsRectangle
Definition: qgsrectangle.h:41
qgsfeaturepool.h
QgsReadWriteLocker
Definition: qgsreadwritelocker.h:40
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
Definition: qgsfeaturerequest.h:75
QgsFeaturePool::isFeatureCached
bool isFeatureCached(QgsFeatureId fid)
Checks if the feature fid is cached.
Definition: qgsfeaturepool.cpp:158
QgsFeedback
Definition: qgsfeedback.h:43
QgsFeaturePool::geometryType
QgsWkbTypes::GeometryType geometryType() const
The geometry type of this layer.
Definition: qgsfeaturepool.cpp:175
QgsReadWriteLocker::Write
@ Write
Lock for write.
Definition: qgsreadwritelocker.h:76
QgsFeaturePool::layerName
QString layerName() const
Returns the name of the layer.
Definition: qgsfeaturepool.cpp:164
qgsvectordataprovider.h
qgsvectorlayerutils.h
QgsSpatialIndex
Definition: qgsspatialindex.h:67
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
QgsFeaturePool::crs
QgsCoordinateReferenceSystem crs() const
The coordinate reference system of this layer.
Definition: qgsfeaturepool.cpp:169
QgsCoordinateReferenceSystem
Definition: qgscoordinatereferencesystem.h:206
QgsFeaturePool::removeFeature
void removeFeature(const QgsFeatureId featureId)
Removes a feature from the cache and the spatial index.
Definition: qgsfeaturepool.cpp:140
QgsFeaturePool::allFeatureIds
QgsFeatureIds allFeatureIds() const
Returns the complete set of feature ids in this pool.
Definition: qgsfeaturepool.cpp:95
qgsvectorlayer.h
QgsFeaturePool::layer
QgsVectorLayer * layer() const
Gets a pointer to the underlying layer.
Definition: qgsfeaturepool.cpp:107
qgsgeometry.h
QgsWkbTypes::GeometryType
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:139
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:373
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsVectorLayerFeatureSource
Definition: qgsvectorlayerfeatureiterator.h:51
QgsSpatialIndex::intersects
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
Definition: qgsspatialindex.cpp:488
QgsReadWriteLocker::Unlocked
@ Unlocked
Unlocked.
Definition: qgsreadwritelocker.h:77
QgsFeature
Definition: qgsfeature.h:55
QgsFeaturePool::layerId
QString layerId() const
The layer id of the layer.
Definition: qgsfeaturepool.cpp:180
QgsFeaturePool::QgsFeaturePool
QgsFeaturePool(QgsVectorLayer *layer)
Creates a new feature pool for layer.
Definition: qgsfeaturepool.cpp:29
QgsFeatureIterator
Definition: qgsfeatureiterator.h:263
QgsFeaturePool::getIntersects
QgsFeatureIds getIntersects(const QgsRectangle &rect) const
Gets all feature ids in the bounding box rect.
Definition: qgsfeaturepool.cpp:100
QgsSpatialIndex::addFeature
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a feature to the index.
Definition: qgsspatialindex.cpp:403
QgsFeaturePool::refreshCache
void refreshCache(const QgsFeature &feature)
Changes a feature in the cache and the spatial index.
Definition: qgsfeaturepool.cpp:129
QgsFeatureId
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
QgsFeaturePool::insertFeature
void insertFeature(const QgsFeature &feature, bool skipLock=false)
Inserts a feature into the cache and the spatial index.
Definition: qgsfeaturepool.cpp:119