[processing] add QgsProcessingParameterMeshLayer parameter

This commit is contained in:
Peter Petrik 2018-12-12 10:58:43 +01:00
parent c7cb5a8e3b
commit e71660215c
24 changed files with 609 additions and 23 deletions

View File

@ -36,10 +36,9 @@ and parameters.
TypeRaster,
TypeFile,
TypeVector,
TypeMesh
};
};
/************************************************************************

View File

@ -670,6 +670,18 @@ sources and stored temporarily in the ``context``. In either case, callers do no
need to handle deletion of the returned layer.
%End
QgsMeshLayer *parameterAsMeshLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a mesh layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
need to handle deletion of the returned layer.
.. versionadded:: 3.6
%End
QString parameterAsOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a output layer destination.

View File

@ -155,6 +155,8 @@ their acceptable ranges, defaults, etc.
sipType = sipType_QgsProcessingParameterRange;
else if ( sipCpp->type() == QgsProcessingParameterRasterLayer::typeName() )
sipType = sipType_QgsProcessingParameterRasterLayer;
else if ( sipCpp->type() == QgsProcessingParameterMeshLayer::typeName() )
sipType = sipType_QgsProcessingParameterMeshLayer;
else if ( sipCpp->type() == QgsProcessingParameterEnum::typeName() )
sipType = sipType_QgsProcessingParameterEnum;
else if ( sipCpp->type() == QgsProcessingParameterString::typeName() )
@ -745,6 +747,29 @@ need to handle deletion of the returned layer.
.. versionadded:: 3.4
%End
static QgsMeshLayer *parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a mesh layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
need to handle deletion of the returned layer.
.. versionadded:: 3.6
%End
static QgsMeshLayer *parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` and ``value`` to a mesh layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
need to handle deletion of the returned layer.
.. versionadded:: 3.6
%End
static QgsCoordinateReferenceSystem parameterAsCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a coordinate reference system.
@ -1955,6 +1980,45 @@ Creates a new parameter using the definition from a script code.
};
class QgsProcessingParameterMeshLayer : QgsProcessingParameterDefinition
{
%Docstring
A mesh layer parameter for processing algorithms.
.. versionadded:: 3.6
%End
%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:
QgsProcessingParameterMeshLayer( const QString &name,
const QString &description = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterMeshLayer.
%End
static QString typeName();
%Docstring
Returns the type name for the parameter class.
%End
virtual QgsProcessingParameterDefinition *clone() const /Factory/;
virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;
virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;
static QgsProcessingParameterMeshLayer *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Creates a new parameter using the definition from a script code.
%End
};
class QgsProcessingParameterField : QgsProcessingParameterDefinition
{
%Docstring

View File

@ -35,6 +35,8 @@ value.
.. seealso:: :py:func:`compatibleVectorLayers`
.. seealso:: :py:func:`compatibleMeshLayers`
.. seealso:: :py:func:`compatibleLayers`
%End
@ -55,7 +57,26 @@ value.
.. seealso:: :py:func:`compatibleRasterLayers`
.. seealso:: :py:func:`compatibleMeshLayers`
.. seealso:: :py:func:`compatibleLayers`
%End
static QList<QgsMeshLayer *> compatibleMeshLayers( QgsProject *project, bool sort = true );
%Docstring
Returns a list of mesh 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:`compatibleLayers`
.. versionadded:: 3.6
%End
static QList< QgsMapLayer * > compatibleLayers( QgsProject *project, bool sort = true );
@ -76,6 +97,7 @@ value.
UnknownType,
Vector,
Raster,
Mesh,
};
static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true, LayerHint typeHint = UnknownType );

View File

@ -33,6 +33,7 @@ The QgsMapLayerProxyModel class provides an easy to use model to display the lis
VectorLayer,
PluginLayer,
WritableLayer,
MeshLayer,
All
};
typedef QFlags<QgsMapLayerProxyModel::Filter> Filters;

View File

@ -83,7 +83,8 @@ def getFileFilter(param):
return QgsProviderRegistry.instance().fileVectorFilters()
elif param.type() == 'fileDestination':
return param.fileFilter() + ';;' + tr('All files (*.*)')
elif param.type() == 'mesh':
return tr('All files (*.*)')
if param.defaultFileExtension():
return tr('Default extension') + ' (*.' + param.defaultFileExtension() + ')'
else:

View File

@ -61,6 +61,7 @@ from qgis.core import (
QgsProcessingParameterString,
QgsProcessingParameterExpression,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMeshLayer,
QgsProcessingParameterField,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterMapLayer,
@ -331,6 +332,7 @@ class CrsWidgetWrapper(WidgetWrapper):
self.combo.addItem(self.dialog.resolveValueDescription(crs), crs)
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterRasterLayer,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMeshLayer,
QgsProcessingParameterFeatureSource],
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer,
@ -402,7 +404,8 @@ class ExtentWidgetWrapper(WidgetWrapper):
widget.addItem(self.USE_MIN_COVERING_EXTENT, None)
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterFeatureSource,
QgsProcessingParameterRasterLayer,
QgsProcessingParameterVectorLayer],
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMeshLayer],
[QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer])
@ -638,10 +641,15 @@ class MultipleLayerWidgetWrapper(WidgetWrapper):
[QgsProcessingOutputRasterLayer,
QgsProcessingOutputMapLayer,
QgsProcessingOutputMultipleLayers])
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMesh:
options = self.dialog.getAvailableValuesOfType(
(QgsProcessingParameterMeshLayer, QgsProcessingParameterMultipleLayers),
[])
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMapLayer:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterRasterLayer,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMeshLayer,
QgsProcessingParameterMultipleLayers),
[QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
@ -659,11 +667,14 @@ class MultipleLayerWidgetWrapper(WidgetWrapper):
else:
if self.parameterDefinition().layerType() == QgsProcessing.TypeRaster:
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMesh:
options = QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() in (QgsProcessing.TypeVectorAnyGeometry, QgsProcessing.TypeVector):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMapLayer:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
options.extend(QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False))
options.extend(QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False))
else:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.parameterDefinition().layerType()],
False)
@ -681,11 +692,14 @@ class MultipleLayerWidgetWrapper(WidgetWrapper):
if self.parameterDefinition().layerType() != QgsProcessing.TypeFile:
if self.parameterDefinition().layerType() == QgsProcessing.TypeRaster:
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMesh:
options = QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() in (QgsProcessing.TypeVectorAnyGeometry, QgsProcessing.TypeVector):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMapLayer:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
options.extend(QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False))
options.extend(QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False))
else:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.parameterDefinition().layerType()],
False)
@ -724,11 +738,14 @@ class MultipleLayerWidgetWrapper(WidgetWrapper):
else:
if self.parameterDefinition().layerType() == QgsProcessing.TypeRaster:
options = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMesh:
options = QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False)
elif self.parameterDefinition().layerType() in (QgsProcessing.TypeVectorAnyGeometry, QgsProcessing.TypeVector):
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
elif self.parameterDefinition().layerType() == QgsProcessing.TypeMapLayer:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [], False)
options.extend(QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance(), False))
options.extend(QgsProcessingUtils.compatibleMeshLayers(QgsProject.instance(), False))
else:
options = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance(), [self.parameterDefinition().layerType()],
False)
@ -896,7 +913,7 @@ class MapLayerWidgetWrapper(WidgetWrapper):
def getAvailableLayers(self):
return self.dialog.getAvailableValuesOfType(
[QgsProcessingParameterRasterLayer, QgsProcessingParameterVectorLayer, QgsProcessingParameterMapLayer, QgsProcessingParameterString],
[QgsProcessingParameterRasterLayer, QgsProcessingParameterMeshLayer, QgsProcessingParameterVectorLayer, QgsProcessingParameterMapLayer, QgsProcessingParameterString],
[QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputString, QgsProcessingOutputFile])
def selectFile(self):
@ -986,6 +1003,22 @@ class RasterWidgetWrapper(MapLayerWidgetWrapper):
self.widgetValueHasChanged.emit(self)
class MeshWidgetWrapper(MapLayerWidgetWrapper):
def getAvailableLayers(self):
return self.dialog.getAvailableValuesOfType((QgsProcessingParameterMeshLayer, QgsProcessingParameterString),
())
def setComboBoxFilters(self, combo):
combo.setFilters(QgsMapLayerProxyModel.MeshLayer)
def selectFile(self):
filename, selected_filter = self.getFileName(self.combo.currentText())
if filename:
self.combo.setEditText(filename)
self.widgetValueHasChanged.emit(self)
class EnumWidgetWrapper(WidgetWrapper):
NOT_SELECTED = '[Not selected]'
@ -1856,6 +1889,8 @@ class WidgetWrapperFactory:
wrapper = RangeWidgetWrapper
elif param.type() == 'matrix':
wrapper = FixedTableWidgetWrapper
elif param.type() == 'mesh':
wrapper = MeshWidgetWrapper
else:
assert False, param.type()
return wrapper(param, dialog, row, col)

View File

@ -237,6 +237,9 @@ class WrappersTest(unittest.TestCase):
def testMapLayer(self):
self.checkConstructWrapper(QgsProcessingParameterMapLayer('test'), MapLayerWidgetWrapper)
def testMeshLayer(self):
self.checkConstructWrapper(QgsProcessingParameterMeshLayer('test'), MeshWidgetWrapper)
def testDistance(self):
self.checkConstructWrapper(QgsProcessingParameterDistance('test'), DistanceWidgetWrapper)

View File

@ -54,6 +54,7 @@ from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingParameterPoint,
QgsProcessingParameterRange,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMeshLayer,
QgsProcessingOutputString,
QgsProcessingOutputFile,
QgsProcessingOutputFolder,
@ -299,6 +300,7 @@ class ProcessingAlgFactory():
MULTILAYER = "MULTILAYER",
RASTER_LAYER = "RASTER_LAYER",
VECTOR_LAYER = "VECTOR_LAYER",
MESH_LAYER = "MESH_LAYER",
FILE_DEST = "FILE_DEST",
FOLDER_DEST = "FOLDER_DEST",
RASTER_LAYER_DEST = "RASTER_LAYER_DEST",
@ -439,6 +441,7 @@ class ProcessingAlgFactory():
alg.RANGE: QgsProcessingParameterRange
alg.VECTOR_LAYER: QgsProcessingParameterVectorLayer
alg.AUTH_CFG: QgsProcessingParameterAuthConfig
alg.MESH_LAYER: QgsProcessingParameterMeshLayer
:param type: The type of the input. This should be a type define on `alg` like alg.STRING, alg.DISTANCE
@ -485,6 +488,7 @@ input_type_mapping = {
ProcessingAlgFactory.RANGE: QgsProcessingParameterRange,
ProcessingAlgFactory.VECTOR_LAYER: QgsProcessingParameterVectorLayer,
ProcessingAlgFactory.AUTH_CFG: QgsProcessingParameterAuthConfig,
ProcessingAlgFactory.MESH_LAYER: QgsProcessingParameterMeshLayer,
}
output_type_mapping = {

View File

@ -43,7 +43,7 @@ class CORE_EXPORT QgsProcessing
//! Data source types enum
enum SourceType
{
TypeMapLayer = -2, //!< Any map layer type (raster or vector)
TypeMapLayer = -2, //!< Any map layer type (raster or vector or mesh)
TypeVectorAnyGeometry = -1, //!< Any vector layer with geometry
TypeVectorPoint = 0, //!< Vector point layers
TypeVectorLine = 1, //!< Vector line layers
@ -51,10 +51,9 @@ 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
};
};
#endif // QGSPROCESSING_H

View File

@ -27,6 +27,7 @@
#include "qgsmessagelog.h"
#include "qgsvectorlayer.h"
#include "qgsprocessingfeedback.h"
#include "qgsmeshlayer.h"
QgsProcessingAlgorithm::~QgsProcessingAlgorithm()
{
@ -611,6 +612,11 @@ QgsRasterLayer *QgsProcessingAlgorithm::parameterAsRasterLayer( const QVariantMa
return QgsProcessingParameters::parameterAsRasterLayer( parameterDefinition( name ), parameters, context );
}
QgsMeshLayer *QgsProcessingAlgorithm::parameterAsMeshLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
{
return QgsProcessingParameters::parameterAsMeshLayer( parameterDefinition( name ), parameters, context );
}
QString QgsProcessingAlgorithm::parameterAsOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
{
return QgsProcessingParameters::parameterAsOutputLayer( parameterDefinition( name ), parameters, context );

View File

@ -34,6 +34,7 @@ class QgsProcessingFeedback;
class QgsFeatureSink;
class QgsProcessingModelAlgorithm;
class QgsProcessingAlgorithmConfigurationWidget;
class QgsMeshLayer;
#ifdef SIP_RUN
% ModuleHeaderCode
@ -664,6 +665,18 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
QgsRasterLayer *parameterAsRasterLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
/**
* Evaluates the parameter with matching \a name to a mesh layer.
*
* Layers will either be taken from \a context's active project, or loaded from external
* sources and stored temporarily in the \a context. In either case, callers do not
* need to handle deletion of the returned layer.
*
* \since QGIS 3.6
*/
QgsMeshLayer *parameterAsMeshLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
/**
* Evaluates the parameter with matching \a name to a output layer destination.
*/

