Fix up non-const getters for attributes and geometry in QgsFeature

(preparation for implicit sharing)
This commit is contained in:
Nyall Dawson 2015-05-20 21:43:53 +10:00
parent 73ed56af98
commit d393d268e1
33 changed files with 100 additions and 62 deletions

View File

@ -241,8 +241,8 @@ class QgsFeature
*/
void setFeatureId( qint64 id );
const QgsAttributes& attributes() const;
//QgsAttributes& attributes();
QgsAttributes attributes() const;
void setAttributes( const QgsAttributes& attrs );
/**
@ -312,26 +312,36 @@ class QgsFeature
/**
* Get the geometry object associated with this feature
*
* It is possible to modify the geometry in place but this will
* be removed in 3.0 and therefore @link setGeometry @endlink should be called explicitly.
*
* @note will be modified to return by value in QGIS 3.0: `QgsGeometry geometry() const;`
*/
QgsGeometry* geometry() const;
QgsGeometry* geometry();
/** Gets a const pointer to the geometry object associated with this feature
/** Gets a const pointer to the geometry object associated with this feature.
* @note this is a temporary method for 2.x release cycle. Will be removed in QGIS 3.0.
* @note added in QGIS 2.9
* @note will be removed in QGIS 3.0
*/
const QgsGeometry* constGeometry() const;
/**
* Get the geometry object associated with this feature
* The caller assumes responsibility for the QgsGeometry*'s destruction.
* @deprecated will be removed in QGIS 3.0
*/
QgsGeometry *geometryAndOwnership() /Factory/;
QgsGeometry *geometryAndOwnership() /Factory,Deprecated/;
/** Set this feature's geometry from another QgsGeometry object (deep copy)
*/
void setGeometry( const QgsGeometry& geom );
/** Set this feature's geometry (takes geometry ownership)
*
* @note not available in python bindings
* @deprecated will be removed in QGIS 3.0
*/
// void setGeometry( QgsGeometry* geom /Transfer/ );
@ -339,6 +349,8 @@ class QgsFeature
* Set this feature's geometry from WKB
*
* This feature assumes responsibility for destroying geom.
*
* @deprecated will be removed in QGIS 3.0
*/
void setGeometryAndOwnership( unsigned char * geom /Transfer/, size_t length );

View File

