QGIS API Documentation  2.99.0-Master (716ff6c)
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 
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  {
74  }
75  else
76  {
77  mFilterExpression.reset( nullptr );
78  }
80  mAttrs = rh.mAttrs;
82  mLimit = rh.mLimit;
83  mOrderBy = rh.mOrderBy;
84  return *this;
85 }
86 
88 {
89  mFilterRect = rect;
90  return *this;
91 }
92 
94 {
96  mFilterFid = fid;
97  return *this;
98 }
99 
101 {
103  mFilterFids = fids;
104  return *this;
105 }
106 
108 {
110  mFilterExpression.reset( new QgsExpression( expression ) );
111  return *this;
112 }
113 
115 {
116  if ( mFilterExpression )
117  {
118  setFilterExpression( QStringLiteral( "(%1) AND (%2)" ).arg( mFilterExpression->expression(), expression ) );
119  }
120  else
121  {
122  setFilterExpression( expression );
123  }
124  return *this;
125 }
126 
128 {
129  mExpressionContext = context;
130  return *this;
131 }
132 
133 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending )
134 {
135  mOrderBy.append( OrderByClause( expression, ascending ) );
136  return *this;
137 }
138 
139 QgsFeatureRequest &QgsFeatureRequest::addOrderBy( const QString &expression, bool ascending, bool nullsfirst )
140 {
141  mOrderBy.append( OrderByClause( expression, ascending, nullsfirst ) );
142  return *this;
143 }
144 
146 {
147  return mOrderBy;
148 }
149 
151 {
152  mOrderBy = orderBy;
153  return *this;
154 }
155 
157 {
158  mLimit = limit;
159  return *this;
160 }
161 
163 {
164  mFlags = flags;
165  return *this;
166 }
167 
169 {
171  mAttrs = attrs;
172  return *this;
173 }
174 
175 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QStringList &attrNames, const QgsFields &fields )
176 {
177  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
178  {
179  //attribute string list contains the all attributes flag, so we must fetch all attributes
180  return *this;
181  }
182 
184  mAttrs.clear();
185 
186  Q_FOREACH ( const QString &attrName, attrNames )
187  {
188  int attrNum = fields.lookupField( attrName );
189  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
190  mAttrs.append( attrNum );
191  }
192 
193  return *this;
194 }
195 
196 QgsFeatureRequest &QgsFeatureRequest::setSubsetOfAttributes( const QSet<QString> &attrNames, const QgsFields &fields )
197 {
198  if ( attrNames.contains( QgsFeatureRequest::ALL_ATTRIBUTES ) )
199  {
200  //attribute string list contains the all attributes flag, so we must fetch all attributes
201  return *this;
202  }
203 
205  mAttrs.clear();
206 
207  Q_FOREACH ( const QString &attrName, attrNames )
208  {
209  int attrNum = fields.lookupField( attrName );
210  if ( attrNum != -1 && !mAttrs.contains( attrNum ) )
211  mAttrs.append( attrNum );
212  }
213 
214  return *this;
215 }
216 
218 {
220  return *this;
221 }
222 
224 {
225  if ( !mFilterRect.isNull() )
226  {
227  if ( !feature.hasGeometry() || !feature.geometry().intersects( mFilterRect ) )
228  return false;
229  }
230 
231  switch ( mFilter )
232  {
234  return true;
235 
237  return ( feature.id() == mFilterFid );
238 
240  mExpressionContext.setFeature( feature );
241  return ( mFilterExpression->evaluate( &mExpressionContext ).toBool() );
242 
244  return ( mFilterFids.contains( feature.id() ) );
245  }
246 
247  return true;
248 }
249 
250 
251 #include "qgsfeatureiterator.h"
252 #include "qgslogger.h"
253 
255 {
256  while ( !mActiveIterators.empty() )
257  {
258  QgsAbstractFeatureIterator *it = *mActiveIterators.begin();
259  QgsDebugMsg( "closing active iterator" );
260  it->close();
261  }
262 }
263 
265 {
266  mActiveIterators.insert( it );
267 }
268 
270 {
271  mActiveIterators.remove( it );
272 }
273 
274 
275 
276 QgsFeatureRequest::OrderByClause::OrderByClause( const QString &expression, bool ascending )
277  : mExpression( expression )
278  , mAscending( ascending )
279 {
280  // postgres behavior: default for ASC: NULLS LAST, default for DESC: NULLS FIRST
281  mNullsFirst = !ascending;
282 }
283 
285  : mExpression( expression )
286  , mAscending( ascending )
287  , mNullsFirst( nullsfirst )
288 {
289 }
290 
292 {
293  return mAscending;
294 }
295 
297 {
298  mAscending = ascending;
299 }
300 
302 {
303  return mNullsFirst;
304 }
305 
307 {
308  mNullsFirst = nullsFirst;
309 }
310 
312 {
313  return QStringLiteral( "%1 %2 %3" )
314  .arg( mExpression.expression(),
315  mAscending ? "ASC" : "DESC",
316  mNullsFirst ? "NULLS FIRST" : "NULLS LAST" );
317 }
318 
320 {
321  return mExpression;
322 }
323 
324 QgsFeatureRequest::OrderBy::OrderBy( const QList<QgsFeatureRequest::OrderByClause> &other )
325 {
326  Q_FOREACH ( const QgsFeatureRequest::OrderByClause &clause, other )
327  {
328  append( clause );
329  }
330 }
331 
332 QList<QgsFeatureRequest::OrderByClause> QgsFeatureRequest::OrderBy::list() const
333 {
334  return *this;
335 }
336 
337 void QgsFeatureRequest::OrderBy::save( QDomElement &elem ) const
338 {
339  QDomDocument doc = elem.ownerDocument();
340  QList<OrderByClause>::ConstIterator it;
341  for ( it = constBegin(); it != constEnd(); ++it )
342  {
343  const OrderByClause &clause = *it;
344  QDomElement clauseElem = doc.createElement( QStringLiteral( "orderByClause" ) );
345  clauseElem.setAttribute( QStringLiteral( "asc" ), clause.ascending() );
346  clauseElem.setAttribute( QStringLiteral( "nullsFirst" ), clause.nullsFirst() );
347  clauseElem.appendChild( doc.createTextNode( clause.expression().expression() ) );
348 
349  elem.appendChild( clauseElem );
350  }
351 }
352 
353 void QgsFeatureRequest::OrderBy::load( const QDomElement &elem )
354 {
355  clear();
356 
357  QDomNodeList clauses = elem.childNodes();
358 
359  for ( int i = 0; i < clauses.size(); ++i )
360  {
361  QDomElement clauseElem = clauses.at( i ).toElement();
362  QString expression = clauseElem.text();
363  bool asc = clauseElem.attribute( QStringLiteral( "asc" ) ).toInt() != 0;
364  bool nullsFirst = clauseElem.attribute( QStringLiteral( "nullsFirst" ) ).toInt() != 0;
365 
366  append( OrderByClause( expression, asc, nullsFirst ) );
367  }
368 }
369 
371 {
372  QSet<QString> usedAttributes;
373 
374  QList<OrderByClause>::ConstIterator it;
375  for ( it = constBegin(); it != constEnd(); ++it )
376  {
377  const OrderByClause &clause = *it;
378 
379  usedAttributes.unite( clause.expression().referencedColumns() );
380  }
381 
382  return usedAttributes;
383 }
384 
386 {
387  QStringList results;
388 
389  QList<OrderByClause>::ConstIterator it;
390  for ( it = constBegin(); it != constEnd(); ++it )
391  {
392  const OrderByClause &clause = *it;
393 
394  results << clause.dump();
395  }
396 
397  return results.join( QStringLiteral( ", " ) );
398 }
int lookupField(const QString &fieldName) const
Look up field&#39;s index from the field name.
Definition: qgsfields.cpp:289
Class for parsing and evaluation of expressions (formerly called "search strings").
QgsFeatureId id
Definition: qgsfeature.h:70
QgsFeatureIds mFilterFids
virtual bool close()=0
end of iterating: free the resources / lock
A rectangle specified with double values.
Definition: qgsrectangle.h:38
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
bool intersects(const QgsRectangle &r) const
Test 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)
QList< 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:36
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:517
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Container of fields for a vector layer.
Definition: qgsfields.h:39
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.
QSet< QString > referencedColumns() const
Get list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:61
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
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
QList< int > QgsAttributeList
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
QString expression() const
Return the original, unmodified expression string.
QgsFeatureRequest & setSimplifyMethod(const QgsSimplifyMethod &simplifyMethod)
Set a simplification method for geometries that will be fetched.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
QgsFeatureId mFilterFid
QgsExpression expression() const
The expression.
No filter is applied.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
void setAscending(bool ascending)
Set if ascending order is requested.
QgsAttributeList mAttrs
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.
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.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rect)
Set rectangle from which features will be taken.
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.