Skip to content
Permalink
Browse files

AttributeForm: Create a dummy button box for intercepting ok clicks

when the ok button is hidden and the accept was actually triggered
by something else. This allows to continue using custom validation
logic without changes.
Fixes #8885
  • Loading branch information
m-kuhn committed Nov 28, 2013
1 parent 08b43aa commit 999a996b733925c78082ffdbd66afea2b7a2c813
@@ -37,6 +37,7 @@ QgsDualView::QgsDualView( QWidget* parent )
, mEditorContext()
, mMasterModel( NULL )
, mAttributeDialog( NULL )
, mLayerCache( NULL )
, mProgressDlg( NULL )
, mFeatureSelectionManager( NULL )
{
@@ -190,14 +191,14 @@ void QgsDualView::columnBoxInit()

void QgsDualView::hideEvent( QHideEvent* event )
{
saveEditChanges();
QStackedWidget::hideEvent( event );
if ( saveEditChanges() )
QStackedWidget::hideEvent( event );
}

void QgsDualView::focusOutEvent( QFocusEvent* event )
{
saveEditChanges();
QStackedWidget::focusOutEvent( event );
if ( saveEditChanges() )
QStackedWidget::focusOutEvent( event );
}

void QgsDualView::setView( QgsDualView::ViewMode view )
@@ -257,35 +258,52 @@ void QgsDualView::initModels( QgsMapCanvas* mapCanvas, const QgsFeatureRequest&

void QgsDualView::on_mFeatureList_currentEditSelectionChanged( const QgsFeature &feat )
{
// Invalid feature? Strange: bail out
if ( !feat.isValid() )
return;

// We already show the feature in question: bail out
if ( mAttributeDialog && mAttributeDialog->feature()
&& mAttributeDialog->feature()->id() == feat.id() )
return;

bool dontChange = false;

// 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() )
{
saveEditChanges();
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
if ( saveEditChanges() )
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
else
dontChange = true;
}

mAttributeDialog = new QgsAttributeDialog( mLayerCache->layer(), new QgsFeature( feat ), true, this, false, mEditorContext );
mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() );
mAttributeDialog->dialog()->setVisible( true );
if ( !dontChange )
{
mAttributeDialog = new QgsAttributeDialog( mLayerCache->layer(), new QgsFeature( feat ), true, this, false, mEditorContext );
mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() );
mAttributeDialog->dialog()->setVisible( true );

delete oldDialog;
delete oldDialog;
}
else
{
setCurrentEditSelection( QgsFeatureIds() << oldDialog->feature()->id() );
}
}

void QgsDualView::setCurrentEditSelection( const QgsFeatureIds& fids )
{
mFeatureList->setEditSelection( fids );
}

void QgsDualView::saveEditChanges()
bool QgsDualView::saveEditChanges()
{
if ( mAttributeDialog && mAttributeDialog->dialog() )
{
if ( mLayerCache->layer() && mLayerCache->layer()->isEditable() )
if ( mAttributeDialog->editable() )
{
// Get the current (unedited) feature
QgsFeature srcFeat;
@@ -294,29 +312,47 @@ void QgsDualView::saveEditChanges()
QgsAttributes src = srcFeat.attributes();

// Let the dialog write the edited widget values to it's feature
mAttributeDialog->accept();
// Get the edited feature
const QgsAttributes &dst = mAttributeDialog->feature()->attributes();

if ( src.count() != dst.count() )
QDialogButtonBox* buttonBox = mAttributeDialog->dialog()->findChild<QDialogButtonBox*>();
if ( buttonBox && buttonBox->button( QDialogButtonBox::Ok ) )
{
// bail out
return;
QPushButton* okBtn = buttonBox->button( QDialogButtonBox::Ok );
okBtn->click();
}
else
{
mAttributeDialog->accept();
}

mLayerCache->layer()->beginEditCommand( tr( "Attributes changed" ) );

for ( int i = 0; i < dst.count(); ++i )
if ( mAttributeDialog->dialog()->result() == QDialog::Accepted )
{
if ( dst[i] != src[i] )
// Get the edited feature
const QgsAttributes &dst = mAttributeDialog->feature()->attributes();

if ( src.count() != dst.count() )
{
mLayerCache->layer()->changeAttributeValue( fid, i, dst[i] );
// bail out
return false;
}
}

mLayerCache->layer()->endEditCommand();
mLayerCache->layer()->beginEditCommand( tr( "Attributes changed" ) );

for ( int i = 0; i < dst.count(); ++i )
{
if ( dst[i] != src[i] )
{
mLayerCache->layer()->changeAttributeValue( fid, i, dst[i] );
}
}

mLayerCache->layer()->endEditCommand();
}
else
{
return false;
}
}
}
return true;
}

void QgsDualView::previewExpressionBuilder()
@@ -156,8 +156,11 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas

/**
* @brief saveEditChanges
*
* @return true if the saving was ok. false is possible due to connected
* validation logic.
*/
void saveEditChanges();
bool saveEditChanges();

/**
* Update the shown feature if an attribute changed
@@ -97,6 +97,16 @@ QString QgsFeatureListView::parserErrorString()
return mModel->parserErrorString();
}

QgsFeatureIds QgsFeatureListView::currentEditSelection()
{
QgsFeatureIds selection;
Q_FOREACH( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
{
selection << idx.data( QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
}
return selection;
}

void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
{
QPoint pos = event->pos();
@@ -100,6 +100,13 @@ class GUI_EXPORT QgsFeatureListView : public QListView
*/
QString parserErrorString();

/**
* Get the currentEditSelection
*
* @return A list of edited feature ids
*/
QgsFeatureIds currentEditSelection();

protected:
virtual void mouseMoveEvent( QMouseEvent *event );
virtual void mousePressEvent( QMouseEvent *event );
@@ -418,6 +418,8 @@ void QgsAttributeDialog::init()
}
}

mEditable = mLayer->isEditable();

if ( mDialog )
{
if ( mDialog->objectName().isEmpty() )
@@ -451,6 +453,16 @@ void QgsAttributeDialog::init()
{
if ( buttonBox )
{
// Add dummy buttons
if ( mLayer->isEditable() )
{
buttonBox->clear();

buttonBox->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
connect( buttonBox, SIGNAL( accepted() ), mDialog, SLOT( accept() ) );
connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
}

buttonBox->setVisible( false );
}
}
@@ -80,6 +80,13 @@ class GUI_EXPORT QgsAttributeDialog : public QObject

QgsFeature* feature() { return mFeature; }

/**
* Is this dialog editable?
*
* @return returns true, if this dialog was created in an editable manner.
*/
bool editable() { return mEditable; }

public slots:
void accept();

@@ -106,6 +113,9 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
bool mShowDialogButtons;
QString mReturnvarname;

// true if this dialog is editable
bool mEditable;

static int sFormCounter;
static QString sSettingsPath;
};

0 comments on commit 999a996

Please sign in to comment.
You can’t perform that action at this time.