17#include "moc_qgsprocessingaggregatewidgets.cpp" 
   26#include <QStandardItemModel> 
   37  : QAbstractTableModel( parent )
 
   38  , mExpressionContextGenerator( new 
QgsFieldMappingModel::ExpressionContextGenerator( sourceFields ) )
 
 
   45  if ( role == Qt::DisplayRole )
 
   47    switch ( orientation )
 
   55            return tr( 
"Source Expression" );
 
   59            return tr( 
"Aggregate Function" );
 
   63            return tr( 
"Delimiter" );
 
   75            return tr( 
"Length" );
 
   79            return tr( 
"Precision" );
 
 
  100  if ( parent.isValid() )
 
  102  return mMapping.count();
 
 
  107  if ( parent.isValid() )
 
 
  114  if ( index.isValid() )
 
  117    const Aggregate &agg { mMapping.at( index.row() ) };
 
  121      case Qt::DisplayRole:
 
  132            return agg.aggregate;
 
  136            return agg.delimiter;
 
  140            return agg.field.displayName();
 
  144            return agg.field.typeName();
 
  148            return agg.field.length();
 
  152            return agg.field.precision();
 
 
  164  if ( index.isValid() )
 
  166    return Qt::ItemFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled );
 
  168  return Qt::ItemFlags();
 
 
  173  if ( index.isValid() )
 
  175    if ( role == Qt::EditRole )
 
  203          setFieldTypeFromName( f.
field, value.toString() );
 
  209          const int length { value.toInt( &ok ) };
 
  217          const int precision { value.toInt( &ok ) };
 
  223      emit dataChanged( index, index );
 
 
  234bool QgsAggregateMappingModel::moveUpOrDown( 
const QModelIndex &index, 
bool up )
 
  236  if ( !index.isValid() && index.model() == 
this )
 
  240  const int row { up ? index.row() - 1 : index.row() };
 
  242  if ( row < 0 || row + 1 >= 
rowCount( QModelIndex() ) )
 
  246  beginMoveRows( QModelIndex(), row, row, QModelIndex(), row + 2 );
 
  247  mMapping.swapItemsAt( row, row + 1 );
 
  252QString QgsAggregateMappingModel::qgsFieldToTypeName( 
const QgsField &field )
 
  257    if ( type.mType == field.
type() && type.mSubType == field.
subType() )
 
  259      return type.mTypeName;
 
  265void QgsAggregateMappingModel::setFieldTypeFromName( 
QgsField &field, 
const QString &name )
 
  270    if ( type.mTypeName == name )
 
  283  if ( mExpressionContextGenerator )
 
  284    mExpressionContextGenerator->setSourceFields( mSourceFields );
 
  297      aggregate.
aggregate = QStringLiteral( 
"sum" );
 
  298    else if ( f.type() == QMetaType::Type::QString || ( f.type() == QMetaType::Type::QVariantList && f.subType() == QMetaType::Type::QString ) )
 
  299      aggregate.
aggregate = QStringLiteral( 
"concatenate" );
 
  303    mMapping.push_back( aggregate );
 
 
  310  return mExpressionContextGenerator.get();
 
 
  315  mExpressionContextGenerator->setBaseExpressionContextGenerator( generator );
 
 
  327  for ( 
auto &agg : mMapping )
 
  329    agg.field.setTypeName( qgsFieldToTypeName( agg.field ) );
 
 
  336  const int lastRow { 
rowCount( QModelIndex() ) };
 
  337  beginInsertRows( QModelIndex(), lastRow, lastRow );
 
  344  mMapping.push_back( agg );
 
 
  350  if ( index.isValid() && index.model() == 
this && index.row() < 
rowCount( QModelIndex() ) )
 
  352    beginRemoveRows( QModelIndex(), index.row(), index.row() );
 
  353    mMapping.removeAt( index.row() );
 
 
  365  return moveUpOrDown( index );
 
 
  370  return moveUpOrDown( index, 
false );
 
 
  381  QVBoxLayout *verticalLayout = 
