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 ) );
QgsAttributeDialog *dialog = new QgsAttributeDialog( l, &feature, false, NULL, true );
return dialog->dialog();
return dialog;
}
QgsVectorLayerTools* QgisAppInterface::vectorLayerTools()

View File

@ -64,11 +64,11 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
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 );
dialog->dialog()->addAction( a );
dialog->addAction( a );
for ( int i = 0; i < mLayer->actions()->size(); i++ )
{
@ -77,11 +77,11 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
if ( !action.runable() )
continue;
QgsFeatureAction *a = new QgsFeatureAction( action.name(), *f, mLayer, i, -1, dialog->dialog() );
dialog->dialog()->addAction( a );
QgsFeatureAction *a = new QgsFeatureAction( action.name(), *f, mLayer, i, -1, dialog );
dialog->addAction( a );
connect( a, SIGNAL( triggered() ), a, SLOT( execute() ) );
QAbstractButton *pb = dialog->dialog()->findChild<QAbstractButton *>( action.name() );
QAbstractButton *pb = dialog->findChild<QAbstractButton *>( action.name() );
if ( pb )
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
QgsAttributeDialog* oldDialog = mAttributeDialog;
if ( mAttributeDialog && mAttributeDialog->dialog() )
if ( mAttributeDialog )
{
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
mAttributeEditorLayout->removeWidget( mAttributeDialog );
}
// TODO: Get a proper QgsDistanceArea thingie
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
mAttributeEditorLayout->addWidget( attrDialog );
attrDialog->show();

View File

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

View File

@ -22,7 +22,6 @@
#include "qgsattributeform.h"
#include <QDialog>
#include <QPointer>
class QLayout;
@ -33,7 +32,7 @@ class QgsHighlight;
class QgsVectorLayer;
class QgsVectorLayerTools;
class GUI_EXPORT QgsAttributeDialog : public QObject
class GUI_EXPORT QgsAttributeDialog : public QDialog
{
Q_OBJECT
@ -83,7 +82,14 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
*/
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; }
@ -115,25 +121,13 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
public slots:
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
//! closed.
void show();
protected:
bool eventFilter( QObject *obj, QEvent *e );
private slots:
void onDialogFinished( int result );
void show( bool autoDelete = true );
private:
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;
// Used to sync multiple widgets for the same field
QgsHighlight *mHighlight;