Skip to content
Permalink
Browse files

[processing] Add a model-only algorithm for renaming layers

This is required for algorithms with behaviour which depends on the
layer names (e.g. the package algorithm uses the layer name as
the table name in the geopackage).

We need a way for models to be able to explicitly specify a layer
name for this algorithm to be useful in models, otherwise the
auto-generated temporary layer names are used (which are not
very nice!)
  • Loading branch information
nyalldawson committed Nov 26, 2017
1 parent aef0d33 commit 6283ca62bcd5a62261825476e9f321daf4e49c60
@@ -50,6 +50,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmpromotetomultipart.cpp
processing/qgsalgorithmrasterlayeruniquevalues.cpp
processing/qgsalgorithmremovenullgeometry.cpp
processing/qgsalgorithmrenamelayer.cpp
processing/qgsalgorithmsaveselectedfeatures.cpp
processing/qgsalgorithmsimplify.cpp
processing/qgsalgorithmsmooth.cpp
@@ -0,0 +1,87 @@
/***************************************************************************
qgsalgorithmrenamelayer.cpp
---------------------
begin : November 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmrenamelayer.h"

///@cond PRIVATE

QString QgsRenameLayerAlgorithm::name() const
{
return QStringLiteral( "renamelayer" );
}

QgsProcessingAlgorithm::Flags QgsRenameLayerAlgorithm::flags() const
{
return FlagHideFromToolbox;
}

QString QgsRenameLayerAlgorithm::displayName() const
{
return QObject::tr( "Rename layer" );
}

QStringList QgsRenameLayerAlgorithm::tags() const
{
return QObject::tr( "change,layer,name" ).split( ',' );
}

QString QgsRenameLayerAlgorithm::group() const
{
return QObject::tr( "Modeler tool" );
}

QString QgsRenameLayerAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm renames a layer." );
}

QgsRenameLayerAlgorithm *QgsRenameLayerAlgorithm::createInstance() const
{
return new QgsRenameLayerAlgorithm();
}

void QgsRenameLayerAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "INPUT" ), QObject::tr( "Layer" ) ) );
addParameter( new QgsProcessingParameterString( QStringLiteral( "NAME" ), QObject::tr( "New name" ) ) );
addOutput( new QgsProcessingOutputMapLayer( QStringLiteral( "OUTPUT" ), QObject::tr( "Layer" ) ) );
}

QVariantMap QgsRenameLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsMapLayer *layer = parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context );
QString name = parameterAsString( parameters, QStringLiteral( "NAME" ), context );

if ( !layer )
throw QgsProcessingException( QObject::tr( "Invalid input layer" ) );

if ( name.isEmpty() )
throw QgsProcessingException( QObject::tr( "Invalid (empty) layer name" ) );

bool parameterWasLayerName = parameters.value( QStringLiteral( "INPUT" ) ).toString() == layer->name();

layer->setName( name );
QVariantMap results;
if ( parameterWasLayerName )
results.insert( QStringLiteral( "OUTPUT" ), name );
else
results.insert( QStringLiteral( "OUTPUT" ), parameters.value( QStringLiteral( "INPUT" ) ) );

return results;
}

///@endcond
@@ -0,0 +1,53 @@
/***************************************************************************
qgsalgorithmrenamelayer.h
---------------------
begin : November 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSALGORITHMRENAMELAYER_H
#define QGSALGORITHMRENAMELAYER_H

#define SIP_NO_FILE

#include "qgis.h"
#include "qgsprocessingalgorithm.h"

///@cond PRIVATE

/**
* Native rename layer algorithm.
*/
class QgsRenameLayerAlgorithm : public QgsProcessingAlgorithm
{
public:
QgsRenameLayerAlgorithm() = default;
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
Flags flags() const override;
QString name() const override;
QString displayName() const override;
virtual QStringList tags() const override;
QString group() const override;
QString shortHelpString() const override;
QgsRenameLayerAlgorithm *createInstance() const override SIP_FACTORY;

protected:

virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback * ) override;

};

