QGIS API Documentation  2.14.11-Essen
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 {
33  mFields = layer->fields();
34  mJoinBuffer = layer->mJoinBuffer->clone();
35  mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer );
36  mCrsId = layer->crs().srsid();
37 
38  mCanBeSimplified = layer->hasGeometryType() && layer->geometryType() != QGis::Point;
39 
40  mHasEditBuffer = layer->editBuffer();
41  if ( mHasEditBuffer )
42  {
43 #if 0
44  // TODO[MD]: after merge
45  if ( request.filterType() == QgsFeatureRequest::FilterFid )
46  {
47 
48  // only copy relevant parts
49  if ( L->editBuffer()->addedFeatures().contains( request.filterFid() ) )
50  mAddedFeatures.insert( request.filterFid(), L->editBuffer()->addedFeatures()[ request.filterFid()] );
51 
52  if ( L->editBuffer()->changedGeometries().contains( request.filterFid() ) )
53  mChangedGeometries.insert( request.filterFid(), L->editBuffer()->changedGeometries()[ request.filterFid()] );
54 
55  if ( L->editBuffer()->deletedFeatureIds().contains( request.filterFid() ) )
56  mDeletedFeatureIds.insert( request.filterFid() );
57 
58  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
59  mChangedAttributeValues.insert( request.filterFid(), L->editBuffer()->changedAttributeValues()[ request.filterFid()] );
60 
61  if ( L->editBuffer()->changedAttributeValues().contains( request.filterFid() ) )
62  mChangedFeaturesRequest.setFilterFids( QgsFeatureIds() << request.filterFid() );
63  }
64  else
65  {
66 #endif
73 #if 0
74  }
75 #endif
76  }
77 }
78 
80 {
81  delete mJoinBuffer;
84 }
85 
87 {
88  // return feature iterator that does not own this source
89  return QgsFeatureIterator( new QgsVectorLayerFeatureIterator( this, false, request ) );
90 }
91 
92 
95  , mFetchedFid( false )
96  , mEditGeometrySimplifier( nullptr )
97 {
98  prepareFields();
99 
101 
102  // by default provider's request is the same
104 
106  {
107  // prepare list of attributes to match provider fields
108  QSet<int> providerSubset;
110  int nPendingFields = mSource->mFields.count();
111  Q_FOREACH ( int attrIndex, subset )
112  {
113  if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
114  if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
115  providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
116  }
117 
118  // This is done in order to be prepared to do fallback order bys
119  // and be sure we have the required columns.
120  // TODO:
121  // It would be nicer to first check if we can compile the order by
122  // and only modify the subset if we cannot.
123  if ( !mProviderRequest.orderBy().isEmpty() )
124  {
125  Q_FOREACH ( const QString& attr, mProviderRequest.orderBy().usedAttributes() )
126  {
127  providerSubset << mSource->mFields.fieldNameIndex( attr );
128  }
129  }
130 
131  mProviderRequest.setSubsetOfAttributes( providerSubset.toList() );
132  }
133 
135  {
136  Q_FOREACH ( const QString& field, mProviderRequest.filterExpression()->referencedColumns() )
137  {
138  int idx = source->mFields.fieldNameIndex( field );
139 
140  // If there are fields in the expression which are not of origin provider, the provider will not be able to filter based on them.
141  // In this case we disable the expression filter.
142  if ( source->mFields.fieldOrigin( idx ) != QgsFields::OriginProvider )
143  {
145  }
146  }
147  }
148 
149  if ( mSource->mHasEditBuffer )
150  {
153  }
154 
155  if ( request.filterType() == QgsFeatureRequest::FilterFid )
156  {
157  mFetchedFid = false;
158  }
159  else // no filter or filter by rect
160  {
161  if ( mSource->mHasEditBuffer )
162  {
164  }
165  else
166  {
168  }
169 
171  }
172 
174  {
177  }
178 }
179 
180 
182 {
183  delete mEditGeometrySimplifier;
184  mEditGeometrySimplifier = nullptr;
185 
186  qDeleteAll( mExpressionFieldInfo );
187 
188  close();
189 }
190 
191 
192 
194 {
195  f.setValid( false );
196 
197  if ( mClosed )
198  return false;
199 
201  {
202  if ( mFetchedFid )
203  return false;
204  bool res = nextFeatureFid( f );
205  mFetchedFid = true;
206  return res;
207  }
208 
209  if ( !mRequest.filterRect().isNull() )
210  {
211  if ( fetchNextChangedGeomFeature( f ) )
212  return true;
213 
214  // no more changed geometries
215  }
216 
218  {
220  return true;
221 
222  // no more changed features
223  }
224 
225  while ( fetchNextAddedFeature( f ) )
226  {
227  return true;
228  }
229  // no more added features
230 
231  if ( mProviderIterator.isClosed() )
232  {
235  }
236 
237  while ( mProviderIterator.nextFeature( f ) )
238  {
239  if ( mFetchConsidered.contains( f.id() ) )
240  continue;
241 
242  // TODO[MD]: just one resize of attributes
243  f.setFields( mSource->mFields );
244 
245  // update attributes
246  if ( mSource->mHasEditBuffer )
248 
249  if ( mHasVirtualAttributes )
251 
253  {
254  //filtering by expression, and couldn't do it on the provider side
257  {
258  //feature did not match filter
259  continue;
260  }
261  }
262 
263  // update geometry
264  // TODO[MK]: FilterRect check after updating the geometry
267 
268  return true;
269  }
270  // no more provider features
271 
272  close();
273  return false;
274 }
275 
276 
277 
279 {
280  if ( mClosed )
281  return false;
282 
284  {
285  mFetchedFid = false;
286  }
287  else
288  {
291  }
292 
293  return true;
294 }
295 
297 {
298  if ( mClosed )
299  return false;
300 
302 
303  iteratorClosed();
304 
305  mClosed = true;
306  return true;
307 }
308 
309 
310 
311 
313 {
315  {
317 
318  if ( mFetchConsidered.contains( fid ) )
319  // must have changed geometry outside rectangle
320  continue;
321 
323  // skip features which are not accepted by the filter
324  continue;
325 
327 
328  return true;
329  }
330 
332  return false; // no more added features
333 }
334 
335 
337 {
338  f.setFeatureId( src.id() );
339  f.setValid( true );
340  f.setFields( mSource->mFields );
341 
343  {
344  f.setGeometry( new QgsGeometry( *src.constGeometry() ) );
345 
346  // simplify the edited geometry using its simplifier configured
347  if ( mEditGeometrySimplifier )
348  {
349  QgsGeometry* geometry = f.geometry();
350  QGis::GeometryType geometryType = geometry->type();
351  if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mEditGeometrySimplifier->simplifyGeometry( geometry );
352  }
353  }
354 
355  // TODO[MD]: if subset set just some attributes
356 
357  f.setAttributes( src.attributes() );
358 
359  if ( mHasVirtualAttributes )
361 }
362 
363 
364 
366 {
367  // check if changed geometries are in rectangle
369  {
370  QgsFeatureId fid = mFetchChangedGeomIt.key();
371 
372  if ( mFetchConsidered.contains( fid ) )
373  // skip deleted features
374  continue;
375 
376  mFetchConsidered << fid;
377 
378  if ( !mFetchChangedGeomIt->intersects( mRequest.filterRect() ) )
379  // skip changed geometries not in rectangle and don't check again
380  continue;
381 
383 
384  // return complete feature
386  return true;
387  }
388 
389  return false; // no more changed geometries
390 }
391 
393 {
395  {
396  if ( mFetchConsidered.contains( f.id() ) )
397  // skip deleted features and those already handled by the geometry
398  continue;
399 
400  mFetchConsidered << f.id();
401 
403 
404  if ( mHasVirtualAttributes )
406 
409  {
410  return true;
411  }
412  }
413 
414  return false;
415 }
416 
417 
419 {
420  f.setFeatureId( fid );
421  f.setValid( true );
422  f.setFields( mSource->mFields );
423 
425  {
426  f.setGeometry( geom );
427 
428  // simplify the edited geometry using its simplifier configured
429  if ( mEditGeometrySimplifier )
430  {
431  QgsGeometry* geometry = f.geometry();
432  QGis::GeometryType geometryType = geometry->type();
433  if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mEditGeometrySimplifier->simplifyGeometry( geometry );
434  }
435  }
436 
437  bool subsetAttrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes );
438  if ( !subsetAttrs || !mRequest.subsetOfAttributes().isEmpty() )
439  {
440  // retrieve attributes from provider
441  QgsFeature tmp;
442  //mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
443  QgsFeatureRequest request;
445  if ( subsetAttrs )
446  {
448  }
450  if ( fi.nextFeature( tmp ) )
451  {
454  f.setAttributes( tmp.attributes() );
455  }
456  }
457 
459 }
460 
461 
462 
464 {
466 
469 }
470 
472 {
473  if ( !mSource->mFields.exists( fieldIdx ) )
474  return;
475 
476  if ( mSource->mFields.fieldOrigin( fieldIdx ) != QgsFields::OriginJoin )
477  return;
478 
479  int sourceLayerIndex;
480  const QgsVectorJoinInfo* joinInfo = mSource->mJoinBuffer->joinForFieldIndex( fieldIdx, mSource->mFields, sourceLayerIndex );
481  Q_ASSERT( joinInfo );
482 
483  QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
484  Q_ASSERT( joinLayer );
485 
486  if ( !mFetchJoinInfo.contains( joinInfo ) )
487  {
488  FetchJoinInfo info;
489  info.joinInfo = joinInfo;
490  info.joinLayer = joinLayer;
492 
493  if ( joinInfo->targetFieldName.isEmpty() )
494  info.targetField = joinInfo->targetFieldIndex; //for compatibility with 1.x
495  else
497 
498  if ( joinInfo->joinFieldName.isEmpty() )
499  info.joinField = joinInfo->joinFieldIndex; //for compatibility with 1.x
500  else
501  info.joinField = joinLayer->fields().indexFromName( joinInfo->joinFieldName );
502 
503  // for joined fields, we always need to request the targetField from the provider too
504  if ( !mPreparedFields.contains( info.targetField ) && !mFieldsToPrepare.contains( info.targetField ) )
505  mFieldsToPrepare << info.targetField;
506 
509 
510  mFetchJoinInfo.insert( joinInfo, info );
511  }
512 
513  // store field source index - we'll need it when fetching from provider
514  mFetchJoinInfo[ joinInfo ].attributes.push_back( sourceLayerIndex );
515 }
516 
518 {
520 
521  int oi = mSource->mFields.fieldOriginIndex( fieldIdx );
522  QgsExpression* exp = new QgsExpression( exps[oi].cachedExpression );
523 
524  QgsDistanceArea da;
525  da.setSourceCrs( mSource->mCrsId );
526  da.setEllipsoidalMode( true );
527  da.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
528  exp->setGeomCalculator( da );
529  exp->setDistanceUnits( QgsProject::instance()->distanceUnits() );
530  exp->setAreaUnits( QgsProject::instance()->areaUnits() );
531 
532  exp->prepare( mExpressionContext.data() );
533  mExpressionFieldInfo.insert( fieldIdx, exp );
534 
535  Q_FOREACH ( const QString& col, exp->referencedColumns() )
536  {
537  int dependentFieldIdx = mSource->mFields.fieldNameIndex( col );
539  {
540  mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() << dependentFieldIdx );
541  }
542  // also need to fetch this dependent field
543  if ( !mPreparedFields.contains( dependentFieldIdx ) && !mFieldsToPrepare.contains( dependentFieldIdx ) )
544  mFieldsToPrepare << dependentFieldIdx;
545  }
546 
547  if ( exp->needsGeometry() )
548  {
549  mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry );
550  }
551 }
552 
554 {
555  mPreparedFields.clear();
556  mFieldsToPrepare.clear();
557  mFetchJoinInfo.clear();
558  mOrderedJoinInfoList.clear();
559 
560  mExpressionContext.reset( new QgsExpressionContext() );
561  mExpressionContext->appendScope( QgsExpressionContextUtils::globalScope() );
562  mExpressionContext->appendScope( QgsExpressionContextUtils::projectScope() );
563  mExpressionContext->setFields( mSource->mFields );
564 
566 
567  while ( !mFieldsToPrepare.isEmpty() )
568  {
569  int fieldIdx = mFieldsToPrepare.takeFirst();
570  if ( mPreparedFields.contains( fieldIdx ) )
571  continue;
572 
573  mPreparedFields << fieldIdx;
574  prepareField( fieldIdx );
575  }
576 
577  //sort joins by dependency
578  if ( mFetchJoinInfo.size() > 0 )
579  {
580  createOrderedJoinList();
581  }
582 }
583 
584 void QgsVectorLayerFeatureIterator::createOrderedJoinList()
585 {
586  mOrderedJoinInfoList = mFetchJoinInfo.values();
587  if ( mOrderedJoinInfoList.size() < 2 )
588  {
589  return;
590  }
591 
592  QSet<int> resolvedFields; //todo: get provider / virtual fields without joins
593 
594  //add all provider fields without joins as resolved fields
595  QList< int >::const_iterator prepFieldIt = mPreparedFields.constBegin();
596  for ( ; prepFieldIt != mPreparedFields.constEnd(); ++prepFieldIt )
597  {
598  if ( mSource->mFields.fieldOrigin( *prepFieldIt ) != QgsFields::OriginJoin )
599  {
600  resolvedFields.insert( *prepFieldIt );
601  }
602  }
603 
604  //iterate through the joins. If target field is not yet covered, move the entry to the end of the list
605 
606  //some join combinations might not have a resolution at all
607  int maxIterations = ( mOrderedJoinInfoList.size() + 1 ) * mOrderedJoinInfoList.size() / 2.0;
608  int currentIteration = 0;
609 
610  for ( int i = 0; i < mOrderedJoinInfoList.size() - 1; ++i )
611  {
612  if ( !resolvedFields.contains( mOrderedJoinInfoList.at( i ).targetField ) )
613  {
614  mOrderedJoinInfoList.append( mOrderedJoinInfoList.at( i ) );
615  mOrderedJoinInfoList.removeAt( i );
616  --i;
617  }
618  else
619  {
620  int offset = mOrderedJoinInfoList.at( i ).indexOffset;
621  int joinField = mOrderedJoinInfoList.at( i ).joinField;
622 
623  QgsAttributeList attributes = mOrderedJoinInfoList.at( i ).attributes;
624  QgsAttributeList::const_iterator attIt = attributes.constBegin();
625  for ( ; attIt != attributes.constEnd(); ++attIt )
626  {
627  if ( *attIt != joinField )
628  {
629  resolvedFields.insert( joinField < *attIt ? *attIt + offset - 1 : *attIt + offset );
630  }
631  }
632  }
633 
634  ++currentIteration;
635  if ( currentIteration >= maxIterations )
636  {
637  break;
638  }
639  }
640 }
641 
643 {
644  switch ( mSource->mFields.fieldOrigin( fieldIdx ) )
645  {
647  prepareExpression( fieldIdx );
648  break;
649 
652  {
653  prepareJoin( fieldIdx );
654  }
655  break;
656 
660  break;
661  }
662 }
663 
665 {
666  QList< FetchJoinInfo >::const_iterator joinIt = mOrderedJoinInfoList.constBegin();
667  for ( ; joinIt != mOrderedJoinInfoList.constEnd(); ++joinIt )
668  {
669  QVariant targetFieldValue = f.attribute( joinIt->targetField );
670 
671  if ( !targetFieldValue.isValid() )
672  continue;
673 
674  const QHash< QString, QgsAttributes>& memoryCache = joinIt->joinInfo->cachedAttributes;
675  if ( memoryCache.isEmpty() )
676  joinIt->addJoinedAttributesDirect( f, targetFieldValue );
677  else
678  joinIt->addJoinedAttributesCached( f, targetFieldValue );
679  }
680 }
681 
683 {
684  // make sure we have space for newly added attributes
685  QgsAttributes attr = f.attributes();
686  attr.resize( mSource->mFields.count() ); // Provider attrs count + joined attrs count + expression attrs count
687  f.setAttributes( attr );
688 
689  // possible TODO - handle combinations of expression -> join -> expression -> join?
690  // but for now, write that off as too complex and an unlikely rare, unsupported use case
691 
692  QList< int > fetchedVirtualAttributes;
693  //first, check through joins for any virtual fields we need
695  for ( ; joinIt != mFetchJoinInfo.constEnd(); ++joinIt )
696  {
697  if ( mExpressionFieldInfo.contains( joinIt->targetField ) )
698  {
699  // have to calculate expression field before we can handle this join
700  addExpressionAttribute( f, joinIt->targetField );
701  fetchedVirtualAttributes << joinIt->targetField;
702  }
703  }
704 
705  if ( !mFetchJoinInfo.isEmpty() )
706  addJoinedAttributes( f );
707 
708  // add remaining expression fields
709  if ( !mExpressionFieldInfo.isEmpty() )
710  {
712  for ( ; it != mExpressionFieldInfo.constEnd(); ++it )
713  {
714  if ( fetchedVirtualAttributes.contains( it.key() ) )
715  continue;
716 
717  addExpressionAttribute( f, it.key() );
718  }
719  }
720 }
721 
723 {
724  QgsExpression* exp = mExpressionFieldInfo.value( attrIndex );
725  mExpressionContext->setFeature( f );
726  QVariant val = exp->evaluate( mExpressionContext.data() );
727  mSource->mFields.at( attrIndex ).convertCompatible( val );
728  f.setAttribute( attrIndex, val );
729 }
730 
732 {
733  delete mEditGeometrySimplifier;
734  mEditGeometrySimplifier = nullptr;
735 
736  // setup simplification for edited geometries to fetch
738  {
739  mEditGeometrySimplifier = QgsSimplifyMethod::createGeometrySimplifier( simplifyMethod );
740  return nullptr != mEditGeometrySimplifier;
741  }
742  return false;
743 }
744 
745 bool QgsVectorLayerFeatureIterator::providerCanSimplify( QgsSimplifyMethod::MethodType methodType ) const
746 {
747  Q_UNUSED( methodType );
748 #if 0
749  // TODO[MD]: after merge
750  QgsVectorDataProvider* provider = L->dataProvider();
751 
752  if ( provider && methodType != QgsSimplifyMethod::NoSimplification )
753  {
754  int capabilities = provider->capabilities();
755 
756  if ( methodType == QgsSimplifyMethod::OptimizeForRendering )
757  {
758  return ( capabilities & QgsVectorDataProvider::SimplifyGeometries );
759  }
760  else if ( methodType == QgsSimplifyMethod::PreserveTopology )
761  {
763  }
764  }
765 #endif
766  return false;
767 }
768 
769 
771 {
772  const QHash<QString, QgsAttributes>& memoryCache = joinInfo->cachedAttributes;
773  QHash<QString, QgsAttributes>::const_iterator it = memoryCache.find( joinValue.toString() );
774  if ( it == memoryCache.constEnd() )
775  return; // joined value not found -> leaving the attributes empty (null)
776 
777  int index = indexOffset;
778 
779  const QgsAttributes& featureAttributes = it.value();
780  for ( int i = 0; i < featureAttributes.count(); ++i )
781  {
782  f.setAttribute( index++, featureAttributes.at( i ) );
783  }
784 }
785 
786 
787 
789 {
790  // no memory cache, query the joined values by setting substring
791  QString subsetString;
792 
793  QString joinFieldName;
794  if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->fields().count() )
795  joinFieldName = joinLayer->fields().field( joinInfo->joinFieldIndex ).name(); // for compatibility with 1.x
796  else
797  joinFieldName = joinInfo->joinFieldName;
798 
799  subsetString.append( QString( "\"%1\"" ).arg( joinFieldName ) );
800 
801  if ( joinValue.isNull() )
802  {
803  subsetString += " IS NULL";
804  }
805  else
806  {
807  QString v = joinValue.toString();
808  switch ( joinValue.type() )
809  {
810  case QVariant::Int:
811  case QVariant::LongLong:
812  case QVariant::Double:
813  break;
814 
815  default:
816  case QVariant::String:
817  v.replace( '\'', "''" );
818  v.prepend( '\'' ).append( '\'' );
819  break;
820  }
821  subsetString += '=' + v;
822  }
823 
824  // maybe user requested just a subset of layer's attributes
825  // so we do not have to cache everything
826  bool hasSubset = joinInfo->joinFieldNamesSubset();
827  QVector<int> subsetIndices;
828  if ( hasSubset )
829  subsetIndices = QgsVectorLayerJoinBuffer::joinSubsetIndices( joinLayer, *joinInfo->joinFieldNamesSubset() );
830 
831  // select (no geometry)
832  QgsFeatureRequest request;
834  request.setSubsetOfAttributes( attributes );
835  request.setFilterExpression( subsetString );
836  request.setLimit( 1 );
837  QgsFeatureIterator fi = joinLayer->getFeatures( request );
838 
839  // get first feature
840  QgsFeature fet;
841  if ( fi.nextFeature( fet ) )
842  {
843  int index = indexOffset;
844  QgsAttributes attr = fet.attributes();
845  if ( hasSubset )
846  {
847  for ( int i = 0; i < subsetIndices.count(); ++i )
848  f.setAttribute( index++, attr.at( subsetIndices.at( i ) ) );
849  }
850  else
851  {
852  // use all fields except for the one used for join (has same value as exiting field in target layer)
853  for ( int i = 0; i < attr.count(); ++i )
854  {
855  if ( i == joinField )
856  continue;
857 
858  f.setAttribute( index++, attr.at( i ) );
859  }
860  }
861  }
862  else
863  {
864  // no suitable join feature found, keeping empty (null) attributes
865  }
866 }
867 
868 
869 
870 
872 {
873  QgsFeatureId featureId = mRequest.filterFid();
874 
875  // deleted already?
876  if ( mSource->mDeletedFeatureIds.contains( featureId ) )
877  return false;
878 
879  // has changed geometry?
881  {
882  useChangedAttributeFeature( featureId, mSource->mChangedGeometries[featureId], f );
883  return true;
884  }
885 
886  // added features
888  {
889  if ( iter->id() == featureId )
890  {
891  useAddedFeature( *iter, f );
892  return true;
893  }
894  }
895 
896  // regular features
898  if ( fi.nextFeature( f ) )
899  {
900  f.setFields( mSource->mFields );
901 
902  if ( mSource->mHasEditBuffer )
904 
905  if ( mHasVirtualAttributes )
907 
908  return true;
909  }
910 
911  return false;
912 }
913 
915 {
916  QgsAttributes attrs = f.attributes();
917 
918  // remove all attributes that will disappear - from higher indices to lower
919  for ( int idx = mSource->mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
920  {
921  attrs.remove( mSource->mDeletedAttributeIds[idx] );
922  }
923 
924  // adjust size to accommodate added attributes
925  attrs.resize( attrs.count() + mSource->mAddedAttributes.count() );
926 
927  // update changed attributes
929  {
931  for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
932  attrs[it.key()] = it.value();
933  }
934  f.setAttributes( attrs );
935 }
936 
938 {
939  if ( mSource->mChangedGeometries.contains( f.id() ) )
941 }
942 
943 bool QgsVectorLayerFeatureIterator::prepareOrderBy( const QList<QgsFeatureRequest::OrderByClause>& orderBys )
944 {
945  Q_UNUSED( orderBys );
946  return true;
947 }
948 
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()
void addJoinedAttributesDirect(QgsFeature &f, const QVariant &joinValue) const
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:431
static unsigned index
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.
QString & append(QChar ch)
Filter using feature ID.
QgsVectorLayerJoinBuffer * mJoinBuffer
bool containsJoins() const
Quick way to test if there is any join at all.
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:195
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
FieldOrigin fieldOrigin(int fieldIdx) const
Get field&#39;s origin (value from an enumeration)
Definition: qgsfield.cpp:411
QString targetFieldName
Join field in the target layer.
bool contains(const Key &key) const
GeometryType
Definition: qgis.h:111
Q_DECL_DEPRECATED QVariant evaluate(const QgsFeature *f)
Evaluate the feature and return the result.
const Flags & flags() const
void addExpressionAttribute(QgsFeature &f, int attrIndex)
Adds an expression based attribute to a feature.
QgsFeatureMap::ConstIterator mFetchAddedFeaturesIt
QgsGeometryMap::ConstIterator mFetchChangedGeomIt
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:196
bool exists(int i) const
Return if a field index is valid.
Definition: qgsfield.cpp:375
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:433
Supports simplification of geometries on provider side according to a distance tolerance.
QStringList referencedColumns() const
Get list of columns referenced by the expression.
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 QgsVectorJoinInfo * joinForFieldIndex(int index, const QgsFields &fields, int &sourceFieldIndex) const
Finds the vector join for a layer field index.
const_iterator constBegin() const
QgsFeatureId filterFid() const
Get the feature ID that should be fetched.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
const QgsChangedAttributesMap & changedAttributeValues()
Changed attributes values which are not commited.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
bool convertCompatible(QVariant &v) const
Converts the provided variant to a compatible format.
Definition: qgsfield.cpp:175
FilterType filterType() const
Return the filter type which is currently set on this request.
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
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QMap< int, QgsExpression * > mExpressionFieldInfo
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
field comes from the underlying data provider of the vector layer (originIndex = index in provider&#39;s ...
Definition: qgsfield.h:194
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
const QgsRectangle & filterRect() const
Get the rectangle from which features will be taken.
int count() const
Return number of items.
Definition: qgsfield.cpp:365
const QList< ExpressionField > & expressions() const
it has not been specified where the field comes from
Definition: qgsfield.h:193
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:76
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:385
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
QgsFields fields() const
Returns the list of fields of this layer.
int joinedFieldsOffset(const QgsVectorJoinInfo *info, const QgsFields &fields)
Find out what is the first index of the join within fields.
int joinField
index of field (of the joined layer) must have equal value
QgsExpression * filterExpression() const
Returns the filter expression if set.
virtual bool simplifyGeometry(QgsGeometry *geometry) const =0
Simplifies the specified geometry.
int fieldOriginIndex(int fieldIdx) const
Get field&#39;s origin index (its meaning is specific to each type of origin)
Definition: qgsfield.cpp:419
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QList< Key > keys() const
void updateChangedAttributes(QgsFeature &f)
Update feature with uncommited attribute updates.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Set feature ID that should be fetched.
Simplify using the map2pixel data to optimize the rendering of geometries.
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
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:520
bool isNull() const
const QgsVectorJoinInfo * joinInfo
cannonical source of information about the join
QgsFeatureRequest & disableFilter()
Disables filter conditions.
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.
void addJoinedAttributesCached(QgsFeature &f, const QVariant &joinValue) const
bool isEmpty() const
const_iterator constEnd() const
void remove(int i)
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()
No simplification is applied.
QgsFeatureRequest & setFlags(const QgsFeatureRequest::Flags &flags)
Set flags that affect how features will be fetched.
QGis::GeometryType geometryType() const
Returns point, line or polygon.
iterator end()
Fetch only a subset of attributes (setSubsetOfAttributes sets this flag)
QgsExpressionFieldBuffer * mExpressionFieldBuffer
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
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.
T * data() const
const T value(const Key &key) const
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
QgsAttributeList subsetOfAttributes() const
Return the subset of attributes which at least need to be fetched.
iterator find(const Key &key)
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:503
Partial snapshot of vector layer&#39;s state (only the members necessary for access to features) ...
bool contains(const T &value) const
QgsGeometry * geometry()
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:76
QgsVectorLayerFeatureSource(QgsVectorLayer *layer)
bool contains(const T &value) const
int indexOffset
at what position the joined fields start
Supports topological simplification of geometries on provider side according to a distance tolerance...
void useChangedAttributeFeature(QgsFeatureId fid, const QgsGeometry &geom, QgsFeature &f)
const QgsFeatureMap & addedFeatures()
New features which are not commited.
virtual QgsAbstractFeatureSource * featureSource() const
Return feature source object that can be used for querying provider&#39;s data.
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
int indexFromName(const QString &name) const
Look up field&#39;s index from name. Returns -1 on error.
Definition: qgsfield.cpp:424
Buffers information about expression fields for a vector layer.
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
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:428
T takeFirst()
bool isEmpty() const
virtual bool rewind() override
reset the iterator to the starting position
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:381
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.
MethodType methodType() const
Gets the simplification type.
int count(const T &value) const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setDistanceUnits(QGis::UnitType unit)
Sets the desired distance units for calculations involving geomCalculator(), eg "$length" and "$perim...
QgsFeatureRequest & setLimit(long limit)
Set the maximum number of features to request.
static QgsAbstractGeometrySimplifier * createGeometrySimplifier(const QgsSimplifyMethod &simplifyMethod)
Creates a geometry simplifier according to specified method.
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
bool isValid() const
This class contains information about how to simplify geometries fetched from a QgsFeatureIterator.
iterator insert(const Key &key, const T &value)
bool isEmpty() const
static QgsExpressionContextScope * projectScope()
Creates a new scope which contains variables and functions relating to the current QGIS project...
Simplify using the Douglas-Peucker algorithm ensuring that the result is a valid geometry.
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request)=0
Get an iterator for features matching the specified request.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
const_iterator constEnd() const
bool nextFeature(QgsFeature &f)
const_iterator constBegin() const
long srsid() const
Returns the SrsId, if available.
This is the base class for vector data providers.
Type type() const
QgsChangedAttributesMap mChangedAttributeValues
OrderBy orderBy() const
Return a list of order by clauses specified for this feature request.
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
Represents a vector layer which manages a vector based data sets.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:271
const QgsAttributeList & deletedAttributeIds()
Deleted attributes fields which are not commited.
field is calculated from an expression
Definition: qgsfield.h:197
QString toString() const
QString joinLayerId
Source layer.
bool isClosed() const
find out whether the iterator is still valid or closed already
void setEllipsoidalMode(bool flag)
Sets whether coordinates must be projected to ellipsoid before measuring.
QgsVectorLayerJoinBuffer * clone() const
Create a copy of the join buffer.
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