Add support for field renaming in QgsVectorLayer and edit buffer

This commit is contained in:
Nyall Dawson 2016-05-31 10:05:54 +10:00
parent ccc67ef7a5
commit 0e03115d33
13 changed files with 570 additions and 1 deletions

View File

@ -941,6 +941,13 @@ class QgsVectorLayer : QgsMapLayer
/** Removes an alias (a display name) for attributes to display in dialogs */
void remAttributeAlias( int attIndex );
/** Renames an attribute field (but does not commit it).
* @param attIndex attribute index
* @param newName new name of field
* @note added in QGIS 2.16
*/
bool renameAttribute( int attIndex, const QString& newName );
/**
* Adds a tab (for the attribute editor form) holding groups and fields
*

View File

@ -43,6 +43,12 @@ class QgsVectorLayerEditBuffer : QObject
/** Delete an attribute field (but does not commit it) */
virtual bool deleteAttribute( int attr );
/** Renames an attribute field (but does not commit it)
* @param attr attribute index
* @param newName new name of field
* @note added in QGIS 2.16
*/
virtual bool renameAttribute( int attr, const QString& newName );
/**
Attempts to commit any changes to disk. Returns the result of the attempt.
@ -98,10 +104,25 @@ class QgsVectorLayerEditBuffer : QObject
void attributeAdded( int idx );
void attributeDeleted( int idx );
/** Emitted when an attribute has been renamed
* @param idx attribute index
* @param newName new attribute name
* @note added in QGSI 2.16
*/
void attributeRenamed( int idx, const QString& newName );
/** Signals emitted after committing changes */
void committedAttributesDeleted( const QString& layerId, const QgsAttributeList& deletedAttributes );
void committedAttributesAdded( const QString& layerId, const QList<QgsField>& addedAttributes );
void committedFeaturesAdded( const QString& layerId, const QgsFeatureList& addedFeatures );
/** Emitted after committing an attribute rename
* @param layerId ID of layer
* @param renamedAttributes map of field index to new name
* @note added in QGIS 2.16
*/
void committedAttributesRenamed( const QString& layerId, const QgsFieldNameMap& renamedAttributes );
void committedFeaturesRemoved( const QString& layerId, const QgsFeatureIds& deletedFeatureIds );
void committedAttributeValuesChanges( const QString& layerId, const QgsChangedAttributesMap& changedAttributesValues );
void committedGeometriesChanges( const QString& layerId, const QgsGeometryMap& changedGeometries );

View File

@ -14,6 +14,7 @@ class QgsVectorLayerEditPassthrough : QgsVectorLayerEditBuffer
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant() );
bool addAttribute( const QgsField &field );
bool deleteAttribute( int attr );
bool renameAttribute( int attr, const QString& newName );
bool commitChanges( QStringList& commitErrors );
void rollBack();

View File

@ -1,10 +1,21 @@
/** \ingroup core
* \class QgsVectorLayerUndoCommand
* \brief Base class for undo commands within a QgsVectorLayerEditBuffer.
*/
class QgsVectorLayerUndoCommand : QUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommand
* @param buffer associated edit buffer
*/
QgsVectorLayerUndoCommand( QgsVectorLayerEditBuffer *buffer /Transfer/ );
//! Returns the layer associated with the undo command
QgsVectorLayer *layer();
QgsGeometryCache *cache();
@ -13,12 +24,22 @@ class QgsVectorLayerUndoCommand : QUndoCommand
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandAddFeature
* \brief Undo command for adding a feature to a vector layer.
*/
class QgsVectorLayerUndoCommandAddFeature : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandAddFeature
* @param buffer associated edit buffer
* @param f feature to add to layer
*/
QgsVectorLayerUndoCommandAddFeature( QgsVectorLayerEditBuffer* buffer /Transfer/, QgsFeature& f );
virtual void undo();
@ -26,12 +47,22 @@ class QgsVectorLayerUndoCommandAddFeature : QgsVectorLayerUndoCommand
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandDeleteFeature
* \brief Undo command for deleting a feature from a vector layer.
*/
class QgsVectorLayerUndoCommandDeleteFeature : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandDeleteFeature
* @param buffer associated edit buffer
* @param fid feature ID of feature to delete from layer
*/
QgsVectorLayerUndoCommandDeleteFeature( QgsVectorLayerEditBuffer* buffer /Transfer/, QgsFeatureId fid );
virtual void undo();
@ -39,12 +70,23 @@ class QgsVectorLayerUndoCommandDeleteFeature : QgsVectorLayerUndoCommand
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandChangeGeometry
* \brief Undo command for modifying the geometry of a feature from a vector layer.
*/
class QgsVectorLayerUndoCommandChangeGeometry : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandChangeGeometry
* @param buffer associated edit buffer
* @param fid feature ID of feature to modify geometry of
* @param newGeom new geometry for feature
*/
QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer* buffer /Transfer/, QgsFeatureId fid, QgsGeometry* newGeom /Transfer/ );
~QgsVectorLayerUndoCommandChangeGeometry();
@ -55,24 +97,47 @@ class QgsVectorLayerUndoCommandChangeGeometry : QgsVectorLayerUndoCommand
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandChangeAttribute
* \brief Undo command for modifying an attribute of a feature from a vector layer.
*/
class QgsVectorLayerUndoCommandChangeAttribute : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandChangeAttribute
* @param buffer associated edit buffer
* @param fid feature ID of feature to modify
* @param fieldIndex index of field to modify
* @param newValue new value of attribute
* @param oldValue previous value of attribute
*/
QgsVectorLayerUndoCommandChangeAttribute( QgsVectorLayerEditBuffer* buffer /Transfer/, QgsFeatureId fid, int fieldIndex, const QVariant &newValue, const QVariant &oldValue );
virtual void undo();
virtual void redo();
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandAddAttribute
* \brief Undo command for adding a new attribute to a vector layer.
*/
class QgsVectorLayerUndoCommandAddAttribute : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandAddAttribute
* @param buffer associated edit buffer
* @param field definition of new field to add
*/
QgsVectorLayerUndoCommandAddAttribute( QgsVectorLayerEditBuffer* buffer /Transfer/, const QgsField& field );
virtual void undo();
@ -80,15 +145,51 @@ class QgsVectorLayerUndoCommandAddAttribute : QgsVectorLayerUndoCommand
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandDeleteAttribute
* \brief Undo command for removing an existing attribute from a vector layer.
*/
class QgsVectorLayerUndoCommandDeleteAttribute : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandDeleteAttribute
* @param buffer associated edit buffer
* @param fieldIndex index of field to delete
*/
QgsVectorLayerUndoCommandDeleteAttribute( QgsVectorLayerEditBuffer* buffer /Transfer/, int fieldIndex );
virtual void undo();
virtual void redo();
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandRenameAttribute
* \brief Undo command for renaming an existing attribute of a vector layer.
* \note added in QGIS 2.16
*/
class QgsVectorLayerUndoCommandRenameAttribute : QgsVectorLayerUndoCommand
{
%TypeHeaderCode
#include "qgsvectorlayerundocommand.h"
%End
public:
/** Constructor for QgsVectorLayerUndoCommandRenameAttribute
* @param buffer associated edit buffer
* @param fieldIndex index of field to rename
* @param newName new name for field
*/
QgsVectorLayerUndoCommandRenameAttribute( QgsVectorLayerEditBuffer* buffer /Transfer/, int fieldIndex, const QString& newName );
virtual void undo();
virtual void redo();
};

View File

@ -2360,6 +2360,14 @@ void QgsVectorLayer::remAttributeAlias( int attIndex )
}
}
bool QgsVectorLayer::renameAttribute( int attIndex, const QString& newName )
{
if ( !mEditBuffer || !mDataProvider )
return false;
return mEditBuffer->renameAttribute( attIndex, newName );
}
void QgsVectorLayer::addAttributeAlias( int attIndex, const QString& aliasString )
{
if ( attIndex < 0 || attIndex >= fields().count() )

View File

@ -1316,6 +1316,13 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Removes an alias (a display name) for attributes to display in dialogs */
void remAttributeAlias( int attIndex );
/** Renames an attribute field (but does not commit it).
* @param attIndex attribute index
* @param newName new name of field
* @note added in QGIS 2.16
*/
bool renameAttribute( int attIndex, const QString& newName );
/**
* Adds a tab (for the attribute editor form) holding groups and fields
*

View File

@ -72,6 +72,12 @@ void QgsVectorLayerEditBuffer::updateFields( QgsFields& fields )
{
fields.append( mAddedAttributes[i], QgsFields::OriginEdit, i );
}
// rename fields
QgsFieldNameMap::const_iterator renameIt = mRenamedAttributes.constBegin();
for ( ; renameIt != mRenamedAttributes.constEnd(); ++renameIt )
{
fields[ renameIt.key()].setName( renameIt.value() );
}
}
@ -261,6 +267,27 @@ bool QgsVectorLayerEditBuffer::deleteAttribute( int index )
return true;
}
bool QgsVectorLayerEditBuffer::renameAttribute( int index, const QString& newName )
{
if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::RenameAttributes ) )
return false;
if ( newName.isEmpty() )
return false;
if ( index < 0 || index >= L->fields().count() )
return false;
Q_FOREACH ( const QgsField& updatedField, L->fields() )
{
if ( updatedField.name() == newName )
return false;
}
L->undoStack()->push( new QgsVectorLayerUndoCommandRenameAttribute( this, index, newName ) );
return true;
}
bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
{
@ -355,6 +382,25 @@ bool QgsVectorLayerEditBuffer::commitChanges( QStringList& commitErrors )
}
}
// rename attributes
if ( !mRenamedAttributes.isEmpty() )
{
if (( cap & QgsVectorDataProvider::RenameAttributes ) && provider->renameAttributes( mRenamedAttributes ) )
{
commitErrors << tr( "SUCCESS: %n attribute(s) renamed.", "renamed attributes count", mRenamedAttributes.size() );
emit committedAttributesRenamed( L->id(), mRenamedAttributes );
mRenamedAttributes.clear();
attributesChanged = true;
}
else
{
commitErrors << tr( "ERROR: %n attribute(s) not renamed", "not renamed attributes count", mRenamedAttributes.size() );
success = false;
}
}
//
// check that addition/removal went as expected
//
@ -620,6 +666,20 @@ void QgsVectorLayerEditBuffer::handleAttributeAdded( int index )
attrs.insert( index, QVariant() );
featureIt->setAttributes( attrs );
}
// go through renamed attributes and adapt
QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
//sort keys
qSort( sortedRenamedIndices.begin(), sortedRenamedIndices.end(), qGreater< int >() );
Q_FOREACH ( int renameIndex, sortedRenamedIndices )
{
if ( renameIndex >= index )
{
mRenamedAttributes[ renameIndex + 1 ] = mRenamedAttributes.value( renameIndex );
}
}
//remove last
mRenamedAttributes.remove( index );
}
void QgsVectorLayerEditBuffer::handleAttributeDeleted( int index )
@ -645,6 +705,24 @@ void QgsVectorLayerEditBuffer::handleAttributeDeleted( int index )
attrs.remove( index );
featureIt->setAttributes( attrs );
}
// go through rename attributes and adapt
QList< int > sortedRenamedIndices = mRenamedAttributes.keys();
//sort keys
qSort( sortedRenamedIndices.begin(), sortedRenamedIndices.end() );
int last = -1;
mRenamedAttributes.remove( index );
Q_FOREACH ( int renameIndex, sortedRenamedIndices )
{
if ( renameIndex > index )
{
mRenamedAttributes.insert( renameIndex - 1, mRenamedAttributes.value( renameIndex ) );
last = renameIndex;
}
}
//remove last
if ( last > -1 )
mRenamedAttributes.remove( last );
}

View File

@ -69,6 +69,12 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
/** Delete an attribute field (but does not commit it) */
virtual bool deleteAttribute( int attr );
/** Renames an attribute field (but does not commit it)
* @param attr attribute index
* @param newName new name of field
* @note added in QGIS 2.16
*/
virtual bool renameAttribute( int attr, const QString& newName );
/**
Attempts to commit any changes to disk. Returns the result of the attempt.
@ -124,9 +130,23 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
void attributeAdded( int idx );
void attributeDeleted( int idx );
/** Emitted when an attribute has been renamed
* @param idx attribute index
* @param newName new attribute name
* @note added in QGSI 2.16
*/
void attributeRenamed( int idx, const QString& newName );
/** Signals emitted after committing changes */
void committedAttributesDeleted( const QString& layerId, const QgsAttributeList& deletedAttributes );
void committedAttributesAdded( const QString& layerId, const QList<QgsField>& addedAttributes );
/** Emitted after committing an attribute rename
* @param layerId ID of layer
* @param renamedAttributes map of field index to new name
* @note added in QGIS 2.16
*/
void committedAttributesRenamed( const QString& layerId, const QgsFieldNameMap& renamedAttributes );
void committedFeaturesAdded( const QString& layerId, const QgsFeatureList& addedFeatures );
void committedFeaturesRemoved( const QString& layerId, const QgsFeatureIds& deletedFeatureIds );
void committedAttributeValuesChanges( const QString& layerId, const QgsChangedAttributesMap& changedAttributesValues );
@ -150,7 +170,6 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
/** Update added and changed features after removal of an attribute */
void handleAttributeDeleted( int index );
/** Updates an index in an attribute map to a new value (for updates of changed attributes) */
void updateAttributeMapIndex( QgsAttributeMap& attrs, int index, int offset ) const;
@ -167,6 +186,7 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
friend class QgsVectorLayerUndoCommandChangeAttribute;
friend class QgsVectorLayerUndoCommandAddAttribute;
friend class QgsVectorLayerUndoCommandDeleteAttribute;
friend class QgsVectorLayerUndoCommandRenameAttribute;
/** Deleted feature IDs which are not commited. Note a feature can be added and then deleted
again before the change is committed - in that case the added feature would be removed
@ -186,6 +206,9 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject
/** Added attributes fields which are not commited */
QList<QgsField> mAddedAttributes;
/** Renamed attributes which are not commited. */
QgsFieldNameMap mRenamedAttributes;
/** Changed geometries which are not commited. */
QgsGeometryMap mChangedGeometries;
};

View File

@ -133,6 +133,19 @@ bool QgsVectorLayerEditPassthrough::deleteAttribute( int attr )
return false;
}
bool QgsVectorLayerEditPassthrough::renameAttribute( int attr, const QString& newName )
{
QgsFieldNameMap map;
map[ attr ] = newName;
if ( L->dataProvider()->renameAttributes( map ) )
{
mModified = true;
emit attributeRenamed( attr, newName );
return true;
}
return false;
}
bool QgsVectorLayerEditPassthrough::commitChanges( QStringList& /*commitErrors*/ )
{
mModified = false;

View File

@ -33,6 +33,7 @@ class CORE_EXPORT QgsVectorLayerEditPassthrough : public QgsVectorLayerEditBuffe
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant() ) override;
bool addAttribute( const QgsField &field ) override;
bool deleteAttribute( int attr ) override;
bool renameAttribute( int attr, const QString& newName ) override;
bool commitChanges( QStringList& commitErrors ) override;
void rollBack() override;

View File

@ -355,6 +355,11 @@ QgsVectorLayerUndoCommandDeleteAttribute::QgsVectorLayerUndoCommandDeleteAttribu
mOldField = mBuffer->mAddedAttributes[mOriginIndex];
}
if ( mBuffer->mRenamedAttributes.contains( fieldIndex ) )
{
mOldName = mBuffer->mRenamedAttributes.value( fieldIndex );
}
// save values of new features
for ( QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constBegin(); it != mBuffer->mAddedFeatures.constEnd(); ++it )
{
@ -386,6 +391,12 @@ void QgsVectorLayerUndoCommandDeleteAttribute::undo()
mBuffer->updateLayerFields();
mBuffer->handleAttributeAdded( mFieldIndex ); // update changed attributes + new features
if ( !mOldName.isEmpty() )
{
mBuffer->mRenamedAttributes[ mFieldIndex ] = mOldName;
mBuffer->updateLayerFields();
}
// set previously used attributes of new features
for ( QgsFeatureMap::iterator it = mBuffer->mAddedFeatures.begin(); it != mBuffer->mAddedFeatures.end(); ++it )
{
@ -425,3 +436,26 @@ void QgsVectorLayerUndoCommandDeleteAttribute::redo()
mBuffer->updateLayerFields();
emit mBuffer->attributeDeleted( mFieldIndex );
}
QgsVectorLayerUndoCommandRenameAttribute::QgsVectorLayerUndoCommandRenameAttribute( QgsVectorLayerEditBuffer* buffer, int fieldIndex, const QString& newName )
: QgsVectorLayerUndoCommand( buffer )
, mFieldIndex( fieldIndex )
, mOldName( layer()->fields().at( fieldIndex ).name() )
, mNewName( newName )
{
}
void QgsVectorLayerUndoCommandRenameAttribute::undo()
{
mBuffer->mRenamedAttributes[ mFieldIndex ] = mOldName;
mBuffer->updateLayerFields();
emit mBuffer->attributeRenamed( mFieldIndex, mOldName );
}
void QgsVectorLayerUndoCommandRenameAttribute::redo()
{
mBuffer->mRenamedAttributes[ mFieldIndex ] = mNewName;
mBuffer->updateLayerFields();
emit mBuffer->attributeRenamed( mFieldIndex, mNewName );
}

View File

@ -31,14 +31,24 @@ class QgsGeometryCache;
#include "qgsvectorlayer.h"
#include "qgsvectorlayereditbuffer.h"
/** \ingroup core
* \class QgsVectorLayerUndoCommand
* \brief Base class for undo commands within a QgsVectorLayerEditBuffer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommand : public QUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommand
* @param buffer associated edit buffer
*/
QgsVectorLayerUndoCommand( QgsVectorLayerEditBuffer *buffer )
: QUndoCommand()
, mBuffer( buffer )
{}
//! Returns the layer associated with the undo command
inline QgsVectorLayer *layer() { return mBuffer->L; }
inline QgsGeometryCache *cache() { return mBuffer->L->cache(); }
@ -46,13 +56,24 @@ class CORE_EXPORT QgsVectorLayerUndoCommand : public QUndoCommand
virtual bool mergeWith( const QUndoCommand * ) override { return false; }
protected:
//! Associated edit buffer
QgsVectorLayerEditBuffer* mBuffer;
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandAddFeature
* \brief Undo command for adding a feature to a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandAddFeature : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandAddFeature
* @param buffer associated edit buffer
* @param f feature to add to layer
*/
QgsVectorLayerUndoCommandAddFeature( QgsVectorLayerEditBuffer* buffer, QgsFeature& f );
virtual void undo() override;
@ -63,9 +84,19 @@ class CORE_EXPORT QgsVectorLayerUndoCommandAddFeature : public QgsVectorLayerUnd
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandDeleteFeature
* \brief Undo command for deleting a feature from a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandDeleteFeature : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandDeleteFeature
* @param buffer associated edit buffer
* @param fid feature ID of feature to delete from layer
*/
QgsVectorLayerUndoCommandDeleteFeature( QgsVectorLayerEditBuffer* buffer, QgsFeatureId fid );
virtual void undo() override;
@ -76,10 +107,20 @@ class CORE_EXPORT QgsVectorLayerUndoCommandDeleteFeature : public QgsVectorLayer
QgsFeature mOldAddedFeature;
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandChangeGeometry
* \brief Undo command for modifying the geometry of a feature from a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandChangeGeometry : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandChangeGeometry
* @param buffer associated edit buffer
* @param fid feature ID of feature to modify geometry of
* @param newGeom new geometry for feature
*/
QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer* buffer, QgsFeatureId fid, QgsGeometry* newGeom );
~QgsVectorLayerUndoCommandChangeGeometry();
@ -95,9 +136,22 @@ class CORE_EXPORT QgsVectorLayerUndoCommandChangeGeometry : public QgsVectorLaye
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandChangeAttribute
* \brief Undo command for modifying an attribute of a feature from a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandChangeAttribute : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandChangeAttribute
* @param buffer associated edit buffer
* @param fid feature ID of feature to modify
* @param fieldIndex index of field to modify
* @param newValue new value of attribute
* @param oldValue previous value of attribute
*/
QgsVectorLayerUndoCommandChangeAttribute( QgsVectorLayerEditBuffer* buffer, QgsFeatureId fid, int fieldIndex, const QVariant &newValue, const QVariant &oldValue );
virtual void undo() override;
virtual void redo() override;
@ -110,10 +164,19 @@ class CORE_EXPORT QgsVectorLayerUndoCommandChangeAttribute : public QgsVectorLay
bool mFirstChange;
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandAddAttribute
* \brief Undo command for adding a new attribute to a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandAddAttribute : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandAddAttribute
* @param buffer associated edit buffer
* @param field definition of new field to add
*/
QgsVectorLayerUndoCommandAddAttribute( QgsVectorLayerEditBuffer* buffer, const QgsField& field );
virtual void undo() override;
@ -124,10 +187,19 @@ class CORE_EXPORT QgsVectorLayerUndoCommandAddAttribute : public QgsVectorLayerU
int mFieldIndex;
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandDeleteAttribute
* \brief Undo command for removing an existing attribute from a vector layer.
*/
class CORE_EXPORT QgsVectorLayerUndoCommandDeleteAttribute : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandDeleteAttribute
* @param buffer associated edit buffer
* @param fieldIndex index of field to delete
*/
QgsVectorLayerUndoCommandDeleteAttribute( QgsVectorLayerEditBuffer* buffer, int fieldIndex );
virtual void undo() override;
@ -141,6 +213,34 @@ class CORE_EXPORT QgsVectorLayerUndoCommandDeleteAttribute : public QgsVectorLay
QgsEditorWidgetConfig mOldEditorWidgetConfig;
QMap<QgsFeatureId, QVariant> mDeletedValues;
QString mOldName;
};
/** \ingroup core
* \class QgsVectorLayerUndoCommandRenameAttribute
* \brief Undo command for renaming an existing attribute of a vector layer.
* \note added in QGIS 2.16
*/
class CORE_EXPORT QgsVectorLayerUndoCommandRenameAttribute : public QgsVectorLayerUndoCommand
{
public:
/** Constructor for QgsVectorLayerUndoCommandRenameAttribute
* @param buffer associated edit buffer
* @param fieldIndex index of field to rename
* @param newName new name for field
*/
QgsVectorLayerUndoCommandRenameAttribute( QgsVectorLayerEditBuffer* buffer, int fieldIndex, const QString& newName );
virtual void undo() override;
virtual void redo() override;
private:
int mFieldIndex;
QString mOldName;
QString mNewName;
};

View File

@ -832,6 +832,181 @@ class TestQgsVectorLayer(unittest.TestCase):
layer.commitChanges()
checkAfter2()
# RENAME ATTRIBUTE
def test_RenameAttribute(self):
layer = createLayerWithOnePoint()
# without editing mode
self.assertFalse(layer.renameAttribute(0, 'renamed'))
def checkFieldNames(names):
flds = layer.fields()
f = next(layer.getFeatures())
self.assertEqual(flds.count(), len(names))
self.assertEqual(f.fields().count(), len(names))
for idx, expected_name in enumerate(names):
self.assertEqual(flds[idx].name(), expected_name)
self.assertEqual(f.fields().at(idx).name(), expected_name)
layer.startEditing()
checkFieldNames(['fldtxt', 'fldint'])
self.assertFalse(layer.renameAttribute(-1, 'fldtxt2'))
self.assertFalse(layer.renameAttribute(10, 'fldtxt2'))
self.assertFalse(layer.renameAttribute(0, 'fldint')) # duplicate name
self.assertTrue(layer.renameAttribute(0, 'fldtxt2'))
checkFieldNames(['fldtxt2', 'fldint'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint'])
layer.undoStack().redo()
checkFieldNames(['fldtxt2', 'fldint'])
# change two fields
self.assertTrue(layer.renameAttribute(1, 'fldint2'))
checkFieldNames(['fldtxt2', 'fldint2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt2', 'fldint'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint'])
layer.undoStack().redo()
checkFieldNames(['fldtxt2', 'fldint'])
layer.undoStack().redo()
checkFieldNames(['fldtxt2', 'fldint2'])
# two renames
self.assertTrue(layer.renameAttribute(0, 'fldtxt3'))
checkFieldNames(['fldtxt3', 'fldint2'])
self.assertTrue(layer.renameAttribute(0, 'fldtxt4'))
checkFieldNames(['fldtxt4', 'fldint2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt3', 'fldint2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt2', 'fldint2'])
layer.undoStack().redo()
checkFieldNames(['fldtxt3', 'fldint2'])
layer.undoStack().redo()
checkFieldNames(['fldtxt4', 'fldint2'])
def test_RenameAttributeAfterAdd(self):
layer = createLayerWithOnePoint()
def checkFieldNames(names):
flds = layer.fields()
f = next(layer.getFeatures())
self.assertEqual(flds.count(), len(names))
self.assertEqual(f.fields().count(), len(names))
for idx, expected_name in enumerate(names):
self.assertEqual(flds[idx].name(), expected_name)
self.assertEqual(f.fields().at(idx).name(), expected_name)
layer.startEditing()
checkFieldNames(['fldtxt', 'fldint'])
self.assertTrue(layer.renameAttribute(1, 'fldint2'))
checkFieldNames(['fldtxt', 'fldint2'])
#add an attribute
self.assertTrue(layer.addAttribute(QgsField("flddouble", QVariant.Double, "double")))
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
# rename it
self.assertTrue(layer.renameAttribute(2, 'flddouble2'))
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
self.assertTrue(layer.addAttribute(QgsField("flddate", QVariant.Date, "date")))
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
self.assertTrue(layer.renameAttribute(2, 'flddouble3'))
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
self.assertTrue(layer.renameAttribute(3, 'flddate2'))
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble2', 'flddate'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate'])
layer.undoStack().redo()
checkFieldNames(['fldtxt', 'fldint2', 'flddouble3', 'flddate2'])
def test_RenameAttributeAndDelete(self):
layer = createLayerWithOnePoint()
layer.dataProvider().addAttributes(
[QgsField("flddouble", QVariant.Double, "double")])
layer.updateFields()
def checkFieldNames(names):
flds = layer.fields()
f = next(layer.getFeatures())
self.assertEqual(flds.count(), len(names))
self.assertEqual(f.fields().count(), len(names))
for idx, expected_name in enumerate(names):
self.assertEqual(flds[idx].name(), expected_name)
self.assertEqual(f.fields().at(idx).name(), expected_name)
layer.startEditing()
checkFieldNames(['fldtxt', 'fldint', 'flddouble'])
self.assertTrue(layer.renameAttribute(0, 'fldtxt2'))
checkFieldNames(['fldtxt2', 'fldint', 'flddouble'])
self.assertTrue(layer.renameAttribute(2, 'flddouble2'))
checkFieldNames(['fldtxt2', 'fldint', 'flddouble2'])
#delete an attribute
self.assertTrue(layer.deleteAttribute(0))
checkFieldNames(['fldint', 'flddouble2'])
# rename remaining
self.assertTrue(layer.renameAttribute(0, 'fldint2'))
checkFieldNames(['fldint2', 'flddouble2'])
self.assertTrue(layer.renameAttribute(1, 'flddouble3'))
checkFieldNames(['fldint2', 'flddouble3'])
#delete an attribute
self.assertTrue(layer.deleteAttribute(0))
checkFieldNames(['flddouble3'])
self.assertTrue(layer.renameAttribute(0, 'flddouble4'))
checkFieldNames(['flddouble4'])
layer.undoStack().undo()
checkFieldNames(['flddouble3'])
layer.undoStack().undo()
checkFieldNames(['fldint2', 'flddouble3'])
layer.undoStack().undo()
checkFieldNames(['fldint2', 'flddouble2'])
layer.undoStack().undo()
checkFieldNames(['fldint', 'flddouble2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt2', 'fldint', 'flddouble2'])
layer.undoStack().undo()
checkFieldNames(['fldtxt2', 'fldint', 'flddouble'])
layer.undoStack().undo()
checkFieldNames(['fldtxt', 'fldint', 'flddouble'])
#layer.undoStack().redo()
#checkFieldNames(['fldtxt2', 'fldint'])
#layer.undoStack().redo()
#checkFieldNames(['fldint'])
def test_fields(self):
layer = createLayerWithOnePoint()