Skip to content

Commit

Permalink
Fixes crash when displaying relation editor
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Cabieces authored and Hugo Mercier committed Mar 17, 2020
1 parent 9dc1ade commit 1c9e032
Show file tree
Hide file tree
Showing 14 changed files with 69 additions and 26 deletions.
Expand Up @@ -77,6 +77,14 @@ Returns the related feature foreign keys
%End

void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar );
%Docstring
Sets the editor ``context``

.. note::

if context cadDockWidget is null, it won't be possible to digitize
the geometry of a referenced feature from this widget
%End

bool embedForm();
%Docstring
Expand Down
5 changes: 5 additions & 0 deletions python/gui/auto_generated/qgsrelationeditorwidget.sip.in
Expand Up @@ -74,6 +74,11 @@ Sets the ``feature`` being edited and updates the UI unless ``update`` is set to
void setEditorContext( const QgsAttributeEditorContext &context );
%Docstring
Sets the editor ``context``

.. note::

if context cadDockWidget is null, it won't be possible to digitize
the geometry of a referencing feature from this widget
%End

QgsIFeatureSelectionManager *featureSelectionManager();
Expand Down
12 changes: 11 additions & 1 deletion src/app/qgisapp.cpp
Expand Up @@ -9286,7 +9286,7 @@ void QgisApp::modifyAttributesOfSelectedFeatures()

//dummy feature
QgsFeature f;
QgsAttributeEditorContext context;
QgsAttributeEditorContext context( createAttributeEditorContext() );
context.setAllowCustomUi( false );
context.setVectorLayerTools( mVectorLayerTools );
context.setCadDockWidget( mAdvancedDigitizingDockWidget );
Expand Down Expand Up @@ -15572,3 +15572,13 @@ void QgisApp::triggerCrashHandler()
RaiseException( 0x12345678, 0, 0, nullptr );
#endif
}

QgsAttributeEditorContext QgisApp::createAttributeEditorContext()
{
QgsAttributeEditorContext context;
context.setVectorLayerTools( vectorLayerTools() );
context.setMapCanvas( mapCanvas() );
context.setCadDockWidget( cadDockWidget() );
context.setMainMessageBar( messageBar() );
return context;
}
6 changes: 6 additions & 0 deletions src/app/qgisapp.h
Expand Up @@ -1109,6 +1109,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
//! Create a new spatial bookmark
void newBookmark( bool inProject = false );

/**
* Creates a default attribute editor context using the main map canvas and the main edit tools and message bar
* \since QGIS 3.12
*/
QgsAttributeEditorContext createAttributeEditorContext();

protected:

//! Handle state changes (WindowTitleChange)
Expand Down
6 changes: 1 addition & 5 deletions src/app/qgisappinterface.cpp
Expand Up @@ -755,12 +755,8 @@ QgsAttributeDialog *QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeat
myDa.setSourceCrs( l->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );

QgsAttributeEditorContext context;
QgsAttributeEditorContext context( QgisApp::instance()->createAttributeEditorContext() );
context.setDistanceArea( myDa );
context.setVectorLayerTools( qgis->vectorLayerTools() );
context.setMapCanvas( qgis->mapCanvas() );
context.setCadDockWidget( qgis->cadDockWidget() );
context.setMainMessageBar( qgis->messageBar() );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, qgis, true, context );
if ( !feature.isValid() )
{
Expand Down
11 changes: 4 additions & 7 deletions src/app/qgsattributetabledialog.cpp
Expand Up @@ -152,12 +152,9 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
QgsDistanceArea da;
da.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
mEditorContext.setDistanceArea( da );

mEditorContext.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );
mEditorContext.setMapCanvas( QgisApp::instance()->mapCanvas() );
mEditorContext.setMainMessageBar( QgisApp::instance()->messageBar() );
mEditorContext.setCadDockWidget( QgisApp::instance()->cadDockWidget() );
QgsAttributeEditorContext editorContext = QgisApp::instance()->createAttributeEditorContext();
editorContext.setDistanceArea( da );

QgsFeatureRequest r;
bool needsGeom = false;
Expand All @@ -177,12 +174,12 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
r.setFlags( QgsFeatureRequest::NoGeometry );

// Initialize dual view
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, mEditorContext, false );
mMainView->init( mLayer, QgisApp::instance()->mapCanvas(), r, editorContext, false );

