Skip to content

Commit

Permalink
Don't emit layerModified for every atomic change made during a bulk
Browse files Browse the repository at this point in the history
operation to the vector layer edit buffer

Eg Instead of emitting layerModified for every individual feature
in a call to QgsVectorLayer::addFeatures, we defer the signal
and emit it only once after adding all the features.

This avoids a lot of expensive, unnecessary work which is triggered
by the signal
  • Loading branch information
nyalldawson authored and github-actions[bot] committed Nov 18, 2022
1 parent 332a3fd commit ecfa173
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 deletions.
Expand Up @@ -331,6 +331,7 @@ Updates an index in an attribute map to a new value (for updates of changed attr




};

/************************************************************************
Expand Down
32 changes: 29 additions & 3 deletions src/core/vector/qgsvectorlayereditbuffer.cpp
Expand Up @@ -53,6 +53,9 @@ bool QgsVectorLayerEditBuffer::isModified() const

void QgsVectorLayerEditBuffer::undoIndexChanged( int index )
{
if ( mBlockModifiedSignals )
return;

QgsDebugMsgLevel( QStringLiteral( "undo index changed %1" ).arg( index ), 4 );
Q_UNUSED( index )
emit layerModified();
Expand Down Expand Up @@ -149,12 +152,23 @@ bool QgsVectorLayerEditBuffer::addFeatures( QgsFeatureList &features )
if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures ) )
return false;

// we don't want to emit layerModified for every added feature, rather just once for the batch lot
mBlockModifiedSignals++;

bool result = true;
bool anyAdded = false;
for ( QgsFeatureList::iterator iter = features.begin(); iter != features.end(); ++iter )
{
result = result && addFeature( *iter );
const bool thisFeatureResult = addFeature( *iter );
result = result && thisFeatureResult;
anyAdded |= thisFeatureResult;
}

mBlockModifiedSignals--;

if ( anyAdded )
emit layerModified();

L->updateExtents();
return result;
}
Expand Down Expand Up @@ -198,11 +212,16 @@ bool QgsVectorLayerEditBuffer::deleteFeatures( const QgsFeatureIds &fids )
return false;
}

// we don't want to emit layerModified for every deleted feature, rather just once for the batch lot
mBlockModifiedSignals++;

bool ok = true;
const auto constFids = fids;
for ( QgsFeatureId fid : constFids )
for ( QgsFeatureId fid : fids )
ok = deleteFeature( fid ) && ok;

mBlockModifiedSignals--;
emit layerModified();

return ok;
}

Expand Down Expand Up @@ -231,6 +250,10 @@ bool QgsVectorLayerEditBuffer::changeGeometry( QgsFeatureId fid, const QgsGeomet
bool QgsVectorLayerEditBuffer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues )
{
bool success = true;

// we don't want to emit layerModified for every changed attribute, rather just once for the batch lot
mBlockModifiedSignals++;

for ( auto it = newValues.constBegin() ; it != newValues.constEnd(); ++it )
{
const int field = it.key();
Expand All @@ -243,6 +266,9 @@ bool QgsVectorLayerEditBuffer::changeAttributeValues( QgsFeatureId fid, const Qg
success &= changeAttributeValue( fid, field, newValue, oldValue );
}

mBlockModifiedSignals--;
emit layerModified();

return success;
}

Expand Down
2 changes: 2 additions & 0 deletions src/core/vector/qgsvectorlayereditbuffer.h
Expand Up @@ -330,6 +330,8 @@ class CORE_EXPORT QgsVectorLayerEditBuffer : public QObject

QgsVectorLayerEditBufferGroup *mEditBufferGroup = nullptr;

int mBlockModifiedSignals = 0;

friend class QgsGrassProvider; //GRASS provider totally abuses the edit buffer

private:
Expand Down

0 comments on commit ecfa173

Please sign in to comment.