Skip to content
Permalink
Browse files

filterFeatures functionality in attributetable filter model instead o…

…f the widget for re-filtering on main model data changed (e.g. add feature)
  • Loading branch information
signedav committed Mar 16, 2020
1 parent 1f53537 commit 6d1fdc6629c4a12af914c8128ddff7ef57eb54ed
@@ -196,6 +196,12 @@ Returns -1 if none is defined.
Set the attribute table configuration to control which fields are shown,
in which order they are shown as well as if and where an action column
is shown.
%End

void setFilterExpression( const QgsExpression &expression, const QgsExpressionContext &context );
%Docstring
Set the ``expression`` to be stored in case of the features need to be
filtered (like on filter or on main model data change).
%End

signals:
@@ -241,6 +247,8 @@ the master table model changes.
When a change is signalled, the filter is updated and invalidated if needed.
%End

void filterFeatures();

};

/************************************************************************
@@ -122,13 +122,18 @@ filter restrictions
:return: Number of features
%End

void setFilteredFeatures( const QgsFeatureIds &filteredFeatures );
void setFilteredFeatures( const QgsFeatureIds &filteredFeatures );
%Docstring
Set a list of currently visible features

:param filteredFeatures: A list of feature ids

.. deprecated::
since filterFeatures is handled in the attribute filter model itself
%End

void filterFeatures( const QgsExpression &filterExpression, const QgsExpressionContext &context );

QgsFeatureIds filteredFeatures();
%Docstring
Gets a list of currently visible feature ids.
@@ -26,6 +26,7 @@
#include "qgsrenderer.h"
#include "qgsvectorlayereditbuffer.h"
#include "qgsexpressioncontextutils.h"
#include "qgsapplication.h"

//////////////////
// Filter Model //
@@ -323,6 +324,15 @@ void QgsAttributeTableFilterModel::setFilterMode( FilterMode filterMode )
disconnect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::reloadVisible );
}

if ( filterMode == ShowFilteredList )
{
connect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::filterFeatures );
}
else
{
disconnect( mTableModel, &QgsAttributeTableModel::dataChanged, this, &QgsAttributeTableFilterModel::filterFeatures );
}

mFilterMode = filterMode;
invalidateFilter();
}
@@ -379,6 +389,58 @@ void QgsAttributeTableFilterModel::reloadVisible()
invalidateFilter();
}

void QgsAttributeTableFilterModel::filterFeatures()
{
if ( !mFilterExpression.isValid() )
return;

QgsFeatureIds filteredFeatures;
QgsDistanceArea myDa;

myDa.setSourceCrs( mTableModel->layer()->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );

bool fetchGeom = mFilterExpression.needsGeometry();

QApplication::setOverrideCursor( Qt::WaitCursor );

mFilterExpression.setGeomCalculator( &myDa );
mFilterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
mFilterExpression.setAreaUnits( QgsProject::instance()->areaUnits() );
QgsFeatureRequest request( mTableModel->request() );
request.setSubsetOfAttributes( mFilterExpression.referencedColumns(), mTableModel->layer()->fields() );
if ( !fetchGeom )
{
request.setFlags( QgsFeatureRequest::NoGeometry );
}
else
{
// force geometry extraction if the filter requests it
request.setFlags( request.flags() & ~QgsFeatureRequest::NoGeometry );
}
QgsFeatureIterator featIt = mTableModel->layer()->getFeatures( request );

QgsFeature f;

while ( featIt.nextFeature( f ) )
{
mFilterExpressionContext.setFeature( f );
if ( mFilterExpression.evaluate( &mFilterExpressionContext ).toInt() != 0 )
filteredFeatures << f.id();

// check if there were errors during evaluating
if ( mFilterExpression.hasEvalError() )
break;
}

featIt.close();

setFilteredFeatures( filteredFeatures );

QApplication::restoreOverrideCursor();
}


void QgsAttributeTableFilterModel::selectionChanged()
{
if ( ShowSelected == mFilterMode )
@@ -221,6 +221,12 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
*/
void setAttributeTableConfig( const QgsAttributeTableConfig &config );

/**
* Set the \a expression to be stored in case of the features need to be
* filtered (like on filter or on main model data change).
*/
void setFilterExpression( const QgsExpression &expression, const QgsExpressionContext &context ) { mFilterExpression = expression; mFilterExpressionContext = context; }

signals:

/**
@@ -261,6 +267,8 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub
*/
void reloadVisible();

void filterFeatures();

