Skip to content

Commit

Permalink
[processing] Add option for multiple field parameters to default to
Browse files Browse the repository at this point in the history
selecting all available fields

For some algorithms this is better UX then defaulting to an empty list
  • Loading branch information
nyalldawson committed Jan 4, 2020
1 parent 306a603 commit 1a74938
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 6 deletions.
Expand Up @@ -2358,7 +2358,8 @@ A vector layer or feature source field parameter for processing algorithms.
const QString &parentLayerParameterName = QString(),
DataType type = Any,
bool allowMultiple = false,
bool optional = false );
bool optional = false,
bool defaultToAllFields = false );
%Docstring
Constructor for QgsProcessingParameterField.
%End
Expand Down Expand Up @@ -2421,6 +2422,26 @@ Returns whether multiple field selections are permitted.
Sets whether multiple field selections are permitted.

.. seealso:: :py:func:`allowMultiple`
%End

bool defaultToAllFields() const;
%Docstring
Returns whether a parameter which allows multiple selections (see allowMultiple()) should automatically
select all fields as the default value.

.. seealso:: :py:func:`setDefaultToAllFields`

.. versionadded:: 3.12
%End

void setDefaultToAllFields( bool enabled );
%Docstring
Sets whether a parameter which allows multiple selections (see allowMultiple()) should automatically
select all fields as the default value.

.. seealso:: :py:func:`defaultToAllFields`

.. versionadded:: 3.12
%End

virtual QVariantMap toVariantMap() const;
Expand Down
3 changes: 3 additions & 0 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -1572,6 +1572,9 @@ def setLayer(self, layer):

self.refreshItems()

if self.parameterDefinition().allowMultiple() and self.parameterDefinition().defaultToAllFields():
self.setValue(self.getFields())

def refreshItems(self):
if self.parameterDefinition().allowMultiple():
self.widget.updateForOptions(self.getFields())
Expand Down
36 changes: 32 additions & 4 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -3863,11 +3863,12 @@ QgsProcessingParameterMeshLayer *QgsProcessingParameterMeshLayer::fromScriptCode
return new QgsProcessingParameterMeshLayer( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
}

QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, DataType type, bool allowMultiple, bool optional )
QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, DataType type, bool allowMultiple, bool optional, bool defaultToAllFields )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentLayerParameterName( parentLayerParameterName )
, mDataType( type )
, mAllowMultiple( allowMultiple )
, mDefaultToAllFields( defaultToAllFields )
{

}
Expand Down Expand Up @@ -3973,6 +3974,9 @@ QString QgsProcessingParameterField::asScriptCode() const
if ( mAllowMultiple )
code += QStringLiteral( "multiple " );

if ( mDefaultToAllFields )
code += QStringLiteral( "default_to_all_fields " );

code += mParentLayerParameterName + ' ';

code += mDefault.toString();
Expand Down Expand Up @@ -4012,9 +4016,14 @@ QString QgsProcessingParameterField::asPythonString( const QgsProcessing::Python

code += QStringLiteral( ", parentLayerParameterName='%1'" ).arg( mParentLayerParameterName );
code += QStringLiteral( ", allowMultiple=%1" ).arg( mAllowMultiple ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );

QgsProcessingContext c;
code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
code += QStringLiteral( ", defaultValue=%1" ).arg( valueAsPythonString( mDefault, c ) );

if ( mDefaultToAllFields )
code += QStringLiteral( ", defaultToAllFields=True" );

code += ')';

return code;
}
}
Expand Down Expand Up @@ -4059,12 +4068,23 @@ void QgsProcessingParameterField::setAllowMultiple( bool allowMultiple )
mAllowMultiple = allowMultiple;
}

bool QgsProcessingParameterField::defaultToAllFields() const
{
return mDefaultToAllFields;
}

void QgsProcessingParameterField::setDefaultToAllFields( bool enabled )
{
mDefaultToAllFields = enabled;
}

QVariantMap QgsProcessingParameterField::toVariantMap() const
{
QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
map.insert( QStringLiteral( "parent_layer" ), mParentLayerParameterName );
map.insert( QStringLiteral( "data_type" ), mDataType );
map.insert( QStringLiteral( "allow_multiple" ), mAllowMultiple );
map.insert( QStringLiteral( "default_to_all_fields" ), mDefaultToAllFields );
return map;
}

Expand All @@ -4074,6 +4094,7 @@ bool QgsProcessingParameterField::fromVariantMap( const QVariantMap &map )
mParentLayerParameterName = map.value( QStringLiteral( "parent_layer" ) ).toString();
mDataType = static_cast< DataType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
mAllowMultiple = map.value( QStringLiteral( "allow_multiple" ) ).toBool();
mDefaultToAllFields = map.value( QStringLiteral( "default_to_all_fields" ) ).toBool();
return true;
}

Expand All @@ -4082,6 +4103,7 @@ QgsProcessingParameterField *QgsProcessingParameterField::fromScriptCode( const
QString parent;
DataType type = Any;
bool allowMultiple = false;
bool defaultToAllFields = false;
QString def = definition;

if ( def.startsWith( QLatin1String( "numeric " ), Qt::CaseInsensitive ) )
Expand All @@ -4106,6 +4128,12 @@ QgsProcessingParameterField *QgsProcessingParameterField::fromScriptCode( const
def = def.mid( 8 ).trimmed();
}

if ( def.startsWith( QLatin1String( "default_to_all_fields" ), Qt::CaseInsensitive ) )
{
defaultToAllFields = true;
def = def.mid( 21 ).trimmed();
}

QRegularExpression re( QStringLiteral( "(.*?)\\s+(.*)$" ) );
QRegularExpressionMatch m = re.match( def );
if ( m.hasMatch() )
Expand All @@ -4119,7 +4147,7 @@ QgsProcessingParameterField *QgsProcessingParameterField::fromScriptCode( const
def.clear();
}

return new QgsProcessingParameterField( name, description, def.isEmpty() ? QVariant() : def, parent, type, allowMultiple, isOptional );
return new QgsProcessingParameterField( name, description, def.isEmpty() ? QVariant() : def, parent, type, allowMultiple, isOptional, defaultToAllFields );
}

