Skip to content
Permalink
Browse files

Final touches to the parent form API

  • Loading branch information
elpaso committed Mar 2, 2020
1 parent fa6958f commit 195efa42a119cfe8114c8db52eb5b2ae3425c996
Showing with 534 additions and 27 deletions.
  1. +10 −1 python/core/auto_generated/expression/qgsexpressioncontextutils.sip.in
  2. +39 −3 python/core/auto_generated/fieldformatter/qgsvaluerelationfieldformatter.sip.in
  3. +1 −0 python/gui/auto_generated/attributetable/qgsattributetableview.sip.in
  4. +10 −0 python/gui/auto_generated/attributetable/qgsdualview.sip.in
  5. +13 −0 python/gui/auto_generated/editorwidgets/core/qgseditorwidgetwrapper.sip.in
  6. +15 −0 python/gui/auto_generated/editorwidgets/qgsrelationwidgetwrapper.sip.in
  7. +18 −0 python/gui/auto_generated/qgsattributeeditorcontext.sip.in
  8. +12 −0 python/gui/auto_generated/qgsattributeform.sip.in
  9. +19 −1 python/gui/auto_generated/qgsrelationeditorwidget.sip.in
  10. +7 −0 resources/function_help/json/current_parent_value
  11. +16 −0 src/core/expression/qgsexpression.cpp
  12. +37 −0 src/core/expression/qgsexpressioncontextutils.cpp
  13. +9 −1 src/core/expression/qgsexpressioncontextutils.h
  14. +66 −4 src/core/fieldformatter/qgsvaluerelationfieldformatter.cpp
  15. +33 −3 src/core/fieldformatter/qgsvaluerelationfieldformatter.h
  16. +1 −0 src/gui/attributetable/qgsattributetableview.h
  17. +8 −0 src/gui/attributetable/qgsdualview.cpp
  18. +10 −0 src/gui/attributetable/qgsdualview.h
  19. +6 −0 src/gui/editorwidgets/core/qgseditorwidgetwrapper.cpp
  20. +13 −0 src/gui/editorwidgets/core/qgseditorwidgetwrapper.h
  21. +5 −1 src/gui/editorwidgets/qgshtmlwidgetwrapper.cpp
  22. +21 −0 src/gui/editorwidgets/qgsrelationwidgetwrapper.cpp
  23. +14 −0 src/gui/editorwidgets/qgsrelationwidgetwrapper.h
  24. +5 −2 src/gui/editorwidgets/qgsvaluerelationconfigdlg.cpp
  25. +39 −4 src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.cpp
  26. +4 −0 src/gui/editorwidgets/qgsvaluerelationwidgetwrapper.h
  27. +16 −0 src/gui/qgsattributeeditorcontext.h
  28. +12 −0 src/gui/qgsattributeform.cpp
  29. +12 −0 src/gui/qgsattributeform.h
  30. +0 −1 src/gui/qgsfeaturelistcombobox.h
  31. +19 −3 src/gui/qgsrelationeditorwidget.cpp
  32. +19 −1 src/gui/qgsrelationeditorwidget.h
  33. +7 −2 tests/src/gui/testqgsvaluerelationwidgetwrapper.cpp
  34. +18 −0 tests/src/python/test_qgsfieldformatters.py
@@ -33,11 +33,20 @@ For instance, QGIS version numbers and variables specified through QGIS options.

static QgsExpressionContextScope *formScope( const QgsFeature &formFeature = QgsFeature( ), const QString &formMode = QString() ) /Factory/;
%Docstring
Creates a new scope which contains functions and variables from the current attribute form/table ``feature``.
Creates a new scope which contains functions and variables from the current attribute form/table ``formFeature``.
The variables and values in this scope will reflect the current state of the form/row being edited.
The ``formMode`` (SingleEditMode etc.) is passed as text

.. versionadded:: 3.2
%End

static QgsExpressionContextScope *parentFormScope( const QgsFeature &formFeature = QgsFeature( ), const QString &formMode = QString() ) /Factory/;
%Docstring
Creates a new scope which contains functions and variables from the current parent attribute form/table ``formFeature``.
The variables and values in this scope will reflect the current state of the parent form/row being edited.
The ``formMode`` (SingleEditMode etc.) is passed as text

