QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
qgsattributetablefiltermodel.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  QgsAttributeTableFilterModel.cpp
3  --------------------------------------
4  Date : Feb 2009
5  Copyright : (C) 2009 Vita Cizek
6  Email : weetya (at) gmail.com
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 <QItemSelectionModel>
17 
18 #include "qgis.h"
20 #include "qgsattributetablemodel.h"
21 #include "qgsfeatureiterator.h"
22 #include "qgsvectorlayer.h"
24 #include "qgsfeature.h"
25 #include "qgsmapcanvas.h"
26 #include "qgslogger.h"
27 #include "qgsrenderer.h"
30 #include "qgsapplication.h"
31 
33 // Filter Model //
35 
37  : QSortFilterProxyModel( parent )
38  , mCanvas( canvas )
39 {
40  setSourceModel( sourceModel );
41  setDynamicSortFilter( true );
42  setSortRole( QgsAttributeTableModel::SortRole );
43  connect( layer(), &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableFilterModel::selectionChanged );
44 
45  mReloadVisibleTimer.setSingleShot( true );
46  connect( &mReloadVisibleTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::reloadVisible );
47  mFilterFeaturesTimer.setSingleShot( true );
48  connect( &mFilterFeaturesTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::filterFeatures );
49 }
50 
51 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
52 {
53  if ( mSelectedOnTop )
54  {
55  bool leftSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( left.row() ) );
56  bool rightSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( right.row() ) );
57 
58  if ( leftSelected && !rightSelected )
59  {
60  return sortOrder() == Qt::AscendingOrder;
61  }
62  else if ( rightSelected && !leftSelected )
63  {
64  return sortOrder() == Qt::DescendingOrder;
65  }
66  }
67 
68  if ( mTableModel->sortCacheExpression().isEmpty() )
69  {
70  //shortcut when no sort order set
71  return false;
72  }
73 
75  right.data( QgsAttributeTableModel::SortRole ) );
76 }
77 
78 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
79 {
80  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
81  order = Qt::AscendingOrder;
82  if ( column < 0 || column >= mColumnMapping.size() )
83  {
84  sort( QString() );
85  }
86  else
87  {
88  int myColumn = mColumnMapping.at( column );
89  masterModel()->prefetchColumnData( myColumn );
90  QSortFilterProxyModel::sort( myColumn, order );
91  }
92  emit sortColumnChanged( column, order );
93 }
94 
95 QVariant QgsAttributeTableFilterModel::data( const QModelIndex &index, int role ) const
96 {
97  if ( mapColumnToSource( index.column() ) == -1 ) // actions
98  {
99  if ( role == TypeRole )
100  return ColumnTypeActionButton;
101  else if ( role == QgsAttributeTableModel::FeatureIdRole )
102  {
103  QModelIndex fieldIndex = QSortFilterProxyModel::mapToSource( QSortFilterProxyModel::index( index.row(), 0, index.parent() ) );
104  return sourceModel()->data( fieldIndex, QgsAttributeTableModel::FeatureIdRole );
105  }
106  }
107  else if ( role == TypeRole )
108  return ColumnTypeField;
109 
110  return QSortFilterProxyModel::data( index, role );
111 }
112 
113 QVariant QgsAttributeTableFilterModel::headerData( int section, Qt::Orientation orientation, int role ) const
114 {
115  if ( orientation == Qt::Horizontal )
116  {
117  if ( mColumnMapping.at( section ) == -1 && role == Qt::DisplayRole )
118  return tr( "Actions" );
119  else
120  return QSortFilterProxyModel::headerData( section, orientation, role );
121  }
122  else
123  {
124  if ( role == Qt::DisplayRole )
125  return section + 1;
126  else
127  {
128  int sourceSection = mapToSource( index( section, ( !mColumnMapping.isEmpty() && mColumnMapping.at( 0 ) == -1 ) ? 1 : 0 ) ).row();
129  return sourceModel()->headerData( sourceSection, orientation, role );
130  }
131  }
132 }
133 
135 {
136  return mColumnMapping.indexOf( -1 );
137 }
138 
139 int QgsAttributeTableFilterModel::columnCount( const QModelIndex &parent ) const
140 {
141  Q_UNUSED( parent )
142  return mColumnMapping.count();
143 }
144 
146 {
147  QgsAttributeTableConfig oldConfig = mConfig;
148  mConfig = config;
149  mConfig.update( layer()->fields() );
150 
151  if ( mConfig.hasSameColumns( oldConfig ) )
152  {
153  return;
154  }
155 
156  QVector<int> newColumnMapping;
157  const auto constColumns = mConfig.columns();
158  for ( const QgsAttributeTableConfig::ColumnConfig &columnConfig : constColumns )
159  {
160  // Hidden? Forget about this column
161  if ( columnConfig.hidden )
162  continue;
163 
164  // The new value for the mapping (field index or -1 for action column)
165  int newValue = ( columnConfig.type == QgsAttributeTableConfig::Action ) ? -1 : layer()->fields().lookupField( columnConfig.name );
166  newColumnMapping << newValue;
167  }
168 
169  if ( newColumnMapping != mColumnMapping )
170  {
171  bool requiresReset = false;
172  int firstRemovedColumn = -1;
173  int removedColumnCount = 0;
174 
175  // Check if there have a contiguous set of columns have been removed or if we require a full reset
176  for ( int i = 0; i < std::min( newColumnMapping.size(), mColumnMapping.size() - removedColumnCount ); ++i )
177  {
178  if ( newColumnMapping.at( i ) == mColumnMapping.at( i + removedColumnCount ) )
179  continue;
180 
181  if ( firstRemovedColumn == -1 )
182  {
183  firstRemovedColumn = i;
184 
185  while ( i < mColumnMapping.size() - removedColumnCount && mColumnMapping.at( i + removedColumnCount ) != newColumnMapping.at( i ) )
186  {
187  ++removedColumnCount;
188  }
189  }
190  else
191  {
192  requiresReset = true;
193  break;
194  }
195  }
196 
197  // No difference found so far
198  if ( firstRemovedColumn == -1 )
199  {
200  if ( newColumnMapping.size() > mColumnMapping.size() )
201  {
202  // More columns: appended to the end
203  beginInsertColumns( QModelIndex(), mColumnMapping.size(), newColumnMapping.size() - 1 );
204  mColumnMapping = newColumnMapping;
205  endInsertColumns();
206  }
207  else
208  {
209  // Less columns: removed from the end
210  beginRemoveColumns( QModelIndex(), newColumnMapping.size(), mColumnMapping.size() - 1 );
211  mColumnMapping = newColumnMapping;
212  endRemoveColumns();
213  }
214  }
215  else
216  {
217  if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount )
218  {
219  //the amount of removed column in the model need to be equal removedColumnCount
220  beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount - 1 );
221  mColumnMapping = newColumnMapping;
222  endRemoveColumns();
223  }
224  else
225  {
226  requiresReset = true;
227  }
228  }
229 
230  if ( requiresReset )
231  {
232  beginResetModel();
233  mColumnMapping = newColumnMapping;
234  endResetModel();
235  }
236  }
237 
238  if ( !config.sortExpression().isEmpty() )
239  sort( config.sortExpression(), config.sortOrder() );
240 }
241 
243 {
244  mFilterExpression = expression;
245  mFilterExpressionContext = context;
246 }
247 
248 void QgsAttributeTableFilterModel::sort( const QString &expression, Qt::SortOrder order )
249 {
250  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
251  order = Qt::AscendingOrder;
252 
253  QSortFilterProxyModel::sort( -1 );
254  masterModel()->prefetchSortData( expression );
255  QSortFilterProxyModel::sort( 0, order );
256 }
257 
259 {
260  return masterModel()->sortCacheExpression();
261 }
262 
264 {
265  if ( mSelectedOnTop != selectedOnTop )
266  {
267  mSelectedOnTop = selectedOnTop;
268  int column = sortColumn();
269  Qt::SortOrder order = sortOrder();
270 
271  // set default sort values if they are not correctly set
272  if ( column < 0 )
273  column = 0;
274 
275  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
276  order = Qt::AscendingOrder;
277 
278  sort( 0, Qt::AscendingOrder );
279  invalidate();
280  }
281 }
282 
284 {
285  mTableModel = sourceModel;
286 
287  for ( int i = 0; i < mTableModel->columnCount() - mTableModel->extraColumns(); ++i )
288  {
289  mColumnMapping.append( i );
290  }
291 
292  QSortFilterProxyModel::setSourceModel( sourceModel );
293 
294  // Disconnect any code to update columns in the parent, we handle this manually
295  disconnect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
296  disconnect( mTableModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsInserted( QModelIndex, int, int ) ) );
297  disconnect( mTableModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
298  disconnect( mTableModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsRemoved( QModelIndex, int, int ) ) );
299  // The following connections are needed in order to keep the filter model in sync, see: regression #15974
300  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeInserted, this, &QgsAttributeTableFilterModel::onColumnsChanged );
301  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeRemoved, this, &QgsAttributeTableFilterModel::onColumnsChanged );
302 
303 }
304 
306 {
307  return mSelectedOnTop;
308 }
309 
311 {
312  mFilteredFeatures = ids;
314  invalidateFilter();
315 }
316 
318 {
319  QgsFeatureIds ids;
320  ids.reserve( rowCount() );
321  for ( int i = 0; i < rowCount(); ++i )
322  {
323  QModelIndex row = index( i, 0 );
324  ids << rowToId( row );
325  }
326  return ids;
327 }
328 
330 {
331  if ( filterMode != mFilterMode )
332  {
335  mFilterMode = filterMode;
336  invalidateFilter();
337  }
338 }
339 
341 {
342  // cleanup existing connections
343  switch ( mFilterMode )
344  {
345  case ShowVisible:
346  disconnect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
347  disconnect( mCanvas, &QgsMapCanvas::temporalRangeChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
348  disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
349  disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
350  break;
351  case ShowAll:
352  case ShowEdited:
353  case ShowSelected:
354  break;
355  case ShowFilteredList:
356  disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
357  disconnect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
358  disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
359  break;
360  }
361 }
362 
364 {
365  // setup new connections
366  switch ( filterMode )
367  {
368  case ShowVisible:
369  connect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
370  connect( mCanvas, &QgsMapCanvas::temporalRangeChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
371  connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
372  connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
374  break;
375  case ShowAll:
376  case ShowEdited:
377  case ShowSelected:
378  break;
379  case ShowFilteredList:
380  connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
381  connect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
382  connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
383  break;
384  }
385 }
386 
387 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
388 {
389  Q_UNUSED( sourceParent )
390  switch ( mFilterMode )
391  {
392  case ShowAll:
393  return true;
394 
395  case ShowFilteredList:
396  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
397 
398  case ShowSelected:
399  return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );
400 
401  case ShowVisible:
402  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
403 
404  case ShowEdited:
405  {
406  QgsVectorLayerEditBuffer *editBuffer = layer()->editBuffer();
407  if ( editBuffer )
408  {
409  QgsFeatureId fid = masterModel()->rowToId( sourceRow );
410 
411  if ( editBuffer->isFeatureAdded( fid ) )
412  return true;
413 
414  if ( editBuffer->isFeatureAttributesChanged( fid ) )
415  return true;
416 
417  if ( editBuffer->isFeatureGeometryChanged( fid ) )
418  return true;
419 
420  return false;
421  }
422  return false;
423  }
424 
425  default:
426  Q_ASSERT( false ); // In debug mode complain
427  return true; // In release mode accept row
428  }
429  // returns are handled in their respective case statement above
430 }
431 
433 {
434  reloadVisible();
435 }
436 
437 void QgsAttributeTableFilterModel::reloadVisible()
438 {
440  invalidateFilter();
441  emit visibleReloaded();
442 }
443 
444 void QgsAttributeTableFilterModel::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
445 {
446  Q_UNUSED( fid );
447  Q_UNUSED( value );
448 
449  if ( mFilterExpression.referencedAttributeIndexes( layer()->fields() ).contains( idx ) )
450  {
451  startTimedFilterFeatures();
452  }
453 }
454 
455 void QgsAttributeTableFilterModel::onGeometryChanged()
456 {
457  if ( mFilterExpression.needsGeometry() )
458  {
459  startTimedFilterFeatures();
460  }
461 }
462 
463 void QgsAttributeTableFilterModel::startTimedReloadVisible()
464 {
465  mReloadVisibleTimer.start( 10 );
466 }
467 
468 void QgsAttributeTableFilterModel::startTimedFilterFeatures()
469 {
470  mFilterFeaturesTimer.start( 10 );
471 }
472 
474 {
475  if ( !mFilterExpression.isValid() )
476  return;
477 
479  QgsDistanceArea distanceArea;
480 
481  distanceArea.setSourceCrs( mTableModel->layer()->crs(), QgsProject::instance()->transformContext() );
482  distanceArea.setEllipsoid( QgsProject::instance()->ellipsoid() );
483 
484  const bool fetchGeom = mFilterExpression.needsGeometry();
485 
486  QApplication::setOverrideCursor( Qt::WaitCursor );
487 
488  mFilterExpression.setGeomCalculator( &distanceArea );
489  mFilterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
490  mFilterExpression.setAreaUnits( QgsProject::instance()->areaUnits() );
491  QgsFeatureRequest request( mTableModel->request() );
492  request.setSubsetOfAttributes( mFilterExpression.referencedColumns(), mTableModel->layer()->fields() );
493  if ( !fetchGeom )
494  {
496  }
497  else
498  {
499  // force geometry extraction if the filter requests it
500  request.setFlags( request.flags() & ~QgsFeatureRequest::NoGeometry );
501  }
502  QgsFeatureIterator featIt = mTableModel->layer()->getFeatures( request );
503 
504  QgsFeature f;
505 
506  // Record the first evaluation error
507  QString error;
508 
509  while ( featIt.nextFeature( f ) )
510  {
511  mFilterExpressionContext.setFeature( f );
512  if ( mFilterExpression.evaluate( &mFilterExpressionContext ).toInt() != 0 )
513  filteredFeatures << f.id();
514 
515  // check if there were errors during evaluating
516  if ( mFilterExpression.hasEvalError() && error.isEmpty() )
517  {
518  error = mFilterExpression.evalErrorString( );
519  }
520  }
521 
522  featIt.close();
523 
525 
526  QApplication::restoreOverrideCursor();
527 
528  emit featuresFiltered();
529 
530  if ( ! error.isEmpty() )
531  {
532  emit filterError( error );
533  }
534 
535 }
536 
537 
538 void QgsAttributeTableFilterModel::selectionChanged()
539 {
540  if ( ShowSelected == mFilterMode )
541  {
542  invalidateFilter();
543  }
544  else if ( mSelectedOnTop )
545  {
546  invalidate();
547  }
548 }
549 
550 void QgsAttributeTableFilterModel::onColumnsChanged()
551 {
552  setAttributeTableConfig( mConfig );
553 }
554 
555 int QgsAttributeTableFilterModel::mapColumnToSource( int column ) const
556 {
557  if ( mColumnMapping.isEmpty() )
558  return column;
559  if ( column < 0 || column >= mColumnMapping.size() )
560  return -1;
561  else
562  return mColumnMapping.at( column );
563 }
564 
565 int QgsAttributeTableFilterModel::mapColumnFromSource( int column ) const
566 {
567  if ( mColumnMapping.isEmpty() )
568  return column;
569  else
570  return mColumnMapping.indexOf( column );
571 }
572 
574 {
575  if ( !layer() )
576  return;
577 
578  bool filter = false;
579  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
580  QgsRenderContext renderContext;
582 
583  mFilteredFeatures.clear();
584  if ( !layer()->renderer() )
585  {
586  QgsDebugMsg( QStringLiteral( "Cannot get renderer" ) );
587  return;
588  }
589 
590  std::unique_ptr< QgsFeatureRenderer > renderer( layer()->renderer()->clone() );
591 
592  const QgsMapSettings &ms = mCanvas->mapSettings();
593  if ( !layer()->isInScaleRange( ms.scale() ) )
594  {
595  QgsDebugMsg( QStringLiteral( "Out of scale limits" ) );
596  }
597  else
598  {
599  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
600  {
601  // setup scale
602  // mapRenderer()->renderContext()->scale is not automatically updated when
603  // render extent changes (because it's scale is used to identify if changed
604  // since last render) -> use local context
605  renderContext.setExtent( ms.visibleExtent() );
606  renderContext.setMapToPixel( ms.mapToPixel() );
607  renderContext.setRendererScale( ms.scale() );
608  }
609 
610  filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
611  }
612 
613  renderer->startRender( renderContext, layer()->fields() );
614 
615  QgsFeatureRequest r( masterModel()->request() );
616  if ( !r.filterRect().isNull() )
617  {
618  r.setFilterRect( r.filterRect().intersect( rect ) );
619  }
620  else
621  {
622  r.setFilterRect( rect );
623  }
624 
625  if ( mCanvas->mapSettings().isTemporal() )
626  {
627  if ( !layer()->temporalProperties()->isVisibleInTemporalRange( mCanvas->mapSettings().temporalRange() ) )
628  return;
629 
630  QgsVectorLayerTemporalContext temporalContext;
631  temporalContext.setLayer( layer() );
632  const QString temporalFilter = qobject_cast< const QgsVectorLayerTemporalProperties * >( layer()->temporalProperties() )->createFilterString( temporalContext, mCanvas->mapSettings().temporalRange() );
633  if ( !temporalFilter.isEmpty() )
634  r.setFilterExpression( temporalFilter );
635  }
636 
638 
639  QgsFeature f;
640 
641  while ( features.nextFeature( f ) )
642  {
643  renderContext.expressionContext().setFeature( f );
644  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
645  {
646  mFilteredFeatures << f.id();
647  }
648 #if 0
649  if ( t.elapsed() > 5000 )
650  {
651  bool cancel = false;
652  emit progress( i, cancel );
653  if ( cancel )
654  break;
655 
656  t.restart();
657  }
658 #endif
659  }
660 
661  features.close();
662 
663  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
664  {
665  renderer->stopRender( renderContext );
666  }
667 }
668 
670 {
671  return masterModel()->rowToId( mapToSource( row ).row() );
672 }
673 
675 {
676  return mapFromMaster( masterModel()->idToIndex( fid ) );
677 }
678 
680 {
681  QModelIndexList indexes;
682  const auto constIdToIndexList = masterModel()->idToIndexList( fid );
683  for ( const QModelIndex &idx : constIdToIndexList )
684  {
685  indexes.append( mapFromMaster( idx ) );
686  }
687 
688  return indexes;
689 }
690 
691 QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex &proxyIndex ) const
692 {
693  if ( !proxyIndex.isValid() )
694  return QModelIndex();
695 
696  int sourceColumn = mapColumnToSource( proxyIndex.column() );
697 
698  // For the action column there is no matching column in the source model, just return the first one
699  // so we are still able to query for the feature id, the feature...
700  if ( sourceColumn == -1 )
701  sourceColumn = 0;
702 
703  return QSortFilterProxyModel::mapToSource( index( proxyIndex.row(), sourceColumn, proxyIndex.parent() ) );
704 }
705 
706 QModelIndex QgsAttributeTableFilterModel::mapFromSource( const QModelIndex &sourceIndex ) const
707 {
708  QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
709 
710  if ( proxyIndex.column() < 0 )
711  return QModelIndex();
712 
713  int col = mapColumnFromSource( proxyIndex.column() );
714 
715  if ( col == -1 )
716  col = 0;
717 
718  return index( proxyIndex.row(), col, proxyIndex.parent() );
719 }
720 
721 Qt::ItemFlags QgsAttributeTableFilterModel::flags( const QModelIndex &index ) const
722 {
723  // Handle the action column flags here, the master model doesn't know it
724  if ( mapColumnToSource( index.column() ) == -1 )
725  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
726 
727  QModelIndex source_index = mapToSource( index );
728  return masterModel()->flags( source_index );
729 }
This is a container for configuration of the attribute table.
@ Action
This column represents an action widget.
Qt::SortOrder sortOrder() const
Gets the sort order.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
void update(const QgsFields &fields)
Update the configuration with the given fields.
QString sortExpression() const
Gets the expression used for sorting.
bool hasSameColumns(const QgsAttributeTableConfig &other) const
Compare this configuration's columns name, type, and order to other.
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
QString sortExpression() const
The expression which is used to sort the attribute table.
FilterMode filterMode()
The current filterModel.
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
@ TypeRole
The type of a given column.
Q_DECL_DEPRECATED void extentsChanged()
Is called upon every change of the visible extents on the map canvas.
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
QgsAttributeTableFilterModel(QgsMapCanvas *canvas, QgsAttributeTableModel *sourceModel, QObject *parent=nullptr)
Make sure, the master model is already loaded, so the selection will get synchronized.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
int columnCount(const QModelIndex &parent) const override
void generateListOfVisibleFeatures()
Updates the list of currently visible features on the map canvas.
QModelIndexList fidToIndexList(QgsFeatureId fid)
void disconnectFilterModeConnections()
Disconnect the connections set for the current filterMode.
QModelIndex fidToIndex(QgsFeatureId fid) override
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table configuration to control which fields are shown, in which order they are show...
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Used by the sorting algorithm.
FilterMode
The filter mode defines how the rows should be filtered.
@ ShowFilteredList
Show only features whose ids are on the filter list. {.
@ ShowVisible
Show only visible features (depends on the map canvas)
@ ShowSelected
Show only selected features.
@ ShowEdited
Show only features which have unsaved changes.
bool selectedOnTop()
Returns if selected features are currently shown on top.
void filterError(const QString &errorMessage)
Emitted when an error occurred while filtering features.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Returns true if the source row will be accepted.
QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
void filterFeatures()
Updates the filtered features in the filter model.
int actionColumnIndex() const
Gets the index of the first column that contains an action widget.
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...
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
QVariant data(const QModelIndex &index, int role) const override
void featuresFiltered()
Emitted when the filtering of the features has been done.
void visibleReloaded()
Emitted when the the visible features on extend are reloaded (the list is created)
@ ColumnTypeActionButton
This column shows action buttons.
@ ColumnTypeField
This column shows a field.
QgsFeatureIds filteredFeatures()
Gets a list of currently filtered feature ids.
void setSourceModel(QgsAttributeTableModel *sourceModel)
Set the attribute table model that backs this model.
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
void sortColumnChanged(int column, Qt::SortOrder order)
Emitted whenever the sort column is changed.
void connectFilterModeConnections(FilterMode filterMode)
Disconnect the connections set for the new filterMode.
Qt::ItemFlags flags(const QModelIndex &index) const override
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
const QgsFeatureRequest & request() const
Gets the the feature request.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
QgsVectorLayer * layer() const
Returns the layer this model uses as backend.
QString sortCacheExpression(unsigned long cacheIndex=0) const
The expression which was used to fill the sorting cache at index cacheIndex.
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
int extraColumns() const
Empty extra columns to announce from this model.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
QModelIndexList idToIndexList(QgsFeatureId id) const
void prefetchSortData(const QString &expression, unsigned long cacheIndex=0)
Prefetches the entire data for an expression.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
@ SortRole
Role used for sorting start here.
@ FeatureIdRole
Get the feature id of the feature in this row.
void prefetchColumnData(int column)
Caches the entire data for one column.
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
QString evalErrorString() const
Returns evaluation error.
void setDistanceUnits(QgsUnitTypes::DistanceUnit unit)
Sets the desired distance units for calculations involving geomCalculator(), e.g.,...
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
void setAreaUnits(QgsUnitTypes::AreaUnit unit)
Sets the desired areal units for calculations involving geomCalculator(), e.g., "$area".
void setGeomCalculator(const QgsDistanceArea *calc)
Sets the geometry calculator used for distance and area calculations in expressions.
bool hasEvalError() const
Returns true if an error occurred when evaluating last input.
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
QVariant evaluate()
Evaluate the feature and return the result.
bool isValid() const
Checks if this expression is valid.
QSet< int > referencedAttributeIndexes(const QgsFields &fields) const
Returns a list of field name indexes obtained from the provided fields.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
@ ScaleDependent
Depends on scale if feature will be rendered (rule based )
Definition: qgsrenderer.h:257
@ Filter
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ....
Definition: qgsrenderer.h:256
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression.
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
const Flags & flags() const
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:56
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:344
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:86
void extentsChanged()
Emitted when the extents of the map change.
void temporalRangeChanged()
Emitted when the map canvas temporal range changes.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:91
The QgsMapSettings class contains configuration for rendering of the map.
double scale() const
Returns the calculated map scale.
const QgsMapToPixel & mapToPixel() const
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:501
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:105
A rectangle specified with double values.
Definition: qgsrectangle.h:42
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:447
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Definition: qgsrectangle.h:312
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context's map to pixel transform, which transforms between map coordinates and device coordi...
void setRendererScale(double scale)
Sets the renderer map scale.
const QgsDateTimeRange & temporalRange() const
Returns the datetime range for the object.
bool isTemporal() const
Returns true if the object's temporal range is enabled, and the object will be filtered when renderin...
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
bool isFeatureAdded(QgsFeatureId id) const
Returns true if the specified feature ID has been added but not committed.
bool isFeatureAttributesChanged(QgsFeatureId id) const
Returns true if the specified feature ID has had an attribute changed but not committed.
bool isFeatureGeometryChanged(QgsFeatureId id) const
Returns true if the specified feature ID has had its geometry changed but not committed.
Encapsulates the context in which a QgsVectorLayer's temporal capabilities will be applied.
void setLayer(QgsVectorLayer *layer)
Sets the associated layer.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)
Emitted whenever an attribute value change is done in the edit buffer.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
Emitted when selection was changed.
void featureAdded(QgsFeatureId fid)
Emitted when a new feature has been added to the layer.
Q_INVOKABLE QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on.
void geometryChanged(QgsFeatureId fid, const QgsGeometry &geometry)
Emitted whenever a geometry change is done in the edit buffer.
bool qgsVariantLessThan(const QVariant &lhs, const QVariant &rhs)
Compares two QVariant values and returns whether the first is less than the second.
Definition: qgis.cpp:121
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Defines the configuration of a column in the attribute table.