Skip to content

Commit f07389b

Browse files
authored
fix constraints not checked when they should be (#6550) (#6599)
1 parent 5bcd361 commit f07389b

File tree

6 files changed

+56
-19
lines changed

6 files changed

+56
-19
lines changed

python/gui/qgsattributeform.sip.in

+14-1
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,25 @@ on all attribute widgets.
139139

140140
signals:
141141

142-
void attributeChanged( const QString &attribute, const QVariant &value );
142+
void attributeChanged( const QString &attribute, const QVariant &value );
143143
%Docstring
144144
Notifies about changes of attributes
145145

146146
:param attribute: The name of the attribute that changed.
147147
:param value: The new value of the attribute.
148+
149+
.. deprecated:: since 3.0
150+
%End
151+
152+
void widgetValueChanged( const QString &attribute, const QVariant &value, bool attributeChanged );
153+
%Docstring
154+
Notifies about changes of attributes
155+
156+
:param attribute: The name of the attribute that changed.
157+
:param value: The new value of the attribute.
158+
:param attributeChanged: If true, it corresponds to an actual change of the feature attribute
159+
160+
.. versionadded:: 3.0.1
148161
%End
149162

150163

src/gui/attributetable/qgsdualview.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const Qg
9898
mAttributeEditor->layout()->addWidget( mAttributeForm );
9999
}
100100

101-
connect( mAttributeForm, &QgsAttributeForm::attributeChanged, this, &QgsDualView::featureFormAttributeChanged );
101+
connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged );
102102
connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged );
103103
connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature );
104104
connect( mAttributeForm, &QgsAttributeForm::filterExpressionSet, this, &QgsDualView::filterExpressionSet );
@@ -880,9 +880,12 @@ void QgsDualView::extentChanged()
880880
emit filterChanged();
881881
}
882882

883-
void QgsDualView::featureFormAttributeChanged()
883+
void QgsDualView::featureFormAttributeChanged( const QString &attribute, const QVariant &value, bool attributeChanged )
884884
{
885-
mFeatureList->setCurrentFeatureEdited( true );
885+
Q_UNUSED( attribute );
886+
Q_UNUSED( value );
887+
if ( attributeChanged )
888+
mFeatureList->setCurrentFeatureEdited( true );
886889
}
887890

888891
void QgsDualView::setFilteredFeatures( const QgsFeatureIds &filteredFeatures )

src/gui/attributetable/qgsdualview.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
327327
* Will forward this signal to the feature list to visually represent
328328
* that there has been an edit event.
329329
*/
330-
void featureFormAttributeChanged();
330+
void featureFormAttributeChanged( const QString &attribute, const QVariant &value, bool attributeChanged );
331331

332332
/**
333333
* Will be called periodically, when loading layers from slow data providers.

src/gui/qgsattributeform.cpp

+15-6
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ void QgsAttributeForm::changeAttribute( const QString &field, const QVariant &va
240240

241241
void QgsAttributeForm::setFeature( const QgsFeature &feature )
242242
{
243+
mIsSettingFeature = true;
243244
mFeature = feature;
244245

245246
switch ( mMode )
@@ -266,6 +267,7 @@ void QgsAttributeForm::setFeature( const QgsFeature &feature )
266267
break;
267268
}
268269
}
270+
mIsSettingFeature = false;
269271
}
270272

271273
bool QgsAttributeForm::saveEdits()
@@ -692,11 +694,7 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value )
692694
QgsEditorWidgetWrapper *eww = qobject_cast<QgsEditorWidgetWrapper *>( sender() );
693695
Q_ASSERT( eww );
694696

695-
const QVariant oldValue = mFeature.attribute( eww->fieldIdx() );
696-
697-
// Safety check, if we receive the same value again, no reason to do anything
698-
if ( oldValue == value && oldValue.isNull() == value.isNull() )
699-
return;
697+
bool signalEmitted = false;
700698

701699
if ( mValuesInitialized )
702700
mDirty = true;
@@ -707,7 +705,12 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value )
707705
case IdentifyMode:
708706
case AddFeatureMode:
709707
{
708+
Q_NOWARN_DEPRECATED_PUSH
710709
emit attributeChanged( eww->field().name(), value );
710+
Q_NOWARN_DEPRECATED_PUSH
711+
emit widgetValueChanged( eww->field().name(), value, !mIsSettingFeature );
712+
713+
signalEmitted = true;
711714

712715
updateJoinedFields( *eww );
713716

@@ -739,7 +742,13 @@ void QgsAttributeForm::onAttributeChanged( const QVariant &value )
739742

740743
updateConstraints( eww );
741744

742-
emit attributeChanged( eww->field().name(), value );
745+
if ( !signalEmitted )
746+
{
747+
Q_NOWARN_DEPRECATED_PUSH
748+
emit attributeChanged( eww->field().name(), value );
749+
Q_NOWARN_DEPRECATED_PUSH
750+
emit widgetValueChanged( eww->field().name(), value, !mIsSettingFeature );
751+
}
743752
}
744753

745754
void QgsAttributeForm::updateAllConstraints()

src/gui/qgsattributeform.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,19 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
178178
*
179179
* \param attribute The name of the attribute that changed.
180180
* \param value The new value of the attribute.
181+
* \deprecated since 3.0
181182
*/
182-
void attributeChanged( const QString &attribute, const QVariant &value );
183+
Q_DECL_DEPRECATED void attributeChanged( const QString &attribute, const QVariant &value );
184+
185+
/**
186+
* Notifies about changes of attributes
187+
*
188+
* \param attribute The name of the attribute that changed.
189+
* \param value The new value of the attribute.
190+
* \param attributeChanged If true, it corresponds to an actual change of the feature attribute
191+
* \since QGIS 3.0.1
192+
*/
193+
void widgetValueChanged( const QString &attribute, const QVariant &value, bool attributeChanged );
183194

