QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 #include "qgsvectorlayercache.h"
32 
34 // Filter Model //
36 
38  : QSortFilterProxyModel( parent )
39  , mCanvas( canvas )
40 {
41  setSourceModel( sourceModel );
42  setDynamicSortFilter( true );
43  setSortRole( QgsAttributeTableModel::SortRole );
44  connect( layer(), &QgsVectorLayer::selectionChanged, this, &QgsAttributeTableFilterModel::selectionChanged );
45 
46  mReloadVisibleTimer.setSingleShot( true );
47  connect( &mReloadVisibleTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::reloadVisible );
48  mFilterFeaturesTimer.setSingleShot( true );
49  connect( &mFilterFeaturesTimer, &QTimer::timeout, this, &QgsAttributeTableFilterModel::filterFeatures );
50 }
51 
52 bool QgsAttributeTableFilterModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
53 {
54  if ( mSelectedOnTop )
55  {
56  bool leftSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( left.row() ) );
57  bool rightSelected = layer()->selectedFeatureIds().contains( masterModel()->rowToId( right.row() ) );
58 
59  if ( leftSelected && !rightSelected )
60  {
61  return sortOrder() == Qt::AscendingOrder;
62  }
63  else if ( rightSelected && !leftSelected )
64  {
65  return sortOrder() == Qt::DescendingOrder;
66  }
67  }
68 
69  if ( mTableModel->sortCacheExpression().isEmpty() )
70  {
71  //shortcut when no sort order set
72  return false;
73  }
74 
76  right.data( QgsAttributeTableModel::SortRole ) );
77 }
78 
79 void QgsAttributeTableFilterModel::sort( int column, Qt::SortOrder order )
80 {
81  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
82  order = Qt::AscendingOrder;
83  if ( column < 0 || column >= mColumnMapping.size() )
84  {
85  sort( QString() );
86  }
87  else
88  {
89  int myColumn = mColumnMapping.at( column );
90  masterModel()->prefetchColumnData( myColumn );
91  QSortFilterProxyModel::sort( myColumn, order );
92  }
93  emit sortColumnChanged( column, order );
94 }
95 
96 QVariant QgsAttributeTableFilterModel::data( const QModelIndex &index, int role ) const
97 {
98  if ( mapColumnToSource( index.column() ) == -1 ) // actions
99  {
100  if ( role == TypeRole )
101  return ColumnTypeActionButton;
102  else if ( role == QgsAttributeTableModel::FeatureIdRole )
103  {
104  QModelIndex fieldIndex = QSortFilterProxyModel::mapToSource( QSortFilterProxyModel::index( index.row(), 0, index.parent() ) );
105  return sourceModel()->data( fieldIndex, QgsAttributeTableModel::FeatureIdRole );
106  }
107  }
108  else if ( role == TypeRole )
109  return ColumnTypeField;
110 
111  return QSortFilterProxyModel::data( index, role );
112 }
113 
114 QVariant QgsAttributeTableFilterModel::headerData( int section, Qt::Orientation orientation, int role ) const
115 {
116  if ( orientation == Qt::Horizontal )
117  {
118  if ( mColumnMapping.at( section ) == -1 && role == Qt::DisplayRole )
119  return tr( "Actions" );
120  else
121  return QSortFilterProxyModel::headerData( section, orientation, role );
122  }
123  else
124  {
125  if ( role == Qt::DisplayRole )
126  return section + 1;
127  else
128  {
129  int sourceSection = mapToSource( index( section, ( !mColumnMapping.isEmpty() && mColumnMapping.at( 0 ) == -1 ) ? 1 : 0 ) ).row();
130  return sourceModel()->headerData( sourceSection, orientation, role );
131  }
132  }
133 }
134 
136 {
137  return mColumnMapping.indexOf( -1 );
138 }
139 
140 int QgsAttributeTableFilterModel::columnCount( const QModelIndex &parent ) const
141 {
142  Q_UNUSED( parent )
143  return mColumnMapping.count();
144 }
145 
147 {
148  QgsAttributeTableConfig oldConfig = mConfig;
149  mConfig = config;
150  mConfig.update( layer()->fields() );
151 
152  if ( mConfig.hasSameColumns( oldConfig ) )
153  {
154  return;
155  }
156 
157  QVector<int> newColumnMapping;
158  const auto constColumns = mConfig.columns();
159  for ( const QgsAttributeTableConfig::ColumnConfig &columnConfig : constColumns )
160  {
161  // Hidden? Forget about this column
162  if ( columnConfig.hidden )
163  continue;
164 
165  // The new value for the mapping (field index or -1 for action column)
166  int newValue = ( columnConfig.type == QgsAttributeTableConfig::Action ) ? -1 : layer()->fields().lookupField( columnConfig.name );
167  newColumnMapping << newValue;
168  }
169 
170  if ( newColumnMapping != mColumnMapping )
171  {
172  bool requiresReset = false;
173  int firstRemovedColumn = -1;
174  int removedColumnCount = 0;
175 
176  // Check if there have a contiguous set of columns have been removed or if we require a full reset
177  for ( int i = 0; i < std::min( newColumnMapping.size(), mColumnMapping.size() - removedColumnCount ); ++i )
178  {
179  if ( newColumnMapping.at( i ) == mColumnMapping.at( i + removedColumnCount ) )
180  continue;
181 
182  if ( firstRemovedColumn == -1 )
183  {
184  firstRemovedColumn = i;
185 
186  while ( i < mColumnMapping.size() - removedColumnCount && mColumnMapping.at( i + removedColumnCount ) != newColumnMapping.at( i ) )
187  {
188  ++removedColumnCount;
189  }
190  }
191  else
192  {
193  requiresReset = true;
194  break;
195  }
196  }
197 
198  // No difference found so far
199  if ( firstRemovedColumn == -1 )
200  {
201  if ( newColumnMapping.size() > mColumnMapping.size() )
202  {
203  // More columns: appended to the end
204  beginInsertColumns( QModelIndex(), mColumnMapping.size(), newColumnMapping.size() - 1 );
205  mColumnMapping = newColumnMapping;
206  endInsertColumns();
207  }
208  else
209  {
210  // Less columns: removed from the end
211  beginRemoveColumns( QModelIndex(), newColumnMapping.size(), mColumnMapping.size() - 1 );
212  mColumnMapping = newColumnMapping;
213  endRemoveColumns();
214  }
215  }
216  else
217  {
218  if ( newColumnMapping.size() == mColumnMapping.size() - removedColumnCount )
219  {
220  //the amount of removed column in the model need to be equal removedColumnCount
221  beginRemoveColumns( QModelIndex(), firstRemovedColumn, firstRemovedColumn + removedColumnCount - 1 );
222  mColumnMapping = newColumnMapping;
223  endRemoveColumns();
224  }
225  else
226  {
227  requiresReset = true;
228  }
229  }
230 
231  if ( requiresReset )
232  {
233  beginResetModel();
234  mColumnMapping = newColumnMapping;
235  endResetModel();
236  }
237  }
238 
239  if ( !config.sortExpression().isEmpty() )
240  sort( config.sortExpression(), config.sortOrder() );
241 }
242 
244 {
245  mFilterExpression = expression;
246  mFilterExpressionContext = context;
247 }
248 
249 void QgsAttributeTableFilterModel::sort( const QString &expression, Qt::SortOrder order )
250 {
251  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
252  order = Qt::AscendingOrder;
253 
254  QSortFilterProxyModel::sort( -1 );
255  masterModel()->prefetchSortData( expression );
256  QSortFilterProxyModel::sort( 0, order );
257 }
258 
260 {
261  return masterModel()->sortCacheExpression();
262 }
263 
265 {
266  if ( mSelectedOnTop != selectedOnTop )
267  {
268  mSelectedOnTop = selectedOnTop;
269  int column = sortColumn();
270  Qt::SortOrder order = sortOrder();
271 
272  // set default sort values if they are not correctly set
273  if ( column < 0 )
274  column = 0;
275 
276  if ( order != Qt::AscendingOrder && order != Qt::DescendingOrder )
277  order = Qt::AscendingOrder;
278 
279  sort( 0, Qt::AscendingOrder );
280  invalidate();
281  }
282 }
283 
285 {
286  mTableModel = sourceModel;
287 
288  for ( int i = 0; i < mTableModel->columnCount() - mTableModel->extraColumns(); ++i )
289  {
290  mColumnMapping.append( i );
291  }
292 
293  QSortFilterProxyModel::setSourceModel( sourceModel );
294 
295  // Disconnect any code to update columns in the parent, we handle this manually
296  disconnect( mTableModel, SIGNAL( columnsAboutToBeInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeInserted( QModelIndex, int, int ) ) );
297  disconnect( mTableModel, SIGNAL( columnsInserted( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsInserted( QModelIndex, int, int ) ) );
298  disconnect( mTableModel, SIGNAL( columnsAboutToBeRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsAboutToBeRemoved( QModelIndex, int, int ) ) );
299  disconnect( mTableModel, SIGNAL( columnsRemoved( QModelIndex, int, int ) ), this, SLOT( _q_sourceColumnsRemoved( QModelIndex, int, int ) ) );
300  // The following connections are needed in order to keep the filter model in sync, see: regression #15974
301  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeInserted, this, &QgsAttributeTableFilterModel::onColumnsChanged );
302  connect( mTableModel, &QAbstractItemModel::columnsAboutToBeRemoved, this, &QgsAttributeTableFilterModel::onColumnsChanged );
303 
304 }
305 
307 {
308  return mSelectedOnTop;
309 }
310 
312 {
313  mFilteredFeatures = ids;
315  invalidateFilter();
316 }
317 
319 {
320  QgsFeatureIds ids;
321  ids.reserve( rowCount() );
322  for ( int i = 0; i < rowCount(); ++i )
323  {
324  QModelIndex row = index( i, 0 );
325  ids << rowToId( row );
326  }
327  return ids;
328 }
329 
331 {
332  if ( filterMode != mFilterMode )
333  {
336  mFilterMode = filterMode;
337  invalidateFilter();
338  }
339 }
340 
342 {
343  // cleanup existing connections
344  switch ( mFilterMode )
345  {
346  case ShowVisible:
347  disconnect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
348  disconnect( mCanvas, &QgsMapCanvas::temporalRangeChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
349  disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
350  disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
351  break;
352  case ShowAll:
353  case ShowEdited:
354  case ShowSelected:
355  break;
356  case ShowFilteredList:
357  disconnect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
358  disconnect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
359  disconnect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
360  break;
361  }
362 }
363 
365 {
366  // setup new connections
367  switch ( filterMode )
368  {
369  case ShowVisible:
370  connect( mCanvas, &QgsMapCanvas::extentsChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
371  connect( mCanvas, &QgsMapCanvas::temporalRangeChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
372  connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
373  connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::startTimedReloadVisible );
375  break;
376  case ShowAll:
377  case ShowEdited:
378  case ShowSelected:
379  break;
380  case ShowFilteredList:
381  connect( layer(), &QgsVectorLayer::featureAdded, this, &QgsAttributeTableFilterModel::startTimedFilterFeatures );
382  connect( layer(), &QgsVectorLayer::attributeValueChanged, this, &QgsAttributeTableFilterModel::onAttributeValueChanged );
383  connect( layer(), &QgsVectorLayer::geometryChanged, this, &QgsAttributeTableFilterModel::onGeometryChanged );
384  break;
385  }
386 }
387 
388 bool QgsAttributeTableFilterModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
389 {
390  Q_UNUSED( sourceParent )
391  switch ( mFilterMode )
392  {
393  case ShowAll:
394  return true;
395 
396  case ShowFilteredList:
397  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
398 
399  case ShowSelected:
400  return layer()->selectedFeatureIds().contains( masterModel()->rowToId( sourceRow ) );
401 
402  case ShowVisible:
403  return mFilteredFeatures.contains( masterModel()->rowToId( sourceRow ) );
404 
405  case ShowEdited:
406  {
407  QgsVectorLayerEditBuffer *editBuffer = layer()->editBuffer();
408  if ( editBuffer )
409  {
410  QgsFeatureId fid = masterModel()->rowToId( sourceRow );
411 
412  if ( editBuffer->isFeatureAdded( fid ) )
413  return true;
414 
415  if ( editBuffer->isFeatureAttributesChanged( fid ) )
416  return true;
417 
418  if ( editBuffer->isFeatureGeometryChanged( fid ) )
419  return true;
420 
421  return false;
422  }
423  return false;
424  }
425 
426  default:
427  Q_ASSERT( false ); // In debug mode complain
428  return true; // In release mode accept row
429  }
430  // returns are handled in their respective case statement above
431 }
432 
434 {
435  reloadVisible();
436 }
437 
438 void QgsAttributeTableFilterModel::reloadVisible()
439 {
441  invalidateFilter();
442  emit visibleReloaded();
443 }
444 
445 void QgsAttributeTableFilterModel::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
446 {
447  Q_UNUSED( fid );
448  Q_UNUSED( value );
449 
450  if ( mFilterExpression.referencedAttributeIndexes( layer()->fields() ).contains( idx ) )
451  {
452  startTimedFilterFeatures();
453  }
454 }
455 
456 void QgsAttributeTableFilterModel::onGeometryChanged()
457 {
458  if ( mFilterExpression.needsGeometry() )
459  {
460  startTimedFilterFeatures();
461  }
462 }
463 
464 void QgsAttributeTableFilterModel::startTimedReloadVisible()
465 {
466  mReloadVisibleTimer.start( 10 );
467 }
468 
469 void QgsAttributeTableFilterModel::startTimedFilterFeatures()
470 {
471  mFilterFeaturesTimer.start( 10 );
472 }
473 
475 {
476  if ( !mFilterExpression.isValid() )
477  return;
478 
480  QgsDistanceArea distanceArea;
481 
482  distanceArea.setSourceCrs( mTableModel->layer()->crs(), QgsProject::instance()->transformContext() );
483  distanceArea.setEllipsoid( QgsProject::instance()->ellipsoid() );
484 
485  const bool fetchGeom = mFilterExpression.needsGeometry();
486 
487  QApplication::setOverrideCursor( Qt::WaitCursor );
488 
489  mFilterExpression.setGeomCalculator( &distanceArea );
490  mFilterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
491  mFilterExpression.setAreaUnits( QgsProject::instance()->areaUnits() );
492  QgsFeatureRequest request( mTableModel->request() );
493  request.setSubsetOfAttributes( mFilterExpression.referencedColumns(), mTableModel->layer()->fields() );
494  if ( !fetchGeom )
495  {
497  }
498  else
499  {
500  // force geometry extraction if the filter requests it
501  request.setFlags( request.flags() & ~QgsFeatureRequest::NoGeometry );
502  }
503  QgsFeatureIterator featIt = mTableModel->layer()->getFeatures( request );
504 
505  QgsFeature f;
506 
507  // Record the first evaluation error
508  QString error;
509 
510  while ( featIt.nextFeature( f ) )
511  {
512  mFilterExpressionContext.setFeature( f );
513  if ( mFilterExpression.evaluate( &mFilterExpressionContext ).toInt() != 0 )
514  filteredFeatures << f.id();
515 
516  // check if there were errors during evaluating
517  if ( mFilterExpression.hasEvalError() && error.isEmpty() )
518  {
519  error = mFilterExpression.evalErrorString( );
520  }
521  }
522 
523  featIt.close();
524 
526 
527  QApplication::restoreOverrideCursor();
528 
529  emit featuresFiltered();
530 
531  if ( ! error.isEmpty() )
532  {
533  emit filterError( error );
534  }
535 
536 }
537 
538 
539 void QgsAttributeTableFilterModel::selectionChanged()
540 {
541  if ( ShowSelected == mFilterMode )
542  {
543  invalidateFilter();
544  }
545  else if ( mSelectedOnTop )
546  {
547  invalidate();
548  }
549 }
550 
551 void QgsAttributeTableFilterModel::onColumnsChanged()
552 {
553  setAttributeTableConfig( mConfig );
554 }
555 
556 int QgsAttributeTableFilterModel::mapColumnToSource( int column ) const
557 {
558  if ( mColumnMapping.isEmpty() )
559  return column;
560  if ( column < 0 || column >= mColumnMapping.size() )
561  return -1;
562  else
563  return mColumnMapping.at( column );
564 }
565 
566 int QgsAttributeTableFilterModel::mapColumnFromSource( int column ) const
567 {
568  if ( mColumnMapping.isEmpty() )
569  return column;
570  else
571  return mColumnMapping.indexOf( column );
572 }
573 
575 {
576  if ( !layer() )
577  return;
578 
579  bool filter = false;
580  QgsRectangle rect = mCanvas->mapSettings().mapToLayerCoordinates( layer(), mCanvas->extent() );
581  QgsRenderContext renderContext;
583 
584  mFilteredFeatures.clear();
585  if ( !layer()->renderer() )
586  {
587  QgsDebugMsg( QStringLiteral( "Cannot get renderer" ) );
588  return;
589  }
590 
591  std::unique_ptr< QgsFeatureRenderer > renderer( layer()->renderer()->clone() );
592 
593  const QgsMapSettings &ms = mCanvas->mapSettings();
594  if ( !layer()->isInScaleRange( ms.scale() ) )
595  {
596  QgsDebugMsg( QStringLiteral( "Out of scale limits" ) );
597  }
598  else
599  {
600  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
601  {
602  // setup scale
603  // mapRenderer()->renderContext()->scale is not automatically updated when
604  // render extent changes (because it's scale is used to identify if changed
605  // since last render) -> use local context
606  renderContext.setExtent( ms.visibleExtent() );
607  renderContext.setMapToPixel( ms.mapToPixel() );
608  renderContext.setRendererScale( ms.scale() );
609  }
610 
611  filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
612  }
613 
614  renderer->startRender( renderContext, layer()->fields() );
615 
616  QgsFeatureRequest r( masterModel()->request() );
617  if ( !r.filterRect().isNull() )
618  {
619  r.setFilterRect( r.filterRect().intersect( rect ) );
620  }
621  else
622  {
623  r.setFilterRect( rect );
624  }
625 
626  if ( mCanvas->mapSettings().isTemporal() )
627  {
628  if ( !layer()->temporalProperties()->isVisibleInTemporalRange( mCanvas->mapSettings().temporalRange() ) )
629  return;
630 
631  QgsVectorLayerTemporalContext temporalContext;
632  temporalContext.setLayer( layer() );
633  const QString temporalFilter = qobject_cast< const QgsVectorLayerTemporalProperties * >( layer()->temporalProperties() )->createFilterString( temporalContext, mCanvas->mapSettings().temporalRange() );
634  if ( !temporalFilter.isEmpty() )
635  r.setFilterExpression( temporalFilter );
636  }
637 
639 
640  QgsFeature f;
641 
642  while ( features.nextFeature( f ) )
643  {
644  renderContext.expressionContext().setFeature( f );
645  if ( !filter || renderer->willRenderFeature( f, renderContext ) )
646  {
647  mFilteredFeatures << f.id();
648  }
649 #if 0
650  if ( t.elapsed() > 5000 )
651  {
652  bool cancel = false;
653  emit progress( i, cancel );
654  if ( cancel )
655  break;
656 
657  t.restart();
658  }
659 #endif
660  }
661 
662  features.close();
663 
664  if ( renderer->capabilities() & QgsFeatureRenderer::ScaleDependent )
665  {
666  renderer->stopRender( renderContext );
667  }
668 }
669 
671 {
672  return masterModel()->rowToId( mapToSource( row ).row() );
673 }
674 
676 {
677  return mapFromMaster( masterModel()->idToIndex( fid ) );
678 }
679 
681 {
682  QModelIndexList indexes;
683  const auto constIdToIndexList = masterModel()->idToIndexList( fid );
684  for ( const QModelIndex &idx : constIdToIndexList )
685  {
686  indexes.append( mapFromMaster( idx ) );
687  }
688 
689  return indexes;
690 }
691 
692 QModelIndex QgsAttributeTableFilterModel::mapToSource( const QModelIndex &proxyIndex ) const
693 {
694  if ( !proxyIndex.isValid() )
695  return QModelIndex();
696 
697  int sourceColumn = mapColumnToSource( proxyIndex.column() );
698 
699  // For the action column there is no matching column in the source model, just return the first one
700  // so we are still able to query for the feature id, the feature...
701  if ( sourceColumn == -1 )
702  sourceColumn = 0;
703 
704  return QSortFilterProxyModel::mapToSource( index( proxyIndex.row(), sourceColumn, proxyIndex.parent() ) );
705 }
706 
707 QModelIndex QgsAttributeTableFilterModel::mapFromSource( const QModelIndex &sourceIndex ) const
708 {
709  QModelIndex proxyIndex = QSortFilterProxyModel::mapFromSource( sourceIndex );
710 
711  if ( proxyIndex.column() < 0 )
712  return QModelIndex();
713 
714  int col = mapColumnFromSource( proxyIndex.column() );
715 
716  if ( col == -1 )
717  col = 0;
718 
719  return index( proxyIndex.row(), col, proxyIndex.parent() );
720 }
721 
722 Qt::ItemFlags QgsAttributeTableFilterModel::flags( const QModelIndex &index ) const
723 {
724  // Handle the action column flags here, the master model doesn't know it
725  if ( mapColumnToSource( index.column() ) == -1 )
726  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
727 
728  QModelIndex source_index = mapToSource( index );
729  return masterModel()->flags( source_index );
730 }
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:265
@ Filter
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ....
Definition: qgsrenderer.h:264
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 unique ID, geometry and a list of field...
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:76
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:467
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:479
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Definition: qgsrectangle.h:333
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:127
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.