QGIS API Documentation 3.43.0-Master (e01d6d7c4c0)
qgsalgorithmaddincrementalfield.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmaddincrementalfield.cpp
3 -----------------------------------
4 begin : April 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "qgsfeaturerequest.h"
20
22
23QString QgsAddIncrementalFieldAlgorithm::name() const
24{
25 return QStringLiteral( "addautoincrementalfield" );
26}
27
28QString QgsAddIncrementalFieldAlgorithm::displayName() const
29{
30 return QObject::tr( "Add autoincremental field" );
31}
32
33QString QgsAddIncrementalFieldAlgorithm::shortHelpString() const
34{
35 return QObject::tr( "This algorithm adds a new integer field to a vector layer, with a sequential value for each feature.\n\n"
36 "This field can be used as a unique ID for features in the layer. The new attribute "
37 "is not added to the input layer but a new layer is generated instead.\n\n"
38 "The initial starting value for the incremental series can be specified.\n\n"
39 "Specifying an optional modulus value will restart the count to START whenever the field value reaches the modulus value.\n\n"
40 "Optionally, grouping fields can be specified. If group fields are present, then the field value will "
41 "be reset for each combination of these group field values.\n\n"
42 "The sort order for features may be specified, if so, then the incremental field will respect "
43 "this sort order." );
44}
45
46QString QgsAddIncrementalFieldAlgorithm::shortDescription() const
47{
48 return QObject::tr( "Adds a new integer field to a vector layer, with a sequential value for each feature, "
49 "usable as a unique ID for features in the layer." );
50}
51
52QStringList QgsAddIncrementalFieldAlgorithm::tags() const
53{
54 return QObject::tr( "add,create,serial,primary,key,unique,fields" ).split( ',' );
55}
56
57QString QgsAddIncrementalFieldAlgorithm::group() const
58{
59 return QObject::tr( "Vector table" );
60}
61
62QString QgsAddIncrementalFieldAlgorithm::groupId() const
63{
64 return QStringLiteral( "vectortable" );
65}
66
67QString QgsAddIncrementalFieldAlgorithm::outputName() const
68{
69 return QObject::tr( "Incremented" );
70}
71
72QList<int> QgsAddIncrementalFieldAlgorithm::inputLayerTypes() const
73{
74 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector );
75}
76
77QgsAddIncrementalFieldAlgorithm *QgsAddIncrementalFieldAlgorithm::createInstance() const
78{
79 return new QgsAddIncrementalFieldAlgorithm();
80}
81
82Qgis::ProcessingFeatureSourceFlags QgsAddIncrementalFieldAlgorithm::sourceFlags() const
83{
85}
86
87void QgsAddIncrementalFieldAlgorithm::initParameters( const QVariantMap & )
88{
89 addParameter( new QgsProcessingParameterString( QStringLiteral( "FIELD_NAME" ), QObject::tr( "Field name" ), QStringLiteral( "AUTO" ) ) );
90 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "START" ), QObject::tr( "Start values at" ), Qgis::ProcessingNumberParameterType::Integer, 0, true ) );
91 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MODULUS" ), QObject::tr( "Modulus value" ), Qgis::ProcessingNumberParameterType::Integer, QVariant( 0 ), true ) );
92 addParameter( new QgsProcessingParameterField( QStringLiteral( "GROUP_FIELDS" ), QObject::tr( "Group values by" ), QVariant(), QStringLiteral( "INPUT" ), Qgis::ProcessingFieldParameterDataType::Any, true, true ) );
93
94 // sort params
95 auto sortExp = std::make_unique<QgsProcessingParameterExpression>( QStringLiteral( "SORT_EXPRESSION" ), QObject::tr( "Sort expression" ), QVariant(), QStringLiteral( "INPUT" ), true );
96 sortExp->setFlags( sortExp->flags() | Qgis::ProcessingParameterFlag::Advanced );
97 addParameter( sortExp.release() );
98 auto sortAscending = std::make_unique<QgsProcessingParameterBoolean>( QStringLiteral( "SORT_ASCENDING" ), QObject::tr( "Sort ascending" ), true );
99 sortAscending->setFlags( sortAscending->flags() | Qgis::ProcessingParameterFlag::Advanced );
100 addParameter( sortAscending.release() );
101 auto sortNullsFirst = std::make_unique<QgsProcessingParameterBoolean>( QStringLiteral( "SORT_NULLS_FIRST" ), QObject::tr( "Sort nulls first" ), false );
102 sortNullsFirst->setFlags( sortNullsFirst->flags() | Qgis::ProcessingParameterFlag::Advanced );
103 addParameter( sortNullsFirst.release() );
104}
105
106QgsFields QgsAddIncrementalFieldAlgorithm::outputFields( const QgsFields &inputFields ) const
107{
108 QgsFields outFields = inputFields;
109 outFields.append( QgsField( mFieldName, QMetaType::Type::LongLong ) );
110 mFields = outFields;
111 return outFields;
112}
113
114bool QgsAddIncrementalFieldAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
115{
116 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
117 mStartValue = parameterAsInt( parameters, QStringLiteral( "START" ), context );
118 mValue = mStartValue;
119 mModulusValue = parameterAsInt( parameters, QStringLiteral( "MODULUS" ), context );
120 mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context );
121 mGroupedFieldNames = parameterAsStrings( parameters, QStringLiteral( "GROUP_FIELDS" ), context );
122
123 mSortExpressionString = parameterAsExpression( parameters, QStringLiteral( "SORT_EXPRESSION" ), context );
124 mSortAscending = parameterAsBoolean( parameters, QStringLiteral( "SORT_ASCENDING" ), context );
125 mSortNullsFirst = parameterAsBoolean( parameters, QStringLiteral( "SORT_NULLS_FIRST" ), context );
126
127 if ( source->fields().lookupField( mFieldName ) >= 0 )
128 {
129 throw QgsProcessingException( QObject::tr( "A field with the same name (%1) already exists" ).arg( mFieldName ) );
130 }
131
132 return true;
133}
134
135QgsFeatureRequest QgsAddIncrementalFieldAlgorithm::request() const
136{
137 if ( mSortExpressionString.isEmpty() )
138 return QgsFeatureRequest();
139
140 return QgsFeatureRequest().setOrderBy( QgsFeatureRequest::OrderBy() << QgsFeatureRequest::OrderByClause( mSortExpressionString, mSortAscending, mSortNullsFirst ) );
141}
142
143QgsFeatureList QgsAddIncrementalFieldAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
144{
145 if ( !mGroupedFieldNames.empty() && mGroupedFields.empty() )
146 {
147 for ( const QString &field : std::as_const( mGroupedFieldNames ) )
148 {
149 int idx = mFields.lookupField( field );
150 if ( idx >= 0 )
151 mGroupedFields << idx;
152 }
153 }
154
155 QgsFeature f = feature;
156 QgsAttributes attributes = f.attributes();
157 if ( mGroupedFields.empty() )
158 {
159 attributes.append( mValue );
160 mValue++;
161 if ( mModulusValue != 0 && ( mValue % mModulusValue ) == 0 )
162 mValue = mStartValue;
163 }
164 else
165 {
166 QgsAttributes groupAttributes;
167 groupAttributes.reserve( mGroupedFields.size() );
168 for ( int index : std::as_const( mGroupedFields ) )
169 {
170 groupAttributes << f.attribute( index );
171 }
172 long long value = mGroupedValues.value( groupAttributes, mStartValue );
173 attributes.append( value );
174 value++;
175 if ( mModulusValue != 0 && ( value % mModulusValue ) == 0 )
176 value = mStartValue;
177 mGroupedValues[groupAttributes] = value;
178 }
179 f.setAttributes( attributes );
180 return QgsFeatureList() << f;
181}
182
183bool QgsAddIncrementalFieldAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
184{
185 Q_UNUSED( layer )
186 return false;
187}
188
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3588
A vector of attributes.
The OrderByClause class represents an order by clause for a QgsFeatureRequest.
Represents a list of OrderByClauses, with the most important first and the least important last.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setOrderBy(const OrderBy &orderBy)
Set a list of order by clauses.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsAttributes attributes
Definition qgsfeature.h:67
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:70
Base class for all map layer types.
Definition qgsmaplayer.h:77
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A vector layer or feature source field parameter for processing algorithms.
A numeric parameter for processing algorithms.
A string parameter for processing algorithms.
QList< QgsFeature > QgsFeatureList