Fix attribute dialog crash on close

This commit is contained in:
Matthias Kuhn 2014-07-11 20:52:43 +02:00
parent 677abbf3dd
commit ad5aa3050e
5 changed files with 38 additions and 97 deletions

View File

@ -628,7 +628,7 @@ QDialog* QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeature &featur
myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) ); myDa.setEllipsoid( QgsProject::instance()->readEntry( "Measure", "/Ellipsoid", GEO_NONE ) );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true ); QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
return dialog->dialog(); return dialog;
} }
QgsVectorLayerTools* QgisAppInterface::vectorLayerTools() QgsVectorLayerTools* QgisAppInterface::vectorLayerTools()

View File

@ -64,11 +64,11 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
if ( mLayer->actions()->size() > 0 ) if ( mLayer->actions()->size() > 0 )
{ {
dialog->dialog()->setContextMenuPolicy( Qt::ActionsContextMenu ); dialog->setContextMenuPolicy( Qt::ActionsContextMenu );
QAction *a = new QAction( tr( "Run actions" ), dialog->dialog() ); QAction *a = new QAction( tr( "Run actions" ), dialog );
a->setEnabled( false ); a->setEnabled( false );
dialog->dialog()->addAction( a ); dialog->addAction( a );
for ( int i = 0; i < mLayer->actions()->size(); i++ ) for ( int i = 0; i < mLayer->actions()->size(); i++ )
{ {
@ -77,11 +77,11 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
if ( !action.runable() ) if ( !action.runable() )
continue; continue;
QgsFeatureAction *a = new QgsFeatureAction( action.name(), *f, mLayer, i, -1, dialog->dialog() ); QgsFeatureAction *a = new QgsFeatureAction( action.name(), *f, mLayer, i, -1, dialog );
dialog->dialog()->addAction( a ); dialog->addAction( a );
connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) ); connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) );
QAbstractButton *pb = dialog->dialog()->findChild<QAbstractButton *>( action.name() ); QAbstractButton *pb = dialog->findChild<QAbstractButton *>( action.name() );
if ( pb ) if ( pb )
connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) ); connect( pb, SIGNAL( clicked() ), a, SLOT( execute() ) );
} }

View File

@ -182,14 +182,14 @@ void QgsRelationReferenceWidget::referenceChanged( int index )
// Backup old dialog and delete only after creating the new dialog, so we can "hot-swap" the contained QgsFeature // Backup old dialog and delete only after creating the new dialog, so we can "hot-swap" the contained QgsFeature
QgsAttributeDialog* oldDialog = mAttributeDialog; QgsAttributeDialog* oldDialog = mAttributeDialog;
if ( mAttributeDialog && mAttributeDialog->dialog() ) if ( mAttributeDialog )
{ {
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() ); mAttributeEditorLayout->removeWidget( mAttributeDialog );
} }
// TODO: Get a proper QgsDistanceArea thingie // TODO: Get a proper QgsDistanceArea thingie
mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, mAttributeEditorFrame, false, mEditorContext ); mAttributeDialog = new QgsAttributeDialog( mReferencedLayer, new QgsFeature( feat ), true, mAttributeEditorFrame, false, mEditorContext );
QWidget* attrDialog = mAttributeDialog->dialog(); QWidget* attrDialog = mAttributeDialog;
attrDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window attrDialog->setWindowFlags( Qt::Widget ); // Embed instead of opening as window
mAttributeEditorLayout->addWidget( attrDialog ); mAttributeEditorLayout->addWidget( attrDialog );
attrDialog->show(); attrDialog->show();

View File

