Skip to content

Commit

Permalink
[processing] Add a model-only algorithm for renaming layers
Browse files Browse the repository at this point in the history
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 6283ca6
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
87 changes: 87 additions & 0 deletions src/analysis/processing/qgsalgorithmrenamelayer.cpp
Original file line number Diff line number Diff line change
@@ -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
53 changes: 53 additions & 0 deletions src/analysis/processing/qgsalgorithmrenamelayer.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/analysis/processing/qgsnativealgorithms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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() );
Expand Down
53 changes: 53 additions & 0 deletions tests/src/analysis/testqgsprocessingalgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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.