34 (
mBuffer->L->isEditCommandActive() && !
mBuffer->L->dataProvider()->transaction()->savePoints().isEmpty() ) || !autocreate ?
mBuffer->L->dataProvider()->transaction()->savePoints().last()
35 :
mBuffer->L->dataProvider()->transaction()->createSavepoint( mError )
37 , mHasError( !mError.isEmpty() )
38 , mRecreateSavePoint(
mBuffer->L->isEditCommandActive() ? !
mBuffer->L->dataProvider()->transaction()->lastSavePointIsDirty() : true )
50 setText( text() +
" " + QObject::tr(
"failed" ) );
69 if ( savePointId.isEmpty() )
72 if ( mRecreateSavePoint &&
mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) == -1 )
74 mSavePointId =
mBuffer->L->dataProvider()->transaction()->createSavepoint( mSavePointId, mError );
75 if ( mSavePointId.isEmpty() )
83 mSavePointId = savePointId;
92 if ( !
hasError() &&
mBuffer->L->dataProvider()->transaction()->savePoints().indexOf( mSavePointId ) != -1 )
94 if ( !
mBuffer->L->dataProvider()->transaction()->rollbackToSavepoint( mSavePointId, mError ) )
106 static int sAddedIdLowWaterMark = -1;
109 mInitialFeatures << f;
111 sAddedIdLowWaterMark--;
112 mInitialFeatures.last().setId( sAddedIdLowWaterMark );
114 mFeatures = mInitialFeatures;
121 for (
const QgsFeature &f : std::as_const( mFeatures ) )
123 mBuffer->mAddedFeatures.remove( f.id() );
124 emit
mBuffer->featureDeleted( f.id() );
126 mFeatures = mInitialFeatures;
132 mFeatures = mInitialFeatures;
133 mBuffer->L->dataProvider()->clearErrors();
136 for (
const QgsFeature &f : std::as_const( mFeatures ) )
138 mBuffer->mAddedFeatures.insert( f.id(), f );
139 emit
mBuffer->featureAdded( f.id() );
159 mBuffer->mDeletedFeatureIds.remove( fid );
160 if ( mDeletedNewFeatures.contains( fid ) )
162 mBuffer->mAddedFeatures.insert( fid, mDeletedNewFeatures.value( fid ) );
164 emit
mBuffer->featureAdded( fid );
171 mBuffer->L->dataProvider()->clearErrors();
174 mDeletedNewFeatures.clear();
177 if (
mBuffer->mAddedFeatures.contains( fid ) )
179 mDeletedNewFeatures.insert( fid,
mBuffer->mAddedFeatures[fid] );
180 mBuffer->mAddedFeatures.remove( fid );
184 mBuffer->mDeletedFeatureIds.insert( fid );
186 emit
mBuffer->featureDeleted( fid );
199 , mOldGeom(
mBuffer->L->getFeature( mFid ).geometry() )
201 if (
mBuffer->mAddedFeatures.contains( mFid ) )
203 mFirstChange = false;
205 else if (
mBuffer->mChangedGeometries.contains( mFid ) )
207 mFirstChange = false;
208 mOldGeom = mBuffer->mChangedGeometries[mFid];
216 if (
mBuffer->mAddedFeatures.contains( mFid ) )
218 mBuffer->mAddedFeatures[mFid].setGeometry( mOldGeom );
220 else if ( mFirstChange )
222 mBuffer->mChangedGeometries.remove( mFid );
226 mBuffer->mChangedGeometries[mFid] = mOldGeom;
228 emit
mBuffer->geometryChanged( mFid, mOldGeom );
235 geomMap.insert( mFid, mNewGeom );
236 mBuffer->L->dataProvider()->clearErrors();
237 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeGeometryValues( geomMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
239 if (
mBuffer->mAddedFeatures.contains( mFid ) )
241 mBuffer->mAddedFeatures[mFid].setGeometry( mNewGeom );
245 mBuffer->mChangedGeometries[mFid] = mNewGeom;
247 emit
mBuffer->geometryChanged( mFid, mNewGeom );
257 if ( other->id() !=
id() )
264 if ( merge->mFid != mFid )
267 mNewGeom = merge->mNewGeom;
277 , mFieldIndex( field )
278 , mNewValue( newValue )
279 , mOldValue(
mBuffer->L->getFeature( mFid ).attribute( field ) )
281 if (
mBuffer->mAddedFeatures.contains( mFid ) )
284 QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
285 Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
286 if ( it.value().attribute( mFieldIndex ).isValid() )
288 mOldValue = it.value().attribute( mFieldIndex );
289 mFirstChange = false;
292 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( mFieldIndex ) )
294 mOldValue = mBuffer->mChangedAttributeValues[mFid][mFieldIndex];
295 mFirstChange = false;
303 QVariant original = mOldValue;
305 if (
mBuffer->mAddedFeatures.contains( mFid ) )
308 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
309 Q_ASSERT( it !=
mBuffer->mAddedFeatures.end() );
310 it.value().setAttribute( mFieldIndex, mOldValue );
312 else if ( mFirstChange )
315 mBuffer->mChangedAttributeValues[mFid].remove( mFieldIndex );
316 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
317 mBuffer->mChangedAttributeValues.remove( mFid );
319 if ( !mOldValue.isValid() )
327 std::unique_ptr<QgsVectorLayer> layerClone(
layer()->clone() );
335 mBuffer->mChangedAttributeValues[mFid][mFieldIndex] = mOldValue;
337 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, original );
344 map.insert( mFieldIndex, mNewValue );
346 attribMap.insert( mFid, map );
347 mBuffer->L->dataProvider()->clearErrors();
348 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
351 QgsFeatureMap::iterator it =
mBuffer->mAddedFeatures.find( mFid );
352 if ( it !=
mBuffer->mAddedFeatures.end() )
354 it.value().setAttribute( mFieldIndex, mNewValue );
359 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
364 mBuffer->mChangedAttributeValues[mFid].insert( mFieldIndex, mNewValue );
366 emit
mBuffer->attributeValueChanged( mFid, mFieldIndex, mNewValue );
383 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
389 if (
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() ) != -1 )
393 mBuffer->mAddedAttributes.removeAll( mField );
395 emit
mBuffer->attributeDeleted( attr );
405 mBuffer->L->dataProvider()->clearErrors();
406 if (
setSavePoint() &&
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField ) && !
mBuffer->L->dataProvider()->hasErrors() )
409 const int attr =
mBuffer->L->dataProvider()->fieldNameIndex( mField.name() );
410 mBuffer->mAddedAttributes.append( mField );
411 emit
mBuffer->attributeAdded( attr );
421 , mField(
mBuffer->L->fields()[attr] )
422 , mOriginalFieldIndex( attr )
429 mBuffer->L->dataProvider()->clearErrors();
436 if (
mBuffer->L->dataProvider()->fields().indexFromName( mField.name() ) == -1 )
438 ok =
mBuffer->L->dataProvider()->addAttributes( QList<QgsField>() << mField );
440 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
442 mBuffer->mDeletedAttributeIds.removeOne( mOriginalFieldIndex );
444 emit
mBuffer->attributeAdded( mOriginalFieldIndex );
459 mBuffer->L->dataProvider()->clearErrors();
462 mBuffer->mDeletedAttributeIds.append( mOriginalFieldIndex );
464 emit
mBuffer->attributeDeleted( mOriginalFieldIndex );
475 , mNewName( newName )
476 , mOldName(
mBuffer->L->fields()[mAttr].name() )
484 map[mAttr] = mOldName;
485 mBuffer->L->dataProvider()->clearErrors();
492 if (
mBuffer->L->dataProvider()->fields().indexFromName( mOldName ) == -1 )
494 ok =
mBuffer->L->dataProvider()->renameAttributes( map );
496 if ( ok && !
mBuffer->L->dataProvider()->hasErrors() )
499 emit
mBuffer->attributeRenamed( mAttr, mOldName );
515 map[mAttr] = mNewName;
516 mBuffer->L->dataProvider()->clearErrors();
520 emit
mBuffer->attributeRenamed( mAttr, mNewName );
530 , mTransaction( transaction )
539 emit
mBuffer->L->layerModified();
555 QString savePointId = mTransaction->createSavepoint(
errorMessage );
584 , mNewValues( newValues )
585 , mOldValues( oldValues )
587 if ( mOldValues.isEmpty() )
589 const auto oldAttrs( mBuffer->L->getFeature( mFid ).attributes() );
590 for ( auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
592 mOldValues[it.key()] = oldAttrs[it.key()];
595 const bool isAdded { mBuffer->mAddedFeatures.contains( mFid ) };
596 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
598 if ( isAdded && mBuffer->mAddedFeatures[mFid].attribute( it.key() ).isValid() )
600 mFirstChanges[it.key()] = false;
602 else if ( mBuffer->mChangedAttributeValues.contains( mFid ) && mBuffer->mChangedAttributeValues[mFid].contains( it.key() ) )
604 mFirstChanges[it.key()] = false;
608 mFirstChanges[it.key()] = true;
617 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
618 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
620 const auto fieldIndex { it.key() };
621 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
623 addedIt.value().setAttribute( fieldIndex, mOldValues[it.key()] );
625 else if ( mFirstChanges.contains( fieldIndex ) && mFirstChanges[fieldIndex] )
628 mBuffer->mChangedAttributeValues[mFid].remove( fieldIndex );
633 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
637 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, mOldValues[it.key()] );
639 emit
mBuffer->attributeValueChanged( mFid, it.key(), mOldValues[it.key()] );
641 if (
mBuffer->mChangedAttributeValues[mFid].isEmpty() )
642 mBuffer->mChangedAttributeValues.remove( mFid );
649 attribMap.insert( mFid, mNewValues );
650 mBuffer->L->dataProvider()->clearErrors();
651 if (
setSavePoint() &&
mBuffer->L->dataProvider()->changeAttributeValues( attribMap ) && !
mBuffer->L->dataProvider()->hasErrors() )
653 QgsFeatureMap::iterator addedIt =
mBuffer->mAddedFeatures.find( mFid );
654 for (
auto it = mNewValues.constBegin(); it != mNewValues.constEnd(); ++it )
656 const auto fieldIndex { it.key() };
658 if ( addedIt !=
mBuffer->mAddedFeatures.end() )
660 addedIt.value().setAttribute( fieldIndex, it.value() );
665 if ( !
mBuffer->mChangedAttributeValues.contains( mFid ) )
669 mBuffer->mChangedAttributeValues[mFid].insert( fieldIndex, it.value() );
671 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