Skip to content

Commit

Permalink
Add methods to resolve parameters to layouts/layout items
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 11, 2019
1 parent ba82954 commit 0003e91
Show file tree
Hide file tree
Showing 8 changed files with 265 additions and 8 deletions.
Expand Up @@ -783,6 +783,30 @@ Evaluates the parameter with matching ``name`` to a range of values.
QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const; QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring %Docstring
Evaluates the parameter with matching ``name`` to a list of fields. Evaluates the parameter with matching ``name`` to a list of fields.
%End

QgsPrintLayout *parameterAsLayout( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a print layout.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End

QgsLayoutItem *parameterAsLayoutItem( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QgsPrintLayout *layout );
%Docstring
Evaluates the parameter with matching ``name`` to a print layout item, taken from the specified ``layout``.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End %End


static QString invalidSourceError( const QVariantMap &parameters, const QString &name ); static QString invalidSourceError( const QVariantMap &parameters, const QString &name );
Expand Down
Expand Up @@ -937,6 +937,55 @@ Evaluates the parameter with matching ``definition`` and ``value`` to a list of
.. versionadded:: 3.4 .. versionadded:: 3.4
%End %End


static QgsPrintLayout *parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a print layout.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End

static QgsPrintLayout *parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a print layout.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End

static QgsLayoutItem *parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, QgsPrintLayout *layout );
%Docstring
Evaluates the parameter with matching ``definition`` to a print layout item, taken from the specified ``layout``.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End

static QgsLayoutItem *parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, QgsPrintLayout *layout );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a print layout, taken from the specified ``layout``.

.. warning::

This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.

.. versionadded:: 3.8
%End


static QgsProcessingParameterDefinition *parameterFromVariantMap( const QVariantMap &map ) /Factory/; static QgsProcessingParameterDefinition *parameterFromVariantMap( const QVariantMap &map ) /Factory/;
%Docstring %Docstring
Creates a new QgsProcessingParameterDefinition using the configuration from a Creates a new QgsProcessingParameterDefinition using the configuration from a
Expand Down Expand Up @@ -2756,8 +2805,9 @@ class QgsProcessingParameterLayout : QgsProcessingParameterDefinition
%Docstring %Docstring
A print layout parameter, allowing users to select a print layout. A print layout parameter, allowing users to select a print layout.


QgsProcessingParameterLayout should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsString()` QgsProcessingParameterLayout should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsLayout()`
This will return the name of the target print layout. This will return the matching layout from the context's current project. Alternatively, calling
QgsProcessingAlgorithm.parameterAsString() will return the name of the target print layout.


.. versionadded:: 3.8 .. versionadded:: 3.8
%End %End
Expand Down
10 changes: 10 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -691,6 +691,16 @@ QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap &parame
return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context ); return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context );
} }


QgsPrintLayout *QgsProcessingAlgorithm::parameterAsLayout( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
{
return QgsProcessingParameters::parameterAsLayout( parameterDefinition( name ), parameters, context );
}

QgsLayoutItem *QgsProcessingAlgorithm::parameterAsLayoutItem( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QgsPrintLayout *layout )
{
return QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition( name ), parameters, context, layout );
}

QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap &parameters, const QString &name ) QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap &parameters, const QString &name )
{ {
if ( !parameters.contains( name ) ) if ( !parameters.contains( name ) )
Expand Down
20 changes: 20 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -780,6 +780,26 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/ */
QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const; QStringList parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;


/**
* Evaluates the parameter with matching \a name to a print layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
QgsPrintLayout *parameterAsLayout( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a print layout item, taken from the specified \a layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
QgsLayoutItem *parameterAsLayoutItem( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QgsPrintLayout *layout );

/** /**
* Returns a user-friendly string to use as an error when a source parameter could * Returns a user-friendly string to use as an error when a source parameter could
* not be loaded. * not be loaded.
Expand Down
53 changes: 52 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -31,7 +31,8 @@
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
#include "qgsmeshlayer.h" #include "qgsmeshlayer.h"
#include "qgsapplication.h" #include "qgsapplication.h"

#include "qgslayoutmanager.h"
#include "qgsprintlayout.h"
#include <functional> #include <functional>




Expand Down Expand Up @@ -1464,6 +1465,56 @@ QStringList QgsProcessingParameters::parameterAsFields( const QgsProcessingParam
return resultStringList; return resultStringList;
} }


QgsPrintLayout *QgsProcessingParameters::parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
if ( !definition )
return nullptr;

return parameterAsLayout( definition, parameters.value( definition->name() ), context );
}

QgsPrintLayout *QgsProcessingParameters::parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
{
const QString layoutName = parameterAsString( definition, value, context );
if ( layoutName.isEmpty() )
return nullptr;

if ( !context.project() )
return nullptr;

QgsMasterLayoutInterface *l = context.project()->layoutManager()->layoutByName( layoutName );
if ( l && l->layoutType() == QgsMasterLayoutInterface::PrintLayout )
return static_cast< QgsPrintLayout * >( l );
else
return nullptr;
}

QgsLayoutItem *QgsProcessingParameters::parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, QgsPrintLayout *layout )
{
if ( !definition )
return nullptr;

return parameterAsLayoutItem( definition, parameters.value( definition->name() ), context, layout );
}

QgsLayoutItem *QgsProcessingParameters::parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, QgsPrintLayout *layout )
{
if ( !layout )
return nullptr;

const QString id = parameterAsString( definition, value, context );
if ( id.isEmpty() )
return nullptr;

// prefer matching by uuid, since it's gauranteed to be unique.
if ( QgsLayoutItem *item = layout->itemByUuid( id ) )
return item;
else if ( QgsLayoutItem *item = layout->itemById( id ) )
return item;
else
return nullptr;
}

QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantMap( const QVariantMap &map ) QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantMap( const QVariantMap &map )
{ {
QString type = map.value( QStringLiteral( "parameter_type" ) ).toString(); QString type = map.value( QStringLiteral( "parameter_type" ) ).toString();
Expand Down
48 changes: 46 additions & 2 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -38,6 +38,8 @@ class QgsProcessingFeatureSource;
class QgsProcessingOutputDefinition; class QgsProcessingOutputDefinition;
class QgsProcessingFeedback; class QgsProcessingFeedback;
class QgsProcessingProvider; class QgsProcessingProvider;
class QgsPrintLayout;
class QgsLayoutItem;


/** /**
* \class QgsProcessingFeatureSourceDefinition * \class QgsProcessingFeatureSourceDefinition
Expand Down Expand Up @@ -989,6 +991,47 @@ class CORE_EXPORT QgsProcessingParameters
*/ */
static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context ); static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );


/**
* Evaluates the parameter with matching \a definition to a print layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
static QgsPrintLayout *parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a definition and \a value to a print layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
static QgsPrintLayout *parameterAsLayout( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a definition to a print layout item, taken from the specified \a layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
static QgsLayoutItem *parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, QgsPrintLayout *layout );

/**
* Evaluates the parameter with matching \a definition and \a value to a print layout, taken from the specified \a layout.
*
* \warning This method is not safe to run in a background thread, so it must either be used within a prepareAlgorithm
* implementation (which runs in the main thread), or the algorithm must return the FlagNoThreading flag.
*
* \since QGIS 3.8
*/
static QgsLayoutItem *parameterAsLayoutItem( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context, QgsPrintLayout *layout );


