[bugfix] Do not crash when layer is destroyed while loading

Fixes #17636 QGIS crashes when a layer is removed
while loading the attribute table
This commit is contained in:
Alessandro Pasotti 2017-12-09 16:07:02 +01:00
parent 53ebe050bd
commit e479b71594
5 changed files with 85 additions and 48 deletions

View File

@ -208,6 +208,12 @@ class QgsDualView : QStackedWidget
%Docstring %Docstring
Copy the content of the selected cell in the clipboard. Copy the content of the selected cell in the clipboard.
.. versionadded:: 1.16 .. versionadded:: 1.16
%End
void cancelProgress( );
%Docstring
Cancel the progress dialog (if any)
.. versionadded:: 3.0
%End %End
signals: signals:

View File

@ -69,7 +69,7 @@ QgsExpressionContext QgsAttributeTableDialog::createExpressionContext() const
void QgsAttributeTableDialog::updateMultiEditButtonState() void QgsAttributeTableDialog::updateMultiEditButtonState()
{ {
if ( mLayer->editFormConfig().layout() == QgsEditFormConfig::UiFileLayout ) if ( ! mLayer || ( mLayer->editFormConfig().layout() == QgsEditFormConfig::UiFileLayout ) )
return; return;
mActionToggleMultiEdit->setEnabled( mLayer->isEditable() ); mActionToggleMultiEdit->setEnabled( mLayer->isEditable() );
@ -199,7 +199,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
// info from layer to table // info from layer to table
connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsAttributeTableDialog::editingToggled ); connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsAttributeTableDialog::editingToggled );
connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsAttributeTableDialog::editingToggled ); connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsAttributeTableDialog::editingToggled );
connect( mLayer, &QObject::destroyed, this, &QWidget::close ); connect( mLayer, &QObject::destroyed, mMainView, &QgsDualView::cancelProgress );
connect( mLayer, &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableDialog::updateTitle );
connect( mLayer, &QgsVectorLayer::featureAdded, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::featureAdded, this, &QgsAttributeTableDialog::updateTitle );
connect( mLayer, &QgsVectorLayer::featuresDeleted, this, &QgsAttributeTableDialog::updateTitle ); connect( mLayer, &QgsVectorLayer::featuresDeleted, this, &QgsAttributeTableDialog::updateTitle );
@ -292,6 +292,9 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
break; break;
} }
// Layer might have been destroyed while loading!
if ( mLayer )
{
mUpdateExpressionText->registerExpressionContextGenerator( this ); mUpdateExpressionText->registerExpressionContextGenerator( this );
mFieldCombo->setFilters( QgsFieldProxyModel::AllTypes | QgsFieldProxyModel::HideReadOnly ); mFieldCombo->setFilters( QgsFieldProxyModel::AllTypes | QgsFieldProxyModel::HideReadOnly );
mFieldCombo->setLayer( mLayer ); mFieldCombo->setLayer( mLayer );
@ -345,6 +348,13 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
} }
editingToggled(); editingToggled();
// Close and delete if the layer has been destroyed
connect( mLayer, &QObject::destroyed, this, &QWidget::close );
}
else
{
QWidget::close();
}
} }
QgsAttributeTableDialog::~QgsAttributeTableDialog() QgsAttributeTableDialog::~QgsAttributeTableDialog()
@ -354,6 +364,10 @@ QgsAttributeTableDialog::~QgsAttributeTableDialog()
void QgsAttributeTableDialog::updateTitle() void QgsAttributeTableDialog::updateTitle()
{ {
if ( ! mLayer )
{
return;
}
QWidget *w = mDock ? qobject_cast<QWidget *>( mDock ) : qobject_cast<QWidget *>( this ); QWidget *w = mDock ? qobject_cast<QWidget *>( mDock ) : qobject_cast<QWidget *>( this );
w->setWindowTitle( tr( " %1 :: Features Total: %2, Filtered: %3, Selected: %4" ) w->setWindowTitle( tr( " %1 :: Features Total: %2, Filtered: %3, Selected: %4" )
.arg( mLayer->name() ) .arg( mLayer->name() )

View File

@ -230,7 +230,7 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib
QMenu *mFilterColumnsMenu = nullptr; QMenu *mFilterColumnsMenu = nullptr;
QSignalMapper *mFilterActionMapper = nullptr; QSignalMapper *mFilterActionMapper = nullptr;
QgsVectorLayer *mLayer = nullptr; QPointer< QgsVectorLayer > mLayer = nullptr;
QgsSearchWidgetWrapper *mCurrentSearchWidgetWrapper = nullptr; QgsSearchWidgetWrapper *mCurrentSearchWidgetWrapper = nullptr;
QStringList mVisibleFields; QStringList mVisibleFields;
QgsAttributeEditorContext mEditorContext; QgsAttributeEditorContext mEditorContext;

View File

@ -318,6 +318,10 @@ void QgsDualView::restoreRecentDisplayExpressions()
void QgsDualView::saveRecentDisplayExpressions() const void QgsDualView::saveRecentDisplayExpressions() const
{ {
if ( ! mLayer )
{
return;
}
QList<QAction *> actions = mFeatureListPreviewButton->actions(); QList<QAction *> actions = mFeatureListPreviewButton->actions();
// Remove existing same action // Remove existing same action
@ -397,6 +401,7 @@ void QgsDualView::insertRecentlyUsedDisplayExpression( const QString &expression
mLastDisplayExpressionAction = previewAction; mLastDisplayExpressionAction = previewAction;
} }
void QgsDualView::mFeatureList_aboutToChangeEditSelection( bool &ok ) void QgsDualView::mFeatureList_aboutToChangeEditSelection( bool &ok )
{ {
if ( mLayer->isEditable() && !mAttributeForm->save() ) if ( mLayer->isEditable() && !mAttributeForm->save() )
@ -515,6 +520,12 @@ void QgsDualView::copyCellContent() const
} }
} }
void QgsDualView::cancelProgress()
{
if ( mProgressDlg )
mProgressDlg->cancel();
}
void QgsDualView::hideEvent( QHideEvent *event ) void QgsDualView::hideEvent( QHideEvent *event )
{ {
Q_UNUSED( event ) Q_UNUSED( event )

View File

@ -236,6 +236,12 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
*/ */
void copyCellContent() const; void copyCellContent() const;
/**
* Cancel the progress dialog (if any)
* \since QGIS 3.0
*/
void cancelProgress( );
signals: signals:
/** /**
@ -360,7 +366,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
QAction *mLastDisplayExpressionAction = nullptr; QAction *mLastDisplayExpressionAction = nullptr;
QMenu *mHorizontalHeaderMenu = nullptr; QMenu *mHorizontalHeaderMenu = nullptr;
QgsVectorLayerCache *mLayerCache = nullptr; QgsVectorLayerCache *mLayerCache = nullptr;
QgsVectorLayer *mLayer = nullptr; QPointer< QgsVectorLayer > mLayer = nullptr;
QProgressDialog *mProgressDlg = nullptr; QProgressDialog *mProgressDlg = nullptr;
QgsIFeatureSelectionManager *mFeatureSelectionManager = nullptr; QgsIFeatureSelectionManager *mFeatureSelectionManager = nullptr;
QgsDistanceArea mDistanceArea; QgsDistanceArea mDistanceArea;