QGIS API Documentation  2.99.0-Master (9fdd060)
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;
88  return *this;
89 }
90 
92 {
93  mFilterRect = rect;
94  return *this;
95 }
96 
98 {
100  mFilterFid = fid;
101  return *this;
102 }
103 
105 {
107  mFilterFids = fids;
108  return *this;
109 }
110 
112 {
113  mInvalidGeometryFilter = check;
114  return *this;
115 }
116 
117 QgsFeatureRequest &QgsFeatureRequest::setInvalidGeometryCallback( const std::function<void ( const QgsFeature & )> &callback )
118 {
119  mInvalidGeometryCallback = callback;
120  return *this;
121 }
122 
124 {
126  mFilterExpression.reset( new QgsExpression( expression ) );
127  return *this;
128 }
129 
131 {
132  if ( mFilterExpression )
133  {
134  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
135  }
136  else
137  {
138  setFilterExpression( expression );
139  }
140  return *this;
141 }
142 
144 {
145  mExpressionContext = context;
146  return *this;
147 }
148 
149 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
150 {
151  mOrderBy.append( OrderByClause( expression, ascending ) );
152  return *this;
153 }
154 
155 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
156 {
157  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
158  return *this;
159 }
160 
162 {
163  return mOrderBy;
164 }
165 
167 {
168  mOrderBy = orderBy;
169  return *this;
170 }
171 
173 {
174  mLimit = limit;
175  return *this;
176 }
177 
179 {
180  mFlags = flags;
181  return *this;
182 }
183 
185 {
187  mAttrs = attrs;
188  return *this;
189 }
190 
191 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
192 {
193  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
194  {
195  //attribute string list contains the all attributes flag, so we must fetch all attributes
196  return *this;
197  }
198 
200  mAttrs.clear();
201 
202  Q_FOREACH ( const QString &attrName, attrNames )
203  {
204  int attrNum = fields.lookupField( attrName );
205  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
206  mAttrs.append( attrNum );
207  }
208 
209  return *this;
210 }
211 
212 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
213 {
214  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
215  {
216  //attribute string list contains the all attributes flag, so we must fetch all attributes
217  return *this;
218  }
219 
221  mAttrs.clear();
222 
223  Q_FOREACH ( const QString &attrName, attrNames )
224  {
225  int attrNum = fields.lookupField( attrName );
226  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
227  mAttrs.append( attrNum );
228  }
229 
230  return *this;
231 }
232 
234 {
236  return *this;
237 }
238 
239 
241 {
242  return mCrs;
243 }
244 
246 {
247  mCrs = crs;
248  return *this;
249 }
250 
251 QgsFeatureRequest &QgsFeatureRequest::setTransformErrorCallback( const std::function<void ( const QgsFeature & )> &callback )
252 {
253  mTransformErrorCallback = callback;
254  return *this;
255 }
256 
258 {
259  if ( !mFilterRect.isNull() )
260  {
261  if ( !feature.hasGeometry() || !feature.geometry().intersects( mFilterRect ) )
262  return false;
263  }
264 
265  switch ( mFilter )
266  {
268  return true;
269 
271  return ( feature.id() == mFilterFid );
272 
274  mExpressionContext.setFeature( feature );
275  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
276 
278  return ( mFilterFids.contains( feature.id() ) );
279  }
280 
281  return true;
282 }
283 
284 
285 #include "qgsfeatureiterator.h"
286 #include "qgslogger.h"
287 
289 {
290  while ( !mActiveIterators.empty() )
291  {
292  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
293  QgsDebugMsg( "closing active iterator" );
294  it->close();
295  }
296 }
297 
299 {
300  mActiveIterators.insert( it );
301 }
302 
304 {
305  mActiveIterators.remove( it );
306 }
307 
308 
309 
310 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
311  : mExpression( expression )
312  , mAscending( ascending )
313 {
314  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
315  mNullsFirst = !ascending;
316 }
317 
319  : mExpression( expression )
320  , mAscending( ascending )
321  , mNullsFirst( nullsfirst )
322 {
323 }
324 
326  : mExpression( expression )
327  , mAscending( ascending )
328 {
329  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
330  mNullsFirst = !ascending;
331 }
332 
333 QgsFeatureRequest::OrderByClause::OrderByClause( const QgsExpression &expression, bool ascending, bool nullsfirst )
334  : mExpression( expression )
335  , mAscending( ascending )
336  , mNullsFirst( nullsfirst )
337 {
338 
339 }
340 
342 {
343  return mAscending;
344 }
345 
347 {
348  mAscending = ascending;
349 }
350 
352 {
353  return mNullsFirst;
354 }
355 
357 {
358  mNullsFirst = nullsFirst;
359 }
360 
362 {
363  return QStringLiteral( "%1 %2 %3" )
364  .arg( mExpression.expression(),
365  mAscending ? "ASC" : "DESC",
366  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
367 }
368 
370 {
371  return mExpression;
372 }
373 
375 {
376  return mExpression.prepare( context );
377 }
378 
379 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
380 {
381  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, other )
382  {
383  append( clause );
384  }
385 }
386 
387 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
388 {
389  return *this;
390 }
391 
392 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
393 {
394  QDomDocument doc = elem.ownerDocument();
395  QList<OrderByClause>::ConstIterator it;
396  for ( it = constBegin(); it != constEnd(); ++it )
397  {
398  const OrderByClause &clause = *it;
399  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
400  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
401  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
402  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
403 
404  elem.appendChild( clauseElem );
405  }
406 }
407 
408 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
409 {
410  clear();
411 
412  QDomNodeList clauses = elem.childNodes();
413 
414  for ( int i = 0; i < clauses.size(); ++i )
415  {
416  QDomElement clauseElem = clauses.at( i ).toElement();
417  QString expression = clauseElem.text();
418  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
419  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
420 
421  append( OrderByClause( expression, asc, nullsFirst ) );
422  }
423 }
424 
426 {
427  QSet<QString> usedAttributes;
428 
429  QList<OrderByClause>::ConstIterator it;
430  for ( it = constBegin(); it != constEnd(); ++it )
431  {
432  const OrderByClause &clause = *it;
433 
434  usedAttributes.unite( clause.expression().referencedColumns() );
435  }
436 
437  return usedAttributes;
438 }
439 
441 {
442  QStringList results;
443 
444  QList<OrderByClause>::ConstIterator it;
445  for ( it = constBegin(); it != constEnd(); ++it )
446  {
447  const OrderByClause &clause = *it;
448 
449  results << clause.dump();
450  }
451 
452  return results.join( QStringLiteral( ", " ) );
453 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:299
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 intersects(const QgsRectangle &r) const
Tests for intersection with a rectangle (uses GEOS)
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:37
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.
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.
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)
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.
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.
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs for feature&#39;s geometries.
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
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
const QgsSimplifyMethod & simplifyMethod() const
Get simplification method for geometries that will be fetched.
CORE_EXPORT OrderBy()
Create a new empty order by.
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.