/*************************************************************************** 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 #include typedef QMap 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 mAddedAttributes; QgsChangedAttributesMap mChangedAttributeValues; QgsAttributeList mDeletedAttributeIds; QgsCoordinateReferenceSystem mCrs; }; /** * \ingroup core */ class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureIteratorFromSource { 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 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 mFetchJoinInfo; QMap mExpressionFieldInfo; bool mHasVirtualAttributes; private: #ifdef SIP_RUN QgsVectorLayerFeatureIterator( const QgsVectorLayerFeatureIterator &rhs ); #endif std::unique_ptr 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 &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