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 static_cast<int>( agg.field.type() );
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 f.
field.
setType(
static_cast<QVariant::Type
>( value.toInt( ) ) );
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 QStringList usedFields;
271 aggregate.
aggregate = QStringLiteral(
"sum" );
272 else if ( f.type() == QVariant::String || ( f.type() == QVariant::List && f.subType() == QVariant::String ) )
273 aggregate.
aggregate = QStringLiteral(
"concatenate" );
277 mMapping.push_back( aggregate );
284 return mExpressionContextGenerator.get();
289 mExpressionContextGenerator->setBaseExpressionContextGenerator( generator );
306 const int lastRow {
rowCount( QModelIndex( ) ) };
307 beginInsertRows( QModelIndex(), lastRow, lastRow );
313 mMapping.push_back( agg );
319 if ( index.isValid() && index.model() ==
this && index.row() <
rowCount( QModelIndex() ) )
321 beginRemoveRows( QModelIndex(), index.row(), index.row() );
322 mMapping.removeAt( index.row() );
334 return moveUpOrDown( index );
339 return moveUpOrDown( index,
false );
351 QVBoxLayout *verticalLayout =
new QVBoxLayout();
352 verticalLayout->setContentsMargins( 0, 0, 0, 0 );
353 mTableView =
new QTableView();
354 verticalLayout->addWidget( mTableView );
355 setLayout( verticalLayout );
358 mTableView->setModel( mModel );
364 connect( mModel, &QgsAggregateMappingModel::rowsInserted,
this, [ = ] { updateColumns(); } );
365 connect( mModel, &QgsAggregateMappingModel::modelReset,
this, [ = ] { updateColumns(); } );
374 return qobject_cast<QgsAggregateMappingModel *>( mModel );
389 return mTableView->selectionModel();
399 mTableView->scrollTo( index );
414 if ( ! mTableView->selectionModel()->hasSelection() )
417 std::list<int> rowsToRemove { selectedRows() };
418 rowsToRemove.reverse();
419 for (
int row : rowsToRemove )
421 if ( !
model()->removeField(
model()->index( row, 0, QModelIndex() ) ) )
431 if ( ! mTableView->selectionModel()->hasSelection() )
434 const std::list<int> rowsToMoveUp { selectedRows() };
435 for (
int row : rowsToMoveUp )
437 if ( !
model()->moveUp(
model()->index( row, 0, QModelIndex() ) ) )
447 if ( ! mTableView->selectionModel()->hasSelection() )
450 std::list<int> rowsToMoveDown { selectedRows() };
451 rowsToMoveDown.reverse();
452 for (
int row : rowsToMoveDown )
454 if ( !
model()->moveDown(
model()->index( row, 0, QModelIndex() ) ) )
462 void QgsAggregateMappingWidget::updateColumns()
464 for (
int i = 0; i < mModel->rowCount(); ++i )
471 for (
int i = 0; i < mModel->columnCount(); ++i )
473 mTableView->resizeColumnToContents( i );
477 std::list<int> QgsAggregateMappingWidget::selectedRows()
480 if ( mTableView->selectionModel()->hasSelection() )
482 const QModelIndexList constSelection { mTableView->selectionModel()->selectedIndexes() };
483 for (
const QModelIndex &index : constSelection )
485 rows.push_back( index.row() );
499 QgsAggregateMappingWidget::AggregateDelegate::AggregateDelegate( QObject *parent )
500 : QStyledItemDelegate( parent )
504 QWidget *QgsAggregateMappingWidget::AggregateDelegate::createEditor( QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex & )
const
507 QComboBox *editor =
new QComboBox( parent );
509 const QStringList aggregateList { QgsAggregateMappingWidget::AggregateDelegate::aggregates() };
511 for (
const QString &aggregate : aggregateList )
513 editor->addItem( aggregate );
514 editor->setItemData( i, aggregate, Qt::UserRole );
519 qgis::overload<int >::of( &QComboBox::currentIndexChanged ),
521 [ = ](
int currentIndex )
523 Q_UNUSED( currentIndex )
524 const_cast< QgsAggregateMappingWidget::AggregateDelegate *
>( this )->emit commitData( editor );
530 void QgsAggregateMappingWidget::AggregateDelegate::setEditorData( QWidget *editor,
const QModelIndex &index )
const
532 QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
533 if ( ! editorWidget )
536 const QVariant value { index.model()->data( index, Qt::EditRole ) };
537 editorWidget->setCurrentIndex( editorWidget->findData( value ) );
540 void QgsAggregateMappingWidget::AggregateDelegate::setModelData( QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index )
const
542 QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
543 if ( ! editorWidget )
546 const QVariant currentValue { editorWidget->currentData( ) };
547 model->setData( index, currentValue, Qt::EditRole );
550 const QStringList QgsAggregateMappingWidget::AggregateDelegate::aggregates()
552 static QStringList sAggregates;
553 static std::once_flag initialized;
554 std::call_once( initialized, [ = ]( )
556 sAggregates << QStringLiteral(
"first_value" );
561 if ( !
function || function->isDeprecated() || function->name().isEmpty() || function->name().at( 0 ) ==
'_' )
564 if ( function->groups().contains( QLatin1String(
"Aggregates" ) ) )
566 if ( function->name() == QLatin1String(
"aggregate" )
567 || function->name() == QLatin1String(
"relation_aggregate" ) )
570 sAggregates.append( function->name() );
573 std::sort( sAggregates.begin(), sAggregates.end() );