Skip to content

Commit

Permalink
AttributeForm: Create a dummy button box for intercepting ok clicks
Browse files Browse the repository at this point in the history
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 Dec 3, 2013
1 parent 08b43aa commit 999a996
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 27 deletions.
88 changes: 62 additions & 26 deletions src/gui/attributetable/qgsdualview.cpp
Expand Up @@ -37,6 +37,7 @@ QgsDualView::QgsDualView( QWidget* parent )
, mEditorContext()
, mMasterModel( NULL )
, mAttributeDialog( NULL )
, mLayerCache( NULL )
, mProgressDlg( NULL )
, mFeatureSelectionManager( NULL )
{
Expand Down Expand Up @@ -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 )
Expand Down Expand Up @@ -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;
Expand All @@ -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()
Expand Down
5 changes: 4 additions & 1 deletion src/gui/attributetable/qgsdualview.h
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/gui/attributetable/qgsfeaturelistview.cpp
Expand Up @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions src/gui/attributetable/qgsfeaturelistview.h
Expand Up @@ -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 );
Expand Down
12 changes: 12 additions & 0 deletions src/gui/qgsattributedialog.cpp
Expand Up @@ -418,6 +418,8 @@ void QgsAttributeDialog::init()
}
}

mEditable = mLayer->isEditable();

if ( mDialog )
{
if ( mDialog->objectName().isEmpty() )
Expand Down Expand Up @@ -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 );
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/gui/qgsattributedialog.h
Expand Up @@ -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();

Expand All @@ -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;
};
Expand Down

0 comments on commit 999a996

Please sign in to comment.