From 97c1b0d3223318e6110fa6c496b560e29e3a58c8 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 12 Oct 2017 08:29:25 +1000 Subject: [PATCH] [FEATURE] Port autoincremental field to c++ Also add: - support for setting initial value for field to start at - support for user-set field names (instead of always using 'AUTO') --- python/plugins/processing/algs/help/qgis.yaml | 7 -- .../algs/qgis/AutoincrementalField.py | 60 ------------- .../algs/qgis/QGISAlgorithmProvider.py | 2 - .../autoincrement_field_field_name.gml | 86 +++++++++++++++++++ .../autoincrement_field_field_name.xsd | 44 ++++++++++ .../expected/autoincrement_field_start.gml | 86 +++++++++++++++++++ .../expected/autoincrement_field_start.xsd | 44 ++++++++++ .../tests/testdata/qgis_algorithm_tests.yaml | 29 ++++++- src/core/processing/qgsnativealgorithms.cpp | 46 ++++++++++ src/core/processing/qgsnativealgorithms.h | 33 +++++++ 10 files changed, 367 insertions(+), 70 deletions(-) delete mode 100644 python/plugins/processing/algs/qgis/AutoincrementalField.py create mode 100644 python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.gml create mode 100644 python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.xsd create mode 100644 python/plugins/processing/tests/testdata/expected/autoincrement_field_start.gml create mode 100644 python/plugins/processing/tests/testdata/expected/autoincrement_field_start.xsd diff --git a/python/plugins/processing/algs/help/qgis.yaml b/python/plugins/processing/algs/help/qgis.yaml index 898b2fe40da..c0b1d5f1f50 100644 --- a/python/plugins/processing/algs/help/qgis.yaml +++ b/python/plugins/processing/algs/help/qgis.yaml @@ -1,10 +1,3 @@ -qgis:addautoincrementalfield: > - This algorithm adds a new integer field to a vector layer, with a sequential value for each feature. - - This field can be used as a unique ID for features in the layer. - - The new attribute is not added to the input layer but a new layer is generated instead. - qgis:addfieldtoattributestable: > This algorithm adds a new attribute to a vector layer. diff --git a/python/plugins/processing/algs/qgis/AutoincrementalField.py b/python/plugins/processing/algs/qgis/AutoincrementalField.py deleted file mode 100644 index 5cf8f7281cf..00000000000 --- a/python/plugins/processing/algs/qgis/AutoincrementalField.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -*************************************************************************** - AutoincrementalField.py - --------------------- - Date : August 2012 - Copyright : (C) 2012 by Victor Olaya - Email : volayaf 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. * -* * -*************************************************************************** -""" - -__author__ = 'Victor Olaya' -__date__ = 'August 2012' -__copyright__ = '(C) 2012, Victor Olaya' - -# This will get replaced with a git SHA1 when you do a git archive - -__revision__ = '$Format:%H$' - -from qgis.PyQt.QtCore import QVariant -from qgis.core import (QgsField) -from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm - - -class AutoincrementalField(QgisFeatureBasedAlgorithm): - - def __init__(self): - super().__init__() - self.current = 0 - - def group(self): - return self.tr('Vector table') - - def name(self): - return 'addautoincrementalfield' - - def displayName(self): - return self.tr('Add autoincremental field') - - def outputName(self): - return self.tr('Incremented') - - def outputFields(self, inputFields): - inputFields.append(QgsField('AUTO', QVariant.Int)) - return inputFields - - def processFeature(self, feature, feedback): - attributes = feature.attributes() - attributes.append(self.current) - self.current += 1 - feature.setAttributes(attributes) - return feature diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py index 657eb6a7a61..8e165d6da9c 100755 --- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py @@ -43,7 +43,6 @@ from .QgisAlgorithm import QgisAlgorithm from .AddTableField import AddTableField from .Aggregate import Aggregate from .Aspect import Aspect -from .AutoincrementalField import AutoincrementalField from .BasicStatistics import BasicStatisticsForField from .Boundary import Boundary from .CheckValidity import CheckValidity @@ -174,7 +173,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider): algs = [AddTableField(), Aggregate(), Aspect(), - AutoincrementalField(), BasicStatisticsForField(), Boundary(), CheckValidity(), diff --git a/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.gml b/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.gml new file mode 100644 index 00000000000..8473f423675 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.gml @@ -0,0 +1,86 @@ + + + + + 0-5 + 83 + + + + + + 1,1 + 1 + 2 + 0 + + + + + 3,3 + 2 + 1 + 1 + + + + + 2,2 + 3 + 0 + 2 + + + + + 5,2 + 4 + 2 + 3 + + + + + 4,1 + 5 + 1 + 4 + + + + + 0,-5 + 6 + 0 + 5 + + + + + 8,-1 + 7 + 0 + 6 + + + + + 7,-1 + 8 + 0 + 7 + + + + + 0,-1 + 9 + 0 + 8 + + + diff --git a/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.xsd b/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.xsd new file mode 100644 index 00000000000..5db0e7e6603 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/autoincrement_field_field_name.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.gml b/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.gml new file mode 100644 index 00000000000..21f75e32e80 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.gml @@ -0,0 +1,86 @@ + + + + + 0-5 + 83 + + + + + + 1,1 + 1 + 2 + 10 + + + + + 3,3 + 2 + 1 + 11 + + + + + 2,2 + 3 + 0 + 12 + + + + + 5,2 + 4 + 2 + 13 + + + + + 4,1 + 5 + 1 + 14 + + + + + 0,-5 + 6 + 0 + 15 + + + + + 8,-1 + 7 + 0 + 16 + + + + + 7,-1 + 8 + 0 + 17 + + + + + 0,-1 + 9 + 0 + 18 + + + diff --git a/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.xsd b/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.xsd new file mode 100644 index 00000000000..e16f3691c60 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/autoincrement_field_start.xsd @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index e2fbd30aa5f..458e47963eb 100755 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -414,7 +414,7 @@ tests: name: expected/unique_values.gml type: vector - - algorithm: qgis:addautoincrementalfield + - algorithm: native:addautoincrementalfield name: Add autoincremental field params: INPUT: @@ -425,6 +425,33 @@ tests: name: expected/autoincrement_field.gml type: vector + - algorithm: native:addautoincrementalfield + name: Add autoincremental field with start value + params: + FIELD_NAME: AUTO + INPUT: + name: points.gml + type: vector + START: 10 + results: + OUTPUT: + name: expected/autoincrement_field_start.gml + type: vector + + - algorithm: native:addautoincrementalfield + name: Add autoincremental field with name + params: + FIELD_NAME: my_field + INPUT: + name: points.gml + type: vector + START: 0 + results: + OUTPUT: + name: expected/autoincrement_field_field_name.gml + type: vector + + - algorithm: native:dissolve name: Dissolve using field params: diff --git a/src/core/processing/qgsnativealgorithms.cpp b/src/core/processing/qgsnativealgorithms.cpp index a479e67e26c..b351b17041e 100644 --- a/src/core/processing/qgsnativealgorithms.cpp +++ b/src/core/processing/qgsnativealgorithms.cpp @@ -93,6 +93,7 @@ void QgsNativeAlgorithms::loadAlgorithms() addAlgorithm( new QgsJoinByAttributeAlgorithm() ); addAlgorithm( new QgsJoinWithLinesAlgorithm() ); addAlgorithm( new QgsAssignProjectionAlgorithm() ); + addAlgorithm( new QgsAddIncrementalFieldAlgorithm() ); } void QgsSaveSelectedFeatures::initAlgorithm( const QVariantMap & ) @@ -698,6 +699,51 @@ QgsFeature QgsAssignProjectionAlgorithm::processFeature( const QgsFeature &featu +QString QgsAddIncrementalFieldAlgorithm::shortHelpString() const +{ + return QObject::tr( "This algorithm adds a new integer field to a vector layer, with a sequential value for each feature.\n\n" + "This field can be used as a unique ID for features in the layer. The new attribute " + "is not added to the input layer but a new layer is generated instead.\n\n" + "The initial starting value for the incremental series can be specified." ); +} + +QgsAddIncrementalFieldAlgorithm *QgsAddIncrementalFieldAlgorithm::createInstance() const +{ + return new QgsAddIncrementalFieldAlgorithm(); +} + +void QgsAddIncrementalFieldAlgorithm::initParameters( const QVariantMap & ) +{ + addParameter( new QgsProcessingParameterString( QStringLiteral( "FIELD_NAME" ), QObject::tr( "Field name" ), QStringLiteral( "AUTO" ) ) ); + addParameter( new QgsProcessingParameterNumber( QStringLiteral( "START" ), QObject::tr( "Start values at" ), + QgsProcessingParameterNumber::Integer, 0, true ) ); +} + +QgsFields QgsAddIncrementalFieldAlgorithm::outputFields( const QgsFields &inputFields ) const +{ + QgsFields outFields = inputFields; + outFields.append( QgsField( mFieldName, QVariant::LongLong ) ); + return outFields; +} + +bool QgsAddIncrementalFieldAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) +{ + mValue = parameterAsInt( parameters, QStringLiteral( "START" ), context ); + mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context ); + return true; +} + +QgsFeature QgsAddIncrementalFieldAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * ) +{ + QgsFeature f = feature; + QgsAttributes attributes = f.attributes(); + attributes.append( mValue ); + mValue++; + f.setAttributes( attributes ); + return f; +} + + void QgsSubdivideAlgorithm::initParameters( const QVariantMap & ) { addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MAX_NODES" ), QObject::tr( "Maximum nodes in parts" ), QgsProcessingParameterNumber::Integer, diff --git a/src/core/processing/qgsnativealgorithms.h b/src/core/processing/qgsnativealgorithms.h index 49106824fca..e4c67b0de62 100644 --- a/src/core/processing/qgsnativealgorithms.h +++ b/src/core/processing/qgsnativealgorithms.h @@ -164,6 +164,39 @@ class QgsAssignProjectionAlgorithm : public QgsProcessingFeatureBasedAlgorithm }; + +/** + * Native add incremental field algorithm. + */ +class QgsAddIncrementalFieldAlgorithm : public QgsProcessingFeatureBasedAlgorithm +{ + + public: + + QgsAddIncrementalFieldAlgorithm() = default; + QString name() const override { return QStringLiteral( "addautoincrementalfield" ); } + QString displayName() const override { return QObject::tr( "Add autoincremental field" ); } + virtual QStringList tags() const override { return QObject::tr( "add,create,serial,primary,key,unique,field" ).split( ',' ); } + QString group() const override { return QObject::tr( "Vector table" ); } + QString shortHelpString() const override; + QgsAddIncrementalFieldAlgorithm *createInstance() const override SIP_FACTORY; + + protected: + + void initParameters( const QVariantMap &configuration = QVariantMap() ) override; + QString outputName() const override { return QObject::tr( "Incremented" ); } + QgsFields outputFields( const QgsFields &inputFields ) const override; + + bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; + QgsFeature processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) override; + + private: + + long long mValue = 0; + QString mFieldName; + +}; + /** * Native buffer algorithm. */