QgsAttributeTableConfig config = mLayer->attributeTableConfig();
mMainView->setAttributeTableConfig( config );

mFeatureFilterWidget->init( mLayer, mEditorContext, mMainView, QgisApp::instance()->messageBar(), QgisApp::instance()->messageTimeout() );
mFeatureFilterWidget->init( mLayer, editorContext, mMainView, QgisApp::instance()->messageBar(), QgisApp::instance()->messageTimeout() );

mActionFeatureActions = new QToolButton();
mActionFeatureActions->setAutoRaise( false );
Expand Down
1 change: 0 additions & 1 deletion src/app/qgsattributetabledialog.h
Expand Up @@ -221,7 +221,6 @@ class APP_EXPORT QgsAttributeTableDialog : public QDialog, private Ui::QgsAttrib

QPointer< QgsVectorLayer > mLayer = nullptr;
QStringList mVisibleFields;
QgsAttributeEditorContext mEditorContext;

void updateMultiEditButtonState();
void deleteFeature( QgsFeatureId fid );
Expand Down
7 changes: 2 additions & 5 deletions src/app/qgsfeatureaction.cpp
Expand Up @@ -53,22 +53,19 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
{
QgsFeature *f = cloneFeature ? new QgsFeature( *mFeature ) : mFeature;

QgsAttributeEditorContext context;
QgsAttributeEditorContext context( QgisApp::instance()->createAttributeEditorContext() );

QgsDistanceArea myDa;

myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );

context.setDistanceArea( myDa );
context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );
context.setMapCanvas( QgisApp::instance()->mapCanvas() );
context.setCadDockWidget( QgisApp::instance()->cadDockWidget() );
context.setMainMessageBar( QgisApp::instance()->messageBar() );
context.setFormMode( QgsAttributeEditorContext::StandaloneDialog );

QgsAttributeDialog *dialog = new QgsAttributeDialog( mLayer, f, cloneFeature, parentWidget(), true, context );
dialog->setWindowFlags( dialog->windowFlags() | Qt::Tool );

dialog->setObjectName( QStringLiteral( "featureactiondlg:%1:%2" ).arg( mLayer->id() ).arg( f->id() ) );

QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral( "Feature" ) );
Expand Down
6 changes: 5 additions & 1 deletion src/app/qgsmaptoolfillring.cpp
Expand Up @@ -164,7 +164,11 @@ void QgsMapToolFillRing::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
}
else
{
QgsAttributeDialog *dialog = new QgsAttributeDialog( vlayer, &ft, false, nullptr, true );
QgsAttributeEditorContext context;
// don't set cadDockwidget in context because we don't want to be able to create geometries from this dialog
// there is one modified and one created feature, so it's a mess of we start to digitize a relation feature geometry
context.setVectorLayerTools( QgisApp::instance()->vectorLayerTools() );
QgsAttributeDialog *dialog = new QgsAttributeDialog( vlayer, &ft, false, nullptr, true, context );
dialog->setMode( QgsAttributeEditorContext::AddFeatureMode );
res = dialog->exec(); // will also add the feature
}
Expand Down
11 changes: 8 additions & 3 deletions src/gui/editorwidgets/qgsrelationreferencewidget.cpp
Expand Up @@ -156,6 +156,7 @@ QgsRelationReferenceWidget::QgsRelationReferenceWidget( QWidget *parent )
mHighlightFeatureButton->hide();
mAttributeEditorFrame->hide();
mInvalidLabel->hide();
mAddEntryButton->hide();

// connect buttons
connect( mOpenFormButton, &QAbstractButton::clicked, this, &QgsRelationReferenceWidget::openForm );
Expand Down Expand Up @@ -429,8 +430,12 @@ void QgsRelationReferenceWidget::setEditorContext( const QgsAttributeEditorConte
mMapToolIdentify.reset( new QgsMapToolIdentifyFeature( mCanvas ) );
mMapToolIdentify->setButton( mMapIdentificationButton );

mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( mCanvas, context.cadDockWidget() ) );
mMapToolDigitize->setButton( mAddEntryButton );
if ( mEditorContext.cadDockWidget() )
{
mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( mCanvas, mEditorContext.cadDockWidget() ) );
mMapToolDigitize->setButton( mAddEntryButton );
updateAddEntryButton();
}
}

