QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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"
23#include "qgsreadwritelocker.h"
24
25#include <QMutexLocker>
26#include <QThread>
27
28
29
31 : mFeatureCache( CACHE_SIZE )
32 , mLayer( layer )
33 , mGeometryType( layer->geometryType() )
34 , mFeatureSource( std::make_unique<QgsVectorLayerFeatureSource>( layer ) )
35 , mLayerName( layer->name() )
36{
37
38}
39
41{
42 // Why is there a write lock acquired here? Weird, we only want to read a feature from the cache, right?
43 // A method like `QCache::object(const Key &key) const` certainly would not modify its internals.
44 // Mmmh. What if reality was different?
45 // If one reads the docs very, very carefully one will find the term "reentrant" in the
46 // small print of the QCache docs. This is the hint that reality is different.
47 //
48 // https://bugreports.qt.io/browse/QTBUG-19794
49
51 QgsFeature *cachedFeature = mFeatureCache.object( id );
52 if ( cachedFeature )
53 {
54 //feature was cached
55 feature = *cachedFeature;
56 }
57 else
58 {
59 // Feature not in cache, retrieve from layer
60 // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
61 if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
62 {
63 return false;
64 }
66 mFeatureCache.insert( id, new QgsFeature( feature ) );
67 mIndex.addFeature( feature );
68 }
69 return true;
70}
71
73{
75 Q_UNUSED( feedback )
76 Q_ASSERT( QThread::currentThread() == qApp->thread() );
77
78 mFeatureCache.clear();
79 mIndex = QgsSpatialIndex();
80
81 QgsFeatureIds fids;
82
83 mFeatureSource = std::make_unique<QgsVectorLayerFeatureSource>( mLayer );
84
85 QgsFeatureIterator it = mFeatureSource->getFeatures( request );
86 QgsFeature feature;
87 while ( it.nextFeature( feature ) )
88 {
89 insertFeature( feature, true );
90 fids << feature.id();
91 }
92
93 return fids;
94}
95
97{
98 return mFeatureIds;
99}
100
102{
103 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
104 QgsFeatureIds ids = qgis::listToSet( mIndex.intersects( rect ) );
105 return ids;
106}
107
109{
110 Q_ASSERT( QThread::currentThread() == qApp->thread() );
111
112 return mLayer.data();
113}
114
115QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
116{
117 return mLayer;
118}
119
120void QgsFeaturePool::insertFeature( const QgsFeature &feature, bool skipLock )
121{
123 if ( !skipLock )
125 mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
126 QgsFeature indexFeature( feature );
127 mIndex.addFeature( indexFeature );
128}
129
131{
132 QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
133 mFeatureCache.remove( feature.id() );
134 mIndex.deleteFeature( feature );
135 locker.unlock();
136
137 QgsFeature tempFeature;
138 getFeature( feature.id(), tempFeature );
139}
140
142{
143 QgsFeature origFeature;
145 if ( getFeature( featureId, origFeature ) )
146 {
148 mIndex.deleteFeature( origFeature );
149 }
151 mFeatureCache.remove( origFeature.id() );
152}
153
155{
156 mFeatureIds = ids;
157}
158
160{
161 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
162 return mFeatureCache.contains( fid );
163}
164
166{
167 return mLayerName;
168}
169
171{
173 return mFeatureSource->crs();
174}
175
177{
178 return mGeometryType;
179}
180
182{
184 return mFeatureSource->id();
185}
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition: qgis.h:255
This class represents a coordinate reference system (CRS).
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
void refreshCache(const QgsFeature &feature)
Changes a feature in the cache and the spatial index.
Qgis::GeometryType geometryType() const
The geometry type of this layer.
QgsFeaturePool(QgsVectorLayer *layer)
Creates a new feature pool for layer.
QgsFeatureIds allFeatureIds() const
Returns the complete set of feature ids in this pool.
QString layerId() const
The layer id of the layer.
void insertFeature(const QgsFeature &feature, bool skipLock=false)
Inserts a feature into the cache and the spatial index.
QPointer< QgsVectorLayer > layerPtr() const
Gets a QPointer to the underlying layer.
bool isFeatureCached(QgsFeatureId fid)
Checks if the feature fid is cached.
QgsCoordinateReferenceSystem crs() const
The coordinate reference system of this layer.
QgsFeatureIds getFeatures(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Gets features for the provided request.
QgsFeatureIds getIntersects(const QgsRectangle &rect) const
Gets all feature ids in the bounding box rect.
QString layerName() const
Returns the name of the layer.
void setFeatureIds(const QgsFeatureIds &ids)
Sets all the feature ids governed by this feature pool.
void removeFeature(const QgsFeatureId featureId)
Removes a feature from the cache and the spatial index.
QgsVectorLayer * layer() const
Gets a pointer to the underlying layer.
bool getFeature(QgsFeatureId id, QgsFeature &feature)
Retrieves the feature with the specified id into feature.
This class wraps a request for features to a vector layer (or directly its vector data provider).
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
@ Write
Lock for write.
@ Read
Lock for read.
void unlock()
Unlocks the lock.
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
A spatial index for QgsFeature objects.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a feature to the index.
bool deleteFeature(const QgsFeature &feature)
Removes a feature from the index.
Partial snapshot of vector layer's state (only the members necessary for access to features)
Represents a vector layer which manages a vector based data sets.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28