Skip to content

Commit

Permalink
Add missing tests for vector input parameter, add vector out parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 21, 2017
1 parent 0da3652 commit c685ec2
Show file tree
Hide file tree
Showing 4 changed files with 407 additions and 1 deletion.
60 changes: 60 additions & 0 deletions python/core/processing/qgsprocessingparameters.sip
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ class QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSource;
else if ( sipCpp->type() == "sink" )
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "vectorOut" )
sipType = sipType_QgsProcessingParameterVectorOutput;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
else if ( sipCpp->type() == "fileOut" )
Expand Down Expand Up @@ -1173,6 +1175,10 @@ class QgsProcessingParameterVectorLayer : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;

virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;


};

Expand Down Expand Up @@ -1355,6 +1361,60 @@ class QgsProcessingParameterFeatureSink : QgsProcessingParameterDefinition
virtual bool fromVariantMap( const QVariantMap &map );


};


class QgsProcessingParameterVectorOutput : QgsProcessingParameterDefinition
{
%Docstring
A vector layer output parameter. Consider using the more flexible QgsProcessingParameterFeatureSink wherever
possible.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterVectorOutput( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny, const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterVectorOutput.
%End

virtual QString type() const;
virtual bool isDestination() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;

virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;


QgsProcessingParameterDefinition::LayerType dataType() const;
%Docstring
Returns the layer type for layers associated with the parameter.
.. seealso:: setDataType()
:rtype: QgsProcessingParameterDefinition.LayerType
%End

bool hasGeometry() const;
%Docstring
Returns true if the layer is likely to include geometries. In cases were presence of geometry
cannot be reliably determined in advance, this method will default to returning true.
:rtype: bool
%End

void setDataType( QgsProcessingParameterDefinition::LayerType type );
%Docstring
Sets the layer ``type`` for the layers associated with the parameter.
.. seealso:: dataType()
%End

virtual QVariantMap toVariantMap() const;

virtual bool fromVariantMap( const QVariantMap &map );


};

class QgsProcessingParameterRasterOutput : QgsProcessingParameterDefinition
Expand Down
141 changes: 140 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,14 +744,16 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantM
def.reset( new QgsProcessingParameterString( name ) );
else if ( type == QStringLiteral( "expression" ) )
def.reset( new QgsProcessingParameterExpression( name ) );
else if ( type == QStringLiteral( "table" ) )
else if ( type == QStringLiteral( "vector" ) )
def.reset( new QgsProcessingParameterVectorLayer( name ) );
else if ( type == QStringLiteral( "field" ) )
def.reset( new QgsProcessingParameterField( name ) );
else if ( type == QStringLiteral( "source" ) )
def.reset( new QgsProcessingParameterFeatureSource( name ) );
else if ( type == QStringLiteral( "sink" ) )
def.reset( new QgsProcessingParameterFeatureSink( name ) );
else if ( type == QStringLiteral( "vectorOut" ) )
def.reset( new QgsProcessingParameterVectorOutput( name ) );
else if ( type == QStringLiteral( "rasterOut" ) )
def.reset( new QgsProcessingParameterRasterOutput( name ) );
else if ( type == QStringLiteral( "fileOut" ) )
Expand Down Expand Up @@ -1737,6 +1739,46 @@ QgsProcessingParameterVectorLayer::QgsProcessingParameterVectorLayer( const QStr

}

bool QgsProcessingParameterVectorLayer::checkValueIsAcceptable( const QVariant &var, QgsProcessingContext *context ) const
{
if ( !var.isValid() )
return mFlags & FlagOptional;

if ( var.canConvert<QgsProperty>() )
{
return true;
}

if ( qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( var ) ) )
return true;

if ( var.type() != QVariant::String || var.toString().isEmpty() )
return mFlags & FlagOptional;

if ( !context )
{
// that's as far as we can get without a context
return true;
}

// try to load as layer
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context ) )
return true;

return false;
}

QString QgsProcessingParameterVectorLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
{
if ( val.canConvert<QgsProperty>() )
return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );

QVariantMap p;
p.insert( name(), val );
QgsVectorLayer *layer = QgsProcessingParameters::parameterAsVectorLayer( this, p, context );
return layer ? QgsProcessingUtils::normalizeLayerSource( layer->source() ).prepend( '\'' ).append( '\'' ) : QString();
}

QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, DataType type, bool allowMultiple, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentLayerParameter( parentLayerParameterName )
Expand Down Expand Up @@ -2208,3 +2250,100 @@ bool QgsProcessingParameterFolderOutput::checkValueIsAcceptable( const QVariant

return true;
}

