QGIS API Documentation 3.43.0-Master (261ee7da134)
qgsalgorithmrefactorfields.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmrefactorfields.h
3 ---------------------------------
4 begin : June 2020
5 copyright : (C) 2020 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
20
22
23QString QgsRefactorFieldsAlgorithm::name() const
24{
25 return QStringLiteral( "refactorfields" );
26}
27
28QString QgsRefactorFieldsAlgorithm::displayName() const
29{
30 return QObject::tr( "Refactor fields" );
31}
32
33QString QgsRefactorFieldsAlgorithm::shortHelpString() const
34{
35 return QObject::tr( "This algorithm allows editing the structure of the attributes table of a vector layer. Fields can be modified "
36 "in their type and name, using a fields mapping.\n\n"
37 "The original layer is not modified. A new layer is generated, which contains a modified attribute table, according "
38 "to the provided fields mapping.\n\n"
39 "Rows in orange have constraints in the template layer from which these fields were loaded. Treat this information "
40 "as a hint during configuration. No constraints will be added on an output layer nor will they be checked or "
41 "enforced by the algorithm." );
42}
43
44QString QgsRefactorFieldsAlgorithm::shortDescription() const
45{
46 return QObject::tr( "Allows editing the structure of the attributes table of a vector layer, permitting field renaming, creation and deletion." );
47}
48
49QStringList QgsRefactorFieldsAlgorithm::tags() const
50{
51 return QObject::tr( "attributes,table" ).split( ',' );
52}
53
54QString QgsRefactorFieldsAlgorithm::group() const
55{
56 return QObject::tr( "Vector table" );
57}
58
59QString QgsRefactorFieldsAlgorithm::groupId() const
60{
61 return QStringLiteral( "vectortable" );
62}
63
64QString QgsRefactorFieldsAlgorithm::outputName() const
65{
66 return QObject::tr( "Refactored" );
67}
68
69QList<int> QgsRefactorFieldsAlgorithm::inputLayerTypes() const
70{
71 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::Vector );
72}
73
74Qgis::ProcessingFeatureSourceFlags QgsRefactorFieldsAlgorithm::sourceFlags() const
75{
77}
78
79QgsRefactorFieldsAlgorithm *QgsRefactorFieldsAlgorithm::createInstance() const
80{
81 return new QgsRefactorFieldsAlgorithm();
82}
83
84void QgsRefactorFieldsAlgorithm::initParameters( const QVariantMap & )
85{
86 auto param = std::make_unique<QgsProcessingParameterFieldMapping>( QStringLiteral( "FIELDS_MAPPING" ), QObject::tr( "Fields mapping" ), QStringLiteral( "INPUT" ) );
87 addParameter( param.release() );
88}
89
90QgsFields QgsRefactorFieldsAlgorithm::outputFields( const QgsFields & ) const
91{
92 return mFields;
93}
94
95bool QgsRefactorFieldsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
96{
97 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
98 if ( !source )
99 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
100
101 mDa.setSourceCrs( source->sourceCrs(), context.transformContext() );
102 mDa.setEllipsoid( context.ellipsoid() );
103
104 mExpressionContext = createExpressionContext( parameters, context, source.get() );
105
106 const QVariantList mapping = parameters.value( QStringLiteral( "FIELDS_MAPPING" ) ).toList();
107 for ( const QVariant &map : mapping )
108 {
109 const QVariantMap fieldDef = map.toMap();
110 const QString name = fieldDef.value( QStringLiteral( "name" ) ).toString();
111 if ( name.isEmpty() )
112 throw QgsProcessingException( QObject::tr( "Field name cannot be empty" ) );
113
114 const QMetaType::Type type = static_cast<QMetaType::Type>( fieldDef.value( QStringLiteral( "type" ) ).toInt() );
115 const QString typeName = fieldDef.value( QStringLiteral( "sub_name" ) ).toString();
116 const QMetaType::Type subType = static_cast<QMetaType::Type>( fieldDef.value( QStringLiteral( "sub_type" ) ).toInt() );
117
118 const int length = fieldDef.value( QStringLiteral( "length" ), 0 ).toInt();
119 const int precision = fieldDef.value( QStringLiteral( "precision" ), 0 ).toInt();
120
121 const QString alias = fieldDef.value( QStringLiteral( "alias" ) ).toString();
122 const QString comment = fieldDef.value( QStringLiteral( "comment" ) ).toString();
123
124 QgsField newField( name, type, typeName, length, precision, QString(), subType );
125 newField.setAlias( alias );
126 newField.setComment( comment );
127 mFields.append( newField );
128
129 const QString expressionString = fieldDef.value( QStringLiteral( "expression" ) ).toString();
130 if ( !expressionString.isEmpty() )
131 {
132 QgsExpression expression( expressionString );
133 expression.setGeomCalculator( &mDa );
134 expression.setDistanceUnits( context.distanceUnit() );
135 expression.setAreaUnits( context.areaUnit() );
136 if ( expression.hasParserError() )
137 {
138 throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
139 .arg(
140 name,
141 expressionString,
142 expression.parserErrorString()
143 ) );
144 }
145 mExpressions.append( expression );
146 }
147 else
148 {
149 mExpressions.append( QgsExpression() );
150 }
151 }
152
153 return true;
154}
155
156QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
157{
158 if ( !mExpressionsPrepared )
159 {
160 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
161 {
162 if ( it->isValid() )
163 it->prepare( &mExpressionContext );
164 }
165 }
166
167 QgsAttributes attributes;
168 attributes.reserve( mExpressions.size() );
169 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
170 {
171 if ( it->isValid() )
172 {
173 mExpressionContext.setFeature( feature );
174 mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
175 const QVariant value = it->evaluate( &mExpressionContext );
176 if ( it->hasEvalError() )
177 {
178 throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
179 }
180 attributes.append( value );
181 }
182 else
183 {
184 attributes.append( QVariant() );
185 }
186 }
187
188 QgsFeature f = feature;
189 f.setAttributes( attributes );
190 mRowNumber++;
191 return QgsFeatureList() << f;
192}
193
194bool QgsRefactorFieldsAlgorithm::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...
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3588
A vector of attributes.
Handles parsing and evaluation of expressions (formerly called "search strings").
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
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
Base class for all map layer types.
Definition qgsmaplayer.h:77
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Qgis::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
Qgis::DistanceUnit distanceUnit() const
Returns the distance unit to use for distance calculations.
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
QList< QgsFeature > QgsFeatureList
const QString & typeName
int precision