@ -5916,7 +5916,7 @@ void QgisApp::mergeAttributesOfSelectedFeatures()
vl->beginEditCommand( tr( "Merged feature attributes" ) );
const QgsAttributes &merged = d.mergedAttributes();
QgsAttributes merged = d.mergedAttributes();
foreach ( QgsFeatureId fid, vl->selectedFeaturesIds() )
{
@ -6232,7 +6232,7 @@ void QgisApp::editPaste( QgsMapLayer *destinationLayer )
QgsFeatureList::iterator featureIt = features.begin();
while ( featureIt != features.end() )
{
const QgsAttributes &srcAttr = featureIt->attributes();
QgsAttributes srcAttr = featureIt->attributes();
QgsAttributes dstAttr( dstAttrCount );
for ( int src = 0; src < srcAttr.count(); ++src )

View File

@ -99,7 +99,7 @@ void QgsClipboard::setSystemClipboard()
// then the field contents
for ( QgsFeatureList::iterator it = mFeatureClipboard.begin(); it != mFeatureClipboard.end(); ++it )
{
const QgsAttributes& attributes = it->attributes();
QgsAttributes attributes = it->attributes();
// TODO: Set up Paste Transformations to specify the order in which fields are added.
if ( copyWKT )

View File

@ -229,7 +229,7 @@ void QgsFeatureAction::onFeatureSaved( const QgsFeature& feature )
QgsFields fields = mLayer->pendingFields();
for ( int idx = 0; idx < fields.count(); ++idx )
{
const QgsAttributes &newValues = feature.attributes();
QgsAttributes newValues = feature.attributes();
QgsAttributeMap origValues = sLastUsedValues[ mLayer ];
if ( origValues[idx] != newValues[idx] )
{

View File

@ -455,7 +455,7 @@ void QgsIdentifyResultsDialog::addFeature( QgsVectorLayer *vlayer, const QgsFeat
}
const QgsFields &fields = vlayer->pendingFields();
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
bool featureLabeled = false;
for ( int i = 0; i < attrs.count(); ++i )
{
@ -719,7 +719,7 @@ void QgsIdentifyResultsDialog::addFeature( QgsRasterLayer *layer,
if ( feature.isValid() )
{
QgsDebugMsg( QString( "fields size = %1 attributes size = %2" ).arg( fields.size() ).arg( feature.attributes().size() ) );
const QgsAttributes& attrs = feature.attributes();
QgsAttributes attrs = feature.attributes();
for ( int i = 0; i < attrs.count(); ++i )
{
if ( i >= fields.count() )

View File

@ -69,7 +69,7 @@ void QgsLabelPropertyDialog::init( const QString& layerId, int featureId, const
{
return;
}
const QgsAttributes& attributeValues = mCurLabelFeat.attributes();
QgsAttributes attributeValues = mCurLabelFeat.attributes();
//get layerproperties. Problem: only for pallabeling...

View File

@ -483,7 +483,7 @@ bool QgsMapToolLabel::dataDefinedPosition( QgsVectorLayer* vlayer, const QgsFeat
return false;
}
const QgsAttributes& attributes = f.attributes();
QgsAttributes attributes = f.attributes();
if ( !attributes[xCol].isNull() )
x = attributes[xCol].toDouble( &xSuccess );
if ( !attributes[yCol].isNull() )

View File

@ -119,7 +119,7 @@ void QgsMergeAttributesDialog::createTableWidgetContents()
{
verticalHeaderLabels << FID_TO_STRING( mFeatureList[i].id() );
const QgsAttributes &attrs = mFeatureList[i].attributes();
QgsAttributes attrs = mFeatureList[i].attributes();
for ( int j = 0; j < mTableWidget->columnCount(); j++ )
{

View File

@ -109,7 +109,7 @@ void QgsFeature::deleteAttribute( int field )
}
QgsGeometry *QgsFeature::geometry() const
QgsGeometry *QgsFeature::geometry()
{
return mGeometry;
}
@ -257,9 +257,9 @@ QDataStream& operator<<( QDataStream& out, const QgsFeature& feature )
{
out << feature.id();
out << feature.attributes();
if ( feature.geometry() )
if ( feature.constGeometry() )
{
out << *( feature.geometry() );
out << *( feature.constGeometry() );
}
else
{
@ -275,9 +275,11 @@ QDataStream& operator>>( QDataStream& in, QgsFeature& feature )
QgsFeatureId id;
QgsGeometry* geometry = new QgsGeometry();
bool valid;
in >> id >> feature.attributes() >> *geometry >> valid;
QgsAttributes attr;
in >> id >> attr >> *geometry >> valid;
feature.setFeatureId( id );
feature.setGeometry( geometry );
feature.setAttributes( attr );
feature.setValid( valid );
return in;
}

View File

@ -144,8 +144,7 @@ class CORE_EXPORT QgsFeature
*/
void setFeatureId( QgsFeatureId id );
const QgsAttributes& attributes() const { return mAttributes; }
QgsAttributes& attributes() { return mAttributes; }
QgsAttributes attributes() const { return mAttributes; }
void setAttributes( const QgsAttributes& attrs ) { mAttributes = attrs; }
/**
@ -189,26 +188,36 @@ class CORE_EXPORT QgsFeature
/**
* Get the geometry object associated with this feature
*
* It is possible to modify the geometry in place but this will
* be removed in 3.0 and therefore @link setGeometry @endlink should be called explicitly.
*
* @note will be modified to return by value in QGIS 3.0: `QgsGeometry geometry() const;`
*/
QgsGeometry* geometry() const;
QgsGeometry* geometry();
/** Gets a const pointer to the geometry object associated with this feature
/** Gets a const pointer to the geometry object associated with this feature.
* @note this is a temporary method for 2.x release cycle. Will be removed in QGIS 3.0.
* @note added in QGIS 2.9
* @note will be removed in QGIS 3.0
*/
const QgsGeometry* constGeometry() const;
/**
* Get the geometry object associated with this feature
* The caller assumes responsibility for the QgsGeometry*'s destruction.
* @deprecated will be removed in QGIS 3.0
*/
QgsGeometry *geometryAndOwnership();
Q_DECL_DEPRECATED QgsGeometry *geometryAndOwnership();
/** Set this feature's geometry from another QgsGeometry object (deep copy)
*/
void setGeometry( const QgsGeometry& geom );
/** Set this feature's geometry (takes geometry ownership)
*
* @note not available in python bindings
* @deprecated will be removed in QGIS 3.0
*/
void setGeometry( QgsGeometry* geom );
@ -216,6 +225,8 @@ class CORE_EXPORT QgsFeature
* Set this feature's geometry from WKB
*
* This feature assumes responsibility for destroying geom.
*
* @deprecated will be removed in QGIS 3.0
*/
void setGeometryAndOwnership( unsigned char * geom, size_t length );

View File

@ -407,7 +407,7 @@ void QgsVectorDataProvider::fillMinMaxCache()
while ( fi.nextFeature( f ) )
{
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
{
const QVariant& varValue = attrs[*it];

View File

@ -980,8 +980,8 @@ bool QgsVectorLayer::updateFeature( QgsFeature &f )
}
}
const QgsAttributes &fa = f.attributes();
const QgsAttributes &ca = current.attributes();
QgsAttributes fa = f.attributes();
QgsAttributes ca = current.attributes();
for ( int attr = 0; attr < fa.count(); ++attr )
{

View File

@ -84,7 +84,7 @@ void QgsVectorLayerEditBuffer::updateFeatureGeometry( QgsFeature &f )
void QgsVectorLayerEditBuffer::updateChangedAttributes( QgsFeature &f )
{
QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
// remove all attributes that will disappear - from higher indices to lower
for ( int idx = mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
@ -102,6 +102,8 @@ void QgsVectorLayerEditBuffer::updateChangedAttributes( QgsFeature &f )
for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
attrs[it.key()] = it.value();
}
f.setAttributes( attrs );
}
@ -579,8 +581,9 @@ void QgsVectorLayerEditBuffer::handleAttributeAdded( int index )
QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
{
QgsAttributes& attrs = featureIt->attributes();
QgsAttributes attrs = featureIt->attributes();
attrs.insert( index, QVariant() );
featureIt->setAttributes( attrs );
}
}
@ -602,8 +605,9 @@ void QgsVectorLayerEditBuffer::handleAttributeDeleted( int index )
QgsFeatureMap::iterator featureIt = mAddedFeatures.begin();
for ( ; featureIt != mAddedFeatures.end(); ++featureIt )
{
QgsAttributes& attrs = featureIt->attributes();
QgsAttributes attrs = featureIt->attributes();
attrs.remove( index );
featureIt->setAttributes( attrs );
}
}

View File

@ -547,7 +547,9 @@ void QgsVectorLayerFeatureIterator::addJoinedAttributes( QgsFeature &f )
void QgsVectorLayerFeatureIterator::addVirtualAttributes( QgsFeature& f )
{
// make sure we have space for newly added attributes
f.attributes().resize( mSource->mFields.count() ); // Provider attrs count + joined attrs count + expression attrs count
QgsAttributes attr = f.attributes();
attr.resize( mSource->mFields.count() ); // Provider attrs count + joined attrs count + expression attrs count
f.setAttributes( attr );
if ( !mFetchJoinInfo.isEmpty() )
addJoinedAttributes( f );
@ -684,7 +686,7 @@ void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( Qg
if ( fi.nextFeature( fet ) )
{
int index = indexOffset;
const QgsAttributes& attr = fet.attributes();
QgsAttributes attr = fet.attributes();
if ( hasSubset )
{
for ( int i = 0; i < subsetIndices.count(); ++i )
@ -756,7 +758,7 @@ bool QgsVectorLayerFeatureIterator::nextFeatureFid( QgsFeature& f )
void QgsVectorLayerFeatureIterator::updateChangedAttributes( QgsFeature &f )
{
QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
// remove all attributes that will disappear - from higher indices to lower
for ( int idx = mSource->mDeletedAttributeIds.count() - 1; idx >= 0; --idx )
@ -774,6 +776,7 @@ void QgsVectorLayerFeatureIterator::updateChangedAttributes( QgsFeature &f )
for ( QgsAttributeMap::const_iterator it = map.begin(); it != map.end(); ++it )
attrs[it.key()] = it.value();
}
f.setAttributes( attrs );
}
void QgsVectorLayerFeatureIterator::updateFeatureGeometry( QgsFeature &f )

View File

@ -133,7 +133,7 @@ QString QgsVectorLayerImport::errorMessage()
bool QgsVectorLayerImport::addFeature( QgsFeature& feat )
{
const QgsAttributes &attrs = feat.attributes();
QgsAttributes attrs = feat.attributes();
QgsFeature newFeat;
if ( feat.constGeometry() )

View File

@ -152,7 +152,7 @@ void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
QgsFeature f;
while ( fit.nextFeature( f ) )
{
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
QString key = attrs[joinFieldIndex].toString();
if ( hasSubset )
{

View File

@ -237,7 +237,7 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
QgsSymbolV2* QgsCategorizedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature )
{
const QgsAttributes& attrs = feature.attributes();
QgsAttributes attrs = feature.attributes();
QVariant value;
if ( mAttrNum == -1 )
{

View File

@ -350,7 +350,7 @@ QgsSymbolV2* QgsGraduatedSymbolRendererV2::symbolForFeature( QgsFeature& feature
QgsSymbolV2* QgsGraduatedSymbolRendererV2::originalSymbolForFeature( QgsFeature& feature )
{
const QgsAttributes& attrs = feature.attributes();
QgsAttributes attrs = feature.attributes();
QVariant value;
if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
{

View File

@ -125,7 +125,7 @@ bool QgsHeatmapRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& c
}
else
{
const QgsAttributes& attrs = feature.attributes();
QgsAttributes attrs = feature.attributes();
value = attrs.value( mWeightAttrNum );
}
bool ok = false;

View File

@ -435,7 +435,7 @@ void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
{
QString attribute;
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
{
attribute = attrs[mLabelIndex].toString();

View File

@ -94,7 +94,7 @@ QWidget* QgsFormAnnotationItem::createDesignerWidget( const QString& filePath )
if ( mVectorLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeature ).setFlags( QgsFeatureRequest::NoGeometry ) ).nextFeature( f ) )
{
const QgsFields& fields = mVectorLayer->pendingFields();
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
for ( int i = 0; i < attrs.count(); ++i )
{
if ( i < fields.count() )

View File

@ -595,7 +595,7 @@ void eVisGenericEventBrowserGui::loadRecord()
QString myCompassOffsetField = cboxCompassOffsetField->currentText();
QString myEventImagePathField = cboxEventImagePathField->currentText();
const QgsFields& myFields = mDataProvider->fields();
const QgsAttributes& myAttrs = myFeature->attributes();
QgsAttributes myAttrs = myFeature->attributes();
//loop through the attributes and display their contents
for ( int i = 0; i < myAttrs.count(); ++i )
{
@ -842,7 +842,7 @@ void eVisGenericEventBrowserGui::on_cboxEventImagePathField_currentIndexChanged(
if ( 0 == myFeature )
return;
const QgsAttributes& myAttrs = myFeature->attributes();
QgsAttributes myAttrs = myFeature->attributes();
for ( int i = 0 ; i < myAttrs.count(); ++i )
{
if ( myFields[i].name() == cboxEventImagePathField->currentText() )
@ -870,7 +870,7 @@ void eVisGenericEventBrowserGui::on_cboxCompassBearingField_currentIndexChanged(
if ( 0 == myFeature )
return;
const QgsAttributes& myAttrs = myFeature->attributes();
QgsAttributes myAttrs = myFeature->attributes();
for ( int i = 0; i < myAttrs.count(); ++i )
{
if ( myFields[i].name() == cboxCompassBearingField->currentText() )
@ -898,7 +898,7 @@ void eVisGenericEventBrowserGui::on_cboxCompassOffsetField_currentIndexChanged(
if ( 0 == myFeature )
return;
const QgsAttributes& myAttrs = myFeature->attributes();
QgsAttributes myAttrs = myFeature->attributes();
for ( int i = 0; i < myAttrs.count(); ++i )
{
if ( myFields[i].name() == cboxCompassOffsetField->currentText() )

View File

@ -3740,7 +3740,7 @@ void QgsGrassModuleSelection::updateSelection()
if ( !selected.contains( feature.id() ) )
continue;
const QgsAttributes& attr = feature.attributes();
QgsAttributes attr = feature.attributes();
if ( attr.size() > keyField )
{
if ( i > 0 )

View File

@ -21,7 +21,7 @@ RgSpeedProperter::RgSpeedProperter( int attributeId, double defaultValue, double
QVariant RgSpeedProperter::property( double distance, const QgsFeature& f ) const
{
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
if ( mAttributeId < 0 || mAttributeId >= attrs.count() )
return QVariant( distance / ( mDefaultValue*mToMetricFactor ) );

View File

@ -219,7 +219,7 @@ bool QgsGPXProvider::addFeature( QgsFeature& f )
QGis::WkbType wkbType = f.constGeometry()->wkbType();
bool success = false;
QgsGPSObject* obj = NULL;
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
QgsAttributeMap::const_iterator it;
// is it a waypoint?

View File

@ -295,7 +295,9 @@ int main( int argc, char **argv )
QgsFeature& centroid = centroids[id];
if ( feature.geometry()->contains( centroid.geometry() ) )
{
centroid.attributes().append( feature.id() );
QgsAttributes attr = centroid.attributes();
attr.append( feature.id() );
centroid.setAttributes( attr );
}
}
}

View File

@ -355,7 +355,9 @@ bool QgsMemoryProvider::addAttributes( const QList<QgsField> &attributes )
for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
{
QgsFeature& f = fit.value();
f.attributes().append( QVariant() );
QgsAttributes attr = f.attributes();
attr.append( QVariant() );
f.setAttributes( attr );
}
}
return true;
@ -375,7 +377,9 @@ bool QgsMemoryProvider::deleteAttributes( const QgsAttributeIds& attributes )
for ( QgsFeatureMap::iterator fit = mFeatures.begin(); fit != mFeatures.end(); ++fit )
{
QgsFeature& f = fit.value();
f.attributes().remove( idx );
QgsAttributes attr = f.attributes();
attr.remove( idx );
f.setAttributes( attr );
}
}
return true;

View File

@ -765,7 +765,7 @@ bool QgsMssqlProvider::addFeatures( QgsFeatureList & flist )
QSqlQuery query = QSqlQuery( mDatabase );
query.setForwardOnly( true );
const QgsAttributes& attrs = it->attributes();
QgsAttributes attrs = it->attributes();
for ( int i = 0; i < attrs.count(); ++i )
{

View File

@ -993,7 +993,7 @@ bool QgsOgrProvider::addFeature( QgsFeature& f )
}
}
const QgsAttributes& attrs = f.attributes();
QgsAttributes attrs = f.attributes();
char *oldlocale = setlocale( LC_NUMERIC, NULL );
if ( oldlocale )

View File

@ -1203,7 +1203,7 @@ bool QgsOracleProvider::addFeatures( QgsFeatureList &flist )
}
}
const QgsAttributes &attributevec = flist[0].attributes();
QgsAttributes attributevec = flist[0].attributes();
// look for unique attribute values to place in statement instead of passing as parameter
// e.g. for defaults
@ -1226,7 +1226,7 @@ bool QgsOracleProvider::addFeatures( QgsFeatureList &flist )
int i;
for ( i = 1; i < flist.size(); i++ )
{
const QgsAttributes &attributevec = flist[i].attributes();
QgsAttributes attributevec = flist[i].attributes();
QVariant v2 = attributevec[idx];
if ( !v2.isValid() )
@ -1283,7 +1283,7 @@ bool QgsOracleProvider::addFeatures( QgsFeatureList &flist )
for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); ++features )
{
const QgsAttributes &attributevec = features->attributes();
QgsAttributes attributevec = features->attributes();
QgsDebugMsg( QString( "insert feature %1" ).arg( features->id() ) );
@ -1340,7 +1340,7 @@ bool QgsOracleProvider::addFeatures( QgsFeatureList &flist )
{
for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); ++features )
{
const QgsAttributes &attributevec = features->attributes();
QgsAttributes attributevec = features->attributes();
if ( mPrimaryKeyType == pktInt )
{

View File

@ -1664,7 +1664,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
}
}
const QgsAttributes &attributevec = flist[0].attributes();
QgsAttributes attributevec = flist[0].attributes();
// look for unique attribute values to place in statement instead of passing as parameter
// e.g. for defaults
@ -1688,7 +1688,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
int i;
for ( i = 1; i < flist.size(); i++ )
{
const QgsAttributes &attrs2 = flist[i].attributes();
QgsAttributes attrs2 = flist[i].attributes();
QVariant v2 = attrs2[idx];
if ( v2 != v )
@ -1768,7 +1768,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); ++features )
{
const QgsAttributes &attrs = features->attributes();
QgsAttributes attrs = features->attributes();
QStringList params;
if ( !mGeometryColumn.isNull() )
@ -1817,7 +1817,7 @@ bool QgsPostgresProvider::addFeatures( QgsFeatureList &flist )
{
for ( QgsFeatureList::iterator features = flist.begin(); features != flist.end(); ++features )
{
const QgsAttributes &attrs = features->attributes();
QgsAttributes attrs = features->attributes();
if ( mPrimaryKeyType == pktInt )
{

View File

@ -3549,7 +3549,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
if ( flist.size() == 0 )
return true;
const QgsAttributes & attributevec = flist[0].attributes();
QgsAttributes attributevec = flist[0].attributes();
ret = sqlite3_exec( sqliteHandle, "BEGIN", NULL, NULL, &errMsg );
if ( ret == SQLITE_OK )
@ -3594,7 +3594,7 @@ bool QgsSpatiaLiteProvider::addFeatures( QgsFeatureList & flist )
for ( QgsFeatureList::iterator feature = flist.begin(); feature != flist.end(); ++feature )
{
// looping on each feature to insert
const QgsAttributes& attributevec = feature->attributes();
QgsAttributes attributevec = feature->attributes();
// resetting Prepared Statement and bindings
sqlite3_reset( stmt );

View File

@ -154,7 +154,7 @@ void TestQgsFeature::attributes()
//test implicit sharing detachment
QgsFeature copy( feature );
QCOMPARE( copy.attributes(), feature.attributes() );
copy.attributes().clear();
copy.setAttributes( QgsAttributes() );
QVERIFY( copy.attributes().isEmpty() );
QCOMPARE( feature.attributes(), mAttrs );