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