Skip to content

Commit

Permalink
Merge pull request #8177 from elpaso/bugfix-20094-field-calculator-sl…
Browse files Browse the repository at this point in the history
…owness

Fixes slow update in field calculator
  • Loading branch information
elpaso committed Oct 15, 2018
2 parents 87e0f69 + c8ea3a7 commit 096b4ce
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 6 deletions.
2 changes: 2 additions & 0 deletions python/core/auto_generated/qgsapplication.sip.in
Expand Up @@ -824,6 +824,7 @@ Emits the signal to collect all the strings of .qgs to be included in ts file
.. versionadded:: 3.4
%End


%If (ANDROID)
//dummy method to workaround sip generation issue
bool x11EventFilter( XEvent *event );
Expand Down Expand Up @@ -852,6 +853,7 @@ In order to register translatable strings, connect to this signal and register t
.. versionadded:: 3.4
%End


};


Expand Down
7 changes: 7 additions & 0 deletions python/core/auto_generated/qgsvectorlayer.sip.in
Expand Up @@ -2371,6 +2371,13 @@ Is emitted, before changes are committed to the data provider
void beforeRollBack();
%Docstring
Is emitted, before changes are rolled back
%End

void afterRollBack();
%Docstring
Is emitted, after changes are rolled back

.. versionadded:: 3.4
%End

void attributeAdded( int idx );
Expand Down
13 changes: 10 additions & 3 deletions src/app/qgisapp.cpp
Expand Up @@ -7093,13 +7093,14 @@ void QgisApp::fieldCalculator()

void QgisApp::attributeTable( QgsAttributeTableFilterModel::FilterMode filter )
{
QgsVectorLayer *myLayer = qobject_cast<QgsVectorLayer *>( activeLayer() );
if ( !myLayer )
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( activeLayer() );
if ( !vectorLayer )
{
return;
}

QgsAttributeTableDialog *mDialog = new QgsAttributeTableDialog( myLayer, filter );
QgsAttributeTableDialog *mDialog = new QgsAttributeTableDialog( vectorLayer, filter );

mDialog->show();
// the dialog will be deleted by itself on close
}
Expand Down Expand Up @@ -9191,6 +9192,7 @@ bool QgisApp::toggleEditing( QgsMapLayer *layer, bool allowCancel )
return res;
}


void QgisApp::saveActiveLayerEdits()
{
saveEdits( activeLayer(), true, true );
Expand Down Expand Up @@ -14153,3 +14155,8 @@ void QgisApp::triggerCrashHandler()
RaiseException( 0x12345678, 0, 0, nullptr );
#endif
}

void QgisApp::blockAttributeTableUpdates( const QgsVectorLayer *layer, const bool blocked )
{
emit attributeTableUpdateBlocked( layer, blocked );
}
14 changes: 14 additions & 0 deletions src/app/qgisapp.h
Expand Up @@ -1008,6 +1008,13 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
*/
void triggerCrashHandler();

/**
* Emits the signal to set the \a blocked state of attribute tables connected a particular \a layer
*
* \since QGIS 3.4
*/
void blockAttributeTableUpdates( const QgsVectorLayer *layer, const bool blocked );

protected:

//! Handle state changes (WindowTitleChange)
Expand Down Expand Up @@ -1741,6 +1748,13 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
*/
void activeLayerChanged( QgsMapLayer *layer );

/**
* Emitted when \a blocked status of attribute table updates for a particular \a layer must change
*
* \since QGIS 3.4
*/
void attributeTableUpdateBlocked( const QgsVectorLayer *layer, const bool blocked );

private:
void startProfile( const QString &name );
void endProfile();
Expand Down
20 changes: 19 additions & 1 deletion src/app/qgsattributetabledialog.cpp
Expand Up @@ -111,6 +111,16 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
connect( mActionExpressionSelect, &QAction::triggered, this, &QgsAttributeTableDialog::mActionExpressionSelect_triggered );
connect( mMainView, &QgsDualView::showContextMenuExternally, this, &QgsAttributeTableDialog::showContextMenu );

// Block/unblock table updates (feature cache signals)
connect( QgisApp::instance(), &QgisApp::attributeTableUpdateBlocked, [ = ]( const QgsVectorLayer * layer, const bool blocked )
{
if ( layer == mLayer )
this->blockCacheUpdateSignals( blocked );
} );
// Massive rollbacks can also freeze the GUI due to the feature cache signals
connect( mLayer, &QgsVectorLayer::beforeRollBack, [ = ] { this->blockCacheUpdateSignals( true ); } );
connect( mLayer, &QgsVectorLayer::afterRollBack, [ = ] { this->blockCacheUpdateSignals( false ); } );

