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