From d5580772208010c897cc44a75214b36d07254903 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 12 Oct 2016 18:32:47 +1000 Subject: [PATCH] Fix renaming a virtual field leads to crash (fix #15669) (cherry-picked from 3a76708bcb4785f5fe930be0b18396e5fa87031f) --- python/core/qgsexpressionfieldbuffer.sip | 10 +++++++ src/core/qgsexpressionfieldbuffer.cpp | 5 ++++ src/core/qgsexpressionfieldbuffer.h | 10 +++++++ src/core/qgsvectorlayer.cpp | 35 ++++++++++++++++++++++-- tests/src/python/test_qgsvectorlayer.py | 10 +++++++ 5 files changed, 67 insertions(+), 3 deletions(-) diff --git a/python/core/qgsexpressionfieldbuffer.sip b/python/core/qgsexpressionfieldbuffer.sip index dfa3aee5e8fb..8bceb4a67db4 100644 --- a/python/core/qgsexpressionfieldbuffer.sip +++ b/python/core/qgsexpressionfieldbuffer.sip @@ -27,6 +27,16 @@ class QgsExpressionFieldBuffer */ void removeExpression( int index ); + /** + * Renames an expression field at a given index + * + * @param index The index of the expression to change + * @param name New name for field + * + * @note added in 3.0 + */ + void renameExpression( int index, const QString& name ); + /** * Changes the expression at a given index * diff --git a/src/core/qgsexpressionfieldbuffer.cpp b/src/core/qgsexpressionfieldbuffer.cpp index 2da260254c62..5ded28d14e3f 100644 --- a/src/core/qgsexpressionfieldbuffer.cpp +++ b/src/core/qgsexpressionfieldbuffer.cpp @@ -33,6 +33,11 @@ void QgsExpressionFieldBuffer::removeExpression( int index ) mExpressions.removeAt( index ); } +void QgsExpressionFieldBuffer::renameExpression( int index, const QString& name ) +{ + mExpressions[index].field.setName( name ); +} + void QgsExpressionFieldBuffer::updateExpression( int index, const QString& exp ) { mExpressions[index].expression = exp; diff --git a/src/core/qgsexpressionfieldbuffer.h b/src/core/qgsexpressionfieldbuffer.h index 0d47fc0552a5..0cecbb8b671a 100644 --- a/src/core/qgsexpressionfieldbuffer.h +++ b/src/core/qgsexpressionfieldbuffer.h @@ -67,6 +67,16 @@ class CORE_EXPORT QgsExpressionFieldBuffer */ void removeExpression( int index ); + /** + * Renames an expression field at a given index + * + * @param index The index of the expression to change + * @param name New name for field + * + * @note added in 3.0 + */ + void renameExpression( int index, const QString& name ); + /** * Changes the expression at a given index * diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index cd6cb636ed68..f06f9c93323f 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -2405,12 +2405,41 @@ void QgsVectorLayer::remAttributeAlias( int attIndex ) } } -bool QgsVectorLayer::renameAttribute( int attIndex, const QString& newName ) +bool QgsVectorLayer::renameAttribute( int index, const QString& newName ) { - if ( !mEditBuffer || !mDataProvider ) + if ( index < 0 || index >= fields().count() ) return false; - return mEditBuffer->renameAttribute( attIndex, newName ); + switch ( mUpdatedFields.fieldOrigin( index ) ) + { + case QgsFields::OriginExpression: + { + if ( mExpressionFieldBuffer ) + { + int oi = mUpdatedFields.fieldOriginIndex( index ); + mExpressionFieldBuffer->renameExpression( oi, newName ); + updateFields(); + return true; + } + else + { + return false; + } + } + + case QgsFields::OriginProvider: + case QgsFields::OriginEdit: + + if ( !mEditBuffer || !mDataProvider ) + return false; + + return mEditBuffer->renameAttribute( index, newName ); + + case QgsFields::OriginJoin: + case QgsFields::OriginUnknown: + return false; + + } } void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString ) diff --git a/tests/src/python/test_qgsvectorlayer.py b/tests/src/python/test_qgsvectorlayer.py index 81c1c10941ff..747e64809c2b 100644 --- a/tests/src/python/test_qgsvectorlayer.py +++ b/tests/src/python/test_qgsvectorlayer.py @@ -1033,6 +1033,16 @@ def checkFieldNames(names): #layer.undoStack().redo() #checkFieldNames(['fldint']) + def test_RenameExpressionField(self): + layer = createLayerWithOnePoint() + exp_field_idx = layer.addExpressionField('1+1', QgsField('math_is_hard', QVariant.Int)) + + #rename and check + self.assertTrue(layer.renameAttribute(exp_field_idx, 'renamed')) + self.assertEqual(layer.fields()[exp_field_idx].name(), 'renamed') + f = next(layer.getFeatures()) + self.assertEqual(f.fields()[exp_field_idx].name(), 'renamed') + def test_fields(self): layer = createLayerWithOnePoint()