1 /*************************************************************************** 2 qgsvectorlayerfeatureiterator.h 3 --------------------- 4 begin : Dezember 2012 5 copyright : (C) 2012 by Martin Dobias 6 email : wonder dot sk at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 #ifndef QGSVECTORLAYERFEATUREITERATOR_H 16 #define QGSVECTORLAYERFEATUREITERATOR_H 17 18 #include "qgis_core.h" 19 #include "qgis_sip.h" 20 #include "qgsfeatureiterator.h" 21 #include "qgsfields.h" 22 #include "qgscoordinatereferencesystem.h" 23 #include "qgsfeaturesource.h" 24 #include "qgsexpressioncontextscopegenerator.h" 25 26 #include <QPointer> 27 #include <QSet> 28 #include <memory> 29 30 typedef QMap<QgsFeatureId, QgsFeature> QgsFeatureMap SIP_SKIP; 31 32 class QgsExpressionFieldBuffer; 33 class QgsVectorLayer; 34 class QgsVectorLayerEditBuffer; 35 class QgsVectorLayerJoinBuffer; 36 class QgsVectorLayerJoinInfo; 37 class QgsExpressionContext; 38 39 class QgsVectorLayerFeatureIterator; 40 41 #ifdef SIP_RUN 42 % ModuleHeaderCode 43 #include "qgsfeatureiterator.h" 44 % End 45 #endif 46 47 /** 48 * \ingroup core 49 * \brief Partial snapshot of vector layer's state (only the members necessary for access to features) 50 */ 51 class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource 52 { 53 public: 54 55 /** 56 * Constructor for QgsVectorLayerFeatureSource. 57 * \param layer source layer 58 */ 59 explicit QgsVectorLayerFeatureSource( const QgsVectorLayer *layer ); 60 61 //! QgsVectorLayerFeatureSource cannot be copied 62 QgsVectorLayerFeatureSource( const QgsVectorLayerFeatureSource &other ) = delete; 63 //! QgsVectorLayerFeatureSource cannot be copied 64 QgsVectorLayerFeatureSource &operator==( const QgsVectorLayerFeatureSource &other ) = delete; 65 66 ~QgsVectorLayerFeatureSource() override; 67 68 QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) override; 69 70 friend class QgsVectorLayerFeatureIterator SIP_SKIP; 71 72 /** 73 * Returns the fields that will be available for features that are retrieved from 74 * this source. 75 * 76 * \since QGIS 3.0 77 */ 78 QgsFields fields() const; 79 80 /** 81 * Returns the coordinate reference system for features retrieved from this source. 82 * \since QGIS 3.0 83 */ 84 QgsCoordinateReferenceSystem crs() const; 85 86 /** 87 * Returns the layer id of the source layer. 88 * 89 * \since QGIS 3.4 90 */ 91 QString id() const; 92 93 protected: 94 95 std::unique_ptr< QgsAbstractFeatureSource > mProviderFeatureSource; 96 std::unique_ptr< QgsVectorLayerJoinBuffer > mJoinBuffer; 97 std::unique_ptr< QgsExpressionFieldBuffer > mExpressionFieldBuffer; 98 99 QgsFields mFields; 100 101 QString mId; 102 103 QgsExpressionContextScope mLayerScope; 104 105 bool mHasEditBuffer; 106 107 // A deep-copy is only performed, if the original maps change 108 // see here https://github.com/qgis/Quantum-GIS/pull/673 109 // for explanation 110 QgsFeatureMap mAddedFeatures; 111 QgsGeometryMap mChangedGeometries; 112 QgsFeatureIds mDeletedFeatureIds; 113 QList<QgsField> mAddedAttributes; 114 QgsChangedAttributesMap mChangedAttributeValues; 115 QgsAttributeList mDeletedAttributeIds; 116 117 QgsCoordinateReferenceSystem mCrs; 118 119 private: 120 #ifdef SIP_RUN 121 QgsVectorLayerFeatureSource( const QgsVectorLayerFeatureSource &other ); 122 #endif 123 }; 124 125 /** 126 * \ingroup core 127 */ 128 class CORE_EXPORT QgsVectorLayerFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource> 129 { 130 public: 131 QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request ); 132 133 ~QgsVectorLayerFeatureIterator() override; 134 135 //! reset the iterator to the starting position 136 bool rewind() override; 137 138 //! end of iterating: free the resources / lock 139 bool close() override; 140 141 void setInterruptionChecker( QgsFeedback *interruptionChecker ) override SIP_SKIP; 142 143 /** 144 * Join information prepared for fast attribute id mapping in QgsVectorLayerJoinBuffer::updateFeatureAttributes(). 145 * Created in the select() method of QgsVectorLayerJoinBuffer for the joins that contain fetched attributes 146 */ 147 struct CORE_EXPORT FetchJoinInfo 148 { 149 const QgsVectorLayerJoinInfo *joinInfo;//!< Canonical source of information about the join 150 QgsAttributeList attributes; //!< Attributes to fetch 151 int indexOffset; //!< At what position the joined fields start 152 153 #ifndef SIP_RUN 154 155 /** 156 * Feature source for join 157 * 158 * \note Not available in Python bindings 159 * \since QGIS 3.20 160 */ 161 std::shared_ptr< QgsVectorLayerFeatureSource > joinSource; 162 163 /** 164 * Fields from joined layer. 165 * 166 * \note Not available in Python bindings 167 * \since QGIS 3.20 168 */ 169 QgsFields joinLayerFields; 170 #endif 171 172 int targetField; //!< Index of field (of this layer) that drives the join 173 int joinField; //!< Index of field (of the joined layer) must have equal value 174 175 void addJoinedAttributesCached( QgsFeature &f, const QVariant &joinValue ) const; 176 void addJoinedAttributesDirect( QgsFeature &f, const QVariant &joinValue ) const; 177 }; 178 179 bool isValid() const override; 180 181 protected: 182 //! fetch next feature, return TRUE on success 183 bool fetchFeature( QgsFeature &feature ) override; 184 185 /** 186 * Overrides default method as we only need to filter features in the edit buffer 187 * while for others filtering is left to the provider implementation. 188 */ nextFeatureFilterExpression(QgsFeature & f)189 bool nextFeatureFilterExpression( QgsFeature &f ) override { return fetchFeature( f ); } 190 191 //! Setup the simplification of geometries to fetch using the specified simplify method 192 bool prepareSimplification( const QgsSimplifyMethod &simplifyMethod ) override; 193 194 //! \note not available in Python bindings 195 void rewindEditBuffer() SIP_SKIP; 196 197 //! \note not available in Python bindings 198 void prepareJoin( int fieldIdx ) SIP_SKIP; 199 200 //! \note not available in Python bindings 201 void prepareExpression( int fieldIdx ) SIP_SKIP; 202 203 //! \note not available in Python bindings 204 void prepareFields() SIP_SKIP; 205 206 //! \note not available in Python bindings 207 void prepareField( int fieldIdx ) SIP_SKIP; 208 209 //! \note not available in Python bindings 210 bool fetchNextAddedFeature( QgsFeature &f ) SIP_SKIP; 211 //! \note not available in Python bindings 212 bool fetchNextChangedGeomFeature( QgsFeature &f ) SIP_SKIP; 213 //! \note not available in Python bindings 214 bool fetchNextChangedAttributeFeature( QgsFeature &f ) SIP_SKIP; 215 //! \note not available in Python bindings 216 void useAddedFeature( const QgsFeature &src, QgsFeature &f ) SIP_SKIP; 217 //! \note not available in Python bindings 218 void useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f ) SIP_SKIP; 219 //! \note not available in Python bindings 220 bool nextFeatureFid( QgsFeature &f ) SIP_SKIP; 221 //! \note not available in Python bindings 222 void addJoinedAttributes( QgsFeature &f ) SIP_SKIP; 223 224 /** 225 * Adds attributes that don't source from the provider but are added inside QGIS 226 * Includes 227 * 228 * - Joined fields 229 * - Expression fields 230 * 231 * \param f The feature will be modified 232 * \note not available in Python bindings 233 */ 234 void addVirtualAttributes( QgsFeature &f ) SIP_SKIP; 235 236 /** 237 * Adds an expression based attribute to a feature 238 * \param f feature 239 * \param attrIndex attribute index 240 * \note not available in Python bindings 241 * \since QGIS 2.14 242 */ 243 void addExpressionAttribute( QgsFeature &f, int attrIndex ) SIP_SKIP; 244 245 /** 246 * Update feature with uncommitted attribute updates. 247 * \note not available in Python bindings 248 */ 249 void updateChangedAttributes( QgsFeature &f ) SIP_SKIP; 250 251 /** 252 * Update feature with uncommitted geometry updates. 253 * \note not available in Python bindings 254 */ 255 void updateFeatureGeometry( QgsFeature &f ) SIP_SKIP; 256 257 QgsFeatureRequest mProviderRequest; 258 QgsFeatureIterator mProviderIterator; 259 QgsFeatureRequest mChangedFeaturesRequest; 260 QgsFeatureIterator mChangedFeaturesIterator; 261 262 QgsRectangle mFilterRect; 263 QgsCoordinateTransform mTransform; 264 265 // only related to editing 266 QSet<QgsFeatureId> mFetchConsidered; 267 QgsGeometryMap::ConstIterator mFetchChangedGeomIt; 268 QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt; 269 270 bool mFetchedFid; // when iterating by FID: indicator whether it has been fetched yet or not 271 272 /** 273 * Information about joins used in the current select() statement. 274 * Allows faster mapping of attribute ids compared to mVectorJoins. 275 */ 276 QMap<const QgsVectorLayerJoinInfo *, QgsVectorLayerFeatureIterator::FetchJoinInfo> mFetchJoinInfo; 277 278 QMap<int, QgsExpression *> mExpressionFieldInfo; 279 280 bool mHasVirtualAttributes; 281 282 private: 283 #ifdef SIP_RUN 284 QgsVectorLayerFeatureIterator( const QgsVectorLayerFeatureIterator &rhs ); 285 #endif 286 287 void createExpressionContext(); 288 std::unique_ptr<QgsExpressionContext> mExpressionContext; 289 290 QgsFeedback *mInterruptionChecker = nullptr; 291 292 QList< int > mPreparedFields; 293 QList< int > mFieldsToPrepare; 294 295 //! Join list sorted by dependency 296 QList< FetchJoinInfo > mOrderedJoinInfoList; 297 298 /** 299 * Will always return TRUE. We assume that ordering has been done on provider level already. 300 * 301 */ 302 bool prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause> &orderBys ) override; 303 304 //! returns whether the iterator supports simplify geometries on provider side 305 bool providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const override; 306 307 void createOrderedJoinList(); 308 309 /** 310 * Performs any post-processing (such as transformation) and feature based validity checking, e.g. checking for geometry validity. 311 */ 312 bool postProcessFeature( QgsFeature &feature ); 313 314 /** 315 * Checks a feature's geometry for validity, if requested in feature request. 316 */ 317 bool checkGeometryValidity( const QgsFeature &feature ); 318 319 bool mDelegatedOrderByToProvider = false; 320 }; 321 322 323 324 /** 325 * \class QgsVectorLayerSelectedFeatureSource 326 * \ingroup core 327 * \brief QgsFeatureSource subclass for the selected features from a QgsVectorLayer. 328 * \since QGIS 3.0 329 */ 330 class CORE_EXPORT QgsVectorLayerSelectedFeatureSource : public QgsFeatureSource, public QgsExpressionContextScopeGenerator 331 { 332 public: 333 334 /** 335 * Constructor for QgsVectorLayerSelectedFeatureSource, for selected features from the specified \a layer. 336 * The currently selected feature IDs are stored, so change to the layer selection after constructing 337 * the QgsVectorLayerSelectedFeatureSource will not be reflected. 338 */ 339 QgsVectorLayerSelectedFeatureSource( QgsVectorLayer *layer ); 340 341 //! QgsVectorLayerSelectedFeatureSource cannot be copied 342 QgsVectorLayerSelectedFeatureSource( const QgsVectorLayerSelectedFeatureSource &other ) = delete; 343 //! QgsVectorLayerSelectedFeatureSource cannot be copied 344 QgsVectorLayerSelectedFeatureSource &operator==( const QgsVectorLayerSelectedFeatureSource &other ) = delete; 345 346 QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override; 347 QgsCoordinateReferenceSystem sourceCrs() const override; 348 QgsFields fields() const override; 349 QgsWkbTypes::Type wkbType() const override; 350 long featureCount() const override; 351 QString sourceName() const override; 352 QgsExpressionContextScope *createExpressionContextScope() const override; 353 SpatialIndexPresence hasSpatialIndex() const override; 354 355 private: 356 357 #ifdef SIP_RUN 358 QgsVectorLayerSelectedFeatureSource( const QgsVectorLayerSelectedFeatureSource &other ); 359 #endif 360 361 // ideally this wouldn't be mutable, but QgsVectorLayerFeatureSource has non-const getFeatures() 362 mutable QgsVectorLayerFeatureSource mSource; 363 QgsFeatureIds mSelectedFeatureIds; 364 QgsWkbTypes::Type mWkbType = QgsWkbTypes::Unknown; 365 QString mName; 366 QPointer< QgsVectorLayer > mLayer; 367 368 }; 369 370 ///@cond PRIVATE 371 372 #ifndef SIP_RUN 373 class QgsVectorLayerSelectedFeatureIterator : public QgsAbstractFeatureIterator 374 { 375 public: 376 377 QgsVectorLayerSelectedFeatureIterator( const QgsFeatureIds &selectedFeatureIds, 378 const QgsFeatureRequest &request, 379 QgsVectorLayerFeatureSource &source ); 380 381 bool rewind() override; 382 bool close() override; 383 384 protected: 385 bool fetchFeature( QgsFeature &f ) override; 386 387 private: 388 QgsFeatureIds mSelectedFeatureIds; 389 QgsFeatureIterator mIterator; 390 391 }; 392 393 #endif 394 395 ///@endcond 396 397 #endif // QGSVECTORLAYERFEATUREITERATOR_H 398