QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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"
23 #include "qgsfeature.h"
24 #include "qgsmapcanvas.h"
25 #include "qgslogger.h"
26 #include "qgsrenderer.h"
29 // Filter Model //
31 
33  : QSortFilterProxyModel( parent )
34  , mCanvas( canvas )
35 {
36  setSourceModel( sourceModel );
37  setDynamicSortFilter( true );
38  setSortRole( QgsAttributeTableModel::SortRole );
39  connect( layer(), &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableFilterModel::selectionChanged );
40 }
41 
42 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
43 {
44  if ( mSelectedOnTop )
45  {
46  bool leftSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( left.row() ) );
47  bool rightSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( right.row() ) );
48 
49  if ( leftSelected && !rightSelected )
50  {
51  return sortOrder() == Qt::AscendingOrder;
52  }
53  else if ( rightSelected && !leftSelected )
54  {
55  return sortOrder() == Qt::DescendingOrder;
56  }
57  }
58 
59  if ( mTableModel->sortCacheExpression().isEmpty() )
60  {
61  //shortcut when no sort order set
62  return false;
63  }
64 
66  right.data( QgsAttributeTableModel::SortRole ) );
67 }
68 
69 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
70 {
71  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
72  order = Qt::AscendingOrder;
73 
74  int myColumn = mColumnMapping.at( column );
75  masterModel()->prefetchColumnData( myColumn );
76  QSortFilterProxyModel::sort( myColumn, order );
77  emit sortColumnChanged( column, order );
78 }
79 
80 QVariant QgsAttributeTableFilterModel::data( const QModelIndex &index, int role ) const
81 {
82  if ( mapColumnToSource( index.column() ) == -1 ) // actions
83  {
84  if ( role == TypeRole )
86  else if ( role == QgsAttributeTableModel::FeatureIdRole )
87  {
88  QModelIndex fieldIndex = QSortFilterProxyModel::mapToSource( QSortFilterProxyModel::index( index.row(), 0, index.parent() ) );
89  return sourceModel()->data( fieldIndex, QgsAttributeTableModel::FeatureIdRole );
90  }
91  }
92  else if ( role == TypeRole )
93  return ColumnTypeField;
94 
95  return QSortFilterProxyModel::data( index, role );
96 }
97 
98 QVariant QgsAttributeTableFilterModel::headerData( int section, Qt::Orientation orientation, int role ) const
99 {
100  if ( orientation == Qt::Horizontal )
101  {
102  if ( mColumnMapping.at( section ) == -1 && role == Qt::DisplayRole )
103  return tr( "Actions" );
104  else
105  return QSortFilterProxyModel::headerData( section, orientation, role );
106  }
107  else
108  {
109  if ( role == Qt::DisplayRole )
110  return section + 1;
111  else
112  {
113  int sourceSection = mapToSource( index( section, ( !mColumnMapping.isEmpty() && mColumnMapping.at( 0 ) == -1 ) ? 1 : 0 ) ).row();
114  return sourceModel()->headerData( sourceSection, orientation, role );
115  }
116  }
117 }
118 
120 {
121  return mColumnMapping.indexOf( -1 );
122 }
123 
124 int QgsAttributeTableFilterModel::columnCount( const QModelIndex &parent ) const
125 {
126  Q_UNUSED( parent );
127  return mColumnMapping.count();
128 }
129 
131 {
132  QgsAttributeTableConfig oldConfig = mConfig;
133  mConfig = config;
134  mConfig.update( layer()->fields() );
135 
136  if ( mConfig.hasSameColumns( oldConfig ) )
137  {
138  return;
139  }
140 
141  QVector<int> newColumnMapping;
142  Q_FOREACH ( const QgsAttributeTableConfig::ColumnConfig &columnConfig, mConfig.columns() )
143  {
144  // Hidden? Forget about this column
145  if ( columnConfig.hidden )
146  continue;
147 
148  // The new value for the mapping (field index or -1 for action column)
149  int newValue = ( columnConfig.type == QgsAttributeTableConfig::Action ) ? -1 : layer()->fields().lookupField( columnConfig.name );
150  newColumnMapping << newValue;
151  }
152 
153  if ( newColumnMapping != mColumnMapping )
154  {
155  bool requiresReset = false;
156  int firstRemovedColumn = -1;
157  int removedColumnCount = 0;
158 
159  // Check if there have a contiguous set of columns have been removed or if we require a full reset
160  for ( int i = 0; i < std::min( newColumnMapping.size(), mColumnMapping.size() - removedColumnCount ); ++i )
161  {
162  if ( newColumnMapping.at( i ) == mColumnMapping.at( i + removedColumnCount ) )
163  continue;
164 
165  if ( firstRemovedColumn == -1 )
166  {
167  firstRemovedColumn = i;
168 
169  while ( i < mColumnMapping.size() - removedColumnCount && mColumnMapping.at( i + removedColumnCount ) != newColumnMapping.at( i ) )
170  {
171  ++removedColumnCount;
172  }
173  }
174  else
175  {
176  requiresReset = true;
177  break;
178  }
179  }
180 
181  // No difference found so far
182  if ( firstRemovedColumn == -1 )
183  {
184  if ( newColumnMapping.size() > mColumnMapping.size() )
185  {
186  // More columns: appended to the end
187  beginInsertColumns( QModelIndex(), mColumnMapping.size(), newColumnMapping.size() - 1 );
188  mColumnMapping = newColumnMapping;
189  endInsertColumns();
190  }
191  else
192  {
193  // Less columns: removed from the end
194  beginRemoveColumns( QModelIndex(), newColumnMapping.size(), mColumnMapping.size() - 1 );
195  mColumnMapping = newColumnMapping;
196  endRemoveColumns();
197  }
198  }
199  else
200  {
201  if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount )
202  {
203  //the amount of removed column in the model need to be equal removedColumnCount
204  beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount - 1 );
205  mColumnMapping = newColumnMapping;
206  endRemoveColumns();
207  }
208  else
209  {
210  requiresReset = true;
211  }
212  }
213 
214  if ( requiresReset )
215  {
216  beginResetModel();
217  mColumnMapping = newColumnMapping;
218  endResetModel();
219  }
220  }
221 
222  if ( !config.sortExpression().isEmpty() )
223  sort( config.sortExpression(), config.sortOrder() );
224 }
225 
226 void QgsAttributeTableFilterModel::sort( const QString &expression, Qt::SortOrder order )
227 {
228  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
229  order = Qt::AscendingOrder;
230 
231  QSortFilterProxyModel::sort( -1 );
232  masterModel()->prefetchSortData( expression );
233  QSortFilterProxyModel::sort( 0, order );
234 }
235 
237 {
238  return masterModel()->sortCacheExpression();
239 }
240 
242 {
243  if ( mSelectedOnTop != selectedOnTop )
244  {
245  mSelectedOnTop = selectedOnTop;
246  int column = sortColumn();
247  Qt::SortOrder order = sortOrder();
248 
249  // set default sort values if they are not correctly set
250  if ( column < 0 || ( order != Qt::AscendingOrder && order != Qt::DescendingOrder ) )
251  {
252  sort( 0, Qt::AscendingOrder );
253  invalidate();
254  }
255  }
256 }
257 
259 {
260  mTableModel = sourceModel;
261 
262  for ( int i = 0; i < mTableModel->columnCount() - mTableModel->extraColumns(); ++i )
263  {
264  mColumnMapping.append( i );
265  }
266 
267  QSortFilterProxyModel::setSourceModel( sourceModel );
268 
269  // Disconnect any code to update columns in the parent, we handle this manually
270  disconnect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
271  disconnect( mTableModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsInserted( QModelIndex, int, int ) ) );
272  disconnect( mTableModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
273  disconnect( mTableModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsRemoved( QModelIndex, int, int ) ) );
274  // The following connections are needed in order to keep the filter model in sync, see: regression #15974
275  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeInserted, this, &QgsAttributeTableFilterModel::onColumnsChanged );
276  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeRemoved, this, &QgsAttributeTableFilterModel::onColumnsChanged );
277 
278 }
279 
281 {
282  return mSelectedOnTop;
283 }
284 
286 {
287  mFilteredFeatures = ids;
289  invalidateFilter();
290 }
291 
293 {
294  QgsFeatureIds ids;
295  ids.reserve( rowCount() );
296  for ( int i = 0; i < rowCount(); ++i )
297  {
298  QModelIndex row = index( i, 0 );
299  ids << rowToId( row );
300  }
301  return ids;
302 }
303 
305 {
306  if ( filterMode != mFilterMode )
307  {
308  if ( filterMode == ShowVisible )
309  {
312  }
313  else
314  {
316  }
317 
318  mFilterMode = filterMode;
319  invalidateFilter();
320  }
321 }
322 
323 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
324 {
325  Q_UNUSED( sourceParent );
326  switch ( mFilterMode )
327  {
328  case ShowAll:
329  return true;
330 
331  case ShowFilteredList:
332  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
333 
334  case ShowSelected:
335  return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );
336 
337  case ShowVisible:
338  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
339 
340  case ShowEdited:
341  {
342  QgsVectorLayerEditBuffer *editBuffer = layer()->editBuffer();
343  if ( editBuffer )
344  {
345  QgsFeatureId fid = masterModel()->rowToId( sourceRow );
346 
347  if ( editBuffer->isFeatureAdded( fid ) )
348  return true;
349 
350  if ( editBuffer->isFeatureAttributesChanged( fid ) )
351  return true;
352 
353  if ( editBuffer->isFeatureGeometryChanged( fid ) )
354  return true;
355 
356  return false;
357  }
358  return false;
359  }
360 
361  default:
362  Q_ASSERT( false ); // In debug mode complain
363  return true; // In release mode accept row
364  }
365  // returns are handled in their respective case statement above
366 }
367 
369 {
371  invalidateFilter();
372 }
373 
374 void QgsAttributeTableFilterModel::selectionChanged()
375 {
376  if ( ShowSelected == mFilterMode )
377  {
378  invalidateFilter();
379  }
380  else if ( mSelectedOnTop )
381  {
382  invalidate();
383  }
384 }
385 
386 void QgsAttributeTableFilterModel::onColumnsChanged()
387 {
388  setAttributeTableConfig( mConfig );
389 }
390 
391 int QgsAttributeTableFilterModel::mapColumnToSource( int column ) const
392 {
393  if ( mColumnMapping.isEmpty() )
394  return column;
395  if ( column < 0 || column >= mColumnMapping.size() )
396  return -1;
397  else
398  return mColumnMapping.at( column );
399 }
400 
401 int QgsAttributeTableFilterModel::mapColumnFromSource( int column ) const
402 {
403  if ( mColumnMapping.isEmpty() )
404  return column;
405  else
406  return mColumnMapping.indexOf( column );
407 }
408 
410 {
411  if ( !layer() )
412  return;
413 
414  bool filter = false;
415  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
416  QgsRenderContext renderContext;
418 
419  mFilteredFeatures.clear();
420  if ( !layer()->renderer() )
421  {
422  QgsDebugMsg( QStringLiteral( "Cannot get renderer" ) );
423  return;
424  }
425 
426  std::unique_ptr< QgsFeatureRenderer > renderer( layer()->renderer()->clone() );
427 
428  const QgsMapSettings &ms = mCanvas->mapSettings();
429  if ( !layer()->isInScaleRange( ms.scale() ) )
430  {
431  QgsDebugMsg( QStringLiteral( "Out of scale limits" ) );
432  }
433  else
434  {
435  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
436  {
437  // setup scale
438  // mapRenderer()->renderContext()->scale is not automatically updated when
439  // render extent changes (because it's scale is used to identify if changed
440  // since last render) -> use local context
441  renderContext.setExtent( ms.visibleExtent() );
442  renderContext.setMapToPixel( ms.mapToPixel() );
443  renderContext.setRendererScale( ms.scale() );
444  }
445 
446  filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
447  }
448 
449  renderer->startRender( renderContext, layer()->fields() );
450 
451  QgsFeatureRequest r( masterModel()->request() );
452  if ( !r.filterRect().isNull() )
453  {
454  r.setFilterRect( r.filterRect().intersect( rect ) );
455  }
456  else
457  {
458  r.setFilterRect( rect );
459  }
461 
462  QgsFeature f;
463 
464  while ( features.nextFeature( f ) )
465  {
466  renderContext.expressionContext().setFeature( f );
467  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
468  {
469  mFilteredFeatures << f.id();
470  }
471 #if 0
472  if ( t.elapsed() > 5000 )
473  {
474  bool cancel = false;
475  emit progress( i, cancel );
476  if ( cancel )
477  break;
478 
479  t.restart();
480  }
481 #endif
482  }
483 
484  features.close();
485 
486  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
487  {
488  renderer->stopRender( renderContext );
489  }
490 }
491 
493 {
494  return masterModel()->rowToId( mapToSource( row ).row() );
495 }
496 
498 {
499  return mapFromMaster( masterModel()->idToIndex( fid ) );
500 }
501 
503 {
504  QModelIndexList indexes;
505  Q_FOREACH ( const QModelIndex &idx, masterModel()->idToIndexList( fid ) )
506  {
507  indexes.append( mapFromMaster( idx ) );
508  }
509 
510  return indexes;
511 }
512 
513 QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex &proxyIndex ) const
514 {
515  if ( !proxyIndex.isValid() )
516  return QModelIndex();
517 
518  int sourceColumn = mapColumnToSource( proxyIndex.column() );
519 
520  // For the action column there is no matching column in the source model, just return the first one
521  // so we are still able to query for the feature id, the feature...
522  if ( sourceColumn == -1 )
523  sourceColumn = 0;
524 
525  return QSortFilterProxyModel::mapToSource( index( proxyIndex.row(), sourceColumn, proxyIndex.parent() ) );
526 }
527 
528 QModelIndex QgsAttributeTableFilterModel::mapFromSource( const QModelIndex &sourceIndex ) const
529 {
530  QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
531 
532  if ( proxyIndex.column() < 0 )
533  return QModelIndex();
534 
535  int col = mapColumnFromSource( proxyIndex.column() );
536 
537  if ( col == -1 )
538  col = 0;
539 
540  return index( proxyIndex.row(), col, proxyIndex.parent() );
541 }
542 
543 Qt::ItemFlags QgsAttributeTableFilterModel::flags( const QModelIndex &index ) const
544 {
545  // Handle the action column flags here, the master model doesn't know it
546  if ( mapColumnToSource( index.column() ) == -1 )
547  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
548 
549  QModelIndex source_index = mapToSource( index );
550  return masterModel()->flags( source_index );
551 }
void generateListOfVisibleFeatures()
Updates the list of currently visible features on the map canvas.
QgsFeatureId id
Definition: qgsfeature.h:64
QgsFeatureId rowToId(const QModelIndex &row)
Returns the feature id for a given model index.
Wrapper for iterator of features from vector data provider or vector layer.
QVariant data(const QModelIndex &index, int role) const override
QgsAttributeTableConfig::Type type
The type of this column.
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Depends on scale if feature will be rendered (rule based )
Definition: qgsrenderer.h:245
void update(const QgsFields &fields)
Update the configuration with the given fields.
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
Returns true if the source row will be accepted.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
bool selectedOnTop()
Returns if selected features are currently shown on top.
void setAttributeTableConfig(const QgsAttributeTableConfig &config)
Set the attribute table configuration to control which fields are shown, in which order they are show...
double scale() const
Returns the calculated map scale.
void setSelectedOnTop(bool selectedOnTop)
Changes the sort order of the features.
int actionColumnIndex() const
Gets the index of the first column that contains an action widget.
void setFilterMode(FilterMode filterMode)
Set the filter mode the filter will use.
const QgsRectangle & filterRect() const
Returns the rectangle from which features will be taken.
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ...
Definition: qgsrenderer.h:244
int extraColumns() const
Empty extra columns to announce from this model.
void setRendererScale(double scale)
Sets the renderer map scale.
void prefetchSortData(const QString &expression, unsigned long cacheIndex=0)
Prefetches the entire data for an expression.
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
Used by the sorting algorithm.
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
Definition: qgsrectangle.h:435
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes takes output image size into accou...
bool isFeatureGeometryChanged(QgsFeatureId id) const
Returns true if the specified feature ID has had its geometry changed but not committed.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
This column represents an action widget.
const QgsMapToPixel & mapToPixel() const
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer&#39;s CRS
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
A model backed by a QgsVectorLayerCache which is able to provide feature/attribute information to a Q...
Show only visible features (depends on the map canvas)
void setExtent(const QgsRectangle &extent)
When rendering a map layer, calling this method sets the "clipping" extent for the layer (in the laye...
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
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:153
QgsAttributeTableFilterModel(QgsMapCanvas *canvas, QgsAttributeTableModel *sourceModel, QObject *parent=nullptr)
Make sure, the master model is already loaded, so the selection will get synchronized.
virtual void setFilteredFeatures(const QgsFeatureIds &ids)
Specify a list of features, which the filter will accept.
The QgsMapSettings class contains configuration for rendering of the map.
QString sortExpression() const
Gets the expression used for sorting.
Get the feature id of the feature in this row.
QgsVectorLayer * layer() const
Returns the layer this filter acts on.
Roles used for sorting start here.
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
Qt::SortOrder sortOrder() const
Gets the sort order.
FilterMode filterMode()
The current filterModel.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns.
FilterMode
The filter mode defines how the rows should be filtered.
bool hasSameColumns(const QgsAttributeTableConfig &other) const
Compare this configuration&#39;s columns name, type, and order to other.
bool hidden
Flag that controls if the column is hidden.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
void selectionChanged(const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect)
This signal is emitted when selection was changed.
Show only features which have unsaved changes.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
int lookupField(const QString &fieldName) const
Looks up field&#39;s index from the field name.
Definition: qgsfields.cpp:320
QgsVectorLayerCache * layerCache() const
Returns the layer cache this model uses as backend.
QString name
The name of the attribute if this column represents a field.
void setSourceModel(QgsAttributeTableModel *sourceModel)
Set the attribute table model that backs this model.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Definition: qgsrectangle.h:311
void extentsChanged()
Is called upon every change of the visible extents on the map canvas.
QgsExpressionContext & expressionContext()
Gets the expression context.
Show only features whose ids are on the filter list. {.
QVector< QgsAttributeTableConfig::ColumnConfig > columns() const
Gets the list with all columns and their configuration.
Contains information about the context of a rendering operation.
QgsAttributeTableModel * masterModel() const
Returns the table model this filter is using.
QModelIndex mapFromMaster(const QModelIndex &sourceIndex) const
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
Sort by the given column using the given order.
QString sortExpression() const
The expression which is used to sort the attribute table.
int columnCount(const QModelIndex &parent) const override
QString sortCacheExpression(unsigned long cacheIndex=0) const
The expression which was used to fill the sorting cache at index cacheIndex.
void setMapToPixel(const QgsMapToPixel &mtp)
Sets the context&#39;s map to pixel transform, which transforms between map coordinates and device coordi...
Defines the configuration of a column in the attribute table.
QgsFeatureIds filteredFeatures()
Gets a list of currently filtered feature ids.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
QgsFeatureId rowToId(int row) const
Maps row to feature id.
bool isFeatureAttributesChanged(QgsFeatureId id) const
Returns true if the specified feature ID has had an attribute changed but not committed.
void appendScopes(const QList< QgsExpressionContextScope * > &scopes)
Appends a list of scopes to the end of the context.
bool nextFeature(QgsFeature &f)
This is a container for configuration of the attribute table.
bool isFeatureAdded(QgsFeatureId id) const
Returns true if the specified feature ID has been added but not committed.
void sortColumnChanged(int column, Qt::SortOrder order)
Is emitted whenever the sort column is changed.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &featureRequest=QgsFeatureRequest())
Query this VectorLayerCache for features.
QModelIndexList fidToIndexList(QgsFeatureId fid)
void extentsChanged()
Emitted when the extents of the map change.
void prefetchColumnData(int column)
Caches the entire data for one column.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns item flags for the index.
QModelIndex fidToIndex(QgsFeatureId fid) override
Qt::ItemFlags flags(const QModelIndex &index) const override