QGIS API Documentation 3.41.0-Master (3440c17df1d)
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 : smani@sourcepole.ch *
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 , mLayerId( layer->id() )
36 , mLayerName( layer->name() )
37 , mCrs( layer->crs() )
38{
39 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
40}
41
43{
44 // Why is there a write lock acquired here? Weird, we only want to read a feature from the cache, right?
45 // A method like `QCache::object(const Key &key) const` certainly would not modify its internals.
46 // Mmmh. What if reality was different?
47 // If one reads the docs very, very carefully one will find the term "reentrant" in the
48 // small print of the QCache docs. This is the hint that reality is different.
49 //
50 // https://bugreports.qt.io/browse/QTBUG-19794
51
53 QgsFeature *cachedFeature = mFeatureCache.object( id );
54 if ( cachedFeature )
55 {
56 //feature was cached
57 feature = *cachedFeature;
58 }
59 else
60 {
61 // Feature not in cache, retrieve from layer
62 // TODO: avoid always querying all attributes (attribute values are needed when merging by attribute)
63 if ( !mFeatureSource->getFeatures( QgsFeatureRequest( id ) ).nextFeature( feature ) )
64 {
65 return false;
66 }
68 mFeatureCache.insert( id, new QgsFeature( feature ) );
69 mIndex.addFeature( feature );
70 }
71 return true;
72}
73
75{
77 Q_UNUSED( feedback )
78 Q_ASSERT( mLayer );
79 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
80
81 mFeatureCache.clear();
82 mIndex = QgsSpatialIndex();
83
84 QgsFeatureIds fids;
85
86 mFeatureSource = std::make_unique<QgsVectorLayerFeatureSource>( mLayer );
87
88 QgsFeatureIterator it = mFeatureSource->getFeatures( request );
89 QgsFeature feature;
90 while ( it.nextFeature( feature ) )
91 {
92 insertFeature( feature, true );
93 fids << feature.id();
94 }
95
96 return fids;
97}
98
100{
101 return mFeatureIds;
102}
103
105{
106 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
107 QgsFeatureIds ids = qgis::listToSet( mIndex.intersects( rect ) );
108 return ids;
109}
110
112{
113 if ( mLayer )
114 Q_ASSERT( QThread::currentThread() == mLayer->thread() );
115
116 return mLayer.data();
117}
118
119QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
120{
121 return mLayer;
122}
123
124void QgsFeaturePool::insertFeature( const QgsFeature &feature, bool skipLock )
125{
127 if ( !skipLock )
129 mFeatureCache.insert( feature.id(), new QgsFeature( feature ) );
130 QgsFeature indexFeature( feature );
131 mIndex.addFeature( indexFeature );
132}
133
135{
136 QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
137 mFeatureCache.remove( feature.id() );
138 mIndex.deleteFeature( feature );
139 locker.unlock();
140
141 QgsFeature tempFeature;
142 getFeature( feature.id(), tempFeature );
143}
144
146{
147 QgsFeature origFeature;
149 if ( getFeature( featureId, origFeature ) )
150 {
152 mIndex.deleteFeature( origFeature );
153 }
155 mFeatureCache.remove( origFeature.id() );
156}
157
159{
160 mFeatureIds = ids;
161}
162
164{
165 const QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
166 return mFeatureCache.contains( fid );
167}
168
170{
171 return mLayerName;
172}
173
175{
176 return mCrs;
177}
178
180{
181 return mGeometryType;
182}
183
185{
186 return mLayerId;
187}
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.
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: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