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