new QVBoxLayout();
 
  382  verticalLayout->setContentsMargins( 0, 0, 0, 0 );
 
  383  mTableView = 
new QTableView();
 
  384  verticalLayout->addWidget( mTableView );
 
  385  setLayout( verticalLayout );
 
  388  mTableView->setModel( mModel );
 
  394  connect( mModel, &QgsAggregateMappingModel::rowsInserted, 
this, [
this] { updateColumns(); } );
 
  395  connect( mModel, &QgsAggregateMappingModel::modelReset, 
this, [
this] { updateColumns(); } );
 
 
  404  return qobject_cast<QgsAggregateMappingModel *>( mModel );
 
 
  419  return mTableView->selectionModel();
 
 
  429  mSourceLayer = layer;
 
 
  439  mTableView->scrollTo( index );
 
 
  454  if ( !mTableView->selectionModel()->hasSelection() )
 
  457  std::list<int> rowsToRemove { selectedRows() };
 
  458  rowsToRemove.reverse();
 
  459  for ( 
const int row : rowsToRemove )
 
 
  471  if ( !mTableView->selectionModel()->hasSelection() )
 
  474  const std::list<int> rowsToMoveUp { selectedRows() };
 
  475  for ( 
const int row : rowsToMoveUp )
 
 
  487  if ( !mTableView->selectionModel()->hasSelection() )
 
  490  std::list<int> rowsToMoveDown { selectedRows() };
 
  491  rowsToMoveDown.reverse();
 
  492  for ( 
const int row : rowsToMoveDown )
 
 
  502void QgsAggregateMappingWidget::updateColumns()
 
  504  for ( 
int i = 0; i < mModel->rowCount(); ++i )
 
  511  for ( 
int i = 0; i < mModel->columnCount(); ++i )
 
  513    mTableView->resizeColumnToContents( i );
 
  517std::list<int> QgsAggregateMappingWidget::selectedRows()
 
  520  if ( mTableView->selectionModel()->hasSelection() )
 
  522    const QModelIndexList constSelection { mTableView->selectionModel()->selectedIndexes() };
 
  523    for ( 
const QModelIndex &index : constSelection )
 
  525      rows.push_back( index.row() );
 
  540QgsAggregateMappingDelegate::QgsAggregateMappingDelegate( QObject *parent )
 
  541  : QStyledItemDelegate( parent )
 
  545QWidget *QgsAggregateMappingDelegate::createEditor( QWidget *parent, 
const QStyleOptionViewItem &option, 
const QModelIndex & )
 const 
  548  QComboBox *editor = 
