QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
23 QString QgsRefactorFieldsAlgorithm::name() const
24 {
25  return QStringLiteral( "refactorfields" );
26 }
27 
28 QString QgsRefactorFieldsAlgorithm::displayName() const
29 {
30  return QObject::tr( "Refactor fields" );
31 }
32 
33 QString 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 
44 QStringList QgsRefactorFieldsAlgorithm::tags() const
45 {
46  return QObject::tr( "attributes,table" ).split( ',' );
47 }
48 
49 QString QgsRefactorFieldsAlgorithm::group() const
50 {
51  return QObject::tr( "Vector table" );
52 }
53 
54 QString QgsRefactorFieldsAlgorithm::groupId() const
55 {
56  return QStringLiteral( "vectortable" );
57 }
58 
59 QString QgsRefactorFieldsAlgorithm::outputName() const
60 {
61  return QObject::tr( "Refactored" );
62 }
63 
64 QList<int> QgsRefactorFieldsAlgorithm::inputLayerTypes() const
65 {
66  return QList<int>() << QgsProcessing::TypeVector;
67 }
68 
69 QgsProcessingFeatureSource::Flag QgsRefactorFieldsAlgorithm::sourceFlags() const
70 {
72 }
73 
74 QgsRefactorFieldsAlgorithm *QgsRefactorFieldsAlgorithm::createInstance() const
75 {
76  return new QgsRefactorFieldsAlgorithm();
77 }
78 
79 void QgsRefactorFieldsAlgorithm::initParameters( const QVariantMap & )
80 {
81  std::unique_ptr< QgsProcessingParameterFieldMapping > param = qgis::make_unique< QgsProcessingParameterFieldMapping> ( QStringLiteral( "FIELDS_MAPPING" ), QObject::tr( "Fields mapping" ), QStringLiteral( "INPUT" ) );
82  addParameter( param.release() );
83 }
84 
85 QgsFields QgsRefactorFieldsAlgorithm::outputFields( const QgsFields & ) const
86 {
87  return mFields;
88 }
89 
90 bool 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 
111  const int length = fieldDef.value( QStringLiteral( "length" ), 0 ).toInt();
112  const int precision = fieldDef.value( QStringLiteral( "precision" ), 0 ).toInt();
113 
114  mFields.append( QgsField( name, type, QString(), length, precision ) );
115 
116  const QString expressionString = fieldDef.value( QStringLiteral( "expression" ) ).toString();
117  if ( !expressionString.isEmpty() )
118  {
119  QgsExpression expression( expressionString );
120  expression.setGeomCalculator( &mDa );
121  expression.setDistanceUnits( context.distanceUnit() );
122  expression.setAreaUnits( context.areaUnit() );
123  if ( expression.hasParserError() )
124  {
125  throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
126  .arg(
127  name,
128  expressionString,
129  expression.parserErrorString() ) );
130  }
131  mExpressions.append( expression );
132  }
133  else
134  {
135  mExpressions.append( QgsExpression() );
136  }
137  }
138 
139  return true;
140 }
141 
142 QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
143 {
144  if ( !mExpressionsPrepared )
145  {
146  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
147  {
148  if ( it->isValid() )
149  it->prepare( &mExpressionContext );
150  }
151  }
152 
153  QgsAttributes attributes;
154  attributes.reserve( mExpressions.size() );
155  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
156  {
157  if ( it->isValid() )
158  {
159  mExpressionContext.setFeature( feature );
160  mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
161  const QVariant value = it->evaluate( &mExpressionContext );
162  if ( it->hasEvalError() )
163  {
164  throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
165  }
166  attributes.append( value );
167  }
168  else
169  {
170  attributes.append( QVariant() );
171  }
172  }
173 
174  QgsFeature f = feature;
175  f.setAttributes( attributes );
176  mRowNumber++;
177  return QgsFeatureList() << f;
178 }
179 
180 bool QgsRefactorFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
181 {
182  Q_UNUSED( layer )
183  return false;
184 }
185 
qgsprocessingparameterfieldmap.h
qgsalgorithmrefactorfields.h
QgsProcessingContext::distanceUnit
QgsUnitTypes::DistanceUnit distanceUnit() const
Returns the distance unit to use for distance calculations.
Definition: qgsprocessingcontext.cpp:141
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:38
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:45
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:477
precision
int precision
Definition: qgswfsgetfeature.cpp:49
QgsProcessing::TypeVector
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:53
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:44
QgsProcessingContext::ellipsoid
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Definition: qgsprocessingcontext.cpp:131
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:583
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:149
QgsProcessingFeatureSource::Flag
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
Definition: qgsprocessingutils.h:476
QgsProcessingContext::areaUnit
QgsUnitTypes::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
Definition: qgsprocessingcontext.cpp:151
QgsMapLayer
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsAttributes
A vector of attributes.
Definition: qgsattributes.h:58
QgsFeature
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:129
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings").
Definition: qgsexpression.h:105
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50