QGIS API Documentation  2.99.0-Master (8ec3eaf)
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 }
36 
38 {
39  bool dataOk = false;
40  if ( mRequest.limit() >= 0 && mFetchedCount >= mRequest.limit() )
41  {
42  return false;
43  }
44 
45  if ( mUseCachedFeatures )
46  {
47  if ( mFeatureIterator != mCachedFeatures.constEnd() )
48  {
49  f = mFeatureIterator->mFeature;
50  ++mFeatureIterator;
51  dataOk = true;
52  }
53  else
54  {
55  dataOk = false;
56  // even the zombie dies at this point...
57  mZombie = false;
58  }
59  }
60  else
61  {
62  switch ( mRequest.filterType() )
63  {
65  dataOk = nextFeatureFilterExpression( f );
66  break;
67 
69  dataOk = nextFeatureFilterFids( f );
70  break;
71 
72  default:
73  dataOk = fetchFeature( f );
74  break;
75  }
76  }
77 
78  if ( dataOk )
79  mFetchedCount++;
80 
81  return dataOk;
82 }
83 
85 {
86  while ( fetchFeature( f ) )
87  {
90  return true;
91  }
92  return false;
93 }
94 
96 {
97  while ( fetchFeature( f ) )
98  {
99  if ( mRequest.filterFids().contains( f.id() ) )
100  return true;
101  }
102  return false;
103 }
104 
106 {
107  // Prepare if required the simplification of geometries to fetch:
108  // This code runs here because of 'prepareSimplification()' is virtual and it can be overrided
109  // in inherited iterators who change the default behavior.
110  // It would be better to call this method in the constructor enabling virtual-calls as it is described by example at:
111  // http://www.parashift.com/c%2B%2B-faq-lite/calling-virtuals-from-ctor-idiom.html
112  if ( refs == 0 )
113  {
115 
116  // Should be called as last preparation step since it possibly will already fetch all features
117  setupOrderBy( mRequest.orderBy() );
118  }
119  refs++;
120 }
121 
123 {
124  refs--;
125  if ( !refs )
126  delete this;
127 }
128 
130 {
131  Q_UNUSED( simplifyMethod );
132  return false;
133 }
134 
135 void QgsAbstractFeatureIterator::setupOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
136 {
137  // Let the provider try using an efficient order by strategy first
138  if ( !orderBys.isEmpty() && !prepareOrderBy( orderBys ) )
139  {
140  // No success from the provider
141 
142  // Prepare the expressions
143  QList<QgsFeatureRequest::OrderByClause> preparedOrderBys( orderBys );
144  QList<QgsFeatureRequest::OrderByClause>::iterator orderByIt( preparedOrderBys.begin() );
145 
146  QgsExpressionContext* expressionContext( mRequest.expressionContext() );
147  do
148  {
149  orderByIt->expression().prepare( expressionContext );
150  }
151  while ( ++orderByIt != preparedOrderBys.end() );
152 
153  // Fetch all features
154  QgsIndexedFeature indexedFeature;
155  indexedFeature.mIndexes.resize( preparedOrderBys.size() );
156 
157  while ( nextFeature( indexedFeature.mFeature ) )
158  {
159  expressionContext->setFeature( indexedFeature.mFeature );
160  int i = 0;
161  Q_FOREACH ( const QgsFeatureRequest::OrderByClause& orderBy, preparedOrderBys )
162  {
163  indexedFeature.mIndexes.replace( i++, orderBy.expression().evaluate( expressionContext ) );
164  }
165 
166  // We need all features, to ignore the limit for this pre-fetch
167  // keep the fetched count at 0.
168  mFetchedCount = 0;
169  mCachedFeatures.append( indexedFeature );
170  }
171 
172  qSort( mCachedFeatures.begin(), mCachedFeatures.end(), QgsExpressionSorter( preparedOrderBys ) );
173 
174  mFeatureIterator = mCachedFeatures.constBegin();
175  mUseCachedFeatures = true;
176  // The real iterator is closed, we are only serving cached features
177  mZombie = true;
178  }
179 }
180 
181 bool QgsAbstractFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
182 {
183  Q_UNUSED( methodType )
184  return false;
185 }
186 
187 bool QgsAbstractFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
188 {
189  Q_UNUSED( orderBys )
190  return false;
191 }
192 
194 {
195 }
196 
198 
200 {
201  if ( this != &other )
202  {
203  if ( mIter )
204  mIter->deref();
205  mIter = other.mIter;
206  if ( mIter )
207  mIter->ref();
208  }
209  return *this;
210 }
QgsFeatureId id
Definition: qgsfeature.h:139
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:135
QgsExpression * filterExpression() const
Returns the filter expression if set.
Interface that can be optionaly 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.
virtual ~QgsAbstractFeatureIterator()
destructor makes sure that the iterator is closed properly
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters