Skip to content

Commit

Permalink
add support for plugin layers in QgsProcessingParameterMapLayer and
Browse files Browse the repository at this point in the history
QgsProcessingParameterMultipleLayers (fix #44183)
  • Loading branch information
alexbruy authored and nyalldawson committed Jul 29, 2021
1 parent 0e37716 commit 7cb631e
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 2 deletions.
3 changes: 2 additions & 1 deletion python/core/auto_generated/processing/qgsprocessing.sip.in
Expand Up @@ -36,7 +36,8 @@ and parameters.
TypeRaster,
TypeFile,
TypeVector,
TypeMesh
TypeMesh,
TypePlugin
};

enum PythonOutputType
Expand Down
25 changes: 25 additions & 0 deletions python/core/auto_generated/processing/qgsprocessingutils.sip.in
Expand Up @@ -37,6 +37,8 @@ value.

.. seealso:: :py:func:`compatibleMeshLayers`

.. seealso:: :py:func:`compatiblePluginLayers`

.. seealso:: :py:func:`compatibleLayers`
%End

Expand All @@ -59,6 +61,8 @@ value.

.. seealso:: :py:func:`compatibleMeshLayers`

.. seealso:: :py:func:`compatiblePluginLayers`

.. seealso:: :py:func:`compatibleLayers`
%End

Expand All @@ -74,9 +78,30 @@ value.

.. seealso:: :py:func:`compatibleVectorLayers`

.. seealso:: :py:func:`compatiblePluginLayers`

.. seealso:: :py:func:`compatibleLayers`

.. versionadded:: 3.6
%End

static QList<QgsPluginLayer *> compatiblePluginLayers( QgsProject *project, bool sort = true );
%Docstring
Returns a list of plugin layers from a ``project`` which are compatible with the processing
framework.

If the ``sort`` argument is ``True`` then the layers will be sorted by their :py:func:`QgsMapLayer.name()`
value.

.. seealso:: :py:func:`compatibleRasterLayers`

.. seealso:: :py:func:`compatibleVectorLayers`

.. seealso:: :py:func:`compatibleMeshLayers`

.. seealso:: :py:func:`compatibleLayers`

.. versionadded:: 3.22
%End

static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );
Expand Down
5 changes: 4 additions & 1 deletion src/core/processing/qgsprocessing.h
Expand Up @@ -52,7 +52,8 @@ class CORE_EXPORT QgsProcessing
TypeRaster = 3, //!< Raster layers
TypeFile = 4, //!< Files (i.e. non map layer sources, such as text files)
TypeVector = 5, //!< Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink has no geometry.
TypeMesh = 6 //!< Mesh layers \since QGIS 3.6
TypeMesh = 6, //!< Mesh layers \since QGIS 3.6
TypePlugin = 7 //!< Plugin layers \since QGIS 3.22
};

//! Available Python output types
Expand Down Expand Up @@ -88,6 +89,8 @@ class CORE_EXPORT QgsProcessing
return QStringLiteral( "TypeVector" );
case QgsProcessing::TypeMesh:
return QStringLiteral( "TypeMesh" );
case QgsProcessing::TypePlugin:
return QStringLiteral( "TypePlugin" );
}
return QString();
}
Expand Down
13 changes: 13 additions & 0 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -2720,6 +2720,10 @@ QString QgsProcessingParameterMapLayer::asScriptCode() const
case QgsProcessing::TypeMesh:
code += QLatin1String( "mesh " );
break;

case QgsProcessing::TypePlugin:
code += QLatin1String( "plugin " );
break;
}
}

Expand Down Expand Up @@ -2769,6 +2773,12 @@ QgsProcessingParameterMapLayer *QgsProcessingParameterMapLayer::fromScriptCode(
def = def.mid( 5 );
continue;
}
else if ( def.startsWith( QLatin1String( "plugin" ), Qt::CaseInsensitive ) )
{
types << QgsProcessing::TypePlugin;
def = def.mid( 7 );
continue;
}
break;
}

Expand Down Expand Up @@ -3848,6 +3858,7 @@ QString QgsProcessingParameterMultipleLayers::createFileFilter() const
return QgsProviderRegistry::instance()->fileMeshFilters() + QStringLiteral( ";;" ) + QObject::tr( "All files (*.*)" );

