QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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.project()->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  if ( context.project() )
122  {
123  expression.setDistanceUnits( context.project()->distanceUnits() );
124  expression.setAreaUnits( context.project()->areaUnits() );
125  }
126  if ( expression.hasParserError() )
127  {
128  throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
129  .arg(
130  name,
131  expressionString,
132  expression.parserErrorString() ) );
133  }
134  mExpressions.append( expression );
135  }
136  else
137  {
138  mExpressions.append( QgsExpression() );
139  }
140  }
141 
142  return true;
143 }
144 
145 QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
146 {
147  if ( !mExpressionsPrepared )
148  {
149  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
150  {
151  if ( it->isValid() )
152  it->prepare( &mExpressionContext );
153  }
154  }
155 
156  QgsAttributes attributes;
157  attributes.reserve( mExpressions.size() );
158  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
159  {
160  if ( it->isValid() )
161  {
162  mExpressionContext.setFeature( feature );
163  mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
164  const QVariant value = it->evaluate( &mExpressionContext );
165  if ( it->hasEvalError() )
166  {
167  throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
168  }
169  attributes.append( value );
170  }
171  else
172  {
173  attributes.append( QVariant() );
174  }
175  }
176 
177  QgsFeature f = feature;
178  f.setAttributes( attributes );
179  mRowNumber++;
180  return QgsFeatureList() << f;
181 }
182 
183 bool QgsRefactorFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
184 {
185  Q_UNUSED( layer )
186  return false;
187 }
188 
qgsprocessingparameterfieldmap.h
qgsalgorithmrefactorfields.h
QgsProcessingContext::project
QgsProject * project() const
Returns the project in which the algorithm is being executed.
Definition: qgsprocessingcontext.h:99
QgsProcessingFeedback
Definition: qgsprocessingfeedback.h:37
QgsProject::distanceUnits
QgsUnitTypes::DistanceUnit distanceUnits() const
Convenience function to query default distance measurement units for project.
Definition: qgsproject.cpp:2879
QgsFields
Definition: qgsfields.h:44
QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition: qgsprocessingutils.h:475
QgsProject::areaUnits
QgsUnitTypes::AreaUnit areaUnits() const
Convenience function to query default area measurement units for project.
Definition: qgsproject.cpp:2897
precision
int precision
Definition: qgswfsgetfeature.cpp:103
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
Definition: qgsprocessingcontext.h:43
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:572
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:135
QgsProcessingFeatureSource::Flag
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
Definition: qgsprocessingutils.h:473
QgsMapLayer
Definition: qgsmaplayer.h:81
QgsAttributes
Definition: qgsattributes.h:57
QgsFeature
Definition: qgsfeature.h:55
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:127
QgsExpression
Definition: qgsexpression.h:113
QgsProject::ellipsoid
QString ellipsoid
Definition: qgsproject.h:100
QgsProcessingException
Definition: qgsexception.h:82
QgsField
Definition: qgsfield.h:49