Skip to content

Commit

Permalink
[processing] Add json syntax option for encoding data defined parameter
Browse files Browse the repository at this point in the history
values

Refs #50482
  • Loading branch information
nyalldawson committed Jan 16, 2023
1 parent 2d403b0 commit 7b29e79
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 3 deletions.
Expand Up @@ -496,6 +496,15 @@ Removes any raw pointer values from an input ``map``, replacing them with
appropriate string values where possible.

.. versionadded:: 3.26
%End

static QVariantMap preprocessQgisProcessParameters( const QVariantMap &parameters, bool &ok, QString &error );
%Docstring
Pre-processes a set of ``parameter`` values for the qgis_process command.

In particular, this function upgrades encoded data defined values to :py:class:`QgsProperty` objects.

.. versionadded:: 3.30
%End

};
Expand Down
40 changes: 40 additions & 0 deletions src/core/processing/qgsprocessingutils.cpp
Expand Up @@ -1379,6 +1379,46 @@ QVariantMap QgsProcessingUtils::removePointerValuesFromMap( const QVariantMap &m
return res;
}

QVariantMap QgsProcessingUtils::preprocessQgisProcessParameters( const QVariantMap &parameters, bool &ok, QString &error )
{
QVariantMap output;
ok = true;
for ( auto it = parameters.constBegin(); it != parameters.constEnd(); ++it )
{
if ( it.value().type() == QVariant::Map )
{
const QVariantMap value = it.value().toMap();
if ( value.value( QStringLiteral( "type" ) ).toString() == QLatin1String( "data_defined" ) )
{
const QString expression = value.value( QStringLiteral( "expression" ) ).toString();
const QString field = value.value( QStringLiteral( "field" ) ).toString();
if ( !expression.isEmpty() )
{
output.insert( it.key(), QgsProperty::fromExpression( expression ) );
}
else if ( !field.isEmpty() )
{
output.insert( it.key(), QgsProperty::fromField( field ) );
}
else
{
ok = false;
error = QObject::tr( "Invalid data defined parameter for %1, requires 'expression' or 'field' values." ).arg( it.key() );
}
}
else
{
output.insert( it.key(), it.value() );
}
}
else
{
output.insert( it.key(), it.value() );
}
}
return output;
}

//
// QgsProcessingFeatureSource
//
Expand Down
9 changes: 9 additions & 0 deletions src/core/processing/qgsprocessingutils.h
Expand Up @@ -502,6 +502,15 @@ class CORE_EXPORT QgsProcessingUtils
*/
static QVariantMap removePointerValuesFromMap( const QVariantMap &map );

/**
* Pre-processes a set of \a parameter values for the qgis_process command.
*
* In particular, this function upgrades encoded data defined values to QgsProperty objects.
*
* \since QGIS 3.30
*/
static QVariantMap preprocessQgisProcessParameters( const QVariantMap &parameters, bool &ok, QString &error );

private:
static bool canUseLayer( const QgsRasterLayer *layer );
static bool canUseLayer( const QgsMeshLayer *layer );
Expand Down
6 changes: 5 additions & 1 deletion src/gui/processing/qgsprocessingalgorithmdialogbase.cpp
Expand Up @@ -234,7 +234,11 @@ QgsProcessingAlgorithmDialogBase::QgsProcessingAlgorithmDialogBase( QWidget *par
if ( parameterValues.isEmpty() )
return;

setParameters( parameterValues );
bool ok = false;
QString error;
const QVariantMap preparedValues = QgsProcessingUtils::preprocessQgisProcessParameters( parameterValues, ok, error );

setParameters( preparedValues );
} );

mButtonBox->addButton( mAdvancedButton, QDialogButtonBox::ResetRole );
Expand Down
13 changes: 11 additions & 2 deletions src/process/qgsprocess.cpp
Expand Up @@ -998,14 +998,23 @@ int QgsProcessingExec::showAlgorithmHelp( const QString &inputId, bool useJson )
return 0;
}

