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