Skip to content

Commit

Permalink
[processing] Add a new 'Calculate expression' algorithm for use in mo…
Browse files Browse the repository at this point in the history
…dels

This algorithm will simply calculate the results of a QGIS expression
and make the result available for use in other parts of the model.

It avoids the need to use the same expression multiple times throughout
a model if the same result needs to be used more than once, and also
permits use cases which otherwise are not possible (eg generating a
timestamp value once and then reusing this throughout a model -- if
every use recalculated the timestamp then the values would differ
during the model's runtime).
  • Loading branch information
nyalldawson committed Aug 25, 2023
1 parent 32abc34 commit 94d2f85
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmboundary.cpp
processing/qgsalgorithmboundingbox.cpp
processing/qgsalgorithmbuffer.cpp
processing/qgsalgorithmcalculateexpression.cpp
processing/qgsalgorithmcalculateoverlaps.cpp
processing/qgsalgorithmcategorizeusingstyle.cpp
processing/qgsalgorithmcellstatistics.cpp
Expand Down
94 changes: 94 additions & 0 deletions src/analysis/processing/qgsalgorithmcalculateexpression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/***************************************************************************
qgsalgorithmcalculateexpression.cpp
---------------------
begin : August 2023
copyright : (C) 2023 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmcalculateexpression.h"

///@cond PRIVATE

QString QgsCalculateExpressionAlgorithm::name() const
{
return QStringLiteral( "calculateexpression" );
}

QgsProcessingAlgorithm::Flags QgsCalculateExpressionAlgorithm::flags() const
{
return FlagHideFromToolbox | FlagSkipGenericModelLogging;
}

QString QgsCalculateExpressionAlgorithm::displayName() const
{
return QObject::tr( "Calculate expression" );
}

QStringList QgsCalculateExpressionAlgorithm::tags() const
{
return QObject::tr( "evaluate,variable,store" ).split( ',' );
}

QString QgsCalculateExpressionAlgorithm::group() const
{
return QObject::tr( "Modeler tools" );
}

QString QgsCalculateExpressionAlgorithm::groupId() const
{
return QStringLiteral( "modelertools" );
}

QString QgsCalculateExpressionAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm calculates the result of a QGIS expression and makes it available for use in other parts of the model." );
}

QgsCalculateExpressionAlgorithm *QgsCalculateExpressionAlgorithm::createInstance() const
{
return new QgsCalculateExpressionAlgorithm();
}

void QgsCalculateExpressionAlgorithm::initAlgorithm( const QVariantMap & )
{
// possibly this should be a new dedicated parameter type for "QgsProcessingParameterVariant", as the values specified for the parameter will
// be whatever the model calculates as the result of the expression. But this works for now...
std::unique_ptr< QgsProcessingParameterString > inputParameter = std::make_unique< QgsProcessingParameterString >( QStringLiteral( "INPUT" ), QObject::tr( "Input" ), QVariant(), false, false );
// we limit the available sources for this parameter to just precalculated expressions -- otherwise it's confusing if we allow users
// to enter a literal value for this parameter, as they could enter an expression in there and expect it to be evaluated.
inputParameter->setMetadata(
{
QVariantMap( {{
QStringLiteral( "model_widget" ),
QVariantMap(
{ {
QStringLiteral( "accepted_sources" ), QVariantList{ static_cast< int >( Qgis::ProcessingModelChildParameterSource::Expression ) }
}}
)
}} )
} );
addParameter( inputParameter.release() );

addOutput( new QgsProcessingOutputVariant( QStringLiteral( "OUTPUT" ), QObject::tr( "Value" ) ) );
}

QVariantMap QgsCalculateExpressionAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &, QgsProcessingFeedback * )
{
const QVariant res = parameters.value( QStringLiteral( "INPUT" ) );

QVariantMap outputs;
outputs.insert( QStringLiteral( "OUTPUT" ), res );
return outputs;
}

///@endcond
52 changes: 52 additions & 0 deletions src/analysis/processing/qgsalgorithmcalculateexpression.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/***************************************************************************
begin : August 2023
copyright : (C) 2023 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMCALCULATEEXPRESSION_H
#define QGSALGORITHMCALCULATEEXPRESSION_H

#define SIP_NO_FILE

#include "qgis_sip.h"
#include "qgsprocessingalgorithm.h"

///@cond PRIVATE

/**
* Native expression calculation algorithm.
*/
class QgsCalculateExpressionAlgorithm : public QgsProcessingAlgorithm
{
public:
QgsCalculateExpressionAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
Flags flags() const override;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QgsCalculateExpressionAlgorithm *createInstance() const override SIP_FACTORY;

protected:

QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback * ) override;

};

///@endcond PRIVATE

#endif // QGSALGORITHMCALCULATEEXPRESSION_H
2 changes: 2 additions & 0 deletions src/analysis/processing/qgsnativealgorithms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "qgsalgorithmboundary.h"
#include "qgsalgorithmboundingbox.h"
#include "qgsalgorithmbuffer.h"
#include "qgsalgorithmcalculateexpression.h"
#include "qgsalgorithmcalculateoverlaps.h"
#include "qgsalgorithmcategorizeusingstyle.h"
#include "qgsalgorithmcellstatistics.h"
Expand Down Expand Up @@ -285,6 +286,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsBoundaryAlgorithm() );
addAlgorithm( new QgsBoundingBoxAlgorithm() );
addAlgorithm( new QgsBufferAlgorithm() );
addAlgorithm( new QgsCalculateExpressionAlgorithm() );
addAlgorithm( new QgsCalculateVectorOverlapsAlgorithm() );
addAlgorithm( new QgsCategorizeUsingStyleAlgorithm() );
addAlgorithm( new QgsCellStatisticsAlgorithm() );
Expand Down

0 comments on commit 94d2f85

Please sign in to comment.