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.
Original file line number Diff line number Diff line change
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;
%Docstring
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

static QString invalidSourceError( const QVariantMap &parameters, const QString &name );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,55 @@ Evaluates the parameter with matching ``definition`` and ``value`` to a list of
.. versionadded:: 3.4
%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/;
%Docstring
Creates a new QgsProcessingParameterDefinition using the configuration from a
Expand Down Expand Up @@ -2756,8 +2805,9 @@ class QgsProcessingParameterLayout : QgsProcessingParameterDefinition
%Docstring
A print layout parameter, allowing users to select a print layout.

QgsProcessingParameterLayout should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsString()`
This will return the name of the target print layout.
QgsProcessingParameterLayout should be evaluated by calling :py:func:`QgsProcessingAlgorithm.parameterAsLayout()`
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
%End
Expand Down
10 changes: 10 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,16 @@ QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap &parame
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 )
{
if ( !parameters.contains( name ) )
Expand Down
20 changes: 20 additions & 0 deletions src/core/processing/qgsprocessingalgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,26 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
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
* not be loaded.
Expand Down
53 changes: 52 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
#include "qgsvectorlayer.h"
#include "qgsmeshlayer.h"
#include "qgsapplication.h"

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


Expand Down Expand Up @@ -1464,6 +1465,56 @@ QStringList QgsProcessingParameters::parameterAsFields( const QgsProcessingParam
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 )
{
QString type = map.value( QStringLiteral( "parameter_type" ) ).toString();
Expand Down
48 changes: 46 additions & 2 deletions src/core/processing/qgsprocessingparameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class QgsProcessingFeatureSource;
class QgsProcessingOutputDefinition;
class QgsProcessingFeedback;
class QgsProcessingProvider;
class QgsPrintLayout;
class QgsLayoutItem;

/**
* \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 );

/**
* 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
* supplied variant \a map.
Expand Down Expand Up @@ -2591,8 +2634,9 @@ class CORE_EXPORT QgsProcessingParameterBand : public QgsProcessingParameterDefi
* \ingroup core
* A print layout parameter, allowing users to select a print layout.
*
* QgsProcessingParameterLayout should be evaluated by calling QgsProcessingAlgorithm::parameterAsString().
* This will return the name of the target print layout.
* QgsProcessingParameterLayout should be evaluated by calling QgsProcessingAlgorithm::parameterAsLayout().
* 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
*/
Expand Down
1 change: 1 addition & 0 deletions tests/src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src/core/auth
${CMAKE_SOURCE_DIR}/src/core/expression
${CMAKE_SOURCE_DIR}/src/core/geometry
${CMAKE_SOURCE_DIR}/src/core/layout
${CMAKE_SOURCE_DIR}/src/core/mesh
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/processing
Expand Down
63 changes: 60 additions & 3 deletions tests/src/analysis/testqgsprocessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
#include "qgsmessagelog.h"
#include "qgsvectorlayer.h"
#include "qgsexpressioncontextutils.h"

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

class DummyAlgorithm : public QgsProcessingAlgorithm
{
Expand Down Expand Up @@ -5816,6 +5818,14 @@ void TestQgsProcessing::parameterLayout()
{
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!
std::unique_ptr< QgsProcessingParameterLayout > def( new QgsProcessingParameterLayout( "non_optional", QString(), QString(), false ) );
QVERIFY( def->checkValueIsAcceptable( 1 ) );
Expand All @@ -5827,6 +5837,16 @@ void TestQgsProcessing::parameterLayout()
QVariantMap params;
params.insert( "non_optional", 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( 5, context ), QStringLiteral( "'5'" ) );
Expand Down Expand Up @@ -5932,6 +5952,18 @@ void TestQgsProcessing::parameterLayoutItem()
{
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!
std::unique_ptr< QgsProcessingParameterLayoutItem > def( new QgsProcessingParameterLayoutItem( "non_optional", QString(), QVariant(), QString(), -1, false ) );
QVERIFY( def->checkValueIsAcceptable( 1 ) );
Expand All @@ -5941,9 +5973,34 @@ void TestQgsProcessing::parameterLayoutItem()

// string
QVariantMap params;
params.insert( "non_optional", QString( "a" ) );
params.insert( "non_optional", QString( "aaaa" ) );
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( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
Expand Down

0 comments on commit 0003e91

Please sign in to comment.