void QgsVectorLayerRenderer::prepareDiagrams( QgsVectorLayer* layer, QStringList& attributeNames )
{
  if ( !mContext.labelingEngine() )
    return;

  if ( !layer->diagramRenderer() || !layer->diagramLayerSettings() )
    return;

  mDiagrams = true;

  const QgsDiagramRendererV2* diagRenderer = layer->diagramRenderer();
  const QgsDiagramLayerSettings* diagSettings = layer->diagramLayerSettings();

  mContext.labelingEngine()->addDiagramLayer( layer, diagSettings ); // will make internal copy of diagSettings + initialize it

  //add attributes needed by the diagram renderer
  QList<QString> att = diagRenderer->diagramAttributes();
  QList<QString>::const_iterator attIt = att.constBegin();
  for ( ; attIt != att.constEnd(); ++attIt )
  {
    QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, &mFields );
    QStringList columns = expression->referencedColumns();
    QStringList::const_iterator columnsIterator = columns.constBegin();
    for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
    {
      if ( !attributeNames.contains( *columnsIterator ) )
        attributeNames << *columnsIterator;
    }
  }

  const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( layer->diagramRenderer() );
  if ( linearlyInterpolatedDiagramRenderer != NULL )
  {
    if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
    {
      QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), &mFields );
      QStringList columns = expression->referencedColumns();
      QStringList::const_iterator columnsIterator = columns.constBegin();
      for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
      {
        if ( !attributeNames.contains( *columnsIterator ) )
          attributeNames << *columnsIterator;
      }
    }
    else
    {
      QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name();
      if ( !attributeNames.contains( name ) )
        attributeNames << name;
    }
  }

  //and the ones needed for data defined diagram positions
  if ( diagSettings->xPosColumn != -1 )
    attributeNames << mFields.at( diagSettings->xPosColumn ).name();
  if ( diagSettings->yPosColumn != -1 )
    attributeNames << mFields.at( diagSettings->yPosColumn ).name();
}
bool QgsVectorLayerLabelProvider::prepare( const QgsRenderContext &context, QSet<QString> &attributeNames )
{
  QgsPalLayerSettings &lyr = mSettings;
  const QgsMapSettings &mapSettings = mEngine->mapSettings();

  QgsDebugMsgLevel( "PREPARE LAYER " + mLayerId, 4 );

  if ( lyr.drawLabels )
  {
    if ( lyr.fieldName.isEmpty() )
    {
      return false;
    }

    if ( lyr.isExpression )
    {
      QgsExpression exp( lyr.fieldName );
      if ( exp.hasEvalError() )
      {
        QgsDebugMsgLevel( "Prepare error:" + exp.evalErrorString(), 4 );
        return false;
      }
    }
    else
    {
      // If we aren't an expression, we check to see if we can find the column.
      if ( mFields.lookupField( lyr.fieldName ) == -1 )
      {
        return false;
      }
    }
  }

  lyr.mCurFields = mFields;

  if ( lyr.drawLabels || lyr.obstacle )
  {
    if ( lyr.drawLabels )
    {
      // add field indices for label's text, from expression or field
      if ( lyr.isExpression )
      {
        // prepare expression for use in QgsPalLayerSettings::registerFeature()
        QgsExpression *exp = lyr.getLabelExpression();
        exp->prepare( &context.expressionContext() );
        if ( exp->hasEvalError() )
        {
          QgsDebugMsgLevel( "Prepare error:" + exp->evalErrorString(), 4 );
        }
        Q_FOREACH ( const QString &name, exp->referencedColumns() )
        {
          QgsDebugMsgLevel( "REFERENCED COLUMN = " + name, 4 );
          attributeNames.insert( name );
        }
      }
      else
      {
        attributeNames.insert( lyr.fieldName );
      }
    }
void QgsVectorLayerFeatureIterator::prepareExpressions()
{
  const QList<QgsExpressionFieldBuffer::ExpressionField> exps = mSource->mExpressionFieldBuffer->expressions();

  for ( int i = 0; i < mSource->mFields.count(); i++ )
  {
    if ( mSource->mFields.fieldOrigin( i ) == QgsFields::OriginExpression )
    {
      // Only prepare if there is no subset defined or the subset contains this field
      if ( !( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
           || mRequest.subsetOfAttributes().contains( i ) )
      {
        int oi = mSource->mFields.fieldOriginIndex( i );
        QgsExpression* exp = new QgsExpression( exps[oi].expression );
        exp->prepare( mSource->mFields );
        mExpressionFieldInfo.insert( i, exp );

        if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
        {
          QgsAttributeList attrs;
          Q_FOREACH( const QString& col, exp->referencedColumns() )
          {
            attrs.append( mSource->mFields.fieldNameIndex( col ) );
          }

          mRequest.setSubsetOfAttributes( mRequest.subsetOfAttributes() + attrs );
        }

        if ( exp->needsGeometry() )
        {
          mRequest.setFlags( mRequest.flags() & ~QgsFeatureRequest::NoGeometry );
        }
      }
    }
void QgsAttributeTableModel::loadAttributes()
{
  if ( !layer() )
  {
    return;
  }

  bool ins = false, rm = false;

  QgsAttributeList attributes;
  const QgsFields& fields = layer()->pendingFields();
  for ( int idx = 0; idx < fields.count(); ++idx )
  {
    switch ( layer()->editType( idx ) )
    {
      case QgsVectorLayer::Hidden:
        continue;

      case QgsVectorLayer::ValueMap:
        mValueMaps.insert( idx, new QMap< QString, QVariant >( layer()->valueMap( idx ) ) );
        break;

      case QgsVectorLayer::ValueRelation:
      {
        const QgsVectorLayer::ValueRelationData &data =  layer()->valueRelation( idx );

        QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) );
        if ( !layer )
          continue;

        int ki = layer->fieldNameIndex( data.mKey );
        int vi = layer->fieldNameIndex( data.mValue );

        QgsExpression *e = 0;
        if ( !data.mFilterExpression.isEmpty() )
        {
          e = new QgsExpression( data.mFilterExpression );
          if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
            continue;
        }

        if ( ki >= 0 && vi >= 0 )
        {
          QSet<int> attributes;
          attributes << ki << vi;

          QgsFeatureRequest::Flag flags = QgsFeatureRequest::NoGeometry;

          if ( e )
          {
            if ( e->needsGeometry() )
              flags = QgsFeatureRequest::NoFlags;

            foreach ( const QString &field, e->referencedColumns() )
            {
              int idx = layer->fieldNameIndex( field );
              if ( idx < 0 )
                continue;
              attributes << idx;
            }
          }

          QMap< QString, QVariant > *map = new QMap< QString, QVariant >();

          QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFlags( flags ).setSubsetOfAttributes( attributes.toList() ) );
          QgsFeature f;
          while ( fit.nextFeature( f ) )
          {
            if ( e && !e->evaluate( &f ).toBool() )
              continue;

            map->insert( f.attribute( vi ).toString(), f.attribute( ki ) );
          }

          mValueMaps.insert( idx, map );
        }
      }
      break;

      default:
        break;
    }

    attributes << idx;
  }
bool QgsVectorLayerDiagramProvider::prepare( const QgsRenderContext& context, QStringList& attributeNames )
{
  QgsDiagramLayerSettings& s2 = mSettings;
  const QgsMapSettings& mapSettings = mEngine->mapSettings();

  s2.ct = nullptr;
  if ( mapSettings.hasCrsTransformEnabled() )
  {
    if ( context.coordinateTransform() )
      // this is context for layer rendering - use its CT as it includes correct datum transform
      s2.ct = context.coordinateTransform()->clone();
    else
      // otherwise fall back to creating our own CT - this one may not have the correct datum transform!
      s2.ct = new QgsCoordinateTransform( mLayerCrs, mapSettings.destinationCrs() );
  }

  s2.xform = &mapSettings.mapToPixel();

  s2.fields = mFields;

  s2.renderer = mDiagRenderer;

  const QgsDiagramRendererV2* diagRenderer = s2.renderer;

  //add attributes needed by the diagram renderer
  QList<QString> att = diagRenderer->diagramAttributes();
  QList<QString>::const_iterator attIt = att.constBegin();
  for ( ; attIt != att.constEnd(); ++attIt )
  {
    QgsExpression* expression = diagRenderer->diagram()->getExpression( *attIt, context.expressionContext() );
    QStringList columns = expression->referencedColumns();
    QStringList::const_iterator columnsIterator = columns.constBegin();
    for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
    {
      if ( !attributeNames.contains( *columnsIterator ) )
        attributeNames << *columnsIterator;
    }
  }

  const QgsLinearlyInterpolatedDiagramRenderer* linearlyInterpolatedDiagramRenderer = dynamic_cast<const QgsLinearlyInterpolatedDiagramRenderer*>( diagRenderer );
  if ( linearlyInterpolatedDiagramRenderer )
  {
    if ( linearlyInterpolatedDiagramRenderer->classificationAttributeIsExpression() )
    {
      QgsExpression* expression = diagRenderer->diagram()->getExpression( linearlyInterpolatedDiagramRenderer->classificationAttributeExpression(), context.expressionContext() );
      QStringList columns = expression->referencedColumns();
      QStringList::const_iterator columnsIterator = columns.constBegin();
      for ( ; columnsIterator != columns.constEnd(); ++columnsIterator )
      {
        if ( !attributeNames.contains( *columnsIterator ) )
          attributeNames << *columnsIterator;
      }
    }
    else
    {
      QString name = mFields.at( linearlyInterpolatedDiagramRenderer->classificationAttribute() ).name();
      if ( !attributeNames.contains( name ) )
        attributeNames << name;
    }
  }

  //and the ones needed for data defined diagram positions
  if ( mSettings.xPosColumn != -1 )
    attributeNames << mFields.at( mSettings.xPosColumn ).name();
  if ( mSettings.yPosColumn != -1 )
    attributeNames << mFields.at( mSettings.yPosColumn ).name();

  return true;
}