@ -25,7 +25,7 @@
QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent, bool showDialogButtons ) QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeature, bool featureOwner, QgsDistanceArea myDa, QWidget* parent, bool showDialogButtons )
: QObject( parent ) : QDialog( parent )
, mHighlight( 0 ) , mHighlight( 0 )
{ {
QgsAttributeEditorContext context; QgsAttributeEditorContext context;
@ -40,7 +40,7 @@ QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeat
} }
QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeature, bool featureOwner, QWidget* parent, bool showDialogButtons, QgsAttributeEditorContext context ) QgsAttributeDialog::QgsAttributeDialog( QgsVectorLayer* vl, QgsFeature* thepFeature, bool featureOwner, QWidget* parent, bool showDialogButtons, QgsAttributeEditorContext context )
: QObject( parent ) : QDialog( parent )
, mHighlight( 0 ) , mHighlight( 0 )
{ {
init( vl, thepFeature, context, parent ); init( vl, thepFeature, context, parent );
@ -60,25 +60,17 @@ QgsAttributeDialog::~QgsAttributeDialog()
delete mHighlight; delete mHighlight;
} }
delete mDialog; saveGeometry();
} }
void QgsAttributeDialog::saveGeometry() void QgsAttributeDialog::saveGeometry()
{ {
if ( mDialog ) QSettings().setValue( mSettingsPath + "geometry", QDialog::saveGeometry() );
{
QSettings settings;
settings.setValue( mSettingsPath + "geometry", mDialog->saveGeometry() );
}
} }
void QgsAttributeDialog::restoreGeometry() void QgsAttributeDialog::restoreGeometry()
{ {
if ( mDialog ) QDialog::restoreGeometry( QSettings().value( mSettingsPath + "geometry" ).toByteArray() );
{
QSettings settings;
mDialog->restoreGeometry( settings.value( mSettingsPath + "geometry" ).toByteArray() );
}
} }
void QgsAttributeDialog::setHighlight( QgsHighlight* h ) void QgsAttributeDialog::setHighlight( QgsHighlight* h )
@ -91,73 +83,28 @@ void QgsAttributeDialog::setHighlight( QgsHighlight* h )
void QgsAttributeDialog::accept() void QgsAttributeDialog::accept()
{ {
mAttributeForm->save(); mAttributeForm->save();
QDialog::accept();
} }
int QgsAttributeDialog::exec() void QgsAttributeDialog::show( bool autoDelete )
{ {
if ( mDialog ) if ( autoDelete )
{ setAttribute( Qt::WA_DeleteOnClose );
return mDialog->exec();
}
else
{
QgsDebugMsg( "No dialog" );
return QDialog::Accepted;
}
}
void QgsAttributeDialog::show() QDialog::show();
{ raise();
if ( mDialog ) activateWindow();
{
mDialog->setAttribute( Qt::WA_DeleteOnClose );
mDialog->show();
mDialog->raise();
mDialog->activateWindow();
mDialog->installEventFilter( this );
setParent( mDialog );
}
}
bool QgsAttributeDialog::eventFilter( QObject* obj, QEvent* e )
{
if ( mHighlight && obj == mDialog )
{
switch ( e->type() )
{
case QEvent::WindowActivate:
mHighlight->show();
break;
case QEvent::WindowDeactivate:
mHighlight->hide();
break;
default:
break;
}
}
return false;
}
void QgsAttributeDialog::onDialogFinished( int result )
{
Q_UNUSED( result )
saveGeometry();
} }
void QgsAttributeDialog::init( QgsVectorLayer* layer, QgsFeature* feature, QgsAttributeEditorContext& context, QWidget* parent ) void QgsAttributeDialog::init( QgsVectorLayer* layer, QgsFeature* feature, QgsAttributeEditorContext& context, QWidget* parent )
{ {
mDialog = new QDialog( parent ); setWindowTitle( tr( "Feature Attributes" ) );
mDialog->setWindowTitle( tr( "Feature Attributes" ) ); setLayout( new QGridLayout() );
mDialog->setLayout( new QGridLayout() ); layout()->setMargin( 0 );
mDialog->layout()->setMargin( 0 );
mAttributeForm = new QgsAttributeForm( layer, *feature, context, parent ); mAttributeForm = new QgsAttributeForm( layer, *feature, context, parent );
mDialog->layout()->addWidget( mAttributeForm ); layout()->addWidget( mAttributeForm );
QDialogButtonBox* buttonBox = mAttributeForm->findChild<QDialogButtonBox*>(); QDialogButtonBox* buttonBox = mAttributeForm->findChild<QDialogButtonBox*>();
connect( buttonBox, SIGNAL( rejected() ), mDialog, SLOT( reject() ) ); connect( buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
connect( buttonBox, SIGNAL( accepted() ), mDialog, SLOT( accept() ) ); connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
connect( mDialog, SIGNAL( finished( int ) ), this, SLOT( onDialogFinished( int ) ) );
restoreGeometry(); restoreGeometry();
} }

View File

@ -22,7 +22,6 @@
#include "qgsattributeform.h" #include "qgsattributeform.h"
#include <QDialog> #include <QDialog>
#include <QPointer>
class QLayout; class QLayout;
@ -33,7 +32,7 @@ class QgsHighlight;
class QgsVectorLayer; class QgsVectorLayer;
class QgsVectorLayerTools; class QgsVectorLayerTools;
class GUI_EXPORT QgsAttributeDialog : public QObject class GUI_EXPORT QgsAttributeDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
@ -83,7 +82,14 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
*/ */
void setHighlight( QgsHighlight *h ); void setHighlight( QgsHighlight *h );
QDialog *dialog() { return mDialog; } /**
* @brief Returns reference to self. Only here for legacy compliance
*
* @return this
*
* @deprecated Do not use. Just use this object itself. Or QgsAttributeForm if you want to embed.
*/
Q_DECL_DEPRECATED QDialog *dialog() { return this; }
QgsAttributeForm* attributeForm() { return mAttributeForm; } QgsAttributeForm* attributeForm() { return mAttributeForm; }
@ -115,25 +121,13 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
public slots: public slots:
void accept(); void accept();
//! Show the dialog and block the application until the dialog is closed. Ownership of this object is not changed.
int exec();
//! Show the dialog non-blocking. Reparents this dialog to be a child of the dialog form and is deleted when //! Show the dialog non-blocking. Reparents this dialog to be a child of the dialog form and is deleted when
//! closed. //! closed.
void show(); void show( bool autoDelete = true );
protected:
bool eventFilter( QObject *obj, QEvent *e );
private slots:
void onDialogFinished( int result );
private: private:
void init( QgsVectorLayer* layer, QgsFeature* feature, QgsAttributeEditorContext& context, QWidget* parent ); void init( QgsVectorLayer* layer, QgsFeature* feature, QgsAttributeEditorContext& context, QWidget* parent );
// Using a guarded pointer we can savely delete the dialog in the destructor even
// when the dialog is this object's parent
QPointer<QDialog> mDialog;
QString mSettingsPath; QString mSettingsPath;
// Used to sync multiple widgets for the same field // Used to sync multiple widgets for the same field
QgsHighlight *mHighlight; QgsHighlight *mHighlight;