Skip to content

Commit

Permalink
Merge pull request #37845 from qgis-bot/backport-37830-to-release-3_14
Browse files Browse the repository at this point in the history
[Backport release-3_14] Fix pasting features - only a single insert operation, no unnecessary (failing) updates
  • Loading branch information
m-kuhn committed Jul 16, 2020
2 parents 3b58dcb + 0097058 commit 04d607b
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 4 deletions.
1 change: 1 addition & 0 deletions python/gui/auto_generated/qgsattributeeditorcontext.sip.in
Expand Up @@ -31,6 +31,7 @@ showing an embedded form due to relations)
{
SingleEditMode,
AddFeatureMode,
FixAttributeMode,
MultiEditMode,
SearchMode,
AggregateSearchMode,
Expand Down
2 changes: 1 addition & 1 deletion src/app/qgsfixattributedialog.cpp
Expand Up @@ -52,7 +52,7 @@ void QgsFixAttributeDialog::init( QgsVectorLayer *layer, const QgsAttributeEdito
infoLayout->addWidget( mProgressBar );
QgsFeature feature;
mAttributeForm = new QgsAttributeForm( layer, *mCurrentFeature, context, this );
mAttributeForm->setMode( QgsAttributeEditorContext::SingleEditMode );
mAttributeForm->setMode( QgsAttributeEditorContext::FixAttributeMode );
mAttributeForm->disconnectButtonBox();
layout()->addWidget( mAttributeForm );

Expand Down
5 changes: 4 additions & 1 deletion src/core/qgsfeatureid.h
Expand Up @@ -21,7 +21,10 @@ email : matthias@opengis.ch

// feature id (currently 64 bit)

// 64 bit feature ids
/**
* 64 bit feature ids
* negative numbers are used for uncommitted/newly added features
**/
typedef qint64 QgsFeatureId SIP_SKIP;
#define FID_NULL std::numeric_limits<QgsFeatureId>::min()
#define FID_IS_NULL(fid) ( fid == std::numeric_limits<QgsFeatureId>::min() )
Expand Down
1 change: 1 addition & 0 deletions src/gui/qgsattributeeditorcontext.h
Expand Up @@ -49,6 +49,7 @@ class GUI_EXPORT QgsAttributeEditorContext
SingleEditMode, //!< Single edit mode, for editing a single feature
AddFeatureMode, /*!< Add feature mode, for setting attributes for a new feature. In this mode the dialog will be editable even with an invalid feature and
will add a new feature when the form is accepted. */
FixAttributeMode, //!< Fix feature mode, for modifying the feature attributes without saving. The updated feature is available via `feature()` after `save()`
MultiEditMode, //!< Multi edit mode, for editing fields of multiple features at once
SearchMode, //!< Form values are used for searching/filtering the layer
AggregateSearchMode, //!< Form is in aggregate search mode, show each widget in this mode \since QGIS 3.0
Expand Down
22 changes: 20 additions & 2 deletions src/gui/qgsattributeform.cpp
Expand Up @@ -173,6 +173,10 @@ void QgsAttributeForm::setMode( QgsAttributeEditorContext::Mode mode )
w->setMode( QgsAttributeFormWidget::DefaultMode );
break;

case QgsAttributeEditorContext::FixAttributeMode:
w->setMode( QgsAttributeFormWidget::DefaultMode );
break;

case QgsAttributeEditorContext::MultiEditMode:
w->setMode( QgsAttributeFormWidget::MultiEditMode );
break;
Expand Down Expand Up @@ -216,6 +220,11 @@ void QgsAttributeForm::setMode( QgsAttributeEditorContext::Mode mode )
mSearchButtonBox->setVisible( false );
break;

case QgsAttributeEditorContext::FixAttributeMode:
synchronizeEnabledState();
mSearchButtonBox->setVisible( false );
break;

case QgsAttributeEditorContext::MultiEditMode:
resetMultiEdit( false );
synchronizeEnabledState();
Expand Down Expand Up @@ -278,6 +287,7 @@ void QgsAttributeForm::setFeature( const QgsFeature &feature )
case QgsAttributeEditorContext::SingleEditMode:
case QgsAttributeEditorContext::IdentifyMode:
case QgsAttributeEditorContext::AddFeatureMode:
case QgsAttributeEditorContext::FixAttributeMode:
{
resetValues();

Expand Down Expand Up @@ -320,7 +330,7 @@ bool QgsAttributeForm::saveEdits()

// An add dialog should perform an action by default
// and not only if attributes have "changed"
if ( mMode == QgsAttributeEditorContext::AddFeatureMode )
if ( mMode == QgsAttributeEditorContext::AddFeatureMode || mMode == QgsAttributeEditorContext::FixAttributeMode )
doUpdate = true;

QgsAttributes src = mFeature.attributes();
Expand Down Expand Up @@ -379,7 +389,11 @@ bool QgsAttributeForm::saveEdits()

if ( doUpdate )
{
if ( mMode == QgsAttributeEditorContext::AddFeatureMode )
if ( mMode == QgsAttributeEditorContext::FixAttributeMode )
{
mFeature = updatedFeature;
}
else if ( mMode == QgsAttributeEditorContext::AddFeatureMode )
{
mFeature.setValid( true );
mLayer->beginEditCommand( mEditCommandMessage );
Expand Down Expand Up @@ -735,6 +749,7 @@ bool QgsAttributeForm::save()
{
case QgsAttributeEditorContext::SingleEditMode:
case QgsAttributeEditorContext::IdentifyMode:
case QgsAttributeEditorContext::FixAttributeMode:
case QgsAttributeEditorContext::MultiEditMode:
if ( !mDirty )
return true;
Expand All @@ -761,6 +776,7 @@ bool QgsAttributeForm::save()
case QgsAttributeEditorContext::SingleEditMode:
case QgsAttributeEditorContext::IdentifyMode:
case QgsAttributeEditorContext::AddFeatureMode:
case QgsAttributeEditorContext::FixAttributeMode:
case QgsAttributeEditorContext::SearchMode:
case QgsAttributeEditorContext::AggregateSearchMode:
success = saveEdits();
Expand Down Expand Up @@ -848,6 +864,7 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value, const QVariant
case QgsAttributeEditorContext::SingleEditMode:
case QgsAttributeEditorContext::IdentifyMode:
case QgsAttributeEditorContext::AddFeatureMode:
case QgsAttributeEditorContext::FixAttributeMode:
{
Q_NOWARN_DEPRECATED_PUSH
emit attributeChanged( eww->field().name(), value );
Expand Down Expand Up @@ -2264,6 +2281,7 @@ void QgsAttributeForm::layerSelectionChanged()
case QgsAttributeEditorContext::SingleEditMode:
case QgsAttributeEditorContext::IdentifyMode:
case QgsAttributeEditorContext::AddFeatureMode:
case QgsAttributeEditorContext::FixAttributeMode:
case QgsAttributeEditorContext::SearchMode:
case QgsAttributeEditorContext::AggregateSearchMode:
break;
Expand Down
36 changes: 36 additions & 0 deletions tests/src/gui/testqgsattributeform.cpp
Expand Up @@ -50,6 +50,7 @@ class TestQgsAttributeForm : public QObject
void testConstraintsOnJoinedFields();
void testEditableJoin();
void testUpsertOnEdit();
void testFixAttributeForm();
void testAttributeFormInterface();
void testDefaultValueUpdate();
void testDefaultValueUpdateRecursion();
Expand Down Expand Up @@ -878,6 +879,41 @@ void TestQgsAttributeForm::testUpsertOnEdit()
delete layerC;
}

void TestQgsAttributeForm::testFixAttributeForm()
{
QString def = QStringLiteral( "Point?field=id:integer&field=col1:integer" );
QgsVectorLayer *layer = new QgsVectorLayer( def, QStringLiteral( "layer" ), QStringLiteral( "memory" ) );

QVERIFY( layer );

QgsFeature f( layer->fields() );
f.setAttribute( 0, 1 );
f.setAttribute( 1, 681 );

QgsAttributeForm form( layer );

form.setMode( QgsAttributeEditorContext::FixAttributeMode );
form.setFeature( f );

QgsEditorWidgetWrapper *ww = qobject_cast<QgsEditorWidgetWrapper *>( form.mWidgets[1] );
QCOMPARE( ww->field().name(), QString( "col1" ) );
QCOMPARE( ww->value(), QVariant( 681 ) );

// now change the value
ww->setValue( QVariant( 630 ) );

// the value should be updated
QCOMPARE( ww->value(), QVariant( 630 ) );
// the feature is not saved yet, so contains the old value
QCOMPARE( form.feature().attribute( QStringLiteral( "col1" ) ), QVariant( 681 ) );
// now save the feature and enjoy its new value, but don't update the layer
QVERIFY( form.save() );
QCOMPARE( form.feature().attribute( QStringLiteral( "col1" ) ), QVariant( 630 ) );
QCOMPARE( ( int )layer->featureCount(), 0 );

delete layer;
}

void TestQgsAttributeForm::testAttributeFormInterface()
{
// Issue https://github.com/qgis/QGIS/issues/29667
Expand Down

0 comments on commit 04d607b

Please sign in to comment.