Skip to content

Commit 999a996

Browse files
committed
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
1 parent 08b43aa commit 999a996

File tree

6 files changed

+105
-27
lines changed

6 files changed

+105
-27
lines changed

src/gui/attributetable/qgsdualview.cpp

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ QgsDualView::QgsDualView( QWidget* parent )
3737
, mEditorContext()
3838
, mMasterModel( NULL )
3939
, mAttributeDialog( NULL )
40+
, mLayerCache( NULL )
4041
, mProgressDlg( NULL )
4142
, mFeatureSelectionManager( NULL )
4243
{
@@ -190,14 +191,14 @@ void QgsDualView::columnBoxInit()
190191

191192
void QgsDualView::hideEvent( QHideEvent* event )
192193
{
193-
saveEditChanges();
194-
QStackedWidget::hideEvent( event );
194+
if ( saveEditChanges() )
195+
QStackedWidget::hideEvent( event );
195196
}
196197

197198
void QgsDualView::focusOutEvent( QFocusEvent* event )
198199
{
199-
saveEditChanges();
200-
QStackedWidget::focusOutEvent( event );
200+
if ( saveEditChanges() )
201+
QStackedWidget::focusOutEvent( event );
201202
}
202203

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

258259
void QgsDualView::on_mFeatureList_currentEditSelectionChanged( const QgsFeature &feat )
259260
{
261+
// Invalid feature? Strange: bail out
260262
if ( !feat.isValid() )
261263
return;
262264

265+
// We already show the feature in question: bail out
266+
if ( mAttributeDialog && mAttributeDialog->feature()
267+
&& mAttributeDialog->feature()->id() == feat.id() )
268+
return;
269+
270+
bool dontChange = false;
271+
263272
// Backup old dialog and delete only after creating the new dialog, so we can "hot-swap" the contained QgsFeature
264273
QgsAttributeDialog* oldDialog = mAttributeDialog;
265274

266275
if ( mAttributeDialog && mAttributeDialog->dialog() )
267276
{
268-
saveEditChanges();
269-
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
277+
if ( saveEditChanges() )
278+
mAttributeEditorLayout->removeWidget( mAttributeDialog->dialog() );
279+
else
280+
dontChange = true;
270281
}
271282

272-
mAttributeDialog = new QgsAttributeDialog( mLayerCache->layer(), new QgsFeature( feat ), true, this, false, mEditorContext );
273-
mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() );
274-
mAttributeDialog->dialog()->setVisible( true );
283+
if ( !dontChange )
284+
{
285+
mAttributeDialog = new QgsAttributeDialog( mLayerCache->layer(), new QgsFeature( feat ), true, this, false, mEditorContext );
286+
mAttributeEditorLayout->addWidget( mAttributeDialog->dialog() );
287+
mAttributeDialog->dialog()->setVisible( true );
275288

276-
delete oldDialog;
289+
delete oldDialog;
290+
}
291+
else
292+
{
293+
setCurrentEditSelection( QgsFeatureIds() << oldDialog->feature()->id() );
294+
}
277295
}
278296

279297
void QgsDualView::setCurrentEditSelection( const QgsFeatureIds& fids )
280298
{
281299
mFeatureList->setEditSelection( fids );
282300
}
283301

