23 #include <QMessageBox>
24 #include <QPushButton>
25 #include <QStandardItemModel>
26 #include <QToolButton>
36 : QAbstractTableModel( parent )
37 , mExpressionContextGenerator( new
QgsFieldMappingModel::ExpressionContextGenerator( sourceFields ) )
44 if ( role == Qt::DisplayRole )
46 switch ( orientation )
54 return tr(
"Source Expression" );
58 return tr(
"Aggregate Function" );
62 return tr(
"Delimiter" );
74 return tr(
"Length" );
78 return tr(
"Precision" );
99 if ( parent.isValid() )
101 return mMapping.count();
106 if ( parent.isValid() )
113 if ( index.isValid() )
116 const Aggregate &agg { mMapping.at( index.row() ) };
120 case Qt::DisplayRole:
131 return agg.aggregate;
135 return agg.delimiter;
139 return agg.field.displayName();
143 return agg.field.typeName();
147 return agg.field.length();
151 return agg.field.precision();
163 if ( index.isValid() )
165 return Qt::ItemFlags( Qt::ItemIsSelectable |
169 return Qt::ItemFlags();
174 if ( index.isValid() )
176 if ( role == Qt::EditRole )
204 QgsFieldMappingModel::setFieldTypeFromName( f.
field, value.toString() );
210 const int length { value.toInt( &ok ) };
218 const int precision { value.toInt( &ok ) };
224 emit dataChanged( index, index );
235 bool QgsAggregateMappingModel::moveUpOrDown(
const QModelIndex &index,
bool up )
237 if ( ! index.isValid() && index.model() ==
this )
241 const int row { up ? index.row() - 1 : index.row() };
243 if ( row < 0 || row + 1 >=
rowCount( QModelIndex() ) )
247 beginMoveRows( QModelIndex( ), row, row, QModelIndex(), row + 2 );
248 #if QT_VERSION < QT_VERSION_CHECK(5, 13, 0)
249 mMapping.swap( row, row + 1 );
251 mMapping.swapItemsAt( row, row + 1 );
260 if ( mExpressionContextGenerator )
261 mExpressionContextGenerator->setSourceFields( mSourceFields );
263 const QStringList usedFields;
271 aggregate.
field.
setTypeName( QgsFieldMappingModel::qgsFieldToTypeName( f ) );
275 aggregate.
aggregate = QStringLiteral(
"sum" );
276 else if ( f.type() == QVariant::String || ( f.type() == QVariant::List && f.subType() == QVariant::String ) )
277 aggregate.
aggregate = QStringLiteral(
"concatenate" );
281 mMapping.push_back( aggregate );
288 return mExpressionContextGenerator.get();
293 mExpressionContextGenerator->setBaseExpressionContextGenerator( generator );
305 for (
auto &agg : mMapping )
307 agg.field.setTypeName( QgsFieldMappingModel::qgsFieldToTypeName( agg.field ) );
314 const int lastRow {
rowCount( QModelIndex( ) ) };
315 beginInsertRows( QModelIndex(), lastRow, lastRow );
322 mMapping.push_back( agg );
328 if ( index.isValid() && index.model() ==
this && index.row() <
rowCount( QModelIndex() ) )
330 beginRemoveRows( QModelIndex(), index.row(), index.row() );
331 mMapping.removeAt( index.row() );
343 return moveUpOrDown( index );
348 return moveUpOrDown( index,
false );
360 QVBoxLayout *verticalLayout =
new QVBoxLayout();
361 verticalLayout->setContentsMargins( 0, 0, 0, 0 );
362 mTableView =
new QTableView();
363 verticalLayout->addWidget( mTableView );
364 setLayout( verticalLayout );
367 mTableView->setModel( mModel );
373 connect( mModel, &QgsAggregateMappingModel::rowsInserted,
this, [ = ] { updateColumns(); } );
374 connect( mModel, &QgsAggregateMappingModel::modelReset,
this, [ = ] { updateColumns(); } );
383 return qobject_cast<QgsAggregateMappingModel *>( mModel );
398 return mTableView->selectionModel();
408 mSourceLayer = layer;
418 mTableView->scrollTo( index );
433 if ( ! mTableView->selectionModel()->hasSelection() )
436 std::list<int> rowsToRemove { selectedRows() };
437 rowsToRemove.reverse();
438 for (
const int row : rowsToRemove )
440 if ( !
model()->removeField(
model()->index( row, 0, QModelIndex() ) ) )
450 if ( ! mTableView->selectionModel()->hasSelection() )
453 const std::list<int> rowsToMoveUp { selectedRows() };
454 for (
const int row : rowsToMoveUp )
456 if ( !
model()->moveUp(
model()->index( row, 0, QModelIndex() ) ) )
466 if ( ! mTableView->selectionModel()->hasSelection() )
469 std::list<int> rowsToMoveDown { selectedRows() };
470 rowsToMoveDown.reverse();
471 for (
const int row : rowsToMoveDown )
473 if ( !
model()->moveDown(
model()->index( row, 0, QModelIndex() ) ) )
481 void QgsAggregateMappingWidget::updateColumns()
483 for (
int i = 0; i < mModel->rowCount(); ++i )
490 for (
int i = 0; i < mModel->columnCount(); ++i )
492 mTableView->resizeColumnToContents( i );
496 std::list<int> QgsAggregateMappingWidget::selectedRows()
499 if ( mTableView->selectionModel()->hasSelection() )
501 const QModelIndexList constSelection { mTableView->selectionModel()->selectedIndexes() };
502 for (
const QModelIndex &index : constSelection )
504 rows.push_back( index.row() );
518 QgsAggregateMappingWidget::AggregateDelegate::AggregateDelegate( QObject *parent )
519 : QStyledItemDelegate( parent )
523 QWidget *QgsAggregateMappingWidget::AggregateDelegate::createEditor( QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex & )
const
526 QComboBox *editor =
new QComboBox( parent );
528 const QStringList aggregateList { QgsAggregateMappingWidget::AggregateDelegate::aggregates() };
530 for (
const QString &aggregate : aggregateList )
532 editor->addItem( aggregate );
533 editor->setItemData( i, aggregate, Qt::UserRole );
538 qOverload<int >( &QComboBox::currentIndexChanged ),
540 [ = ](
int currentIndex )
542 Q_UNUSED( currentIndex )
543 const_cast< QgsAggregateMappingWidget::AggregateDelegate *
>( this )->emit commitData( editor );
549 void QgsAggregateMappingWidget::AggregateDelegate::setEditorData( QWidget *editor,
const QModelIndex &index )
const
551 QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
552 if ( ! editorWidget )
555 const QVariant value = index.model()->data( index, Qt::EditRole );
556 editorWidget->setCurrentIndex( editorWidget->findData( value ) );
559 void QgsAggregateMappingWidget::AggregateDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index )
const
561 QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
562 if ( ! editorWidget )
565 const QVariant currentValue = editorWidget->currentData( );
566 model->setData( index, currentValue, Qt::EditRole );
569 const QStringList QgsAggregateMappingWidget::AggregateDelegate::aggregates()
571 static QStringList sAggregates;
572 static std::once_flag initialized;
573 std::call_once( initialized, [ = ]( )
575 sAggregates << QStringLiteral(
"first_value" )
576 << QStringLiteral(
"last_value" );
581 if ( !
function || function->isDeprecated() || function->name().isEmpty() || function->name().at( 0 ) ==
'_' )
584 if ( function->groups().contains( QLatin1String(
"Aggregates" ) ) )
586 if ( function->name() == QLatin1String(
"aggregate" )
587 || function->name() == QLatin1String(
"relation_aggregate" ) )
590 sAggregates.append( function->name() );
593 std::sort( sAggregates.begin(), sAggregates.end() );