Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add api to convert a processing parameter value to a string, if possible
Designed for use in converting an algorithm's parameters for
representation as a qgis_process command line
  • Loading branch information
nyalldawson committed Dec 16, 2021
1 parent e73d51d commit ee3257b
Show file tree
Hide file tree
Showing 4 changed files with 806 additions and 0 deletions.
Expand Up @@ -517,6 +517,8 @@ Returns a string version of the parameter input ``value``, which is suitable for
parameter value when running an algorithm directly from a Python command.

.. seealso:: :py:func:`valueAsJsonObject`

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

virtual QVariant valueAsJsonObject( const QVariant &value, QgsProcessingContext &context ) const;
Expand All @@ -529,6 +531,25 @@ converted to a simple string or numeric value equivalent.

.. seealso:: :py:func:`valueAsPythonString`

.. seealso:: :py:func:`valueAsString`

.. versionadded:: 3.24
%End

virtual QString valueAsString( const QVariant &value, QgsProcessingContext &context, bool &ok /Out/ ) const;
%Docstring
Returns a string version of the parameter input ``value`` (if possible).

:param value: value to convert
:param context: processing context

:return: - value converted to string
- ok: will be set to ``True`` if value could be represented as a string

.. seealso:: :py:func:`valueAsJsonObject`

.. seealso:: :py:func:`valueAsPythonString`

.. versionadded:: 3.24
%End

Expand Down
175 changes: 175 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -2649,6 +2649,181 @@ QVariant QgsProcessingParameterDefinition::valueAsJsonObject( const QVariant &va
return value;
}

QString QgsProcessingParameterDefinition::valueAsString( const QVariant &value, QgsProcessingContext &context, bool &ok ) const
{
ok = true;

if ( !value.isValid() )
return QString();

switch ( value.userType() )
{
// simple types which can be directly represented in JSON -- not that strings are NOT handled here yet!
case QMetaType::Bool:
case QMetaType::Char:
case QMetaType::Int:
case QMetaType::Double:
case QMetaType::Float:
case QMetaType::LongLong:
case QMetaType::ULongLong:
case QMetaType::UInt:
case QMetaType::ULong:
case QMetaType::UShort:
return value.toString();

default:
break;
}

if ( value.userType() == QMetaType::type( "QgsProperty" ) )
{
const QgsProperty prop = value.value< QgsProperty >();
switch ( prop.propertyType() )
{
case QgsProperty::InvalidProperty:
return QString();
case QgsProperty::StaticProperty:
return valueAsString( prop.staticValue(), context, ok );

// these are not supported for serialization
case QgsProperty::FieldBasedProperty:
case QgsProperty::ExpressionBasedProperty:
QgsDebugMsg( QStringLiteral( "could not convert expression/field based property to string" ) );
return QString();
}
}

// value may be a CRS
if ( value.userType() == QMetaType::type( "QgsCoordinateReferenceSystem" ) )
{
const QgsCoordinateReferenceSystem crs = value.value< QgsCoordinateReferenceSystem >();
if ( !crs.isValid() )
return QString();
else if ( !crs.authid().isEmpty() )
return crs.authid();
else
return crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED );
}
else if ( value.userType() == QMetaType::type( "QgsRectangle" ) )
{
const QgsRectangle r = value.value<QgsRectangle>();
return QStringLiteral( "%1, %3, %2, %4" ).arg( qgsDoubleToString( r.xMinimum() ),
qgsDoubleToString( r.yMinimum() ),
qgsDoubleToString( r.xMaximum() ),
qgsDoubleToString( r.yMaximum() ) );
}
else if ( value.userType() == QMetaType::type( "QgsReferencedRectangle" ) )
{
const QgsReferencedRectangle r = value.value<QgsReferencedRectangle>();
return QStringLiteral( "%1, %3, %2, %4 [%5]" ).arg( qgsDoubleToString( r.xMinimum() ),
qgsDoubleToString( r.yMinimum() ),
qgsDoubleToString( r.xMaximum() ),
qgsDoubleToString( r.yMaximum() ), r.crs().authid() );
}
else if ( value.userType() == QMetaType::type( "QgsGeometry" ) )
{
const QgsGeometry g = value.value<QgsGeometry>();
if ( !g.isNull() )
{
return g.asWkt();
}
else
{
return QString();
}
}
else if ( value.userType() == QMetaType::type( "QgsReferencedGeometry" ) )
{
const QgsReferencedGeometry g = value.value<QgsReferencedGeometry>();
if ( !g.isNull() )
{
if ( !g.crs().isValid() )
return g.asWkt();
else
return QStringLiteral( "CRS=%1;%2" ).arg( g.crs().authid().isEmpty() ? g.crs().toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) : g.crs().authid(), g.asWkt() );
}
else
{
return QString();
}
}
else if ( value.userType() == QMetaType::type( "QgsPointXY" ) )
{
const QgsPointXY r = value.value<QgsPointXY>();
return QStringLiteral( "%1,%2" ).arg( qgsDoubleToString( r.x() ),
qgsDoubleToString( r.y() ) );
}
else if ( value.userType() == QMetaType::type( "QgsReferencedPointXY" ) )
{
const QgsReferencedPointXY r = value.value<QgsReferencedPointXY>();
return QStringLiteral( "%1,%2 [%3]" ).arg( qgsDoubleToString( r.x() ),
qgsDoubleToString( r.y() ),
r.crs().authid() );
}
else if ( value.userType() == QMetaType::type( "QgsProcessingFeatureSourceDefinition" ) )
{
const QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
return valueAsString( fromVar.source, context, ok );
}
else if ( value.userType() == QMetaType::type( "QgsProcessingOutputLayerDefinition" ) )
{
const QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
return valueAsString( fromVar.sink, context, ok );
}
else if ( value.userType() == QMetaType::type( "QColor" ) )
{
const QColor fromVar = value.value< QColor >();
if ( !fromVar.isValid() )
return QString();

return QStringLiteral( "rgba( %1, %2, %3, %4 )" ).arg( fromVar.red() ).arg( fromVar.green() ).arg( fromVar.blue() ).arg( QString::number( fromVar.alphaF(), 'f', 2 ) );
}
else if ( value.userType() == QMetaType::type( "QDateTime" ) )
{
const QDateTime fromVar = value.toDateTime();
if ( !fromVar.isValid() )
return QString();

return fromVar.toString( Qt::ISODate );
}
else if ( value.userType() == QMetaType::type( "QDate" ) )
{
const QDate fromVar = value.toDate();
if ( !fromVar.isValid() )
return QString();

return fromVar.toString( Qt::ISODate );
}
else if ( value.userType() == QMetaType::type( "QTime" ) )
{
const QTime fromVar = value.toTime();
if ( !fromVar.isValid() )
return QString();

return fromVar.toString( Qt::ISODate );
}

