QGIS API Documentation  3.6.0-Noosa (5873452)
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  Q_FOREACH ( const QgsAttributeTableConfig::ColumnConfig &columnConfig, mConfig.columns() )
145  {
146  // Hidden? Forget about this column
147  if ( columnConfig.hidden )
148  continue;
149 
150  // The new value for the mapping (field index or -1 for action column)
151  int newValue = ( columnConfig.type == QgsAttributeTableConfig::Action ) ? -1 : layer()->fields().lookupField( columnConfig.name );
152  newColumnMapping << newValue;
153  }
154 
155  if ( newColumnMapping != mColumnMapping )
156  {
157  bool requiresReset = false;
158  int firstRemovedColumn = -1;
159  int removedColumnCount = 0;
160 
161  // Check if there have a contiguous set of columns have been removed or if we require a full reset
162  for ( int i = 0; i < std::min( newColumnMapping.size(), mColumnMapping.size() - removedColumnCount ); ++i )
163  {
164  if ( newColumnMapping.at( i ) == mColumnMapping.at( i + removedColumnCount ) )
165  continue;
166 
167  if ( firstRemovedColumn == -1 )
168  {
169  firstRemovedColumn = i;
170 
171  while ( i < mColumnMapping.size() - removedColumnCount && mColumnMapping.at( i + removedColumnCount ) != newColumnMapping.at( i ) )
172  {
173  ++removedColumnCount;
174  }
175  }
176  else
177  {
178  requiresReset = true;
179  break;
180  }
181  }
182 
183  // No difference found so far
184  if ( firstRemovedColumn == -1 )
185  {
186  if ( newColumnMapping.size() > mColumnMapping.size() )
187  {
188  // More columns: appended to the end
189  beginInsertColumns( QModelIndex(), mColumnMapping.size(), newColumnMapping.size() - 1 );
190  mColumnMapping = newColumnMapping;
191  endInsertColumns();
192  }
193  else
194  {
195  // Less columns: removed from the end
196  beginRemoveColumns( QModelIndex(), newColumnMapping.size(), mColumnMapping.size() - 1 );
197  mColumnMapping = newColumnMapping;
198  endRemoveColumns();
199  }
200  }
201  else
202  {
203  if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount )
204  {
205  //the amount of removed column in the model need to be equal removedColumnCount
206  beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount - 1 );
207  mColumnMapping = newColumnMapping;
208  endRemoveColumns();
209  }
210  else
211  {
212  requiresReset = true;
213  }
214  }
215 
216  if ( requiresReset )
217  {
218  beginResetModel();
219  mColumnMapping = newColumnMapping;
220  endResetModel();
221  }
222  }
223 
224  if ( !config.sortExpression().isEmpty() )
225  sort( config.sortExpression(), config.sortOrder() );
226 }
227 
228 void QgsAttributeTableFilterModel::sort( const QString &expression, Qt::SortOrder order )
229 {
230  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
231  order = Qt::AscendingOrder;
232 
233  QSortFilterProxyModel::sort( -1 );
234  masterModel()->prefetchSortData( expression );
235  QSortFilterProxyModel::sort( 0, order );
236 }
237 
239 {
240  return masterModel()->sortCacheExpression();
241 }
242 
244 {
245  if ( mSelectedOnTop != selectedOnTop )
246  {
247  mSelectedOnTop = selectedOnTop;
248  int column = sortColumn();
249  Qt::SortOrder order = sortOrder();
250 
251  // set default sort values if they are not correctly set
252  if ( column < 0 || ( order != Qt::AscendingOrder && order != Qt::DescendingOrder ) )
253  {
254  sort( 0, Qt::AscendingOrder );
255  invalidate();
256  }
257  }
258 }
259 
261 {
262  mTableModel = sourceModel;
263 
264  for ( int i = 0; i < mTableModel->columnCount() - mTableModel->extraColumns(); ++i )
265  {
266  mColumnMapping.append( i );
267  }
268 
269  QSortFilterProxyModel::setSourceModel( sourceModel );
270 
271  // Disconnect any code to update columns in the parent, we handle this manually
272  disconnect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
273  disconnect( mTableModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsInserted( QModelIndex, int, int ) ) );
274  disconnect( mTableModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
275  disconnect( mTableModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsRemoved( QModelIndex, int, int ) ) );
276  // The following connections are needed in order to keep the filter model in sync, see: regression #15974
277  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeInserted, this, &QgsAttributeTableFilterModel::onColumnsChanged );
278  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeRemoved, this, &QgsAttributeTableFilterModel::onColumnsChanged );
279 
280 }
281 
283 {
284  return mSelectedOnTop;
285 }
286 
288 {
289  mFilteredFeatures = ids;
291  invalidateFilter();
292 }
293 
295 {
296  QgsFeatureIds ids;
297  ids.reserve( rowCount() );
298  for ( int i = 0; i < rowCount(); ++i )
299  {
300  QModelIndex row = index( i, 0 );
301  ids << rowToId( row );
302  }
303  return ids;
304 }
305 
307 {
308  if ( filterMode != mFilterMode )
309  {
310  if ( filterMode == ShowVisible )
311  {
314  }
315  else
316  {
318  }
319 
320  mFilterMode = filterMode;
321  invalidateFilter();
322  }
323 }
324 
325 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
326 {
327  Q_UNUSED( sourceParent );
328  switch ( mFilterMode )
329  {
330  case ShowAll:
331  return true;
332 
333  case ShowFilteredList:
334  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
335 
336  case ShowSelected:
337  return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );
338 
339  case ShowVisible:
340  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
341 
342  case ShowEdited:
343  {
344  QgsVectorLayerEditBuffer *editBuffer = layer()->editBuffer();
345  if ( editBuffer )
346  {
347  QgsFeatureId fid = masterModel()->rowToId( sourceRow );
348 
349  if ( editBuffer->isFeatureAdded( fid ) )
350  return true;
351 
352  if ( editBuffer->isFeatureAttributesChanged( fid ) )
353  return true;
354 
355  if ( editBuffer->isFeatureGeometryChanged( fid ) )
356  return true;
357 
358  return false;
359  }
360  return false;
361  }
362 
363  default:
364  Q_ASSERT( false ); // In debug mode complain
365  return true; // In release mode accept row
366  }
367  // returns are handled in their respective case statement above
368 }
369 
371 {
373  invalidateFilter();
374 }
375 
376 void QgsAttributeTableFilterModel::selectionChanged()
377 {
378  if ( ShowSelected == mFilterMode )
379  {
380  invalidateFilter();
381  }
382  else if ( mSelectedOnTop )
383  {
384  invalidate();
385  }
386 }
387 
388 void QgsAttributeTableFilterModel::onColumnsChanged()
389 {
390  setAttributeTableConfig( mConfig );
391 }
392 
393 int QgsAttributeTableFilterModel::mapColumnToSource( int column ) const
394 {
395  if ( mColumnMapping.isEmpty() )
396  return column;
397  if ( column < 0 || column >= mColumnMapping.size() )
398  return -1;
399  else
400  return mColumnMapping.at( column );
401 }
402 
403 int QgsAttributeTableFilterModel::mapColumnFromSource( int column ) const
404 {
405  if ( mColumnMapping.isEmpty() )
406  return column;
407  else
408  return mColumnMapping.indexOf( column );
409 }
410 
412 {
413  if ( !layer() )
414  return;
415 
416  bool filter = false;
417  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
418  QgsRenderContext renderContext;
420 
421  mFilteredFeatures.clear();
422  if ( !layer()->renderer() )
423  {
424  QgsDebugMsg( QStringLiteral( "Cannot get renderer" ) );
425  return;
426  }
427 
428  std::unique_ptr< QgsFeatureRenderer > renderer( layer()->renderer()->clone() );
429 
430  const QgsMapSettings &ms = mCanvas->mapSettings();
431  if ( !layer()->isInScaleRange( ms.scale() ) )
432  {
433  QgsDebugMsg( QStringLiteral( "Out of scale limits" ) );
434  }
435  else
436  {
437  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
438  {
439  // setup scale
440  // mapRenderer()->renderContext()->scale is not automatically updated when
441  // render extent changes (because it's scale is used to identify if changed
442  // since last render) -> use local context
443  renderContext.setExtent( ms.visibleExtent() );
444  renderContext.setMapToPixel( ms.mapToPixel() );
445  renderContext.setRendererScale( ms.scale() );
446  }
447 
448  filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
449  }
450 
451  renderer->startRender( renderContext, layer()->fields() );
452 
453  QgsFeatureRequest r( masterModel()->request() );
454  if ( !r.filterRect().isNull() )
455  {
456  r.setFilterRect( r.filterRect().intersect( rect ) );
457  }
458  else
459  {
460  r.setFilterRect( rect );
461  }
463 
464  QgsFeature f;
465 
466  while ( features.nextFeature( f ) )
467  {
468  renderContext.expressionContext().setFeature( f );
469  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
470  {
471  mFilteredFeatures << f.id();
472  }
473 #if 0
474  if ( t.elapsed() > 5000 )
475  {
476  bool cancel = false;
477  emit progress( i, cancel );
478  if ( cancel )
479  break;
480 
481  t.restart();
482  }
483 #endif
484  }
485 
486  features.close();
487 
488  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
489  {
490  renderer->stopRender( renderContext );
491  }
492 }
493 
495 {
496  return masterModel()->rowToId( mapToSource( row ).row() );
497 }
498 
500 {
501  return mapFromMaster( masterModel()->idToIndex( fid ) );
502 }
503 
505 {
506  QModelIndexList indexes;
507  Q_FOREACH ( const QModelIndex &idx, masterModel()->idToIndexList( fid ) )
508  {
509  indexes.append( mapFromMaster( idx ) );
510  }
511 
512  return indexes;
513 }
514 
515 QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex &proxyIndex ) const
516 {
517  if ( !proxyIndex.isValid() )
518  return QModelIndex();
519 
520  int sourceColumn = mapColumnToSource( proxyIndex.column() );
521 
522  // For the action column there is no matching column in the source model, just return the first one
523  // so we are still able to query for the feature id, the feature...
524  if ( sourceColumn == -1 )
525  sourceColumn = 0;
526 
527  return QSortFilterProxyModel::mapToSource( index( proxyIndex.row(), sourceColumn, proxyIndex.parent() ) );
528 }
529 
530 QModelIndex QgsAttributeTableFilterModel::mapFromSource( const QModelIndex &sourceIndex ) const
531 {
532  QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
533 
534  if ( proxyIndex.column() < 0 )
535  return QModelIndex();
536 
537  int col = mapColumnFromSource( proxyIndex.column() );
538 
539  if ( col == -1 )
540  col = 0;
541 
542  return index( proxyIndex.row(), col, proxyIndex.parent() );
543 }
544 
545 Qt::ItemFlags QgsAttributeTableFilterModel::flags( const QModelIndex &index ) const
546 {
547  // Handle the action column flags here, the master model doesn't know it
548  if ( mapColumnToSource( index.column() ) == -1 )
549  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
550 
551  QModelIndex source_index = mapToSource( index );
552  return masterModel()->flags( source_index );
553 }
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
QgsAttributeTableConfig::Type type
The type of this column.
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: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...
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:244
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:73
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.
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.
Roles used for sorting start here.
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
FilterMode filterMode()
The current filterModel.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
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.
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)...
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)
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.
bool isFeatureAttributesChanged(QgsFeatureId id) const
Returns true if the specified feature ID has had an attribute changed but not committed.
const QgsMapToPixel & mapToPixel() const
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.
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)
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)
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.
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.