284-
void QgsDualView::saveEditChanges()
302+
bool QgsDualView::saveEditChanges()
285303
{
286304
if ( mAttributeDialog && mAttributeDialog->dialog() )
287305
{
288-
if ( mLayerCache->layer() && mLayerCache->layer()->isEditable() )
306+
if ( mAttributeDialog->editable() )
289307
{
290308
// Get the current (unedited) feature
291309
QgsFeature srcFeat;
@@ -294,29 +312,47 @@ void QgsDualView::saveEditChanges()
294312
QgsAttributes src = srcFeat.attributes();
295313

296314
// Let the dialog write the edited widget values to it's feature
297-
mAttributeDialog->accept();
298-
// Get the edited feature
299-
const QgsAttributes &dst = mAttributeDialog->feature()->attributes();
300-
301-
if ( src.count() != dst.count() )
315+
QDialogButtonBox* buttonBox = mAttributeDialog->dialog()->findChild<QDialogButtonBox*>();
316+
if ( buttonBox && buttonBox->button( QDialogButtonBox::Ok ) )
302317
{
303-
// bail out
304-
return;
318+
QPushButton* okBtn = buttonBox->button( QDialogButtonBox::Ok );
319+
okBtn->click();
320+
}
321+
else
322+
{
323+
mAttributeDialog->accept();
305324
}
306325

307-
mLayerCache->layer()->beginEditCommand( tr( "Attributes changed" ) );
308-
309-
for ( int i = 0; i < dst.count(); ++i )
326+
if ( mAttributeDialog->dialog()->result() == QDialog::Accepted )
310327
{
311-
if ( dst[i] != src[i] )
328+
// Get the edited feature
329+
const QgsAttributes &dst = mAttributeDialog->feature()->attributes();
330+
331+
if ( src.count() != dst.count() )
312332
{
313-
mLayerCache->layer()->changeAttributeValue( fid, i, dst[i] );
333+
// bail out
334+
return false;
314335
}
315-
}
316336

317-
mLayerCache->layer()->endEditCommand();
337+
mLayerCache->layer()->beginEditCommand( tr( "Attributes changed" ) );
338+
339+
for ( int i = 0; i < dst.count(); ++i )
340+
{
341+
if ( dst[i] != src[i] )
342+
{
343+
mLayerCache->layer()->changeAttributeValue( fid, i, dst[i] );
344+
}
345+
}
346+
347+
mLayerCache->layer()->endEditCommand();
348+
}
349+
else
350+
{
351+
return false;
352+
}
318353
}
319354
}
355+
return true;
320356
}
321357

322358
void QgsDualView::previewExpressionBuilder()

src/gui/attributetable/qgsdualview.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,11 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
156156

157157
/**
158158
* @brief saveEditChanges
159+
*
160+
* @return true if the saving was ok. false is possible due to connected
161+
* validation logic.
159162
*/
160-
void saveEditChanges();
163+
bool saveEditChanges();
161164

162165
/**
163166
* Update the shown feature if an attribute changed

src/gui/attributetable/qgsfeaturelistview.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ QString QgsFeatureListView::parserErrorString()
9797
return mModel->parserErrorString();
9898
}
9999

100+
QgsFeatureIds QgsFeatureListView::currentEditSelection()
101+
{
102+
QgsFeatureIds selection;
103+
Q_FOREACH( QModelIndex idx, mCurrentEditSelectionModel->selectedIndexes() )
104+
{
105+
selection << idx.data( QgsAttributeTableModel::FeatureIdRole ).value<QgsFeatureId>();
106+
}
107+
return selection;
108+
}
109+
100110
void QgsFeatureListView::mousePressEvent( QMouseEvent *event )
101111
{
102112
QPoint pos = event->pos();

src/gui/attributetable/qgsfeaturelistview.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ class GUI_EXPORT QgsFeatureListView : public QListView
100100
*/
101101
QString parserErrorString();
102102

103+
/**
104+
* Get the currentEditSelection
105+
*
106+
* @return A list of edited feature ids
107+
*/
108+
QgsFeatureIds currentEditSelection();
109+
103110
protected:
104111
virtual void mouseMoveEvent( QMouseEvent *event );
105112
virtual void mousePressEvent( QMouseEvent *event );

src/gui/qgsattributedialog.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ void QgsAttributeDialog::init()
418418
}
419419
}
420420

421+
mEditable = mLayer->isEditable();
422+
421423
if ( mDialog )
422424
{
423425
if ( mDialog->objectName().isEmpty() )
@@ -451,6 +453,16 @@ void QgsAttributeDialog::init()
451453
{
452454
if ( buttonBox )
453455
{
456+
// Add dummy buttons
457+
if ( mLayer->isEditable() )
458+
{
459+
buttonBox->clear();
460+
461+
buttonBox->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
462+
connect( buttonBox, SIGNAL( accepted() ), mDialog, SLOT( accept() ) );
463+
connect( buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
464+
}
465+
454466
buttonBox->setVisible( false );
455467
}
456468
}

src/gui/qgsattributedialog.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ class GUI_EXPORT QgsAttributeDialog : public QObject
8080

8181
QgsFeature* feature() { return mFeature; }
8282

83+
/**
84+
* Is this dialog editable?
85+
*
86+
* @return returns true, if this dialog was created in an editable manner.
87+
*/
88+
bool editable() { return mEditable; }
89+
8390
public slots:
8491
void accept();
8592

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

116+
// true if this dialog is editable
117+
bool mEditable;
118+
109119
static int sFormCounter;
110120
static QString sSettingsPath;
111121
};

0 commit comments

Comments
 (0)