QGIS API Documentation  3.0.2-Girona (307d082)
qgsfeaturerequest.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeaturerequest.cpp
3  ---------------------
4  begin : Mai 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 "qgsfeaturerequest.h"
16 
17 #include "qgsfields.h"
18 #include "qgsgeometry.h"
19 
20 #include <QStringList>
21 
22 //constants
23 const QString QgsFeatureRequest::ALL_ATTRIBUTES = QStringLiteral( "#!allattributes!#" );
24 
26  : mFlags( nullptr )
27 {
28 }
29 
31  : mFilter( FilterFid )
32  , mFilterFid( fid )
33  , mFlags( nullptr )
34 {
35 }
36 
38  : mFilter( FilterFids )
39  , mFilterFids( fids )
40  , mFlags( nullptr )
41 {
42 
43 }
44 
46  : mFilterRect( rect )
47  , mFlags( nullptr )
48 {
49 }
50 
51 QgsFeatureRequest::QgsFeatureRequest( const QgsExpression &expr, const QgsExpressionContext &context )
53  , mFilterExpression( new QgsExpression( expr ) )
54  , mExpressionContext( context )
55  , mFlags( nullptr )
56 {
57 }
58 
60 {
61  operator=( rh );
62 }
63 
65 {
66  mFlags = rh.mFlags;
67  mFilter = rh.mFilter;
71  if ( rh.mFilterExpression )
72  {
73  mFilterExpression.reset( new QgsExpression( *rh.mFilterExpression ) );
74  }
75  else
76  {
77  mFilterExpression.reset( nullptr );
78  }
82  mAttrs = rh.mAttrs;
84  mLimit = rh.mLimit;
85  mOrderBy = rh.mOrderBy;
86  mCrs = rh.mCrs;
89  return *this;
90 }
91 
93 {
94  mFilterRect = rect;
95  return *this;
96 }
97 
99 {
100  mFilter = FilterFid;
101  mFilterFid = fid;
102  return *this;
103 }
104 
106 {
108  mFilterFids = fids;
109  return *this;
110 }
111 
113 {
114  mInvalidGeometryFilter = check;
115  return *this;
116 }
117 
118 QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
119 {
120  mInvalidGeometryCallback = callback;
121  return *this;
122 }
123 
125 {
127  mFilterExpression.reset( new QgsExpression( expression ) );
128  return *this;
129 }
130 
132 {
133  if ( mFilterExpression )
134  {
135  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
136  }
137  else
138  {
139  setFilterExpression( expression );
140  }
141  return *this;
142 }
143 
145 {
146  mExpressionContext = context;
147  return *this;
148 }
149 
150 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
151 {
152  mOrderBy.append( OrderByClause( expression, ascending ) );
153  return *this;
154 }
155 
156 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
157 {
158  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
159  return *this;
160 }
161 
163 {
164  return mOrderBy;
165 }
166 
168 {
169  mOrderBy = orderBy;
170  return *this;
171 }
172 
174 {
175  mLimit = limit;
176  return *this;
177 }
178 
180 {
181  mFlags = flags;
182  return *this;
183 }
184 
186 {
188  mAttrs = attrs;
189  return *this;
190 }
191 
192 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
193 {
194  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
195  {
196  //attribute string list contains the all attributes flag, so we must fetch all attributes
197  return *this;
198  }
199 
201  mAttrs.clear();
202 
203  Q_FOREACH ( const QString &attrName, attrNames )
204  {
205  int attrNum = fields.lookupField( attrName );
206  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
207  mAttrs.append( attrNum );
208  }
209 
210  return *this;
211 }
212 
213 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
214 {
215  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
216  {
217  //attribute string list contains the all attributes flag, so we must fetch all attributes
218  return *this;
219  }
220 
222  mAttrs.clear();
223 
224  Q_FOREACH ( const QString &attrName, attrNames )
225  {
226  int attrNum = fields.lookupField( attrName );
227  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
228  mAttrs.append( attrNum );
229  }
230 
231  return *this;
232 }
233 
235 {
237  return *this;
238 }
239 
240 
242 {
243  return mCrs;
244 }
245 
247 {
248  return mTransformContext;
249 }
250 
252 {
253  mCrs = crs;
254  mTransformContext = context;
255  return *this;
256 }
257 
258 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
259 {
260  mTransformErrorCallback = callback;
261  return *this;
262 }
263 
265 {
266  if ( !mFilterRect.isNull() )
267  {
268  if ( !feature.hasGeometry() || !feature.geometry().intersects( mFilterRect ) )
269  return false;
270  }
271 
272  switch ( mFilter )
273  {
275  return true;
276 
278  return ( feature.id() == mFilterFid );
279 
281  mExpressionContext.setFeature( feature );
282  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
283 
285  return ( mFilterFids.contains( feature.id() ) );
286  }
287 
288  return true;
289 }
290 
292 {
293  return mConnectionTimeout;
294 }
295 
297 {
299 }
300 
301 
302 #include "qgsfeatureiterator.h"
303 #include "qgslogger.h"
304 
306 {
307  while ( !mActiveIterators.empty() )
308  {
309  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
310  QgsDebugMsg( "closing active iterator" );
311  it->close();
312  }
313 }
314 
316 {
317  mActiveIterators.insert( it );
318 }
319 
321 {
322  mActiveIterators.remove( it );
323 }
324 
325 
326 
327 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
328  : mExpression( expression )
329  , mAscending( ascending )
330 {
331  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
332  mNullsFirst = !ascending;
333 }
334 
336  : mExpression( expression )
337  , mAscending( ascending )
338  , mNullsFirst( nullsfirst )
339 {
340 }
341 
343  : mExpression( expression )
344  , mAscending( ascending )
345 {
346  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
347  mNullsFirst = !ascending;
348 }
349 
350 QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
351  : mExpression( expression )
352  , mAscending( ascending )
353  , mNullsFirst( nullsfirst )
354 {
355 
356 }
357 
359 {
360  return mAscending;
361 }
362 
364 {
365  mAscending = ascending;
366 }
367 
369 {
370  return mNullsFirst;
371 }
372 
374 {
375  mNullsFirst = nullsFirst;
376 }
377 
379 {
380  return QStringLiteral( "%1 %2 %3" )
381  .arg( mExpression.expression(),
382  mAscending ? "ASC" : "DESC",
383  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
384 }
385 
387 {
388  return mExpression;
389 }
390 
392 {
393  return mExpression.prepare( context );
394 }
395 
397 
398 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
399 {
400  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, other )
401  {
402  append( clause );
403  }
404 }
405 
406 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
407 {
408  return *this;
409 }
410 
411 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
412 {
413  QDomDocument doc = elem.ownerDocument();
414  QList<OrderByClause>::ConstIterator it;
415  for ( it = constBegin(); it != constEnd(); ++it )
416  {
417  const OrderByClause &clause = *it;
418  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
419  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
420  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
421  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
422 
423  elem.appendChild( clauseElem );
424  }
425 }
426 
427 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
428 {
429  clear();
430 
431  QDomNodeList clauses = elem.childNodes();
432 
433  for ( int i = 0; i < clauses.size(); ++i )
434  {
435  QDomElement clauseElem = clauses.at( i ).toElement();
436  QString expression = clauseElem.text();
437  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
438  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
439 
440  append( OrderByClause( expression, asc, nullsFirst ) );
441  }
442 }
443 
445 {
446  QSet<QString> usedAttributes;
447 
448  QList<OrderByClause>::ConstIterator it;
449  for ( it = constBegin(); it != constEnd(); ++it )
450  {
451  const OrderByClause &clause = *it;
452 
453  usedAttributes.unite( clause.expression().referencedColumns() );
454  }
455 
456  return usedAttributes;
457 }
458 
460 {
461  QStringList results;
462 
463  QList<OrderByClause>::ConstIterator it;
464  for ( it = constBegin(); it != constEnd(); ++it )
465  {
466  const OrderByClause &clause = *it;
467 
468  results << clause.dump();
469  }
470 
471  return results.join( QStringLiteral( ", " ) );
472 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature&#39;s geometries.
QgsFeatureId id
Definition: qgsfeature.h:71
QgsCoordinateReferenceSystem mCrs
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:39
long limit() const
Returns the maximum number of features to request, or -1 if no limit set.
bool nullsFirst() const
Set if NULLS should be returned first.
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
QSet< QString > CORE_EXPORT usedAttributes() const
Returns a set of used attributes.
Filter using feature ID.
Filter using feature IDs.
QgsSimplifyMethod mSimplifyMethod
QgsFeatureRequest & setInvalidGeometryCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering an invalid geometry and invalidGeometryCheck() is s...
bool ascending() const
Order ascending.
const Flags & flags() const
QString dump() const
Dumps the content to an SQL equivalent.
void iteratorClosed(QgsAbstractFeatureIterator *it)
QgsFeatureRequest & setInvalidGeometryCheck(InvalidGeometryCheck check)
Sets invalid geometry checking behavior.
InvalidGeometryCheck mInvalidGeometryFilter
QList< QgsFeatureRequest::OrderByClause > CORE_EXPORT list() const
Get a copy as a list of OrderByClauses.
QString CORE_EXPORT dump() const
Dumps the content to an SQL equivalent syntax.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:544
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for feature&#39;s geometries, or an invalid QgsCoordi...
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfields.h:42
void CORE_EXPORT load(const QDomElement &elem)
Deserialize from XML.
QgsFeatureRequest & addOrderBy(const QString &expression, bool ascending=true)
Adds a new OrderByClause, appending it as the least important one.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:62
QgsFeatureRequest & operator=(const QgsFeatureRequest &rh)
Assignment operator.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
QgsExpressionContext mExpressionContext
InvalidGeometryCheck
Handling of features with invalid geometries.
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
QgsFeatureRequest & combineFilterExpression(const QString &expression)
Modifies the existing filter expression to add an additional expression filter.
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
CORE_EXPORT OrderBy()
Create a new empty order by.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
OrderByClause(const QString &expression, bool ascending=true)
Creates a new OrderByClause for a QgsFeatureRequest.
std::unique_ptr< QgsExpression > mFilterExpression
Internal feature iterator to be implemented within data providers.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsFeatureRequest()
construct a default request: for all features get attributes and geometries
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
static const QString ALL_ATTRIBUTES
A special attribute that if set matches all attributes.
QgsRectangle mFilterRect
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
void setConnectionTimeout(int connectionTimeout)
The timeout for how long we should wait for a connection if none is available from the pool at this m...
Contains information about the context in which a coordinate transform is executed.
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
QgsFeatureRequest & setTransformErrorCallback(const std::function< void(const QgsFeature &)> &callback)
Sets a callback function to use when encountering a transform error when iterating features and a des...
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
bool prepare(QgsExpressionContext *context)
Prepare the expression with the given context.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureId mFilterFid
QgsExpression expression() const
The expression.
No filter is applied.
std::function< void(const QgsFeature &) > mInvalidGeometryCallback
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
QgsCoordinateTransformContext mTransformContext
std::function< void(const QgsFeature &) > mTransformErrorCallback
void setAscending(bool ascending)
Set if ascending order is requested.
QgsAttributeList mAttrs
This class represents a coordinate reference system (CRS).
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
qint64 QgsFeatureId
Definition: qgsfeature.h:37
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
QList< int > QgsAttributeList
Definition: qgsfield.h:27
int connectionTimeout() const
The timeout for how long we should wait for a connection if none is available from the pool at this m...
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
QgsCoordinateTransformContext transformContext() const
Returns the transform context, for use when a destinationCrs() has been set and reprojection is requi...
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
Represents a list of OrderByClauses, with the most important first and the least important last...
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Set flags that affect how features will be fetched.
void iteratorOpened(QgsAbstractFeatureIterator *it)
void setNullsFirst(bool nullsFirst)
Set if NULLS should be returned first.