View File

@ -29,6 +29,7 @@
#include "qgsprocessingparametertype.h"
#include "qgsrasterfilewriter.h"
#include "qgsvectorlayer.h"
#include "qgsmeshlayer.h"
#include <functional>
@ -571,6 +572,16 @@ QgsRasterLayer *QgsProcessingParameters::parameterAsRasterLayer( const QgsProces
return qobject_cast< QgsRasterLayer *>( parameterAsLayer( definition, value, context ) );
}
QgsMeshLayer *QgsProcessingParameters::parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
return qobject_cast< QgsMeshLayer *>( parameterAsLayer( definition, parameters, context ) );
}
QgsMeshLayer *QgsProcessingParameters::parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context )
{
return qobject_cast< QgsMeshLayer *>( parameterAsLayer( definition, value, context ) );
}
QString QgsProcessingParameters::parameterAsOutputLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
QVariant val;
@ -1485,6 +1496,8 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromVariantM
def.reset( new QgsProcessingParameterFolderDestination( name ) );
else if ( type == QgsProcessingParameterBand::typeName() )
def.reset( new QgsProcessingParameterBand( name ) );
else if ( type == QgsProcessingParameterMeshLayer::typeName() )
def.reset( new QgsProcessingParameterMeshLayer( name ) );
else
{
QgsProcessingParameterType *paramType = QgsApplication::instance()->processingRegistry()->parameterType( type );
@ -1567,6 +1580,8 @@ QgsProcessingParameterDefinition *QgsProcessingParameters::parameterFromScriptCo
return QgsProcessingParameterFolderDestination::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "band" ) )
return QgsProcessingParameterBand::fromScriptCode( name, description, isOptional, definition );
else if ( type == QStringLiteral( "mesh" ) )
return QgsProcessingParameterMeshLayer::fromScriptCode( name, description, isOptional, definition );
return nullptr;
}
@ -3234,6 +3249,79 @@ QgsProcessingParameterVectorLayer *QgsProcessingParameterVectorLayer::fromScript
return new QgsProcessingParameterVectorLayer( name, description, QList< int>(), definition.isEmpty() ? QVariant() : definition, isOptional );
}
QgsProcessingParameterMeshLayer::QgsProcessingParameterMeshLayer( const QString &name,
const QString &description,
const QVariant &defaultValue,
bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
{
}
QgsProcessingParameterDefinition *QgsProcessingParameterMeshLayer::clone() const
{
return new QgsProcessingParameterMeshLayer( *this );
}
bool QgsProcessingParameterMeshLayer::checkValueIsAcceptable( const QVariant &v, QgsProcessingContext *context ) const
{
if ( !v.isValid() )
return mFlags & FlagOptional;
QVariant var = v;
if ( var.canConvert<QgsProperty>() )
{
QgsProperty p = var.value< QgsProperty >();
if ( p.propertyType() == QgsProperty::StaticProperty )
{
var = p.staticValue();
}
else
{
return true;
}
}
if ( qobject_cast< QgsMeshLayer * >( qvariant_cast<QObject *>( var ) ) )
return true;
if ( var.type() != QVariant::String || var.toString().isEmpty() )
return mFlags & FlagOptional;
if ( !context )
{
// that's as far as we can get without a context
return true;
}
// try to load as layer
if ( QgsProcessingUtils::mapLayerFromString( var.toString(), *context, true, QgsProcessingUtils::Mesh ) )
return true;
return false;
}
QString QgsProcessingParameterMeshLayer::valueAsPythonString( const QVariant &val, QgsProcessingContext &context ) const
{
if ( !val.isValid() )
return QStringLiteral( "None" );
if ( val.canConvert<QgsProperty>() )
return QStringLiteral( "QgsProperty.fromExpression('%1')" ).arg( val.value< QgsProperty >().asExpression() );
QVariantMap p;
p.insert( name(), val );
QgsMeshLayer *layer = QgsProcessingParameters::parameterAsMeshLayer( this, p, context );
return layer ? QgsProcessingUtils::stringToPythonLiteral( QgsProcessingUtils::normalizeLayerSource( layer->source() ) )
: QgsProcessingUtils::stringToPythonLiteral( val.toString() );
}
QgsProcessingParameterMeshLayer *QgsProcessingParameterMeshLayer::fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition )
{
return new QgsProcessingParameterMeshLayer( name, description, definition.isEmpty() ? QVariant() : definition, isOptional );
}
QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, const QString &description, const QVariant &defaultValue, const QString &parentLayerParameterName, DataType type, bool allowMultiple, bool optional )
: QgsProcessingParameterDefinition( name, description, defaultValue, optional )
, mParentLayerParameterName( parentLayerParameterName )
@ -3243,6 +3331,7 @@ QgsProcessingParameterField::QgsProcessingParameterField( const QString &name, c
}
QgsProcessingParameterDefinition *QgsProcessingParameterField::clone() const
{
return new QgsProcessingParameterField( *this );
@ -3825,6 +3914,7 @@ bool QgsProcessingParameterFeatureSink::hasGeometry() const
case QgsProcessing::TypeRaster:
case QgsProcessing::TypeFile:
case QgsProcessing::TypeVector:
case QgsProcessing::TypeMesh:
return false;
}
return true;
@ -4391,6 +4481,7 @@ bool QgsProcessingParameterVectorDestination::hasGeometry() const
case QgsProcessing::TypeRaster:
case QgsProcessing::TypeFile:
case QgsProcessing::TypeVector:
case QgsProcessing::TypeMesh:
return false;
}
return true;