private slots:
void selectionChanged();
void onColumnsChanged();
@@ -274,6 +282,9 @@ class GUI_EXPORT QgsAttributeTableFilterModel: public QSortFilterProxyModel, pub

QgsAttributeTableConfig mConfig;
QVector<int> mColumnMapping;
QgsExpression mFilterExpression;
QgsExpressionContext mFilterExpressionContext;

int mapColumnToSource( int column ) const;
int mapColumnFromSource( int column ) const;

@@ -1076,6 +1076,13 @@ void QgsDualView::setFilteredFeatures( const QgsFeatureIds &filteredFeatures )
mFilterModel->setFilteredFeatures( filteredFeatures );
}

void QgsDualView::filterFeatures( const QgsExpression &filterExpression, const QgsExpressionContext &context )
{
mFilterModel->setFilterExpression( filterExpression, context );
mFilterModel->filterFeatures();
}


void QgsDualView::setRequest( const QgsFeatureRequest &request )
{
mMasterModel->setRequest( request );
@@ -157,8 +157,11 @@ class GUI_EXPORT QgsDualView : public QStackedWidget, private Ui::QgsDualViewBas
*
* \param filteredFeatures A list of feature ids
*
*/
void setFilteredFeatures( const QgsFeatureIds &filteredFeatures );
* \deprecated since filterFeatures is handled in the attribute filter model itself
*/
Q_DECL_DEPRECATED void setFilteredFeatures( const QgsFeatureIds &filteredFeatures );

void filterFeatures( const QgsExpression &filterExpression, const QgsExpressionContext &context );

/**
* Gets a list of currently visible feature ids.
@@ -89,7 +89,6 @@ void QgsFeatureFilterWidget::init( QgsVectorLayer *layer, const QgsAttributeEdit

connect( mLayer, &QgsVectorLayer::attributeAdded, this, &QgsFeatureFilterWidget::columnBoxInit );
connect( mLayer, &QgsVectorLayer::attributeDeleted, this, &QgsFeatureFilterWidget::columnBoxInit );
connect( mMainView->masterModel(), &QgsAttributeTableModel::dataChanged, this, &QgsFeatureFilterWidget::filterQueryAccepted );

//set delay on entering text
mFilterQueryTimer.setSingleShot( true );
@@ -447,12 +446,6 @@ void QgsFeatureFilterWidget::setFilterExpression( const QString &filterString, Q
}
}

QgsFeatureIds filteredFeatures;
QgsDistanceArea myDa;

myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );

// parse search string and build parsed tree
QgsExpression filterExpression( filter );
if ( filterExpression.hasParserError() )
@@ -468,50 +461,8 @@ void QgsFeatureFilterWidget::setFilterExpression( const QString &filterString, Q
mMessageBar->pushMessage( tr( "Evaluation error" ), filterExpression.evalErrorString(), Qgis::Warning, mMessageBarTimeout );
}

bool fetchGeom = filterExpression.needsGeometry();

QApplication::setOverrideCursor( Qt::WaitCursor );

filterExpression.setGeomCalculator( &myDa );
filterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
filterExpression.setAreaUnits( QgsProject::instance()->areaUnits() );
QgsFeatureRequest request( mMainView->masterModel()->request() );
request.setSubsetOfAttributes( filterExpression.referencedColumns(), mLayer->fields() );
if ( !fetchGeom )
{
request.setFlags( QgsFeatureRequest::NoGeometry );
}
else
{
// force geometry extraction if the filter requests it
request.setFlags( request.flags() & ~QgsFeatureRequest::NoGeometry );
}
QgsFeatureIterator featIt = mLayer->getFeatures( request );
mMainView->filterFeatures( filterExpression, context );

QgsFeature f;

while ( featIt.nextFeature( f ) )
{
context.setFeature( f );
if ( filterExpression.evaluate( &context ).toInt() != 0 )
filteredFeatures << f.id();

// check if there were errors during evaluating
if ( filterExpression.hasEvalError() )
break;
}

featIt.close();

mMainView->setFilteredFeatures( filteredFeatures );

QApplication::restoreOverrideCursor();

if ( filterExpression.hasEvalError() )
{
mMessageBar->pushMessage( tr( "Error filtering" ), filterExpression.evalErrorString(), Qgis::Warning, mMessageBarTimeout );
return;
}
mMainView->setFilterMode( QgsAttributeTableFilterModel::ShowFilteredList );
}

0 comments on commit 6d1fdc6

Please sign in to comment.
You can’t perform that action at this time.