Skip to content

Commit

Permalink
Add support for field renaming in QgsVectorLayer and edit buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 2, 2016
1 parent ccc67ef commit 0e03115
Show file tree
Hide file tree
Showing 13 changed files with 570 additions and 1 deletion.
7 changes: 7 additions & 0 deletions python/core/qgsvectorlayer.sip
Expand Up @@ -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
*
Expand Down
21 changes: 21 additions & 0 deletions python/core/qgsvectorlayereditbuffer.sip
Expand Up @@ -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.
Expand Down Expand Up @@ -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 );
Expand Down
1 change: 1 addition & 0 deletions python/core/qgsvectorlayereditpassthrough.sip
Expand Up @@ -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();

Expand Down
101 changes: 101 additions & 0 deletions python/core/qgsvectorlayerundocommand.sip
@@ -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();

Expand All @@ -13,38 +24,69 @@ 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();
virtual void redo();
};


/** \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();
virtual void redo();
};


/** \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();

Expand All @@ -55,40 +97,99 @@ 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();
virtual void redo();
};


/** \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();

};
8 changes: 8 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -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() )
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -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
*
Expand Down
78 changes: 78 additions & 0 deletions src/core/qgsvectorlayereditbuffer.cpp
Expand Up @@ -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() );
}
}


Expand Down Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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
//
Expand Down Expand Up @@ -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 )
Expand All @@ -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 );
}


Expand Down

0 comments on commit 0e03115

Please sign in to comment.