Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport release-3_40] [vector layer] Fix newly-added features in the edit buffer prior to adding a new attribute will not save the new attribute's values #60310

Merged
merged 3 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ Update feature with uncommitted geometry updates
Update feature with uncommitted attribute updates
%End

void handleAttributeAdded( int index );
void handleAttributeAdded( int index, const QgsField &field );
%Docstring
Update added and changed features after addition of an attribute
%End
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ Update feature with uncommitted geometry updates
Update feature with uncommitted attribute updates
%End

void handleAttributeAdded( int index );
void handleAttributeAdded( int index, const QgsField &field );
%Docstring
Update added and changed features after addition of an attribute
%End
Expand Down
23 changes: 22 additions & 1 deletion src/core/vector/qgsvectorlayereditbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ bool QgsVectorLayerEditBuffer::changeAttributeValue( QgsFeatureId fid, int field
if ( field < 0 || field >= L->fields().count() ||
L->fields().fieldOrigin( field ) == Qgis::FieldOrigin::Join ||
L->fields().fieldOrigin( field ) == Qgis::FieldOrigin::Expression )
{
return false;
}

L->undoStack()->push( new QgsVectorLayerUndoCommandChangeAttribute( this, fid, field, newValue, oldValue ) );
return true;
Expand Down Expand Up @@ -503,7 +505,7 @@ QString QgsVectorLayerEditBuffer::dumpEditBuffer()
}
#endif

void QgsVectorLayerEditBuffer::handleAttributeAdded( int index )
void QgsVectorLayerEditBuffer::handleAttributeAdded( int index, const QgsField &field )
{
// go through the changed attributes map and adapt indices
QgsChangedAttributesMap::iterator it = mChangedAttributeValues.begin();
Expand All @@ -519,6 +521,21 @@ void QgsVectorLayerEditBuffer::handleAttributeAdded( int index )
QgsAttributes attrs = featureIt->attributes();
attrs.insert( index, QVariant() );
featureIt->setAttributes( attrs );
QgsFields fields;
const QgsFields oldFields = featureIt->fields();
for ( int i = 0; i < oldFields.size(); i++ )
{
if ( i == index )
{
fields.append( field, L->fields().fieldOrigin( L->fields().indexFromName( field.name() ) ) );
}
fields.append( oldFields.at( i ), oldFields.fieldOrigin( i ) );
}
if ( index == oldFields.size() )
{
fields.append( field, L->fields().fieldOrigin( L->fields().indexFromName( field.name() ) ) );
}
featureIt->setFields( fields, false );
}

// go through renamed attributes and adapt
Expand Down Expand Up @@ -559,6 +576,9 @@ void QgsVectorLayerEditBuffer::handleAttributeDeleted( int index )
QgsAttributes attrs = featureIt->attributes();
attrs.remove( index );
featureIt->setAttributes( attrs );
QgsFields fields = featureIt->fields();
fields.remove( index );
featureIt->setFields( fields, false );
}

// go through rename attributes and adapt
Expand Down Expand Up @@ -919,6 +939,7 @@ bool QgsVectorLayerEditBuffer::commitChangesAddFeatures( bool &featuresAdded, QS
// not be sent to the data provider. Refs #18784
for ( int i = 0; i < featuresToAdd.count(); ++i )
{
// Empty the feature's fields so the up-to-date fields from the data provider is used to match attributes
QgsVectorLayerUtils::matchAttributesToFields( featuresToAdd[i], L->dataProvider()->fields() );
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/vector/qgsvectorlayereditbuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
void updateChangedAttributes( QgsFeature &f );

//! Update added and changed features after addition of an attribute
void handleAttributeAdded( int index );
void handleAttributeAdded( int index, const QgsField &field );

//! Update added and changed features after removal of an attribute
void handleAttributeDeleted( int index );
Expand Down
4 changes: 2 additions & 2 deletions src/core/vector/qgsvectorlayerundocommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ void QgsVectorLayerUndoCommandAddAttribute::undo()
void QgsVectorLayerUndoCommandAddAttribute::redo()
{
mBuffer->mAddedAttributes.append( mField );
mBuffer->handleAttributeAdded( mFieldIndex );
mBuffer->handleAttributeAdded( mFieldIndex, mField );
mBuffer->updateLayerFields();

emit mBuffer->attributeAdded( mFieldIndex );
Expand Down Expand Up @@ -391,7 +391,7 @@ void QgsVectorLayerUndoCommandDeleteAttribute::undo()
}

mBuffer->updateLayerFields();
mBuffer->handleAttributeAdded( mFieldIndex ); // update changed attributes + new features
mBuffer->handleAttributeAdded( mFieldIndex, mOldField ); // update changed attributes + new features

if ( !mOldName.isEmpty() )
{
Expand Down
23 changes: 22 additions & 1 deletion tests/src/python/test_qgsvectorlayereditbuffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import os
from osgeo import gdal

from qgis.PyQt.QtCore import QTemporaryDir, QVariant
from qgis.PyQt.QtCore import QMetaType, QTemporaryDir, QVariant
from qgis.PyQt.QtTest import QSignalSpy
from qgis.core import (
Qgis,
Expand Down Expand Up @@ -856,6 +856,27 @@ def _check_feature(wkt):

_test(Qgis.TransactionMode.BufferedGroups)

def testAddNewFeatureAndNewAttribute(self):
layer = QgsVectorLayer("Point?field=fldtxt:string", "addfeat", "memory")
layer.startEditing()

# Add a new feature with fields information attached to it
f = QgsFeature(layer.fields())
f.setAttributes(["test"])
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
layer.addFeature(f)

# Add a new attribute to the layer
layer.addAttribute(QgsField("fldint", QMetaType.Type.Int))

# Change the newly-added attribute value for the new feature
layer.changeAttributeValue(f.id(), 1, 123)

# Commit changes
layer.commitChanges()

self.assertEqual(layer.getFeature(1).attributes(), ["test", 123])


if __name__ == "__main__":
unittest.main()
Loading