QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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  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  mFields.append( QgsField( name, type, typeName, length, precision, QString(), subType ) );
117 
118  const QString expressionString = fieldDef.value( QStringLiteral( "expression" ) ).toString();
119  if ( !expressionString.isEmpty() )
120  {
121  QgsExpression expression( expressionString );
122  expression.setGeomCalculator( &mDa );
123  expression.setDistanceUnits( context.distanceUnit() );
124  expression.setAreaUnits( context.areaUnit() );
125  if ( expression.hasParserError() )
126  {
127  throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
128  .arg(
129  name,
130  expressionString,
131  expression.parserErrorString() ) );
132  }
133  mExpressions.append( expression );
134  }
135  else
136  {
137  mExpressions.append( QgsExpression() );
138  }
139  }
140 
141  return true;
142 }
143 
144 QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
145 {
146  if ( !mExpressionsPrepared )
147  {
148  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
149  {
150  if ( it->isValid() )
151  it->prepare( &mExpressionContext );
152  }
153  }
154 
155  QgsAttributes attributes;
156  attributes.reserve( mExpressions.size() );
157  for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
158  {
159  if ( it->isValid() )
160  {
161  mExpressionContext.setFeature( feature );
162  mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
163  const QVariant value = it->evaluate( &mExpressionContext );
164  if ( it->hasEvalError() )
165  {
166  throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
167  }
168  attributes.append( value );
169  }
170  else
171  {
172  attributes.append( QVariant() );
173  }
174  }
175 
176  QgsFeature f = feature;
177  f.setAttributes( attributes );
178  mRowNumber++;
179  return QgsFeatureList() << f;
180 }
181 
182 bool QgsRefactorFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
183 {
184  Q_UNUSED( layer )
185  return false;
186 }
187 
qgsprocessingparameterfieldmap.h
qgsalgorithmrefactorfields.h
QgsProcessingContext::distanceUnit
QgsUnitTypes::DistanceUnit distanceUnit() const
Returns the distance unit to use for distance calculations.
Definition: qgsprocessingcontext.cpp:195
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
QgsFields
Container of fields for a vector layer.
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:584
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:54
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsProcessingContext::ellipsoid
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Definition: qgsprocessingcontext.cpp:185
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:165
typeName
const QString & typeName
Definition: qgswfsgetfeature.cpp:109
QgsProcessingFeatureSource::Flag
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
Definition: qgsprocessingutils.h:582
QgsProcessingContext::areaUnit
QgsUnitTypes::AreaUnit areaUnit() const
Returns the area unit to use for area calculations.
Definition: qgsprocessingcontext.cpp:205
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50