QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
qgslayoutattributetablewidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgslayoutattributetablewidget.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 
19 #include "qgslayoutatlas.h"
20 #include "qgslayout.h"
21 #include "qgslayoutframe.h"
23 #include "qgslayoutitemwidget.h"
25 #include "qgslayouttablecolumn.h"
26 #include "qgslayoutitemmap.h"
27 #include "qgsvectorlayer.h"
29 #include "qgsproject.h"
30 #include "qgsrelationmanager.h"
31 #include "qgsguiutils.h"
33 
35  : QgsLayoutItemBaseWidget( nullptr, frame ? qobject_cast< QgsLayoutItemAttributeTable* >( frame->multiFrame() ) : nullptr )
36  , mTable( frame ? qobject_cast< QgsLayoutItemAttributeTable* >( frame->multiFrame() ) : nullptr )
37  , mFrame( frame )
38 {
39  setupUi( this );
40  connect( mRefreshPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeTableWidget::mRefreshPushButton_clicked );
41  connect( mAttributesPushButton, &QPushButton::clicked, this, &QgsLayoutAttributeTableWidget::mAttributesPushButton_clicked );
42  connect( mMaximumRowsSpinBox, static_cast < void ( QSpinBox::* )( int ) > ( &QSpinBox::valueChanged ), this, &QgsLayoutAttributeTableWidget::mMaximumRowsSpinBox_valueChanged );
43  connect( mMarginSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutAttributeTableWidget::mMarginSpinBox_valueChanged );
44  connect( mGridStrokeWidthSpinBox, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), this, &QgsLayoutAttributeTableWidget::mGridStrokeWidthSpinBox_valueChanged );
45  connect( mGridColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mGridColorButton_colorChanged );
46  connect( mBackgroundColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mBackgroundColorButton_colorChanged );
47  connect( mHeaderFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mHeaderFontColorButton_colorChanged );
48  connect( mContentFontColorButton, &QgsColorButton::colorChanged, this, &QgsLayoutAttributeTableWidget::mContentFontColorButton_colorChanged );
49  connect( mDrawHorizontalGrid, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mDrawHorizontalGrid_toggled );
50  connect( mDrawVerticalGrid, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mDrawVerticalGrid_toggled );
51  connect( mShowGridGroupCheckBox, &QgsCollapsibleGroupBoxBasic::toggled, this, &QgsLayoutAttributeTableWidget::mShowGridGroupCheckBox_toggled );
52  connect( mShowOnlyVisibleFeaturesCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::mShowOnlyVisibleFeaturesCheckBox_stateChanged );
53  connect( mFeatureFilterCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::mFeatureFilterCheckBox_stateChanged );
54  connect( mFeatureFilterEdit, &QLineEdit::editingFinished, this, &QgsLayoutAttributeTableWidget::mFeatureFilterEdit_editingFinished );
55  connect( mFeatureFilterButton, &QToolButton::clicked, this, &QgsLayoutAttributeTableWidget::mFeatureFilterButton_clicked );
56  connect( mHeaderHAlignmentComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mHeaderHAlignmentComboBox_currentIndexChanged );
57  connect( mHeaderModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mHeaderModeComboBox_currentIndexChanged );
58  connect( mWrapStringLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutAttributeTableWidget::mWrapStringLineEdit_editingFinished );
59  connect( mAddFramePushButton, &QPushButton::clicked, this, &QgsLayoutAttributeTableWidget::mAddFramePushButton_clicked );
60  connect( mResizeModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mResizeModeComboBox_currentIndexChanged );
61  connect( mSourceComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mSourceComboBox_currentIndexChanged );
62  connect( mRelationsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mRelationsComboBox_currentIndexChanged );
63  connect( mEmptyModeComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mEmptyModeComboBox_currentIndexChanged );
64  connect( mDrawEmptyCheckBox, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mDrawEmptyCheckBox_toggled );
65  connect( mEmptyMessageLineEdit, &QLineEdit::editingFinished, this, &QgsLayoutAttributeTableWidget::mEmptyMessageLineEdit_editingFinished );
66  connect( mIntersectAtlasCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::mIntersectAtlasCheckBox_stateChanged );
67  connect( mUniqueOnlyCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::mUniqueOnlyCheckBox_stateChanged );
68  connect( mEmptyFrameCheckBox, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mEmptyFrameCheckBox_toggled );
69  connect( mHideEmptyBgCheckBox, &QCheckBox::toggled, this, &QgsLayoutAttributeTableWidget::mHideEmptyBgCheckBox_toggled );
70  connect( mWrapBehaviorComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsLayoutAttributeTableWidget::mWrapBehaviorComboBox_currentIndexChanged );
71  connect( mAdvancedCustomizationButton, &QPushButton::clicked, this, &QgsLayoutAttributeTableWidget::mAdvancedCustomizationButton_clicked );
72  connect( mUseConditionalStylingCheckBox, &QCheckBox::stateChanged, this, &QgsLayoutAttributeTableWidget::useConditionalStylingChanged );
73  setPanelTitle( tr( "Table Properties" ) );
74 
75  mContentFontToolButton->setMode( QgsFontButton::ModeQFont );
76  mHeaderFontToolButton->setMode( QgsFontButton::ModeQFont );
77 
78  blockAllSignals( true );
79 
80  mResizeModeComboBox->addItem( tr( "Use Existing Frames" ), QgsLayoutMultiFrame::UseExistingFrames );
81  mResizeModeComboBox->addItem( tr( "Extend to Next Page" ), QgsLayoutMultiFrame::ExtendToNextPage );
82  mResizeModeComboBox->addItem( tr( "Repeat Until Finished" ), QgsLayoutMultiFrame::RepeatUntilFinished );
83 
84  mEmptyModeComboBox->addItem( tr( "Draw Headers Only" ), QgsLayoutTable::HeadersOnly );
85  mEmptyModeComboBox->addItem( tr( "Hide Entire Table" ), QgsLayoutTable::HideTable );
86  mEmptyModeComboBox->addItem( tr( "Show Set Message" ), QgsLayoutTable::ShowMessage );
87 
88  mWrapBehaviorComboBox->addItem( tr( "Truncate Text" ), QgsLayoutTable::TruncateText );
89  mWrapBehaviorComboBox->addItem( tr( "Wrap Text" ), QgsLayoutTable::WrapText );
90 
91  mHeaderModeComboBox->addItem( tr( "On First Frame" ), QgsLayoutTable::FirstFrame );
92  mHeaderModeComboBox->addItem( tr( "On All Frames" ), QgsLayoutTable::AllFrames );
93  mHeaderModeComboBox->addItem( tr( "No Header" ), QgsLayoutTable::NoHeaders );
94 
95  mHeaderHAlignmentComboBox->addItem( tr( "Follow Column Alignment" ), QgsLayoutTable::FollowColumn );
96  mHeaderHAlignmentComboBox->addItem( tr( "Left" ), QgsLayoutTable::HeaderLeft );
97  mHeaderHAlignmentComboBox->addItem( tr( "Center" ), QgsLayoutTable::HeaderCenter );
98  mHeaderHAlignmentComboBox->addItem( tr( "Right" ), QgsLayoutTable::HeaderRight );
99 
100  mSourceComboBox->addItem( tr( "Layer Features" ), QgsLayoutItemAttributeTable::LayerAttributes );
101  toggleAtlasSpecificControls( static_cast< bool >( coverageLayer() ) );
102 
103  //update relations combo when relations modified in project
104  connect( QgsProject::instance()->relationManager(), &QgsRelationManager::changed, this, &QgsLayoutAttributeTableWidget::updateRelationsCombo );
105 
106  mLayerComboBox->setFilters( QgsMapLayerProxyModel::VectorLayer );
107  connect( mLayerComboBox, &QgsMapLayerComboBox::layerChanged, this, &QgsLayoutAttributeTableWidget::changeLayer );
108 
109  mComposerMapComboBox->setCurrentLayout( mTable->layout() );
110  mComposerMapComboBox->setItemType( QgsLayoutItemRegistry::LayoutMap );
111  connect( mComposerMapComboBox, &QgsLayoutItemComboBox::itemChanged, this, &QgsLayoutAttributeTableWidget::composerMapChanged );
112 
113  mHeaderFontColorButton->setColorDialogTitle( tr( "Select Header Font Color" ) );
114  mHeaderFontColorButton->setAllowOpacity( true );
115  mHeaderFontColorButton->setContext( QStringLiteral( "composer" ) );
116  mContentFontColorButton->setColorDialogTitle( tr( "Select Content Font Color" ) );
117  mContentFontColorButton->setAllowOpacity( true );
118  mContentFontColorButton->setContext( QStringLiteral( "composer" ) );
119  mGridColorButton->setColorDialogTitle( tr( "Select Grid Color" ) );
120  mGridColorButton->setAllowOpacity( true );
121  mGridColorButton->setContext( QStringLiteral( "composer" ) );
122  mGridColorButton->setDefaultColor( Qt::black );
123  mBackgroundColorButton->setColorDialogTitle( tr( "Select Background Color" ) );
124  mBackgroundColorButton->setAllowOpacity( true );
125  mBackgroundColorButton->setContext( QStringLiteral( "composer" ) );
126  mBackgroundColorButton->setShowNoColor( true );
127  mBackgroundColorButton->setNoColorString( tr( "No Background" ) );
128 
129  updateGuiElements();
130 
131  if ( mTable )
132  {
133  connect( mTable, &QgsLayoutMultiFrame::changed, this, &QgsLayoutAttributeTableWidget::updateGuiElements );
134 
135  // repopulate relations combo box if atlas layer changes
136  connect( &mTable->layout()->reportContext(), &QgsLayoutReportContext::layerChanged,
137  this, &QgsLayoutAttributeTableWidget::atlasToggled );
138 
139  if ( QgsLayoutAtlas *atlas = layoutAtlas() )
140  {
141  connect( atlas, &QgsLayoutAtlas::toggled, this, &QgsLayoutAttributeTableWidget::atlasToggled );
142  atlasToggled();
143  }
144 
145  mLayerSourceDDBtn->registerExpressionContextGenerator( mTable );
146  }
147 
149 
150  //embed widget for general options
151  if ( mFrame )
152  {
153  //add widget for general composer item properties
154  mItemPropertiesWidget = new QgsLayoutItemPropertiesWidget( this, mFrame );
155  mainLayout->addWidget( mItemPropertiesWidget );
156  }
157 
158  connect( mHeaderFontToolButton, &QgsFontButton::changed, this, &QgsLayoutAttributeTableWidget::headerFontChanged );
159  connect( mContentFontToolButton, &QgsFontButton::changed, this, &QgsLayoutAttributeTableWidget::contentFontChanged );
160 }
161 
163 {
164  mIntersectAtlasCheckBox->setText( tr( "Show only features intersecting %1 feature" ).arg( string ) );
165  const int atlasFeatureIndex = mSourceComboBox->findData( QgsLayoutItemAttributeTable::AtlasFeature );
166  if ( atlasFeatureIndex != -1 )
167  {
168  mSourceComboBox->setItemText( atlasFeatureIndex, tr( "Current %1 Feature" ).arg( string ) );
169  }
170 }
171 
173 {
174  if ( mItemPropertiesWidget )
175  mItemPropertiesWidget->setMasterLayout( masterLayout );
176 }
177 
179 {
180  QgsLayoutFrame *frame = qobject_cast< QgsLayoutFrame * >( item );
181  if ( !frame )
182  return false;
183 
184  QgsLayoutMultiFrame *multiFrame = frame->multiFrame();
185  if ( !multiFrame )
186  return false;
187 
188  if ( multiFrame->type() != QgsLayoutItemRegistry::LayoutAttributeTable )
189  return false;
190 
191  if ( mTable )
192  {
193  disconnect( mTable, &QgsLayoutObject::changed, this, &QgsLayoutAttributeTableWidget::updateGuiElements );
194  }
195 
196  mTable = qobject_cast< QgsLayoutItemAttributeTable * >( multiFrame );
197  mFrame = frame;
198  mItemPropertiesWidget->setItem( frame );
199 
200  if ( mTable )
201  {
202  connect( mTable, &QgsLayoutObject::changed, this, &QgsLayoutAttributeTableWidget::updateGuiElements );
203  }
204 
205  updateGuiElements();
206 
207  return true;
208 }
209 
210 
211 void QgsLayoutAttributeTableWidget::mRefreshPushButton_clicked()
212 {
213  if ( !mTable )
214  {
215  return;
216  }
217 
218  mTable->refreshAttributes();
219 }
220 
221 void QgsLayoutAttributeTableWidget::mAttributesPushButton_clicked()
222 {
223  if ( !mTable )
224  {
225  return;
226  }
227 
228  //make deep copy of current columns, so we can restore them in case of cancellation
229  QVector<QgsLayoutTableColumn *> currentColumns;
230  auto it = mTable->columns().constBegin();
231  for ( ; it != mTable->columns().constEnd() ; ++it )
232  {
233  QgsLayoutTableColumn *copy = ( *it )->clone();
234  currentColumns.append( copy );
235  }
236 
237  mTable->beginCommand( tr( "Change Table Attributes" ) );
238 
239  //temporarily block updates for the window, to stop table trying to repaint under windows (#11462)
240  window()->setUpdatesEnabled( false );
241 
242  QgsLayoutAttributeSelectionDialog d( mTable, mTable->sourceLayer(), this );
243  if ( d.exec() == QDialog::Accepted )
244  {
245  mTable->refreshAttributes();
246  //safe to unblock updates
247  window()->setUpdatesEnabled( true );
248  mTable->update();
249  mTable->endCommand();
250 
251  //clear currentColumns to free memory
252  qDeleteAll( currentColumns );
253  currentColumns.clear();
254  }
255  else
256  {
257  //undo changes
258  mTable->setColumns( currentColumns );
259  window()->setUpdatesEnabled( true );
260  mTable->cancelCommand();
261  }
262 }
263 
264 void QgsLayoutAttributeTableWidget::composerMapChanged( QgsLayoutItem *item )
265 {
266  if ( !mTable )
267  {
268  return;
269  }
270 
271  mTable->beginCommand( tr( "Change Table Map" ) );
272  mTable->setMap( qobject_cast< QgsLayoutItemMap * >( item ) );
273  mTable->update();
274  mTable->endCommand();
275 }
276 
277 void QgsLayoutAttributeTableWidget::mMaximumRowsSpinBox_valueChanged( int i )
278 {
279  if ( !mTable )
280  {
281  return;
282  }
283 
284  mTable->beginCommand( tr( "Change Table Rows" ), QgsLayoutMultiFrame::UndoTableMaximumFeatures );
285  mTable->setMaximumNumberOfFeatures( i );
286  mTable->update();
287  mTable->endCommand();
288 }
289 
290 void QgsLayoutAttributeTableWidget::mMarginSpinBox_valueChanged( double d )
291 {
292  if ( !mTable )
293  {
294  return;
295  }
296 
297  mTable->beginCommand( tr( "Change Table Margin" ), QgsLayoutMultiFrame::UndoTableMargin );
298  mTable->setCellMargin( d );
299  mTable->endCommand();
300 }
301 
302 void QgsLayoutAttributeTableWidget::headerFontChanged()
303 {
304  if ( !mTable )
305  return;
306 
307  mTable->beginCommand( tr( "Change Table Font" ) );
308  mTable->setHeaderFont( mHeaderFontToolButton->currentFont() );
309  mTable->endCommand();
310 }
311 
312 void QgsLayoutAttributeTableWidget::mHeaderFontColorButton_colorChanged( const QColor &newColor )
313 {
314  if ( !mTable )
315  {
316  return;
317  }
318 
319  mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableHeaderFontColor );
320  mTable->setHeaderFontColor( newColor );
321  mTable->endCommand();
322 }
323 
324 void QgsLayoutAttributeTableWidget::contentFontChanged()
325 {
326  if ( !mTable )
327  {
328  return;
329  }
330 
331  mTable->beginCommand( tr( "Change Table Font" ) );
332  mTable->setContentFont( mContentFontToolButton->currentFont() );
333  mTable->endCommand();
334 }
335 
336 void QgsLayoutAttributeTableWidget::mContentFontColorButton_colorChanged( const QColor &newColor )
337 {
338  if ( !mTable )
339  {
340  return;
341  }
342 
343  mTable->beginCommand( tr( "Change Font Color" ), QgsLayoutMultiFrame::UndoTableContentFontColor );
344  mTable->setContentFontColor( newColor );
345  mTable->endCommand();
346 }
347 
348 void QgsLayoutAttributeTableWidget::mGridStrokeWidthSpinBox_valueChanged( double d )
349 {
350  if ( !mTable )
351  {
352  return;
353  }
354 
355  mTable->beginCommand( tr( "Change Table Line Width" ), QgsLayoutMultiFrame::UndoTableGridStrokeWidth );
356  mTable->setGridStrokeWidth( d );
357  mTable->endCommand();
358 }
359 
360 void QgsLayoutAttributeTableWidget::mGridColorButton_colorChanged( const QColor &newColor )
361 {
362  if ( !mTable )
363  {
364  return;
365  }
366 
367  mTable->beginCommand( tr( "Change Table Grid Color" ), QgsLayoutMultiFrame::UndoTableGridColor );
368  mTable->setGridColor( newColor );
369  mTable->endCommand();
370 }
371 
372 void QgsLayoutAttributeTableWidget::mDrawHorizontalGrid_toggled( bool state )
373 {
374  if ( !mTable )
375  {
376  return;
377  }
378 
379  mTable->beginCommand( tr( "Toggle Table Grid" ) );
380  mTable->setHorizontalGrid( state );
381  mTable->endCommand();
382 }
383 
384 void QgsLayoutAttributeTableWidget::mDrawVerticalGrid_toggled( bool state )
385 {
386  if ( !mTable )
387  {
388  return;
389  }
390 
391  mTable->beginCommand( tr( "Toggled Table Grid" ) );
392  mTable->setVerticalGrid( state );
393  mTable->endCommand();
394 }
395 
396 void QgsLayoutAttributeTableWidget::mShowGridGroupCheckBox_toggled( bool state )
397 {
398  if ( !mTable )
399  {
400  return;
401  }
402 
403  mTable->beginCommand( tr( "Toggle Table Grid" ) );
404  mTable->setShowGrid( state );
405  mTable->endCommand();
406 }
407 
408 void QgsLayoutAttributeTableWidget::mBackgroundColorButton_colorChanged( const QColor &newColor )
409 {
410  if ( !mTable )
411  {
412  return;
413  }
414 
415  mTable->beginCommand( tr( "Change Table Color" ), QgsLayoutMultiFrame::UndoTableBackgroundColor );
416  mTable->setBackgroundColor( newColor );
417  mTable->endCommand();
418 }
419 
420 void QgsLayoutAttributeTableWidget::updateGuiElements()
421 {
422  if ( !mTable || !mFrame )
423  {
424  return;
425  }
426 
427  blockAllSignals( true );
428 
429  mSourceComboBox->setCurrentIndex( mSourceComboBox->findData( mTable->source() ) );
430  mRelationsComboBox->setCurrentIndex( mRelationsComboBox->findData( mTable->relationId() ) );
431 
432  //layer combo box
433  if ( mTable->vectorLayer() )
434  {
435  mLayerComboBox->setLayer( mTable->vectorLayer() );
436  if ( mTable->vectorLayer()->geometryType() == QgsWkbTypes::NullGeometry )
437  {
438  //layer has no geometry, so uncheck & disable controls which require geometry
439  mShowOnlyVisibleFeaturesCheckBox->setChecked( false );
440  mShowOnlyVisibleFeaturesCheckBox->setEnabled( false );
441  }
442  else
443  {
444  mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
445  }
446  }
447 
448  mComposerMapComboBox->setItem( mTable->map() );
449  mMaximumRowsSpinBox->setValue( mTable->maximumNumberOfFeatures() );
450  mMarginSpinBox->setValue( mTable->cellMargin() );
451  mGridStrokeWidthSpinBox->setValue( mTable->gridStrokeWidth() );
452  mGridColorButton->setColor( mTable->gridColor() );
453  mDrawHorizontalGrid->setChecked( mTable->horizontalGrid() );
454  mDrawVerticalGrid->setChecked( mTable->verticalGrid() );
455  if ( mTable->showGrid() )
456  {
457  mShowGridGroupCheckBox->setChecked( true );
458  }
459  else
460  {
461  mShowGridGroupCheckBox->setChecked( false );
462  }
463  mBackgroundColorButton->setColor( mTable->backgroundColor() );
464 
465  mHeaderFontColorButton->setColor( mTable->headerFontColor() );
466  mContentFontColorButton->setColor( mTable->contentFontColor() );
467  mHeaderFontToolButton->setCurrentFont( mTable->headerFont() );
468  mContentFontToolButton->setCurrentFont( mTable->contentFont() );
469 
470  if ( mTable->displayOnlyVisibleFeatures() && mShowOnlyVisibleFeaturesCheckBox->isEnabled() )
471  {
472  mShowOnlyVisibleFeaturesCheckBox->setCheckState( Qt::Checked );
473  mComposerMapComboBox->setEnabled( true );
474  mComposerMapLabel->setEnabled( true );
475  }
476  else
477  {
478  mShowOnlyVisibleFeaturesCheckBox->setCheckState( Qt::Unchecked );
479  mComposerMapComboBox->setEnabled( false );
480  mComposerMapLabel->setEnabled( false );
481  }
482 
483  mUniqueOnlyCheckBox->setChecked( mTable->uniqueRowsOnly() );
484  mIntersectAtlasCheckBox->setChecked( mTable->filterToAtlasFeature() );
485  mFeatureFilterEdit->setText( mTable->featureFilter() );
486  mFeatureFilterCheckBox->setCheckState( mTable->filterFeatures() ? Qt::Checked : Qt::Unchecked );
487  mFeatureFilterEdit->setEnabled( mTable->filterFeatures() );
488  mFeatureFilterButton->setEnabled( mTable->filterFeatures() );
489  mUseConditionalStylingCheckBox->setChecked( mTable->useConditionalStyling() );
490 
491  mHeaderHAlignmentComboBox->setCurrentIndex( mHeaderHAlignmentComboBox->findData( mTable->headerHAlignment() ) );
492  mHeaderModeComboBox->setCurrentIndex( mHeaderModeComboBox->findData( mTable->headerMode() ) );
493 
494  mEmptyModeComboBox->setCurrentIndex( mEmptyModeComboBox->findData( mTable->emptyTableBehavior() ) );
495  mEmptyMessageLineEdit->setText( mTable->emptyTableMessage() );
496  mEmptyMessageLineEdit->setEnabled( mTable->emptyTableBehavior() == QgsLayoutTable::ShowMessage );
497  mEmptyMessageLabel->setEnabled( mTable->emptyTableBehavior() == QgsLayoutTable::ShowMessage );
498  mDrawEmptyCheckBox->setChecked( mTable->showEmptyRows() );
499  mWrapStringLineEdit->setText( mTable->wrapString() );
500  mWrapBehaviorComboBox->setCurrentIndex( mWrapBehaviorComboBox->findData( mTable->wrapBehavior() ) );
501 
502  mResizeModeComboBox->setCurrentIndex( mResizeModeComboBox->findData( mTable->resizeMode() ) );
503  mAddFramePushButton->setEnabled( mTable->resizeMode() == QgsLayoutMultiFrame::UseExistingFrames );
504 
505  mEmptyFrameCheckBox->setChecked( mFrame->hidePageIfEmpty() );
506  mHideEmptyBgCheckBox->setChecked( mFrame->hideBackgroundIfEmpty() );
507 
508  updateDataDefinedButton( mLayerSourceDDBtn );
509 
510  toggleSourceControls();
511 
512  blockAllSignals( false );
513 }
514 
515 void QgsLayoutAttributeTableWidget::atlasToggled()
516 {
517  // display/hide atlas options in source combobox depending on atlas status
518  // if there's no atlas but there IS a coverageLayer, it's a report export and we should enable the controls
519  bool atlasEnabled = ( layoutAtlas() && layoutAtlas()->enabled() ) || ( !layoutAtlas() && coverageLayer() );
520 
521 
522  toggleAtlasSpecificControls( atlasEnabled );
523 
524  if ( !mTable )
525  return;
526 
527  whileBlocking( mSourceComboBox )->setCurrentIndex( mSourceComboBox->findData( mTable->source() ) );
528 
529  if ( !atlasEnabled && mTable->filterToAtlasFeature() )
530  {
531  mTable->setFilterToAtlasFeature( false );
532  }
533 }
534 
535 void QgsLayoutAttributeTableWidget::updateRelationsCombo()
536 {
537  mRelationsComboBox->blockSignals( true );
538  mRelationsComboBox->clear();
539 
540  QgsVectorLayer *atlasLayer = coverageLayer();
541  if ( atlasLayer )
542  {
543  const QList<QgsRelation> relations = QgsProject::instance()->relationManager()->referencedRelations( atlasLayer );
544  for ( const QgsRelation &relation : relations )
545  {
546  mRelationsComboBox->addItem( relation.name(), relation.id() );
547  }
548  if ( mTable )
549  {
550  mRelationsComboBox->setCurrentIndex( mRelationsComboBox->findData( mTable->relationId() ) );
551  }
552  }
553 
554  mRelationsComboBox->blockSignals( false );
555 }
556 
557 void QgsLayoutAttributeTableWidget::toggleAtlasSpecificControls( const bool atlasEnabled )
558 {
559  if ( !atlasEnabled )
560  {
561  if ( mTable->source() == QgsLayoutItemAttributeTable::AtlasFeature )
562  {
564  }
565  mSourceComboBox->removeItem( mSourceComboBox->findData( QgsLayoutItemAttributeTable::AtlasFeature ) );
566  mSourceComboBox->removeItem( mSourceComboBox->findData( QgsLayoutItemAttributeTable::RelationChildren ) );
567  mRelationsComboBox->blockSignals( true );
568  mRelationsComboBox->setEnabled( false );
569  mRelationsComboBox->clear();
570  mRelationsComboBox->blockSignals( false );
571  mIntersectAtlasCheckBox->setEnabled( false );
572  }
573  else
574  {
575  if ( mSourceComboBox->findData( QgsLayoutItemAttributeTable::AtlasFeature ) == -1 )
576  {
577  //add missing atlasfeature option to combobox
578  mSourceComboBox->addItem( tr( "Current Atlas Feature" ), QgsLayoutItemAttributeTable::AtlasFeature );
579  }
580  if ( mSourceComboBox->findData( QgsLayoutItemAttributeTable::RelationChildren ) == -1 )
581  {
582  //add missing relation children option to combobox
583  mSourceComboBox->addItem( tr( "Relation Children" ), QgsLayoutItemAttributeTable::RelationChildren );
584  }
585 
586  //add relations for coverage layer
587  updateRelationsCombo();
588  mRelationsComboBox->setEnabled( true );
589  mIntersectAtlasCheckBox->setEnabled( true );
590  }
591 }
592 
593 void QgsLayoutAttributeTableWidget::blockAllSignals( bool b )
594 {
595  mSourceComboBox->blockSignals( b );
596  mLayerComboBox->blockSignals( b );
597  mComposerMapComboBox->blockSignals( b );
598  mMaximumRowsSpinBox->blockSignals( b );
599  mMarginSpinBox->blockSignals( b );
600  mGridColorButton->blockSignals( b );
601  mGridStrokeWidthSpinBox->blockSignals( b );
602  mBackgroundColorButton->blockSignals( b );
603  mDrawHorizontalGrid->blockSignals( b );
604  mDrawVerticalGrid->blockSignals( b );
605  mShowGridGroupCheckBox->blockSignals( b );
606  mShowOnlyVisibleFeaturesCheckBox->blockSignals( b );
607  mUniqueOnlyCheckBox->blockSignals( b );
608  mIntersectAtlasCheckBox->blockSignals( b );
609  mFeatureFilterEdit->blockSignals( b );
610  mFeatureFilterCheckBox->blockSignals( b );
611  mHeaderHAlignmentComboBox->blockSignals( b );
612  mHeaderModeComboBox->blockSignals( b );
613  mHeaderFontColorButton->blockSignals( b );
614  mContentFontColorButton->blockSignals( b );
615  mResizeModeComboBox->blockSignals( b );
616  mRelationsComboBox->blockSignals( b );
617  mEmptyModeComboBox->blockSignals( b );
618  mEmptyMessageLineEdit->blockSignals( b );
619  mEmptyFrameCheckBox->blockSignals( b );
620  mHideEmptyBgCheckBox->blockSignals( b );
621  mDrawEmptyCheckBox->blockSignals( b );
622  mWrapStringLineEdit->blockSignals( b );
623  mWrapBehaviorComboBox->blockSignals( b );
624  mContentFontToolButton->blockSignals( b );
625  mHeaderFontToolButton->blockSignals( b );
626 }
627 
628 void QgsLayoutAttributeTableWidget::setMaximumNumberOfFeatures( int n )
629 {
630  whileBlocking( mMaximumRowsSpinBox )->setValue( n );
631 }
632 
633 void QgsLayoutAttributeTableWidget::mShowOnlyVisibleFeaturesCheckBox_stateChanged( int state )
634 {
635  if ( !mTable )
636  {
637  return;
638  }
639 
640  mTable->beginCommand( tr( "Toggle Visible Features Only" ) );
641  bool showOnlyVisibleFeatures = ( state == Qt::Checked );
642  mTable->setDisplayOnlyVisibleFeatures( showOnlyVisibleFeatures );
643  mTable->update();
644  mTable->endCommand();
645 
646  //enable/disable map combobox based on state of checkbox
647  mComposerMapComboBox->setEnabled( state == Qt::Checked );
648  mComposerMapLabel->setEnabled( state == Qt::Checked );
649 }
650 
651 void QgsLayoutAttributeTableWidget::mUniqueOnlyCheckBox_stateChanged( int state )
652 {
653  if ( !mTable )
654  {
655  return;
656  }
657 
658  mTable->beginCommand( tr( "Toggle Table Filter Duplicates" ) );
659  mTable->setUniqueRowsOnly( state == Qt::Checked );
660  mTable->update();
661  mTable->endCommand();
662 }
663 
664 void QgsLayoutAttributeTableWidget::mEmptyFrameCheckBox_toggled( bool checked )
665 {
666  if ( !mFrame )
667  {
668  return;
669  }
670 
671  mFrame->beginCommand( tr( "Toggle Empty Frame Mode" ) );
672  mFrame->setHidePageIfEmpty( checked );
673  mFrame->endCommand();
674 }
675 
676 void QgsLayoutAttributeTableWidget::mHideEmptyBgCheckBox_toggled( bool checked )
677 {
678  if ( !mFrame )
679  {
680  return;
681  }
682 
683  mFrame->beginCommand( tr( "Toggle Background Display" ) );
684  mFrame->setHideBackgroundIfEmpty( checked );
685  mFrame->endCommand();
686 }
687 
688 void QgsLayoutAttributeTableWidget::mIntersectAtlasCheckBox_stateChanged( int state )
689 {
690  if ( !mTable )
691  {
692  return;
693  }
694 
695  mTable->beginCommand( tr( "Toggle Table Atlas Filter" ) );
696  bool filterToAtlas = ( state == Qt::Checked );
697  mTable->setFilterToAtlasFeature( filterToAtlas );
698  mTable->update();
699  mTable->endCommand();
700 }
701 
702 void QgsLayoutAttributeTableWidget::mFeatureFilterCheckBox_stateChanged( int state )
703 {
704  if ( !mTable )
705  {
706  return;
707  }
708 
709  if ( state == Qt::Checked )
710  {
711  mFeatureFilterEdit->setEnabled( true );
712  mFeatureFilterButton->setEnabled( true );
713  }
714  else
715  {
716  mFeatureFilterEdit->setEnabled( false );
717  mFeatureFilterButton->setEnabled( false );
718  }
719 
720  mTable->beginCommand( tr( "Toggle Table Feature Filter" ) );
721  mTable->setFilterFeatures( state == Qt::Checked );
722  mTable->update();
723  mTable->endCommand();
724 }
725 
726 void QgsLayoutAttributeTableWidget::mFeatureFilterEdit_editingFinished()
727 {
728  if ( !mTable )
729  {
730  return;
731  }
732 
733  mTable->beginCommand( tr( "Change Table Feature Filter" ) );
734  mTable->setFeatureFilter( mFeatureFilterEdit->text() );
735  mTable->update();
736  mTable->endCommand();
737 }
738 
739 void QgsLayoutAttributeTableWidget::mFeatureFilterButton_clicked()
740 {
741  if ( !mTable )
742  {
743  return;
744  }
745 
746  QgsExpressionContext context = mTable->createExpressionContext();
747  QgsExpressionBuilderDialog exprDlg( mTable->sourceLayer(), mFeatureFilterEdit->text(), this, QStringLiteral( "generic" ), context );
748  exprDlg.setWindowTitle( tr( "Expression Based Filter" ) );
749  if ( exprDlg.exec() == QDialog::Accepted )
750  {
751  QString expression = exprDlg.expressionText();
752  if ( !expression.isEmpty() )
753  {
754  mFeatureFilterEdit->setText( expression );
755  mTable->beginCommand( tr( "Change Table Feature Filter" ) );
756  mTable->setFeatureFilter( mFeatureFilterEdit->text() );
757  mTable->update();
758  mTable->endCommand();
759  }
760  }
761 }
762 
763 void QgsLayoutAttributeTableWidget::mHeaderHAlignmentComboBox_currentIndexChanged( int )
764 {
765  if ( !mTable )
766  {
767  return;
768  }
769 
770  mTable->beginCommand( tr( "Change Table Alignment" ) );
771  mTable->setHeaderHAlignment( static_cast< QgsLayoutTable::HeaderHAlignment >( mHeaderHAlignmentComboBox->currentData().toInt() ) );
772  mTable->endCommand();
773 }
774 
775 void QgsLayoutAttributeTableWidget::mHeaderModeComboBox_currentIndexChanged( int )
776 {
777  if ( !mTable )
778  {
779  return;
780  }
781 
782  mTable->beginCommand( tr( "Change Table Header Mode" ) );
783  mTable->setHeaderMode( static_cast< QgsLayoutTable::HeaderMode >( mHeaderModeComboBox->currentData().toInt() ) );
784  mTable->endCommand();
785 }
786 
787 void QgsLayoutAttributeTableWidget::mWrapStringLineEdit_editingFinished()
788 {
789  if ( !mTable )
790  {
791  return;
792  }
793 
794  mTable->beginCommand( tr( "Change Table Wrap String" ) );
795  mTable->setWrapString( mWrapStringLineEdit->text() );
796  mTable->endCommand();
797 }
798 
799 void QgsLayoutAttributeTableWidget::changeLayer( QgsMapLayer *layer )
800 {
801  if ( !mTable )
802  {
803  return;
804  }
805 
806  QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer );
807  if ( !vl )
808  {
809  return;
810  }
811 
812  mTable->beginCommand( tr( "Change Table Layer" ) );
813  mTable->setVectorLayer( vl );
814  mTable->update();
815  mTable->endCommand();
816 
818  {
819  //layer has no geometry, so uncheck & disable controls which require geometry
820  mShowOnlyVisibleFeaturesCheckBox->setChecked( false );
821  mShowOnlyVisibleFeaturesCheckBox->setEnabled( false );
822  }
823  else
824  {
825  mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
826  }
827 }
828 
829 void QgsLayoutAttributeTableWidget::mAddFramePushButton_clicked()
830 {
831  if ( !mTable || !mFrame )
832  {
833  return;
834  }
835 
836  //create a new frame based on the current frame
837  QPointF pos = mFrame->pos();
838  //shift new frame so that it sits 10 units below current frame
839  pos.ry() += mFrame->rect().height() + 10;
840 
841  QgsLayoutFrame *newFrame = mTable->createNewFrame( mFrame, pos, mFrame->rect().size() );
842  mTable->recalculateFrameSizes();
843 
844  //set new frame as selection
845  if ( QgsLayout *layout = mTable->layout() )
846  {
847  layout->setSelectedItem( newFrame );
848  }
849 }
850 
851 void QgsLayoutAttributeTableWidget::mResizeModeComboBox_currentIndexChanged( int index )
852 {
853  if ( !mTable )
854  {
855  return;
856  }
857 
858  mTable->beginCommand( tr( "Change Resize Mode" ) );
859  mTable->setResizeMode( static_cast< QgsLayoutMultiFrame::ResizeMode >( mResizeModeComboBox->itemData( index ).toInt() ) );
860  mTable->endCommand();
861 
862  mAddFramePushButton->setEnabled( mTable->resizeMode() == QgsLayoutMultiFrame::UseExistingFrames );
863 }
864 
865 void QgsLayoutAttributeTableWidget::mSourceComboBox_currentIndexChanged( int index )
866 {
867  if ( !mTable )
868  {
869  return;
870  }
871 
872  mTable->beginCommand( tr( "Change Table Source" ) );
873  mTable->setSource( static_cast< QgsLayoutItemAttributeTable::ContentSource >( mSourceComboBox->itemData( index ).toInt() ) );
874  mTable->endCommand();
875 
876  toggleSourceControls();
877 }
878 
879 void QgsLayoutAttributeTableWidget::mRelationsComboBox_currentIndexChanged( int index )
880 {
881  if ( !mTable )
882  {
883  return;
884  }
885 
886  mTable->beginCommand( tr( "Change Table Source Relation" ) );
887  mTable->setRelationId( mRelationsComboBox->itemData( index ).toString() );
888  mTable->endCommand();
889 }
890 
891 void QgsLayoutAttributeTableWidget::mEmptyModeComboBox_currentIndexChanged( int index )
892 {
893  if ( !mTable )
894  {
895  return;
896  }
897 
898  mTable->beginCommand( tr( "Change Empty Table Behavior" ) );
899  mTable->setEmptyTableBehavior( static_cast< QgsLayoutTable::EmptyTableMode >( mEmptyModeComboBox->itemData( index ).toInt() ) );
900  mTable->endCommand();
901  mEmptyMessageLineEdit->setEnabled( mTable->emptyTableBehavior() == QgsLayoutTable::ShowMessage );
902  mEmptyMessageLabel->setEnabled( mTable->emptyTableBehavior() == QgsLayoutTable::ShowMessage );
903 }
904 
905 void QgsLayoutAttributeTableWidget::mWrapBehaviorComboBox_currentIndexChanged( int index )
906 {
907  if ( !mTable )
908  {
909  return;
910  }
911 
912  mTable->beginCommand( tr( "Change Table Wrap Mode" ) );
913  mTable->setWrapBehavior( static_cast< QgsLayoutTable::WrapBehavior >( mWrapBehaviorComboBox->itemData( index ).toInt() ) );
914  mTable->endCommand();
915 }
916 
917 void QgsLayoutAttributeTableWidget::mAdvancedCustomizationButton_clicked()
918 {
919  if ( !mTable )
920  {
921  return;
922  }
923 
924  QgsLayoutTableBackgroundColorsDialog d( mTable, this );
925  d.exec();
926 }
927 
928 void QgsLayoutAttributeTableWidget::useConditionalStylingChanged( bool checked )
929 {
930  if ( !mTable )
931  {
932  return;
933  }
934 
935  mTable->beginCommand( tr( "Toggle Table Conditional Styling" ) );
936  mTable->setUseConditionalStyling( checked );
937  mTable->update();
938  mTable->endCommand();
939 }
940 
941 void QgsLayoutAttributeTableWidget::mDrawEmptyCheckBox_toggled( bool checked )
942 {
943  if ( !mTable )
944  {
945  return;
946  }
947 
948  mTable->beginCommand( tr( "Change Show Empty Rows" ) );
949  mTable->setShowEmptyRows( checked );
950  mTable->endCommand();
951 }
952 
953 void QgsLayoutAttributeTableWidget::mEmptyMessageLineEdit_editingFinished()
954 {
955  if ( !mTable )
956  {
957  return;
958  }
959 
960  mTable->beginCommand( tr( "Change Empty Table Message" ) );
961  mTable->setEmptyTableMessage( mEmptyMessageLineEdit->text() );
962  mTable->endCommand();
963 }
964 
965 void QgsLayoutAttributeTableWidget::toggleSourceControls()
966 {
967  switch ( mTable->source() )
968  {
970  mLayerComboBox->setEnabled( true );
971  mLayerComboBox->setVisible( true );
972  mLayerSourceDDBtn->setVisible( true );
973  mLayerLabel->setVisible( true );
974  mRelationsComboBox->setEnabled( false );
975  mRelationsComboBox->setVisible( false );
976  mRelationLabel->setVisible( false );
977  mMaximumRowsSpinBox->setEnabled( true );
978  mMaxNumFeaturesLabel->setEnabled( true );
979  mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
980  mComposerMapComboBox->setEnabled( mTable->displayOnlyVisibleFeatures() );
981  mComposerMapLabel->setEnabled( mTable->displayOnlyVisibleFeatures() );
982  break;
984  mLayerComboBox->setEnabled( false );
985  mLayerComboBox->setVisible( false );
986  mLayerSourceDDBtn->setVisible( false );
987  mLayerLabel->setVisible( false );
988  mRelationsComboBox->setEnabled( false );
989  mRelationsComboBox->setVisible( false );
990  mRelationLabel->setVisible( false );
991  mMaximumRowsSpinBox->setEnabled( false );
992  mMaxNumFeaturesLabel->setEnabled( false );
993  mShowOnlyVisibleFeaturesCheckBox->setEnabled( false );
994  mComposerMapComboBox->setEnabled( false );
995  mComposerMapLabel->setEnabled( false );
996  break;
998  mLayerComboBox->setEnabled( false );
999  mLayerComboBox->setVisible( false );
1000  mLayerLabel->setVisible( false );
1001  mLayerSourceDDBtn->setVisible( false );
1002  mRelationsComboBox->setEnabled( true );
1003  mRelationsComboBox->setVisible( true );
1004  mRelationLabel->setVisible( true );
1005  mMaximumRowsSpinBox->setEnabled( true );
1006  mMaxNumFeaturesLabel->setEnabled( true );
1007  mShowOnlyVisibleFeaturesCheckBox->setEnabled( true );
1008  mComposerMapComboBox->setEnabled( true );
1009  mComposerMapLabel->setEnabled( true );
1010  break;
1011  }
1012 }
Base class for all map layer types.
Definition: qgsmaplayer.h:79
Base class for graphical items within a QgsLayout.
Show header rows only.
Header uses the same alignment as the column.
Don&#39;t automatically create new frames, just use existing frames.
A widget for controlling the common properties of layout items (e.g.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Text which doesn&#39;t fit inside the cell is truncated.
Table shows attributes from related child features.
void toggled(bool)
Emitted when atlas is enabled or disabled.
Shows preset message instead of table contents.
void updateDataDefinedButton(QgsPropertyOverrideButton *button)
Updates a previously registered data defined button to reflect the item&#39;s current properties...
void layerChanged(QgsMapLayer *layer)
Emitted whenever the currently selected layer changes.
Text which doesn&#39;t fit inside the cell is wrapped. Note that this only applies to text in columns wit...
bool setNewItem(QgsLayoutItem *item) override
Attempts to update the widget to show the properties for the specified item.
Table shows attributes from features in a vector layer.
QList< QgsRelation > referencedRelations(const QgsVectorLayer *layer=nullptr) const
Gets all relations where this layer is the referenced part (i.e.
Creates new full page frames on the following page(s) until the entire multiframe content is visible...
A dialog for customization of the cell background colors for a QgsLayoutTable.
Stores properties of a column for a QgsLayoutTable.
Abstract base class for layout items with the ability to distribute the content to several frames (Qg...
void registerDataDefinedButton(QgsPropertyOverrideButton *button, QgsLayoutObject::DataDefinedProperty property)
Registers a data defined button, setting up its initial value, connections and description.
Attribute table source layer.
No headers shown for table.
Align headers right.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Class used to render QgsLayout as an atlas, by iterating over the features from an associated vector ...
QgsLayoutMultiFrame * multiFrame() const
Returns the parent multiframe for the frame.
void changed()
Emitted when the widget&#39;s text format settings are changed.
A layout table subclass that displays attributes from a vector layer.
Header shown on first frame only.
Table shows attributes from the current atlas feature.
void layerChanged(QgsVectorLayer *layer)
Emitted when the context&#39;s layer is changed.
QgsLayoutAttributeTableWidget(QgsLayoutFrame *frame)
constructor
QgsRelationManager relationManager
Definition: qgsproject.h:102
void setMasterLayout(QgsMasterLayoutInterface *masterLayout) override
Sets the master layout associated with the item.
QgsLayoutAtlas * layoutAtlas() const
Returns the atlas for the layout (if available)
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
Definition: qgslayout.h:49
A dialog to select what attributes to display (in the table item), set the column properties and spec...
void itemChanged(QgsLayoutItem *item)
Emitted whenever the currently selected item changes.
Align headers left.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
QgsVectorLayer * coverageLayer() const
Returns the current layout context coverage layer (if set).
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
void changed()
Emitted when relations are added or removed to the manager.
A base class for property widgets for layout items.
virtual int type() const =0
Returns unique multiframe type id.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:450
Headers shown on all frames.
bool enabled() const
Returns whether the atlas generation is enabled.
QgsLayoutTableColumn * clone()
Creates a duplicate column which is a deep copy of this column.
void setItem(QgsLayoutItem *item)
Sets the layout item.
Configure font settings for use with QFont objects.
Definition: qgsfontbutton.h:59
void setReportTypeString(const QString &string) override
Sets the string to use to describe the current report type (e.g.
Interface for master layout type objects, such as print layouts and reports.
Align headers to center.
void changed()
Emitted when the object&#39;s properties change.
Represents a vector layer which manages a vector based data sets.
Base class for frame items, which form a layout multiframe item.
void setPanelTitle(const QString &panelTitle)
Set the title of the panel when shown in the interface.
A generic dialog for building expression strings.
Hides entire table if empty.
void setMasterLayout(QgsMasterLayoutInterface *masterLayout)
Sets the master layout associated with the item.