.. versionadded:: 3.14
%End

static void setGlobalVariable( const QString &name, const QVariant &value );
@@ -64,7 +64,7 @@ Utility to convert a list or a string representation of an (hstore style: {1,2..
.. versionadded:: 3.2
%End

static QgsValueRelationFieldFormatter::ValueRelationCache createCache( const QVariantMap &config, const QgsFeature &formFeature = QgsFeature() );
static QgsValueRelationFieldFormatter::ValueRelationCache createCache( const QVariantMap &config, const QgsFeature &formFeature = QgsFeature(), const QgsFeature &parentFormFeature = QgsFeature() );
%Docstring
Create a cache for a value relation field.
This can be used to keep the value map in the local memory
@@ -112,9 +112,45 @@ Returns a list of variables required by the form context ``expression``
.. versionadded:: 3.2
%End

static bool expressionIsUsable( const QString &expression, const QgsFeature &feature );
static bool expressionRequiresParentFormScope( const QString &expression );
%Docstring
Check whether the ``feature`` has all values required by the ``expression``
Check if the ``expression`` requires a parent form scope (i.e. if it uses fields
or geometry of the parent form's currently edited feature).

:param expression: The widget's filter expression

:return: ``True`` if the expression requires a parent form scope

.. versionadded:: 3.14
%End

static QSet<QString> expressionParentFormAttributes( const QString &expression );
%Docstring
Returns a list of attributes required by the parent form's form context ``expression``

:param expression: Form filter expression

:return: list of parent attributes required by the expression

.. versionadded:: 3.14
%End

static QSet<QString> expressionParentFormVariables( const QString &expression );
%Docstring
Returns a list of variables required by the parent form's form context ``expression``

:param expression: Form filter expression

:return: list of parent variables required by the expression

.. versionadded:: 3.14
%End


static bool expressionIsUsable( const QString &expression, const QgsFeature &feature, const QgsFeature &parentFeature = QgsFeature() );
%Docstring
Check whether the ``feature`` has all values required by the ``expression``,
optionally checks for ``parentFeature``

:return: ``True`` if the expression can be used

@@ -69,6 +69,7 @@ Returns the selected features in the attribute table in table sorted order.
.. versionadded:: 3.4
%End


protected:

virtual void mousePressEvent( QMouseEvent *event );
@@ -232,6 +232,16 @@ Copy the content of the selected cell in the clipboard.
Cancel the progress dialog (if any)

.. versionadded:: 3.0
%End

void parentFormValueChanged( const QString &attribute, const QVariant &value );
%Docstring
Called in embedded forms when an ``attribute`` ``value`` in the parent form has changed.

Notify the form widgets that something has changed in case they
have filter expression that depend on the parent form scope.

.. versionadded:: 3.14
%End

signals:
@@ -302,6 +302,19 @@ to reflect the new values.
void emitValueChanged();
%Docstring
Will call the value() method to determine the emitted value
%End

virtual void parentFormValueChanged( const QString &attribute, const QVariant &value );
%Docstring
Is called in embedded form widgets when an ``attribute`` ``value`` in
the parent form has changed.

The default implementations does nothing.
Subclasses should reimplement this method to notify the form widgets
that something has changed in case they have filter expressions that
depend on the parent form scope.

.. versionadded:: 3.14
%End

protected:
@@ -88,6 +88,21 @@ The relation for which this wrapper is created.
.. versionadded:: 3.0
%End

void widgetValueChanged( const QString &attribute, const QVariant &newValue, bool attributeChanged );
%Docstring
Will be called when a value in the current edited form or table row
changes

Forward the signal to the embedded form

:param attribute: The name of the attribute that changed.
:param newValue: The new value of the attribute.
:param attributeChanged: If ``True``, it corresponds to an actual change of the feature attribute

.. versionadded:: 3.14
%End


protected:
virtual QWidget *createWidget( QWidget *parent );

@@ -235,6 +235,24 @@ Set current ``feature`` for the currently edited form or table row
.. seealso:: :py:func:`formFeature`

.. versionadded:: 3.2
%End

QgsFeature parentFormFeature() const;
%Docstring
Returns the feature of the currently edited parent form in its actual state

.. seealso:: :py:func:`setParentFormFeature`

.. versionadded:: 3.14
%End

void setParentFormFeature( const QgsFeature &feature );
%Docstring
Sets the ``feature`` of the currently edited parent form

.. seealso:: :py:func:`parentFormFeature`

.. versionadded:: 3.14
%End

Mode attributeFormMode() const;
@@ -280,6 +280,18 @@ Resets the search/filter form values.
reload current feature
%End

void parentFormValueChanged( const QString &attribute, const QVariant &newValue );
%Docstring
Is called in embedded forms when an ``attribute`` value in the parent form
has changed to ``newValue``.

Notify the form widgets that something has changed in case they
have filter expressions that depend on the parent form scope.

.. versionadded:: 3.14
%End


};


@@ -63,7 +63,10 @@ inserting and deleting entries on the intermediate table as required.
:param nmrelation: Optional reference from the referencing table to a 3rd N:M table
%End

void setFeature( const QgsFeature &feature );
void setFeature( const QgsFeature &feature, bool update = true );
%Docstring
Sets the ``feature`` being edited and updates the UI unless ``update`` is set to ``False``
%End

void setEditorContext( const QgsAttributeEditorContext &context );

@@ -129,6 +132,21 @@ Determines if the "Save child layer edits" button should be shown
.. versionadded:: 3.14
%End

QgsFeature feature() const;
%Docstring
Returns the widget's current feature

.. versionadded:: 3.14
%End

public slots:

void parentFormValueChanged( const QString &attribute, const QVariant &newValue );
%Docstring
Called when an ``attribute`` value in the parent widget has changed to ``newValue``

.. versionadded:: 3.14
%End

};

@@ -0,0 +1,7 @@
{
"name": "current_parent_value",
"type": "function",
"description": "Only usable in an embedded form context, this function returns the current, unsaved value of a field in the parent form currently being edited. This will differ from the parent feature's actual attribute values for features which are currently being edited or have not yet been added to a parent layer. When used in a value-relation widget filter expression, this function should be wrapped into a 'coalesce()' that can retrieve the actual parent feature from the layer when the form is not used in an embedded context.",
"arguments": [ {"arg":"field_name","description":"a field name in the current parent form"}],
"examples": [ { "expression":"current_parent_value( 'FIELD_NAME' )","returns":"The current value of a field 'FIELD_NAME' in the parent form."} ]
}
@@ -826,6 +826,22 @@ void QgsExpression::initVariableHelp()
sVariableHelpTexts()->insert( QStringLiteral( "current_geometry" ), QCoreApplication::translate( "current_geometry", "Represents the geometry of the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );
sVariableHelpTexts()->insert( QStringLiteral( "current_feature" ), QCoreApplication::translate( "current_feature", "Represents the feature currently being edited in the form or the table row. Can be used in a form/row context to filter the related features." ) );

//parent form context variable
sVariableHelpTexts()->insert( QStringLiteral( "current_parent_geometry" ), QCoreApplication::translate( "current_parent_geometry",
"Only usable in an embedded form context, "
"represents the geometry of the feature currently being edited in the parent form.\n"
"Can be used in a form/row context to filter the related features using a value "
"from the feature currently edited in the parent form, to make sure that the filter "
"still works with standalone forms it is recommended to wrap this variable in a "
"'coalesce()'." ) );
sVariableHelpTexts()->insert( QStringLiteral( "current_parent_feature" ), QCoreApplication::translate( "current_parent_feature",
"Only usable in an embedded form context, "
"represents the feature currently being edited in the parent form.\n"
"Can be used in a form/row context to filter the related features using a value "
"from the feature currently edited in the parent form, to make sure that the filter "
"still works with standalone forms it is recommended to wrap this variable in a "
"'coalesce()'." ) );

//form variable
sVariableHelpTexts()->insert( QStringLiteral( "form_mode" ), QCoreApplication::translate( "form_mode", "What the form is used for, like AddFeatureMode, SingleEditMode, MultiEditMode, SearchMode, AggregateSearchMode or IdentifyMode as string." ) );
}
@@ -134,6 +134,31 @@ class GetCurrentFormFieldValue : public QgsScopedExpressionFunction

};

class GetCurrentParentFormFieldValue : public QgsScopedExpressionFunction
{
public:
GetCurrentParentFormFieldValue( )
: QgsScopedExpressionFunction( QStringLiteral( "current_parent_value" ), QgsExpressionFunction::ParameterList() << QStringLiteral( "field_name" ), QStringLiteral( "Form" ) )
{}

QVariant func( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *, const QgsExpressionNodeFunction * ) override
{
QString fieldName( values.at( 0 ).toString() );
const QgsFeature feat( context->variable( QStringLiteral( "current_parent_feature" ) ).value<QgsFeature>() );
if ( fieldName.isEmpty() || ! feat.isValid( ) )
{
return QVariant();
}
return feat.attribute( fieldName ) ;
}

QgsScopedExpressionFunction *clone() const override
{
return new GetCurrentParentFormFieldValue( );
}

};


class GetProcessingParameterValue : public QgsScopedExpressionFunction
{
@@ -172,6 +197,17 @@ QgsExpressionContextScope *QgsExpressionContextUtils::formScope( const QgsFeatur
return scope;
}


QgsExpressionContextScope *QgsExpressionContextUtils::parentFormScope( const QgsFeature &parentFormFeature, const QString &parentFormMode )
{
QgsExpressionContextScope *scope = new QgsExpressionContextScope( QObject::tr( "Parent Form" ) );
scope->addFunction( QStringLiteral( "current_parent_value" ), new GetCurrentParentFormFieldValue( ) );
scope->setVariable( QStringLiteral( "current_parent_geometry" ), parentFormFeature.geometry( ), true );
scope->setVariable( QStringLiteral( "current_parent_feature" ), parentFormFeature, true );
scope->setVariable( QStringLiteral( "parent_form_mode" ), parentFormMode, true );
return scope;
}

QgsExpressionContextScope *QgsExpressionContextUtils::projectScope( const QgsProject *project )
{
if ( !project )
@@ -766,6 +802,7 @@ void QgsExpressionContextUtils::registerContextFunctions()
QgsExpression::registerFunction( new GetLayerVisibility( QList<QgsMapLayer *>(), 0.0 ) );
QgsExpression::registerFunction( new GetProcessingParameterValue( QVariantMap() ) );
QgsExpression::registerFunction( new GetCurrentFormFieldValue( ) );
QgsExpression::registerFunction( new GetCurrentParentFormFieldValue( ) );
}

bool QgsScopedExpressionFunction::usesGeometry( const QgsExpressionNodeFunction *node ) const
@@ -54,13 +54,21 @@ class CORE_EXPORT QgsExpressionContextUtils
static QgsExpressionContextScope *globalScope() SIP_FACTORY;

/**
* Creates a new scope which contains functions and variables from the current attribute form/table \a feature.
* Creates a new scope which contains functions and variables from the current attribute form/table \a formFeature.
* The variables and values in this scope will reflect the current state of the form/row being edited.
* The \a formMode (SingleEditMode etc.) is passed as text
* \since QGIS 3.2
*/
static QgsExpressionContextScope *formScope( const QgsFeature &formFeature = QgsFeature( ), const QString &formMode = QString() ) SIP_FACTORY;

/**
* Creates a new scope which contains functions and variables from the current parent attribute form/table \a formFeature.
* The variables and values in this scope will reflect the current state of the parent form/row being edited.
* The \a formMode (SingleEditMode etc.) is passed as text
* \since QGIS 3.14
*/
static QgsExpressionContextScope *parentFormScope( const QgsFeature &formFeature = QgsFeature( ), const QString &formMode = QString() ) SIP_FACTORY;

/**
* Sets a global context variable. This variable will be contained within scopes retrieved via
* globalScope().

0 comments on commit 195efa4

Please sign in to comment.
You can’t perform that action at this time.