QGIS API Documentation  2.99.0-Master (d55fa22)
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  {
85  if ( mRequest.filterExpression()->evaluate( mRequest.expressionContext() ).toBool() )
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->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  std::sort( 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:70
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.
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:61
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