QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource* source, bool ownSource, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIteratorFromSource( source, ownSource, request )
    , mEditGeometrySimplifier( 0 )
{

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( mSource->mJoinBuffer->containsJoins() )
    prepareJoins();

  prepareExpressions();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QgsAttributeList providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    int nPendingFields = mSource->mFields.count();
    for ( int i = 0; i < subset.count(); ++i )
    {
      int attrIndex = subset[i];
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( mSource->mFields.fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << mSource->mFields.fieldOriginIndex( attrIndex );
    }
    mProviderRequest.setSubsetOfAttributes( providerSubset );
  }

  if ( mSource->mHasEditBuffer )
  {
    mChangedFeaturesRequest = mProviderRequest;
    mChangedFeaturesRequest.setFilterFids( mSource->mChangedAttributeValues.keys().toSet() );
  }

  if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    mFetchedFid = false;
  }
  else // no filter or filter by rect
  {
    if ( mSource->mHasEditBuffer )
    {
      mChangedFeaturesIterator = mSource->mProviderFeatureSource->getFeatures( mChangedFeaturesRequest );
    }
    else
    {
      mProviderIterator = mSource->mProviderFeatureSource->getFeatures( mProviderRequest );
    }

    rewindEditBuffer();
  }

  if ( mRequest.filterType() == QgsFeatureRequest::FilterExpression )
  {
    mRequest.filterExpression()->prepare( mSource->mFields );
  }
}
QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayer* layer, const QgsFeatureRequest& request )
    : QgsAbstractFeatureIterator( request ), L( layer )
{
  QgsVectorLayerJoinBuffer* joinBuffer = L->mJoinBuffer;

  if ( L->editBuffer() )
  {
    mAddedFeatures = QgsFeatureMap( L->editBuffer()->addedFeatures() );
    mChangedGeometries = QgsGeometryMap( L->editBuffer()->changedGeometries() );
    mDeletedFeatureIds = QgsFeatureIds( L->editBuffer()->deletedFeatureIds() );
    mChangedAttributeValues = QgsChangedAttributesMap( L->editBuffer()->changedAttributeValues() );
    mAddedAttributes = QList<QgsField>( L->editBuffer()->addedAttributes() );
    mDeletedAttributeIds = QgsAttributeList( L->editBuffer()->deletedAttributeIds() );
  }

  // prepare joins: may add more attributes to fetch (in order to allow join)
  if ( joinBuffer->containsJoins() )
    prepareJoins();

  // by default provider's request is the same
  mProviderRequest = mRequest;

  if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    // prepare list of attributes to match provider fields
    QgsAttributeList providerSubset;
    QgsAttributeList subset = mProviderRequest.subsetOfAttributes();
    const QgsFields &pendingFields = L->pendingFields();
    int nPendingFields = pendingFields.count();
    for ( int i = 0; i < subset.count(); ++i )
    {
      int attrIndex = subset[i];
      if ( attrIndex < 0 || attrIndex >= nPendingFields ) continue;
      if ( L->pendingFields().fieldOrigin( attrIndex ) == QgsFields::OriginProvider )
        providerSubset << L->pendingFields().fieldOriginIndex( attrIndex );
    }
    mProviderRequest.setSubsetOfAttributes( providerSubset );
  }

  if ( request.filterType() == QgsFeatureRequest::FilterFid )
  {
    mFetchedFid = false;
  }
  else // no filter or filter by rect
  {
    mProviderIterator = L->dataProvider()->getFeatures( mProviderRequest );

    rewindEditBuffer();
  }
}
bool QgsVectorLayerFeatureIterator::rewind()
{
  if ( mClosed )
    return false;

  if ( mRequest.filterType() == QgsFeatureRequest::FilterFid )
  {
    mFetchedFid = false;
  }
  else
  {
    mProviderIterator.rewind();
    rewindEditBuffer();
  }

  return true;
}