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