QGIS API Documentation 4.3.0-Master (ffcfc20b9b4)
Loading...
Searching...
No Matches
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
20#include "qgsfeaturerequest.h"
21
22#include <QString>
23
24using namespace Qt::StringLiterals;
25
27
28QString QgsAddIncrementalFieldAlgorithm::name() const
29{
30 return u"addautoincrementalfield"_s;
31}
32
33QString QgsAddIncrementalFieldAlgorithm::displayName() const
34{
35 return QObject::tr( "Add autoincremental field" );
36}
37
38QString QgsAddIncrementalFieldAlgorithm::shortHelpString() const
39{
40 return QObject::tr(
41 "This algorithm adds a new integer field to a vector layer, with a sequential value for each feature.\n\n"
42 "This field can be used as a unique ID for features in the layer. The new attribute "
43 "is not added to the input layer but a new layer is generated instead.\n\n"
44 "The initial starting value for the incremental series can be specified.\n\n"
45 "Specifying an optional modulus value will restart the count to START whenever the field value reaches the modulus value.\n\n"
46 "Optionally, grouping fields can be specified. If group fields are present, then the field value will "
47 "be reset for each combination of these group field values.\n\n"
48 "The sort order for features may be specified, if so, then the incremental field will respect "
49 "this sort order."
50 );
51}
52
53QString QgsAddIncrementalFieldAlgorithm::shortDescription() const
54{
55 return QObject::tr(
56 "Adds a new integer field to a vector layer, with a sequential value for each feature, "
57 "usable as a unique ID for features in the layer."
58 );
59}
60
61QStringList QgsAddIncrementalFieldAlgorithm::tags() const
62{
63 return QObject::tr( "add,create,serial,primary,key,unique,fields" ).split( ',' );
64}
65
66QString QgsAddIncrementalFieldAlgorithm::group() const
67{
68 return QObject::tr( "Vector table" );
69}
70
71QString QgsAddIncrementalFieldAlgorithm::groupId() const
72{
73 return u"vectortable"_s;
74}
75
76QString QgsAddIncrementalFieldAlgorithm::outputName() const
77{
78 return QObject::tr( "Incremented" );
79}
80
81QList<int> QgsAddIncrementalFieldAlgorithm::inputLayerTypes() const
82{
83 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector );
84}
85
86QgsAddIncrementalFieldAlgorithm *QgsAddIncrementalFieldAlgorithm::createInstance() const
87{
88 return new QgsAddIncrementalFieldAlgorithm();
89}
90
91Qgis::ProcessingFeatureSourceFlags QgsAddIncrementalFieldAlgorithm::sourceFlags() const
92{
94}
95
96void QgsAddIncrementalFieldAlgorithm::initParameters( const QVariantMap & )
97{
98 addParameter( new QgsProcessingParameterString( u"FIELD_NAME"_s, QObject::tr( "Field name" ), u"AUTO"_s ) );
99 addParameter( new QgsProcessingParameterNumber( u"START"_s, QObject::tr( "Start values at" ), Qgis::ProcessingNumberParameterType::Integer, 0, true ) );
100 addParameter( new QgsProcessingParameterNumber( u"MODULUS"_s, QObject::tr( "Modulus value" ), Qgis::ProcessingNumberParameterType::Integer, QVariant( 0 ), true ) );
101 addParameter( new QgsProcessingParameterField( u"GROUP_FIELDS"_s, QObject::tr( "Group values by" ), QVariant(), u"INPUT"_s, Qgis::ProcessingFieldParameterDataType::Any, true, true ) );
102
103 // sort params
104 auto sortExp = std::make_unique<QgsProcessingParameterExpression>( u"SORT_EXPRESSION"_s, QObject::tr( "Sort expression" ), QVariant(), u"INPUT"_s, true );
105 sortExp->setFlags( sortExp->flags() | Qgis::ProcessingParameterFlag::Advanced );
106 addParameter( sortExp.release() );
107 auto sortAscending = std::make_unique<QgsProcessingParameterBoolean>( u"SORT_ASCENDING"_s, QObject::tr( "Sort ascending" ), true );
108 sortAscending->setFlags( sortAscending->flags() | Qgis::ProcessingParameterFlag::Advanced );
109 addParameter( sortAscending.release() );
110 auto sortNullsFirst = std::make_unique<QgsProcessingParameterBoolean>( u"SORT_NULLS_FIRST"_s, QObject::tr( "Sort nulls first" ), false );
111 sortNullsFirst->setFlags( sortNullsFirst->flags() | Qgis::ProcessingParameterFlag::Advanced );
112 addParameter( sortNullsFirst.release() );
113}
114
115QgsFields QgsAddIncrementalFieldAlgorithm::outputFields( const QgsFields &inputFields ) const
116{
117 QgsFields outFields = inputFields;
118 outFields.append( QgsField( mFieldName, QMetaType::Type::LongLong ) );
119 mFields = outFields;
120 return outFields;
121}
122
123bool QgsAddIncrementalFieldAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
124{
125 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
126 mStartValue = parameterAsInt( parameters, u"START"_s, context );
127 mValue = mStartValue;
128 mModulusValue = parameterAsInt( parameters, u"MODULUS"_s, context );
129 mFieldName = parameterAsString( parameters, u"FIELD_NAME"_s, context );
130 mGroupedFieldNames = parameterAsStrings( parameters, u"GROUP_FIELDS"_s, context );
131
132 mSortExpressionString = parameterAsExpression( parameters, u"SORT_EXPRESSION"_s, context );
133 mSortAscending = parameterAsBoolean( parameters, u"SORT_ASCENDING"_s, context );
134 mSortNullsFirst = parameterAsBoolean( parameters, u"SORT_NULLS_FIRST"_s, context );
135
136 if ( source->fields().lookupField( mFieldName ) >= 0 )
137 {
138 throw QgsProcessingException( QObject::tr( "A field with the same name (%1) already exists" ).arg( mFieldName ) );
139 }
140
141 return true;
142}
143
144QgsFeatureRequest QgsAddIncrementalFieldAlgorithm::request() const
145{
146 if ( mSortExpressionString.isEmpty() )
147 return QgsFeatureRequest();
148
149 return QgsFeatureRequest().setOrderBy( QgsFeatureRequest::OrderBy() << QgsFeatureRequest::OrderByClause( mSortExpressionString, mSortAscending, mSortNullsFirst ) );
150}
151
152QgsFeatureList QgsAddIncrementalFieldAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
153{
154 QGS_MARK_ALGORITHM_SOURCE
155
156 if ( !mGroupedFieldNames.empty() && mGroupedFields.empty() )
157 {
158 for ( const QString &field : std::as_const( mGroupedFieldNames ) )
159 {
160 int idx = mFields.lookupField( field );
161 if ( idx >= 0 )
162 mGroupedFields << idx;
163 }
164 }
165
166 QgsFeature f = feature;
167 QgsAttributes attributes = f.attributes();
168 if ( mGroupedFields.empty() )
169 {
170 attributes.append( mValue );
171 mValue++;
172 if ( mModulusValue != 0 && ( mValue % mModulusValue ) == 0 )
173 mValue = mStartValue;
174 }
175 else
176 {
177 QgsAttributes groupAttributes;
178 groupAttributes.reserve( mGroupedFields.size() );
179 for ( int index : std::as_const( mGroupedFields ) )
180 {
181 groupAttributes << f.attribute( index );
182 }
183 long long value = mGroupedValues.value( groupAttributes, mStartValue );
184 attributes.append( value );
185 value++;
186 if ( mModulusValue != 0 && ( value % mModulusValue ) == 0 )
187 value = mStartValue;
188 mGroupedValues[groupAttributes] = value;
189 }
190 f.setAttributes( attributes );
191 return QgsFeatureList() << f;
192}
193
194bool QgsAddIncrementalFieldAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
195{
196 Q_UNUSED( layer )
197 return false;
198}
199
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition qgis.h:3755
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3930
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
Definition qgis.h:3982
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3941
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:60
QgsAttributes attributes
Definition qgsfeature.h:64
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:56
Container of fields for a vector layer.
Definition qgsfields.h:45
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:75
Base class for all map layer types.
Definition qgsmaplayer.h:83
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