QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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 "qgsvectorlayerutils.h"
24#include "qgsreadwritelocker.h"
25
26#include <QMutexLocker>
27#include <QThread>
28
29
30
32 : mFeatureCache( CACHE_SIZE )
33 , mLayer( layer )
34 , mGeometryType( layer->geometryType() )
35 , mFeatureSource( std::make_unique<QgsVectorLayerFeatureSource>( layer ) )
36 , mLayerName( layer->name() )
37{
38
39}
40
42{
43 // Why is there a write lock acquired here? Weird, we only want to read a feature from the cache, right?
44 // A method like `QCache::object(const Key &key) const` certainly would not modify its internals.
45 // Mmmh. What if reality was different?
46 // If one reads the docs very, very carefully one will find the term "reentrant" in the
47 // small print of the QCache docs. This is the hint that reality is different.
48 //
49 // https://bugreports.qt.io/browse/QTBUG-19794
50
52 QgsFeature *cachedFeature = mFeatureCache.object( id );
53 if ( cachedFeature )
54 {
55 //feature was cached
56 feature = *cachedFeature;
57 }
58 else
59 {
60 // Feature not in cache, retrieve from layer
61 // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
62 if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
63 {
64 return false;
65 }
67 mFeatureCache.insert( id, new QgsFeature( feature ) );
68 mIndex.addFeature( feature );
69 }
70 return true;
71}
72
74{
76 Q_UNUSED( feedback )
77 Q_ASSERT( QThread::currentThread() == qApp->thread() );
78
79 mFeatureCache.clear();
80 mIndex = QgsSpatialIndex();
81
82 QgsFeatureIds fids;
83
84 mFeatureSource = std::make_unique<QgsVectorLayerFeatureSource>( mLayer );
85
86 QgsFeatureIterator it = mFeatureSource->getFeatures( request );
87 QgsFeature feature;
88 while ( it.nextFeature( feature ) )
89 {
90 insertFeature( feature, true );
91 fids << feature.id();
92 }
93
94 return fids;
95}
96
98{
99 return mFeatureIds;
100}
101
103{
104 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
105 QgsFeatureIds ids = qgis::listToSet( mIndex.intersects( rect ) );
106 return ids;
107}
108
110{
111 Q_ASSERT( QThread::currentThread() == qApp->thread() );
112
113 return mLayer.data();
114}
115
116QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
117{
118 return mLayer;
119}
120
121void QgsFeaturePool::insertFeature( const QgsFeature &feature, bool skipLock )
122{
124 if ( !skipLock )
126 mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
127 QgsFeature indexFeature( feature );
128 mIndex.addFeature( indexFeature );
129}
130
132{
133 QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
134 mFeatureCache.remove( feature.id() );
135 mIndex.deleteFeature( feature );
136 locker.unlock();
137
138 QgsFeature tempFeature;
139 getFeature( feature.id(), tempFeature );
140}
141
143{
144 QgsFeature origFeature;
146 if ( getFeature( featureId, origFeature ) )
147 {
149 mIndex.deleteFeature( origFeature );
150 }
152 mFeatureCache.remove( origFeature.id() );
153}
154
156{
157 mFeatureIds = ids;
158}
159
161{
162 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
163 return mFeatureCache.contains( fid );
164}
165
167{
168 return mLayerName;
169}
170
172{
174 return mFeatureSource->crs();
175}
176
178{
179 return mGeometryType;
180}
181
183{
185 return mFeatureSource->id();
186}
This class represents a coordinate reference system (CRS).
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
void refreshCache(const QgsFeature &feature)
Changes a feature in the cache and the spatial index.
QgsWkbTypes::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:45
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.
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
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