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