QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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 = std::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 
A vector of attributes.
Definition: qgsattributes.h:58
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:153
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
Base class for all map layer types.
Definition: qgsmaplayer.h:73
Contains information about the context in which a processing algorithm is executed.
QgsUnitTypes::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
QgsUnitTypes::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
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Base class for providing feedback from a processing algorithm.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
Definition: qgsprocessing.h:54
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
int precision