QGIS API Documentation 3.41.0-Master (cea29feecf2)
Loading...
Searching...
No Matches
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
30 : mFeatureCache( CACHE_SIZE )
31 , mLayer( layer )
32 , mGeometryType( layer->geometryType() )
33 , mFeatureSource( std::make_unique<QgsVectorLayerFeatureSource>( layer ) )
34 , mLayerId( layer->id() )
35 , mLayerName( layer->name() )
36 , mCrs( layer->crs() )
37{
38 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
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
51 // If the feature we want is amongst the features that have been updated,
52 // then get it from the dedicated hash.
53 // It would not be thread-safe to get it directly from the layer,
54 // and it could be outdated in the feature source (in case of a memory layer),
55 // and it could have been cleared from the cache due to a cache overflow.
56 if ( mUpdatedFeatures.contains( id ) )
57 {
58 feature = mUpdatedFeatures[id];
59 return true;
60 }
61
62 QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
63 QgsFeature *cachedFeature = mFeatureCache.object( id );
64 if ( cachedFeature )
65 {
66 //feature was cached
67 feature = *cachedFeature;
68 }
69 else
70 {
71 // Feature not in cache, retrieve from layer
72 // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
73 if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
74 {
75 return false;
76 }
78 mFeatureCache.insert( id, new QgsFeature( feature ) );
79 mIndex.addFeature( feature );
80 }
81 return true;
82}
83
85{
87 Q_UNUSED( feedback )
88 Q_ASSERT( mLayer );
89 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
90
91 mUpdatedFeatures.clear();
92 mFeatureCache.clear();
93 mIndex = QgsSpatialIndex();
94
95 QgsFeatureIds fids;
96
97 mFeatureSource = std::make_unique<QgsVectorLayerFeatureSource>( mLayer );
98
99 QgsFeatureIterator it = mFeatureSource->getFeatures( request );
100 QgsFeature feature;
101 while ( it.nextFeature( feature ) )
102 {
103 insertFeature( feature, true );
104 fids << feature.id();
105 }
106
107 return fids;
108}
109
111{
112 return mFeatureIds;
113}
114
116{
117 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
118 QgsFeatureIds ids = qgis::listToSet( mIndex.intersects( rect ) );
119 return ids;
120}
121
123{
124 if ( mLayer )
125 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
126
127 return mLayer.data();
128}
129
130QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
131{
132 return mLayer;
133}
134
135void QgsFeaturePool::insertFeature( const QgsFeature &feature, bool skipLock )
136{
138 if ( !skipLock )
140 mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
141 QgsFeature indexFeature( feature );
142 mIndex.addFeature( indexFeature );
143}
144
145void QgsFeaturePool::refreshCache( QgsFeature feature, const QgsFeature &origFeature )
146{
147 // insert/refresh the updated features as well
148 mUpdatedFeatures.insert( feature.id(), feature );
149
150 QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
151 mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
152 mIndex.deleteFeature( origFeature );
153 mIndex.addFeature( feature );
154 locker.unlock();
155}
156
158{
159 mUpdatedFeatures.remove( featureId );
160 QgsFeature origFeature;
162 if ( getFeature( featureId, origFeature ) )
163 {
165 mIndex.deleteFeature( origFeature );
166 }
168 mFeatureCache.remove( origFeature.id() );
169}
170
172{
173 mFeatureIds = ids;
174}
175
177{
178 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
179 return mFeatureCache.contains( fid );
180}
181
183{
184 return mLayerName;
185}
186
188{
189 return mCrs;
190}
191
193{
194 return mGeometryType;
195}
196
198{
199 return mLayerId;
200}
GeometryType
The geometry types are used to group Qgis::WkbType in a coarse way.
Definition qgis.h:337
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.
Qgis::GeometryType geometryType() const
The geometry type of this layer.
QgsFeaturePool(QgsVectorLayer *layer)
Creates a new feature pool for layer.
void refreshCache(QgsFeature feature, const QgsFeature &origFeature)
Changes a feature in the cache and the spatial index.
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:58
QgsFeatureId id
Definition qgsfeature.h:66
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.
void unlock()
Unlocks the lock.
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
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
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
const QgsCoordinateReferenceSystem & crs