QgsFeatureList QgsConvexHullAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
{
  QgsFeature f = feature;
  if ( f.hasGeometry() )
  {
    QgsGeometry outputGeometry;
    if ( QgsWkbTypes::flatType( f.geometry().wkbType() ) == QgsWkbTypes::Point )
    {
      feedback->reportError( QObject::tr( "Cannot calculate convex hull for a single Point feature (try 'Minimum bounding geometry' algorithm instead)." ) );
      f.clearGeometry();
    }
    else
    {
      outputGeometry = f.geometry().convexHull();
      if ( outputGeometry.isNull() )
        feedback->reportError( outputGeometry.lastError() );
      f.setGeometry( outputGeometry );
    }
    if ( !outputGeometry.isNull() )
    {
      QgsAttributes attrs = f.attributes();
      attrs << outputGeometry.constGet()->area()
            << outputGeometry.constGet()->perimeter();
      f.setAttributes( attrs );
    }
    else
    {
      QgsAttributes attrs = f.attributes();
      attrs << QVariant()
            << QVariant();
      f.setAttributes( attrs );
    }
  }
  return QgsFeatureList() << f;
}
QgsFeature QgsConvexHullAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback )
{
  QgsFeature f = feature;
  if ( f.hasGeometry() )
  {
    QgsGeometry outputGeometry = f.geometry().convexHull();
    if ( !outputGeometry )
      feedback->reportError( outputGeometry.lastError() );
    f.setGeometry( outputGeometry );
    if ( outputGeometry )
    {
      QgsAttributes attrs = f.attributes();
      attrs << outputGeometry.constGet()->area()
            << outputGeometry.constGet()->perimeter();
      f.setAttributes( attrs );
    }
    else
    {
      QgsAttributes attrs = f.attributes();
      attrs << QVariant()
            << QVariant();
      f.setAttributes( attrs );
    }
  }
  return f;
}
bool QgsVectorLayerImport::addFeature( QgsFeature& feat )
{
  QgsAttributes attrs = feat.attributes();

  QgsFeature newFeat;
  if ( feat.constGeometry() )
    newFeat.setGeometry( *feat.constGeometry() );

  newFeat.initAttributes( mAttributeCount );

  for ( int i = 0; i < attrs.count(); ++i )
  {
    // add only mapped attributes (un-mapped ones will not be present in the
    // destination layer)
    int dstIdx = mOldToNewAttrIdx.value( i, -1 );
    if ( dstIdx < 0 )
      continue;

    QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 );
    newFeat.setAttribute( dstIdx, attrs.at( i ) );
  }

  mFeatureBuffer.append( newFeat );

  if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE )
  {
    return flushBuffer();
  }

  return true;
}
Exemple #4
0
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( feature.fields() )
    expressionContext.setFields( *feature.fields() );

  QVariant attrVal;
  if ( is.classificationAttributeIsExpression )
  {
    QgsExpression* expression = getExpression( is.classificationAttributeExpression, expressionContext );
    attrVal = expression->evaluate( &expressionContext );
  }
  else
  {
    attrVal = feature.attributes().at( is.classificationAttribute );
  }

  bool ok = false;
  double val = attrVal.toDouble( &ok );
  if ( !ok )
  {
    return QSizeF(); //zero size if attribute is missing
  }

  return sizeForValue( val, s, is );
}
void QgsVectorLayerFeatureIterator::useAddedFeature( const QgsFeature& src, QgsFeature& f )
{
  f.setFeatureId( src.id() );
  f.setValid( true );
  f.setFields( &L->mUpdatedFields );

  if ( src.geometry() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
  {
    f.setGeometry( *src.geometry() );

    // simplify the edited geometry using its simplifier configured
    if ( mEditGeometrySimplifier )
    {
      QgsGeometry* geometry = f.geometry();
      QGis::GeometryType geometryType = geometry->type();
      if ( geometryType == QGis::Line || geometryType == QGis::Polygon ) mEditGeometrySimplifier->simplifyGeometry( geometry );
    }
  }

  // TODO[MD]: if subset set just some attributes

  f.setAttributes( src.attributes() );

  if ( !mFetchJoinInfo.isEmpty() )
    addJoinedAttributes( f );
}
QgsFeatureList QgsAddXYFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  if ( mTransformNeedsInitialization )
  {
    mTransform = QgsCoordinateTransform( mSourceCrs, mCrs, context.transformContext() );
    mTransformNeedsInitialization = false;
  }

  QVariant x;
  QVariant y;
  if ( feature.hasGeometry() )
  {
    if ( feature.geometry().isMultipart() )
      throw QgsProcessingException( QObject::tr( "Multipoint features are not supported - please convert to single point features first." ) );

    const QgsPointXY point = feature.geometry().asPoint();
    try
    {
      const QgsPointXY transformed = mTransform.transform( point );
      x = transformed.x();
      y = transformed.y();
    }
    catch ( QgsCsException & )
    {
      feedback->reportError( QObject::tr( "Could not transform point to destination CRS" ) );
    }
  }
  QgsFeature f =  feature;
  QgsAttributes attributes = f.attributes();
  attributes << x << y;
  f.setAttributes( attributes );
  return QgsFeatureList() << f;
}
void QgsFeatureAction::onFeatureSaved( const QgsFeature& feature )
{
  QgsAttributeForm* form = qobject_cast<QgsAttributeForm*>( sender() );
  Q_UNUSED( form ) // only used for Q_ASSERT
  Q_ASSERT( form );

  // Assign provider generated values
  if ( mFeature )
    *mFeature = feature;

  mFeatureSaved = true;

  QSettings settings;
  bool reuseLastValues = settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool();
  QgsDebugMsg( QString( "reuseLastValues: %1" ).arg( reuseLastValues ) );

  if ( reuseLastValues )
  {
    QgsFields fields = mLayer->fields();
    for ( int idx = 0; idx < fields.count(); ++idx )
    {
      QgsAttributes newValues = feature.attributes();
      QgsAttributeMap origValues = sLastUsedValues[ mLayer ];
      if ( origValues[idx] != newValues.at( idx ) )
      {
        QgsDebugMsg( QString( "saving %1 for %2" ).arg( sLastUsedValues[ mLayer ][idx].toString() ).arg( idx ) );
        sLastUsedValues[ mLayer ][idx] = newValues.at( idx );
      }
    }
  }
}
bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, const QgsFeatureId &featureId, double& x, bool& xSuccess, double& y, bool& ySuccess, int& xCol, int& yCol ) const
{
  xSuccess = false;
  ySuccess = false;

  if ( !vlayer )
  {
    return false;
  }

  if ( mCurrentLabelPos.isDiagram )
  {
    if ( !diagramMoveable( vlayer, xCol, yCol ) )
    {
      return false;
    }
  }
  else if ( !labelMoveable( vlayer, xCol, yCol ) )
  {
    return false;
  }

  QgsFeature f;
  if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
  {
    return false;
  }

  const QgsAttributes& attributes = f.attributes();
  x = attributes[xCol].toDouble( &xSuccess );
  y = attributes[yCol].toDouble( &ySuccess );

  return true;
}
void QgsVectorLayerFeatureIterator::useChangedAttributeFeature( QgsFeatureId fid, const QgsGeometry& geom, QgsFeature& f )
{
  f.setFeatureId( fid );
  f.setValid( true );
  f.setFields( &L->mUpdatedFields );

  if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
    f.setGeometry( geom );

  bool subsetAttrs = ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes );
  if ( !subsetAttrs || ( subsetAttrs && mRequest.subsetOfAttributes().count() > 0 ) )
  {
    // retrieve attributes from provider
    QgsFeature tmp;
    //mDataProvider->featureAtId( fid, tmp, false, mFetchProvAttributes );
    QgsFeatureRequest request;
    request.setFilterFid( fid ).setFlags( QgsFeatureRequest::NoGeometry ).setSubsetOfAttributes( mProviderRequest.subsetOfAttributes() );
    QgsFeatureIterator fi = L->dataProvider()->getFeatures( request );
    if ( fi.nextFeature( tmp ) )
    {
      updateChangedAttributes( tmp );
      f.setAttributes( tmp.attributes() );
    }
  }

  if ( !mFetchJoinInfo.isEmpty() )
    addJoinedAttributes( f );
}
void QgsNetworkAnalysisAlgorithmBase::loadPoints( QgsFeatureSource *source, QVector< QgsPointXY > &points, QHash< int, QgsAttributes > &attributes, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  feedback->pushInfo( QObject::tr( "Loading points…" ) );

  QgsFeature feat;
  int i = 0;
  int pointId = 1;
  double step = source->featureCount() > 0 ? 100.0 / source->featureCount() : 0;
  QgsFeatureIterator features = source->getFeatures( QgsFeatureRequest().setDestinationCrs( mNetwork->sourceCrs(), context.transformContext() ) );

  while ( features.nextFeature( feat ) )
  {
    i++;
    if ( feedback->isCanceled() )
    {
      break;
    }

    feedback->setProgress( i * step );
    if ( !feat.hasGeometry() )
      continue;

    QgsGeometry geom = feat.geometry();
    QgsAbstractGeometry::vertex_iterator it = geom.vertices_begin();
    while ( it != geom.vertices_end() )
    {
      points.push_back( QgsPointXY( *it ) );
      attributes.insert( pointId, feat.attributes() );
      it++;
      pointId++;
    }
  }
}
void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
{
  //memory cache not required or already done
  if ( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 )
  {
    return;
  }

  QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
  if ( cacheLayer )
  {
    int joinFieldIndex;
    if ( joinInfo.joinFieldName.isEmpty() )
      joinFieldIndex = joinInfo.joinFieldIndex;   //for compatibility with 1.x
    else
      joinFieldIndex = cacheLayer->pendingFields().indexFromName( joinInfo.joinFieldName );

    if ( joinFieldIndex < 0 || joinFieldIndex >= cacheLayer->pendingFields().count() )
      return;

    joinInfo.cachedAttributes.clear();

    QgsFeatureIterator fit = cacheLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) );
    QgsFeature f;
    while ( fit.nextFeature( f ) )
    {
      const QgsAttributes& attrs = f.attributes();
      joinInfo.cachedAttributes.insert( attrs[joinFieldIndex].toString(), attrs );
    }
  }
}
QgsVectorLayer *QgsFeatureSource::materialize( const QgsFeatureRequest &request, QgsFeedback *feedback )
{
  QgsWkbTypes::Type outWkbType = request.flags() & QgsFeatureRequest::NoGeometry ? QgsWkbTypes::NoGeometry : wkbType();
  QgsCoordinateReferenceSystem crs = request.destinationCrs().isValid() ? request.destinationCrs() : sourceCrs();

  QgsAttributeList requestedAttrs = request.subsetOfAttributes();

  QgsFields outFields;
  if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes )
  {
    int i = 0;
    const QgsFields sourceFields = fields();
    for ( const QgsField &field : sourceFields )
    {
      if ( requestedAttrs.contains( i ) )
        outFields.append( field );
      i++;
    }
  }
  else
  {
    outFields = fields();
  }

  std::unique_ptr< QgsVectorLayer > layer( QgsMemoryProviderUtils::createMemoryLayer(
        sourceName(),
        outFields,
        outWkbType,
        crs ) );
  QgsFeature f;
  QgsFeatureIterator it = getFeatures( request );
  int fieldCount = fields().count();
  while ( it.nextFeature( f ) )
  {
    if ( feedback && feedback->isCanceled() )
      break;

    if ( request.flags() & QgsFeatureRequest::SubsetOfAttributes )
    {
      // remove unused attributes
      QgsAttributes attrs;
      for ( int i = 0; i < fieldCount; ++i )
      {
        if ( requestedAttrs.contains( i ) )
        {
          attrs.append( f.attributes().at( i ) );
        }
      }

      f.setAttributes( attrs );
    }

    layer->dataProvider()->addFeature( f, QgsFeatureSink::FastInsert );
  }

  return layer.release();
}
QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
{
  QString attribute;
  const QgsAttributes& attrs = f.attributes();
  if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
  {
    attribute = attrs[mLabelIndex].toString();
  }
  return attribute;
}
Exemple #14
0
QSizeF QgsTextDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  Q_UNUSED( c );

  QVariant attrVal;
  if ( is.classificationAttributeIsExpression )
  {
    QgsExpression* expression = getExpression( is.classificationAttributeExpression, feature.fields() );
    attrVal = expression->evaluate( feature );
  }
  else
  {
    attrVal = feature.attributes()[is.classificationAttribute];
  }

  if ( !attrVal.isValid() )
  {
    return QSizeF(); //zero size if attribute is missing
  }

  double scaledValue = attrVal.toDouble();
  double scaledLowerValue = is.lowerValue;
  double scaledUpperValue = is.upperValue;
  double scaledLowerSizeWidth = is.lowerSize.width();
  double scaledLowerSizeHeight = is.lowerSize.height();
  double scaledUpperSizeWidth = is.upperSize.width();
  double scaledUpperSizeHeight = is.upperSize.height();

  // interpolate the squared value if scale by area
  if ( s.scaleByArea )
  {
    scaledValue = sqrt( scaledValue );
    scaledLowerValue = sqrt( scaledLowerValue );
    scaledUpperValue = sqrt( scaledUpperValue );
    scaledLowerSizeWidth = sqrt( scaledLowerSizeWidth );
    scaledLowerSizeHeight = sqrt( scaledLowerSizeHeight );
    scaledUpperSizeWidth = sqrt( scaledUpperSizeWidth );
    scaledUpperSizeHeight = sqrt( scaledUpperSizeHeight );
  }

  //interpolate size
  double scaledRatio = ( scaledValue - scaledLowerValue ) / ( scaledUpperValue - scaledLowerValue );

  QSizeF size = QSizeF( is.upperSize.width() * scaledRatio + is.lowerSize.width() * ( 1 - scaledRatio ),
                        is.upperSize.height() * scaledRatio + is.lowerSize.height() * ( 1 - scaledRatio ) );

  // Scale, if extension is smaller than the specified minimum
  if ( size.width() <= s.minimumSize && size.height() <= s.minimumSize )
  {
    size.scale( s.minimumSize, s.minimumSize, Qt::KeepAspectRatio );
  }

  return size;
}
Exemple #15
0
void QgsOverlayAnalyzer::intersectFeature( QgsFeature& f, QgsVectorFileWriter* vfw,
    QgsVectorLayer* vl, QgsSpatialIndex* index )
{
  if ( !f.hasGeometry() )
  {
    return;
  }

  QgsGeometry featureGeometry = f.geometry();
  QgsGeometry intersectGeometry;
  QgsFeature overlayFeature;

  QList<QgsFeatureId> intersects;
  intersects = index->intersects( featureGeometry.boundingBox() );
  QList<QgsFeatureId>::const_iterator it = intersects.constBegin();
  QgsFeature outFeature;
  for ( ; it != intersects.constEnd(); ++it )
  {
    if ( !vl->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( overlayFeature ) )
    {
      continue;
    }

    if ( featureGeometry.intersects( overlayFeature.geometry() ) )
    {
      intersectGeometry = featureGeometry.intersection( overlayFeature.geometry() );

      outFeature.setGeometry( intersectGeometry );
      QgsAttributes attributesA = f.attributes();
      QgsAttributes attributesB = overlayFeature.attributes();
      combineAttributeMaps( attributesA, attributesB );
      outFeature.setAttributes( attributesA );

      //add it to vector file writer
      if ( vfw )
      {
        vfw->addFeature( outFeature );
      }
    }
  }
}
Exemple #16
0
void QgsFeaturePool::updateFeature( QgsFeature& feature )
{
  QgsGeometryMap geometryMap;
  geometryMap.insert( feature.id(), QgsGeometry( feature.geometry()->geometry()->clone() ) );
  QgsChangedAttributesMap changedAttributesMap;
  QgsAttributeMap attribMap;
  for ( int i = 0, n = feature.attributes().size(); i < n; ++i )
  {
    attribMap.insert( i, feature.attributes().at( i ) );
  }
  changedAttributesMap.insert( feature.id(), attribMap );
  mLayerMutex.lock();
  mFeatureCache.remove( feature.id() ); // Remove to force reload on next get()
  mLayer->dataProvider()->changeGeometryValues( geometryMap );
  mLayer->dataProvider()->changeAttributeValues( changedAttributesMap );
  mLayerMutex.unlock();
  mIndexMutex.lock();
  mIndex.deleteFeature( feature );
  mIndex.insertFeature( feature );
  mIndexMutex.unlock();
}
Exemple #17
0
QVariant RgSpeedProperter::property( double distance, const QgsFeature& f ) const
{
  QgsAttributes attrs = f.attributes();

  if ( mAttributeId < 0 || mAttributeId >= attrs.count() )
    return QVariant( distance / ( mDefaultValue*mToMetricFactor ) );

  double val = distance / ( attrs.at( mAttributeId ).toDouble() * mToMetricFactor );
  if ( val <= 0.0 )
    return QVariant( distance / ( mDefaultValue / mToMetricFactor ) );

  return QVariant( val );
}
void QgsGeometryAnalyzer::bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, bool dissolve,
    QgsGeometry** dissolveGeometry, double bufferDistance, int bufferDistanceField )
{
  double currentBufferDistance;
  QgsGeometry* featureGeometry = f.geometry();
  QgsGeometry* tmpGeometry = 0;
  QgsGeometry* bufferGeometry = 0;

  if ( !featureGeometry )
  {
    return;
  }

  //create buffer
  if ( bufferDistanceField == -1 )
  {
    currentBufferDistance = bufferDistance;
  }
  else
  {
    currentBufferDistance = f.attribute( bufferDistanceField ).toDouble();
  }
  bufferGeometry = featureGeometry->buffer( currentBufferDistance, 5 );

  if ( dissolve )
  {
    if ( nProcessedFeatures == 0 )
    {
      *dissolveGeometry = bufferGeometry;
    }
    else
    {
      tmpGeometry = *dissolveGeometry;
      *dissolveGeometry = ( *dissolveGeometry )->combine( bufferGeometry );
      delete tmpGeometry;
      delete bufferGeometry;
    }
  }
  else //dissolve
  {
    QgsFeature newFeature;
    newFeature.setGeometry( bufferGeometry );
    newFeature.setAttributes( f.attributes() );

    //add it to vector file writer
    if ( vfw )
    {
      vfw->addFeature( newFeature );
    }
  }
}
QVariant QgsMergeAttributesDialog::featureAttribute( QgsFeatureId featureId, int fieldIdx )
{
  int i;
  for ( i = 0; i < mFeatureList.size() && mFeatureList.at( i ).id() != featureId; i++ )
    ;

  if ( i < mFeatureList.size() )
  {
    const QgsFeature f = mFeatureList.at( i );
    return f.attributes().at( fieldIdx );
  }

  return QVariant( mVectorLayer->fields().at( fieldIdx ).type() );
}
QgsFeatureList QgsMinimumEnclosingCircleAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
{
  QgsFeature f = feature;
  if ( f.hasGeometry() )
  {
    double radius = 0;
    QgsPointXY center;
    QgsGeometry outputGeometry = f.geometry().minimalEnclosingCircle( center, radius, mSegments );
    f.setGeometry( outputGeometry );
    QgsAttributes attrs = f.attributes();
    attrs << radius
          << M_PI *radius *radius;
    f.setAttributes( attrs );
  }
  else
  {
    QgsAttributes attrs = f.attributes();
    attrs << QVariant()
          << QVariant();
    f.setAttributes( attrs );
  }
  return QgsFeatureList() << f;
}
bool QgsVectorLayerEditBuffer::addFeature( QgsFeature& f )
{
  if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures ) )
  {
    return false;
  }
  if ( L->mUpdatedFields.count() != f.attributes().count() )
    return false;

  // TODO: check correct geometry type

  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
  return true;
}
QVariant QgsGraduatedSymbolRenderer::valueForFeature( QgsFeature &feature, QgsRenderContext &context ) const
{
  QgsAttributes attrs = feature.attributes();
  QVariant value;
  if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
  {
    value = mExpression->evaluate( &context.expressionContext() );
  }
  else
  {
    value = attrs.at( mAttrNum );
  }

  return value;
}
void QgsOverlayAnalyzer::intersectFeature( QgsFeature &f, QgsVectorFileWriter *vfw,
    QgsVectorLayer *vl, QgsSpatialIndex *index )
{
  if ( !f.hasGeometry() )
  {
    return;
  }

  QgsGeometry featureGeometry = f.geometry();
  QgsGeometry intersectGeometry;
  QgsFeature overlayFeature;

  QList<QgsFeatureId> intersects = index->intersects( featureGeometry.boundingBox() );
  QgsFeatureRequest req = QgsFeatureRequest().setFilterFids( intersects.toSet() );
  QgsFeatureIterator intersectIt = vl->getFeatures( req );
  QgsFeature outFeature;
  while ( intersectIt.nextFeature( overlayFeature ) )
  {
    if ( featureGeometry.intersects( overlayFeature.geometry() ) )
    {
      intersectGeometry = featureGeometry.intersection( overlayFeature.geometry() );

      outFeature.setGeometry( intersectGeometry );
      QgsAttributes attributesA = f.attributes();
      QgsAttributes attributesB = overlayFeature.attributes();
      combineAttributeMaps( attributesA, attributesB );
      outFeature.setAttributes( attributesA );

      //add it to vector file writer
      if ( vfw )
      {
        vfw->addFeature( outFeature );
      }
    }
  }
}
void QgsVectorLayerFeatureIterator::useAddedFeature( const QgsFeature& src, QgsFeature& f )
{
  f.setFeatureId( src.id() );
  f.setValid( true );
  f.setFields( &L->mUpdatedFields );

  if ( src.geometry() && !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) )
    f.setGeometry( *src.geometry() );

  // TODO[MD]: if subset set just some attributes

  f.setAttributes( src.attributes() );

  if ( !mFetchJoinInfo.isEmpty() )
    addJoinedAttributes( f );
}
bool QgsVectorLayerEditBuffer::addFeature( QgsFeature& f )
{
  if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures ) )
  {
    return false;
  }

  int layerFieldCount = L->dataProvider()->fields().count() + mAddedAttributes.count() - mDeletedAttributeIds.count();
  if ( layerFieldCount != f.attributes().count() )
    return false;

  // TODO: check correct geometry type

  L->undoStack()->push( new QgsVectorLayerUndoCommandAddFeature( this, f ) );
  return true;
}
QSizeF QgsHistogramDiagram::diagramSize( const QgsFeature& feature, const QgsRenderContext& c, const QgsDiagramSettings& s, const QgsDiagramInterpolationSettings& is )
{
  QSizeF size;
  if ( feature.attributes().isEmpty() )
  {
    return size; //zero size if no attributes
  }

  if ( qgsDoubleNear( is.upperValue, is.lowerValue ) )
    return size; // invalid value range => zero size

  double maxValue = 0;

  QgsExpressionContext expressionContext = c.expressionContext();
  expressionContext.setFeature( feature );
  if ( !feature.fields().isEmpty() )
    expressionContext.setFields( feature.fields() );

  Q_FOREACH ( const QString& cat, s.categoryAttributes )
  {
    QgsExpression* expression = getExpression( cat, expressionContext );
    maxValue = qMax( expression->evaluate( &expressionContext ).toDouble(), maxValue );
  }

  // Scale, if extension is smaller than the specified minimum
  if ( maxValue < s.minimumSize )
  {
    maxValue = s.minimumSize;
  }

  switch ( s.diagramOrientation )
  {
    case QgsDiagramSettings::Up:
    case QgsDiagramSettings::Down:
      mScaleFactor = (( is.upperSize.width() - is.lowerSize.height() ) / ( is.upperValue - is.lowerValue ) );
      size.scale( s.barWidth * s.categoryAttributes.size(), maxValue * mScaleFactor, Qt::IgnoreAspectRatio );
      break;

    case QgsDiagramSettings::Right:
    case QgsDiagramSettings::Left:
      mScaleFactor = (( is.upperSize.width() - is.lowerSize.width() ) / ( is.upperValue - is.lowerValue ) );
      size.scale( maxValue * mScaleFactor, s.barWidth * s.categoryAttributes.size(), Qt::IgnoreAspectRatio );
      break;
  }

  return size;
}
void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( QgsFeature& f, const QVariant& joinValue ) const
{
  // no memory cache, query the joined values by setting substring
  QString subsetString = joinLayer->dataProvider()->subsetString(); // provider might already have a subset string
  QString bkSubsetString = subsetString;
  if ( !subsetString.isEmpty() )
  {
    subsetString.append( " AND " );
  }

  QString joinFieldName;
  if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->pendingFields().count() )
    joinFieldName = joinLayer->pendingFields().field( joinInfo->joinFieldIndex ).name();   // for compatibility with 1.x
  else
    joinFieldName = joinInfo->joinFieldName;

  subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
  joinLayer->dataProvider()->setSubsetString( subsetString, false );

  // select (no geometry)
  QgsFeatureRequest request;
  request.setFlags( QgsFeatureRequest::NoGeometry );
  request.setSubsetOfAttributes( attributes );
  QgsFeatureIterator fi = joinLayer->getFeatures( request );

  // get first feature
  QgsFeature fet;
  if ( fi.nextFeature( fet ) )
  {
    int index = indexOffset;
    const QgsAttributes& attr = fet.attributes();
    for ( int i = 0; i < attr.count(); ++i )
    {
      if ( i == joinField )
        continue;

      f.setAttribute( index++, attr[i] );
    }
  }
  else
  {
    // no suitable join feature found, keeping empty (null) attributes
  }

  joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
}
void QgsFeatureAction::updateLastUsedValues( const QgsFeature& feature )
{
  QgsAttributeForm* form = qobject_cast<QgsAttributeForm*>( sender() );
  Q_ASSERT( form );

  QgsFields fields = mLayer->pendingFields();
  for ( int idx = 0; idx < fields.count(); ++idx )
  {
    const QgsAttributes &newValues = feature.attributes();
    QgsAttributeMap origValues = sLastUsedValues[ mLayer ];
    if ( origValues[idx] != newValues[idx] )
    {
      QgsDebugMsg( QString( "saving %1 for %2" ).arg( sLastUsedValues[ mLayer ][idx].toString() ).arg( idx ) );
      sLastUsedValues[ mLayer ][idx] = newValues[idx];
    }
  }
}
QVariant QgsCategorizedSymbolRendererV2::valueForFeature( QgsFeature& feature, QgsRenderContext &context ) const
{
  QgsAttributes attrs = feature.attributes();
  QVariant value;
  if ( mAttrNum == -1 )
  {
    Q_ASSERT( mExpression.data() );

    value = mExpression->evaluate( &context.expressionContext() );
  }
  else
  {
    value = attrs.value( mAttrNum );
  }

  return value;
}
bool QgsMapToolShowHideLabels::showHideLabel( QgsVectorLayer* vlayer,
    int fid,
    bool hide )
{

  // verify attribute table has proper field setup
  bool showSuccess;
  int showCol;
  int show;

  if ( !dataDefinedShowHide( vlayer, fid, show, showSuccess, showCol ) )
  {
    return false;
  }

  // check if attribute value is already the same
  QgsFeature f;
  if ( !vlayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
  {
    return false;
  }

  int colVal = hide ? 0 : 1;
  QVariant fQVal = f.attributes()[showCol];
  bool convToInt;
  int fVal = fQVal.toInt( &convToInt );

  if ( !convToInt || fVal == colVal )
  {
    return false;
  }

  // different attribute value, edit table
  QString labelText = currentLabelText( 24 );
  QString editTxt = hide ? tr( "Hid label" ) : tr( "Showed label" );
  vlayer->beginEditCommand( editTxt + QString( " '%1'" ).arg( labelText ) );
  if ( !vlayer->changeAttributeValue( fid, showCol, colVal, true ) )
  {
    QgsDebugMsg( "Failed write to attribute table" );
    vlayer->endEditCommand();
    return false;
  }
  vlayer->endEditCommand();
  return true;
}