23 const QMap<QString, QString> &expressions,
25 : QAbstractTableModel( parent )
26 , mSourceFields( sourceFields )
27 , mExpressionContextGenerator( new ExpressionContextGenerator( &mSourceFields ) )
34 if ( role == Qt::DisplayRole )
36 switch ( orientation )
44 return tr(
"Source Expression" );
56 return tr(
"Length" );
60 return tr(
"Precision" );
64 return tr(
"Constraints" );
85 if ( parent.isValid() )
87 return mMapping.count();
92 if ( parent.isValid() )
99 if ( index.isValid() )
102 const Field &f { mMapping.at( index.row() ) };
104 const QgsFieldConstraints::Constraints constraints { fieldConstraints( f.field ) };
108 case Qt::DisplayRole:
119 return f.field.displayName();
123 return static_cast<int>( f.field.type() );
127 return f.field.length();
131 return f.field.precision();
135 return constraints != 0 ? tr(
"Constraints active" ) : QString();
140 case Qt::ToolTipRole:
145 QStringList constraintDescription;
146 if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintUnique ) )
148 constraintDescription.push_back( tr(
"Unique" ) );
150 if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintNotNull ) )
152 constraintDescription.push_back( tr(
"Not null" ) );
154 if ( constraints.testFlag( QgsFieldConstraints::Constraint::ConstraintExpression ) )
156 constraintDescription.push_back( tr(
"Expression" ) );
158 return constraintDescription.join( QStringLiteral(
"<br>" ) );
162 case Qt::BackgroundRole:
164 if ( constraints != 0 )
166 return QBrush( QColor( 255, 224, 178 ) );
177 if ( index.isValid() &&
181 return Qt::ItemFlags( Qt::ItemIsSelectable |
185 return Qt::ItemFlags();
190 if ( index.isValid() )
192 if ( role == Qt::EditRole )
194 Field &f = mMapping[index.row()];
210 f.
field.
setType(
static_cast<QVariant::Type
>( value.toInt( ) ) );
216 const int length { value.toInt( &ok ) };
224 const int precision { value.toInt( &ok ) };
234 emit dataChanged( index, index );
244 QgsFieldConstraints::Constraints QgsFieldMappingModel::fieldConstraints(
const QgsField &field )
const
246 QgsFieldConstraints::Constraints constraints;
265 bool QgsFieldMappingModel::moveUpOrDown(
const QModelIndex &index,
bool up )
267 if ( ! index.isValid() && index.model() ==
this )
271 const int row { up ? index.row() - 1 : index.row() };
273 if ( row < 0 || row + 1 >=
rowCount( QModelIndex() ) )
277 beginMoveRows( QModelIndex( ), row, row, QModelIndex(), row + 2 );
278 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
279 mMapping.swap( row, row + 1 );
281 mMapping.swapItemsAt( row, row + 1 );
287 QString QgsFieldMappingModel::findExpressionForDestinationField(
const QgsFieldMappingModel::Field &f, QStringList &excludedFieldNames )
291 for (
const QgsField &sf : qgis::as_const( mSourceFields ) )
295 excludedFieldNames.push_back( sf.name() );
300 for (
const QgsField &sf : qgis::as_const( mSourceFields ) )
302 if ( excludedFieldNames.contains( sf.name() ) || sf.type() != f.
field.
type() )
304 excludedFieldNames.push_back( sf.name() );
313 QStringList usedFields;
315 for (
const Field &f : qgis::as_const( mMapping ) )
322 for (
auto it = mMapping.begin(); it != mMapping.end(); ++it )
324 if ( it->expression.isEmpty() )
326 const QString expression { findExpressionForDestinationField( *it, usedFields ) };
327 if ( ! expression.isEmpty() )
328 it->expression = expression;
336 return mExpressionContextGenerator.get();
341 mExpressionContextGenerator->setBaseExpressionContextGenerator( generator );
345 const QMap<QString, QString> &expressions )
350 QStringList usedFields;
351 for (
const QgsField &df : destinationFields )
356 if ( expressions.contains( f.
field.
name() ) )
361 if ( exp.isField() &&
362 mSourceFields.
names().contains( qgis::setToList( exp.referencedColumns() ).first() ) )
364 usedFields.push_back( qgis::setToList( exp.referencedColumns() ).first() );
369 const QString expression { findExpressionForDestinationField( f, usedFields ) };
370 if ( ! expression.isEmpty() )
373 mMapping.push_back( f );
380 return mDestinationEditable;
390 static const QMap<QVariant::Type, QString> sDataTypes
392 { QVariant::Type::Int, tr(
"Whole number (integer - 32bit)" ) },
393 { QVariant::Type::LongLong, tr(
"Whole number (integer - 64bit)" ) },
394 { QVariant::Type::Double, tr(
"Decimal number (double)" ) },
395 { QVariant::Type::String, tr(
"Text (string)" ) },
396 { QVariant::Type::Date, tr(
"Date" ) },
397 { QVariant::Type::Time, tr(
"Time" ) },
398 { QVariant::Type::DateTime, tr(
"Date & Time" ) },
399 { QVariant::Type::Bool, tr(
"Boolean" ) },
400 { QVariant::Type::ByteArray, tr(
"Binary object (BLOB)" ) },
412 QMap< QString, QgsProperty > fieldMap;
416 const bool isField = exp.
isField();
417 fieldMap.insert( field.originalName, isField
427 for (
int i = 0; i < mMapping.count(); ++i )
429 Field &f = mMapping[i];
462 const int lastRow {
rowCount( QModelIndex( ) ) };
463 beginInsertRows( QModelIndex(), lastRow, lastRow );
468 mMapping.push_back( f );
474 if ( index.isValid() && index.model() ==
this && index.row() <
rowCount( QModelIndex() ) )
476 beginRemoveRows( QModelIndex(), index.row(), index.row() );
477 mMapping.removeAt( index.row() );
489 return moveUpOrDown( index );
494 return moveUpOrDown( index,
false );
497 QgsFieldMappingModel::ExpressionContextGenerator::ExpressionContextGenerator(
const QgsFields *sourceFields )
498 : mSourceFields( sourceFields )
502 QgsExpressionContext QgsFieldMappingModel::ExpressionContextGenerator::createExpressionContext()
const
504 if ( mBaseGenerator )
507 std::unique_ptr< QgsExpressionContextScope > fieldMappingScope = qgis::make_unique< QgsExpressionContextScope >( tr(
"Field Mapping" ) );
508 fieldMappingScope->setFields( *mSourceFields );
526 mBaseGenerator = generator;