QGIS API Documentation  2.99.0-Master (0a63d1f)
qgsfeatureiterator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeatureiterator.cpp
3  ---------------------
4  begin : Juli 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 #include "qgsfeatureiterator.h"
16 #include "qgslogger.h"
17 
18 #include "qgssimplifymethod.h"
19 
20 #include "qgsexpressionsorter.h"
21 
23  : mRequest( request )
24  , mClosed( false )
25  , mZombie( false )
26  , refs( 0 )
27  , mFetchedCount( 0 )
28  , mCompileStatus( NoCompilation )
29  , mUseCachedFeatures( false )
30 {
31 }
32 
34 {
35  bool dataOk = false;
36  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
37  {
38  return false;
39  }
40 
41  if ( mUseCachedFeatures )
42  {
43  if ( mFeatureIterator != mCachedFeatures.constEnd() )
44  {
45  f = mFeatureIterator->mFeature;
46  ++mFeatureIterator;
47  dataOk = true;
48  }
49  else
50  {
51  dataOk = false;
52  // even the zombie dies at this point...
53  mZombie = false;
54  }
55  }
56  else
57  {
58  switch ( mRequest.filterType() )
59  {
61  dataOk = nextFeatureFilterExpression( f );
62  break;
63 
65  dataOk = nextFeatureFilterFids( f );
66  break;
67 
68  default:
69  dataOk = fetchFeature( f );
70  break;
71  }
72  }
73 
74  if ( dataOk )
75  mFetchedCount++;
76 
77  return dataOk;
78 }
79 
81 {
82  while ( fetchFeature( f ) )
83  {
86  return true;
87  }
88  return false;
89 }
90 
92 {
93  while ( fetchFeature( f ) )
94  {
95  if ( mRequest.filterFids().contains( f.id() ) )
96  return true;
97  }
98  return false;
99 }
100 
102 {
103  // Prepare if required the simplification of geometries to fetch:
104  // This code runs here because of 'prepareSimplification()' is virtual and it can be overridden
105  // in inherited iterators who change the default behavior.
106  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
107  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
108  if ( refs == 0 )
109  {
111 
112  // Should be called as last preparation step since it possibly will already fetch all features
113  setupOrderBy( mRequest.orderBy() );
114  }
115  refs++;
116 }
117 
119 {
120  refs--;
121  if ( !refs )
122  delete this;
123 }
124 
126 {
127  Q_UNUSED( simplifyMethod );
128  return false;
129 }
130 
131 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
132 {
133  // Let the provider try using an efficient order by strategy first
134  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
135  {
136  // No success from the provider
137 
138  // Prepare the expressions
139  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
140  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
141 
142  QgsExpressionContext* expressionContext( mRequest.expressionContext() );
143  do
144  {
145  orderByIt->expression().prepare( expressionContext );
146  }
147  while ( ++orderByIt != preparedOrderBys.end() );
148 
149  // Fetch all features
150  QgsIndexedFeature indexedFeature;
151  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
152 
153  while ( nextFeature( indexedFeature.mFeature ) )
154  {
155  expressionContext->setFeature( indexedFeature.mFeature );
156  int i = 0;
157  Q_FOREACH ( const QgsFeatureRequest::OrderByClause& orderBy, preparedOrderBys )
158  {
159  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
160  }
161 
162  // We need all features, to ignore the limit for this pre-fetch
163  // keep the fetched count at 0.
164  mFetchedCount = 0;
165  mCachedFeatures.append( indexedFeature );
166  }
167 
168  qSort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
169 
170  mFeatureIterator = mCachedFeatures.constBegin();
171  mUseCachedFeatures = true;
172  // The real iterator is closed, we are only serving cached features
173  mZombie = true;
174  }
175 }
176 
177 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
178 {
179  Q_UNUSED( methodType )
180  return false;
181 }
182 
183 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
184 {
185  Q_UNUSED( orderBys )
186  return false;
187 }
188 
190 {
191 }
192 
194 
196 {
197  if ( this != &other )
198  {
199  if ( mIter )
200  mIter->deref();
201  mIter = other.mIter;
202  if ( mIter )
203  mIter->ref();
204  }
205  return *this;
206 }
QgsFeatureId id
Definition: qgsfeature.h:140
Wrapper for iterator of features from vector data provider or vector layer.
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
Filter using feature IDs.
long mFetchedCount
Number of features already fetched by iterator.
virtual bool fetchFeature(QgsFeature &f)=0
If you write a feature iterator for your provider, this is the method you need to implement!! ...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
QVariant evaluate()
Evaluate the feature and return the result.
FilterType filterType() const
Return the filter type which is currently set on this request.
const QgsFeatureIds & filterFids() const
Get feature IDs that should be fetched.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:136
QgsExpression * filterExpression() const
Returns the filter expression if set.
Interface that can be optionally attached to an iterator so its nextFeature() implementaton can check...
virtual bool nextFeature(QgsFeature &f)
fetch next feature, return true on success
Temporarily used structure to cache order by information.
QgsFeatureIterator & operator=(const QgsFeatureIterator &other)
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual bool nextFeatureFilterExpression(QgsFeature &f)
By default, the iterator will fetch all features and check if the feature matches the expression...
bool mZombie
A feature iterator may be closed already but still be serving features from the cache.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void deref()
Remove reference, delete if refs == 0.
virtual bool nextFeatureFilterFids(QgsFeature &f)
By default, the iterator will fetch all features and check if the id is in the request.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureRequest mRequest
A copy of the feature request.
QgsExpression expression() const
The expression.
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
QgsAbstractFeatureIterator * mIter
QVector< QVariant > mIndexes
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
int refs
reference counting (to allow seamless copying of QgsFeatureIterator instances) TODO QGIS3: make this ...
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod)
Setup the simplification of geometries to fetch using the specified simplify method.
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters