mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Add support for field renaming in QgsVectorLayer and edit buffer
This commit is contained in:
parent
ccc67ef7a5
commit
0e03115d33
@ -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
|
||||
*
|
||||
|
@ -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 );
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
};
|
||||
|
@ -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() )
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user