Skip to content

Commit

Permalink
Don't allow selection of invisible features due to temporal filters
Browse files Browse the repository at this point in the history
Fixes #40818
  • Loading branch information
nyalldawson committed Jan 4, 2021
1 parent 7edb765 commit 67d5754
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/app/qgsmaptoolselectutils.cpp
Expand Up @@ -33,6 +33,7 @@ email : jpalmer at linz dot govt dot nz
#include "qgsproject.h"
#include "qgsexpressioncontextutils.h"
#include "qgsmessagelog.h"
#include "qgsvectorlayertemporalproperties.h"

#include <QMouseEvent>
#include <QApplication>
Expand Down Expand Up @@ -257,6 +258,17 @@ QgsFeatureIds QgsMapToolSelectUtils::getMatchingFeatures( QgsMapCanvas *canvas,
r->startRender( context, vlayer->fields() );
}

QString temporalFilter;
if ( canvas->mapSettings().isTemporal() )
{
if ( !vlayer->temporalProperties()->isVisibleInTemporalRange( canvas->temporalRange() ) )
return newSelectedFeatures;

QgsVectorLayerTemporalContext temporalContext;
temporalContext.setLayer( vlayer );
temporalFilter = qobject_cast< const QgsVectorLayerTemporalProperties * >( vlayer->temporalProperties() )->createFilterString( temporalContext, canvas->temporalRange() );
}

QgsFeatureRequest request;
request.setFilterRect( selectGeomTrans.boundingBox() );
request.setFlags( QgsFeatureRequest::ExactIntersect );
Expand All @@ -265,6 +277,17 @@ QgsFeatureIds QgsMapToolSelectUtils::getMatchingFeatures( QgsMapCanvas *canvas,
else
request.setNoAttributes();

if ( !temporalFilter.isEmpty() )
request.setFilterExpression( temporalFilter );
if ( r )
{
const QString filterExpression = r->filter( vlayer->fields() );
if ( !filterExpression.isEmpty() )
{
request.combineFilterExpression( filterExpression );
}
}

QgsFeatureIterator fit = vlayer->getFeatures( request );

QgsFeature f;
Expand Down Expand Up @@ -365,7 +388,8 @@ QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::QgsMapToolSelectMenuActions(
QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::~QgsMapToolSelectMenuActions()
{
removeHighlight();
mJobData->isCanceled = true;
if ( mJobData )
mJobData->isCanceled = true;
if ( mFutureWatcher )
mFutureWatcher->waitForFinished();
}
Expand All @@ -384,13 +408,26 @@ void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::populateMenu( QMenu *me

void QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::startFeatureSearch()
{
QString temporalFilter;
if ( mCanvas->mapSettings().isTemporal() )
{
if ( !mVectorLayer->temporalProperties()->isVisibleInTemporalRange( mCanvas->temporalRange() ) )
return;

QgsVectorLayerTemporalContext temporalContext;
temporalContext.setLayer( mVectorLayer );
temporalFilter = qobject_cast< const QgsVectorLayerTemporalProperties * >( mVectorLayer->temporalProperties() )->createFilterString( temporalContext, mCanvas->temporalRange() );
}

mJobData = std::make_shared<DataForSearchingJob>();
mJobData->isCanceled = false;
mJobData->source.reset( new QgsVectorLayerFeatureSource( mVectorLayer ) );
mJobData->selectGeometry = mSelectGeometry;
mJobData->context = QgsRenderContext::fromMapSettings( mCanvas->mapSettings() );
mJobData->filterString = temporalFilter;
mJobData->ct = QgsCoordinateTransform( mCanvas->mapSettings().destinationCrs(), mVectorLayer->crs(), mJobData->context.transformContext() );
mJobData->featureRenderer.reset( mVectorLayer->renderer()->clone() );

mJobData->context.expressionContext() << QgsExpressionContextUtils::layerScope( mVectorLayer );
mJobData->selectBehavior = mBehavior;
if ( mBehavior != QgsVectorLayer::SetSelection )
Expand All @@ -411,7 +448,6 @@ QgsFeatureIds QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::search( std::s
if ( ! transformSelectGeometry( data->selectGeometry, selectGeomTrans, data->ct ) )
return newSelectedFeatures;


// make sure the selection geometry is valid, or intersection tests won't work correctly...
if ( !selectGeomTrans.isGeosValid( ) )
{
Expand All @@ -434,8 +470,18 @@ QgsFeatureIds QgsMapToolSelectUtils::QgsMapToolSelectMenuActions::search( std::s
request.setFilterRect( selectGeomTrans.boundingBox() );
request.setFlags( QgsFeatureRequest::ExactIntersect );

if ( !data->filterString.isEmpty() )
request.setFilterExpression( data->filterString );

if ( r )
{
request.setSubsetOfAttributes( r->usedAttributes( data->context ), data->source->fields() );
const QString filterExpression = r->filter( data->source->fields() );
if ( !filterExpression.isEmpty() )
{
request.combineFilterExpression( filterExpression );
}
}

QgsFeatureIterator fit = data->source->getFeatures( request );

Expand Down
1 change: 1 addition & 0 deletions src/app/qgsmaptoolselectutils.h
Expand Up @@ -189,6 +189,7 @@ namespace QgsMapToolSelectUtils
QgsCoordinateTransform ct;
QgsRenderContext context;
std::unique_ptr<QgsFeatureRenderer> featureRenderer;
QString filterString;
QgsVectorLayer::SelectBehavior selectBehavior;
QgsFeatureIds existingSelection;
};
Expand Down

0 comments on commit 67d5754

Please sign in to comment.