QGIS API Documentation  2.15.0-Master (1f0fce7)
qgsvectorlayerfeatureiterator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerfeatureiterator.cpp
3  ---------------------
4  begin : Dezember 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  ***************************************************************************/
16 
18 #include "qgsgeometrysimplifier.h"
19 #include "qgsmaplayerregistry.h"
20 #include "qgssimplifymethod.h"
21 #include "qgsvectordataprovider.h"
23 #include "qgsvectorlayer.h"
25 #include "qgsexpressioncontext.h"
26 #include "qgsdistancearea.h"
27 #include "qgsproject.h"
28 
30  : mCrsId( 0 )
31 {
32  QMutexLocker locker( &layer->mFeatureSourceConstructorMutex );
34  mFields = layer->fields();
35 
36  layer->createJoinCaches();
37  mJoinBuffer = layer->mJoinBuffer->clone();
38 
39  mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer );
40  mCrsId = layer->crs().srsid();
41 
42  mHasEditBuffer = layer->editBuffer();
43  if ( mHasEditBuffer )
44  {
45 #if 0
46  // TODO[MD]: after merge
47  if ( request.filterType() == QgsFeatureRequest::FilterFid )
48  {
49 
50  // only copy relevant parts
51  if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) )
52  mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] );
53 
54  if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) )
55  mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] );
56 
57  if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) )
58  mDeletedFeatureIds.insert( request.filterFid() );
59 
60  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
61  mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] );
62 
63  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
64  mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() );
65  }
66  else
67  {
68 #endif
75 #if 0
76  }
77 #endif
78  }
79 }
80 
82 {
83  delete mJoinBuffer;
86 }
87 
89 {
90  // return feature iterator that does not own this source
91  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, false, request ) );
92 }
93 
94 
97  , mFetchedFid( false )
98  , mInterruptionChecker( nullptr )
99 {
101  {
104 
106  {
107  //ensure that all fields required for filter expressions are prepared
108  Q_FOREACH ( const QString& field, mRequest.filterExpression()->referencedColumns() )
109  {
110  int attrIdx = mSource->mFields.fieldNameIndex( field );
111  if ( !mRequest.subsetOfAttributes().contains( attrIdx ) )
113  }
114  }
115  }
116 
117  prepareFields();
118 
120 
121  // by default provider's request is the same
123 
125  {
126  // prepare list of attributes to match provider fields
127  QSet<int> providerSubset;
129  int nPendingFields = mSource->mFields.count();
130  Q_FOREACH ( int attrIndex, subset )
131  {
132  if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
133  if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
134  providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
135  }
136 
137  // This is done in order to be prepared to do fallback order bys
138  // and be sure we have the required columns.
139  // TODO:
140  // It would be nicer to first check if we can compile the order by
141  // and only modify the subset if we cannot.
142  if ( !mProviderRequest.orderBy().isEmpty() )
143  {
144  Q_FOREACH ( const QString& attr, mProviderRequest.orderBy().usedAttributes() )
145  {
146  providerSubset << mSource->mFields.fieldNameIndex( attr );
147  }
148  }
149 
150  mProviderRequest.setSubsetOfAttributes( providerSubset.toList() );
151  }
152 
154  {
155  Q_FOREACH ( const QString& field, mProviderRequest.filterExpression()->referencedColumns() )
156  {
157  int idx = source->mFields.fieldNameIndex( field );
158 
159  // If there are fields in the expression which are not of origin provider, the provider will not be able to filter based on them.
160  // In this case we disable the expression filter.
161  if ( source->mFields.fieldOrigin( idx ) != QgsFields::OriginProvider )
162  {
164  }
165  }
166  }
167 
168  if ( mSource->mHasEditBuffer )
169  {
171  QgsFeatureIds changedIds;
172  QgsChangedAttributesMap::const_iterator attIt = mSource->mChangedAttributeValues.constBegin();
173  for ( ; attIt != mSource->mChangedAttributeValues.constEnd(); ++attIt )
174  {
175  changedIds << attIt.key();
176  }
178  }
179 
180  if ( request.filterType() == QgsFeatureRequest::FilterFid )
181  {
182  mFetchedFid = false;
183  }
184  else // no filter or filter by rect
185  {
186  if ( mSource->mHasEditBuffer )
187  {
189  }
190  else
191  {
193  }
194 
196  }
197 }
198 
199 
201 {
202  qDeleteAll( mExpressionFieldInfo );
203 
204  close();
205 }
206 
207 
208 
210 {
211  f.setValid( false );
212 
213  if ( mClosed )
214  return false;
215 
217  {
218  if ( mFetchedFid )
219  return false;
220  bool res = nextFeatureFid( f );
221  mFetchedFid = true;
222  return res;
223  }
224 
225  if ( !mRequest.filterRect().isNull() )
226  {
227  if ( fetchNextChangedGeomFeature( f ) )
228  return true;
229 
230  // no more changed geometries
231  }
232 
234  {
236  return true;
237 
238  // no more changed features
239  }
240 
241  while ( fetchNextAddedFeature( f ) )
242  {
243  return true;
244  }
245  // no more added features
246 
247  if ( mProviderIterator.isClosed() )
248  {
251  mProviderIterator.setInterruptionChecker( mInterruptionChecker );
252  }
253 
254  while ( mProviderIterator.nextFeature( f ) )
255  {
256  if ( mFetchConsidered.contains( f.id() ) )
257  continue;
258 
259  // TODO[MD]: just one resize of attributes
260  f.setFields( mSource->mFields );
261 
262  // update attributes
263  if ( mSource->mHasEditBuffer )
265 
266  if ( mHasVirtualAttributes )
268 
270  {
271  //filtering by expression, and couldn't do it on the provider side
274  {
275  //feature did not match filter
276  continue;
277  }
278  }
279 
280  // update geometry
281  // TODO[MK]: FilterRect check after updating the geometry
284 
285  return true;
286  }
287  // no more provider features
288 
289  close();
290  return false;
291 }
292 
293 
294 
296 {
297  if ( mClosed )
298  return false;
299 
301  {
302  mFetchedFid = false;
303  }
304  else
305  {
308  }
309 
310  return true;
311 }
312 
314 {
315  if ( mClosed )
316  return false;
317 
319 
320  iteratorClosed();
321 
322  mClosed = true;
323  return true;
324 }
325 
327 {
328  mProviderIterator.setInterruptionChecker( interruptionChecker );
329  mInterruptionChecker = interruptionChecker;
330 }
331 
333 {
335  {
337 
338  if ( mFetchConsidered.contains( fid ) )
339  // must have changed geometry outside rectangle
340  continue;
341 
343  // skip features which are not accepted by the filter
344  continue;
345 
347 
348  return true;
349  }
350 
352  return false; // no more added features
353 }
354 
355 
357 {
358  f.setFeatureId( src.id() );
359  f.setValid( true );
360  f.setFields( mSource->mFields );
361 
363  {
364  f.setGeometry( new QgsGeometry( *src.constGeometry() ) );
365  }
366 
367  // TODO[MD]: if subset set just some attributes
368 
369  f.setAttributes( src.attributes() );
370 
371  if ( mHasVirtualAttributes )
373 }
374 
375 
376 
378 {
379  // check if changed geometries are in rectangle
381  {
382  QgsFeatureId fid = mFetchChangedGeomIt.key();
383 
384  if ( mFetchConsidered.contains( fid ) )
385  // skip deleted features
386  continue;
387 
388  mFetchConsidered << fid;
389 
390  if ( !mFetchChangedGeomIt->intersects( mRequest.filterRect() ) )
391  // skip changed geometries not in rectangle and don't check again
392  continue;
393 
395 
396  // return complete feature
398  return true;
399  }
400 
401  return false; // no more changed geometries
402 }
403 
405 {
407  {
408  if ( mFetchConsidered.contains( f.id() ) )
409  // skip deleted features and those already handled by the geometry
410  continue;
411 
412  mFetchConsidered << f.id();
413 
415 
416  if ( mHasVirtualAttributes )
418 
421  {
422  return true;
423  }
424  }
425 
426  return false;
427 }
428 
429 
431 {
432  f.setFeatureId( fid );
433  f.setValid( true );
434  f.setFields( mSource->mFields );
435 
437  {
438  f.setGeometry( geom );
439  }
440 
441  bool subsetAttrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes );
442  if ( !subsetAttrs || !mRequest.subsetOfAttributes().isEmpty() )
443  {
444  // retrieve attributes from provider
445  QgsFeature tmp;
446  //mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
447  QgsFeatureRequest request;
449  if ( subsetAttrs )
450  {
452  }
454  if ( fi.nextFeature( tmp ) )
455  {
458  f.setAttributes( tmp.attributes() );
459  }
460  }
461 
463 }
464 
465 
466 
468 {
470 
473 }
474 
476 {
477  if ( !mSource->mFields.exists( fieldIdx ) )
478  return;
479 
480  if ( mSource->mFields.fieldOrigin( fieldIdx ) != QgsFields::OriginJoin )
481  return;
482 
483  int sourceLayerIndex;
484  const QgsVectorJoinInfo* joinInfo = mSource->mJoinBuffer->joinForFieldIndex( fieldIdx, mSource->mFields, sourceLayerIndex );
485  Q_ASSERT( joinInfo );
486 
487  QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
488  Q_ASSERT( joinLayer );
489 
490  if ( !mFetchJoinInfo.contains( joinInfo ) )
491  {
492  FetchJoinInfo info;
493  info.joinInfo = joinInfo;
494  info.joinLayer = joinLayer;
496 
497  if ( joinInfo->targetFieldName.isEmpty() )
498  info.targetField = joinInfo->targetFieldIndex; //for compatibility with 1.x
499  else
501 
502  if ( joinInfo->joinFieldName.isEmpty() )
503  info.joinField = joinInfo->joinFieldIndex; //for compatibility with 1.x
504  else
505  info.joinField = joinLayer->fields().indexFromName( joinInfo->joinFieldName );
506 
507  // for joined fields, we always need to request the targetField from the provider too
508  if ( !mPreparedFields.contains( info.targetField ) && !mFieldsToPrepare.contains( info.targetField ) )
509  mFieldsToPrepare << info.targetField;
510 
513 
514  mFetchJoinInfo.insert( joinInfo, info );
515  }
516 
517  // store field source index - we'll need it when fetching from provider
518  mFetchJoinInfo[ joinInfo ].attributes.push_back( sourceLayerIndex );
519 }
520 
522 {
524 
525  int oi = mSource->mFields.fieldOriginIndex( fieldIdx );
526  QgsExpression* exp = new QgsExpression( exps[oi].cachedExpression );
527 
528  QgsDistanceArea da;
529  da.setSourceCrs( mSource->mCrsId );
530  da.setEllipsoidalMode( true );
531  da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
532  exp->setGeomCalculator( da );
533  exp->setDistanceUnits( QgsProject::instance()->distanceUnits() );
534  exp->setAreaUnits( QgsProject::instance()->areaUnits() );
535 
536  exp->prepare( mExpressionContext.data() );
537  mExpressionFieldInfo.insert( fieldIdx, exp );
538 
539  Q_FOREACH ( const QString& col, exp->referencedColumns() )
540  {
541  int dependantFieldIdx = mSource->mFields.fieldNameIndex( col );
543  {
544  mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() << dependantFieldIdx );
545  }
546  // also need to fetch this dependant field
547  if ( !mPreparedFields.contains( dependantFieldIdx ) && !mFieldsToPrepare.contains( dependantFieldIdx ) )
548  mFieldsToPrepare << dependantFieldIdx;
549  }
550 
551  if ( exp->needsGeometry() )
552  {
553  mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry );
554  }
555 }
556 
558 {
559  mPreparedFields.clear();
560  mFieldsToPrepare.clear();
561  mFetchJoinInfo.clear();
562 
563  mExpressionContext.reset( new QgsExpressionContext() );
564  mExpressionContext->appendScope( QgsExpressionContextUtils::globalScope() );
565  mExpressionContext->appendScope( QgsExpressionContextUtils::projectScope() );
566  mExpressionContext->setFields( mSource->mFields );
567 
569 
570  while ( !mFieldsToPrepare.isEmpty() )
571  {
572  int fieldIdx = mFieldsToPrepare.takeFirst();
573  if ( mPreparedFields.contains( fieldIdx ) )
574  continue;
575 
576  mPreparedFields << fieldIdx;
577  prepareField( fieldIdx );
578  }
579 }
580 
582 {
583  switch ( mSource->mFields.fieldOrigin( fieldIdx ) )
584  {
586  prepareExpression( fieldIdx );
587  break;
588 
591  {
592  prepareJoin( fieldIdx );
593  }
594  break;
595 
599  break;
600  }
601 }
602 
604 {
606  for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
607  {
608  const FetchJoinInfo& info = joinIt.value();
609  Q_ASSERT( joinIt.key() );
610 
611  QVariant targetFieldValue = f.attribute( info.targetField );
612  if ( !targetFieldValue.isValid() )
613  continue;
614 
615  const QHash< QString, QgsAttributes>& memoryCache = info.joinInfo->cachedAttributes;
616  if ( memoryCache.isEmpty() )
617  info.addJoinedAttributesDirect( f, targetFieldValue );
618  else
619  info.addJoinedAttributesCached( f, targetFieldValue );
620  }
621 }
622 
624 {
625  // make sure we have space for newly added attributes
626  QgsAttributes attr = f.attributes();
627  attr.resize( mSource->mFields.count() ); // Provider attrs count + joined attrs count + expression attrs count
628  f.setAttributes( attr );
629 
630  // possible TODO - handle combinations of expression -> join -> expression -> join?
631  // but for now, write that off as too complex and an unlikely rare, unsupported use case
632 
633  QList< int > fetchedVirtualAttributes;
634  //first, check through joins for any virtual fields we need
636  for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
637  {
638  if ( mExpressionFieldInfo.contains( joinIt->targetField ) )
639  {
640  // have to calculate expression field before we can handle this join
641  addExpressionAttribute( f, joinIt->targetField );
642  fetchedVirtualAttributes << joinIt->targetField;
643  }
644  }
645 
646  if ( !mFetchJoinInfo.isEmpty() )
647  addJoinedAttributes( f );
648 
649  // add remaining expression fields
650  if ( !mExpressionFieldInfo.isEmpty() )
651  {
653  for ( ; it != mExpressionFieldInfo.constEnd(); ++it )
654  {
655  if ( fetchedVirtualAttributes.contains( it.key() ) )
656  continue;
657 
658  addExpressionAttribute( f, it.key() );
659  }
660  }
661 }
662 
664 {
665  QgsExpression* exp = mExpressionFieldInfo.value( attrIndex );
666  mExpressionContext->setFeature( f );
667  QVariant val = exp->evaluate( mExpressionContext.data() );
668  mSource->mFields.at( attrIndex ).convertCompatible( val );
669  f.setAttribute( attrIndex, val );
670 }
671 
673 {
674  Q_UNUSED( simplifyMethod );
675  return false;
676 }
677 
678 bool QgsVectorLayerFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
679 {
680  Q_UNUSED( methodType );
681  return false;
682 }
683 
684 
686 {
687  const QHash<QString, QgsAttributes>& memoryCache = joinInfo->cachedAttributes;
688  QHash<QString, QgsAttributes>::const_iterator it = memoryCache.find( joinValue.toString() );
689  if ( it == memoryCache.constEnd() )
690  return; // joined value not found -> leaving the attributes empty (null)
691 
692  int index = indexOffset;
693 
694  const QgsAttributes& featureAttributes = it.value();
695  for ( int i = 0; i < featureAttributes.count(); ++i )
696  {
697  f.setAttribute( index++, featureAttributes.at( i ) );
698  }
699 }
700 
701 
702 
704 {
705  // no memory cache, query the joined values by setting substring
706  QString subsetString;
707 
708  QString joinFieldName;
709  if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->fields().count() )
710  joinFieldName = joinLayer->fields().field( joinInfo->joinFieldIndex ).name(); // for compatibility with 1.x
711  else
712  joinFieldName = joinInfo->joinFieldName;
713 
714  subsetString.append( QString( "\"%1\"" ).arg( joinFieldName ) );
715 
716  if ( joinValue.isNull() )
717  {
718  subsetString += " IS NULL";
719  }
720  else
721  {
722  QString v = joinValue.toString();
723  switch ( joinValue.type() )
724  {
725  case QVariant::Int:
726  case QVariant::LongLong:
727  case QVariant::Double:
728  break;
729 
730  default:
731  case QVariant::String:
732  v.replace( '\'', "''" );
733  v.prepend( '\'' ).append( '\'' );
734  break;
735  }
736  subsetString += '=' + v;
737  }
738 
739  // maybe user requested just a subset of layer's attributes
740  // so we do not have to cache everything
741  bool hasSubset = joinInfo->joinFieldNamesSubset();
742  QVector<int> subsetIndices;
743  if ( hasSubset )
744  subsetIndices = QgsVectorLayerJoinBuffer::joinSubsetIndices( joinLayer, *joinInfo->joinFieldNamesSubset() );
745 
746  // select (no geometry)
747  QgsFeatureRequest request;
749  request.setSubsetOfAttributes( attributes );
750  request.setFilterExpression( subsetString );
751  request.setLimit( 1 );
752  QgsFeatureIterator fi = joinLayer->getFeatures( request );
753 
754  // get first feature
755  QgsFeature fet;
756  if ( fi.nextFeature( fet ) )
757  {
758  int index = indexOffset;
759  QgsAttributes attr = fet.attributes();
760  if ( hasSubset )
761  {
762  for ( int i = 0; i < subsetIndices.count(); ++i )
763  f.setAttribute( index++, attr.at( subsetIndices.at( i ) ) );
764  }
765  else
766  {
767  // use all fields except for the one used for join (has same value as exiting field in target layer)
768  for ( int i = 0; i < attr.count(); ++i )
769  {
770  if ( i == joinField )
771  continue;
772 
773  f.setAttribute( index++, attr.at( i ) );
774  }
775  }
776  }
777  else
778  {
779  // no suitable join feature found, keeping empty (null) attributes
780  }
781 }
782 
783 
784 
785 
787 {
788  QgsFeatureId featureId = mRequest.filterFid();
789 
790  // deleted already?
791  if ( mSource->mDeletedFeatureIds.contains( featureId ) )
792  return false;
793 
794  // has changed geometry?
796  {
797  useChangedAttributeFeature( featureId, mSource->mChangedGeometries[featureId], f );
798  return true;
799  }
800 
801  // added features
803  {
804  if ( iter->id() == featureId )
805  {
806  useAddedFeature( *iter, f );
807  return true;
808  }
809  }
810 
811  // regular features
813  if ( fi.nextFeature( f ) )
814  {
815  f.setFields( mSource->mFields );
816 
817  if ( mSource->mHasEditBuffer )
819 
820  if ( mHasVirtualAttributes )
822 
823  return true;
824  }
825 
826  return false;
827 }
828 
830 {
831  QgsAttributes attrs = f.attributes();
832 
833  // remove all attributes that will disappear - from higher indices to lower
834  for ( int idx = mSource->mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
835  {
836  attrs.remove( mSource->mDeletedAttributeIds[idx] );
837  }
838 
839  // adjust size to accommodate added attributes
840  attrs.resize( attrs.count() + mSource->mAddedAttributes.count() );
841 
842  // update changed attributes
844  {
846  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
847  attrs[it.key()] = it.value();
848  }
849  f.setAttributes( attrs );
850 }
851 
853 {
854  if ( mSource->mChangedGeometries.contains( f.id() ) )
856 }
857 
858 bool QgsVectorLayerFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
859 {
860  Q_UNUSED( orderBys );
861  return true;
862 }
863 
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), eg "$area".
const QgsGeometryMap & changedGeometries()
Changed geometries which are not commited.
QgsAbstractFeatureSource * mProviderFeatureSource
Class for parsing and evaluation of expressions (formerly called "search strings").
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
void addJoinedAttributesDirect(QgsFeature &f, const QVariant &joinValue) const
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:437
static unsigned index
bool acceptFeature(const QgsFeature &feature)
Check if a feature is accepted by this requests filter.
QString & append(QChar ch)
Filter using feature ID.
QgsVectorLayerJoinBuffer * mJoinBuffer
const Flags & flags() const
QString joinFieldName
Join field in the source layer.
field comes from a joined layer (originIndex / 1000 = index of the join, originIndex % 1000 = index w...
Definition: qgsfield.h:201
virtual void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker) override
Attach an object that can be queried regularly by the iterator to check if it must stopped...
QStringList referencedColumns() const
Get list of columns referenced by the expression.
QString targetFieldName
Join field in the target layer.
bool contains(const Key &key) const
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
QgsFeatureId filterFid() const
Get the feature ID that should be fetched.
void addExpressionAttribute(QgsFeature &f, int attrIndex)
Adds an expression based attribute to a feature.
QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt
QgsGeometryMap::ConstIterator mFetchChangedGeomIt
const QgsRectangle & filterRect() const
Get the rectangle from which features will be taken.
Q_DECL_DEPRECATED bool prepare(const QgsFields &fields)
Get the expression ready for evaluation - find out column indexes.
field has been temporarily added in editing mode (originIndex = index in the list of added attributes...
Definition: qgsfield.h:202
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:439
QgsFields fields() const
Returns the list of fields of this layer.
long srsid() const
Returns the SrsId, if available.
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:534
QString & prepend(QChar ch)
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
QgsVectorLayerFeatureIterator(QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request)
QgsExpressionContext * expressionContext()
Returns the expression context used to evaluate filter expressions.
int joinFieldIndex
Join field index in the source layer.
const_iterator constBegin() const
QgsAttributeList subsetOfAttributes() const
Return the subset of attributes which at least need to be fetched.
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:115
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:222
QMap< int, QgsExpression * > mExpressionFieldInfo
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:200
bool setEllipsoid(const QString &ellipsoid)
Sets ellipsoid by its acronym.
bool mClosed
Set to true, as soon as the iterator is closed.
int targetFieldIndex
Join field index in the target layer.
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
QgsVectorLayer * joinLayer
resolved pointer to the joined layer
bool isClosed() const
find out whether the iterator is still valid or closed already
it has not been specified where the field comes from
Definition: qgsfield.h:199
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:76
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
QMap< const QgsVectorJoinInfo *, FetchJoinInfo > mFetchJoinInfo
Information about joins used in the current select() statement.
void reset(T *other)
T value(int i) const
const QgsVectorJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
int joinedFieldsOffset(const QgsVectorJoinInfo *info, const QgsFields &fields)
Find out what is the first index of the join within fields.
QgsVectorLayerJoinBuffer * clone() const
Create a copy of the join buffer.
int joinField
index of field (of the joined layer) must have equal value
virtual QgsAbstractFeatureSource * featureSource() const =0
Return feature source object that can be used for querying provider&#39;s data.
Interface that can be optionaly attached to an iterator so its nextFeature() implementaton can check ...
bool containsJoins() const
Quick way to test if there is any join at all.
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommited attribute updates.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:375
void setGeometry(const QgsGeometry &geom)
Set this feature&#39;s geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:124
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
int count(const T &value) const
void iteratorClosed()
to be called by from subclass in close()
void useAddedFeature(const QgsFeature &src, QgsFeature &f)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
void resize(int size)
const_iterator constEnd() const
void setFeatureId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:101
bool isNull() const
const Key & key() const
const QgsVectorJoinInfo * joinInfo
cannonical source of information about the join
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
QgsFeatureRequest & disableFilter()
Disables filter conditions.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
void updateFeatureGeometry(QgsFeature &f)
Update feature with uncommited geometry updates.
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual bool prepareSimplification(const QgsSimplifyMethod &simplifyMethod) override
Setup the simplification of geometries to fetch using the specified simplify method.
bool isEmpty() const
const_iterator constEnd() const
void remove(int i)
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:419
virtual bool fetchFeature(QgsFeature &feature) override
fetch next feature, return true on success
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
const QgsFeatureIds deletedFeatureIds()
QSet< QString > CORE_EXPORT usedAttributes() const
Returns a set of used attributes.
const T & value() const
int count() const
Return number of items.
Definition: qgsfield.cpp:365
FilterType filterType() const
Return the filter type which is currently set on this request.
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
iterator end()
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
QgsExpressionFieldBuffer * mExpressionFieldBuffer
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:385
iterator begin()
Q_DECL_DEPRECATED void setFields(const QgsFields *fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:173
const QList< QgsField > & addedAttributes()
Added attributes fields which are not commited.
void setFields(const QgsFields &fields)
Convenience function for setting a fields for the context.
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:424
T * data() const
const T value(const Key &key) const
iterator find(const Key &key)
Partial snapshot of vector layer&#39;s state (only the members necessary for access to features) ...
bool contains(const T &value) const
QgsVectorLayerFeatureSource(QgsVectorLayer *layer)
bool contains(const T &value) const
int indexOffset
at what position the joined fields start
void useChangedAttributeFeature(QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f)
const QgsFeatureMap & addedFeatures()
New features which are not commited.
const Key key(const T &value) const
General purpose distance and area calculator.
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:204
QMap< QgsFeatureId, QgsFeature > QgsFeatureMap
QString & replace(int position, int n, QChar after)
QgsFeatureRequest mRequest
A copy of the feature request.
const T & at(int i) const
int targetField
index of field (of this layer) that drives the join
Buffers information about expression fields for a vector layer.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
QHash< QString, QgsAttributes > cachedAttributes
Cache for joined attributes to provide fast lookup (size is 0 if no memory caching) ...
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Set feature IDs that should be fetched.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request) override
Get an iterator for features matching the specified request.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:434
T takeFirst()
bool isEmpty() const
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:175
virtual bool rewind() override
reset the iterator to the starting position
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
virtual bool close() override
end of iterating: free the resources / lock
static QVector< int > joinSubsetIndices(QgsVectorLayer *joinLayer, const QStringList &joinFieldsSubset)
Return a vector of indices for use in join based on field names from the layer.
int count(const T &value) const
void setDistanceUnits(QGis::UnitType unit)
Sets the desired distance units for calculations involving geomCalculator(), eg "$length" and "$perim...
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:411
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
Join information prepared for fast attribute id mapping in QgsVectorLayerJoinBuffer::updateFeatureAtt...
qint64 QgsFeatureId
Definition: qgsfeature.h:31
void setGeomCalculator(const QgsDistanceArea &calc)
Sets the geometry calculator used for distance and area calculations in expressions.
QList< T > toList() const
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
iterator insert(const Key &key, const T &value)
void addJoinedAttributesCached(QgsFeature &f, const QVariant &joinValue) const
bool isEmpty() const
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request)=0
Get an iterator for features matching the specified request.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
Type type() const
QgsChangedAttributesMap mChangedAttributeValues
Geometry is not required. It may still be returned if e.g. required for a filter condition.
A vector of attributes.
Definition: qgsfeature.h:115
const QList< ExpressionField > & expressions() const
Represents a vector layer which manages a vector based data sets.
const QgsAttributeList & deletedAttributeIds()
Deleted attributes fields which are not commited.
field is calculated from an expression
Definition: qgsfield.h:203
QString toString() const
QString joinLayerId
Source layer.
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:551
void createJoinCaches()
Caches joined attributes if required (and not already done)
void setInterruptionChecker(QgsInterruptionChecker *interruptionChecker)
Attach an object that can be queried regularly by the iterator to check if it must stopped...
void setEllipsoidalMode(bool flag)
Sets whether coordinates must be projected to ellipsoid before measuring.
void addVirtualAttributes(QgsFeature &f)
Adds attributes that don&#39;t source from the provider but are added inside QGIS Includes.
Helper template that cares of two things: 1.
const T value(const Key &key) const
QgsExpression * filterExpression() const
Returns the filter expression if set.