QGIS API Documentation 3.27.0-Master (75dc696944)
qgslayoutattributeselectiondialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgslayoutattributeselectiondialog.cpp
3 -------------------------------------
4 begin : November 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
20#include "qgsvectorlayer.h"
22#include "qgsdoublespinbox.h"
23#include "qgssettings.h"
24#include "qgsgui.h"
26#include "qgshelp.h"
27
28#include <QCheckBox>
29#include <QDialogButtonBox>
30#include <QGridLayout>
31#include <QLabel>
32#include <QLineEdit>
33#include <QPushButton>
34#include <QSpinBox>
35#include <QSortFilterProxyModel>
36
37
38
39// QgsLayoutAttributeTableColumnModelBase
40
42 : QAbstractTableModel( parent )
43 , mTable( table )
44{
45}
46
47QModelIndex QgsLayoutAttributeTableColumnModelBase::index( int row, int column, const QModelIndex &parent ) const
48{
49 if ( !hasIndex( row, column, parent ) )
50 return QModelIndex();
51
52 if ( !parent.isValid() )
53 {
54 return createIndex( row, column );
55 }
56
57 return QModelIndex();
58}
59
60QModelIndex QgsLayoutAttributeTableColumnModelBase::parent( const QModelIndex &child ) const
61{
62 Q_UNUSED( child )
63 return QModelIndex();
64}
65
66int QgsLayoutAttributeTableColumnModelBase::rowCount( const QModelIndex &parent ) const
67{
68 if ( parent.isValid() )
69 return 0;
70
71 return columns().length();
72}
73
74int QgsLayoutAttributeTableColumnModelBase::columnCount( const QModelIndex &parent ) const
75{
76 Q_UNUSED( parent )
77 return displayedColumns().count();
78}
79
80QVariant QgsLayoutAttributeTableColumnModelBase::data( const QModelIndex &index, int role ) const
81{
82 if ( !index.isValid() ||
83 ( role != Qt::DisplayRole && role != Qt::EditRole && role != Qt::UserRole ) )
84 {
85 return QVariant();
86 }
87
88 if ( index.row() >= columns().length() )
89 {
90 return QVariant();
91 }
92
93 // get layout column for index
94 const QgsLayoutTableColumn column = columns().value( index.row() );
95
96 const Column col = displayedColumns()[index.column()];
97 switch ( col )
98 {
99 case Attribute:
100 return column.attribute();
101 case Heading:
102 return column.heading();
103 case Alignment:
104 {
105 if ( role == Qt::DisplayRole )
106 {
107 switch ( column.hAlignment() )
108 {
109 case Qt::AlignHCenter:
110 switch ( column.vAlignment() )
111 {
112 case Qt::AlignTop:
113 return tr( "Top center" );
114 case Qt::AlignBottom:
115 return tr( "Bottom center" );
116 default:
117 return tr( "Middle center" );
118 }
119 case Qt::AlignRight:
120 switch ( column.vAlignment() )
121 {
122 case Qt::AlignTop:
123 return tr( "Top right" );
124 case Qt::AlignBottom:
125 return tr( "Bottom right" );
126 default:
127 return tr( "Middle right" );
128 }
129 case Qt::AlignLeft:
130 default:
131 switch ( column.vAlignment() )
132 {
133 case Qt::AlignTop:
134 return tr( "Top left" );
135 case Qt::AlignBottom:
136 return tr( "Bottom left" );
137 default:
138 return tr( "Middle left" );
139 }
140 }
141 }
142 else
143 {
144 //edit role
145 return int( column.hAlignment() | column.vAlignment() );
146 }
147 }
148 case Width:
149 {
150 if ( role == Qt::DisplayRole )
151 {
152 return column.width() <= 0 ? tr( "Automatic" ) : tr( "%1 mm" ).arg( column.width(), 0, 'f', 2 );
153 }
154 else
155 {
156 //edit role
157 return column.width();
158 }
159 }
160 case SortOrder:
161 if ( role == Qt::DisplayRole )
162 {
163 switch ( column.sortOrder() )
164 {
165 case Qt::DescendingOrder:
166 return tr( "Descending" );
167 case Qt::AscendingOrder:
168 default:
169 return tr( "Ascending" );
170 }
171 }
172 else
173 {
174 //edit role
175 return column.sortOrder();
176 }
177 }
178
179 return QVariant();
180}
181
182QVariant QgsLayoutAttributeTableColumnModelBase::headerData( int section, Qt::Orientation orientation, int role ) const
183{
184 if ( !mTable )
185 {
186 return QVariant();
187 }
188
189 if ( role == Qt::DisplayRole )
190 {
191 if ( orientation == Qt::Vertical ) //row
192 {
193 return QVariant( section );
194 }
195 else
196 {
197 const Column col = displayedColumns()[section];
198 switch ( col )
199 {
200 case Attribute:
201 return QVariant( tr( "Attribute" ) );
202
203 case Heading:
204 return QVariant( tr( "Heading" ) );
205
206 case Alignment:
207 return QVariant( tr( "Alignment" ) );
208
209 case Width:
210 return QVariant( tr( "Width" ) );
211
212 case SortOrder:
213 return QVariant( tr( "Sort Order" ) );
214 }
215 }
216 }
217
218 return QVariant();
219}
220
221bool QgsLayoutAttributeTableColumnModelBase::setData( const QModelIndex &index, const QVariant &value, int role )
222{
223 if ( !index.isValid() || role != Qt::EditRole || !mTable )
224 return false;
225
226 if ( index.row() >= columns().length() )
227 return false;
228
229 if ( index.column() > displayedColumns().count() )
230 return false;
231
232 QgsLayoutTableColumn &colToUpdate = columns()[index.row()];
233
234 const Column col = displayedColumns()[index.column()];
235 switch ( col )
236 {
237 case Attribute:
238 // also update column's heading, if it hasn't been customized
239 if ( colToUpdate.heading().isEmpty() || ( colToUpdate.heading() == colToUpdate.attribute() ) )
240 {
241 colToUpdate.setHeading( value.toString() );
242 emit dataChanged( createIndex( index.row(), 1 ), createIndex( index.row(), 1 ) );
243 }
244 colToUpdate.setAttribute( value.toString() );
245 emit dataChanged( index, index );
246 return true;
247
248 case Heading:
249 colToUpdate.setHeading( value.toString() );
250 emit dataChanged( index, index );
251 return true;
252
253 case Alignment:
254 colToUpdate.setHAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignHorizontal_Mask ) );
255 colToUpdate.setVAlignment( Qt::AlignmentFlag( value.toInt() & Qt::AlignVertical_Mask ) );
256 emit dataChanged( index, index );
257 return true;
258
259 case Width:
260 colToUpdate.setWidth( value.toDouble() );
261 emit dataChanged( index, index );
262 return true;
263
264 case SortOrder:
265 colToUpdate.setSortOrder( static_cast< Qt::SortOrder >( value.toInt() ) );
266 emit dataChanged( index, index );
267 return true;
268 }
269
270 return false;
271}
272
273Qt::ItemFlags QgsLayoutAttributeTableColumnModelBase::flags( const QModelIndex &index ) const
274{
275 Qt::ItemFlags flags = QAbstractTableModel::flags( index );
276
277 if ( index.isValid() )
278 {
279 return flags | Qt::ItemIsEditable;
280 }
281 else
282 {
283 return flags;
284 }
285}
286
287bool QgsLayoutAttributeTableColumnModelBase::removeRows( int row, int count, const QModelIndex &parent )
288{
289 Q_UNUSED( parent )
290
291 const int maxRow = std::min< int >( row + count - 1, columns().length() - 1 );
292 beginRemoveRows( QModelIndex(), row, maxRow );
293 //move backwards through rows, removing each corresponding QgsComposerTableColumn
294 for ( int i = maxRow; i >= row; --i )
295 {
296 columns().removeAt( i );
297 }
298 endRemoveRows();
299 return true;
300}
301
302bool QgsLayoutAttributeTableColumnModelBase::insertRows( int row, int count, const QModelIndex &parent )
303{
304 Q_UNUSED( parent )
305 beginInsertRows( QModelIndex(), row, row + count - 1 );
306 //create new QgsComposerTableColumns for each inserted row
307 for ( int i = row; i < row + count; ++i )
308 {
309 columns().insert( i, QgsLayoutTableColumn() );
310 }
311 endInsertRows();
312 return true;
313}
314
316{
317 if ( ( direction == ShiftUp && row <= 0 ) ||
318 ( direction == ShiftDown && row >= rowCount() - 1 ) )
319 {
320 //row is already at top/bottom
321 return false;
322 }
323
324 //we shift a row by removing the next row up/down, then reinserting it before/after the target row
325 const int swapWithRow = direction == ShiftUp ? row - 1 : row + 1;
326
327 //remove row
328 beginRemoveRows( QModelIndex(), swapWithRow, swapWithRow );
329 const QgsLayoutTableColumn temp = columns().takeAt( swapWithRow );
330 endRemoveRows();
331
332 //insert row
333 beginInsertRows( QModelIndex(), row, row );
334 columns().insert( row, temp );
335 endInsertRows();
336
337 return true;
338}
339
340// QgsLayoutAttributeTableColumnModel
341
342QVector<QgsLayoutTableColumn> &QgsLayoutAttributeTableColumnModel::columns() const
343{
344 return mTable->columns();
345}
346
348{
349 beginResetModel();
351 endResetModel();
352}
353
354
355// QgsLayoutTableSortModel
356
357QVector<QgsLayoutTableColumn> &QgsLayoutTableSortModel::columns() const
358{
359 return mTable->sortColumns();
360}
361
362// QgsLayoutColumnAlignmentDelegate
363
365{
366
367}
368
369QWidget *QgsLayoutColumnAlignmentDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
370{
371 Q_UNUSED( option )
372 Q_UNUSED( index )
373
374 //create a combo box showing alignment options
375 QComboBox *comboBox = new QComboBox( parent );
376
377 comboBox->addItem( tr( "Top Left" ), int( Qt::AlignTop | Qt::AlignLeft ) );
378 comboBox->addItem( tr( "Top Center" ), int( Qt::AlignTop | Qt::AlignHCenter ) );
379 comboBox->addItem( tr( "Top Right" ), int( Qt::AlignTop | Qt::AlignRight ) );
380 comboBox->addItem( tr( "Middle Left" ), int( Qt::AlignVCenter | Qt::AlignLeft ) );
381 comboBox->addItem( tr( "Middle Center" ), int( Qt::AlignVCenter | Qt::AlignHCenter ) );
382 comboBox->addItem( tr( "Middle Right" ), int( Qt::AlignVCenter | Qt::AlignRight ) );
383 comboBox->addItem( tr( "Bottom Left" ), int( Qt::AlignBottom | Qt::AlignLeft ) );
384 comboBox->addItem( tr( "Bottom Center" ), int( Qt::AlignBottom | Qt::AlignHCenter ) );
385 comboBox->addItem( tr( "Bottom Right" ), int( Qt::AlignBottom | Qt::AlignRight ) );
386
387 const Qt::AlignmentFlag alignment = ( Qt::AlignmentFlag )index.model()->data( index, Qt::EditRole ).toInt();
388 comboBox->setCurrentIndex( comboBox->findData( alignment ) );
389
390 return comboBox;
391}
392
393void QgsLayoutColumnAlignmentDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
394{
395 const Qt::AlignmentFlag alignment = ( Qt::AlignmentFlag )index.model()->data( index, Qt::EditRole ).toInt();
396
397 //set the value for the combobox
398 QComboBox *comboBox = static_cast<QComboBox *>( editor );
399 comboBox->setCurrentIndex( comboBox->findData( alignment ) );
400}
401
402void QgsLayoutColumnAlignmentDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
403{
404 QComboBox *comboBox = static_cast<QComboBox *>( editor );
405 const Qt::AlignmentFlag alignment = ( Qt::AlignmentFlag ) comboBox->currentData().toInt();
406 model->setData( index, alignment, Qt::EditRole );
407}
408
409void QgsLayoutColumnAlignmentDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
410{
411 Q_UNUSED( index )
412 editor->setGeometry( option.rect );
413}
414
415
416// QgsLayoutColumnSourceDelegate
417
418QgsLayoutColumnSourceDelegate::QgsLayoutColumnSourceDelegate( QgsVectorLayer *vlayer, QObject *parent, const QgsLayoutObject *layoutObject, bool forceExpressions )
419 : QItemDelegate( parent )
420 , mVectorLayer( vlayer )
421 , mLayoutObject( layoutObject )
422 , mForceExpressions( forceExpressions )
423{
424
425}
426
427QgsExpressionContext QgsLayoutColumnSourceDelegate::createExpressionContext() const
428{
429 if ( !mLayoutObject )
430 {
431 return QgsExpressionContext();
432 }
433
434 QgsExpressionContext expContext = mLayoutObject->createExpressionContext();
435 expContext.lastScope()->addVariable( QgsExpressionContextScope::StaticVariable( QStringLiteral( "row_number" ), 1, true ) );
436 expContext.setHighlightedVariables( QStringList() << QStringLiteral( "row_number" ) );
437 return expContext;
438}
439
440QWidget *QgsLayoutColumnSourceDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
441{
442 Q_UNUSED( option )
443 Q_UNUSED( index )
444
445 QgsFieldExpressionWidget *fieldExpression = new QgsFieldExpressionWidget( parent );
446 fieldExpression->setLayer( mVectorLayer );
447 fieldExpression->registerExpressionContextGenerator( this );
448
449 //listen out for field changes
450 connect( fieldExpression, static_cast < void ( QgsFieldExpressionWidget::* )( const QString & ) >( &QgsFieldExpressionWidget::fieldChanged ), this, [ = ] { const_cast< QgsLayoutColumnSourceDelegate * >( this )->commitAndCloseEditor(); } );
451 return fieldExpression;
452}
453
454void QgsLayoutColumnSourceDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
455{
456 const QString field = index.model()->data( index, Qt::EditRole ).toString();
457
458 //set the value for the field combobox
459 QgsFieldExpressionWidget *fieldExpression = static_cast<QgsFieldExpressionWidget *>( editor );
460 fieldExpression->setField( field );
461}
462
463void QgsLayoutColumnSourceDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
464{
465 QgsFieldExpressionWidget *fieldExpression = static_cast<QgsFieldExpressionWidget *>( editor );
466 const QString field = mForceExpressions ? fieldExpression->asExpression() : fieldExpression->currentField();
467
468 model->setData( index, field, Qt::EditRole );
469}
470
471void QgsLayoutColumnSourceDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
472{
473 Q_UNUSED( index )
474 editor->setGeometry( option.rect );
475}
476
477void QgsLayoutColumnSourceDelegate::commitAndCloseEditor()
478{
479 QgsFieldExpressionWidget *fieldExpression = qobject_cast<QgsFieldExpressionWidget *>( sender() );
480 emit commitData( fieldExpression );
481}
482
483
484// QgsLayoutColumnSortOrderDelegate
485
487{
488
489}
490
491QWidget *QgsLayoutColumnSortOrderDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
492{
493 Q_UNUSED( option )
494 Q_UNUSED( index )
495
496 QComboBox *comboBox = new QComboBox( parent );
497 QStringList sortOrders;
498 sortOrders << tr( "Ascending" ) << tr( "Descending" );
499 comboBox->addItems( sortOrders );
500 return comboBox;
501}
502
503void QgsLayoutColumnSortOrderDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
504{
505 const Qt::SortOrder order = ( Qt::SortOrder )index.model()->data( index, Qt::EditRole ).toInt();
506
507 //set the value for the combobox
508 QComboBox *comboBox = static_cast<QComboBox *>( editor );
509 switch ( order )
510 {
511 case Qt::DescendingOrder:
512 comboBox->setCurrentIndex( 1 );
513 break;
514 case Qt::AscendingOrder:
515 default:
516 comboBox->setCurrentIndex( 0 );
517 break;
518 }
519}
520
521void QgsLayoutColumnSortOrderDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
522{
523 QComboBox *comboBox = static_cast<QComboBox *>( editor );
524 const int value = comboBox->currentIndex();
525 Qt::SortOrder order;
526 switch ( value )
527 {
528 case 1:
529 order = Qt::DescendingOrder;
530 break;
531 case 0:
532 default:
533 order = Qt::AscendingOrder;
534 break;
535 }
536
537 model->setData( index, order, Qt::EditRole );
538}
539
540void QgsLayoutColumnSortOrderDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
541{
542 Q_UNUSED( index )
543 editor->setGeometry( option.rect );
544}
545
546
547//
548// QgsLayoutColumnWidthDelegate
549//
550
552 : QItemDelegate( parent )
553{
554
555}
556
557QWidget *QgsLayoutColumnWidthDelegate::createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const
558{
559 Q_UNUSED( index )
560 Q_UNUSED( option )
561 QgsDoubleSpinBox *editor = new QgsDoubleSpinBox( parent );
562 editor->setMinimum( 0 );
563 editor->setMaximum( 1000 );
564 editor->setDecimals( 2 );
565 editor->setSuffix( tr( " mm" ) );
566 editor->setSpecialValueText( tr( "Automatic" ) );
567 editor->setShowClearButton( true );
568 return editor;
569}
570
571void QgsLayoutColumnWidthDelegate::setEditorData( QWidget *editor, const QModelIndex &index ) const
572{
573 const int value = index.model()->data( index, Qt::EditRole ).toInt();
574
575 QgsDoubleSpinBox *spinBox = static_cast<QgsDoubleSpinBox *>( editor );
576 spinBox->setValue( value );
577}
578
579void QgsLayoutColumnWidthDelegate::setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const
580{
581 QgsDoubleSpinBox *spinBox = static_cast<QgsDoubleSpinBox *>( editor );
582 spinBox->interpretText();
583 const int value = spinBox->value();
584
585 model->setData( index, value, Qt::EditRole );
586}
587
588void QgsLayoutColumnWidthDelegate::updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const
589{
590 Q_UNUSED( index )
591 editor->setGeometry( option.rect );
592}
593
594
595// QgsLayoutAttributeSelectionDialog
596
598 QWidget *parent, Qt::WindowFlags f )
599 : QDialog( parent, f )
600 , mTable( table )
601 , mVectorLayer( vLayer )
602
603{
604 setupUi( this );
606
607 connect( mRemoveColumnPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mRemoveColumnPushButton_clicked );
608 connect( mAddColumnPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mAddColumnPushButton_clicked );
609 connect( mColumnUpPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mColumnUpPushButton_clicked );
610 connect( mColumnDownPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mColumnDownPushButton_clicked );
611 connect( mResetColumnsPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mResetColumnsPushButton_clicked );
612 connect( mClearColumnsPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mClearColumnsPushButton_clicked );
613 connect( mAddSortColumnPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mAddSortColumnPushButton_clicked );
614 connect( mRemoveSortColumnPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mRemoveSortColumnPushButton_clicked );
615 connect( mSortColumnUpPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mSortColumnUpPushButton_clicked );
616 connect( mSortColumnDownPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeSelectionDialog::mSortColumnDownPushButton_clicked );
617 connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsLayoutAttributeSelectionDialog::showHelp );
618
619 if ( mTable )
620 {
621 //set up models, views and delegates
622 mColumnModel = new QgsLayoutAttributeTableColumnModel( mTable, mColumnsTableView );
623 mColumnsTableView->setModel( mColumnModel );
624 mColumnsTableView->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
625 mColumnSourceDelegate = new QgsLayoutColumnSourceDelegate( vLayer, mColumnsTableView, mTable );
626 mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate );
627 mColumnAlignmentDelegate = new QgsLayoutColumnAlignmentDelegate( mColumnsTableView );
628 mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate );
629 mColumnWidthDelegate = new QgsLayoutColumnWidthDelegate( mColumnsTableView );
630 mColumnsTableView->setItemDelegateForColumn( 3, mColumnWidthDelegate );
631
632 mSortColumnModel = new QgsLayoutTableSortModel( mTable, mSortColumnTableView );
633 mSortColumnTableView->setModel( mSortColumnModel );
634 mSortColumnTableView->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
635 mSortColumnSourceDelegate = new QgsLayoutColumnSourceDelegate( vLayer, mSortColumnTableView, mTable, true );
636 mSortColumnTableView->setItemDelegateForColumn( 0, mSortColumnSourceDelegate );
637 mSortColumnOrderDelegate = new QgsLayoutColumnSortOrderDelegate( mSortColumnTableView );
638 mSortColumnTableView->setItemDelegateForColumn( 1, mSortColumnOrderDelegate );
639 }
640}
641
642void QgsLayoutAttributeSelectionDialog::mRemoveColumnPushButton_clicked()
643{
644 //remove selected rows from model
645 const QModelIndexList indexes = mColumnsTableView->selectionModel()->selectedRows();
646 const int count = indexes.count();
647
648 for ( int i = count; i > 0; --i )
649 mColumnModel->removeRow( indexes.at( i - 1 ).row(), QModelIndex() );
650}
651
652void QgsLayoutAttributeSelectionDialog::mAddColumnPushButton_clicked()
653{
654 //add a new row to the model
655 mColumnModel->insertRow( mColumnModel->rowCount() );
656}
657
658void QgsLayoutAttributeSelectionDialog::mColumnUpPushButton_clicked()
659{
660 //move selected row up
661
662 QModelIndexList indexes = mColumnsTableView->selectionModel()->selectedRows();
663 const int count = indexes.count();
664
665 std::reverse( indexes.begin(), indexes.end() );
666 for ( int i = count; i > 0; --i )
667 mColumnModel->moveRow( indexes.at( i - 1 ).row(), QgsLayoutAttributeTableColumnModelBase::ShiftUp );
668}
669
670void QgsLayoutAttributeSelectionDialog::mColumnDownPushButton_clicked()
671{
672 //move selected row down
673 const QModelIndexList indexes = mColumnsTableView->selectionModel()->selectedRows();
674 const int count = indexes.count();
675
676 for ( int i = count; i > 0; --i )
677 mColumnModel->moveRow( indexes.at( i - 1 ).row(), QgsLayoutAttributeTableColumnModelBase::ShiftDown );
678}
679
680void QgsLayoutAttributeSelectionDialog::mResetColumnsPushButton_clicked()
681{
682 //reset columns to match vector layer's fields
683 mColumnModel->resetToLayer();
684}
685
686void QgsLayoutAttributeSelectionDialog::mClearColumnsPushButton_clicked()
687{
688 //remove all columns
689 mColumnModel->removeRows( 0, mColumnModel->rowCount() );
690}
691
692void QgsLayoutAttributeSelectionDialog::mAddSortColumnPushButton_clicked()
693{
694 //add a new row to the model
695 mSortColumnModel->insertRow( mSortColumnModel->rowCount() );
696}
697
698void QgsLayoutAttributeSelectionDialog::mRemoveSortColumnPushButton_clicked()
699{
700 //remove selected rows from model
701 const QModelIndexList indexes = mSortColumnTableView->selectionModel()->selectedRows();
702 const int count = indexes.count();
703
704 for ( int i = count; i > 0; --i )
705 mSortColumnModel->removeRow( indexes.at( i - 1 ).row(), QModelIndex() );
706}
707
708void QgsLayoutAttributeSelectionDialog::showHelp()
709{
710 QgsHelp::openHelp( QStringLiteral( "print_composer/composer_items/composer_attribute_table.html" ) );
711}
712
713void QgsLayoutAttributeSelectionDialog::mSortColumnDownPushButton_clicked()
714{
715 //move selected row down
716 const QModelIndexList indexes = mSortColumnTableView->selectionModel()->selectedRows();
717 const int count = indexes.count();
718
719 for ( int i = count; i > 0; --i )
720 mSortColumnModel->moveRow( indexes.at( i - 1 ).row(), QgsLayoutTableSortModel::ShiftDown );
721}
722
723void QgsLayoutAttributeSelectionDialog::mSortColumnUpPushButton_clicked()
724{
725 //move selected row up
726 const QModelIndexList indexes = mSortColumnTableView->selectionModel()->selectedRows();
727 const int count = indexes.count();
728
729 for ( int i = count; i > 0; --i )
730 mSortColumnModel->moveRow( indexes.at( i - 1 ).row(), QgsLayoutTableSortModel::ShiftUp );
731}
732
733
The QgsSpinBox is a spin box with a clear button that will set the value to the defined clear value.
void setSpecialValueText(const QString &txt)
Set the special-value text to be txt If set, the spin box will display this text instead of a numeric...
void setShowClearButton(bool showClearButton)
Sets whether the widget will show a clear button.
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void setHighlightedVariables(const QStringList &variableNames)
Sets the list of variable names within the context intended to be highlighted to the user.
The QgsFieldExpressionWidget class reates a widget to choose fields and edit expressions It contains ...
void setField(const QString &fieldName)
sets the current field or expression in the widget
QString asExpression() const
Returns the currently selected field or expression.
void setLayer(QgsMapLayer *layer)
Sets the layer used to display the fields and expression.
void registerExpressionContextGenerator(const QgsExpressionContextGenerator *generator)
Register an expression context generator class that will be used to retrieve an expression context fo...
void fieldChanged(const QString &fieldName)
Emitted when the currently selected field changes.
QString currentField(bool *isExpression=nullptr, bool *isValid=nullptr) const
currentField returns the currently selected field or expression if allowed
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:180
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
QgsLayoutAttributeSelectionDialog(QgsLayoutItemAttributeTable *table, QgsVectorLayer *vLayer, QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
constructor
QModelIndex index(int row, int column, const QModelIndex &parent) const override
Column
Available columns for the configuration table to be used by the model.
@ Attribute
Attribute for a field or an expression.
@ Alignment
Defines the alignment of the column.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
bool moveRow(int row, ShiftDirection direction)
Moves the specified row up or down in the model.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
virtual QVector< QgsLayoutTableColumn > & columns() const =0
To be reimplemented to provide the display or the sort columns.
QVariant data(const QModelIndex &index, int role) const override
QgsLayoutAttributeTableColumnModelBase(QgsLayoutItemAttributeTable *table, QObject *parent=nullptr)
Constructor for QgsLayoutAttributeTableColumnModel.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
virtual QList< Column > displayedColumns() const =0
To be reimplemented to choose which column should be used by the model.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
QModelIndex parent(const QModelIndex &child) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
ShiftDirection
Controls whether a row/column is shifted up or down.
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
A model for displaying columns shown in a QgsLayoutAttributeTable.
QVector< QgsLayoutTableColumn > & columns() const override
To be reimplemented to provide the display or the sort columns.
void resetToLayer()
Resets the attribute table's columns to match the source layer's fields.
A delegate for showing column alignment as a combo box.
void setEditorData(QWidget *editor, const QModelIndex &index) const override
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QgsLayoutColumnAlignmentDelegate(QObject *parent=nullptr)
constructor
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
A delegate for showing column sort order as a combo box.
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
QgsLayoutColumnSortOrderDelegate(QObject *parent=nullptr)
constructor
A delegate for showing column attribute source as a QgsFieldExpressionWidget.
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
QgsLayoutColumnSourceDelegate(QgsVectorLayer *vlayer, QObject *parent=nullptr, const QgsLayoutObject *layoutObject=nullptr, bool forceExpressions=false)
Constructor for QgsLayoutColumnSourceDelegate.
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setEditorData(QWidget *editor, const QModelIndex &index) const override
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
A delegate for showing column width as a spin box.
void setEditorData(QWidget *editor, const QModelIndex &index) const override
QgsLayoutColumnWidthDelegate(QObject *parent=nullptr)
constructor
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override
A layout table subclass that displays attributes from a vector layer.
void resetColumns()
Resets the attribute table's columns to match the vector layer's fields.
A base class for objects which belong to a layout.
QgsExpressionContext createExpressionContext() const override
Creates an expression context relating to the objects' current state.
Stores properties of a column for a QgsLayoutTable.
QString attribute() const
Returns the attribute name or expression used for the column's values.
void setVAlignment(Qt::AlignmentFlag alignment)
Sets the vertical alignment for a column, which controls the alignment used for drawing column values...
double width() const
Returns the width for the column in mm, or 0 if column width is automatically calculated.
Qt::AlignmentFlag vAlignment() const
Returns the vertical alignment for a column, which controls the alignment used for drawing column val...
QString heading() const
Returns the heading for a column, which is the value displayed in the column's header cell.
void setSortOrder(Qt::SortOrder order)
Sets the sort order for the column.
void setAttribute(const QString &attribute)
Sets the attribute name or expression used for the column's values.
Qt::SortOrder sortOrder() const
Returns the sort order for the column.
void setHAlignment(Qt::AlignmentFlag alignment)
Sets the horizontal alignment for a column, which controls the alignment used for drawing column valu...
void setHeading(const QString &heading)
Sets the heading for a column, which is the value displayed in the column's header cell.
Qt::AlignmentFlag hAlignment() const
Returns the horizontal alignment for a column, which controls the alignment used for drawing column v...
void setWidth(const double width)
Sets the width for a column in mm.
Allows for filtering QgsComposerAttributeTable columns by columns which are sorted or unsorted.
QVector< QgsLayoutTableColumn > & columns() const override
To be reimplemented to provide the display or the sort columns.
QgsLayoutTableColumns & columns()
Returns a reference to the list of QgsLayoutTableColumns shown in the table.
QgsLayoutTableSortColumns & sortColumns()
Returns a reference to the list of QgsLayoutTableSortColumns shown in the table.
Represents a vector layer which manages a vector based data sets.
const QgsField & field
Definition: qgsfield.h:463
Single variable definition for use within a QgsExpressionContextScope.