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