QGIS API Documentation  2.17.0-Master (6f7b933)
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() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
Wrapper for iterator of features from vector data provider or vector layer.
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
Filter using feature IDs.
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
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.
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:187
int size() const
Interface that can be optionaly attached to an iterator so its nextFeature() implementaton can check ...
QgsExpression expression() const
The expression.
void append(const T &value)
void resize(int size)
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)
bool isEmpty() const
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)...
FilterType filterType() const
Return the filter type which is currently set on this request.
void deref()
remove reference, delete if refs == 0
iterator end()
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
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.
bool contains(const T &value) const
QgsFeatureRequest mRequest
A copy of the feature request.
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
QgsAbstractFeatureIterator * mIter
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
QVector< QVariant > mIndexes
void replace(int i, const T &value)
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 ...
const_iterator constEnd() const
const_iterator constBegin() const
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
iterator begin()
QgsAbstractFeatureIterator(const QgsFeatureRequest &request)
base class constructor - stores the iteration parameters
QgsExpression * filterExpression() const
Returns the filter expression if set.