///@endcond PRIVATE

#endif // QGSALGORITHMRENAMELAYER_H
@@ -47,6 +47,7 @@
#include "qgsalgorithmpromotetomultipart.h"
#include "qgsalgorithmrasterlayeruniquevalues.h"
#include "qgsalgorithmremovenullgeometry.h"
#include "qgsalgorithmrenamelayer.h"
#include "qgsalgorithmsaveselectedfeatures.h"
#include "qgsalgorithmsimplify.h"
#include "qgsalgorithmsmooth.h"
@@ -124,6 +125,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsPromoteToMultipartAlgorithm() );
addAlgorithm( new QgsRasterLayerUniqueValuesReportAlgorithm() );
addAlgorithm( new QgsRemoveNullGeometryAlgorithm() );
addAlgorithm( new QgsRenameLayerAlgorithm() );
addAlgorithm( new QgsSaveSelectedFeatures() );
addAlgorithm( new QgsSelectByLocationAlgorithm() );
addAlgorithm( new QgsSimplifyAlgorithm() );
@@ -34,6 +34,7 @@ class TestQgsProcessingAlgs: public QObject
void init() {} // will be called before each testfunction is executed.
void cleanup() {} // will be called after every testfunction.
void packageAlg();
void renameLayerAlg();

private:

@@ -116,6 +117,58 @@ void TestQgsProcessingAlgs::packageAlg()
QCOMPARE( polygonLayer->featureCount(), mPolygonLayer->featureCount() );
}

void TestQgsProcessingAlgs::renameLayerAlg()
{
const QgsProcessingAlgorithm *package( QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "native:renamelayer" ) ) );
QVERIFY( package );

std::unique_ptr< QgsProcessingContext > context = qgis::make_unique< QgsProcessingContext >();
context->setProject( QgsProject::instance() );

QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?field=col1:real" ), QStringLiteral( "layer" ), QStringLiteral( "memory" ) );
QVERIFY( layer->isValid() );
QgsProject::instance()->addMapLayer( layer );

QgsProcessingFeedback feedback;

QVariantMap parameters;

// bad layer
parameters.insert( QStringLiteral( "INPUT" ), QStringLiteral( "bad layer" ) );
parameters.insert( QStringLiteral( "NAME" ), QStringLiteral( "new name" ) );
bool ok = false;
( void )package->run( parameters, *context, &feedback, &ok );
QVERIFY( !ok );
QCOMPARE( layer->name(), QStringLiteral( "layer" ) );

//invalid name
parameters.insert( QStringLiteral( "INPUT" ), QStringLiteral( "layer" ) );
parameters.insert( QStringLiteral( "NAME" ), QString() );
ok = false;
( void )package->run( parameters, *context, &feedback, &ok );
QVERIFY( !ok );
QCOMPARE( layer->name(), QStringLiteral( "layer" ) );

//good params
parameters.insert( QStringLiteral( "INPUT" ), QVariant::fromValue( layer ) );
parameters.insert( QStringLiteral( "NAME" ), QStringLiteral( "new name" ) );
ok = false;
QVariantMap results = package->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );
QCOMPARE( layer->name(), QStringLiteral( "new name" ) );
QCOMPARE( results.value( "OUTPUT" ), QVariant::fromValue( layer ) );

// with input layer name as parameter
parameters.insert( QStringLiteral( "INPUT" ), QStringLiteral( "new name" ) );
parameters.insert( QStringLiteral( "NAME" ), QStringLiteral( "new name2" ) );
ok = false;
results = package->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );
QCOMPARE( layer->name(), QStringLiteral( "new name2" ) );
// result should use new name as value
QCOMPARE( results.value( "OUTPUT" ).toString(), QStringLiteral( "new name2" ) );
}


QGSTEST_MAIN( TestQgsProcessingAlgs )
#include "testqgsprocessingalgs.moc"

0 comments on commit 6283ca6

Please sign in to comment.
You can’t perform that action at this time.