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