QgsProcessingParameterFeatureSource::QgsProcessingParameterFeatureSource( const QString &name, const QString &description, const QList<int> &types, const QVariant &defaultValue, bool optional )
Expand Down
22 changes: 21 additions & 1 deletion src/core/processing/qgsprocessingparameters.h
Expand Up @@ -2255,7 +2255,8 @@ class CORE_EXPORT QgsProcessingParameterField : public QgsProcessingParameterDef
const QString &parentLayerParameterName = QString(),
DataType type = Any,
bool allowMultiple = false,
bool optional = false );
bool optional = false,
bool defaultToAllFields = false );

/**
* Returns the type name for the parameter class.
Expand Down Expand Up @@ -2305,6 +2306,24 @@ class CORE_EXPORT QgsProcessingParameterField : public QgsProcessingParameterDef
*/
void setAllowMultiple( bool allowMultiple );

/**
* Returns whether a parameter which allows multiple selections (see allowMultiple()) should automatically
* select all fields as the default value.
*
* \see setDefaultToAllFields()
* \since QGIS 3.12
*/
bool defaultToAllFields() const;

/**
* Sets whether a parameter which allows multiple selections (see allowMultiple()) should automatically
* select all fields as the default value.
*
* \see defaultToAllFields()
* \since QGIS 3.12
*/
void setDefaultToAllFields( bool enabled );

QVariantMap toVariantMap() const override;
bool fromVariantMap( const QVariantMap &map ) override;

Expand All @@ -2318,6 +2337,7 @@ class CORE_EXPORT QgsProcessingParameterField : public QgsProcessingParameterDef
QString mParentLayerParameterName;
DataType mDataType = Any;
bool mAllowMultiple = false;
bool mDefaultToAllFields = false;

};

Expand Down
37 changes: 37 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -4754,6 +4754,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

QVERIFY( def->dependsOnOtherParameters().isEmpty() );
def->setParentLayerParameterName( "my_parent" );
Expand All @@ -4772,6 +4773,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

def->setDataType( QgsProcessingParameterField::Numeric );
pythonCode = def->asPythonString();
Expand All @@ -4786,6 +4788,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

def->setDataType( QgsProcessingParameterField::String );
pythonCode = def->asPythonString();
Expand All @@ -4800,6 +4803,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

def->setDataType( QgsProcessingParameterField::DateTime );
pythonCode = def->asPythonString();
Expand All @@ -4814,6 +4818,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

// multiple
def.reset( new QgsProcessingParameterField( "non_optional", QString(), QVariant(), QString(), QgsProcessingParameterField::Any, true, false ) );
Expand Down Expand Up @@ -4847,6 +4852,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromMap.parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromMap.dataType(), def->dataType() );
QCOMPARE( fromMap.allowMultiple(), def->allowMultiple() );
QCOMPARE( fromMap.defaultToAllFields(), def->defaultToAllFields() );
def.reset( dynamic_cast< QgsProcessingParameterField *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
QVERIFY( dynamic_cast< QgsProcessingParameterField *>( def.get() ) );

Expand All @@ -4862,6 +4868,36 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

// default to all fields
def.reset( new QgsProcessingParameterField( "non_optional", QString(), QVariant(), QString(), QgsProcessingParameterField::Any, true, false, true ) );
map = def->toVariantMap();
QVERIFY( fromMap.fromVariantMap( map ) );
QCOMPARE( fromMap.name(), def->name() );
QCOMPARE( fromMap.description(), def->description() );
QCOMPARE( fromMap.flags(), def->flags() );
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
QCOMPARE( fromMap.parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromMap.dataType(), def->dataType() );
QCOMPARE( fromMap.allowMultiple(), def->allowMultiple() );
QCOMPARE( fromMap.defaultToAllFields(), def->defaultToAllFields() );
def.reset( dynamic_cast< QgsProcessingParameterField *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
QVERIFY( dynamic_cast< QgsProcessingParameterField *>( def.get() ) );

pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterField('non_optional', '', type=QgsProcessingParameterField.Any, parentLayerParameterName='', allowMultiple=True, defaultValue=None, defaultToAllFields=True)" ) );
code = def->asScriptCode();
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
QVERIFY( fromCode.get() );
QCOMPARE( fromCode->name(), def->name() );
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
QCOMPARE( fromCode->flags(), def->flags() );
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

// optional
def.reset( new QgsProcessingParameterField( "optional", QString(), QString( "def" ), QString(), QgsProcessingParameterField::Any, false, true ) );
Expand Down Expand Up @@ -4895,6 +4931,7 @@ void TestQgsProcessing::parameterField()
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
QCOMPARE( fromCode->dataType(), def->dataType() );
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
QCOMPARE( fromCode->defaultToAllFields(), def->defaultToAllFields() );

//optional with multiples
def.reset( new QgsProcessingParameterField( "optional", QString(), QString( "abc;def" ), QString(), QgsProcessingParameterField::Any, true, true ) );
Expand Down

0 comments on commit 1a74938

Please sign in to comment.