27#include <QElapsedTimer>
29#include "moc_qgsvectorlayercache.cpp"
41 connect( mLayer, &QgsVectorLayer::destroyed,
this, &QgsVectorLayerCache::layerDeleted );
52 connectJoinedLayers();
57 qDeleteAll( mCacheIndices );
58 mCacheIndices.clear();
72 return mCache.maxCost();
79 bool shouldCacheGeometry =
cacheGeometry && mLayer->isSpatial();
80 bool mustInvalidate = shouldCacheGeometry && !mCacheGeometry;
81 mCacheGeometry = shouldCacheGeometry;
100 if ( !mCache.isEmpty() && !QSet<int>( mCachedAttributes.cbegin(), mCachedAttributes.cend() ).contains( QSet<int>( attributes.cbegin(), attributes.cend() ) ) )
102 mCachedAttributes = attributes;
109 return mCachedAttributes;
116 mFullCache = fullCache;
138 if ( t.elapsed() > 1000 )
159 mCacheIndices.append( cacheIndex );
166 if ( cacheAddedAttributes == mCacheAddedAttributes )
169 mCacheAddedAttributes = cacheAddedAttributes;
170 if ( mCacheAddedAttributes )
184 bool featureFound =
false;
186 QgsCachedFeature *cachedFeature =
nullptr;
190 cachedFeature = mCache[featureId];
195 feature = cachedFeature->feature();
201 const bool allAttrsFetched { mCachedAttributes.count() == mLayer->fields().count() };
202 if ( !allAttrsFetched )
206 if ( !mCacheGeometry )
210 if ( mLayer->getFeatures( request ).nextFeature( feature ) )
212 cacheFeature( feature, allAttrsFetched );
224 bool featureFound =
false;
226 QgsCachedFeature *cachedFeature =
nullptr;
230 cachedFeature = mCache[featureId];
233 if ( cachedFeature && cachedFeature->allAttributesFetched() )
235 feature = cachedFeature->feature();
240 cacheFeature( feature,
true );
251 bool featureFound =
false;
253 QgsCachedFeature *cachedFeature =
nullptr;
257 cachedFeature = mCache[featureId];
260 if ( cachedFeature && cachedFeature->allAttributesFetched() && cachedFeature->geometryFetched() )
262 feature = cachedFeature->feature();
265 else if ( mLayer->getFeatures(
QgsFeatureRequest().setFilterFid( featureId ) ).nextFeature( feature ) )
267 cacheFeature( feature,
true,
true );
278 bool removed = mCache.remove( fid );
281 if (
auto unorderedIt = std::find( mCacheUnorderedKeys.begin(), mCacheUnorderedKeys.end(), fid ); unorderedIt != mCacheUnorderedKeys.end() )
283 mCacheUnorderedKeys.erase( unorderedIt );
285 if (
auto orderedIt = std::find( mCacheOrderedKeys.begin(), mCacheOrderedKeys.end(), fid ); orderedIt != mCacheOrderedKeys.end() )
286 mCacheOrderedKeys.erase( orderedIt );
303 return mLayer->crs();
310 return mLayer->wkbType();
317 return mLayer->fields();
324 return mLayer->featureCount();
332 if ( fids.count() <= mCache.maxCost() )
334 for (
const auto &idx : std::as_const( mCacheIndices ) )
336 idx->requestCompleted( featureRequest, fids );
350 const auto constMCacheIndices = mCacheIndices;
353 idx->flushFeature( fid );
357void QgsVectorLayerCache::onAttributeValueChanged(
QgsFeatureId fid,
int field,
const QVariant &value )
365 cachedFeat->mFeature.setAttribute( field, value );
371void QgsVectorLayerCache::onJoinAttributeValueChanged(
QgsFeatureId fid,
int field,
const QVariant &value )
375 const QgsVectorLayer *joinLayer = qobject_cast<const QgsVectorLayer *>( sender() );
377 const auto constVectorJoins = mLayer->vectorJoins();
378 for (
const QgsVectorLayerJoinInfo &info : constVectorJoins )
380 if ( joinLayer == info.joinLayer() )
382 const QgsFeature feature = mLayer->joinBuffer()->targetedFeatureOf( &info, joinLayer->getFeature( fid ) );
384 const QString fieldName = info.prefixedFieldName( joinLayer->fields().field( field ) );
385 const int fieldIndex = mLayer->fields().indexFromName( fieldName );
387 if ( feature.
isValid() && fieldIndex != -1 )
389 onAttributeValueChanged( feature.
id(), fieldIndex, value );
396void QgsVectorLayerCache::onFeatureDeleted(
QgsFeatureId fid )
401 mCache.remove( fid );
403 if (
auto it = mCacheUnorderedKeys.find( fid ); it != mCacheUnorderedKeys.end() )
405 mCacheUnorderedKeys.erase( it );
406 if (
auto orderedIt = std::find( mCacheOrderedKeys.begin(), mCacheOrderedKeys.end(), fid ); orderedIt != mCacheOrderedKeys.end() )
407 mCacheOrderedKeys.erase( orderedIt );
412void QgsVectorLayerCache::onFeatureAdded(
QgsFeatureId fid )
420 if (
cacheSize() <= mLayer->featureCount() )
431void QgsVectorLayerCache::attributeAdded(
int field )
435 if ( !mCachedAttributes.contains( field ) )
437 mCachedAttributes.append( field );
442void QgsVectorLayerCache::attributeDeleted(
int field )
447 mCachedAttributes.clear();
449 for (
int attr : attrs )
452 mCachedAttributes << attr;
453 else if ( attr > field )
454 mCachedAttributes << attr - 1;
463 QgsCachedFeature *cachedFeat = mCache[fid];
467 cachedFeat->mFeature.setGeometry( geom );
471void QgsVectorLayerCache::layerDeleted()
479void QgsVectorLayerCache::invalidate()
483 if ( !mCache.isEmpty() )
486 mCacheOrderedKeys.clear();
487 mCacheUnorderedKeys.clear();
498 const auto constMCacheIndices = mCacheIndices;
499 for ( QgsAbstractCacheIndex *idx : constMCacheIndices )
501 if ( idx->getCacheIterator( it, featureRequest ) )
512 if ( mCache.contains( featureRequest.
filterFid() ) )
547 bool requiresWriterIt =
true;
555 requiresWriterIt =
false;
560 requiresWriterIt = !canUseCacheForRequest( featureRequest, it );
567 requiresWriterIt =
false;
568 it = mLayer->getFeatures( featureRequest );
571 if ( requiresWriterIt && mLayer->dataProvider() )
577 if ( mCacheGeometry && mLayer->isSpatial() )
583 if ( mCachedAttributes.count() != mLayer->fields().count() )
586 QSet<int> attrs( requestSubset.begin(), requestSubset.end() );
587 for (
int attr : std::as_const( mCachedAttributes ) )
588 attrs.insert( attr );
608 return mCache.contains( fid );
615 const QList< QgsFeatureId > keys = mCache.keys();
627 requestedAttributes = mLayer->attributeList();
635 const auto constRequestedAttributes = requestedAttributes;
636 for (
int attr : constRequestedAttributes )
638 if ( !mCachedAttributes.contains( attr ) )
648void QgsVectorLayerCache::connectJoinedLayers()
const
652 const auto constVectorJoins = mLayer->
vectorJoins();
661bool QgsVectorLayerCache::QgsCachedFeature::allAttributesFetched()
const
663 return mAllAttributesFetched;
666bool QgsVectorLayerCache::QgsCachedFeature::geometryFetched()
const
668 return mGeometryFetched;
@ Fid
Filter using feature ID.
@ Fids
Filter using feature IDs.
@ Expression
Filter using expression.
@ NoFilter
No filter is applied.
@ SubsetOfAttributes
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag).
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
@ NoFlags
No flags are set.
@ NoFilter
No spatial filtering of features.
QFlags< FeatureRequestFlag > FeatureRequestFlags
Flags for controlling feature requests.
WkbType
The WKB type describes the number of dimensions a geometry has.
Abstract base class for cache indices.
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.
bool close()
Call to end the iteration.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
Qgis::FeatureRequestFilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
Qgis::FeatureRequestFlags flags() const
Returns the flags which affect how features are fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
QgsAttributeList subsetOfAttributes() const
Returns the subset of attributes which at least need to be fetched.
const QgsFeatureIds & filterFids() const
Returns the feature IDs that should be fetched.
QgsFeatureId filterFid() const
Returns the feature ID that should be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool isValid() const
Returns the validity of this feature.
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
void dataChanged()
Data of layer changed.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
bool isFidCached(QgsFeatureId fid) const
Check if a certain feature id is cached.
void featureAboutToBeAdded(QgsFeatureId fid)
Emitted when a new feature is about to be added to the cache (as a result of feature addition to the ...
void setFullCache(bool fullCache)
This enables or disables full caching.
void finished()
When filling the cache, this signal gets emitted once the cache is fully initialized.
void featureRemoved(QgsFeatureId fid)
Gets called, whenever a feature has been removed.
void setCacheAddedAttributes(bool cacheAddedAttributes)
If this is enabled, the subset of cached attributes will automatically be extended to also include ne...
friend class QgsCachedFeature
void invalidated()
The cache has been invalidated and cleared.
void setCacheSubsetOfAttributes(const QgsAttributeList &attributes)
Set the list (possibly a subset) of attributes to be cached.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer and this cache.
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted from the layer and this cache.
QgsFields fields() const
Returns the fields associated with features in the cache.
void setCacheSize(long long cacheSize)
Sets the maximum number of features to keep in the cache.
void cachedLayerDeleted()
Is emitted when the cached layer is deleted.
friend class QgsCachedFeatureWriterIterator
void requestCompleted(const QgsFeatureRequest &featureRequest, const QgsFeatureIds &fids)
Gets called, whenever the full list of feature ids for a certain request is known.
void attributeValueChanged(QgsFeatureId fid, int field, const QVariant &value)
Emitted when an attribute is changed.
bool removeCachedFeature(QgsFeatureId fid)
Removes the feature identified by fid from the cache if present.
void progress(int i, bool &cancel)
When filling the cache, this signal gets emitted periodically to notify about the progress and to be ...
QgsVectorLayer * layer()
Returns the layer to which this cache belongs.
long long featureCount() const
Returns the number of features contained in the source, or -1 if the feature count is unknown.
QgsCoordinateReferenceSystem sourceCrs() const
Returns the coordinate reference system for features in the cache.
bool checkInformationCovered(const QgsFeatureRequest &featureRequest)
Checks if the information required to complete the request is cached.
QgsFeatureIds cachedFeatureIds() const
Returns the set of feature IDs for features which are cached.
bool featureAtIdWithAllAttributes(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id with all attributes, if the cached feature already contains ...
bool cacheGeometry() const
Returns true if the cache will fetch and cache feature geometries.
Qgis::WkbType wkbType() const
Returns the geometry type for features in the cache.
void featureAboutToBeDeleted(QgsFeatureId fid)
Emitted when a feature is about to be deleted from this cache (as a result of a feature deletion from...
friend class QgsCachedFeatureIterator
long long cacheSize() const
Returns the maximum number of features this cache will hold.
QgsAttributeList cacheSubsetOfAttributes() const
Returns the list (possibly a subset) of cached attributes.
void addCacheIndex(QgsAbstractCacheIndex *cacheIndex)
Adds a QgsAbstractCacheIndex to this cache.
QgsVectorLayerCache(QgsVectorLayer *layer, int cacheSize, QObject *parent=nullptr)
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
~QgsVectorLayerCache() override
bool completeFeatureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id with all attributes and geometry, if the cached feature alre...
bool featureAtId(QgsFeatureId featureId, QgsFeature &feature, bool skipCache=false)
Gets the feature at the given feature id.
Defines left outer join from our vector layer to some other vector layer.
Represents a vector layer which manages a vector based dataset.
void attributeAdded(int idx)
Will be emitted, when a new attribute has been added to this vector layer.
void attributeDeleted(int idx)
Will be emitted, when an attribute has been deleted from this vector layer.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
void featureDeleted(QgsFeatureId fid)
Emitted when a feature has been deleted.
const QList< QgsVectorLayerJoinInfo > vectorJoins() const
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
#define QGIS_CHECK_QOBJECT_THREAD_EQUALITY(other)
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS