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() )
204 , mFirstChange( true )
206 if (
mBuffer->mAddedFeatures.contains( mFid ) )
208 mFirstChange = false;
210 else if (
mBuffer->mChangedGeometries.contains( mFid ) )
212 mFirstChange = false;
213 mOldGeom = mBuffer->mChangedGeometries[mFid];
221 if (
mBuffer->mAddedFeatures.contains( mFid ) )
223 mBuffer->mAddedFeatures[ mFid ].setGeometry( mOldGeom );
225 else if ( mFirstChange )
227 mBuffer->mChangedGeometries.remove( mFid );
231 mBuffer->mChangedGeometries[mFid] = mOldGeom;
233 emit
mBuffer->geometryChanged( mFid, mOldGeom );
240 geomMap.insert( mFid, mNewGeom );
241 mBuffer->L->dataProvider()->clearErrors();
242 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeGeometryValues( geomMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
244 if (
mBuffer->mAddedFeatures.contains( mFid ) )
246 mBuffer->mAddedFeatures[ mFid ].setGeometry( mNewGeom );
250 mBuffer->mChangedGeometries[ mFid ] = mNewGeom;
252 emit
mBuffer->geometryChanged( mFid, mNewGeom );
262 if ( other->id() !=
id() )
269 if ( merge->mFid != mFid )
272 mNewGeom = merge->mNewGeom;
283 , mFieldIndex( field )
284 , mNewValue( newValue )
285 , mOldValue(
mBuffer->L->getFeature( mFid ).attribute( field ) )
286 , mFirstChange( true )
289 if (
mBuffer->mAddedFeatures.contains( mFid ) )
292 QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
293 Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
294 if ( it.value().attribute( mFieldIndex ).isValid() )
296 mOldValue = it.value().attribute( mFieldIndex );
297 mFirstChange = false;
300 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
302 mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
303 mFirstChange = false;
311 QVariant original = mOldValue;
313 if (
mBuffer->mAddedFeatures.contains( mFid ) )
316 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
317 Q_ASSERT( it !=
mBuffer->mAddedFeatures.end() );
318 it.value().setAttribute( mFieldIndex, mOldValue );
320 else if ( mFirstChange )
323 mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
324 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
325 mBuffer->mChangedAttributeValues.remove( mFid );
327 if ( !mOldValue.isValid() )
335 std::unique_ptr<QgsVectorLayer> layerClone(
layer()->clone() );
343 mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
345 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
352 map.insert( mFieldIndex, mNewValue );
354 attribMap.insert( mFid, map );
355 mBuffer->L->dataProvider()->clearErrors();
356 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
359 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
360 if ( it !=
mBuffer->mAddedFeatures.end() )
362 it.value().setAttribute( mFieldIndex, mNewValue );
367 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
372 mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
374 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
392 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
398 if (
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() ) != -1 )
402 mBuffer->mAddedAttributes.removeAll( mField );
404 emit
mBuffer->attributeDeleted( attr );
414 mBuffer->L->dataProvider()->clearErrors();
415 if (
setSavePoint() &&
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && !
mBuffer->L->dataProvider()->hasErrors() )
418 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
419 mBuffer->mAddedAttributes.append( mField );
420 emit
mBuffer->attributeAdded( attr );
430 , mField(
mBuffer->L->fields()[ attr ] )
431 , mOriginalFieldIndex( attr )
439 mBuffer->L->dataProvider()->clearErrors();
446 if (
mBuffer->L->dataProvider()->fields().indexFromName( mField.name() ) == -1 )
448 ok =
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField );
450 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
452 mBuffer->mDeletedAttributeIds.removeOne( mOriginalFieldIndex );
454 emit
mBuffer->attributeAdded( mOriginalFieldIndex );
469 mBuffer->L->dataProvider()->clearErrors();
472 mBuffer->mDeletedAttributeIds.append( mOriginalFieldIndex );
474 emit
mBuffer->attributeDeleted( mOriginalFieldIndex );
485 , mNewName( newName )
486 , mOldName(
mBuffer->L->fields()[ mAttr ].name() )
495 map[ mAttr ] = mOldName;
496 mBuffer->L->dataProvider()->clearErrors();
503 if (
mBuffer->L->dataProvider()->fields().indexFromName( mOldName ) == -1 )
505 ok =
mBuffer->L->dataProvider()->renameAttributes( map );
507 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
510 emit
mBuffer->attributeRenamed( mAttr, mOldName );
526 map[ mAttr ] = mNewName;
527 mBuffer->L->dataProvider()->clearErrors();
531 emit
mBuffer->attributeRenamed( mAttr, mNewName );
541 , mTransaction( transaction )
551 emit
mBuffer->L->layerModified();
567 QString savePointId = mTransaction->createSavepoint(
errorMessage );
594 , mNewValues( newValues )
595 , mOldValues( oldValues )
597 if ( mOldValues.isEmpty() )
599 const auto oldAttrs( mBuffer->L->getFeature( mFid ).attributes() );
600 for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
602 mOldValues[ it.key() ] = oldAttrs[ it.key() ];
605 const bool isAdded { mBuffer->mAddedFeatures.contains( mFid ) };
606 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
608 if ( isAdded && mBuffer->mAddedFeatures[ mFid ].attribute( it.key() ).isValid() )
610 mFirstChanges[ it.key() ] = false;
612 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( it.key() ) )
614 mFirstChanges[ it.key() ] = false;
618 mFirstChanges[ it.key() ] = true;
627 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
628 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
630 const auto fieldIndex { it.key() };
631 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
633 addedIt.value().setAttribute( fieldIndex, mOldValues[ it.key() ] );
635 else if ( mFirstChanges.contains( fieldIndex ) && mFirstChanges[ fieldIndex ] )
638 mBuffer->mChangedAttributeValues[mFid].remove( fieldIndex );
643 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
647 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, mOldValues[ it.key() ] );
649 emit
mBuffer->attributeValueChanged( mFid, it.key(), mOldValues[ it.key() ] );
651 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
652 mBuffer->mChangedAttributeValues.remove( mFid );
659 attribMap.insert( mFid, mNewValues );
660 mBuffer->L->dataProvider()->clearErrors();
661 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
663 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
664 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
666 const auto fieldIndex { it.key() };
668 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
670 addedIt.value().setAttribute( fieldIndex, it.value() );
675 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
679 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, it.value() );
681 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