void QgsRelationReferenceWidget::setEmbedForm( bool display )
Expand Down Expand Up @@ -1006,7 +1011,7 @@ void QgsRelationReferenceWidget::entryAdded( const QgsFeature &feat )

void QgsRelationReferenceWidget::updateAddEntryButton()
{
mAddEntryButton->setVisible( mAllowAddFeatures );
mAddEntryButton->setVisible( mAllowAddFeatures && mMapToolDigitize );
mAddEntryButton->setEnabled( mReferencedLayer && mReferencedLayer->isEditable() );
}

Expand Down
5 changes: 5 additions & 0 deletions src/gui/editorwidgets/qgsrelationreferencewidget.h
Expand Up @@ -112,6 +112,11 @@ class GUI_EXPORT QgsRelationReferenceWidget : public QWidget
*/
QVariantList foreignKeys() const;

/**
* Sets the editor \a context
* \note if context cadDockWidget is null, it won't be possible to digitize
* the geometry of a referenced feature from this widget
*/
void setEditorContext( const QgsAttributeEditorContext &context, QgsMapCanvas *canvas, QgsMessageBar *messageBar );

//! determines if the form of the related feature will be shown
Expand Down
Expand Up @@ -88,6 +88,7 @@ void QgsRelationReferenceWidgetWrapper::initWidget( QWidget *editor )
mWidget->setReadOnlySelector( true );
mWidget->setAllowMapIdentification( false );
mWidget->setOpenFormButtonVisible( false );
mWidget->setAllowAddFeatures( false );
break;
}
ctx = ctx->parentContext();
Expand Down
14 changes: 11 additions & 3 deletions src/gui/qgsrelationeditorwidget.cpp
Expand Up @@ -285,7 +285,7 @@ void QgsRelationEditorWidget::initDualView( QgsVectorLayer *layer, const QgsFeat
text = tr( "Add Polygon Feature" );
}

if ( text.isEmpty() )
if ( text.isEmpty() || !mEditorContext.mapCanvas() || !mEditorContext.cadDockWidget() )
{
mAddFeatureGeometryButton->setVisible( false );
}
Expand Down Expand Up @@ -368,8 +368,12 @@ void QgsRelationEditorWidget::setRelations( const QgsRelation &relation, const Q
void QgsRelationEditorWidget::setEditorContext( const QgsAttributeEditorContext &context )
{
mEditorContext = context;
mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( context.mapCanvas(), context.cadDockWidget() ) );
mMapToolDigitize->setButton( mAddFeatureGeometryButton );

if ( context.mapCanvas() && context.cadDockWidget() )
{
mMapToolDigitize.reset( new QgsMapToolDigitizeFeature( context.mapCanvas(), context.cadDockWidget() ) );
mMapToolDigitize->setButton( mAddFeatureGeometryButton );
}
}

QgsIFeatureSelectionManager *QgsRelationEditorWidget::featureSelectionManager()
Expand Down Expand Up @@ -448,6 +452,9 @@ void QgsRelationEditorWidget::addFeatureGeometry()
layer = mRelation.referencingLayer();

mMapToolDigitize->setLayer( layer );

// window is always on top, so we hide it to digitize without seeing it
window()->setVisible( false );
setMapTool( mMapToolDigitize );

connect( mMapToolDigitize, &QgsMapToolDigitizeFeature::digitizingCompleted, this, &QgsRelationEditorWidget::onDigitizingCompleted );
Expand Down Expand Up @@ -984,6 +991,7 @@ void QgsRelationEditorWidget::onKeyPressed( QKeyEvent *e )

void QgsRelationEditorWidget::mapToolDeactivated()
{
window()->setVisible( true );
window()->raise();
window()->activateWindow();

Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsrelationeditorwidget.h
Expand Up @@ -134,6 +134,8 @@ class GUI_EXPORT QgsRelationEditorWidget : public QgsCollapsibleGroupBox

/**
* Sets the editor \a context
* \note if context cadDockWidget is null, it won't be possible to digitize
* the geometry of a referencing feature from this widget
*/
void setEditorContext( const QgsAttributeEditorContext &context );

Expand Down

0 comments on commit 1c9e032

Please sign in to comment.