33 , mSavePointId( (
mBuffer->L->isEditCommandActive() && !
mBuffer->L->dataProvider()->transaction()->savePoints().isEmpty() )
35 ?
mBuffer->L->dataProvider()->transaction()->savePoints().last()
36 :
mBuffer->L->dataProvider()->transaction()->createSavepoint( mError ) )
37 , mHasError( !mError.isEmpty() )
38 , mRecreateSavePoint(
mBuffer->L->isEditCommandActive()
39 ? !
mBuffer->L->dataProvider()->transaction()->lastSavePointIsDirty()
52 setText( text() +
" " + QObject::tr(
"failed" ) );
71 if ( savePointId.isEmpty() )
74 if ( mRecreateSavePoint &&
mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) == -1 )
76 mSavePointId =
mBuffer->L->dataProvider()->transaction()->createSavepoint( mSavePointId, mError );
77 if ( mSavePointId.isEmpty() )
85 mSavePointId = savePointId;
94 if ( !
hasError() &&
mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) != -1 )
96 if ( !
mBuffer->L->dataProvider()->transaction()->rollbackToSavepoint( mSavePointId, mError ) )
108 static int sAddedIdLowWaterMark = -1;
111 mInitialFeatures << f;
113 sAddedIdLowWaterMark--;
114 mInitialFeatures.last().setId( sAddedIdLowWaterMark );
116 mFeatures = mInitialFeatures;
124 for (
const QgsFeature &f : std::as_const( mFeatures ) )
126 mBuffer->mAddedFeatures.remove( f.id() );
127 emit
mBuffer->featureDeleted( f.id() );
129 mFeatures = mInitialFeatures;
135 mFeatures = mInitialFeatures;
136 mBuffer->L->dataProvider()->clearErrors();
139 for (
const QgsFeature &f : std::as_const( mFeatures ) )
141 mBuffer->mAddedFeatures.insert( f.id(), f );
142 emit
mBuffer->featureAdded( f.id() );
163 mBuffer->mDeletedFeatureIds.remove( fid );
164 if ( mDeletedNewFeatures.contains( fid ) )
166 mBuffer->mAddedFeatures.insert( fid, mDeletedNewFeatures.value( fid ) );
168 emit
mBuffer->featureAdded( fid );
175 mBuffer->L->dataProvider()->clearErrors();
178 mDeletedNewFeatures.clear();
181 if (
mBuffer->mAddedFeatures.contains( fid ) )
183 mDeletedNewFeatures.insert( fid,
mBuffer->mAddedFeatures[ fid ] );
184 mBuffer->mAddedFeatures.remove( fid );
188 mBuffer->mDeletedFeatureIds.insert( fid );
190 emit
mBuffer->featureDeleted( fid );
203 , mOldGeom(
mBuffer->L->getFeature( mFid ).geometry() )
205 if (
mBuffer->mAddedFeatures.contains( mFid ) )
207 mFirstChange = false;
209 else if (
mBuffer->mChangedGeometries.contains( mFid ) )
211 mFirstChange = false;
212 mOldGeom = mBuffer->mChangedGeometries[mFid];
220 if (
mBuffer->mAddedFeatures.contains( mFid ) )
222 mBuffer->mAddedFeatures[ mFid ].setGeometry( mOldGeom );
224 else if ( mFirstChange )
226 mBuffer->mChangedGeometries.remove( mFid );
230 mBuffer->mChangedGeometries[mFid] = mOldGeom;
232 emit
mBuffer->geometryChanged( mFid, mOldGeom );
239 geomMap.insert( mFid, mNewGeom );
240 mBuffer->L->dataProvider()->clearErrors();
241 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeGeometryValues( geomMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
243 if (
mBuffer->mAddedFeatures.contains( mFid ) )
245 mBuffer->mAddedFeatures[ mFid ].setGeometry( mNewGeom );
249 mBuffer->mChangedGeometries[ mFid ] = mNewGeom;
251 emit
mBuffer->geometryChanged( mFid, mNewGeom );
261 if ( other->id() !=
id() )
268 if ( merge->mFid != mFid )
271 mNewGeom = merge->mNewGeom;
282 , mFieldIndex( field )
283 , mNewValue( newValue )
284 , mOldValue(
mBuffer->L->getFeature( mFid ).attribute( field ) )
287 if (
mBuffer->mAddedFeatures.contains( mFid ) )
290 QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
291 Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
292 if ( it.value().attribute( mFieldIndex ).isValid() )
294 mOldValue = it.value().attribute( mFieldIndex );
295 mFirstChange = false;
298 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
300 mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
301 mFirstChange = false;
309 QVariant original = mOldValue;
311 if (
mBuffer->mAddedFeatures.contains( mFid ) )
314 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
315 Q_ASSERT( it !=
mBuffer->mAddedFeatures.end() );
316 it.value().setAttribute( mFieldIndex, mOldValue );
318 else if ( mFirstChange )
321 mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
322 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
323 mBuffer->mChangedAttributeValues.remove( mFid );
325 if ( !mOldValue.isValid() )
333 std::unique_ptr<QgsVectorLayer> layerClone(
layer()->clone() );
341 mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
343 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
350 map.insert( mFieldIndex, mNewValue );
352 attribMap.insert( mFid, map );
353 mBuffer->L->dataProvider()->clearErrors();
354 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
357 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
358 if ( it !=
mBuffer->mAddedFeatures.end() )
360 it.value().setAttribute( mFieldIndex, mNewValue );
365 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
370 mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
372 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
390 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
396 if (
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() ) != -1 )
400 mBuffer->mAddedAttributes.removeAll( mField );
402 emit
mBuffer->attributeDeleted( attr );
412 mBuffer->L->dataProvider()->clearErrors();
413 if (
setSavePoint() &&
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && !
mBuffer->L->dataProvider()->hasErrors() )
416 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
417 mBuffer->mAddedAttributes.append( mField );
418 emit
mBuffer->attributeAdded( attr );
428 , mField(
mBuffer->L->fields()[ attr ] )
429 , mOriginalFieldIndex( attr )
437 mBuffer->L->dataProvider()->clearErrors();
444 if (
mBuffer->L->dataProvider()->fields().indexFromName( mField.name() ) == -1 )
446 ok =
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField );
448 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
450 mBuffer->mDeletedAttributeIds.removeOne( mOriginalFieldIndex );
452 emit
mBuffer->attributeAdded( mOriginalFieldIndex );
467 mBuffer->L->dataProvider()->clearErrors();
470 mBuffer->mDeletedAttributeIds.append( mOriginalFieldIndex );
472 emit
mBuffer->attributeDeleted( mOriginalFieldIndex );
483 , mNewName( newName )
484 , mOldName(
mBuffer->L->fields()[ mAttr ].name() )
493 map[ mAttr ] = mOldName;
494 mBuffer->L->dataProvider()->clearErrors();
501 if (
mBuffer->L->dataProvider()->fields().indexFromName( mOldName ) == -1 )
503 ok =
mBuffer->L->dataProvider()->renameAttributes( map );
505 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
508 emit
mBuffer->attributeRenamed( mAttr, mOldName );
524 map[ mAttr ] = mNewName;
525 mBuffer->L->dataProvider()->clearErrors();
529 emit
mBuffer->attributeRenamed( mAttr, mNewName );
539 , mTransaction( transaction )
549 emit
mBuffer->L->layerModified();
565 QString savePointId = mTransaction->createSavepoint(
errorMessage );
592 , mNewValues( newValues )
593 , mOldValues( oldValues )
595 if ( mOldValues.isEmpty() )
597 const auto oldAttrs( mBuffer->L->getFeature( mFid ).attributes() );
598 for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
600 mOldValues[ it.key() ] = oldAttrs[ it.key() ];
603 const bool isAdded { mBuffer->mAddedFeatures.contains( mFid ) };
604 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
606 if ( isAdded && mBuffer->mAddedFeatures[ mFid ].attribute( it.key() ).isValid() )
608 mFirstChanges[ it.key() ] = false;
610 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( it.key() ) )
612 mFirstChanges[ it.key() ] = false;
616 mFirstChanges[ it.key() ] = true;
625 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
626 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
628 const auto fieldIndex { it.key() };
629 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
631 addedIt.value().setAttribute( fieldIndex, mOldValues[ it.key() ] );
633 else if ( mFirstChanges.contains( fieldIndex ) && mFirstChanges[ fieldIndex ] )
636 mBuffer->mChangedAttributeValues[mFid].remove( fieldIndex );
641 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
645 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, mOldValues[ it.key() ] );
647 emit
mBuffer->attributeValueChanged( mFid, it.key(), mOldValues[ it.key() ] );
649 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
650 mBuffer->mChangedAttributeValues.remove( mFid );
657 attribMap.insert( mFid, mNewValues );
658 mBuffer->L->dataProvider()->clearErrors();
659 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
661 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
662 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
664 const auto fieldIndex { it.key() };
666 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
668 addedIt.value().setAttribute( fieldIndex, it.value() );
673 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
677 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, it.value() );
679 emit
mBuffer->attributeValueChanged( mFid, it.key(), it.value() );
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterFid(QgsFeatureId fid)
Sets the feature ID that should be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
A geometry is the spatial representation of a feature.
Allows creation of a multi-layer database-side transaction.
Stores queued vector layer edit operations prior to committing changes to the layer's data provider.
QgsVectorLayer * layer()
Returns the layer associated with the undo command.
QgsVectorLayerUndoCommand(QgsVectorLayerEditBuffer *buffer)
Constructor for QgsVectorLayerUndoCommand.
QgsVectorLayerEditBuffer * mBuffer
Associated edit buffer.
QgsVectorLayerUndoPassthroughCommandAddAttribute(QgsVectorLayerEditBuffer *buffer, const QgsField &field)
Constructor for QgsVectorLayerUndoPassthroughCommandAddAttribute.
QgsFeatureList features() const
List of features (added feaures can be modified by default values from database).
QgsVectorLayerUndoPassthroughCommandAddFeatures(QgsVectorLayerEditBuffer *buffer, QgsFeatureList &features)
Constructor for QgsVectorLayerUndoPassthroughCommandAddFeatures.
QgsVectorLayerUndoPassthroughCommandChangeAttribute(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, int field, const QVariant &newValue)
Constructor for QgsVectorLayerUndoPassthroughCommandChangeAttribute.
QgsVectorLayerUndoPassthroughCommandChangeAttributes(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues=QgsAttributeMap())
Constructor for QgsVectorLayerUndoPassthroughCommandChangeAttributes.
QgsVectorLayerUndoPassthroughCommandChangeGeometry(QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsGeometry &geom)
Constructor for QgsVectorLayerUndoPassthroughCommandChangeGeometry.
bool mergeWith(const QUndoCommand *other) override
QgsVectorLayerUndoPassthroughCommandDeleteAttribute(QgsVectorLayerEditBuffer *buffer, int attr)
Constructor for QgsVectorLayerUndoCommandDeleteAttribute.
QgsVectorLayerUndoPassthroughCommandDeleteFeatures(QgsVectorLayerEditBuffer *buffer, const QgsFeatureIds &fids)
Constructor for QgsVectorLayerUndoPassthroughCommandDeleteFeatures.
QgsVectorLayerUndoPassthroughCommandRenameAttribute(QgsVectorLayerEditBuffer *buffer, int attr, const QString &newName)
Constructor for QgsVectorLayerUndoCommandRenameAttribute.
QgsVectorLayerUndoPassthroughCommandUpdate(QgsVectorLayerEditBuffer *buffer, QgsTransaction *transaction, const QString &sql, const QString &name)
Constructor for QgsVectorLayerUndoCommandUpdate.
QgsVectorLayerUndoPassthroughCommand(QgsVectorLayerEditBuffer *buffer, const QString &text, bool autocreate=true)
Constructor for QgsVectorLayerUndoPassthroughCommand.
QString errorMessage() const
Returns the error message or an empty string if there's none.
void setErrorMessage(const QString &errorMessage)
Sets the error message.
void setError()
Set error flag and append "failed" to text.
bool hasError() const
Returns error status.
bool setSavePoint(const QString &savePointId=QString())
Set the command savepoint or set error status.
bool rollBackToSavePoint()
Rollback command, release savepoint or set error status save point must be set prior to call error sa...
QMap< int, QString > QgsFieldNameMap
QMap< int, QVariant > QgsAttributeMap
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
QList< QgsFeature > QgsFeatureList
QSet< QgsFeatureId > QgsFeatureIds
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
QSet< int > QgsAttributeIds