new QComboBox( parent );
 
  550  const QStringList aggregateList { aggregates() };
 
  552  for ( 
const QString &aggregate : aggregateList )
 
  554    editor->addItem( aggregate );
 
  555    editor->setItemData( i, aggregate, Qt::UserRole );
 
  559  connect( editor, qOverload<int>( &QComboBox::currentIndexChanged ), 
this, [
this, editor]( 
int currentIndex ) {
 
  560    Q_UNUSED( currentIndex )
 
  561    const_cast<QgsAggregateMappingDelegate *
>( this )->emit commitData( editor );
 
  567void QgsAggregateMappingDelegate::setEditorData( QWidget *editor, 
const QModelIndex &index )
 const 
  569  QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
 
  573  const QVariant value = index.model()->data( index, Qt::EditRole );
 
  574  editorWidget->setCurrentIndex( editorWidget->findData( value ) );
 
  577void QgsAggregateMappingDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, 
const QModelIndex &index )
 const 
  579  QComboBox *editorWidget { qobject_cast<QComboBox *>( editor ) };
 
  583  const QVariant currentValue = editorWidget->currentData();
 
  584  model->setData( index, currentValue, Qt::EditRole );
 
  587const QStringList QgsAggregateMappingDelegate::aggregates()
 
  589  static QStringList sAggregates;
 
  590  static std::once_flag initialized;
 
  591  std::call_once( initialized, []() {
 
  592    sAggregates << QStringLiteral( 
"first_value" )
 
  593                << QStringLiteral( 
"last_value" );
 
  598      if ( !function || function->isDeprecated() || function->name().isEmpty() || function->name().at( 0 ) == 
'_' )
 
  601      if ( function->groups().contains( QLatin1String( 
"Aggregates" ) ) )
 
  603        if ( function->name() == QLatin1String( 
"aggregate" )
 
  604             || function->name() == QLatin1String( 
"relation_aggregate" ) )
 
  607        sAggregates.append( function->name() );
 
  610      std::sort( sAggregates.begin(), sAggregates.end() );
 
Holds mapping information for defining sets of aggregates of fields from a QgsFields object.
 
QgsFields sourceFields() const
Returns a list of source fields.
 
void appendField(const QgsField &field, const QString &source=QString(), const QString &aggregate=QString())
Appends a new field to the model, with an optional source and aggregate.
 
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
 
int columnCount(const QModelIndex &parent=QModelIndex()) const override
 
ColumnDataIndex
The ColumnDataIndex enum represents the column index for the view.
 
@ Aggregate
Aggregate name.
 
@ SourceExpression
Expression.
 
@ DestinationPrecision
Destination field precision.
 
@ DestinationName
Destination field name.
 
@ DestinationType
Destination field type string.
 
@ DestinationLength
Destination field length.
 
Qt::ItemFlags flags(const QModelIndex &index) const override
 
bool removeField(const QModelIndex &index)
Removes the field at index from the model, returns true on success.
 
bool moveUp(const QModelIndex &index)
Moves down the field at index.
 
QVariant data(const QModelIndex &index, int role) const override
 
QList< QgsAggregateMappingModel::Aggregate > mapping() const
Returns a list of Aggregate objects representing the current status of the model.
 
bool setData(const QModelIndex &index, const QVariant &value, int role) override
 
QgsExpressionContextGenerator * contextGenerator() const
Returns the context generator with the source fields.
 
bool moveDown(const QModelIndex &index)
Moves up the field at index.
 
void setSourceFields(const QgsFields &sourceFields)
Set source fields to sourceFields.
 
void setMapping(const QList< QgsAggregateMappingModel::Aggregate > &mapping)
Sets the mapping to show in the model.
 
int rowCount(const QModelIndex &parent=QModelIndex()) const override
 
void setBaseExpressionContextGenerator(const QgsExpressionContextGenerator *generator)
Sets the base expression context generator, which will generate the expression contexts for expressio...
 
QgsAggregateMappingModel(const QgsFields &sourceFields=QgsFields(), QObject *parent=nullptr)
Constructs a QgsAggregateMappingModel from a set of sourceFields.
 
Abstract interface for generating an expression context.
 
An abstract base class for defining QgsExpression functions.
 
Handles parsing and evaluation of expressions (formerly called "search strings").
 
static const QList< QgsExpressionFunction * > & Functions()
 
static QString quotedColumnRef(QString name)
Returns a quoted column reference (in double quotes)
 
Holds mapping information for mapping from one set of QgsFields to another.
 
static const QList< QgsVectorDataProvider::NativeType > supportedDataTypes()
Returns a static list of supported data types.
 
Encapsulate a field in an attribute table or data source.
 
void setPrecision(int precision)
Set the field precision.
 
void setSubType(QMetaType::Type subType)
If the field is a collection, set its element's type.
 
void setName(const QString &name)
Set the field name.
 
void setType(QMetaType::Type type)
Set variant type.
 
void setLength(int len)
Set the field length.
 
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
 
void setTypeName(const QString &typeName)
Set the field type.
 
Container of fields for a vector layer.
 
Represents a vector layer which manages a vector based dataset.
 
The Aggregate struct holds information about an aggregate column.
 
QString source
The source expression used as the input for the aggregate calculation.
 
QString delimiter
Delimiter string.
 
QString aggregate
Aggregate name.
 
QgsField field
The field in its current status (it might have been renamed)