Skip to content

Commit

Permalink
[atribute form] Add parent context when editing a child feature throu…
Browse files Browse the repository at this point in the history
…gh the relation editor widget
  • Loading branch information
nirvn committed Jun 2, 2024
1 parent 54e3668 commit 83d61b5
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 16 deletions.
8 changes: 6 additions & 2 deletions python/PyQt6/core/auto_generated/vector/qgsvectorlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -1777,7 +1777,7 @@ be updated. This can be used to override default field value expressions.
.. seealso:: :py:func:`updateFeature`
%End

bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false );
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false, QgsExpressionContext *context = 0 );
%Docstring
Changes an attribute value for a feature (but does not immediately commit the changes).
The ``fid`` argument specifies the ID of the feature to be changed.
Expand All @@ -1796,6 +1796,8 @@ so it is more efficient to explicitly pass an ``oldValue`` if it is already avai
If ``skipDefaultValues`` is set to ``True``, default field values will not
be updated. This can be used to override default field value expressions.

If ``context`` is provided, it will be used when updating default values.

:return: ``True`` if the feature's attribute was successfully changed.

.. note::
Expand All @@ -1815,7 +1817,7 @@ be updated. This can be used to override default field value expressions.
.. seealso:: :py:func:`updateFeature`
%End

bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false );
bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false, QgsExpressionContext *context = 0 );
%Docstring
Changes attributes' values for a feature (but does not immediately
commit the changes).
Expand All @@ -1835,6 +1837,8 @@ If ``skipDefaultValues`` is set to ``True``, default field values will not
be updated. This can be used to override default field value
expressions.

If ``context`` is provided, it will be used when updating default values.

:return: ``True`` if feature's attributes was successfully changed.

.. note::
Expand Down
8 changes: 6 additions & 2 deletions python/core/auto_generated/vector/qgsvectorlayer.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -1777,7 +1777,7 @@ be updated. This can be used to override default field value expressions.
.. seealso:: :py:func:`updateFeature`
%End

bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false );
bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false, QgsExpressionContext *context = 0 );
%Docstring
Changes an attribute value for a feature (but does not immediately commit the changes).
The ``fid`` argument specifies the ID of the feature to be changed.
Expand All @@ -1796,6 +1796,8 @@ so it is more efficient to explicitly pass an ``oldValue`` if it is already avai
If ``skipDefaultValues`` is set to ``True``, default field values will not
be updated. This can be used to override default field value expressions.

If ``context`` is provided, it will be used when updating default values.

:return: ``True`` if the feature's attribute was successfully changed.

.. note::
Expand All @@ -1815,7 +1817,7 @@ be updated. This can be used to override default field value expressions.
.. seealso:: :py:func:`updateFeature`
%End

bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false );
bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false, QgsExpressionContext *context = 0 );
%Docstring
Changes attributes' values for a feature (but does not immediately
commit the changes).
Expand All @@ -1835,6 +1837,8 @@ If ``skipDefaultValues`` is set to ``True``, default field values will not
be updated. This can be used to override default field value
expressions.

If ``context`` is provided, it will be used when updating default values.

:return: ``True`` if feature's attributes was successfully changed.

.. note::
Expand Down
12 changes: 6 additions & 6 deletions src/core/vector/qgsvectorlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ void QgsVectorLayer::setExtent3D( const QgsBox3D &r )
mValidExtent3D = true;
}

void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature, QgsExpressionContext *context )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS

Expand All @@ -1016,7 +1016,7 @@ void QgsVectorLayer::updateDefaultValues( QgsFeatureId fid, QgsFeature feature )
{
if ( idx < 0 || idx >= size )
continue;
feature.setAttribute( idx, defaultValue( idx, feature ) );
feature.setAttribute( idx, defaultValue( idx, feature, context ) );
updateFeature( feature, true );
}
}
Expand Down Expand Up @@ -3398,7 +3398,7 @@ bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool s
}


bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues )
bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue, bool skipDefaultValues, QgsExpressionContext *context )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS

Expand Down Expand Up @@ -3426,12 +3426,12 @@ bool QgsVectorLayer::changeAttributeValue( QgsFeatureId fid, int field, const QV
}

if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
updateDefaultValues( fid );
updateDefaultValues( fid, QgsFeature(), context );

return result;
}

bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues )
bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues, bool skipDefaultValues, QgsExpressionContext *context )
{
QGIS_PROTECT_QOBJECT_THREAD_ACCESS

Expand Down Expand Up @@ -3488,7 +3488,7 @@ bool QgsVectorLayer::changeAttributeValues( QgsFeatureId fid, const QgsAttribute

if ( result && !skipDefaultValues && !mDefaultValueOnUpdateFields.isEmpty() )
{
updateDefaultValues( fid );
updateDefaultValues( fid, QgsFeature(), context );
}

return result;
Expand Down
10 changes: 7 additions & 3 deletions src/core/vector/qgsvectorlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* If \a skipDefaultValues is set to TRUE, default field values will not
* be updated. This can be used to override default field value expressions.
*
* If \a context is provided, it will be used when updating default values.
*
* \returns TRUE if the feature's attribute was successfully changed.
*
* \note Calls to changeAttributeValue() are only valid for layers in which edits have been enabled
Expand All @@ -1747,7 +1749,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* \see changeGeometry()
* \see updateFeature()
*/
Q_INVOKABLE bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false );
Q_INVOKABLE bool changeAttributeValue( QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue = QVariant(), bool skipDefaultValues = false, QgsExpressionContext *context = nullptr );

/**
* Changes attributes' values for a feature (but does not immediately
Expand All @@ -1768,6 +1770,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* be updated. This can be used to override default field value
* expressions.
*
* If \a context is provided, it will be used when updating default values.
*
* \returns TRUE if feature's attributes was successfully changed.
*
* \note Calls to changeAttributeValues() are only valid for layers in
Expand All @@ -1783,7 +1787,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* \see changeAttributeValue()
*
*/
Q_INVOKABLE bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false );
Q_INVOKABLE bool changeAttributeValues( QgsFeatureId fid, const QgsAttributeMap &newValues, const QgsAttributeMap &oldValues = QgsAttributeMap(), bool skipDefaultValues = false, QgsExpressionContext *context = nullptr );

/**
* Add an attribute field (but does not commit it)
Expand Down Expand Up @@ -2794,7 +2798,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
void onAfterCommitChangesDependency();

private:
void updateDefaultValues( QgsFeatureId fid, QgsFeature feature = QgsFeature() );
void updateDefaultValues( QgsFeatureId fid, QgsFeature feature = QgsFeature(), QgsExpressionContext *context = nullptr );

/**
* Returns TRUE if the layer is in read-only mode
Expand Down
1 change: 1 addition & 0 deletions src/gui/attributeformconfig/qgsattributetypedialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ QgsExpressionContext QgsAttributeTypeDialog::createExpressionContext() const
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() )
<< QgsExpressionContextUtils::layerScope( mLayer )
<< QgsExpressionContextUtils::formScope( )
<< QgsExpressionContextUtils::parentFormScope( QgsFeature() )
<< QgsExpressionContextUtils::mapToolCaptureScope( QList<QgsPointLocator::Match>() );

return context;
Expand Down
12 changes: 11 additions & 1 deletion src/gui/qgsattributeform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,9 @@ bool QgsAttributeForm::saveEdits( QString *error )
// An add dialog should perform an action by default
// and not only if attributes have "changed"
if ( mMode == QgsAttributeEditorContext::AddFeatureMode || mMode == QgsAttributeEditorContext::FixAttributeMode )
{
doUpdate = true;
}

QgsAttributes src = mFeature.attributes();
QgsAttributes dst = mFeature.attributes();
Expand Down Expand Up @@ -461,7 +463,8 @@ bool QgsAttributeForm::saveEdits( QString *error )
n++;
}

success = mLayer->changeAttributeValues( mFeature.id(), newValues, oldValues );
QgsExpressionContext context = createExpressionContext( updatedFeature );
success = mLayer->changeAttributeValues( mFeature.id(), newValues, oldValues, false, &context );

if ( success && n > 0 )
{
Expand Down Expand Up @@ -569,6 +572,7 @@ void QgsAttributeForm::updateValuesDependenciesDefaultValues( const int originId
continue;

QgsExpressionContext context = createExpressionContext( updatedFeature );

const QVariant value = mLayer->defaultValue( eww->fieldIdx(), updatedFeature, &context );
eww->setValue( value );
mCurrentFormFeature.setAttribute( eww->field().name(), value );
Expand Down Expand Up @@ -983,7 +987,13 @@ QgsExpressionContext QgsAttributeForm::createExpressionContext( const QgsFeature
context.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mLayer ) );
context.appendScope( QgsExpressionContextUtils::formScope( feature, mContext.attributeFormModeString() ) );
if ( mExtraContextScope )
{
context.appendScope( new QgsExpressionContextScope( *mExtraContextScope.get() ) );
}
if ( mContext.parentFormFeature().isValid() )
{
context.appendScope( QgsExpressionContextUtils::parentFormScope( mContext.parentFormFeature() ) );
}
context.setFeature( feature );
return context;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/src/python/test_qgsrelationeditwidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ def test_add_feature_geometry(self):
# Mock vector layer tool to just set default value on created feature
class DummyVlTools(QgsVectorLayerTools):

def addFeature(self, layer, defaultValues, defaultGeometry, parentWidget=None, showModal=True, hideParent=False):
def addFeature(self, layer, defaultValues, defaultGeometry, parentWidget=None, showModal=True, hideParent=False, scope=None):
f = QgsFeature(layer.fields())
for idx, value in defaultValues.items():
f.setAttribute(idx, value)
Expand Down Expand Up @@ -440,7 +440,7 @@ def setValues(self, values):
"""
self.values = values

def addFeature(self, layer, defaultValues, defaultGeometry, parentWidget=None, showModal=True, hideParent=False):
def addFeature(self, layer, defaultValues, defaultGeometry, parentWidget=None, showModal=True, hideParent=False, scope=None):
"""
Overrides the addFeature method
:param layer: vector layer
Expand Down

0 comments on commit 83d61b5

Please sign in to comment.