// value may be a map layer
QVariantMap p;
p.insert( name(), value );
if ( QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( this, p, context ) )
{
const QString source = QgsProcessingUtils::normalizeLayerSource( layer->source() );
if ( !source.isEmpty() )
return source;
return layer->id();
}

// now we handle strings, after any other specific logic has already been applied
if ( value.userType() == QMetaType::QString )
return value.toString();

// unhandled type
QgsDebugMsg( QStringLiteral( "unsupported variant type %1" ).arg( QMetaType::typeName( value.userType() ) ) );
ok = false;
return value.toString();
}

QString QgsProcessingParameterDefinition::valueAsPythonComment( const QVariant &, QgsProcessingContext & ) const
{
return QString();
Expand Down
16 changes: 16 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -613,6 +613,7 @@ class CORE_EXPORT QgsProcessingParameterDefinition
* parameter value when running an algorithm directly from a Python command.
*
* \see valueAsJsonObject()
* \see valueAsString()
*/
virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;

Expand All @@ -624,10 +625,25 @@ class CORE_EXPORT QgsProcessingParameterDefinition
* converted to a simple string or numeric value equivalent.
*
* \see valueAsPythonString()
* \see valueAsString()
* \since QGIS 3.24
*/
virtual QVariant valueAsJsonObject( const QVariant &value, QgsProcessingContext &context ) const;

/**
* Returns a string version of the parameter input \a value (if possible).
*
* \param value value to convert
* \param context processing context
* \param ok will be set to TRUE if value could be represented as a string
* \returns value converted to string
*
* \see valueAsJsonObject()
* \see valueAsPythonString()
* \since QGIS 3.24
*/
virtual QString valueAsString( const QVariant &value, QgsProcessingContext &context, bool &ok SIP_OUT ) const;

/**
* Returns a Python comment explaining a parameter \a value, or an empty string if no comment is required.
*
Expand Down

0 comments on commit ee3257b

Please sign in to comment.