QgsProcessingParameterVectorOutput::QgsProcessingParameterVectorOutput( const QString &name, const QString &description, QgsProcessingParameterDefinition::LayerType type, const QVariant &defaultValue, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mDataType( type )
{

}

bool QgsProcessingParameterVectorOutput::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const
{
QVariant var = input;
if ( !var.isValid() )
return mFlags & FlagOptional;

if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
{
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
var = fromVar.sink;
}

if ( var.canConvert<QgsProperty>() )
{
return true;
}

if ( var.type() != QVariant::String )
return false;

if ( var.toString().isEmpty() )
return mFlags & FlagOptional;

return true;
}

QString QgsProcessingParameterVectorOutput::valueAsPythonString( const QVariant &value, QgsProcessingContext & ) const
{
if ( value.canConvert<QgsProperty>() )
return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( value.value< QgsProperty >().asExpression() );

if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
{
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
if ( fromVar.sink.propertyType() == QgsProperty::StaticProperty )
{
return QStringLiteral( "QgsProcessingOutputLayerDefinition('%1')" ).arg( fromVar.sink.staticValue().toString() );
}
else
{
return QStringLiteral( "QgsProcessingOutputLayerDefinition(QgsProperty.fromExpression('%1'))" ).arg( fromVar.sink.asExpression() );
}
}

return value.toString().prepend( '\'' ).append( '\'' );
}

QgsProcessingParameterDefinition::LayerType QgsProcessingParameterVectorOutput::dataType() const
{
return mDataType;
}

bool QgsProcessingParameterVectorOutput::hasGeometry() const
{
switch ( mDataType )
{
case TypeAny:
case TypeVectorAny:
case TypeVectorPoint:
case TypeVectorLine:
case TypeVectorPolygon:
case TypeTable:
return true;

case TypeRaster:
case TypeFile:
return false;
}
return true;
}

void QgsProcessingParameterVectorOutput::setDataType( QgsProcessingParameterDefinition::LayerType type )
{
mDataType = type;
}

QVariantMap QgsProcessingParameterVectorOutput::toVariantMap() const
{
QVariantMap map = QgsProcessingParameterDefinition::toVariantMap();
map.insert( QStringLiteral( "data_type" ), mDataType );
return map;
}

bool QgsProcessingParameterVectorOutput::fromVariantMap( const QVariantMap &map )
{
QgsProcessingParameterDefinition::fromVariantMap( map );
mDataType = static_cast< QgsProcessingParameterDefinition::LayerType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
return true;
}
53 changes: 53 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterFeatureSource;
else if ( sipCpp->type() == "sink" )
sipType = sipType_QgsProcessingParameterFeatureSink;
else if ( sipCpp->type() == "vectorOut" )
sipType = sipType_QgsProcessingParameterVectorOutput;
else if ( sipCpp->type() == "rasterOut" )
sipType = sipType_QgsProcessingParameterRasterOutput;
else if ( sipCpp->type() == "fileOut" )
Expand Down Expand Up @@ -1138,6 +1140,8 @@ class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParame
bool optional = false );

QString type() const override { return QStringLiteral( "vector" ); }
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;

};

Expand Down Expand Up @@ -1312,6 +1316,55 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingParame
QgsProcessingParameterDefinition::LayerType mDataType = QgsProcessingParameterDefinition::TypeVectorAny;
};


/**
* \class QgsProcessingParameterVectorOutput
* \ingroup core
* A vector layer output parameter. Consider using the more flexible QgsProcessingParameterFeatureSink wherever
* possible.
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingParameterVectorOutput : public QgsProcessingParameterDefinition
{
public:

/**
* Constructor for QgsProcessingParameterVectorOutput.
*/
QgsProcessingParameterVectorOutput( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny, const QVariant &defaultValue = QVariant(),
bool optional = false );

QString type() const override { return QStringLiteral( "vectorOut" ); }
bool isDestination() const override { return true; }
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;

/**
* Returns the layer type for layers associated with the parameter.
* \see setDataType()
*/
QgsProcessingParameterDefinition::LayerType dataType() const;

/**
* Returns true if the layer is likely to include geometries. In cases were presence of geometry
* cannot be reliably determined in advance, this method will default to returning true.
*/
bool hasGeometry() const;

/**
* Sets the layer \a type for the layers associated with the parameter.
* \see dataType()
*/
void setDataType( QgsProcessingParameterDefinition::LayerType type );

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

private:

QgsProcessingParameterDefinition::LayerType mDataType = QgsProcessingParameterDefinition::TypeVectorAny;
};

/**
* \class QgsProcessingParameterRasterOutput
* \ingroup core
Expand Down
Loading

0 comments on commit c685ec2

Please sign in to comment.