case QgsProcessing::TypeMapLayer:
case QgsProcessing::TypePlugin:
return createAllMapLayerFileFilter();
}
return QString();
Expand Down Expand Up @@ -5840,6 +5851,7 @@ bool QgsProcessingParameterFeatureSink::hasGeometry() const
case QgsProcessing::TypeFile:
case QgsProcessing::TypeVector:
case QgsProcessing::TypeMesh:
case QgsProcessing::TypePlugin:
return false;
}
return true;
Expand Down Expand Up @@ -6535,6 +6547,7 @@ bool QgsProcessingParameterVectorDestination::hasGeometry() const
case QgsProcessing::TypeFile:
case QgsProcessing::TypeVector:
case QgsProcessing::TypeMesh:
case QgsProcessing::TypePlugin:
return false;
}
return true;
Expand Down
33 changes: 33 additions & 0 deletions src/core/processing/qgsprocessingutils.cpp
Expand Up @@ -31,6 +31,7 @@
#include "qgsvectorlayer.h"
#include "qgsproviderregistry.h"
#include "qgsmeshlayer.h"
#include "qgspluginlayer.h"
#include "qgsreferencedgeometry.h"
#include "qgsrasterfilewriter.h"
#include "qgsvectortilelayer.h"
Expand Down Expand Up @@ -107,6 +108,29 @@ QList<QgsMeshLayer *> QgsProcessingUtils::compatibleMeshLayers( QgsProject *proj
return layers;
}

QList<QgsPluginLayer *> QgsProcessingUtils::compatiblePluginLayers( QgsProject *project, bool sort )
{
if ( !project )
return QList<QgsPluginLayer *>();

QList<QgsPluginLayer *> layers;
const auto pluginLayers = project->layers<QgsPluginLayer *>();
for ( QgsPluginLayer *l : pluginLayers )
{
if ( canUseLayer( l ) )
layers << l;
}

if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsPluginLayer * a, const QgsPluginLayer * b ) -> bool
{
return QString::localeAwareCompare( a->name(), b->name() ) < 0;
} );
}
return layers;
}

QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project, bool sort )
{
if ( !project )
Expand All @@ -126,6 +150,10 @@ QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project,
for ( QgsMeshLayer *vl : meshLayers )
layers << vl;

const auto pluginLayers = compatiblePluginLayers( project, false );
for ( QgsPluginLayer *pl : pluginLayers )
layers << pl;

if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsMapLayer * a, const QgsMapLayer * b ) -> bool
Expand Down Expand Up @@ -493,6 +521,11 @@ bool QgsProcessingUtils::canUseLayer( const QgsMeshLayer *layer )
return layer && layer->dataProvider();
}

bool QgsProcessingUtils::canUseLayer( const QgsPluginLayer *layer )
{
return layer && layer->isValid();
}