int QgsProcessingExec::execute( const QString &inputId, const QVariantMap &params, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, QgsProcessingContext::LogLevel logLevel, bool useJson, const QString &projectPath )
int QgsProcessingExec::execute( const QString &inputId, const QVariantMap &inputs, const QString &ellipsoid, QgsUnitTypes::DistanceUnit distanceUnit, QgsUnitTypes::AreaUnit areaUnit, QgsProcessingContext::LogLevel logLevel, bool useJson, const QString &projectPath )
{
QVariantMap json;
if ( useJson )
{
addVersionInformation( json );
}

bool ok = false;
QString error;
const QVariantMap params = QgsProcessingUtils::preprocessQgisProcessParameters( inputs, ok, error );
if ( !ok )
{
std::cerr << error.toLocal8Bit().constData();
return 1;
}

QString id = inputId;

std::unique_ptr< QgsProcessingModelAlgorithm > model;
Expand Down Expand Up @@ -1200,7 +1209,7 @@ int QgsProcessingExec::execute( const QString &inputId, const QVariantMap &param
} );
#endif

bool ok = false;
ok = false;
if ( !useJson )
std::cout << "\n";

Expand Down
29 changes: 29 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -799,6 +799,7 @@ class TestQgsProcessing: public QObject
void sourceTypeToString_data();
void sourceTypeToString();
void formatHelp();
void preprocessParameters();

private:

Expand Down Expand Up @@ -11675,6 +11676,34 @@ void TestQgsProcessing::formatHelp()
QCOMPARE( QgsProcessingUtils::formatHelpMapAsHtml( help, &a ), QStringLiteral( "<html><body><p></p>\n<h2>Examples</h2>\n<p>aabbcc</p><br></body></html>" ) );
}

void TestQgsProcessing::preprocessParameters()
{
QVariantMap inputs;
inputs.insert( QStringLiteral( "int" ), 5 );
inputs.insert( QStringLiteral( "string" ), QStringLiteral( "a string" ) );
inputs.insert( QStringLiteral( "data defined field" ), QVariantMap( {{QStringLiteral( "type" ), QStringLiteral( "data_defined" )}, {QStringLiteral( "field" ), QStringLiteral( "DEPTH_FIELD" ) }} ) );
inputs.insert( QStringLiteral( "data defined expression" ), QVariantMap( {{QStringLiteral( "type" ), QStringLiteral( "data_defined" )}, {QStringLiteral( "expression" ), QStringLiteral( "A_FIELD * 200" ) }} ) );
inputs.insert( QStringLiteral( "invalid" ), QVariantMap( {{QStringLiteral( "type" ), QStringLiteral( "data_defined" )}} ) );

bool ok = false;
QString error;
QVariantMap outputs = QgsProcessingUtils::preprocessQgisProcessParameters( inputs, ok, error );
QVERIFY( !ok );
QVERIFY( !error.isEmpty() );

inputs.remove( QStringLiteral( "invalid" ) );
error.clear();
outputs = QgsProcessingUtils::preprocessQgisProcessParameters( inputs, ok, error );
QVERIFY( ok );
QVERIFY( error.isEmpty() );

QCOMPARE( outputs.value( QStringLiteral( "int" ) ).toInt(), 5 );
QCOMPARE( outputs.value( QStringLiteral( "string" ) ).toString(), QStringLiteral( "a string" ) );
QCOMPARE( outputs.value( QStringLiteral( "data defined field" ) ).value< QgsProperty >().propertyType(), QgsProperty::FieldBasedProperty );
QCOMPARE( outputs.value( QStringLiteral( "data defined field" ) ).value< QgsProperty >().field(), QStringLiteral( "DEPTH_FIELD" ) );
QCOMPARE( outputs.value( QStringLiteral( "data defined expression" ) ).value< QgsProperty >().propertyType(), QgsProperty::ExpressionBasedProperty );
QCOMPARE( outputs.value( QStringLiteral( "data defined expression" ) ).value< QgsProperty >().expressionString(), QStringLiteral( "A_FIELD * 200" ) );
}

QGSTEST_MAIN( TestQgsProcessing )
#include "testqgsprocessing.moc"

0 comments on commit 7b29e79

Please sign in to comment.