const QgsFields fields = mLayer->fields();
for ( const QgsField &field : fields )
{
Expand Down Expand Up @@ -718,7 +728,6 @@ void QgsAttributeTableDialog::mActionOpenFieldCalculator_triggered()
if ( calc.exec() == QDialog::Accepted )
{
int col = masterModel->fieldCol( calc.changedAttributeId() );

if ( col >= 0 )
{
masterModel->reload( masterModel->index( 0, col ), masterModel->index( masterModel->rowCount() - 1, col ) );
Expand Down Expand Up @@ -1130,6 +1139,15 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
mMainView->setFilterMode( QgsAttributeTableFilterModel::ShowFilteredList );
}

void QgsAttributeTableDialog::blockCacheUpdateSignals( const bool block )
{
QgsAttributeTableModel *masterModel = mMainView->masterModel();

if ( ! masterModel )
return;

masterModel->layerCache()->blockSignals( block );
}

void QgsAttributeTableDialog::deleteFeature( const QgsFeatureId fid )
{
Expand Down
1 change: 1 addition & 0 deletions src/app/qgsattributetabledialog.h
Expand Up @@ -242,6 +242,7 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib

void updateMultiEditButtonState();
void deleteFeature( QgsFeatureId fid );
void blockCacheUpdateSignals( const bool block );

friend class TestQgsAttributeTable;
};
Expand Down
11 changes: 9 additions & 2 deletions src/app/qgsfieldcalculator.cpp
Expand Up @@ -163,8 +163,10 @@ void QgsFieldCalculator::accept()
{
builder->saveToRecent( QStringLiteral( "fieldcalc" ) );

if ( !mVectorLayer )
if ( ! mVectorLayer )
{
return;
}

// Set up QgsDistanceArea each time we (re-)calculate
QgsDistanceArea myDa;
Expand Down Expand Up @@ -265,6 +267,10 @@ void QgsFieldCalculator::accept()
return;
}

// Begin feature modifications, block updates for attr tables
// connected to this layer
QgisApp::instance()->blockAttributeTableUpdates( mVectorLayer, true );

//go through all the features and change the new attribute
QgsFeature feature;
bool calculationSuccess = true;
Expand Down Expand Up @@ -315,6 +321,8 @@ void QgsFieldCalculator::accept()
rownum++;
}

QgisApp::instance()->blockAttributeTableUpdates( mVectorLayer, false );

QApplication::restoreOverrideCursor();

if ( !calculationSuccess )
Expand All @@ -323,7 +331,6 @@ void QgsFieldCalculator::accept()
mVectorLayer->destroyEditCommand();
return;
}

mVectorLayer->endEditCommand();
}
QDialog::accept();
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -1535,6 +1535,7 @@ void QgsApplication::collectTranslatableObjects( QgsTranslationContext *translat
emit requestForTranslatableObjects( translationContext );
}


QString QgsApplication::nullRepresentation()
{
ApplicationMembers *appMembers = members();
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsapplication.h
Expand Up @@ -757,6 +757,7 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
void collectTranslatableObjects( QgsTranslationContext *translationContext );


#ifdef SIP_RUN
SIP_IF_FEATURE( ANDROID )
//dummy method to workaround sip generation issue
Expand Down Expand Up @@ -788,6 +789,7 @@ class CORE_EXPORT QgsApplication : public QApplication
*/
void requestForTranslatableObjects( QgsTranslationContext *translationContext );


private:

static void copyPath( const QString &src, const QString &dst );
Expand Down
2 changes: 2 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -2973,6 +2973,8 @@ bool QgsVectorLayer::rollBack( bool deleteBuffer )

mEditBuffer->rollBack();

emit afterRollBack();

if ( isModified() )
{
// new undo stack roll back method
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -2167,6 +2167,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
//! Is emitted, before changes are rolled back
void beforeRollBack();

/**
* Is emitted, after changes are rolled back
* \since QGIS 3.4
*/
void afterRollBack();

/**
* Will be emitted, when a new attribute has been added to this vector layer.
* Applies only to types QgsFields::OriginEdit, QgsFields::OriginProvider and QgsFields::OriginExpression
Expand Down

0 comments on commit 096b4ce

Please sign in to comment.