bool QgsProcessingUtils::canUseLayer( const QgsVectorTileLayer *layer )
{
return layer && layer->isValid();
Expand Down
21 changes: 21 additions & 0 deletions src/core/processing/qgsprocessingutils.h
Expand Up @@ -30,6 +30,7 @@
#include "qgsremappingproxyfeaturesink.h"

class QgsMeshLayer;
class QgsPluginLayer;
class QgsProject;
class QgsProcessingContext;
class QgsMapLayerStore;
Expand Down Expand Up @@ -59,6 +60,7 @@ class CORE_EXPORT QgsProcessingUtils
* value.
* \see compatibleVectorLayers()
* \see compatibleMeshLayers()
* \see compatiblePluginLayers()
* \see compatibleLayers()
*/
static QList< QgsRasterLayer * > compatibleRasterLayers( QgsProject *project, bool sort = true );
Expand All @@ -76,6 +78,7 @@ class CORE_EXPORT QgsProcessingUtils
* value.
* \see compatibleRasterLayers()
* \see compatibleMeshLayers()
* \see compatiblePluginLayers()
* \see compatibleLayers()
*/
static QList< QgsVectorLayer * > compatibleVectorLayers( QgsProject *project,
Expand All @@ -91,12 +94,29 @@ class CORE_EXPORT QgsProcessingUtils
*
* \see compatibleRasterLayers()
* \see compatibleVectorLayers()
* \see compatiblePluginLayers()
* \see compatibleLayers()
*
* \since QGIS 3.6
*/
static QList<QgsMeshLayer *> compatibleMeshLayers( QgsProject *project, bool sort = true );

/**
* Returns a list of plugin layers from a \a project which are compatible with the processing
* framework.
*
* If the \a sort argument is TRUE then the layers will be sorted by their QgsMapLayer::name()
* value.
*
* \see compatibleRasterLayers()
* \see compatibleVectorLayers()
* \see compatibleMeshLayers()
* \see compatibleLayers()
*
* \since QGIS 3.22
*/
static QList<QgsPluginLayer *> compatiblePluginLayers( QgsProject *project, bool sort = true );

/**
* Returns a list of map layers from a \a project which are compatible with the processing
* framework.
Expand Down Expand Up @@ -415,6 +435,7 @@ class CORE_EXPORT QgsProcessingUtils
private:
static bool canUseLayer( const QgsRasterLayer *layer );
static bool canUseLayer( const QgsMeshLayer *layer );
static bool canUseLayer( const QgsPluginLayer *layer );
static bool canUseLayer( const QgsVectorTileLayer *layer );
static bool canUseLayer( const QgsVectorLayer *layer,
const QList< int > &sourceTypes = QList< int >() );
Expand Down
17 changes: 17 additions & 0 deletions src/gui/processing/qgsprocessingmultipleselectiondialog.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsvectorlayer.h"
#include "qgsmeshlayer.h"
#include "qgsrasterlayer.h"
#include "qgspluginlayer.h"
#include "qgsproject.h"
#include "processing/models/qgsprocessingmodelchildparametersource.h"
#include <QStandardItemModel>
Expand Down Expand Up @@ -404,6 +405,17 @@ void QgsProcessingMultipleInputPanelWidget::populateFromProject( QgsProject *pro
break;
}

case QgsProcessing::TypePlugin:
{
const QList<QgsPluginLayer *> options = QgsProcessingUtils::compatiblePluginLayers( project, false );
for ( const QgsPluginLayer *layer : options )
{
addLayer( layer );
}

break;
}

case QgsProcessing::TypeVector:
case QgsProcessing::TypeVectorAnyGeometry:
{
Expand Down Expand Up @@ -433,6 +445,11 @@ void QgsProcessingMultipleInputPanelWidget::populateFromProject( QgsProject *pro
{
addLayer( layer );
}
const QList<QgsPluginLayer *> plugins = QgsProcessingUtils::compatiblePluginLayers( project );
for ( const QgsPluginLayer *layer : plugins )
{
addLayer( layer );
}

break;
}
Expand Down
13 changes: 13 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -5757,6 +5757,7 @@ QgsProcessingMapLayerParameterDefinitionWidget::QgsProcessingMapLayerParameterDe
mLayerTypeComboBox->addItem( tr( "Vector (Any Geometry Type)" ), QgsProcessing::TypeVectorAnyGeometry );
mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );

if ( const QgsProcessingParameterMapLayer *layerParam = dynamic_cast<const QgsProcessingParameterMapLayer *>( definition ) )
{
Expand Down Expand Up @@ -6736,6 +6737,17 @@ void QgsProcessingMultipleLayerPanelWidget::setModel( QgsProcessingModelAlgorith
break;
}

case QgsProcessing::TypePlugin:
{
mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterMapLayer::typeName()
<< QgsProcessingParameterMultipleLayers::typeName()
<< QgsProcessingParameterFile::typeName(),
QStringList() << QgsProcessingOutputFile::typeName()
<< QgsProcessingOutputMapLayer::typeName()
<< QgsProcessingOutputMultipleLayers::typeName() );
break;
}

case QgsProcessing::TypeVector:
{
mModelSources = model->availableSourcesForChild( modelChildAlgorithmID, QStringList() << QgsProcessingParameterFeatureSource::typeName()
Expand Down Expand Up @@ -6877,6 +6889,7 @@ QgsProcessingMultipleLayerParameterDefinitionWidget::QgsProcessingMultipleLayerP
mLayerTypeComboBox->addItem( tr( "Raster" ), QgsProcessing::TypeRaster );
mLayerTypeComboBox->addItem( tr( "File" ), QgsProcessing::TypeFile );
mLayerTypeComboBox->addItem( tr( "Mesh" ), QgsProcessing::TypeMesh );
mLayerTypeComboBox->addItem( tr( "Plugin" ), QgsProcessing::TypePlugin );
if ( const QgsProcessingParameterMultipleLayers *layersParam = dynamic_cast<const QgsProcessingParameterMultipleLayers *>( definition ) )
mLayerTypeComboBox->setCurrentIndex( mLayerTypeComboBox->findData( layersParam->layerType() ) );

Expand Down
5 changes: 5 additions & 0 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -2876,6 +2876,11 @@ void TestQgsProcessing::parameterMapLayer()
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterMapLayer('non_optional', '', defaultValue='', types=[QgsProcessing.TypeRaster,QgsProcessing.TypeVectorPoint])" ) );
code = def->asScriptCode();
QCOMPARE( code, QStringLiteral( "##non_optional=layer raster point" ) );
def->setDataTypes( QList< int >() << QgsProcessing::TypePlugin );
pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterMapLayer('non_optional', '', defaultValue='', types=[QgsProcessing.TypePlugin])" ) );
code = def->asScriptCode();
QCOMPARE( code, QStringLiteral( "##non_optional=layer plugin" ) );

// optional
def.reset( new QgsProcessingParameterMapLayer( "optional", QString(), v1->id(), true ) );
Expand Down

0 comments on commit 7cb631e

Please sign in to comment.