20 #include <QStringList> 
   22 #include <QHeaderView> 
   24 #include <QPlainTextEdit> 
   27   : QTableWidget( parent )
 
   29   mHeaderMenu = 
new QMenu( 
this );
 
   32   connect( 
this, &QgsTableEditorWidget::cellChanged, 
this, [ = ]
 
   38   horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
 
   39   connect( horizontalHeader(), &QWidget::customContextMenuRequested, 
this, [ = ]( 
const QPoint & point )
 
   41     const int column = horizontalHeader()->logicalIndexAt( point.x() );
 
   43     QSet< int > selectedColumns;
 
   44     for ( 
const QModelIndex &index : selectedIndexes() )
 
   46       selectedColumns.insert( index.column() );
 
   50     bool isConsecutive = collectConsecutiveColumnRange( selectedIndexes(), minCol, maxCol );
 
   53     if ( selectedIndexes().count() == 1 )
 
   56       selectColumn( column );
 
   59     else if ( !selectedColumns.contains( column ) )
 
   62       selectColumn( column );
 
   69       QAction *insertBefore = mHeaderMenu->addAction( selectedColumns.size() > 1 ? tr( 
"Insert %1 Columns Before" ).arg( selectedColumns.size() ) : tr( 
"Insert Column Before" ) );
 
   71       QAction *insertAfter = mHeaderMenu->addAction( selectedColumns.size() > 1 ? tr( 
"Insert %1 Columns After" ).arg( selectedColumns.size() ) : tr( 
"Insert Column After" ) );
 
   74     QAction *deleteSelected = mHeaderMenu->addAction( selectedColumns.size() > 1 ? tr( 
"Delete %1 Columns" ).arg( selectedColumns.size() ) : tr( 
"Delete Column" ) );
 
   77     mHeaderMenu->popup( horizontalHeader()->mapToGlobal( point ) );
 
   80   verticalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
 
   81   connect( verticalHeader(), &QWidget::customContextMenuRequested, 
this, [ = ]( 
const QPoint & point )
 
   83     const int row = verticalHeader()->logicalIndexAt( point.y() );
 
   85     QSet< int > selectedRows;
 
   86     for ( 
const QModelIndex &index : selectedIndexes() )
 
   88       selectedRows.insert( index.row() );
 
   92     bool isConsecutive = collectConsecutiveRowRange( selectedIndexes(), minRow, maxRow );
 
   95     if ( selectedIndexes().count() == 1 )
 
  101     else if ( !selectedRows.contains( row ) )
 
  105       isConsecutive = 
true;
 
  108     mHeaderMenu->clear();
 
  111       QAction *insertBefore = mHeaderMenu->addAction( selectedRows.size() > 1 ? tr( 
"Insert %1 Rows Above" ).arg( selectedRows.size() ) : tr( 
"Insert Row Above" ) );
 
  113       QAction *insertAfter = mHeaderMenu->addAction( selectedRows.size() > 1 ? tr( 
"Insert %1 Rows Below" ).arg( selectedRows.size() ) : tr( 
"Insert Row Below" ) );
 
  116     QAction *deleteSelected = mHeaderMenu->addAction( selectedRows.size() > 1 ? tr( 
"Delete %1 Rows" ).arg( selectedRows.size() ) : tr( 
"Delete Row" ) );
 
  119     mHeaderMenu->popup( verticalHeader()->mapToGlobal( point ) );
 
  124   connect( delegate, &QgsTableEditorDelegate::updateNumericFormatForIndex, 
this, &QgsTableEditorWidget::updateNumericFormatForIndex );
 
  125   setItemDelegate( delegate );
 
  128   connect( 
this, &QTableWidget::cellDoubleClicked, 
this, [ = ]
 
  132       d->setWeakEditorMode( 
false );
 
  141   qDeleteAll( mNumericFormats );
 
  144 void QgsTableEditorWidget::updateNumericFormatForIndex( 
const QModelIndex &index )
 
  146   if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  150       i->setData( Qt::DisplayRole, format->formatDouble( index.data( CellContent ).toDouble(), 
QgsNumericFormatContext() ) );
 
  155 void QgsTableEditorWidget::updateHeaders()
 
  163   for ( 
char c = 
'A'; 
c <= 
'Z'; 
c++ )
 
  165     letters.push_back( QString( 
c ) );
 
  168   int len = letters.length();
 
  172   for ( 
int i = 0; i < 1000; i++ )
 
  178       first = letters.at( fIndex );
 
  188     current += letters.at( index );
 
  189     headers.push_back( current );
 
  195   setHorizontalHeaderLabels( headers );
 
  198   if ( mIncludeHeader )
 
  199     headers << tr( 
"Header" );
 
  200   for ( 
int i = 1; i <= 1000; i++ )
 
  202     headers << QString::number( i );
 
  205   setVerticalHeaderLabels( headers );
 
  208 bool QgsTableEditorWidget::collectConsecutiveRowRange( 
const QModelIndexList &list, 
int &minRow, 
int &maxRow )
 const 
  210   QSet< int > includedRows;
 
  211   minRow = std::numeric_limits< int >::max();
 
  213   for ( 
const QModelIndex &index : list )
 
  215     includedRows.insert( index.row() );
 
  216     minRow = std::min( minRow, index.row() );
 
  217     maxRow = std::max( maxRow, index.row() );
 
  221   for ( 
int r = minRow + 1; r < maxRow; r++ )
 
  223     if ( !includedRows.contains( r ) )
 
  229 bool QgsTableEditorWidget::collectConsecutiveColumnRange( 
const QModelIndexList &list, 
int &minColumn, 
int &maxColumn )
 const 
  231   QSet< int > includedColumns;
 
  232   minColumn = std::numeric_limits< int >::max();
 
  234   for ( 
const QModelIndex &index : list )
 
  236     includedColumns.insert( index.column() );
 
  237     minColumn = std::min( minColumn, index.column() );
 
  238     maxColumn = std::max( maxColumn, index.column() );
 
  242   for ( 
int r = minColumn + 1; r < maxColumn; r++ )
 
  244     if ( !includedColumns.contains( r ) )
 
  250 QList<int> QgsTableEditorWidget::collectUniqueRows( 
const QModelIndexList &list )
 const 
  253   for ( 
const QModelIndex &index : list )
 
  255     if ( !res.contains( index.row() ) )
 
  258   std::sort( res.begin(), res.end() );
 
  262 QList<int> QgsTableEditorWidget::collectUniqueColumns( 
const QModelIndexList &list )
 const 
  265   for ( 
const QModelIndex &index : list )
 
  267     if ( !res.contains( index.column() ) )
 
  268       res << index.column();
 
  270   std::sort( res.begin(), res.end() );
 
  276   switch ( event->key() )
 
  282       QTableWidget::keyPressEvent( event );
 
  283       setCurrentCell( currentRow() + 1, currentColumn() );
 
  294       QTableWidget::keyPressEvent( event );
 
  298     d->setWeakEditorMode( 
true );
 
  305   qDeleteAll( mNumericFormats );
 
  306   mNumericFormats.clear();
 
  309   int rowNumber = mIncludeHeader ? 1 : 0;
 
  311   setRowCount( contents.size() + rowNumber );
 
  316       setColumnCount( row.size() );
 
  324       item->setData( CellContent, col.content() ); 
 
  325       item->setData( Qt::BackgroundRole, col.backgroundColor().isValid() ? col.backgroundColor() : QColor( 255, 255, 255 ) );
 
  326       item->setData( PresetBackgroundColorRole, col.backgroundColor().isValid() ? col.backgroundColor() : QVariant() );
 
  327       item->setData( Qt::ForegroundRole, col.textFormat().isValid() ? col.textFormat().color() : QVariant() );
 
  328       item->setData( TextFormat, QVariant::fromValue( col.textFormat() ) );
 
  329       item->setData( HorizontalAlignment, 
static_cast< int >( col.horizontalAlignment() ) );
 
  330       item->setData( VerticalAlignment, 
static_cast< int >( col.verticalAlignment() ) );
 
  331       item->setData( CellProperty, QVariant::fromValue( col.content().value< 
QgsProperty >() ) );
 
  334         item->setFlags( item->flags() & ( ~Qt::ItemIsEditable ) );
 
  336       if ( 
auto *lNumericFormat = col.numericFormat() )
 
  338         mNumericFormats.insert( item, lNumericFormat->clone() );
 
  339         item->setData( Qt::DisplayRole, mNumericFormats.value( item )->formatDouble( col.content().toDouble(), numericContext ) );
 
  341       setItem( rowNumber, colNumber, item );
 
  352     resizeColumnsToContents();
 
  353     resizeRowsToContents();
 
  362   items.reserve( rowCount() );
 
  364   for ( 
int r = mIncludeHeader ? 1 : 0; r < rowCount(); r++ )
 
  367     row.reserve( columnCount() );
 
  368     for ( 
int c = 0; 
c < columnCount(); 
c++ )
 
  371       if ( QTableWidgetItem *i = item( r, 
c ) )
 
  373         cell.
setContent( i->data( CellProperty ).value< 
QgsProperty >().isActive() ? i->data( CellProperty ) : i->data( CellContent ) );
 
  377         cell.
setVerticalAlignment( 
static_cast< Qt::Alignment 
>( i->data( VerticalAlignment ).toInt() ) );
 
  379         if ( mNumericFormats.value( i ) )
 
  384       row.push_back( cell );
 
  386     items.push_back( row );
 
  394   bool changed = 
false;
 
  396   std::unique_ptr< QgsNumericFormat > newFormat( format );
 
  397   const QModelIndexList selection = selectedIndexes();
 
  399   for ( 
const QModelIndex &index : selection )
 
  401     if ( index.row() == 0 && mIncludeHeader )
 
  404     QTableWidgetItem *i = item( index.row(), index.column() );
 
  407       i = 
new QTableWidgetItem();
 
  408       setItem( index.row(), index.column(), i );
 
  410     if ( !mNumericFormats.value( i ) && newFormat )
 
  413       mNumericFormats.insert( i, newFormat->clone() );
 
  415     else if ( mNumericFormats.value( i ) && !newFormat )
 
  418       delete mNumericFormats.value( i );
 
  419       mNumericFormats.remove( i );
 
  421     else if ( newFormat && *newFormat != *mNumericFormats.value( i ) )
 
  424       delete mNumericFormats.value( i );
 
  425       mNumericFormats.insert( i, newFormat->clone() );
 
  427     i->setData( Qt::DisplayRole, newFormat ? mNumericFormats.value( i )->formatDouble( i->data( CellContent ).toDouble(), numericContext ) : i->data( CellContent ) );
 
  430   if ( changed && !mBlockSignals )
 
  438   const QModelIndexList selection = selectedIndexes();
 
  439   for ( 
const QModelIndex &index : selection )
 
  441     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  445         f = mNumericFormats.value( i );
 
  448       else if ( ( !f && !mNumericFormats.value( i ) )
 
  449                 || ( f && mNumericFormats.value( i ) && *f == *mNumericFormats.value( i ) ) )
 
  468   const QModelIndexList selection = selectedIndexes();
 
  469   for ( 
const QModelIndex &index : selection )
 
  471     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  475         f = mNumericFormats.value( i );
 
  478       else if ( ( !f && !mNumericFormats.value( i ) )
 
  479                 || ( f && mNumericFormats.value( i ) && *f == *mNumericFormats.value( i ) ) )
 
  504   const QModelIndexList selection = selectedIndexes();
 
  505   for ( 
const QModelIndex &index : selection )
 
  507     QColor indexColor = model()->data( index, PresetBackgroundColorRole ).isValid() ? model()->data( index, PresetBackgroundColorRole ).value< QColor >() : QColor();
 
  513     else if ( indexColor == 
c )
 
  525   Qt::Alignment alignment = Qt::AlignLeft;
 
  527   const QModelIndexList selection = selectedIndexes();
 
  528   for ( 
const QModelIndex &index : selection )
 
  530     Qt::Alignment cellAlign = 
static_cast< Qt::Alignment 
>( model()->data( index, HorizontalAlignment ).toInt() );
 
  533       alignment = cellAlign;
 
  536     else if ( cellAlign == alignment )
 
  540       return Qt::AlignLeft | Qt::AlignTop;
 
  548   Qt::Alignment alignment = Qt::AlignVCenter;
 
  550   const QModelIndexList selection = selectedIndexes();
 
  551   for ( 
const QModelIndex &index : selection )
 
  553     Qt::Alignment cellAlign = 
static_cast< Qt::Alignment 
>( model()->data( index, VerticalAlignment ).toInt() );
 
  556       alignment = cellAlign;
 
  559     else if ( cellAlign == alignment )
 
  563       return Qt::AlignLeft | Qt::AlignTop;
 
  573   const QModelIndexList selection = selectedIndexes();
 
  574   for ( 
const QModelIndex &index : selection )
 
  579       property = cellProperty;
 
  582     else if ( cellProperty == property )
 
  596   const QModelIndexList selection = selectedIndexes();
 
  597   for ( 
const QModelIndex &index : selection )
 
  599     if ( !model()->data( index, TextFormat ).isValid() )
 
  608     else if ( cellFormat == format )
 
  620   const QModelIndexList selection = selectedIndexes();
 
  621   for ( 
const QModelIndex &index : selection )
 
  626     else if ( thisHeight != height )
 
  639   const QModelIndexList selection = selectedIndexes();
 
  640   for ( 
const QModelIndex &index : selection )
 
  645     else if ( thisWidth != width )
 
  657   for ( 
int col = 0; col < columnCount(); ++col )
 
  659     double thisHeight = model()->data( model()->index( row + ( mIncludeHeader ? 1 : 0 ), col ), RowHeight ).toDouble();
 
  660     height = std::max( thisHeight, height );
 
  668   for ( 
int row = 0; row < rowCount(); ++row )
 
  670     double thisWidth = model()->data( model()->index( row, column ), ColumnWidth ).toDouble();
 
  671     width = std::max( thisWidth, width );
 
  678   if ( row == 0 && mIncludeHeader )
 
  681   bool changed = 
false;
 
  684   for ( 
int col = 0; col < columnCount(); ++col )
 
  686     if ( QTableWidgetItem *i = item( row + ( mIncludeHeader ? 1 : 0 ), col ) )
 
  688       if ( i->data( RowHeight ).toDouble() != height )
 
  690         i->setData( RowHeight, height );
 
  696       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
  697       newItem->setData( RowHeight, height );
 
  698       setItem( row + ( mIncludeHeader ? 1 : 0 ), col, newItem );
 
  704   if ( changed && !mBlockSignals )
 
  710   bool changed = 
false;
 
  712   for ( 
int row = 0; row < rowCount(); ++row )
 
  714     if ( QTableWidgetItem *i = item( row, col ) )
 
  716       if ( i->data( ColumnWidth ).toDouble() != width )
 
  718         i->setData( ColumnWidth, width );
 
  724       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
  725       newItem->setData( ColumnWidth, width );
 
  726       setItem( row, col, newItem );
 
  731   if ( changed && !mBlockSignals )
 
  737   return collectUniqueRows( selectedIndexes() );
 
  742   return collectUniqueColumns( selectedIndexes() );
 
  747   if ( !mIncludeHeader )
 
  748     return QVariantList();
 
  751   res.reserve( columnCount() );
 
  752   for ( 
int col = 0; col < columnCount(); ++col )
 
  754     if ( QTableWidgetItem *i = item( 0, col ) )
 
  756       res << i->data( CellContent );
 
  768   if ( !mIncludeHeader )
 
  771   return collectUniqueRows( selectedIndexes() ).contains( 0 );
 
  776   if ( rowCount() == 0 )
 
  784   if ( !collectConsecutiveRowRange( selectedIndexes(), minRow, maxRow ) )
 
  787   const int rowsToInsert = maxRow - minRow + 1;
 
  788   for ( 
int i = 0; i < rowsToInsert; ++i )
 
  789     insertRow( maxRow + 1 );
 
  792   if ( !mBlockSignals )
 
  798   if ( rowCount() == 0 )
 
  806   if ( !collectConsecutiveRowRange( selectedIndexes(), minRow, maxRow ) )
 
  809   const int rowsToInsert = maxRow - minRow + 1;
 
  810   for ( 
int i = 0; i < rowsToInsert; ++i )
 
  814   if ( !mBlockSignals )
 
  820   if ( columnCount() == 0 )
 
  828   if ( !collectConsecutiveColumnRange( selectedIndexes(), minColumn, maxColumn ) )
 
  831   const int columnsToInsert = maxColumn - minColumn + 1;
 
  832   for ( 
int i = 0; i < columnsToInsert; ++i )
 
  833     insertColumn( minColumn );
 
  836   if ( !mBlockSignals )
 
  842   if ( columnCount() == 0 )
 
  850   if ( !collectConsecutiveColumnRange( selectedIndexes(), minColumn, maxColumn ) )
 
  853   const int columnsToInsert = maxColumn - minColumn + 1;
 
  854   for ( 
int i = 0; i < columnsToInsert; ++i )
 
  855     insertColumn( maxColumn + 1 );
 
  858   if ( !mBlockSignals )
 
  868   bool changed = 
false;
 
  869   for ( 
int i = rows.size() - 1; i >= 0 && rowCount() > 1; i-- )
 
  871     removeRow( rows.at( i ) );
 
  875   if ( changed &&  !mBlockSignals )
 
  882   if ( columns.empty() )
 
  885   bool changed = 
false;
 
  886   for ( 
int i = columns.size() - 1; i >= 0 && columnCount() > 1; i-- )
 
  888     removeColumn( columns.at( i ) );
 
  892   if ( !mBlockSignals && changed )
 
  898   const QModelIndexList s = selectedIndexes();
 
  899   for ( 
const QModelIndex &index : s )
 
  901     selectionModel()->select( index, QItemSelectionModel::Rows | QItemSelectionModel::Select );
 
  907   const QModelIndexList s = selectedIndexes();
 
  908   for ( 
const QModelIndex &index : s )
 
  910     selectionModel()->select( index, QItemSelectionModel::Columns | QItemSelectionModel::Select );
 
  916   const QModelIndexList selection = selectedIndexes();
 
  917   bool changed = 
false;
 
  919   for ( 
const QModelIndex &index : selection )
 
  921     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  923       i->setText( QString() );
 
  924       i->setData( CellContent, QVariant() );
 
  929   if ( changed && !mBlockSignals )
 
  935   const QModelIndexList selection = selectedIndexes();
 
  936   bool changed = 
false;
 
  938   for ( 
const QModelIndex &index : selection )
 
  940     if ( index.row() == 0 && mIncludeHeader )
 
  943     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  945       if ( i->data( Qt::ForegroundRole ).value< QColor >() != color )
 
  947         i->setData( Qt::ForegroundRole, color.isValid() ? color : QVariant() );
 
  950         i->setData( TextFormat, QVariant::fromValue( f ) );
 
  956       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
  957       newItem->setData( Qt::ForegroundRole, color.isValid() ? color : QVariant() );
 
  960       newItem->setData( TextFormat, QVariant::fromValue( f ) );
 
  961       setItem( index.row(), index.column(), newItem );
 
  966   if ( changed && !mBlockSignals )
 
  972   const QModelIndexList selection = selectedIndexes();
 
  973   bool changed = 
false;
 
  975   for ( 
const QModelIndex &index : selection )
 
  977     if ( index.row() == 0 && mIncludeHeader )
 
  980     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
  982       if ( i->data( PresetBackgroundColorRole ).value< QColor >() != color )
 
  984         i->setData( Qt::BackgroundRole, color.isValid() ? color : QVariant() );
 
  985         i->setData( PresetBackgroundColorRole, color.isValid() ? color : QVariant() );
 
  991       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
  992       newItem->setData( Qt::BackgroundRole, color.isValid() ? color : QVariant() );
 
  993       newItem->setData( PresetBackgroundColorRole, color.isValid() ? color : QVariant() );
 
  994       setItem( index.row(), index.column(), newItem );
 
  999   if ( changed && !mBlockSignals )
 
 1005   const QModelIndexList selection = selectedIndexes();
 
 1006   bool changed = 
false;
 
 1008   for ( 
const QModelIndex &index : selection )
 
 1010     if ( index.row() == 0 && mIncludeHeader )
 
 1013     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
 1015       if ( 
static_cast< Qt::Alignment 
>( i->data( HorizontalAlignment ).toInt() ) != alignment )
 
 1017         i->setData( HorizontalAlignment, 
static_cast< int >( alignment ) );
 
 1023       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
 1024       newItem->setData( HorizontalAlignment, 
static_cast< int >( alignment ) );
 
 1025       setItem( index.row(), index.column(), newItem );
 
 1030   if ( changed && !mBlockSignals )
 
 1036   const QModelIndexList selection = selectedIndexes();
 
 1037   bool changed = 
false;
 
 1039   for ( 
const QModelIndex &index : selection )
 
 1041     if ( index.row() == 0 && mIncludeHeader )
 
 1044     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
 1046       if ( 
static_cast< Qt::Alignment 
>( i->data( HorizontalAlignment ).toInt() ) != alignment )
 
 1048         i->setData( VerticalAlignment, 
static_cast< int >( alignment ) );
 
 1054       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
 1055       newItem->setData( VerticalAlignment, 
static_cast< int >( alignment ) );
 
 1056       setItem( index.row(), index.column(), newItem );
 
 1061   if ( changed && !mBlockSignals )
 
 1067   const QModelIndexList selection = selectedIndexes();
 
 1068   bool changed = 
false;
 
 1070   for ( 
const QModelIndex &index : selection )
 
 1072     if ( index.row() == 0 && mIncludeHeader )
 
 1075     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
 1077       if ( i->data( CellProperty ).value< 
QgsProperty >() != property )
 
 1081           i->setData( CellProperty, QVariant::fromValue( property ) );
 
 1083           i->setFlags( i->flags() & ( ~Qt::ItemIsEditable ) );
 
 1087           i->setData( CellProperty, QVariant() );
 
 1088           i->setText( QString() );
 
 1089           i->setFlags( i->flags() | Qt::ItemIsEditable );
 
 1096       QTableWidgetItem *newItem = 
new QTableWidgetItem( property.
asExpression() );
 
 1099         newItem->setData( CellProperty,  QVariant::fromValue( property ) );
 
 1100         newItem->setFlags( newItem->flags() & ( ~Qt::ItemIsEditable ) );
 
 1104         newItem->setData( CellProperty, QVariant() );
 
 1105         newItem->setFlags( newItem->flags() | Qt::ItemIsEditable );
 
 1107       setItem( index.row(), index.column(), newItem );
 
 1112   if ( changed && !mBlockSignals )
 
 1118   const QModelIndexList selection = selectedIndexes();
 
 1119   bool changed = 
false;
 
 1121   for ( 
const QModelIndex &index : selection )
 
 1123     if ( index.row() == 0 && mIncludeHeader )
 
 1126     if ( QTableWidgetItem *i = item( index.row(), index.column() ) )
 
 1128       i->setData( TextFormat, QVariant::fromValue( format ) );
 
 1129       i->setData( Qt::ForegroundRole, format.
color() );
 
 1134       QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
 1135       newItem->setData( TextFormat, QVariant::fromValue( format ) );
 
 1136       newItem->setData( Qt::ForegroundRole, format.
color() );
 
 1137       setItem( index.row(), index.column(), newItem );
 
 1142   if ( changed && !mBlockSignals )
 
 1148   bool changed = 
false;
 
 1151   for ( 
int row : rows )
 
 1153     if ( row == 0 && mIncludeHeader )
 
 1156     for ( 
int col = 0; col < columnCount(); ++col )
 
 1158       if ( QTableWidgetItem *i = item( row, col ) )
 
 1160         if ( i->data( RowHeight ).toDouble() != height )
 
 1162           i->setData( RowHeight, height );
 
 1168         QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
 1169         newItem->setData( RowHeight, height );
 
 1170         setItem( row, col, newItem );
 
 1176   if ( changed && !mBlockSignals )
 
 1182   bool changed = 
false;
 
 1185   for ( 
int col : cols )
 
 1187     for ( 
int row = 0; row < rowCount(); ++row )
 
 1189       if ( QTableWidgetItem *i = item( row, col ) )
 
 1191         if ( i->data( ColumnWidth ).toDouble() != width )
 
 1193           i->setData( ColumnWidth, width );
 
 1199         QTableWidgetItem *newItem = 
new QTableWidgetItem();
 
 1200         newItem->setData( ColumnWidth, width );
 
 1201         setItem( row, col, newItem );
 
 1207   if ( changed && !mBlockSignals )
 
 1213   if ( included == mIncludeHeader )
 
 1216   mIncludeHeader = included;
 
 1218   if ( mIncludeHeader )
 
 1227   if ( !mIncludeHeader )
 
 1232   for ( 
int col = 0; col < columnCount(); ++col )
 
 1234     if ( QTableWidgetItem *i = item( 0, col ) )
 
 1236       i->setText( headers.value( col ).toString() );
 
 1237       i->setData( CellContent, headers.value( col ) ); 
 
 1241       QTableWidgetItem *item = 
new QTableWidgetItem( headers.value( col ).toString() );
 
 1242       item->setData( CellContent, headers.value( col ) ); 
 
 1243       setItem( 0, col, item );
 
 1251 QgsTableEditorTextEdit::QgsTableEditorTextEdit( QWidget *parent )
 
 1252   : QPlainTextEdit( parent )
 
 1255   document()->setDocumentMargin( document()->documentMargin() / 2 );
 
 1257   connect( 
this, &QPlainTextEdit::textChanged, 
this, &QgsTableEditorTextEdit::resizeToContents );
 
 1258   updateMinimumSize();
 
 1261 void QgsTableEditorTextEdit::keyPressEvent( QKeyEvent *event )
 
 1263   switch ( event->key() )
 
 1266     case Qt::Key_Return:
 
 1268       if ( event->modifiers() & Qt::ControlModifier )
 
 1271         insertPlainText( QString( 
'\n' ) );
 
 1287       if ( mWeakEditorMode )
 
 1294         QPlainTextEdit::keyPressEvent( event );
 
 1301       if ( event->modifiers() & Qt::ControlModifier )
 
 1305         insertPlainText( QString( 
'\t' ) );
 
 1316       QPlainTextEdit::keyPressEvent( event );
 
 1320 void QgsTableEditorTextEdit::updateMinimumSize()
 
 1322   const double tm = document()->documentMargin();
 
 1323   const QMargins cm = contentsMargins();
 
 1324   const int width = tm * 2 + cm.left() + cm.right() + 30;
 
 1325   const int height = tm * 2 + cm.top() + cm.bottom() + 4;
 
 1326   QStyleOptionFrame opt;
 
 1327   initStyleOption( &opt );
 
 1328   const QSize sizeFromContent = style()->sizeFromContents( QStyle::CT_LineEdit, &opt, QSize( width, height ), 
this );
 
 1329   setMinimumWidth( sizeFromContent.width() );
 
 1330   setMinimumHeight( sizeFromContent.height() );
 
 1333 void QgsTableEditorTextEdit::setWeakEditorMode( 
bool weakEditorMode )
 
 1335   mWeakEditorMode = weakEditorMode;
 
 1338 void QgsTableEditorTextEdit::resizeToContents()
 
 1340   int oldWidth = width();
 
 1341   int oldHeight = height();
 
 1342   if ( mOriginalWidth == -1 )
 
 1343     mOriginalWidth = oldWidth;
 
 1344   if ( mOriginalHeight == -1 )
 
 1345     mOriginalHeight = oldHeight;
 
 1347   if ( QWidget *parent = parentWidget() )
 
 1349     QPoint position = pos();
 
 1350     QFontMetrics fm( font() );
 
 1352     const QStringList lines = toPlainText().split( 
'\n' );
 
 1353     int maxTextLineWidth = 0;
 
 1354     int totalTextHeight = 0;
 
 1355     for ( 
const QString &line : lines )
 
 1357       const QRect bounds = fontMetrics().boundingRect( line );
 
 1358       maxTextLineWidth = std::max( maxTextLineWidth, bounds.width() );
 
 1359       totalTextHeight += fm.height();
 
 1362     int hintWidth = minimumWidth() + maxTextLineWidth;
 
 1363     int hintHeight = minimumHeight() + totalTextHeight;
 
 1364     int parentWidth = parent->width();
 
 1365     int maxWidth = isRightToLeft() ? position.x() + oldWidth : parentWidth - position.x();
 
 1366     int maxHeight = parent->height() - position.y();
 
 1367     int newWidth = std::clamp( hintWidth, mOriginalWidth, maxWidth );
 
 1368     int newHeight = std::clamp( hintHeight, mOriginalHeight, maxHeight );
 
 1370     if ( mWidgetOwnsGeometry )
 
 1372       setMaximumWidth( newWidth );
 
 1373       setMaximumHeight( newHeight );
 
 1375     if ( isRightToLeft() )
 
 1376       move( position.x() - newWidth + oldWidth, position.y() );
 
 1377     resize( newWidth, newHeight );
 
 1381 void QgsTableEditorTextEdit::changeEvent( QEvent *e )
 
 1383   switch ( e->type() )
 
 1385     case QEvent::FontChange:
 
 1386     case QEvent::StyleChange:
 
 1387     case QEvent::ContentsRectChange:
 
 1388       updateMinimumSize();
 
 1393   QPlainTextEdit::changeEvent( e );
 
 1396 QgsTableEditorDelegate::QgsTableEditorDelegate( QObject *parent )
 
 1397   : QStyledItemDelegate( parent )
 
 1402 void QgsTableEditorDelegate::setWeakEditorMode( 
bool weakEditorMode )
 
 1404   mWeakEditorMode = weakEditorMode;
 
 1407 QWidget *QgsTableEditorDelegate::createEditor( QWidget *parent, 
const QStyleOptionViewItem &, 
const QModelIndex & )
 const 
 1409   QgsTableEditorTextEdit *w = 
new QgsTableEditorTextEdit( parent );
 
 1410   w->setWeakEditorMode( mWeakEditorMode );
 
 1412   if ( !w->style()->styleHint( QStyle::SH_ItemView_DrawDelegateFrame, 0, w ) )
 
 1413     w->setFrameShape( QFrame::NoFrame );
 
 1414   if ( !w->style()->styleHint( QStyle::SH_ItemView_ShowDecorationSelected, 0, w ) )
 
 1415     w->setWidgetOwnsGeometry( 
true );
 
 1420 void QgsTableEditorDelegate::setEditorData( QWidget *editor, 
const QModelIndex &index )
 const 
 1422   QVariant value = index.model()->data( index, QgsTableEditorWidget::CellContent );
 
 1423   if ( QgsTableEditorTextEdit *lineEdit = qobject_cast<QgsTableEditorTextEdit * >( editor ) )
 
 1425     if ( index != mLastIndex || lineEdit->toPlainText() != value.toString() )
 
 1427       lineEdit->setPlainText( value.toString() );
 
 1428       lineEdit->selectAll();
 
 1434 void QgsTableEditorDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, 
const QModelIndex &index )
 const 
 1436   if ( QgsTableEditorTextEdit *lineEdit = qobject_cast<QgsTableEditorTextEdit * >( editor ) )
 
 1438     const QString text = lineEdit->toPlainText();
 
 1439     if ( text != model->data( index, QgsTableEditorWidget::CellContent ).toString() && !model->data( index, QgsTableEditorWidget::CellProperty ).value< 
QgsProperty >().
isActive() )
 
 1441       model->setData( index, text, QgsTableEditorWidget::CellContent );
 
 1442       model->setData( index, text, Qt::DisplayRole );
 
 1443       emit updateNumericFormatForIndex( index );
 
A context for numeric formats.
A store for object properties.
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
bool isActive() const
Returns whether the property is currently active.
Encapsulates the contents and formatting of a single table cell.
void setHorizontalAlignment(Qt::Alignment alignment)
Sets the horizontal alignment for text in the cell.
void setVerticalAlignment(Qt::Alignment alignment)
Sets the vertical alignment for text in the cell.
void setBackgroundColor(const QColor &color)
Sets the cell's background color.
void setTextFormat(const QgsTextFormat &format)
Sets the cell's text format.
void setContent(const QVariant &content)
Sets the cell's content.
void setNumericFormat(QgsNumericFormat *format)
Sets the numeric format used for numbers in the cell, or nullptr if no specific format is set.
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
bool isValid() const
Returns true if the format is valid.
QColor color() const
Returns the color that text will be rendered in.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QVector< QgsTableRow > QgsTableContents
A set of table rows.
QVector< QgsTableCell > QgsTableRow
A row of table cells.