/** /**
* Creates a new QgsProcessingParameterDefinition using the configuration from a * Creates a new QgsProcessingParameterDefinition using the configuration from a
* supplied variant \a map. * supplied variant \a map.
Expand Down Expand Up @@ -2591,8 +2634,9 @@ class CORE_EXPORT QgsProcessingParameterBand : public QgsProcessingParameterDefi
* \ingroup core * \ingroup core
* A print layout parameter, allowing users to select a print layout. * A print layout parameter, allowing users to select a print layout.
* *
* QgsProcessingParameterLayout should be evaluated by calling QgsProcessingAlgorithm::parameterAsString(). * QgsProcessingParameterLayout should be evaluated by calling QgsProcessingAlgorithm::parameterAsLayout().
* This will return the name of the target print layout. * This will return the matching layout from the context's current project. Alternatively, calling
* QgsProcessingAlgorithm::parameterAsString() will return the name of the target print layout.
* *
* \since QGIS 3.8 * \since QGIS 3.8
*/ */
Expand Down
1 change: 1 addition & 0 deletions tests/src/analysis/CMakeLists.txt
Expand Up @@ -11,6 +11,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/auth ${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/expression ${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry ${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/layout
${CMAKE_SOURCE_DIR}/src/core/mesh ${CMAKE_SOURCE_DIR}/src/core/mesh
${CMAKE_SOURCE_DIR}/src/core/metadata ${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/processing ${CMAKE_SOURCE_DIR}/src/core/processing
Expand Down
63 changes: 60 additions & 3 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -41,7 +41,9 @@
#include "qgsmessagelog.h" #include "qgsmessagelog.h"
#include "qgsvectorlayer.h" #include "qgsvectorlayer.h"
#include "qgsexpressioncontextutils.h" #include "qgsexpressioncontextutils.h"

#include "qgsprintlayout.h"
#include "qgslayoutmanager.h"
#include "qgslayoutitemlabel.h"


class DummyAlgorithm : public QgsProcessingAlgorithm class DummyAlgorithm : public QgsProcessingAlgorithm
{ {
Expand Down Expand Up @@ -5816,6 +5818,14 @@ void TestQgsProcessing::parameterLayout()
{ {
QgsProcessingContext context; QgsProcessingContext context;


QgsProject p;
QgsPrintLayout *l = new QgsPrintLayout( &p );
l->setName( "l1" );
QgsPrintLayout *l2 = new QgsPrintLayout( &p );
l2->setName( "l2" );
p.layoutManager()->addLayout( l );
p.layoutManager()->addLayout( l2 );

// not optional! // not optional!
std::unique_ptr< QgsProcessingParameterLayout > def( new QgsProcessingParameterLayout( "non_optional", QString(), QString(), false ) ); std::unique_ptr< QgsProcessingParameterLayout > def( new QgsProcessingParameterLayout( "non_optional", QString(), QString(), false ) );
QVERIFY( def->checkValueIsAcceptable( 1 ) ); QVERIFY( def->checkValueIsAcceptable( 1 ) );
Expand All @@ -5827,6 +5837,16 @@ void TestQgsProcessing::parameterLayout()
QVariantMap params; QVariantMap params;
params.insert( "non_optional", QString( "abcdef" ) ); params.insert( "non_optional", QString( "abcdef" ) );
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString( "abcdef" ) ); QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString( "abcdef" ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayout( def.get(), params, context ) );
params.insert( "non_optional", QString( "l1" ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayout( def.get(), params, context ) );
context.setProject( &p );
params.insert( "non_optional", QString( "abcdef" ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayout( def.get(), params, context ) );
params.insert( "non_optional", QString( "l1" ) );
QCOMPARE( QgsProcessingParameters::parameterAsLayout( def.get(), params, context ), l );
params.insert( "non_optional", QString( "l2" ) );
QCOMPARE( QgsProcessingParameters::parameterAsLayout( def.get(), params, context ), l2 );


QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) ); QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "'5'" ) ); QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "'5'" ) );
Expand Down Expand Up @@ -5932,6 +5952,18 @@ void TestQgsProcessing::parameterLayoutItem()
{ {
QgsProcessingContext context; QgsProcessingContext context;


QgsProject p;
QgsPrintLayout *l = new QgsPrintLayout( &p );
l->setName( "l1" );
QgsLayoutItemLabel *label1 = new QgsLayoutItemLabel( l );
label1->setId( "a" );
l->addLayoutItem( label1 );
QgsLayoutItemLabel *label2 = new QgsLayoutItemLabel( l );
label2->setId( "b" );
l->addLayoutItem( label2 );

QgsPrintLayout *l2 = new QgsPrintLayout( &p );

// not optional! // not optional!
std::unique_ptr< QgsProcessingParameterLayoutItem > def( new QgsProcessingParameterLayoutItem( "non_optional", QString(), QVariant(), QString(), -1, false ) ); std::unique_ptr< QgsProcessingParameterLayoutItem > def( new QgsProcessingParameterLayoutItem( "non_optional", QString(), QVariant(), QString(), -1, false ) );
QVERIFY( def->checkValueIsAcceptable( 1 ) ); QVERIFY( def->checkValueIsAcceptable( 1 ) );
Expand All @@ -5941,9 +5973,34 @@ void TestQgsProcessing::parameterLayoutItem()


// string // string
QVariantMap params; QVariantMap params;
params.insert( "non_optional", QString( "a" ) ); params.insert( "non_optional", QString( "aaaa" ) );
QString f = QgsProcessingParameters::parameterAsString( def.get(), params, context ); QString f = QgsProcessingParameters::parameterAsString( def.get(), params, context );
QCOMPARE( f, QStringLiteral( "a" ) ); QCOMPARE( f, QStringLiteral( "aaaa" ) );

QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, nullptr ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ) );
params.insert( "non_optional", label1->uuid() );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, nullptr ) );
params.insert( "non_optional", QString( "abcdef" ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, nullptr ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ) );
params.insert( "non_optional", label1->uuid() );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, nullptr ) );
QVERIFY( !QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l2 ) );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label1 );
params.insert( "non_optional", label1->id() );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label1 );
params.insert( "non_optional", label2->uuid() );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label2 );
params.insert( "non_optional", label2->id() );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label2 );
// UUID matching must take precedence
label1->setId( label2->uuid() );
params.insert( "non_optional", label2->uuid() );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label2 );
label2->setId( label1->uuid() );
params.insert( "non_optional", label1->uuid() );
QCOMPARE( QgsProcessingParameters::parameterAsLayoutItem( def.get(), params, context, l ), label1 );


QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) ); QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) ); QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
Expand Down

0 comments on commit 0003e91

Please sign in to comment.