QGIS/src/core/qgsvectorlayerfeatureiterator.h
Nyall Dawson d830821b13 Remove QgsInterruptionChecker and replace with QgsFeedback use
There's little need for two classes with similar goals here.
2018-02-19 10:18:00 +10:00

318 lines
11 KiB
C++

/***************************************************************************
qgsvectorlayerfeatureiterator.h
---------------------
begin : Dezember 2012
copyright : (C) 2012 by Martin Dobias
email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSVECTORLAYERFEATUREITERATOR_H
#define QGSVECTORLAYERFEATUREITERATOR_H
#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgsfeatureiterator.h"
#include "qgsfields.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsfeaturesource.h"
#include <QSet>
#include <memory>
typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap SIP_SKIP;
class QgsExpressionFieldBuffer;
class QgsVectorLayer;
class QgsVectorLayerEditBuffer;
class QgsVectorLayerJoinBuffer;
class QgsVectorLayerJoinInfo;
class QgsExpressionContext;
class QgsVectorLayerFeatureIterator;
#ifdef SIP_RUN
% ModuleHeaderCode
#include "qgsfeatureiterator.h"
% End
#endif
/**
* \ingroup core
* Partial snapshot of vector layer's state (only the members necessary for access to features)
*/
class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
{
public:
/**
* Constructor for QgsVectorLayerFeatureSource.
* \param layer source layer
*/
explicit QgsVectorLayerFeatureSource( const QgsVectorLayer *layer );
~QgsVectorLayerFeatureSource() override;
QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) override;
friend class QgsVectorLayerFeatureIterator SIP_SKIP;
/**
* Returns the fields that will be available for features that are retrieved from
* this source.
*
* \since QGIS 3.0
*/
QgsFields fields() const;
/**
* Returns the coordinate reference system for features retrieved from this source.
* \since QGIS 3.0
*/
QgsCoordinateReferenceSystem crs() const;
protected:
QgsAbstractFeatureSource *mProviderFeatureSource = nullptr;
QgsVectorLayerJoinBuffer *mJoinBuffer = nullptr;
QgsExpressionFieldBuffer *mExpressionFieldBuffer = nullptr;
QgsFields mFields;
QgsExpressionContextScope mLayerScope;
bool mHasEditBuffer;
// A deep-copy is only performed, if the original maps change
// see here https://github.com/qgis/Quantum-GIS/pull/673
// for explanation
QgsFeatureMap mAddedFeatures;
QgsGeometryMap mChangedGeometries;
QgsFeatureIds mDeletedFeatureIds;
QList<QgsField> mAddedAttributes;
QgsChangedAttributesMap mChangedAttributeValues;
QgsAttributeList mDeletedAttributeIds;
QgsCoordinateReferenceSystem mCrs;
};
/**
* \ingroup core
*/
class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>
{
public:
QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request );
~QgsVectorLayerFeatureIterator() override;
//! reset the iterator to the starting position
bool rewind() override;
//! end of iterating: free the resources / lock
bool close() override;
void setInterruptionChecker( QgsFeedback *interruptionChecker ) override SIP_SKIP;
/**
* Join information prepared for fast attribute id mapping in QgsVectorLayerJoinBuffer::updateFeatureAttributes().
* Created in the select() method of QgsVectorLayerJoinBuffer for the joins that contain fetched attributes
*/
struct CORE_EXPORT FetchJoinInfo
{
const QgsVectorLayerJoinInfo *joinInfo;//!< Canonical source of information about the join
QgsAttributeList attributes; //!< Attributes to fetch
int indexOffset; //!< At what position the joined fields start
QgsVectorLayer *joinLayer; //!< Resolved pointer to the joined layer
int targetField; //!< Index of field (of this layer) that drives the join
int joinField; //!< Index of field (of the joined layer) must have equal value
void addJoinedAttributesCached( QgsFeature &f, const QVariant &joinValue ) const;
void addJoinedAttributesDirect( QgsFeature &f, const QVariant &joinValue ) const;
};
bool isValid() const override;
protected:
//! fetch next feature, return true on success
bool fetchFeature( QgsFeature &feature ) override;
/**
* Overrides default method as we only need to filter features in the edit buffer
* while for others filtering is left to the provider implementation.
*/
bool nextFeatureFilterExpression( QgsFeature &f ) override { return fetchFeature( f ); }
//! Setup the simplification of geometries to fetch using the specified simplify method
bool prepareSimplification( const QgsSimplifyMethod &simplifyMethod ) override;
//! \note not available in Python bindings
void rewindEditBuffer() SIP_SKIP;
//! \note not available in Python bindings
void prepareJoin( int fieldIdx ) SIP_SKIP;
//! \note not available in Python bindings
void prepareExpression( int fieldIdx ) SIP_SKIP;
//! \note not available in Python bindings
void prepareFields() SIP_SKIP;
//! \note not available in Python bindings
void prepareField( int fieldIdx ) SIP_SKIP;
//! \note not available in Python bindings
bool fetchNextAddedFeature( QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
bool fetchNextChangedGeomFeature( QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
bool fetchNextChangedAttributeFeature( QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
void useAddedFeature( const QgsFeature &src, QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
void useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
bool nextFeatureFid( QgsFeature &f ) SIP_SKIP;
//! \note not available in Python bindings
void addJoinedAttributes( QgsFeature &f ) SIP_SKIP;
/**
* Adds attributes that don't source from the provider but are added inside QGIS
* Includes
* - Joined fields
* - Expression fields
*
* \param f The feature will be modified
* \note not available in Python bindings
*/
void addVirtualAttributes( QgsFeature &f ) SIP_SKIP;
/**
* Adds an expression based attribute to a feature
* \param f feature
* \param attrIndex attribute index
* \since QGIS 2.14
* \note not available in Python bindings
*/
void addExpressionAttribute( QgsFeature &f, int attrIndex ) SIP_SKIP;
/**
* Update feature with uncommitted attribute updates.
* \note not available in Python bindings
*/
void updateChangedAttributes( QgsFeature &f ) SIP_SKIP;
/**
* Update feature with uncommitted geometry updates.
* \note not available in Python bindings
*/
void updateFeatureGeometry( QgsFeature &f ) SIP_SKIP;
QgsFeatureRequest mProviderRequest;
QgsFeatureIterator mProviderIterator;
QgsFeatureRequest mChangedFeaturesRequest;
QgsFeatureIterator mChangedFeaturesIterator;
QgsRectangle mFilterRect;
QgsCoordinateTransform mTransform;
// only related to editing
QSet<QgsFeatureId> mFetchConsidered;
QgsGeometryMap::ConstIterator mFetchChangedGeomIt;
QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt;
bool mFetchedFid; // when iterating by FID: indicator whether it has been fetched yet or not
/**
* Information about joins used in the current select() statement.
Allows faster mapping of attribute ids compared to mVectorJoins */
QMap<const QgsVectorLayerJoinInfo *, QgsVectorLayerFeatureIterator::FetchJoinInfo> mFetchJoinInfo;
QMap<int, QgsExpression *> mExpressionFieldInfo;
bool mHasVirtualAttributes;
private:
#ifdef SIP_RUN
QgsVectorLayerFeatureIterator( const QgsVectorLayerFeatureIterator &rhs );
#endif
std::unique_ptr<QgsExpressionContext> mExpressionContext;
QgsFeedback *mInterruptionChecker = nullptr;
QList< int > mPreparedFields;
QList< int > mFieldsToPrepare;
//! Join list sorted by dependency
QList< FetchJoinInfo > mOrderedJoinInfoList;
/**
* Will always return true. We assume that ordering has been done on provider level already.
*
*/
bool prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys ) override;
//! returns whether the iterator supports simplify geometries on provider side
bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const override;
void createOrderedJoinList();
/**
* Performs any post-processing (such as transformation) and feature based validity checking, e.g. checking for geometry validity.
*/
bool postProcessFeature( QgsFeature &feature );
/**
* Checks a feature's geometry for validity, if requested in feature request.
*/
bool checkGeometryValidity( const QgsFeature &feature );
};
/**
* \class QgsVectorLayerSelectedFeatureSource
* \ingroup core
* QgsFeatureSource subclass for the selected features from a QgsVectorLayer.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsVectorLayerSelectedFeatureSource : public QgsFeatureSource
{
public:
/**
* Constructor for QgsVectorLayerSelectedFeatureSource, for selected features from the specified \a layer.
* The currently selected feature IDs are stored, so change to the layer selection after constructing
* the QgsVectorLayerSelectedFeatureSource will not be reflected.
*/
QgsVectorLayerSelectedFeatureSource( QgsVectorLayer *layer );
QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override;
QgsCoordinateReferenceSystem sourceCrs() const override;
QgsFields fields() const override;
QgsWkbTypes::Type wkbType() const override;
long featureCount() const override;
QString sourceName() const override;
private:
// ideally this wouldn't be mutable, but QgsVectorLayerFeatureSource has non-const getFeatures()
mutable QgsVectorLayerFeatureSource mSource;
QgsFeatureIds mSelectedFeatureIds;
QgsWkbTypes::Type mWkbType = QgsWkbTypes::Unknown;
QString mName;
};
#endif // QGSVECTORLAYERFEATUREITERATOR_H