mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
[processing] Expose some model related variables to expressions
run inside models Allows expressions to access important variables like the current model path
This commit is contained in:
parent
2180b63e35
commit
e533a4078c
@ -1079,6 +1079,17 @@ standard scopes such as the global and project scopes.
|
|||||||
Creates a new scope which contains variables and functions relating to a processing ``algorithm``,
|
Creates a new scope which contains variables and functions relating to a processing ``algorithm``,
|
||||||
when used with the specified ``parameters`` and ``context``.
|
when used with the specified ``parameters`` and ``context``.
|
||||||
For instance, algorithm name and parameter functions.
|
For instance, algorithm name and parameter functions.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`processingModelAlgorithmScope`
|
||||||
|
%End
|
||||||
|
|
||||||
|
static QgsExpressionContextScope *processingModelAlgorithmScope( const QgsProcessingModelAlgorithm *model, const QVariantMap ¶meters, QgsProcessingContext &context ) /Factory/;
|
||||||
|
%Docstring
|
||||||
|
Creates a new scope which contains variables and functions relating to a processing ``model`` algorithm,
|
||||||
|
when used with the specified ``parameters`` and ``context``.
|
||||||
|
For instance, model name and path variables.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
%End
|
%End
|
||||||
|
|
||||||
static QgsExpressionContextScope *notificationScope( const QString &message = QString() ) /Factory/;
|
static QgsExpressionContextScope *notificationScope( const QString &message = QString() ) /Factory/;
|
||||||
|
@ -799,6 +799,10 @@ void QgsExpression::initVariableHelp()
|
|||||||
|
|
||||||
//processing variables
|
//processing variables
|
||||||
sVariableHelpTexts.insert( QStringLiteral( "algorithm_id" ), QCoreApplication::translate( "algorithm_id", "Unique ID for algorithm." ) );
|
sVariableHelpTexts.insert( QStringLiteral( "algorithm_id" ), QCoreApplication::translate( "algorithm_id", "Unique ID for algorithm." ) );
|
||||||
|
sVariableHelpTexts.insert( QStringLiteral( "model_path" ), QCoreApplication::translate( "variable_help", "Full path (including file name) of current model (or project path if model is embedded in a project)." ) );
|
||||||
|
sVariableHelpTexts.insert( QStringLiteral( "model_folder" ), QCoreApplication::translate( "variable_help", "Folder containing current model (or project folder if model is embedded in a project)." ) );
|
||||||
|
sVariableHelpTexts.insert( QStringLiteral( "model_name" ), QCoreApplication::translate( "variable_help", "Name of current model." ) );
|
||||||
|
sVariableHelpTexts.insert( QStringLiteral( "model_group" ), QCoreApplication::translate( "variable_help", "Group for current model." ) );
|
||||||
sVariableHelpTexts.insert( QStringLiteral( "fullextent_minx" ), QCoreApplication::translate( "fullextent_minx", "Minimum x-value from full canvas extent (including all layers)." ) );
|
sVariableHelpTexts.insert( QStringLiteral( "fullextent_minx" ), QCoreApplication::translate( "fullextent_minx", "Minimum x-value from full canvas extent (including all layers)." ) );
|
||||||
sVariableHelpTexts.insert( QStringLiteral( "fullextent_miny" ), QCoreApplication::translate( "fullextent_miny", "Minimum y-value from full canvas extent (including all layers)." ) );
|
sVariableHelpTexts.insert( QStringLiteral( "fullextent_miny" ), QCoreApplication::translate( "fullextent_miny", "Minimum y-value from full canvas extent (including all layers)." ) );
|
||||||
sVariableHelpTexts.insert( QStringLiteral( "fullextent_maxx" ), QCoreApplication::translate( "fullextent_maxx", "Maximum x-value from full canvas extent (including all layers)." ) );
|
sVariableHelpTexts.insert( QStringLiteral( "fullextent_maxx" ), QCoreApplication::translate( "fullextent_maxx", "Maximum x-value from full canvas extent (including all layers)." ) );
|
||||||
|
@ -1381,6 +1381,13 @@ QString QgsProcessingModelAlgorithm::asPythonCommand( const QVariantMap ¶met
|
|||||||
return QgsProcessingAlgorithm::asPythonCommand( parameters, context );
|
return QgsProcessingAlgorithm::asPythonCommand( parameters, context );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsExpressionContext QgsProcessingModelAlgorithm::createExpressionContext( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeatureSource *source ) const
|
||||||
|
{
|
||||||
|
QgsExpressionContext res = QgsProcessingAlgorithm::createExpressionContext( parameters, context, source );
|
||||||
|
res << QgsExpressionContextUtils::processingModelAlgorithmScope( this, parameters, context );
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
QgsProcessingAlgorithm *QgsProcessingModelAlgorithm::createInstance() const
|
QgsProcessingAlgorithm *QgsProcessingModelAlgorithm::createInstance() const
|
||||||
{
|
{
|
||||||
QgsProcessingModelAlgorithm *alg = new QgsProcessingModelAlgorithm();
|
QgsProcessingModelAlgorithm *alg = new QgsProcessingModelAlgorithm();
|
||||||
|
@ -57,6 +57,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
|
|||||||
|
|
||||||
bool canExecute( QString *errorMessage SIP_OUT = nullptr ) const override;
|
bool canExecute( QString *errorMessage SIP_OUT = nullptr ) const override;
|
||||||
QString asPythonCommand( const QVariantMap ¶meters, QgsProcessingContext &context ) const override;
|
QString asPythonCommand( const QVariantMap ¶meters, QgsProcessingContext &context ) const override;
|
||||||
|
QgsExpressionContext createExpressionContext( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeatureSource *source = nullptr ) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the model \a name.
|
* Sets the model \a name.
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
#include "qgsexpressionutils.h"
|
#include "qgsexpressionutils.h"
|
||||||
#include "qgslayoutrendercontext.h"
|
#include "qgslayoutrendercontext.h"
|
||||||
#include "qgsxmlutils.h"
|
#include "qgsxmlutils.h"
|
||||||
|
#include "qgsprocessingmodelalgorithm.h"
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
|
||||||
@ -1329,6 +1329,29 @@ QgsExpressionContextScope *QgsExpressionContextUtils::processingAlgorithmScope(
|
|||||||
return scope.release();
|
return scope.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsExpressionContextScope *QgsExpressionContextUtils::processingModelAlgorithmScope( const QgsProcessingModelAlgorithm *model, const QVariantMap &, QgsProcessingContext &context )
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsExpressionContextScope > modelScope( new QgsExpressionContextScope( QObject::tr( "Model" ) ) );
|
||||||
|
QString modelPath;
|
||||||
|
if ( !model->sourceFilePath().isEmpty() )
|
||||||
|
{
|
||||||
|
modelPath = model->sourceFilePath();
|
||||||
|
}
|
||||||
|
else if ( context.project() )
|
||||||
|
{
|
||||||
|
// fallback to project path -- the model may be embedded in a project, OR an unsaved model. In either case the
|
||||||
|
// project path is a logical value to fall back to
|
||||||
|
modelPath = context.project()->projectStorage() ? context.project()->fileName() : context.project()->absoluteFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString modelFolder = QFileInfo( modelPath ).path();
|
||||||
|
modelScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "model_path" ), QDir::toNativeSeparators( modelPath ), true ) );
|
||||||
|
modelScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "model_folder" ), QDir::toNativeSeparators( modelFolder ), true, true ) );
|
||||||
|
modelScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "model_name" ), model->displayName(), true ) );
|
||||||
|
modelScope->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "model_group" ), model->group(), true ) );
|
||||||
|
return modelScope.release();
|
||||||
|
}
|
||||||
|
|
||||||
QgsExpressionContextScope *QgsExpressionContextUtils::notificationScope( const QString &message )
|
QgsExpressionContextScope *QgsExpressionContextUtils::notificationScope( const QString &message )
|
||||||
{
|
{
|
||||||
std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope() );
|
std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope() );
|
||||||
|
@ -41,6 +41,7 @@ class QgsProcessingAlgorithm;
|
|||||||
class QgsProcessingContext;
|
class QgsProcessingContext;
|
||||||
class QgsLayoutAtlas;
|
class QgsLayoutAtlas;
|
||||||
class QgsLayoutItem;
|
class QgsLayoutItem;
|
||||||
|
class QgsProcessingModelAlgorithm;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup core
|
* \ingroup core
|
||||||
@ -987,9 +988,18 @@ class CORE_EXPORT QgsExpressionContextUtils
|
|||||||
* Creates a new scope which contains variables and functions relating to a processing \a algorithm,
|
* Creates a new scope which contains variables and functions relating to a processing \a algorithm,
|
||||||
* when used with the specified \a parameters and \a context.
|
* when used with the specified \a parameters and \a context.
|
||||||
* For instance, algorithm name and parameter functions.
|
* For instance, algorithm name and parameter functions.
|
||||||
|
* \see processingModelAlgorithmScope()
|
||||||
*/
|
*/
|
||||||
static QgsExpressionContextScope *processingAlgorithmScope( const QgsProcessingAlgorithm *algorithm, const QVariantMap ¶meters, QgsProcessingContext &context ) SIP_FACTORY;
|
static QgsExpressionContextScope *processingAlgorithmScope( const QgsProcessingAlgorithm *algorithm, const QVariantMap ¶meters, QgsProcessingContext &context ) SIP_FACTORY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new scope which contains variables and functions relating to a processing \a model algorithm,
|
||||||
|
* when used with the specified \a parameters and \a context.
|
||||||
|
* For instance, model name and path variables.
|
||||||
|
* \since QGIS 3.6
|
||||||
|
*/
|
||||||
|
static QgsExpressionContextScope *processingModelAlgorithmScope( const QgsProcessingModelAlgorithm *model, const QVariantMap ¶meters, QgsProcessingContext &context ) SIP_FACTORY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new scope which contains variables and functions relating to provider notifications
|
* Creates a new scope which contains variables and functions relating to provider notifications
|
||||||
* \param message the notification message
|
* \param message the notification message
|
||||||
|
@ -189,6 +189,8 @@ QgsExpressionContext QgsProcessingModelerParameterWidget::createExpressionContex
|
|||||||
alg = mModel->childAlgorithm( mChildId ).algorithm();
|
alg = mModel->childAlgorithm( mChildId ).algorithm();
|
||||||
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), mContext );
|
QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( alg, QVariantMap(), mContext );
|
||||||
c << algorithmScope;
|
c << algorithmScope;
|
||||||
|
QgsExpressionContextScope *modelScope = QgsExpressionContextUtils::processingModelAlgorithmScope( mModel, QVariantMap(), mContext );
|
||||||
|
c << modelScope;
|
||||||
QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
|
QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( mChildId, mContext, QVariantMap(), QVariantMap() );
|
||||||
c << childScope;
|
c << childScope;
|
||||||
|
|
||||||
|
@ -239,6 +239,8 @@ QgsExpressionContext QgsAbstractProcessingParameterWidgetWrapper::createExpressi
|
|||||||
|
|
||||||
if ( mWidgetContext.model() )
|
if ( mWidgetContext.model() )
|
||||||
{
|
{
|
||||||
|
c << QgsExpressionContextUtils::processingModelAlgorithmScope( mWidgetContext.model(), QVariantMap(), *context );
|
||||||
|
|
||||||
const QgsProcessingAlgorithm *alg = nullptr;
|
const QgsProcessingAlgorithm *alg = nullptr;
|
||||||
if ( mWidgetContext.model()->childAlgorithms().contains( mWidgetContext.modelChildAlgorithmId() ) )
|
if ( mWidgetContext.model()->childAlgorithms().contains( mWidgetContext.modelChildAlgorithmId() ) )
|
||||||
alg = mWidgetContext.model()->childAlgorithm( mWidgetContext.modelChildAlgorithmId() ).algorithm();
|
alg = mWidgetContext.model()->childAlgorithm( mWidgetContext.modelChildAlgorithmId() ).algorithm();
|
||||||
|
@ -562,6 +562,7 @@ class TestQgsProcessing: public QObject
|
|||||||
void processingFeatureSource();
|
void processingFeatureSource();
|
||||||
void processingFeatureSink();
|
void processingFeatureSink();
|
||||||
void algorithmScope();
|
void algorithmScope();
|
||||||
|
void modelScope();
|
||||||
void validateInputCrs();
|
void validateInputCrs();
|
||||||
void generateIteratingDestination();
|
void generateIteratingDestination();
|
||||||
void asPythonCommand();
|
void asPythonCommand();
|
||||||
@ -5999,6 +6000,39 @@ void TestQgsProcessing::algorithmScope()
|
|||||||
QCOMPARE( exp2.evaluate( &context ).toInt(), 5 );
|
QCOMPARE( exp2.evaluate( &context ).toInt(), 5 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestQgsProcessing::modelScope()
|
||||||
|
{
|
||||||
|
QgsProcessingContext pc;
|
||||||
|
|
||||||
|
QgsProcessingModelAlgorithm alg( "test", "testGroup" );
|
||||||
|
QVariantMap params;
|
||||||
|
params.insert( QStringLiteral( "a_param" ), 5 );
|
||||||
|
std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::processingModelAlgorithmScope( &alg, params, pc ) );
|
||||||
|
QVERIFY( scope.get() );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_name" ) ).toString(), QStringLiteral( "test" ) );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_group" ) ).toString(), QStringLiteral( "testGroup" ) );
|
||||||
|
QVERIFY( scope->hasVariable( QStringLiteral( "model_path" ) ) );
|
||||||
|
QVERIFY( scope->hasVariable( QStringLiteral( "model_folder" ) ) );
|
||||||
|
QVERIFY( scope->variable( QStringLiteral( "model_path" ) ).toString().isEmpty() );
|
||||||
|
QVERIFY( scope->variable( QStringLiteral( "model_folder" ) ).toString().isEmpty() );
|
||||||
|
|
||||||
|
QgsProject p;
|
||||||
|
pc.setProject( &p );
|
||||||
|
p.setFileName( TEST_DATA_DIR + QStringLiteral( "/test_file.qgs" ) );
|
||||||
|
scope.reset( QgsExpressionContextUtils::processingModelAlgorithmScope( &alg, params, pc ) );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_path" ) ).toString(), TEST_DATA_DIR + QStringLiteral( "/test_file.qgs" ) );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_folder" ) ).toString(), TEST_DATA_DIR );
|
||||||
|
|
||||||
|
alg.setSourceFilePath( TEST_DATA_DIR + QStringLiteral( "/processing/my_model.model3" ) );
|
||||||
|
scope.reset( QgsExpressionContextUtils::processingModelAlgorithmScope( &alg, params, pc ) );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_path" ) ).toString(), TEST_DATA_DIR + QStringLiteral( "/processing/my_model.model3" ) );
|
||||||
|
QCOMPARE( scope->variable( QStringLiteral( "model_folder" ) ).toString(), TEST_DATA_DIR + QStringLiteral( "/processing" ) );
|
||||||
|
|
||||||
|
QgsExpressionContext ctx = alg.createExpressionContext( QVariantMap(), pc );
|
||||||
|
QVERIFY( scope->hasVariable( QStringLiteral( "model_path" ) ) );
|
||||||
|
QVERIFY( scope->hasVariable( QStringLiteral( "model_folder" ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
void TestQgsProcessing::validateInputCrs()
|
void TestQgsProcessing::validateInputCrs()
|
||||||
{
|
{
|
||||||
DummyAlgorithm alg( "test" );
|
DummyAlgorithm alg( "test" );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user