QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
44QStringList QgsRefactorFieldsAlgorithm::tags() const
45{
46 return QObject::tr( "attributes,table" ).split( ',' );
47}
48
49QString QgsRefactorFieldsAlgorithm::group() const
50{
51 return QObject::tr( "Vector table" );
52}
53
54QString QgsRefactorFieldsAlgorithm::groupId() const
55{
56 return QStringLiteral( "vectortable" );
57}
58
59QString QgsRefactorFieldsAlgorithm::outputName() const
60{
61 return QObject::tr( "Refactored" );
62}
63
64QList<int> QgsRefactorFieldsAlgorithm::inputLayerTypes() const
65{
66 return QList<int>() << static_cast< int >( Qgis::ProcessingSourceType::Vector );
67}
68
69Qgis::ProcessingFeatureSourceFlags QgsRefactorFieldsAlgorithm::sourceFlags() const
70{
72}
73
74QgsRefactorFieldsAlgorithm *QgsRefactorFieldsAlgorithm::createInstance() const
75{
76 return new QgsRefactorFieldsAlgorithm();
77}
78
79void QgsRefactorFieldsAlgorithm::initParameters( const QVariantMap & )
80{
81 std::unique_ptr< QgsProcessingParameterFieldMapping > param = std::make_unique< QgsProcessingParameterFieldMapping> ( QStringLiteral( "FIELDS_MAPPING" ), QObject::tr( "Fields mapping" ), QStringLiteral( "INPUT" ) );
82 addParameter( param.release() );
83}
84
85QgsFields QgsRefactorFieldsAlgorithm::outputFields( const QgsFields & ) const
86{
87 return mFields;
88}
89
90bool QgsRefactorFieldsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
91{
92 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
93 if ( !source )
94 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
95
96 mDa.setSourceCrs( source->sourceCrs(), context.transformContext() );
97 mDa.setEllipsoid( context.ellipsoid() );
98
99 mExpressionContext = createExpressionContext( parameters, context, source.get() );
100
101 const QVariantList mapping = parameters.value( QStringLiteral( "FIELDS_MAPPING" ) ).toList();
102 for ( const QVariant &map : mapping )
103 {
104 const QVariantMap fieldDef = map.toMap();
105 const QString name = fieldDef.value( QStringLiteral( "name" ) ).toString();
106 if ( name.isEmpty() )
107 throw QgsProcessingException( QObject::tr( "Field name cannot be empty" ) );
108
109 const QVariant::Type type = static_cast< QVariant::Type >( fieldDef.value( QStringLiteral( "type" ) ).toInt() );
110 const QString typeName = fieldDef.value( QStringLiteral( "sub_name" ) ).toString();
111 const QVariant::Type subType = static_cast< QVariant::Type >( fieldDef.value( QStringLiteral( "sub_type" ) ).toInt() );
112
113 const int length = fieldDef.value( QStringLiteral( "length" ), 0 ).toInt();
114 const int precision = fieldDef.value( QStringLiteral( "precision" ), 0 ).toInt();
115
116 const QString alias = fieldDef.value( QStringLiteral( "alias" ) ).toString();
117 const QString comment = fieldDef.value( QStringLiteral( "comment" ) ).toString();
118
119 QgsField newField( name, type, typeName, length, precision, QString(), subType );
120 newField.setAlias( alias );
121 newField.setComment( comment );
122 mFields.append( newField );
123
124 const QString expressionString = fieldDef.value( QStringLiteral( "expression" ) ).toString();
125 if ( !expressionString.isEmpty() )
126 {
127 QgsExpression expression( expressionString );
128 expression.setGeomCalculator( &mDa );
129 expression.setDistanceUnits( context.distanceUnit() );
130 expression.setAreaUnits( context.areaUnit() );
131 if ( expression.hasParserError() )
132 {
133 throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
134 .arg(
135 name,
136 expressionString,
137 expression.parserErrorString() ) );
138 }
139 mExpressions.append( expression );
140 }
141 else
142 {
143 mExpressions.append( QgsExpression() );
144 }
145 }
146
147 return true;
148}
149
150QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
151{
152 if ( !mExpressionsPrepared )
153 {
154 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
155 {
156 if ( it->isValid() )
157 it->prepare( &mExpressionContext );
158 }
159 }
160
161 QgsAttributes attributes;
162 attributes.reserve( mExpressions.size() );
163 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
164 {
165 if ( it->isValid() )
166 {
167 mExpressionContext.setFeature( feature );
168 mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
169 const QVariant value = it->evaluate( &mExpressionContext );
170 if ( it->hasEvalError() )
171 {
172 throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
173 }
174 attributes.append( value );
175 }
176 else
177 {
178 attributes.append( QVariant() );
179 }
180 }
181
182 QgsFeature f = feature;
183 f.setAttributes( attributes );
184 mRowNumber++;
185 return QgsFeatureList() << f;
186}
187
188bool QgsRefactorFieldsAlgorithm::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...
@ 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:3011
A vector of attributes.
Definition: qgsattributes.h:59
Class for 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:56
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
Container of fields for a vector layer.
Definition: qgsfields.h:45
Base class for all map layer types.
Definition: qgsmaplayer.h:75
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.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917
const QString & typeName
int precision