QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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 QMetaType::Type type = static_cast<QMetaType::Type>( fieldDef.value( QStringLiteral( "type" ) ).toInt() );
110 const QString typeName = fieldDef.value( QStringLiteral( "sub_name" ) ).toString();
111 const QMetaType::Type subType = static_cast<QMetaType::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 }
140 mExpressions.append( expression );
141 }
142 else
143 {
144 mExpressions.append( QgsExpression() );
145 }
146 }
147
148 return true;
149}
150
151QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
152{
153 if ( !mExpressionsPrepared )
154 {
155 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
156 {
157 if ( it->isValid() )
158 it->prepare( &mExpressionContext );
159 }
160 }
161
162 QgsAttributes attributes;
163 attributes.reserve( mExpressions.size() );
164 for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
165 {
166 if ( it->isValid() )
167 {
168 mExpressionContext.setFeature( feature );
169 mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
170 const QVariant value = it->evaluate( &mExpressionContext );
171 if ( it->hasEvalError() )
172 {
173 throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
174 }
175 attributes.append( value );
176 }
177 else
178 {
179 attributes.append( QVariant() );
180 }
181 }
182
183 QgsFeature f = feature;
184 f.setAttributes( attributes );
185 mRowNumber++;
186 return QgsFeatureList() << f;
187}
188
189bool QgsRefactorFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
190{
191 Q_UNUSED( layer )
192 return false;
193}
194
@ 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:3507
A vector of attributes.
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: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:76
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