mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-24 00:04:44 -04:00
190 lines
6.8 KiB
C++
190 lines
6.8 KiB
C++
/***************************************************************************
|
|
qgsalgorithmrefactorfields.h
|
|
---------------------------------
|
|
begin : June 2020
|
|
copyright : (C) 2020 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsalgorithmrefactorfields.h"
|
|
#include "qgsprocessingparameterfieldmap.h"
|
|
|
|
///@cond PRIVATE
|
|
|
|
QString QgsRefactorFieldsAlgorithm::name() const
|
|
{
|
|
return QStringLiteral( "refactorfields" );
|
|
}
|
|
|
|
QString QgsRefactorFieldsAlgorithm::displayName() const
|
|
{
|
|
return QObject::tr( "Refactor fields" );
|
|
}
|
|
|
|
QString QgsRefactorFieldsAlgorithm::shortHelpString() const
|
|
{
|
|
return QObject::tr( "This algorithm allows editing the structure of the attributes table of a vector layer. Fields can be modified "
|
|
"in their type and name, using a fields mapping.\n\n"
|
|
"The original layer is not modified. A new layer is generated, which contains a modified attribute table, according "
|
|
"to the provided fields mapping.\n\n"
|
|
"Rows in orange have constraints in the template layer from which these fields were loaded. Treat this information "
|
|
"as a hint during configuration. No constraints will be added on an output layer nor will they be checked or "
|
|
"enforced by the algorithm." );
|
|
}
|
|
|
|
QStringList QgsRefactorFieldsAlgorithm::tags() const
|
|
{
|
|
return QObject::tr( "attributes,table" ).split( ',' );
|
|
}
|
|
|
|
QString QgsRefactorFieldsAlgorithm::group() const
|
|
{
|
|
return QObject::tr( "Vector table" );
|
|
}
|
|
|
|
QString QgsRefactorFieldsAlgorithm::groupId() const
|
|
{
|
|
return QStringLiteral( "vectortable" );
|
|
}
|
|
|
|
QString QgsRefactorFieldsAlgorithm::outputName() const
|
|
{
|
|
return QObject::tr( "Refactored" );
|
|
}
|
|
|
|
QList<int> QgsRefactorFieldsAlgorithm::inputLayerTypes() const
|
|
{
|
|
return QList<int>() << QgsProcessing::TypeVector;
|
|
}
|
|
|
|
QgsProcessingFeatureSource::Flag QgsRefactorFieldsAlgorithm::sourceFlags() const
|
|
{
|
|
return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks;
|
|
}
|
|
|
|
QgsRefactorFieldsAlgorithm *QgsRefactorFieldsAlgorithm::createInstance() const
|
|
{
|
|
return new QgsRefactorFieldsAlgorithm();
|
|
}
|
|
|
|
void QgsRefactorFieldsAlgorithm::initParameters( const QVariantMap & )
|
|
{
|
|
std::unique_ptr< QgsProcessingParameterFieldMapping > param = qgis::make_unique< QgsProcessingParameterFieldMapping> ( QStringLiteral( "FIELDS_MAPPING" ), QObject::tr( "Fields mapping" ), QStringLiteral( "INPUT" ) );
|
|
addParameter( param.release() );
|
|
}
|
|
|
|
QgsFields QgsRefactorFieldsAlgorithm::outputFields( const QgsFields & ) const
|
|
{
|
|
return mFields;
|
|
}
|
|
|
|
bool QgsRefactorFieldsAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
|
{
|
|
std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
|
|
if ( !source )
|
|
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
|
|
|
|
mDa.setSourceCrs( source->sourceCrs(), context.transformContext() );
|
|
mDa.setEllipsoid( context.project()->ellipsoid() );
|
|
|
|
mExpressionContext = createExpressionContext( parameters, context, source.get() );
|
|
|
|
const QVariantList mapping = parameters.value( QStringLiteral( "FIELDS_MAPPING" ) ).toList();
|
|
for ( const QVariant &map : mapping )
|
|
{
|
|
const QVariantMap fieldDef = map.toMap();
|
|
const QString name = fieldDef.value( QStringLiteral( "name" ) ).toString();
|
|
if ( name.isEmpty() )
|
|
throw QgsProcessingException( QObject::tr( "Field name cannot be empty" ) );
|
|
|
|
const QVariant::Type type = static_cast< QVariant::Type >( fieldDef.value( QStringLiteral( "type" ) ).toInt() );
|
|
|
|
const int length = fieldDef.value( QStringLiteral( "length" ), 0 ).toInt();
|
|
const int precision = fieldDef.value( QStringLiteral( "precision" ), 0 ).toInt();
|
|
|
|
mFields.append( QgsField( name, type, QString(), length, precision ) );
|
|
|
|
const QString expressionString = fieldDef.value( QStringLiteral( "expression" ) ).toString();
|
|
if ( !expressionString.isEmpty() )
|
|
{
|
|
QgsExpression expression( expressionString );
|
|
expression.setGeomCalculator( &mDa );
|
|
if ( context.project() )
|
|
{
|
|
expression.setDistanceUnits( context.project()->distanceUnits() );
|
|
expression.setAreaUnits( context.project()->areaUnits() );
|
|
}
|
|
if ( expression.hasParserError() )
|
|
{
|
|
throw QgsProcessingException( QObject::tr( "Parser error for field \"%1\" with expression \"%2\": %3" )
|
|
.arg(
|
|
name,
|
|
expressionString,
|
|
expression.parserErrorString() ) );
|
|
}
|
|
mExpressions.append( expression );
|
|
}
|
|
else
|
|
{
|
|
mExpressions.append( QgsExpression() );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
QgsFeatureList QgsRefactorFieldsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
|
|
{
|
|
if ( !mExpressionsPrepared )
|
|
{
|
|
for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
|
|
{
|
|
if ( it->isValid() )
|
|
it->prepare( &mExpressionContext );
|
|
}
|
|
}
|
|
|
|
QgsAttributes attributes;
|
|
attributes.reserve( mExpressions.size() );
|
|
for ( auto it = mExpressions.begin(); it != mExpressions.end(); ++it )
|
|
{
|
|
if ( it->isValid() )
|
|
{
|
|
mExpressionContext.setFeature( feature );
|
|
mExpressionContext.lastScope()->setVariable( QStringLiteral( "row_number" ), mRowNumber );
|
|
const QVariant value = it->evaluate( &mExpressionContext );
|
|
if ( it->hasEvalError() )
|
|
{
|
|
throw QgsProcessingException( QObject::tr( "Evaluation error in expression \"%1\": %2" ).arg( it->expression(), it->evalErrorString() ) );
|
|
}
|
|
attributes.append( value );
|
|
}
|
|
else
|
|
{
|
|
attributes.append( QVariant() );
|
|
}
|
|
}
|
|
|
|
QgsFeature f = feature;
|
|
f.setAttributes( attributes );
|
|
mRowNumber++;
|
|
return QgsFeatureList() << f;
|
|
}
|
|
|
|
bool QgsRefactorFieldsAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
|
|
{
|
|
Q_UNUSED( layer )
|
|
return false;
|
|
}
|
|
|
|
///@endcond
|