QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsdualview.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdualview.cpp
3  --------------------------------------
4  Date : 10.2.2013
5  Copyright : (C) 2013 Matthias Kuhn
6  Email : matthias at opengis dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QClipboard>
17 #include <QDialog>
18 #include <QMenu>
19 #include <QMessageBox>
20 #include <QProgressDialog>
21 #include <QGroupBox>
22 #include <QInputDialog>
23 #include <QTimer>
24 #include <QShortcut>
25 
26 #include "qgsapplication.h"
27 #include "qgsactionmanager.h"
28 #include "qgsattributetablemodel.h"
29 #include "qgsdualview.h"
31 #include "qgsfeaturelistmodel.h"
33 #include "qgsmapcanvas.h"
35 #include "qgsmessagelog.h"
36 #include "qgsvectordataprovider.h"
37 #include "qgsvectorlayercache.h"
40 #include "qgssettings.h"
41 #include "qgsscrollarea.h"
42 #include "qgsgui.h"
44 #include "qgsshortcutsmanager.h"
46 #include "qgsmapcanvasutils.h"
47 #include "qgsmessagebar.h"
49 
50 
51 QgsDualView::QgsDualView( QWidget *parent )
52  : QStackedWidget( parent )
53 {
54  setupUi( this );
55  connect( mFeatureListView, &QgsFeatureListView::aboutToChangeEditSelection, this, &QgsDualView::featureListAboutToChangeEditSelection );
56  connect( mFeatureListView, &QgsFeatureListView::currentEditSelectionChanged, this, &QgsDualView::featureListCurrentEditSelectionChanged );
57  connect( mFeatureListView, &QgsFeatureListView::currentEditSelectionProgressChanged, this, &QgsDualView::updateEditSelectionProgress );
58  connect( mFeatureListView, &QgsFeatureListView::willShowContextMenu, this, &QgsDualView::widgetWillShowContextMenu );
59 
60  connect( mTableView, &QgsAttributeTableView::willShowContextMenu, this, &QgsDualView::viewWillShowContextMenu );
61  mTableView->horizontalHeader()->setContextMenuPolicy( Qt::CustomContextMenu );
62  connect( mTableView->horizontalHeader(), &QHeaderView::customContextMenuRequested, this, &QgsDualView::showViewHeaderMenu );
63  connect( mTableView, &QgsAttributeTableView::columnResized, this, &QgsDualView::tableColumnResized );
64 
65  mConditionalFormatWidgetStack->hide();
66  mConditionalFormatWidget = new QgsFieldConditionalFormatWidget( this );
67  mConditionalFormatWidgetStack->setMainPanel( mConditionalFormatWidget );
68  mConditionalFormatWidget->setDockMode( true );
69 
70  const QgsSettings settings;
71  mConditionalSplitter->restoreState( settings.value( QStringLiteral( "/qgis/attributeTable/splitterState" ), QByteArray() ).toByteArray() );
72 
73  mPreviewColumnsMenu = new QMenu( this );
74  mActionPreviewColumnsMenu->setMenu( mPreviewColumnsMenu );
75 
76  // Set preview icon
77  mActionExpressionPreview->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionPreview.svg" ) ) );
78 
79  // Connect layer list preview signals
80  connect( mActionExpressionPreview, &QAction::triggered, this, &QgsDualView::previewExpressionBuilder );
81  connect( mFeatureListView, &QgsFeatureListView::displayExpressionChanged, this, &QgsDualView::previewExpressionChanged );
82 
83  // browsing toolbar
84  connect( mNextFeatureButton, &QToolButton::clicked, mFeatureListView, &QgsFeatureListView::editNextFeature );
85  connect( mPreviousFeatureButton, &QToolButton::clicked, mFeatureListView, &QgsFeatureListView::editPreviousFeature );
86  connect( mFirstFeatureButton, &QToolButton::clicked, mFeatureListView, &QgsFeatureListView::editFirstFeature );
87  connect( mLastFeatureButton, &QToolButton::clicked, mFeatureListView, &QgsFeatureListView::editLastFeature );
88 
89  auto createShortcuts = [ = ]( const QString & objectName, void ( QgsFeatureListView::* slot )() )
90  {
91  QShortcut *sc = QgsGui::shortcutsManager()->shortcutByName( objectName );
92  // do not assert for sc as it would lead to crashes in testing
93  // or when using custom widgets lib if built with Debug
94  if ( sc )
95  connect( sc, &QShortcut::activated, mFeatureListView, slot );
96  };
97  createShortcuts( QStringLiteral( "mAttributeTableFirstEditedFeature" ), &QgsFeatureListView::editFirstFeature );
98  createShortcuts( QStringLiteral( "mAttributeTablePreviousEditedFeature" ), &QgsFeatureListView::editPreviousFeature );
99  createShortcuts( QStringLiteral( "mAttributeTableNextEditedFeature" ), &QgsFeatureListView::editNextFeature );
100  createShortcuts( QStringLiteral( "mAttributeTableLastEditedFeature" ), &QgsFeatureListView::editLastFeature );
101 
102  QButtonGroup *buttonGroup = new QButtonGroup( this );
103  buttonGroup->setExclusive( false );
104  buttonGroup->addButton( mAutoPanButton, PanToFeature );
105  buttonGroup->addButton( mAutoZoomButton, ZoomToFeature );
106  const FeatureListBrowsingAction action = QgsSettings().enumValue( QStringLiteral( "/qgis/attributeTable/featureListBrowsingAction" ), NoAction );
107  QAbstractButton *bt = buttonGroup->button( static_cast<int>( action ) );
108  if ( bt )
109  bt->setChecked( true );
110  connect( buttonGroup, qOverload< QAbstractButton *, bool >( &QButtonGroup::buttonToggled ), this, &QgsDualView::panZoomGroupButtonToggled );
111  mFlashButton->setChecked( QgsSettings().value( QStringLiteral( "/qgis/attributeTable/featureListHighlightFeature" ), true ).toBool() );
112  connect( mFlashButton, &QToolButton::clicked, this, &QgsDualView::flashButtonClicked );
113 }
114 
116 {
117  QgsSettings settings;
118  settings.setValue( QStringLiteral( "/qgis/attributeTable/splitterState" ), mConditionalSplitter->saveState() );
119 }
120 
121 void QgsDualView::init( QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request,
122  const QgsAttributeEditorContext &context, bool loadFeatures, bool showFirstFeature )
123 {
124  if ( !layer )
125  return;
126 
127  delete mAttributeForm;
128  mAttributeForm = nullptr;
129 
130  mLayer = layer;
131 
132  // Keep fields order in sync: force config reset
133  connect( mLayer, &QgsVectorLayer::updatedFields, this, [ = ]
134  {
135  mFilterModel->setAttributeTableConfig( attributeTableConfig(), /* force */ true );
136  } );
137 
138  mEditorContext = context;
139 
140  // create an empty form to find out if it needs geometry or not
141  const QgsAttributeForm emptyForm( mLayer, QgsFeature(), mEditorContext );
142 
143  const bool needsGeometry = mLayer->conditionalStyles()->rulesNeedGeometry() ||
144  !( request.flags() & QgsFeatureRequest::NoGeometry )
146  || emptyForm.needsGeometry();
147 
148  initLayerCache( needsGeometry );
149  initModels( mapCanvas, request, loadFeatures );
150 
151  mConditionalFormatWidget->setLayer( mLayer );
152 
153  mTableView->setModel( mFilterModel );
154  mFeatureListView->setModel( mFeatureListModel );
155 
156  connect( mFilterModel, &QgsAttributeTableFilterModel::sortColumnChanged, this, &QgsDualView::onSortColumnChanged );
157 
158  if ( mFeatureListPreviewButton->defaultAction() )
159  mFeatureListView->setDisplayExpression( mDisplayExpression );
160  else
161  columnBoxInit();
162 
163  // This slows down load of the attribute table heaps and uses loads of memory.
164  //mTableView->resizeColumnsToContents();
165 
166  if ( showFirstFeature && mFeatureListModel->rowCount( ) > 0 )
167  mFeatureListView->setEditSelection( QgsFeatureIds() << mFeatureListModel->data( mFeatureListModel->index( 0, 0 ), QgsFeatureListModel::Role::FeatureRole ).value<QgsFeature>().id() );
168 }
169 
170 void QgsDualView::initAttributeForm( const QgsFeature &feature )
171 {
172  Q_ASSERT( !mAttributeForm );
173 
174  mAttributeForm = new QgsAttributeForm( mLayer, feature, mEditorContext );
175  if ( !mEditorContext.parentContext() )
176  {
177  mAttributeEditorScrollArea = new QgsScrollArea();
178  mAttributeEditorScrollArea->setWidgetResizable( true );
179  mAttributeEditor->layout()->addWidget( mAttributeEditorScrollArea );
180  mAttributeEditorScrollArea->setWidget( mAttributeForm );
181  }
182  else
183  {
184  mAttributeEditor->layout()->addWidget( mAttributeForm );
185  }
186 
187  setAttributeTableConfig( mLayer->attributeTableConfig() );
188 
189  connect( mAttributeForm, &QgsAttributeForm::widgetValueChanged, this, &QgsDualView::featureFormAttributeChanged );
190  connect( mAttributeForm, &QgsAttributeForm::modeChanged, this, &QgsDualView::formModeChanged );
192  connect( mAttributeForm, &QgsAttributeForm::flashFeatures, this, [ = ]( const QString & filter )
193  {
194  if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
195  {
196  QgsMapCanvasUtils::flashMatchingFeatures( canvas, mLayer, filter );
197  }
198  } );
199  connect( mAttributeForm, &QgsAttributeForm::zoomToFeatures, this, [ = ]( const QString & filter )
200  {
201  if ( QgsMapCanvas *canvas = mFilterModel->mapCanvas() )
202  {
203  QgsMapCanvasUtils::zoomToMatchingFeatures( canvas, mLayer, filter );
204  }
205  } );
206 
207  connect( mMasterModel, &QgsAttributeTableModel::modelChanged, mAttributeForm, &QgsAttributeForm::refreshFeature );
208 }
209 
210 void QgsDualView::columnBoxInit()
211 {
212  // load fields
213  const QList<QgsField> fields = mLayer->fields().toList();
214 
215  const QString defaultField;
216 
217  mFeatureListPreviewButton->addAction( mActionExpressionPreview );
218  mFeatureListPreviewButton->addAction( mActionPreviewColumnsMenu );
219 
220  const auto constFields = fields;
221  for ( const QgsField &field : constFields )
222  {
223  const int fieldIndex = mLayer->fields().lookupField( field.name() );
224  if ( fieldIndex == -1 )
225  continue;
226 
227  const QString fieldName = field.name();
228  if ( QgsGui::editorWidgetRegistry()->findBest( mLayer, fieldName ).type() != QLatin1String( "Hidden" ) )
229  {
230  const QIcon icon = mLayer->fields().iconForField( fieldIndex );
231  const QString text = mLayer->attributeDisplayName( fieldIndex );
232 
233  // Generate action for the preview popup button of the feature list
234  QAction *previewAction = new QAction( icon, text, mFeatureListPreviewButton );
235  connect( previewAction, &QAction::triggered, this, [ = ] { previewColumnChanged( previewAction, fieldName ); } );
236  mPreviewColumnsMenu->addAction( previewAction );
237 
238  if ( text == defaultField )
239  {
240  mFeatureListPreviewButton->setDefaultAction( previewAction );
241  }
242  }
243  }
244 
245  QMenu *sortMenu = new QMenu( this );
246  QAction *sortMenuAction = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "sort.svg" ) ), tr( "Sort…" ), this );
247  sortMenuAction->setMenu( sortMenu );
248 
249  QAction *sortByPreviewExpressionAsc = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "sort.svg" ) ), tr( "By Preview Expression (ascending)" ), this );
250  connect( sortByPreviewExpressionAsc, &QAction::triggered, this, [ = ]()
251  {
252  mFeatureListModel->setSortByDisplayExpression( true, Qt::AscendingOrder );
253  } );
254  sortMenu->addAction( sortByPreviewExpressionAsc );
255  QAction *sortByPreviewExpressionDesc = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "sort-reverse.svg" ) ), tr( "By Preview Expression (descending)" ), this );
256  connect( sortByPreviewExpressionDesc, &QAction::triggered, this, [ = ]()
257  {
258  mFeatureListModel->setSortByDisplayExpression( true, Qt::DescendingOrder );
259  } );
260  sortMenu->addAction( sortByPreviewExpressionDesc );
261  QAction *sortByPreviewExpressionCustom = new QAction( QgsApplication::getThemeIcon( QStringLiteral( "mIconExpressionPreview.svg" ) ), tr( "By Custom Expression" ), this );
262  connect( sortByPreviewExpressionCustom, &QAction::triggered, this, [ = ]()
263  {
264  if ( modifySort() )
265  mFeatureListModel->setSortByDisplayExpression( false );
266  } );
267  sortMenu->addAction( sortByPreviewExpressionCustom );
268 
269  mFeatureListPreviewButton->addAction( sortMenuAction );
270 
271  QAction *separator = new QAction( mFeatureListPreviewButton );
272  separator->setSeparator( true );
273  mFeatureListPreviewButton->addAction( separator );
274  restoreRecentDisplayExpressions();
275 
276  // If there is no single field found as preview
277  if ( !mFeatureListPreviewButton->defaultAction() )
278  {
279  mFeatureListView->setDisplayExpression( mLayer->displayExpression() );
280  mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
281  const QString displayExpression = mFeatureListView->displayExpression();
282  setDisplayExpression( displayExpression.isEmpty() ? tr( "'[Please define preview text]'" ) : displayExpression );
283  }
284  else
285  {
286  mFeatureListPreviewButton->defaultAction()->trigger();
287  }
288 }
289 
291 {
292  setCurrentIndex( view );
293 }
294 
296 {
297  return static_cast< QgsDualView::ViewMode >( currentIndex() );
298 }
299 
301 {
302  // cleanup any existing connections
303  switch ( mFilterModel->filterMode() )
304  {
306  disconnect( mFilterModel->mapCanvas(), &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged );
308  break;
309 
313  disconnect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
314  break;
315 
318  disconnect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
319  disconnect( masterModel()->layer(), &QgsVectorLayer::layerModified, this, &QgsDualView::updateEditedAddedFeatures );
320  break;
321 
323  disconnect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
324  break;
325  }
326 
327  QgsFeatureRequest r = mMasterModel->request();
328  const bool needsGeometry = filterMode == QgsAttributeTableFilterModel::ShowVisible;
329 
330  const bool requiresTableReload = ( r.filterType() != QgsFeatureRequest::FilterNone || r.spatialFilterType() != Qgis::SpatialFilterType::NoFilter ) // previous request was subset
331  || ( needsGeometry && r.flags() & QgsFeatureRequest::NoGeometry ) // no geometry for last request
332  || ( mMasterModel->rowCount() == 0 ); // no features
333 
334  if ( !needsGeometry )
336  else
340  r.disableFilter();
341 
342  // setup new connections and filter request parameters
343  switch ( filterMode )
344  {
346  connect( mFilterModel->mapCanvas(), &QgsMapCanvas::extentsChanged, this, &QgsDualView::extentChanged );
347  if ( mFilterModel->mapCanvas() )
348  {
349  const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
350  r.setFilterRect( rect );
351  }
353  break;
354 
356  r.setFilterFids( masterModel()->layer()->editBuffer() ? masterModel()->layer()->editBuffer()->allAddedOrEditedFeatures() : QgsFeatureIds() );
358  connect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
359  connect( masterModel()->layer(), &QgsVectorLayer::layerModified, this, &QgsDualView::updateEditedAddedFeatures );
360  break;
361 
365  connect( mFilterModel, &QgsAttributeTableFilterModel::filterError, this, &QgsDualView::filterError );
366  break;
367 
369  connect( masterModel()->layer(), &QgsVectorLayer::selectionChanged, this, &QgsDualView::updateSelectedFeatures );
370  r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
371  break;
372  }
373 
374  // disable the browsing auto pan/scale if the list only shows visible items
375  switch ( filterMode )
376  {
378  setBrowsingAutoPanScaleAllowed( false );
379  break;
380 
385  setBrowsingAutoPanScaleAllowed( true );
386  break;
387  }
388 
389  if ( requiresTableReload )
390  {
391  //disconnect the connections of the current (old) filtermode before reload
392  mFilterModel->disconnectFilterModeConnections();
393 
394  mMasterModel->setRequest( r );
395  whileBlocking( mLayerCache )->setCacheGeometry( needsGeometry );
396  mMasterModel->loadLayer();
397  }
398 
399  //update filter model
400  mFilterModel->setFilterMode( filterMode );
401  emit filterChanged();
402 }
403 
404 void QgsDualView::setSelectedOnTop( bool selectedOnTop )
405 {
406  mFilterModel->setSelectedOnTop( selectedOnTop );
407 }
408 
409 void QgsDualView::initLayerCache( bool cacheGeometry )
410 {
411  // Initialize the cache
412  const QgsSettings settings;
413  const int cacheSize = settings.value( QStringLiteral( "qgis/attributeTableRowCache" ), "10000" ).toInt();
414  mLayerCache = new QgsVectorLayerCache( mLayer, cacheSize, this );
415  mLayerCache->setCacheGeometry( cacheGeometry );
416  if ( 0 == cacheSize || 0 == ( QgsVectorDataProvider::SelectAtId & mLayer->dataProvider()->capabilities() ) )
417  {
418  connect( mLayerCache, &QgsVectorLayerCache::invalidated, this, &QgsDualView::rebuildFullLayerCache );
419  rebuildFullLayerCache();
420  }
421 }
422 
423 void QgsDualView::initModels( QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request, bool loadFeatures )
424 {
425  delete mFeatureListModel;
426  delete mFilterModel;
427  delete mMasterModel;
428 
429  mMasterModel = new QgsAttributeTableModel( mLayerCache, this );
430  mMasterModel->setRequest( request );
431  mMasterModel->setEditorContext( mEditorContext );
432  mMasterModel->setExtraColumns( 1 ); // Add one extra column which we can "abuse" as an action column
433 
434  connect( mMasterModel, &QgsAttributeTableModel::progress, this, &QgsDualView::progress );
435  connect( mMasterModel, &QgsAttributeTableModel::finished, this, &QgsDualView::finished );
436 
438 
439  if ( loadFeatures )
440  mMasterModel->loadLayer();
441 
442  mFilterModel = new QgsAttributeTableFilterModel( mapCanvas, mMasterModel, mMasterModel );
443 
444  // The following connections to invalidate() are necessary to keep the filter model in sync
445  // see regression https://github.com/qgis/QGIS/issues/23890
446  connect( mMasterModel, &QgsAttributeTableModel::rowsRemoved, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
447  connect( mMasterModel, &QgsAttributeTableModel::rowsInserted, mFilterModel, &QgsAttributeTableFilterModel::invalidate );
448 
450 
451  mFeatureListModel = new QgsFeatureListModel( mFilterModel, mFilterModel );
452  mFeatureListModel->setSortByDisplayExpression( true );
453 }
454 
455 void QgsDualView::restoreRecentDisplayExpressions()
456 {
457  const QVariantList previewExpressions = mLayer->customProperty( QStringLiteral( "dualview/previewExpressions" ) ).toList();
458 
459  for ( const QVariant &previewExpression : previewExpressions )
460  insertRecentlyUsedDisplayExpression( previewExpression.toString() );
461 }
462 
463 void QgsDualView::saveRecentDisplayExpressions() const
464 {
465  if ( ! mLayer )
466  {
467  return;
468  }
469  const QList<QAction *> actions = mFeatureListPreviewButton->actions();
470 
471  // Remove existing same action
472  int index = actions.indexOf( mLastDisplayExpressionAction );
473  if ( index != -1 )
474  {
475  QVariantList previewExpressions;
476  for ( ; index < actions.length(); ++index )
477  {
478  QAction *action = actions.at( index );
479  previewExpressions << action->property( "previewExpression" );
480  }
481 
482  mLayer->setCustomProperty( QStringLiteral( "dualview/previewExpressions" ), previewExpressions );
483  }
484 }
485 
486 void QgsDualView::setDisplayExpression( const QString &expression )
487 {
488  mDisplayExpression = expression;
489  insertRecentlyUsedDisplayExpression( expression );
490 }
491 
492 void QgsDualView::insertRecentlyUsedDisplayExpression( const QString &expression )
493 {
494  const QList<QAction *> actions = mFeatureListPreviewButton->actions();
495 
496  // Remove existing same action
497  const int index = actions.indexOf( mLastDisplayExpressionAction );
498  if ( index != -1 )
499  {
500  for ( int i = 0; index + i < actions.length(); ++i )
501  {
502  QAction *action = actions.at( index );
503  if ( action->text() == expression || i >= 9 )
504  {
505  if ( action == mLastDisplayExpressionAction )
506  mLastDisplayExpressionAction = nullptr;
507  mFeatureListPreviewButton->removeAction( action );
508  }
509  else
510  {
511  if ( !mLastDisplayExpressionAction )
512  mLastDisplayExpressionAction = action;
513  }
514  }
515  }
516 
517  QString name = expression;
518  QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconExpressionPreview.svg" ) );
519  if ( expression.startsWith( QLatin1String( "COALESCE( \"" ) ) && expression.endsWith( QLatin1String( ", '<NULL>' )" ) ) )
520  {
521  name = expression.mid( 11, expression.length() - 24 ); // Numbers calculated from the COALESCE / <NULL> parts
522 
523  const int fieldIndex = mLayer->fields().indexOf( name );
524  if ( fieldIndex != -1 )
525  {
526  name = mLayer->attributeDisplayName( fieldIndex );
527  icon = mLayer->fields().iconForField( fieldIndex );
528  }
529  else
530  {
531  name = expression;
532  }
533  }
534 
535  QAction *previewAction = new QAction( icon, name, mFeatureListPreviewButton );
536  previewAction->setProperty( "previewExpression", expression );
537  connect( previewAction, &QAction::triggered, this, [expression, this]( bool )
538  {
539  setDisplayExpression( expression );
540  mFeatureListPreviewButton->setText( expression );
541  }
542  );
543 
544  mFeatureListPreviewButton->insertAction( mLastDisplayExpressionAction, previewAction );
545  mLastDisplayExpressionAction = previewAction;
546 }
547 
548 void QgsDualView::updateEditSelectionProgress( int progress, int count )
549 {
550  mProgressCount->setText( QStringLiteral( "%1 / %2" ).arg( progress + 1 ).arg( count ) );
551  mPreviousFeatureButton->setEnabled( progress > 0 );
552  mNextFeatureButton->setEnabled( progress + 1 < count );
553  mFirstFeatureButton->setEnabled( progress > 0 );
554  mLastFeatureButton->setEnabled( progress + 1 < count );
555  if ( mAttributeForm )
556  {
557  mAttributeForm->setVisible( count > 0 );
558  }
559 }
560 
561 void QgsDualView::panOrZoomToFeature( const QgsFeatureIds &featureset )
562 {
563  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
564  if ( canvas && view() == AttributeEditor && featureset != mLastFeatureSet )
565  {
566  if ( mBrowsingAutoPanScaleAllowed )
567  {
568  if ( mAutoPanButton->isChecked() )
569  QTimer::singleShot( 0, this, [ = ]()
570  {
571  canvas->panToFeatureIds( mLayer, featureset, false );
572  } );
573  else if ( mAutoZoomButton->isChecked() )
574  QTimer::singleShot( 0, this, [ = ]()
575  {
576  canvas->zoomToFeatureIds( mLayer, featureset );
577  } );
578  }
579  if ( mFlashButton->isChecked() )
580  QTimer::singleShot( 0, this, [ = ]()
581  {
582  canvas->flashFeatureIds( mLayer, featureset );
583  } );
584  mLastFeatureSet = featureset;
585  }
586 }
587 
588 void QgsDualView::setBrowsingAutoPanScaleAllowed( bool allowed )
589 {
590  if ( mBrowsingAutoPanScaleAllowed == allowed )
591  return;
592 
593  mBrowsingAutoPanScaleAllowed = allowed;
594 
595  mAutoPanButton->setEnabled( allowed );
596  mAutoZoomButton->setEnabled( allowed );
597 
598  const QString disabledHint = tr( "(disabled when attribute table only shows features visible in the current map canvas extent)" );
599 
600  mAutoPanButton->setToolTip( tr( "Automatically pan to the current feature" ) + ( allowed ? QString() : QString( ' ' ) + disabledHint ) );
601  mAutoZoomButton->setToolTip( tr( "Automatically zoom to the current feature" ) + ( allowed ? QString() : QString( ' ' ) + disabledHint ) );
602 }
603 
604 void QgsDualView::panZoomGroupButtonToggled( QAbstractButton *button, bool checked )
605 {
606  if ( button == mAutoPanButton && checked )
607  {
608  QgsSettings().setEnumValue( QStringLiteral( "/qgis/attributeTable/featureListBrowsingAction" ), PanToFeature );
609  mAutoZoomButton->setChecked( false );
610  }
611  else if ( button == mAutoZoomButton && checked )
612  {
613  QgsSettings().setEnumValue( QStringLiteral( "/qgis/attributeTable/featureListBrowsingAction" ), ZoomToFeature );
614  mAutoPanButton->setChecked( false );
615  }
616  else
617  {
618  QgsSettings().setEnumValue( QStringLiteral( "/qgis/attributeTable/featureListBrowsingAction" ), NoAction );
619  }
620 
621  if ( checked && mLayer->isSpatial() )
622  panOrZoomToFeature( mFeatureListView->currentEditSelection() );
623 }
624 
625 void QgsDualView::flashButtonClicked( bool clicked )
626 {
627  QgsSettings().setValue( QStringLiteral( "/qgis/attributeTable/featureListHighlightFeature" ), clicked );
628  if ( !clicked )
629  return;
630 
631  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
632 
633  if ( canvas )
634  canvas->flashFeatureIds( mLayer, mFeatureListView->currentEditSelection() );
635 }
636 
637 void QgsDualView::filterError( const QString &errorMessage )
638 {
639  if ( mEditorContext.mainMessageBar() )
640  {
641  mEditorContext.mainMessageBar()->pushWarning( tr( "An error occurred while filtering features" ), errorMessage );
642  }
643 }
644 
645 void QgsDualView::featureListAboutToChangeEditSelection( bool &ok )
646 {
647  if ( !mAttributeForm )
648  return;
649 
650  if ( mLayer->isEditable() && !mAttributeForm->save() )
651  ok = false;
652 }
653 
654 void QgsDualView::featureListCurrentEditSelectionChanged( const QgsFeature &feat )
655 {
656  if ( !mAttributeForm )
657  {
658  initAttributeForm( feat );
659  }
660  else if ( !mLayer->isEditable() || mAttributeForm->save() )
661  {
662  mAttributeForm->setFeature( feat );
663  QgsFeatureIds featureset;
664  featureset << feat.id();
665  setCurrentEditSelection( featureset );
666 
667  if ( mLayer->isSpatial() )
668  panOrZoomToFeature( featureset );
669 
670  }
671  else
672  {
673  // Couldn't save feature
674  }
675 }
676 
678 {
679  mFeatureListView->setCurrentFeatureEdited( false );
680  mFeatureListView->setEditSelection( fids );
681 }
682 
684 {
685  return mAttributeForm ? mAttributeForm->save() : false;
686 }
687 
689 {
690  mConditionalFormatWidgetStack->setVisible( !mConditionalFormatWidgetStack->isVisible() );
691 }
692 
694 {
695  if ( !mAttributeForm )
696  return;
697 
698  if ( enabled )
699  {
700  mPreviousView = view();
702  }
703  else
704  {
705  setView( mPreviousView );
706  }
707 
709 }
710 
711 void QgsDualView::toggleSearchMode( bool enabled )
712 {
713  if ( !mAttributeForm )
714  return;
715 
716  if ( enabled )
717  {
720  mAttributeForm->setVisible( true );
721  }
722  else
723  {
725  mAttributeForm->setVisible( mFilterModel->rowCount( ) > 0 );
726  }
727 
728 }
729 
730 void QgsDualView::previewExpressionBuilder()
731 {
732  // Show expression builder
734 
735  QgsExpressionBuilderDialog dlg( mLayer, mFeatureListView->displayExpression(), this, QStringLiteral( "generic" ), context );
736  dlg.setWindowTitle( tr( "Expression Based Preview" ) );
737  dlg.setExpressionText( mFeatureListView->displayExpression() );
738 
739  if ( dlg.exec() == QDialog::Accepted )
740  {
741  mFeatureListView->setDisplayExpression( dlg.expressionText() );
742  mFeatureListPreviewButton->setDefaultAction( mActionExpressionPreview );
743  mFeatureListPreviewButton->setPopupMode( QToolButton::MenuButtonPopup );
744  }
745 
746  setDisplayExpression( mFeatureListView->displayExpression() );
747 }
748 
749 void QgsDualView::previewColumnChanged( QAction *previewAction, const QString &expression )
750 {
751  if ( !mFeatureListView->setDisplayExpression( QStringLiteral( "COALESCE( \"%1\", '<NULL>' )" ).arg( expression ) ) )
752  {
753  QMessageBox::warning( this,
754  tr( "Column Preview" ),
755  tr( "Could not set column '%1' as preview column.\nParser error:\n%2" )
756  .arg( previewAction->text(), mFeatureListView->parserErrorString() )
757  );
758  }
759  else
760  {
761  mFeatureListPreviewButton->setText( previewAction->text() );
762  mFeatureListPreviewButton->setIcon( previewAction->icon() );
763  mFeatureListPreviewButton->setPopupMode( QToolButton::InstantPopup );
764  }
765 
766  setDisplayExpression( mFeatureListView->displayExpression() );
767 }
768 
770 {
771  return mMasterModel->rowCount();
772 }
773 
775 {
776  return mFilterModel->rowCount();
777 }
778 
780 {
781  const QModelIndex currentIndex = mTableView->currentIndex();
782  if ( !currentIndex.isValid() )
783  {
784  return;
785  }
786 
787  const QVariant var = mMasterModel->data( currentIndex, Qt::DisplayRole );
788  QApplication::clipboard()->setText( var.toString() );
789 }
790 
792 {
793  if ( mProgressDlg )
794  mProgressDlg->cancel();
795 }
796 
797 void QgsDualView::parentFormValueChanged( const QString &attribute, const QVariant &newValue )
798 {
799  if ( mAttributeForm )
800  {
801  mAttributeForm->parentFormValueChanged( attribute, newValue );
802  }
803 }
804 
805 void QgsDualView::hideEvent( QHideEvent *event )
806 {
807  Q_UNUSED( event )
808  saveRecentDisplayExpressions();
809 }
810 
811 void QgsDualView::viewWillShowContextMenu( QMenu *menu, const QModelIndex &masterIndex )
812 {
813  if ( !menu )
814  {
815  return;
816  }
817 
818  QAction *copyContentAction = menu->addAction( tr( "Copy Cell Content" ) );
819  menu->addAction( copyContentAction );
820  connect( copyContentAction, &QAction::triggered, this, [masterIndex, this]
821  {
822  const QVariant var = mMasterModel->data( masterIndex, Qt::DisplayRole );
823  QApplication::clipboard()->setText( var.toString() );
824  } );
825 
826  QgsVectorLayer *vl = mFilterModel->layer();
827  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
828  if ( canvas && vl && vl->geometryType() != QgsWkbTypes::NullGeometry )
829  {
830  QAction *zoomToFeatureAction = menu->addAction( tr( "Zoom to Feature" ) );
831  connect( zoomToFeatureAction, &QAction::triggered, this, &QgsDualView::zoomToCurrentFeature );
832 
833  QAction *panToFeatureAction = menu->addAction( tr( "Pan to Feature" ) );
834  connect( panToFeatureAction, &QAction::triggered, this, &QgsDualView::panToCurrentFeature );
835 
836  QAction *flashFeatureAction = menu->addAction( tr( "Flash Feature" ) );
837  connect( flashFeatureAction, &QAction::triggered, this, &QgsDualView::flashCurrentFeature );
838  }
839 
840  //add user-defined actions to context menu
841  const QList<QgsAction> actions = mLayer->actions()->actions( QStringLiteral( "Field" ) );
842  if ( !actions.isEmpty() )
843  {
844  QAction *a = menu->addAction( tr( "Run Layer Action" ) );
845  a->setEnabled( false );
846 
847  for ( const QgsAction &action : actions )
848  {
849  if ( !action.runable() )
850  continue;
851 
852  if ( vl && !vl->isEditable() && action.isEnabledOnlyWhenEditable() )
853  continue;
854 
855  QgsAttributeTableAction *a = new QgsAttributeTableAction( action.name(), this, action.id(), masterIndex );
856  menu->addAction( action.name(), a, &QgsAttributeTableAction::execute );
857  }
858  }
859  const QModelIndex rowSourceIndex = mMasterModel->index( masterIndex.row(), 0 );
860  if ( ! rowSourceIndex.isValid() )
861  {
862  return;
863  }
864 
865  //add actions from QgsMapLayerActionRegistry to context menu
866  const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::Layer | QgsMapLayerAction::SingleFeature );
867  if ( !registeredActions.isEmpty() )
868  {
869  //add a separator between user defined and standard actions
870  menu->addSeparator();
871 
872  for ( QgsMapLayerAction *action : registeredActions )
873  {
874  QgsAttributeTableMapLayerAction *a = new QgsAttributeTableMapLayerAction( action->text(), this, action, rowSourceIndex );
875  menu->addAction( action->text(), a, &QgsAttributeTableMapLayerAction::execute );
876  }
877  }
878 
879  // entries for multiple features layer actions
880  // only show if the context menu is shown over a selected row
881  const QgsFeatureId currentFid = mMasterModel->rowToId( masterIndex.row() );
882  if ( mLayer->selectedFeatureCount() > 1 && mLayer->selectedFeatureIds().contains( currentFid ) )
883  {
884  const QList<QgsMapLayerAction *> registeredActions = QgsGui::mapLayerActionRegistry()->mapLayerActions( mLayer, QgsMapLayerAction::MultipleFeatures );
885  if ( !registeredActions.isEmpty() )
886  {
887  menu->addSeparator();
888  QAction *action = menu->addAction( tr( "Actions on Selection (%1)" ).arg( mLayer->selectedFeatureCount() ) );
889  action->setEnabled( false );
890 
891  for ( QgsMapLayerAction *action : registeredActions )
892  {
893  menu->addAction( action->text(), action, [ = ]() {action->triggerForFeatures( mLayer, mLayer->selectedFeatures() );} );
894  }
895  }
896  }
897 
898  menu->addSeparator();
899  QgsAttributeTableAction *a = new QgsAttributeTableAction( tr( "Open Form" ), this, QUuid(), rowSourceIndex );
900  menu->addAction( tr( "Open Form…" ), a, &QgsAttributeTableAction::featureForm );
901 }
902 
903 
904 void QgsDualView::widgetWillShowContextMenu( QgsActionMenu *menu, const QModelIndex &atIndex )
905 {
906  emit showContextMenuExternally( menu, mFilterModel->rowToId( atIndex ) );
907 }
908 
909 
910 void QgsDualView::showViewHeaderMenu( QPoint point )
911 {
912  const int col = mTableView->columnAt( point.x() );
913 
914  delete mHorizontalHeaderMenu;
915  mHorizontalHeaderMenu = new QMenu( this );
916 
917  QAction *hide = new QAction( tr( "&Hide Column" ), mHorizontalHeaderMenu );
918  connect( hide, &QAction::triggered, this, &QgsDualView::hideColumn );
919  hide->setData( col );
920  mHorizontalHeaderMenu->addAction( hide );
921  QAction *setWidth = new QAction( tr( "&Set Width…" ), mHorizontalHeaderMenu );
922  connect( setWidth, &QAction::triggered, this, &QgsDualView::resizeColumn );
923  setWidth->setData( col );
924  mHorizontalHeaderMenu->addAction( setWidth );
925 
926  QAction *setWidthAllColumns = new QAction( tr( "&Set All Column Widths…" ), mHorizontalHeaderMenu );
927  connect( setWidthAllColumns, &QAction::triggered, this, &QgsDualView::resizeAllColumns );
928  setWidthAllColumns->setData( col );
929  mHorizontalHeaderMenu->addAction( setWidthAllColumns );
930 
931  QAction *optimizeWidth = new QAction( tr( "&Autosize" ), mHorizontalHeaderMenu );
932  connect( optimizeWidth, &QAction::triggered, this, &QgsDualView::autosizeColumn );
933  optimizeWidth->setData( col );
934  mHorizontalHeaderMenu->addAction( optimizeWidth );
935 
936  QAction *optimizeWidthAllColumns = new QAction( tr( "&Autosize All Columns" ), mHorizontalHeaderMenu );
937  connect( optimizeWidthAllColumns, &QAction::triggered, this, &QgsDualView::autosizeAllColumns );
938  mHorizontalHeaderMenu->addAction( optimizeWidthAllColumns );
939 
940 
941  mHorizontalHeaderMenu->addSeparator();
942  QAction *organize = new QAction( tr( "&Organize Columns…" ), mHorizontalHeaderMenu );
943  connect( organize, &QAction::triggered, this, &QgsDualView::organizeColumns );
944  mHorizontalHeaderMenu->addAction( organize );
945  QAction *sort = new QAction( tr( "&Sort…" ), mHorizontalHeaderMenu );
946  connect( sort, &QAction::triggered, this, [ = ]() {modifySort();} );
947  mHorizontalHeaderMenu->addAction( sort );
948 
949  mHorizontalHeaderMenu->popup( mTableView->horizontalHeader()->mapToGlobal( point ) );
950 }
951 
952 void QgsDualView::organizeColumns()
953 {
954  if ( !mLayer )
955  {
956  return;
957  }
958 
959  QgsOrganizeTableColumnsDialog dialog( mLayer, attributeTableConfig(), this );
960  if ( dialog.exec() == QDialog::Accepted )
961  {
962  const QgsAttributeTableConfig config = dialog.config();
963  setAttributeTableConfig( config );
964  }
965 }
966 
967 void QgsDualView::tableColumnResized( int column, int width )
968 {
969  QgsAttributeTableConfig config = mConfig;
970  const int sourceCol = config.mapVisibleColumnToIndex( column );
971  if ( sourceCol >= 0 && config.columnWidth( sourceCol ) != width )
972  {
973  config.setColumnWidth( sourceCol, width );
974  setAttributeTableConfig( config );
975  }
976 }
977 
978 void QgsDualView::hideColumn()
979 {
980  QAction *action = qobject_cast<QAction *>( sender() );
981  const int col = action->data().toInt();
982  QgsAttributeTableConfig config = mConfig;
983  const int sourceCol = mConfig.mapVisibleColumnToIndex( col );
984  if ( sourceCol >= 0 )
985  {
986  config.setColumnHidden( sourceCol, true );
987  setAttributeTableConfig( config );
988  }
989 }
990 
991 void QgsDualView::resizeColumn()
992 {
993  QAction *action = qobject_cast<QAction *>( sender() );
994  const int col = action->data().toInt();
995  if ( col < 0 )
996  return;
997 
998  QgsAttributeTableConfig config = mConfig;
999  const int sourceCol = config.mapVisibleColumnToIndex( col );
1000  if ( sourceCol >= 0 )
1001  {
1002  bool ok = false;
1003  const int width = QInputDialog::getInt( this, tr( "Set column width" ), tr( "Enter column width" ),
1004  mTableView->columnWidth( col ),
1005  0, 1000, 10, &ok );
1006  if ( ok )
1007  {
1008  config.setColumnWidth( sourceCol, width );
1009  setAttributeTableConfig( config );
1010  }
1011  }
1012 }
1013 
1014 void QgsDualView::resizeAllColumns()
1015 {
1016  QAction *action = qobject_cast<QAction *>( sender() );
1017  const int col = action->data().toInt();
1018  if ( col < 0 )
1019  return;
1020 
1021  QgsAttributeTableConfig config = mConfig;
1022 
1023  bool ok = false;
1024  const int width = QInputDialog::getInt( this, tr( "Set Column Width" ), tr( "Enter column width" ),
1025  mTableView->columnWidth( col ),
1026  1, 1000, 10, &ok );
1027  if ( ok )
1028  {
1029  const int colCount = mTableView->model()->columnCount();
1030  if ( colCount > 0 )
1031  {
1032  for ( int i = 0; i < colCount; i++ )
1033  {
1034  config.setColumnWidth( i, width );
1035  }
1036  setAttributeTableConfig( config );
1037  }
1038  }
1039 }
1040 
1041 void QgsDualView::autosizeColumn()
1042 {
1043  QAction *action = qobject_cast<QAction *>( sender() );
1044  const int col = action->data().toInt();
1045  mTableView->resizeColumnToContents( col );
1046 }
1047 
1048 void QgsDualView::autosizeAllColumns()
1049 {
1050  mTableView->resizeColumnsToContents();
1051 }
1052 
1053 bool QgsDualView::modifySort()
1054 {
1055  if ( !mLayer )
1056  return false;
1057 
1058  QgsAttributeTableConfig config = mConfig;
1059 
1060  QDialog orderByDlg;
1061  orderByDlg.setWindowTitle( tr( "Configure Attribute Table Sort Order" ) );
1062  QDialogButtonBox *dialogButtonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel );
1063  QGridLayout *layout = new QGridLayout();
1064  connect( dialogButtonBox, &QDialogButtonBox::accepted, &orderByDlg, &QDialog::accept );
1065  connect( dialogButtonBox, &QDialogButtonBox::rejected, &orderByDlg, &QDialog::reject );
1066  orderByDlg.setLayout( layout );
1067 
1068  QGroupBox *sortingGroupBox = new QGroupBox();
1069  sortingGroupBox->setTitle( tr( "Defined sort order in attribute table" ) );
1070  sortingGroupBox->setCheckable( true );
1071  sortingGroupBox->setChecked( !sortExpression().isEmpty() );
1072  layout->addWidget( sortingGroupBox );
1073  sortingGroupBox->setLayout( new QGridLayout() );
1074 
1075  QgsExpressionBuilderWidget *expressionBuilder = new QgsExpressionBuilderWidget();
1077 
1078  expressionBuilder->initWithLayer( mLayer, context, QStringLiteral( "generic" ) );
1079  expressionBuilder->setExpressionText( sortExpression().isEmpty() ? mLayer->displayExpression() : sortExpression() );
1080 
1081  sortingGroupBox->layout()->addWidget( expressionBuilder );
1082 
1083  QCheckBox *cbxSortAscending = new QCheckBox( tr( "Sort ascending" ) );
1084  cbxSortAscending->setChecked( config.sortOrder() == Qt::AscendingOrder );
1085  sortingGroupBox->layout()->addWidget( cbxSortAscending );
1086 
1087  layout->addWidget( dialogButtonBox );
1088  if ( orderByDlg.exec() )
1089  {
1090  const Qt::SortOrder sortOrder = cbxSortAscending->isChecked() ? Qt::AscendingOrder : Qt::DescendingOrder;
1091  if ( sortingGroupBox->isChecked() )
1092  {
1093  setSortExpression( expressionBuilder->expressionText(), sortOrder );
1094  config.setSortExpression( expressionBuilder->expressionText() );
1095  config.setSortOrder( sortOrder );
1096  }
1097  else
1098  {
1099  setSortExpression( QString(), sortOrder );
1100  config.setSortExpression( QString() );
1101  }
1102 
1103  setAttributeTableConfig( config );
1104  return true;
1105  }
1106  else
1107  {
1108  return false;
1109  }
1110 
1111 }
1112 
1113 void QgsDualView::zoomToCurrentFeature()
1114 {
1115  const QModelIndex currentIndex = mTableView->currentIndex();
1116  if ( !currentIndex.isValid() )
1117  {
1118  return;
1119  }
1120 
1121  QgsFeatureIds ids;
1122  ids.insert( mFilterModel->rowToId( currentIndex ) );
1123  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1124  if ( canvas )
1125  {
1126  canvas->zoomToFeatureIds( mLayer, ids );
1127  }
1128 }
1129 
1130 void QgsDualView::panToCurrentFeature()
1131 {
1132  const QModelIndex currentIndex = mTableView->currentIndex();
1133  if ( !currentIndex.isValid() )
1134  {
1135  return;
1136  }
1137 
1138  QgsFeatureIds ids;
1139  ids.insert( mFilterModel->rowToId( currentIndex ) );
1140  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1141  if ( canvas )
1142  {
1143  canvas->panToFeatureIds( mLayer, ids );
1144  }
1145 }
1146 
1147 void QgsDualView::flashCurrentFeature()
1148 {
1149  const QModelIndex currentIndex = mTableView->currentIndex();
1150  if ( !currentIndex.isValid() )
1151  {
1152  return;
1153  }
1154 
1155  QgsFeatureIds ids;
1156  ids.insert( mFilterModel->rowToId( currentIndex ) );
1157  QgsMapCanvas *canvas = mFilterModel->mapCanvas();
1158  if ( canvas )
1159  {
1160  canvas->flashFeatureIds( mLayer, ids );
1161  }
1162 }
1163 
1164 void QgsDualView::rebuildFullLayerCache()
1165 {
1166  connect( mLayerCache, &QgsVectorLayerCache::progress, this, &QgsDualView::progress, Qt::UniqueConnection );
1167  connect( mLayerCache, &QgsVectorLayerCache::finished, this, &QgsDualView::finished, Qt::UniqueConnection );
1168 
1169  mLayerCache->setFullCache( true );
1170 }
1171 
1172 void QgsDualView::previewExpressionChanged( const QString &expression )
1173 {
1174  mLayer->setDisplayExpression( expression );
1175 }
1176 
1177 void QgsDualView::onSortColumnChanged()
1178 {
1180  if ( cfg.sortExpression() != mFilterModel->sortExpression() ||
1181  cfg.sortOrder() != mFilterModel->sortOrder() )
1182  {
1183  cfg.setSortExpression( mFilterModel->sortExpression() );
1184  cfg.setSortOrder( mFilterModel->sortOrder() );
1185  setAttributeTableConfig( cfg );
1186  }
1187 }
1188 
1189 void QgsDualView::updateSelectedFeatures()
1190 {
1191  QgsFeatureRequest r = mMasterModel->request();
1193  return; // already requested all features
1194 
1195  r.setFilterFids( masterModel()->layer()->selectedFeatureIds() );
1196  mMasterModel->setRequest( r );
1197  mMasterModel->loadLayer();
1198  emit filterChanged();
1199 }
1200 
1201 void QgsDualView::updateEditedAddedFeatures()
1202 {
1203  QgsFeatureRequest r = mMasterModel->request();
1205  return; // already requested all features
1206 
1207  r.setFilterFids( masterModel()->layer()->editBuffer() ? masterModel()->layer()->editBuffer()->allAddedOrEditedFeatures() : QgsFeatureIds() );
1208  mMasterModel->setRequest( r );
1209  mMasterModel->loadLayer();
1210  emit filterChanged();
1211 }
1212 
1213 void QgsDualView::extentChanged()
1214 {
1215  QgsFeatureRequest r = mMasterModel->request();
1216  if ( mFilterModel->mapCanvas() && ( r.filterType() != QgsFeatureRequest::FilterNone || !r.filterRect().isNull() ) )
1217  {
1218  const QgsRectangle rect = mFilterModel->mapCanvas()->mapSettings().mapToLayerCoordinates( mLayer, mFilterModel->mapCanvas()->extent() );
1219  r.setFilterRect( rect );
1220  mMasterModel->setRequest( r );
1221  mMasterModel->loadLayer();
1222  }
1223  emit filterChanged();
1224 }
1225 
1226 void QgsDualView::featureFormAttributeChanged( const QString &attribute, const QVariant &value, bool attributeChanged )
1227 {
1228  Q_UNUSED( attribute )
1229  Q_UNUSED( value )
1230  if ( attributeChanged )
1231  {
1232  mFeatureListView->setCurrentFeatureEdited( true );
1233  mAttributeForm->save();
1234  }
1235 }
1236 
1237 void QgsDualView::setFilteredFeatures( const QgsFeatureIds &filteredFeatures )
1238 {
1239  mFilterModel->setFilteredFeatures( filteredFeatures );
1240 }
1241 
1242 void QgsDualView::filterFeatures( const QgsExpression &filterExpression, const QgsExpressionContext &context )
1243 {
1244  mFilterModel->setFilterExpression( filterExpression, context );
1245  mFilterModel->filterFeatures();
1246 }
1247 
1248 
1250 {
1251  mMasterModel->setRequest( request );
1252 }
1253 
1255 {
1256  mTableView->setFeatureSelectionManager( featureSelectionManager );
1257  mFeatureListView->setFeatureSelectionManager( featureSelectionManager );
1258 
1259  if ( mFeatureSelectionManager && mFeatureSelectionManager->parent() == this )
1260  delete mFeatureSelectionManager;
1261 
1262  mFeatureSelectionManager = featureSelectionManager;
1263 }
1264 
1266 {
1267  mConfig = config;
1268  mConfig.update( mLayer->fields() );
1269  mLayer->setAttributeTableConfig( mConfig );
1270  mFilterModel->setAttributeTableConfig( mConfig );
1271  mTableView->setAttributeTableConfig( mConfig );
1272 }
1273 
1274 void QgsDualView::setSortExpression( const QString &sortExpression, Qt::SortOrder sortOrder )
1275 {
1276  if ( sortExpression.isNull() )
1277  mFilterModel->sort( -1 );
1278  else
1279  mFilterModel->sort( sortExpression, sortOrder );
1280 
1281  mConfig.setSortExpression( sortExpression );
1282  mConfig.setSortOrder( sortOrder );
1283  setAttributeTableConfig( mConfig );
1284 }
1285 
1287 {
1288  return mFilterModel->sortExpression();
1289 }
1290 
1292 {
1293  return mConfig;
1294 }
1295 
1296 void QgsDualView::progress( int i, bool &cancel )
1297 {
1298  if ( !mProgressDlg )
1299  {
1300  mProgressDlg = new QProgressDialog( tr( "Loading features…" ), tr( "Abort" ), 0, 0, this );
1301  mProgressDlg->setWindowTitle( tr( "Attribute Table" ) );
1302  mProgressDlg->setWindowModality( Qt::WindowModal );
1303  mProgressDlg->show();
1304  }
1305 
1306  mProgressDlg->setLabelText( tr( "%L1 features loaded." ).arg( i ) );
1307  QCoreApplication::processEvents();
1308 
1309  cancel = mProgressDlg && mProgressDlg->wasCanceled();
1310 }
1311 
1312 void QgsDualView::finished()
1313 {
1314  delete mProgressDlg;
1315  mProgressDlg = nullptr;
1316 }
1317 
1318 /*
1319  * QgsAttributeTableAction
1320  */
1321 
1323 {
1324  mDualView->masterModel()->executeAction( mAction, mFieldIdx );
1325 }
1326 
1328 {
1329  QgsFeatureIds editedIds;
1330  editedIds << mDualView->masterModel()->rowToId( mFieldIdx.row() );
1331  mDualView->setCurrentEditSelection( editedIds );
1332  mDualView->setView( QgsDualView::AttributeEditor );
1333 }
1334 
1335 /*
1336  * QgsAttributeTableMapLayerAction
1337  */
1338 
1340 {
1341  mDualView->masterModel()->executeMapLayerAction( mAction, mFieldIdx );
1342 }
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
QgsAttributeTableConfig::sortOrder
Qt::SortOrder sortOrder() const
Gets the sort order.
Definition: qgsattributetableconfig.cpp:244
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsAttributeEditorContext::SingleEditMode
@ SingleEditMode
Single edit mode, for editing a single feature.
Definition: qgsattributeeditorcontext.h:49
QgsAttributeTableFilterModel::ShowAll
@ ShowAll
Show all features.
Definition: qgsattributetablefiltermodel.h:47
qgsexpressioncontextutils.h
QgsAttributeForm::modeChanged
void modeChanged(QgsAttributeEditorContext::Mode mode)
Emitted when the form changes mode.
QgsGui::editorWidgetRegistry
static QgsEditorWidgetRegistry * editorWidgetRegistry()
Returns the global editor widget registry, used for managing all known edit widget factories.
Definition: qgsgui.cpp:85
QgsAttributeForm::flashFeatures
void flashFeatures(const QString &filter)
Emitted when the user chooses to flash a filtered set of features.
QgsFeatureListView::displayExpressionChanged
void displayExpressionChanged(const QString &expression)
Emitted whenever the display expression is successfully changed.
QgsDualView::copyCellContent
void copyCellContent() const
Copy the content of the selected cell in the clipboard.
Definition: qgsdualview.cpp:779
QgsAttributeTableAction::featureForm
void featureForm()
Definition: qgsdualview.cpp:1327
QgsFeatureListView::editPreviousFeature
void editPreviousFeature()
editPreviousFeature will try to edit previous feature of the list
Definition: qgsfeaturelistview.h:213
QgsMapCanvas::extent
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Definition: qgsmapcanvas.cpp:1331
QgsAttributeTableConfig::sortExpression
QString sortExpression() const
Gets the expression used for sorting.
Definition: qgsattributetableconfig.cpp:209
QgsDualView::NoAction
@ NoAction
No action is done.
Definition: qgsdualview.h:76
QgsMapSettings::mapToLayerCoordinates
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
Definition: qgsmapsettings.cpp:633
QgsMapLayerAction
An action which can run on map layers The class can be used in two manners:
Definition: qgsmaplayeractionregistry.h:38
qgsvectorlayercache.h
QgsMapLayerAction::SingleFeature
@ SingleFeature
Definition: qgsmaplayeractionregistry.h:46
QgsAttributeTableFilterModel::sortExpression
QString sortExpression() const
The expression which is used to sort the attribute table.
Definition: qgsattributetablefiltermodel.cpp:261
qgsshortcutsmanager.h
QgsVectorLayerCache
This class caches features of a given QgsVectorLayer.
Definition: qgsvectorlayercache.h:46
Qgis::SpatialFilterType::NoFilter
@ NoFilter
No spatial filtering of features.
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:161
QgsDualView::QgsDualView
QgsDualView(QWidget *parent=nullptr)
Constructor.
Definition: qgsdualview.cpp:51
QgsAttributeTableFilterModel::visibleReloaded
void visibleReloaded()
Emitted when the the visible features on extend are reloaded (the list is created)
QgsAttributeTableModel::progress
void progress(int i, bool &cancel)
qgsmapcanvas.h
QgsWkbTypes::NullGeometry
@ NullGeometry
Definition: qgswkbtypes.h:146
QgsExpressionBuilderWidget
A reusable widget that can be used to build a expression string. See QgsExpressionBuilderDialog for e...
Definition: qgsexpressionbuilderwidget.h:42
QgsPanelWidget::setDockMode
virtual void setDockMode(bool dockMode)
Set the widget in dock mode which tells the widget to emit panel widgets and not open dialogs.
Definition: qgspanelwidget.cpp:44
QgsDualView::view
ViewMode view() const
Returns the current view mode.
Definition: qgsdualview.cpp:295
QgsGui::mapLayerActionRegistry
static QgsMapLayerActionRegistry * mapLayerActionRegistry()
Returns the global map layer action registry, used for registering map layer actions.
Definition: qgsgui.cpp:125
QgsDualView::formModeChanged
void formModeChanged(QgsAttributeEditorContext::Mode mode)
Emitted when the form changes mode.
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:437
QgsAttributeTableConfig::setSortOrder
void setSortOrder(Qt::SortOrder sortOrder)
Set the sort order.
Definition: qgsattributetableconfig.cpp:249
qgsmapcanvasutils.h
QgsDualView::PanToFeature
@ PanToFeature
The map is panned to the center of the feature bounding-box.
Definition: qgsdualview.h:77
qgsgui.h
QgsDualView::setMultiEditEnabled
void setMultiEditEnabled(bool enabled)
Sets whether multi edit mode is enabled.
Definition: qgsdualview.cpp:693
QgsFieldConditionalFormatWidget::setLayer
void setLayer(QgsVectorLayer *layer)
Sets the vector layer associated with the widget.
Definition: qgsfieldconditionalformatwidget.cpp:49
QgsAttributeTableFilterModel::ShowFilteredList
@ ShowFilteredList
Show only features whose ids are on the filter list. {.
Definition: qgsattributetablefiltermodel.h:50
QgsFeatureRequest::filterType
FilterType filterType() const
Returns the attribute/ID filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:355
QgsDualView::setView
void setView(ViewMode view)
Change the current view mode.
Definition: qgsdualview.cpp:290
QgsAttributeTableConfig::columnWidth
int columnWidth(int column) const
Returns the width of a column, or -1 if column should use default width.
Definition: qgsattributetableconfig.cpp:219
QgsAttributeForm::setFeature
void setFeature(const QgsFeature &feature)
Update all editors to correspond to a different feature.
Definition: qgsattributeform.cpp:292
QgsMapLayerAction::MultipleFeatures
@ MultipleFeatures
Definition: qgsmaplayeractionregistry.h:47
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsDualView::filterChanged
void filterChanged()
Emitted whenever the filter changes.
QgsAttributeTableFilterModel::sort
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
Definition: qgsattributetablefiltermodel.cpp:81
QgsDualView::attributeTableConfig
QgsAttributeTableConfig attributeTableConfig() const
The config used for the attribute table.
Definition: qgsdualview.cpp:1291
qgsdualview.h
QgsDualView::setFilteredFeatures
Q_DECL_DEPRECATED void setFilteredFeatures(const QgsFeatureIds &filteredFeatures)
Set a list of currently visible features.
Definition: qgsdualview.cpp:1237
QgsAttributeForm::save
bool save()
Save all the values from the editors to the layer.
Definition: qgsattributeform.cpp:821
QgsAttributeTableModel::modelChanged
void modelChanged()
Model has been changed.
QgsFeatureRequest::filterRect
QgsRectangle filterRect() const
Returns the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:117
QgsAttributeTableFilterModel::ShowEdited
@ ShowEdited
Show only features which have unsaved changes.
Definition: qgsattributetablefiltermodel.h:51
QgsExpressionContextUtils::globalProjectLayerScopes
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Definition: qgsexpressioncontextutils.cpp:377
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:61
QgsAttributeEditorContext::SearchMode
@ SearchMode
Form values are used for searching/filtering the layer.
Definition: qgsattributeeditorcontext.h:54
qgsfeaturelistmodel.h
QgsFeatureListView
Shows a list of features and renders a edit button next to each feature.
Definition: qgsfeaturelistview.h:46
QgsAttributeForm::zoomToFeatures
void zoomToFeatures(const QString &filter)
Emitted when the user chooses to zoom to a filtered set of features.
field
const QgsField & field
Definition: qgsfield.h:463
QgsDualView::toggleSearchMode
void toggleSearchMode(bool enabled)
Toggles whether search mode should be enabled in the form.
Definition: qgsdualview.cpp:711
QgsVectorLayerCache::invalidated
void invalidated()
The cache has been invalidated and cleared.
QgsAttributeTableModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows.
Definition: qgsattributetablemodel.cpp:609
QgsAttributeTableModel::executeAction
void executeAction(QUuid action, const QModelIndex &idx) const
Execute an action.
Definition: qgsattributetablemodel.cpp:919
QgsField::name
QString name
Definition: qgsfield.h:60
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsFeatureListModel::data
QVariant data(const QModelIndex &index, int role) const override
Definition: qgsfeaturelistmodel.cpp:61
QgsFeatureListModel::rowCount
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition: qgsfeaturelistmodel.cpp:414
QgsFeatureRequest::disableFilter
QgsFeatureRequest & disableFilter()
Disables any attribute/ID filtering.
Definition: qgsfeaturerequest.h:602
QgsDualView::cancelProgress
void cancelProgress()
Cancel the progress dialog (if any)
Definition: qgsdualview.cpp:791
QgsFeatureRequest::flags
Flags flags() const
Returns the flags which affect how features are fetched.
Definition: qgsfeaturerequest.h:673
QgsFieldConditionalFormatWidget
A widget for customizing conditional formatting options.
Definition: qgsfieldconditionalformatwidget.h:35
QgsAttributeTableModel::executeMapLayerAction
void executeMapLayerAction(QgsMapLayerAction *action, const QModelIndex &idx) const
Execute a QgsMapLayerAction.
Definition: qgsattributetablemodel.cpp:925
QgsAttributeTableFilterModel::mapCanvas
QgsMapCanvas * mapCanvas() const
Returns the map canvas.
Definition: qgsattributetablefiltermodel.h:223
QgsDualView::FeatureListBrowsingAction
FeatureListBrowsingAction
Action on the map canvas when browsing the list of features.
Definition: qgsdualview.h:74
qgsapplication.h
QgsDualView::init
void init(QgsVectorLayer *layer, QgsMapCanvas *mapCanvas, const QgsFeatureRequest &request=QgsFeatureRequest(), const QgsAttributeEditorContext &context=QgsAttributeEditorContext(), bool loadFeatures=true, bool showFirstFeature=true)
Has to be called to initialize the dual view.
Definition: qgsdualview.cpp:121
QgsDualView::masterModel
QgsAttributeTableModel * masterModel() const
Returns the model which has the information about all features (not only filtered)
Definition: qgsdualview.h:186
QgsVectorDataProvider::SelectAtId
@ SelectAtId
Fast access to features using their ID.
Definition: qgsvectordataprovider.h:81
QgsFeatureListView::editLastFeature
void editLastFeature()
editLastFeature will try to edit the last feature of the list
Definition: qgsfeaturelistview.h:219
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:101
qgsifeatureselectionmanager.h
QgsDualView::filteredFeatures
QgsFeatureIds filteredFeatures()
Gets a list of currently visible feature ids.
Definition: qgsdualview.h:179
QgsAttributeForm::parentFormValueChanged
void parentFormValueChanged(const QString &attribute, const QVariant &newValue)
Is called in embedded forms when an attribute value in the parent form has changed to newValue.
Definition: qgsattributeform.cpp:1434
QgsAttributeTableConfig
This is a container for configuration of the attribute table. The configuration is specific for one v...
Definition: qgsattributetableconfig.h:36
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsDualView::saveEditChanges
bool saveEditChanges()
saveEditChanges
Definition: qgsdualview.cpp:683
QgsAttributeForm::refreshFeature
void refreshFeature()
reload current feature
Definition: qgsattributeform.cpp:1420
QgsVectorLayerCache::finished
void finished()
When filling the cache, this signal gets emitted once the cache is fully initialized.
QgsVectorLayerCache::progress
void progress(int i, bool &cancel)
When filling the cache, this signal gets emitted periodically to notify about the progress and to be ...
QgsDualView::ZoomToFeature
@ ZoomToFeature
The map is zoomed to contained the feature bounding-box.
Definition: qgsdualview.h:78
qgsscrollarea.h
QgsAttributeTableFilterModel::featuresFiltered
void featuresFiltered()
Emitted when the filtering of the features has been done.
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:2191
QgsAttributeTableAction::execute
void execute()
Definition: qgsdualview.cpp:1322
QgsAttributeTableConfig::mapVisibleColumnToIndex
int mapVisibleColumnToIndex(int visibleColumn) const
Maps a visible column index to its original column index.
Definition: qgsattributetableconfig.cpp:35
qgsactionmanager.h
QgsVectorLayer::selectionChanged
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
QgsAttributeTableModel::rowToId
QgsFeatureId rowToId(int row) const
Maps row to feature id.
Definition: qgsattributetablemodel.cpp:587
QgsShortcutsManager::shortcutByName
QShortcut * shortcutByName(const QString &name) const
Returns a shortcut by its name, or nullptr if nothing found.
Definition: qgsshortcutsmanager.cpp:313
QgsAttributeTableModel::setRequest
void setRequest(const QgsFeatureRequest &request)
Set a request that will be used to fill this attribute table model.
Definition: qgsattributetablemodel.cpp:1044
QgsAttributeTableFilterModel::sortColumnChanged
void sortColumnChanged(int column, Qt::SortOrder order)
Emitted whenever the sort column is changed.
QgsAttributeTableFilterModel::layer
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
Definition: qgsattributetablefiltermodel.h:160
QgsMapLayerAction::Layer
@ Layer
Definition: qgsmaplayeractionregistry.h:45
QgsAttributeTableModel
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
Definition: qgsattributetablemodel.h:49
QgsExpressionBuilderDialog
A generic dialog for building expression strings.
Definition: qgsexpressionbuilderdialog.h:30
QgsAttributeTableAction
Definition: qgsdualview.h:459
QgsSettings::setEnumValue
void setEnumValue(const QString &key, const T &value, const Section section=NoSection)
Set the value of a setting based on an enum.
Definition: qgssettings.h:334
QgsDualView::setAttributeTableConfig
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table config which should be used to control the appearance of the attribute table.
Definition: qgsdualview.cpp:1265
QgsFieldConditionalFormatWidget::rulesUpdated
void rulesUpdated(const QString &fieldName)
Emitted when the conditional styling rules are updated.
QgsMapCanvas::extentsChanged
void extentsChanged()
Emitted when the extents of the map change.
QgsDualView::filterMode
QgsAttributeTableFilterModel::FilterMode filterMode()
Gets the filter mode.
Definition: qgsdualview.h:134
QgsDualView::AttributeEditor
@ AttributeEditor
Show a list of the features, where one can be chosen and the according attribute dialog will be prese...
Definition: qgsdualview.h:68
QgsAttributeEditorContext::MultiEditMode
@ MultiEditMode
Multi edit mode, for editing fields of multiple features at once.
Definition: qgsattributeeditorcontext.h:53
qgsvectordataprovider.h
QgsDualView::setSelectedOnTop
void setSelectedOnTop(bool selectedOnTop)
Toggle the selectedOnTop flag.
Definition: qgsdualview.cpp:404
QgsMapLayerActionRegistry::mapLayerActions
QList< QgsMapLayerAction * > mapLayerActions(QgsMapLayer *layer, QgsMapLayerAction::Targets targets=QgsMapLayerAction::AllActions)
Returns the map layer actions which can run on the specified layer.
Definition: qgsmaplayeractionregistry.cpp:125
QgsDualView::setSortExpression
void setSortExpression(const QString &sortExpression, Qt::SortOrder sortOrder=Qt::AscendingOrder)
Set the expression used for sorting the table and feature list.
Definition: qgsdualview.cpp:1274
QgsAttributeTableConfig::setColumnWidth
void setColumnWidth(int column, int width)
Sets the width of a column.
Definition: qgsattributetableconfig.cpp:224
QgsActionMenu
This class is a menu that is populated automatically with the actions defined for a given layer.
Definition: qgsactionmenu.h:37
QgsAttributeTableFilterModel::setAttributeTableConfig
void setAttributeTableConfig(const QgsAttributeTableConfig &config, bool force=false)
Set the attribute table configuration to control which fields are shown, in which order they are show...
Definition: qgsattributetablefiltermodel.cpp:148
QgsAttributeTableFilterModel::setSelectedOnTop
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
Definition: qgsattributetablefiltermodel.cpp:266
QgsFeatureRequest::setFilterFids
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
Definition: qgsfeaturerequest.cpp:148
QgsAttributeTableModel::finished
void finished()
QgsDualView::hideEvent
void hideEvent(QHideEvent *event) override
Definition: qgsdualview.cpp:805
qgsmessagebar.h
QgsAttributeTableFilterModel::rowToId
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
Definition: qgsattributetablefiltermodel.cpp:666
qgsattributetablemodel.h
QgsSettings::setValue
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Definition: qgssettings.cpp:279
QgsMapLayer::layerModified
void layerModified()
Emitted when modifications has been done on layer.
qgsmaplayeractionregistry.h
QgsAttributeTableModel::loadLayer
virtual void loadLayer()
Loads the layer into the model Preferably to be called, before using this model as source for any oth...
Definition: qgsattributetablemodel.cpp:460
QgsDualView::setFilterMode
void setFilterMode(QgsAttributeTableFilterModel::FilterMode filterMode)
Set the filter mode.
Definition: qgsdualview.cpp:300
QgsMapCanvas::panToFeatureIds
void panToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids, bool alwaysRecenter=true)
Centers canvas extent to feature ids.
Definition: qgsmapcanvas.cpp:1735
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsDualView::setCurrentEditSelection
void setCurrentEditSelection(const QgsFeatureIds &fids)
Set the current edit selection in the AttributeEditor mode.
Definition: qgsdualview.cpp:677
QgsFeatureRequest::spatialFilterType
Qgis::SpatialFilterType spatialFilterType() const
Returns the spatial filter type which is currently set on this request.
Definition: qgsfeaturerequest.h:369
qgsorganizetablecolumnsdialog.h
QgsDualView::ViewMode
ViewMode
The view modes, in which this widget can present information.
Definition: qgsdualview.h:55
QgsScrollArea
A QScrollArea subclass with improved scrolling behavior.
Definition: qgsscrollarea.h:41
QgsAction
Utility class that encapsulates an action based on vector attributes.
Definition: qgsaction.h:34
QgsAttributeTableFilterModel::filterError
void filterError(const QString &errorMessage)
Emitted when an error occurred while filtering features.
QgsMapCanvas::flashFeatureIds
void flashFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids, const QColor &startColor=QColor(255, 0, 0, 255), const QColor &endColor=QColor(255, 0, 0, 0), int flashes=3, int duration=500)
Causes a set of features with matching ids from a vector layer to flash within the canvas.
Definition: qgsmapcanvas.cpp:1853
QgsAttributeTableFilterModel::setFilterMode
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
Definition: qgsattributetablefiltermodel.cpp:332
QgsAttributeTableFilterModel
Definition: qgsattributetablefiltermodel.h:36
QgsAttributeTableFilterModel::disconnectFilterModeConnections
void disconnectFilterModeConnections()
Disconnect the connections set for the current filterMode.
Definition: qgsattributetablefiltermodel.cpp:343
QgsAttributeTableConfig::setColumnHidden
void setColumnHidden(int column, bool hidden)
Sets whether the specified column should be hidden.
Definition: qgsattributetableconfig.cpp:234
QgsVectorLayerCache::setFullCache
void setFullCache(bool fullCache)
This enables or disables full caching.
Definition: qgsvectorlayercache.cpp:89
QgsAttributeTableMapLayerAction::execute
void execute()
Definition: qgsdualview.cpp:1339
qgseditorwidgetregistry.h
QgsAttributeForm::setMode
void setMode(QgsAttributeEditorContext::Mode mode)
Sets the current mode of the form.
Definition: qgsattributeform.cpp:139
QgsAttributeTableModel::data
QVariant data(const QModelIndex &index, int role) const override
Returns data on the given index.
Definition: qgsattributetablemodel.cpp:661
QgsAttributeTableFilterModel::ShowSelected
@ ShowSelected
Show only selected features.
Definition: qgsattributetablefiltermodel.h:48
QgsAttributeTableModel::fieldConditionalStyleChanged
void fieldConditionalStyleChanged(const QString &fieldName)
Handles updating the model when the conditional style for a field changes.
Definition: qgsattributetablemodel.cpp:513
QgsDualView::sortExpression
QString sortExpression() const
Gets the expression used for sorting the table and feature list.
Definition: qgsdualview.cpp:1286
QgsAttributeTableFilterModel::setFilterExpression
void setFilterExpression(const QgsExpression &expression, const QgsExpressionContext &context)
Set the expression and the context to be stored in case of the features need to be filtered again (li...
Definition: qgsattributetablefiltermodel.cpp:245
QgsFeatureListModel
Definition: qgsfeaturelistmodel.h:39
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsAttributeTableFilterModel::filterFeatures
void filterFeatures()
Updates the filtered features in the filter model.
Definition: qgsattributetablefiltermodel.cpp:476
QgsDualView::parentFormValueChanged
void parentFormValueChanged(const QString &attribute, const QVariant &value)
Called in embedded forms when an attribute value in the parent form has changed.
Definition: qgsdualview.cpp:797
QgsFeatureListView::currentEditSelectionChanged
void currentEditSelectionChanged(QgsFeature &feat)
Emitted whenever the current edit selection has been changed.
QgsFeatureListView::willShowContextMenu
void willShowContextMenu(QgsActionMenu *menu, const QModelIndex &atIndex)
Emitted when the context menu is created to add the specific actions to it.
qgssettings.h
QgsMessageBar::pushWarning
void pushWarning(const QString &title, const QString &message)
Pushes a warning message that must be manually dismissed by the user.
Definition: qgsmessagebar.cpp:205
QgsDualView::setFeatureSelectionManager
void setFeatureSelectionManager(QgsIFeatureSelectionManager *featureSelectionManager)
Set the feature selection model.
Definition: qgsdualview.cpp:1254
QgsVectorLayerCache::setCacheGeometry
void setCacheGeometry(bool cacheGeometry)
Enable or disable the caching of geometries.
Definition: qgsvectorlayercache.cpp:65
QgsAttributeTableFilterModel::setFilteredFeatures
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
Definition: qgsattributetablefiltermodel.cpp:313
QgsAttributeTableModel::setExtraColumns
void setExtraColumns(int extraColumns)
Empty extra columns to announce from this model.
Definition: qgsattributetablemodel.cpp:107
QgsDualView::~QgsDualView
~QgsDualView() override
Definition: qgsdualview.cpp:115
QgsDualView::featureCount
int featureCount()
Returns the number of features on the layer.
Definition: qgsdualview.cpp:769
QgsAttributeForm::filterExpressionSet
void filterExpressionSet(const QString &expression, QgsAttributeForm::FilterType type)
Emitted when a filter expression is set using the form.
QgsDualView::filteredFeatureCount
int filteredFeatureCount()
Returns the number of features which are currently visible, according to the filter restrictions.
Definition: qgsdualview.cpp:774
QgsDualView::filterFeatures
void filterFeatures(const QgsExpression &filterExpression, const QgsExpressionContext &context)
Sets the expression and Updates the filtered features in the filter model.
Definition: qgsdualview.cpp:1242
QgsGui::shortcutsManager
static QgsShortcutsManager * shortcutsManager()
Returns the global shortcuts manager, used for managing a QAction and QShortcut sequences.
Definition: qgsgui.cpp:115
QgsFeatureRequest::FilterNone
@ FilterNone
No filter is applied.
Definition: qgsfeaturerequest.h:115
QgsAttributeForm::widgetValueChanged
void widgetValueChanged(const QString &attribute, const QVariant &value, bool attributeChanged)
Notifies about changes of attributes.
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsFeatureListModel::setSortByDisplayExpression
void setSortByDisplayExpression(bool sortByDisplayExpression, Qt::SortOrder order=Qt::AscendingOrder)
Sort this model by its display expression.
Definition: qgsfeaturelistmodel.cpp:298
QgsDualView::filterExpressionSet
void filterExpressionSet(const QString &expression, QgsAttributeForm::FilterType type)
Emitted when a filter expression is set using the view.
QgsDualView::showContextMenuExternally
void showContextMenuExternally(QgsActionMenu *menu, QgsFeatureId fid)
Emitted when selecting context menu on the feature list to create the context menu individually.
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsFeatureListView::editFirstFeature
void editFirstFeature()
editFirstFeature will try to edit the first feature of the list
Definition: qgsfeaturelistview.h:201
QgsAttributeForm
Definition: qgsattributeform.h:44
QgsAttributeTableView::willShowContextMenu
void willShowContextMenu(QMenu *menu, const QModelIndex &atIndex)
Emitted in order to provide a hook to add additional* menu entries to the context menu.
QgsAttributeTableFilterModel::filterMode
FilterMode filterMode()
The current filterModel.
Definition: qgsattributetablefiltermodel.h:153
QgsMapCanvas::zoomToFeatureIds
void zoomToFeatureIds(QgsVectorLayer *layer, const QgsFeatureIds &ids)
Set canvas extent to the bounding box of a set of features.
Definition: qgsmapcanvas.cpp:1711
QgsVectorLayer::updatedFields
void updatedFields()
Emitted whenever the fields available from this layer have been changed.
QgsIFeatureSelectionManager
Is an interface class to abstract feature selection handling.
Definition: qgsifeatureselectionmanager.h:31
qgsfieldconditionalformatwidget.h
QgsSettings::enumValue
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:282
QgsExpressionBuilderWidget::setExpressionText
void setExpressionText(const QString &expression)
Sets the expression string for the widget.
Definition: qgsexpressionbuilderwidget.cpp:666
QgsAttributeEditorContext::parentContext
const QgsAttributeEditorContext * parentContext() const
Definition: qgsattributeeditorcontext.h:230
QgsAttributeTableMapLayerAction
Definition: qgsdualview.h:491
QgsAttributeTableModel::request
const QgsFeatureRequest & request() const
Gets the the feature request.
Definition: qgsattributetablemodel.cpp:1051
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
QgsExpressionBuilderWidget::initWithLayer
void initWithLayer(QgsVectorLayer *layer, const QgsExpressionContext &context=QgsExpressionContext(), const QString &recentCollection=QStringLiteral("generic"), QgsExpressionBuilderWidget::Flags flags=LoadAll)
Initialize with a layer.
Definition: qgsexpressionbuilderwidget.cpp:265
QgsAttributeEditorContext
This class contains context information for attribute editor widgets. It will be passed to embedded w...
Definition: qgsattributeeditorcontext.h:40
QgsAttributeTableConfig::setSortExpression
void setSortExpression(const QString &sortExpression)
Set the sort expression used for sorting.
Definition: qgsattributetableconfig.cpp:214
QgsAttributeTableFilterModel::FilterMode
FilterMode
The filter mode defines how the rows should be filtered.
Definition: qgsattributetablefiltermodel.h:45
QgsExpressionBuilderWidget::expressionText
QString expressionText()
Gets the expression string that has been set in the expression area.
Definition: qgsexpressionbuilderwidget.cpp:661
QgsDualView::setRequest
void setRequest(const QgsFeatureRequest &request)
Set the request.
Definition: qgsdualview.cpp:1249
QgsAttributeTableModel::setEditorContext
void setEditorContext(const QgsAttributeEditorContext &context)
Sets the context in which this table is shown.
Definition: qgsattributetablemodel.h:237
QgsAttributeEditorContext::mainMessageBar
QgsMessageBar * mainMessageBar()
Returns the main message bar.
Definition: qgsattributeeditorcontext.h:292
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsFeatureListView::editNextFeature
void editNextFeature()
editNextFeature will try to edit next feature of the list
Definition: qgsfeaturelistview.h:207
QgsAttributeTableView::columnResized
void columnResized(int column, int width)
Emitted when a column in the view has been resized.
QgsFeatureListView::currentEditSelectionProgressChanged
void currentEditSelectionProgressChanged(int progress, int count)
Emitted whenever the current edit selection has been changed.
QgsFeatureListView::aboutToChangeEditSelection
void aboutToChangeEditSelection(bool &ok)
QgsRectangle::isNull
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:479
QgsDualView::displayExpressionChanged
void displayExpressionChanged(const QString &expression)
Emitted whenever the display expression is successfully changed.
qgsvectorlayereditbuffer.h
QgsDualView::openConditionalStyles
void openConditionalStyles()
Definition: qgsdualview.cpp:688
QgsAttributeTableFilterModel::ShowVisible
@ ShowVisible
Show only visible features (depends on the map canvas)
Definition: qgsattributetablefiltermodel.h:49
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
qgsmessagelog.h
qgsexpressionbuilderdialog.h
QgsAttributeForm::needsGeometry
bool needsGeometry() const
Returns true if any of the form widgets need feature geometry.
Definition: qgsattributeform.cpp:1446
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50
QgsAttributeTableConfig::update
void update(const QgsFields &fields)
Update the configuration with the given fields.
Definition: qgsattributetableconfig.cpp:55