View File

@ -30,6 +30,7 @@
class QgsProcessingContext;
class QgsRasterLayer;
class QgsMeshLayer;
class QgsVectorLayer;
class QgsFeatureSink;
class QgsProcessingFeatureSource;
@ -228,6 +229,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition
sipType = sipType_QgsProcessingParameterRange;
else if ( sipCpp->type() == QgsProcessingParameterRasterLayer::typeName() )
sipType = sipType_QgsProcessingParameterRasterLayer;
else if ( sipCpp->type() == QgsProcessingParameterMeshLayer::typeName() )
sipType = sipType_QgsProcessingParameterMeshLayer;
else if ( sipCpp->type() == QgsProcessingParameterEnum::typeName() )
sipType = sipType_QgsProcessingParameterEnum;
else if ( sipCpp->type() == QgsProcessingParameterString::typeName() )
@ -805,6 +808,29 @@ class CORE_EXPORT QgsProcessingParameters
*/
static QgsVectorLayer *parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition and \a value to a mesh layer.
*
* Layers will either be taken from \a context's active project, or loaded from external
* sources and stored temporarily in the \a context. In either case, callers do not
* need to handle deletion of the returned layer.
*
* \since QGIS 3.6
*/
static QgsMeshLayer *parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition and \a value to a mesh layer.
*
* Layers will either be taken from \a context's active project, or loaded from external
* sources and stored temporarily in the \a context. In either case, callers do not
* need to handle deletion of the returned layer.
*
* \since QGIS 3.6
*/
static QgsMeshLayer *parameterAsMeshLayer( const QgsProcessingParameterDefinition *definition, const QVariant &value, QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition to a coordinate reference system.
*/
@ -1889,6 +1915,39 @@ class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParame
};
/**
* \class QgsProcessingParameterMeshLayer
* \ingroup core
* A mesh layer parameter for processing algorithms.
* \since QGIS 3.6
*/
class CORE_EXPORT QgsProcessingParameterMeshLayer : public QgsProcessingParameterDefinition
{
public:
/**
* Constructor for QgsProcessingParameterMeshLayer.
*/
QgsProcessingParameterMeshLayer( const QString &name,
const QString &description = QString(),
const QVariant &defaultValue = QVariant(),
bool optional = false );
/**
* Returns the type name for the parameter class.
*/
static QString typeName() { return QStringLiteral( "mesh" ); }
QgsProcessingParameterDefinition *clone() const override SIP_FACTORY;
QString type() const override { return typeName(); }
bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;
/**
* Creates a new parameter using the definition from a script code.
*/
static QgsProcessingParameterMeshLayer *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) SIP_FACTORY;
};
/**
* \class QgsProcessingParameterField
* \ingroup core

View File

@ -64,6 +64,44 @@ class CORE_EXPORT QgsProcessingParameterTypeRasterLayer : public QgsProcessingPa
}
};
/**
* A mesh layer parameter for processing algorithms.
*
* \ingroup core
* \note No Python bindings available. Get your copy from QgsApplication.processingRegistry().parameterType('mesh')
* \since QGIS 3.2
*/
class CORE_EXPORT QgsProcessingParameterTypeMeshLayer : public QgsProcessingParameterType
{
QgsProcessingParameterDefinition *create( const QString &name ) const override SIP_FACTORY
{
return new QgsProcessingParameterMeshLayer( name );
}
QString description() const override
{
return QCoreApplication::translate( "Processing", "A mesh layer parameter." );
}
QString name() const override
{
return QCoreApplication::translate( "Processing", "Mesh Layer" );
}
QString id() const override
{
return QStringLiteral( "mesh" );
}
QStringList acceptedPythonTypes() const override
{
return QStringList() << QObject::tr( "str: layer ID" )
<< QObject::tr( "str: layer name" )
<< QObject::tr( "str: layer source" )
<< QStringLiteral( "QgsMeshLayer" );
}
};
/**
* A vector layer parameter for processing algorithms.
*

View File

@ -24,6 +24,7 @@ QgsProcessingRegistry::QgsProcessingRegistry( QObject *parent SIP_TRANSFERTHIS )
{
addParameterType( new QgsProcessingParameterTypeRasterLayer() );
addParameterType( new QgsProcessingParameterTypeVectorLayer() );
addParameterType( new QgsProcessingParameterTypeMeshLayer() );
addParameterType( new QgsProcessingParameterTypeMapLayer() );
addParameterType( new QgsProcessingParameterTypeBoolean() );
addParameterType( new QgsProcessingParameterTypeExpression() );

View File

@ -30,6 +30,7 @@
#include "qgsfileutils.h"
#include "qgsvectorlayer.h"
#include "qgsproviderregistry.h"
#include "qgsmeshlayer.h"
QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort )
{
@ -37,7 +38,9 @@ QList<QgsRasterLayer *> QgsProcessingUtils::compatibleRasterLayers( QgsProject *
return QList<QgsRasterLayer *>();
QList<QgsRasterLayer *> layers;
Q_FOREACH ( QgsRasterLayer *l, project->layers<QgsRasterLayer *>() )
const auto rasterLayers = project->layers<QgsRasterLayer *>();
for ( QgsRasterLayer *l : rasterLayers )
{
if ( canUseLayer( l ) )
layers << l;
@ -59,7 +62,8 @@ QList<QgsVectorLayer *> QgsProcessingUtils::compatibleVectorLayers( QgsProject *
return QList<QgsVectorLayer *>();
QList<QgsVectorLayer *> layers;
Q_FOREACH ( QgsVectorLayer *l, project->layers<QgsVectorLayer *>() )
const auto vectorLayers = project->layers<QgsVectorLayer *>();
for ( QgsVectorLayer *l : vectorLayers )
{
if ( canUseLayer( l, geometryTypes ) )
layers << l;
@ -75,15 +79,46 @@ QList<QgsVectorLayer *> QgsProcessingUtils::compatibleVectorLayers( QgsProject *
return layers;
}
QList<QgsMeshLayer *> QgsProcessingUtils::compatibleMeshLayers( QgsProject *project, bool sort )
{
if ( !project )
return QList<QgsMeshLayer *>();
QList<QgsMeshLayer *> layers;
const auto meshLayers = project->layers<QgsMeshLayer *>();
for ( QgsMeshLayer *l : meshLayers )
{
if ( canUseLayer( l ) )
layers << l;
}
if ( sort )
{
std::sort( layers.begin(), layers.end(), []( const QgsMeshLayer * a, const QgsMeshLayer * b ) -> bool
{
return QString::localeAwareCompare( a->name(), b->name() ) < 0;
} );
}
return layers;
}
QList<QgsMapLayer *> QgsProcessingUtils::compatibleLayers( QgsProject *project, bool sort )
{
if ( !project )
return QList<QgsMapLayer *>();
QList<QgsMapLayer *> layers;
Q_FOREACH ( QgsRasterLayer *rl, compatibleRasterLayers( project, false ) )
const auto rasterLayers = compatibleRasterLayers( project, false );
for ( QgsRasterLayer *rl : rasterLayers )
layers << rl;
Q_FOREACH ( QgsVectorLayer *vl, compatibleVectorLayers( project, QList< int >(), false ) )
const auto vectorLayers = compatibleVectorLayers( project, QList< int >(), false );
for ( QgsVectorLayer *vl : vectorLayers )
layers << vl;
const auto meshLayers = compatibleMeshLayers( project, false );
for ( QgsMeshLayer *vl : meshLayers )
layers << vl;
if ( sort )
@ -114,7 +149,7 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMa
case QgsMapLayer::PluginLayer:
return true;
case QgsMapLayer::MeshLayer:
return false;
return !canUseLayer( qobject_cast< QgsMeshLayer * >( layer ) );
}
return true;
} ), layers.end() );
@ -131,6 +166,9 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromStore( const QString &string, QgsMa
case Raster:
return l->type() == QgsMapLayer::RasterLayer;
case Mesh:
return l->type() == QgsMapLayer::MeshLayer;
}
return true;
};
@ -216,6 +254,15 @@ QgsMapLayer *QgsProcessingUtils::loadMapLayerFromString( const QString &string,
return rasterLayer.release();
}
}
if ( typeHint == UnknownType || typeHint == Mesh )
{
QgsMeshLayer::LayerOptions meshOptions;
std::unique_ptr< QgsMeshLayer > meshLayer( new QgsMeshLayer( string, name, QStringLiteral( "mdal" ), meshOptions ) );
if ( meshLayer->isValid() )
{
return meshLayer.release();
}
}
return nullptr;
}
@ -312,6 +359,11 @@ QgsProcessingFeatureSource *QgsProcessingUtils::variantToSource( const QVariant
}
}
bool QgsProcessingUtils::canUseLayer( const QgsMeshLayer *layer )
{
return layer && layer->dataProvider();
}
bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer )
{
// only gdal file-based layers
@ -494,7 +546,7 @@ void QgsProcessingUtils::createFeatureSinkPython( QgsFeatureSink **sink, QString
QgsRectangle QgsProcessingUtils::combineLayerExtents( const QList<QgsMapLayer *> &layers, const QgsCoordinateReferenceSystem &crs )
{
QgsRectangle extent;
Q_FOREACH ( QgsMapLayer *layer, layers )
for ( const QgsMapLayer *layer : layers )
{
if ( !layer )
continue;
@ -600,7 +652,9 @@ QString QgsProcessingUtils::formatHelpMapAsHtml( const QVariantMap &map, const Q
s += QStringLiteral( "<p>" ) + getText( QStringLiteral( "ALG_DESC" ) ) + QStringLiteral( "</p>\n" );
QString inputs;
Q_FOREACH ( const QgsProcessingParameterDefinition *def, algorithm->parameterDefinitions() )
const auto parameterDefinitions = algorithm->parameterDefinitions();
for ( const QgsProcessingParameterDefinition *def : parameterDefinitions )
{
inputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
inputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
@ -609,7 +663,8 @@ QString QgsProcessingUtils::formatHelpMapAsHtml( const QVariantMap &map, const Q
s += QObject::tr( "<h2>Input parameters</h2>\n" ) + inputs;
QString outputs;
Q_FOREACH ( const QgsProcessingOutputDefinition *def, algorithm->outputDefinitions() )
const auto outputDefinitions = algorithm->outputDefinitions();
for ( const QgsProcessingOutputDefinition *def : outputDefinitions )
{
outputs += QStringLiteral( "<h3>" ) + def->description() + QStringLiteral( "</h3>\n" );
outputs += QStringLiteral( "<p>" ) + getText( def->name() ) + QStringLiteral( "</p>\n" );
@ -755,7 +810,6 @@ QgsFields QgsProcessingUtils::indicesToFields( const QList<int> &indices, const
return fieldsSubset;
}
//
// QgsProcessingFeatureSource
//

View File

@ -27,6 +27,7 @@
#include "qgsfeaturesink.h"
#include "qgsfeaturesource.h"
class QgsMeshLayer;
class QgsProject;
class QgsProcessingContext;
class QgsMapLayerStore;
@ -53,6 +54,7 @@ class CORE_EXPORT QgsProcessingUtils
* If the \a sort argument is true then the layers will be sorted by their QgsMapLayer::name()
* value.
* \see compatibleVectorLayers()
* \see compatibleMeshLayers()
* \see compatibleLayers()
*/
static QList< QgsRasterLayer * > compatibleRasterLayers( QgsProject *project, bool sort = true );
@ -69,12 +71,28 @@ class CORE_EXPORT QgsProcessingUtils
* If the \a sort argument is true then the layers will be sorted by their QgsMapLayer::name()
* value.
* \see compatibleRasterLayers()
* \see compatibleMeshLayers()
* \see compatibleLayers()
*/
static QList< QgsVectorLayer * > compatibleVectorLayers( QgsProject *project,
const QList< int > &sourceTypes = QList< int >(),
bool sort = true );
/**
* Returns a list of mesh 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 compatibleLayers()
*
* \since QGIS 3.6
*/
static QList<QgsMeshLayer *> compatibleMeshLayers( QgsProject *project, bool sort = true );
/**
* Returns a list of map layers from a \a project which are compatible with the processing
* framework.
@ -95,6 +113,7 @@ class CORE_EXPORT QgsProcessingUtils
UnknownType, //!< Unknown layer type
Vector, //!< Vector layer type
Raster, //!< Raster layer type
Mesh, //!< Mesh layer type \since QGIS 3.6
};
/**
@ -263,8 +282,8 @@ class CORE_EXPORT QgsProcessingUtils
static QgsFields indicesToFields( const QList<int> &indices, const QgsFields &fields );
private:
static bool canUseLayer( const QgsRasterLayer *layer );
static bool canUseLayer( const QgsMeshLayer *layer );
static bool canUseLayer( const QgsVectorLayer *layer,
const QList< int > &sourceTypes = QList< int >() );

View File

@ -19,8 +19,10 @@
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsrasterlayer.h"
#include "qgsmeshlayer.h"
#include "qgsvectordataprovider.h"
#include "qgsrasterdataprovider.h"
#include "qgsmeshdataprovider.h"
QgsMapLayerProxyModel::QgsMapLayerProxyModel( QObject *parent )
: QSortFilterProxyModel( parent )
@ -127,6 +129,7 @@ bool QgsMapLayerProxyModel::filterAcceptsRow( int source_row, const QModelIndex
// layer type
if ( ( mFilters.testFlag( RasterLayer ) && layer->type() == QgsMapLayer::RasterLayer ) ||
( mFilters.testFlag( VectorLayer ) && layer->type() == QgsMapLayer::VectorLayer ) ||
( mFilters.testFlag( MeshLayer ) && layer->type() == QgsMapLayer::MeshLayer ) ||
( mFilters.testFlag( PluginLayer ) && layer->type() == QgsMapLayer::PluginLayer ) )
return true;

View File

@ -50,7 +50,8 @@ class CORE_EXPORT QgsMapLayerProxyModel : public QSortFilterProxyModel
VectorLayer = NoGeometry | HasGeometry,
PluginLayer = 32,
WritableLayer = 64,
All = RasterLayer | VectorLayer | PluginLayer
MeshLayer = 128, //!< QgsMeshLayer \since QGIS 3.6
All = RasterLayer | VectorLayer | PluginLayer | MeshLayer
};
Q_DECLARE_FLAGS( Filters, Filter )
Q_FLAG( Filters )

View File

@ -138,6 +138,7 @@ QStringList QgsProcessingBooleanWidgetWrapper::compatibleParameterTypes() const
<< QgsProcessingParameterMapLayer::typeName()
<< QgsProcessingParameterRasterLayer::typeName()
<< QgsProcessingParameterVectorLayer::typeName()
<< QgsProcessingParameterMeshLayer::typeName()
<< QgsProcessingParameterExpression::typeName();
}
@ -265,6 +266,7 @@ QStringList QgsProcessingCrsWidgetWrapper::compatibleParameterTypes() const
<< QgsProcessingParameterString::typeName()
<< QgsProcessingParameterRasterLayer::typeName()
<< QgsProcessingParameterVectorLayer::typeName()
<< QgsProcessingParameterMeshLayer::typeName()
<< QgsProcessingParameterFeatureSource::typeName();
}

View File

@ -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/mesh
${CMAKE_SOURCE_DIR}/src/core/metadata
${CMAKE_SOURCE_DIR}/src/core/processing
${CMAKE_SOURCE_DIR}/src/core/processing/models

View File

@ -29,6 +29,7 @@
#include "qgis.h"
#include "qgstest.h"
#include "qgsrasterlayer.h"
#include "qgsmeshlayer.h"
#include "qgsproject.h"
#include "qgspoint.h"
#include "qgsgeometry.h"
@ -40,6 +41,7 @@
#include "qgsmessagelog.h"
#include "qgsvectorlayer.h"
class DummyAlgorithm : public QgsProcessingAlgorithm
{
public:
@ -547,6 +549,7 @@ class TestQgsProcessing: public QObject
void parameterExpression();
void parameterField();
void parameterVectorLayer();
void parameterMeshLayer();
void parameterFeatureSource();
void parameterFeatureSink();
void parameterVectorOut();
@ -736,7 +739,12 @@ void TestQgsProcessing::compatibleLayers()
QgsVectorLayer *v3 = new QgsVectorLayer( "LineString", "v3", "memory" );
QgsVectorLayer *v4 = new QgsVectorLayer( "none", "vvvv4", "memory" );
p.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << r3 << v1 << v2 << v3 << v4 );
QFileInfo fm( testDataDir + "/mesh/quad_and_triangle.2dm" );
QgsMeshLayer *m1 = new QgsMeshLayer( fm.filePath(), "MX", "mdal" );
QVERIFY( m1->isValid() );
QgsMeshLayer *m2 = new QgsMeshLayer( fm.filePath(), "mA", "mdal" );
QVERIFY( m2->isValid() );
p.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << r3 << v1 << v2 << v3 << v4 << m1 << m2 );
// compatibleRasterLayers
QVERIFY( QgsProcessingUtils::compatibleRasterLayers( nullptr ).isEmpty() );
@ -753,6 +761,20 @@ void TestQgsProcessing::compatibleLayers()
lIds << rl->name();
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" );
// compatibleMeshLayers
QVERIFY( QgsProcessingUtils::compatibleMeshLayers( nullptr ).isEmpty() );
// sorted
lIds.clear();
Q_FOREACH ( QgsMeshLayer *rl, QgsProcessingUtils::compatibleMeshLayers( &p ) )
lIds << rl->name();
QCOMPARE( lIds, QStringList() << "mA" << "MX" );
// unsorted
lIds.clear();
Q_FOREACH ( QgsMeshLayer *rl, QgsProcessingUtils::compatibleMeshLayers( &p, false ) )
lIds << rl->name();
QCOMPARE( lIds, QStringList() << "MX" << "mA" );
// compatibleVectorLayers
QVERIFY( QgsProcessingUtils::compatibleVectorLayers( nullptr ).isEmpty() );
@ -812,13 +834,13 @@ void TestQgsProcessing::compatibleLayers()
lIds.clear();
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p ) )
lIds << l->name();
QCOMPARE( lIds, QStringList() << "ar2" << "R1" << "v1" << "v3" << "V4" << "vvvv4" << "zz" );
QCOMPARE( lIds, QStringList() << "ar2" << "mA" << "MX" << "R1" << "v1" << "v3" << "V4" << "vvvv4" << "zz" );
// unsorted
lIds.clear();
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p, false ) )
lIds << l->name();
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" << "V4" << "v1" << "v3" << "vvvv4" );
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" << "V4" << "v1" << "v3" << "vvvv4" << "MX" << "mA" );
}
void TestQgsProcessing::normalizeLayerSource()
@ -4518,6 +4540,124 @@ void TestQgsProcessing::parameterVectorLayer()
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
}
void TestQgsProcessing::parameterMeshLayer()
{
// setup a context
QgsProject p;
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
QString vector1 = testDataDir + "multipoint.shp";
QString raster = testDataDir + "landsat.tif";
QString mesh = testDataDir + "mesh/quad_and_triangle.2dm";
QFileInfo fi1( raster );
QFileInfo fi2( vector1 );
QFileInfo fi3( mesh );
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
QgsVectorLayer *v1 = new QgsVectorLayer( fi2.filePath(), "V4", "ogr" );
QgsMeshLayer *m1 = new QgsMeshLayer( fi3.filePath(), "M1", "mdal" );
Q_ASSERT( m1 );
p.addMapLayers( QList<QgsMapLayer *>() << v1 << r1 << m1 );
QgsProcessingContext context;
context.setProject( &p );
// not optional!
std::unique_ptr< QgsProcessingParameterMeshLayer > def( new QgsProcessingParameterMeshLayer( "non_optional", QString(), QString( "somelayer" ), false ) );
QVERIFY( !def->checkValueIsAcceptable( false ) );
QVERIFY( !def->checkValueIsAcceptable( true ) );
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
QVERIFY( !def->checkValueIsAcceptable( "" ) );
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( m1 ) ) );
QVERIFY( !def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
QVERIFY( !def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
// should be OK
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.2dm" ) );
// ... unless we use context, when the check that the layer actually exists is performed
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.2dm", &context ) );
// using existing map layer ID
QVariantMap params;
params.insert( "non_optional", m1->id() );
QCOMPARE( QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context )->id(), m1->id() );
// using existing layer
params.insert( "non_optional", QVariant::fromValue( m1 ) );
QCOMPARE( QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context )->id(), m1->id() );
// not mesh layer
params.insert( "non_optional", r1->id() );
QVERIFY( !QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context ) );
// using existing non-mesh layer
params.insert( "non_optional", QVariant::fromValue( r1 ) );
QVERIFY( !QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context ) );
// string representing a layer source
params.insert( "non_optional", mesh );
QCOMPARE( QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context )->publicSource(), mesh );
// nonsense string
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
QCOMPARE( def->valueAsPythonString( mesh, context ), QString( "'" ) + testDataDir + QStringLiteral( "mesh/quad_and_triangle.2dm'" ) );
QCOMPARE( def->valueAsPythonString( m1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "mesh/quad_and_triangle.2dm'" ) );
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( m1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "mesh/quad_and_triangle.2dm'" ) );
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
QCOMPARE( def->valueAsPythonString( QStringLiteral( "c:\\test\\new data\\test.2dm" ), context ), QStringLiteral( "'c:\\\\test\\\\new data\\\\test.2dm'" ) );
QString code = def->asScriptCode();
QCOMPARE( code, QStringLiteral( "##non_optional=mesh somelayer" ) );
std::unique_ptr< QgsProcessingParameterMeshLayer > fromCode( dynamic_cast< QgsProcessingParameterMeshLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
QVERIFY( fromCode.get() );
QCOMPARE( fromCode->name(), def->name() );
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
QCOMPARE( fromCode->flags(), def->flags() );
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
QVariantMap map = def->toVariantMap();
QgsProcessingParameterMeshLayer fromMap( "x" );
QVERIFY( fromMap.fromVariantMap( map ) );
QCOMPARE( fromMap.name(), def->name() );
QCOMPARE( fromMap.description(), def->description() );
QCOMPARE( fromMap.flags(), def->flags() );
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
def.reset( dynamic_cast< QgsProcessingParameterMeshLayer *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
QVERIFY( dynamic_cast< QgsProcessingParameterMeshLayer *>( def.get() ) );
// optional
def.reset( new QgsProcessingParameterMeshLayer( "optional", QString(), m1->id(), true ) );
params.insert( "optional", QVariant() );
QCOMPARE( QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context )->id(), m1->id() );
QVERIFY( def->checkValueIsAcceptable( false ) );
QVERIFY( def->checkValueIsAcceptable( true ) );
QVERIFY( def->checkValueIsAcceptable( 5 ) );
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.2dm" ) );
QVERIFY( def->checkValueIsAcceptable( "" ) );
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
code = def->asScriptCode();
QCOMPARE( code, QStringLiteral( "##optional=optional mesh " ) + m1->id() );
fromCode.reset( dynamic_cast< QgsProcessingParameterMeshLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
QVERIFY( fromCode.get() );
QCOMPARE( fromCode->name(), def->name() );
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
QCOMPARE( fromCode->flags(), def->flags() );
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
//optional with direct layer default
def.reset( new QgsProcessingParameterMeshLayer( "optional", QString(), QVariant::fromValue( m1 ), true ) );
QCOMPARE( QgsProcessingParameters::parameterAsMeshLayer( def.get(), params, context )->id(), m1->id() );
}
void TestQgsProcessing::parameterFeatureSource()
{
// setup a context

View File

@ -14,7 +14,7 @@ __revision__ = '$Format:%H$'
import qgis # NOQA
from qgis.core import QgsVectorLayer, QgsProject, QgsMapLayerModel, QgsMapLayerProxyModel
from qgis.core import QgsVectorLayer, QgsMeshLayer, QgsProject, QgsMapLayerModel, QgsMapLayerProxyModel
from qgis.PyQt.QtCore import Qt, QModelIndex
from qgis.testing import start_app, unittest
@ -28,6 +28,11 @@ def create_layer(name):
return layer
def create_mesh_layer(name):
layer = QgsMeshLayer("1.0, 2.0\n2.0, 2.0\n3.0, 2.0\n---\n0, 1, 3", name, "mesh_memory")
return layer
class TestQgsMapLayerProxyModel(unittest.TestCase):
def testGettersSetters(self):
@ -56,6 +61,19 @@ class TestQgsMapLayerProxyModel(unittest.TestCase):
m.setFilterString('c')
self.assertEqual(m.filterString(), 'c')
def testMeshLayer(self):
m = QgsMapLayerProxyModel()
l1 = create_mesh_layer("l1")
QgsProject.instance().addMapLayer(l1)
l2 = create_layer('l2')
QgsProject.instance().addMapLayer(l2)
m.setFilters(QgsMapLayerProxyModel.MeshLayer)
self.assertEqual(m.filters(), QgsMapLayerProxyModel.MeshLayer)
self.assertEqual(m.rowCount(), 1)
self.assertEqual(m.data(m.index(0, 0)), 'l1')
def testFilterGeometryType(self):
""" test filtering by geometry type """
QgsProject.instance().clear()