184195
/**
185196
* Will be emitted before the feature is saved. Use this signal to perform sanity checks.
@@ -367,6 +378,7 @@ class GUI_EXPORT QgsAttributeForm : public QWidget
367378
QMap<const QgsVectorLayerJoinInfo *, QgsFeature> mJoinedFeatures;
368379
bool mValuesInitialized = false;
369380
bool mDirty = false;
381+
bool mIsSettingFeature = false;
370382

371383
struct ContainerInformation
372384
{

tests/src/gui/testqgsattributeform.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -111,24 +111,24 @@ void TestQgsAttributeForm::testFieldConstraint()
111111
// build a form for this feature
112112
QgsAttributeForm form2( layer );
113113
form2.setFeature( ft );
114-
QSignalSpy spy( &form2, SIGNAL( attributeChanged( QString, QVariant ) ) );
114+
QSignalSpy spy( &form2, SIGNAL( widgetValueChanged( QString, QVariant, bool ) ) );
115115
ww = qobject_cast<QgsEditorWidgetWrapper *>( form2.mWidgets[0] );
116116

117117
// set value to 1
118118
ww->setValue( 1 );
119-
QCOMPARE( spy.count(), 2 );
119+
QCOMPARE( spy.count(), 1 );
120120
QCOMPARE( constraintsLabel( &form2, ww )->text(), validLabel );
121121

122122
// set value to null
123123
spy.clear();
124124
ww->setValue( QVariant() );
125-
QCOMPARE( spy.count(), 2 );
125+
QCOMPARE( spy.count(), 1 );
126126
QCOMPARE( constraintsLabel( &form2, ww )->text(), invalidLabel );
127127

128128
// set value to 1
129129
spy.clear();
130130
ww->setValue( 1 );
131-
QCOMPARE( spy.count(), 2 );
131+
QCOMPARE( spy.count(), 1 );
132132
QCOMPARE( constraintsLabel( &form2, ww )->text(), validLabel );
133133

134134
// set a soft constraint
@@ -205,11 +205,11 @@ void TestQgsAttributeForm::testFieldMultiConstraints()
205205
ww1 = qobject_cast<QgsEditorWidgetWrapper *>( form2.mWidgets[1] );
206206
ww2 = qobject_cast<QgsEditorWidgetWrapper *>( form2.mWidgets[2] );
207207
ww3 = qobject_cast<QgsEditorWidgetWrapper *>( form2.mWidgets[3] );
208-
QSignalSpy spy2( &form2, SIGNAL( attributeChanged( QString, QVariant ) ) );
208+
QSignalSpy spy2( &form2, SIGNAL( widgetValueChanged( QString, QVariant, bool ) ) );
209209

210210
// change value
211211
ww0->setValue( 2 ); // update col0
212-
QCOMPARE( spy2.count(), 2 );
212+
QCOMPARE( spy2.count(), 1 );
213213

214214
QCOMPARE( constraintsLabel( &form2, ww0 )->text(), inv ); // 2 < ( 1 + 2 )
215215
QCOMPARE( constraintsLabel( &form2, ww1 )->text(), QString() );
@@ -219,7 +219,7 @@ void TestQgsAttributeForm::testFieldMultiConstraints()
219219
// change value
220220
spy2.clear();
221221
ww0->setValue( 1 ); // update col0
222-
QCOMPARE( spy2.count(), 2 );
222+
QCOMPARE( spy2.count(), 1 );
223223

224224
QCOMPARE( constraintsLabel( &form2, ww0 )->text(), val ); // 1 < ( 1 + 2 )
225225
QCOMPARE( constraintsLabel( &form2, ww1 )->text(), QString() );

0 commit comments

Comments
 (0)