Skip to content

Commit

Permalink
avoid freeze with multiple layers locator search (#8650) (#8659)
Browse files Browse the repository at this point in the history
* avoid freeze with multiple layers locator search

if the project had many searchable layers, a freeze occured when running the all features locator filter
the feature iterator was created in prepare (main thread) and the maximum number of connection was reached

* fix leak + clear former prepared layers

* avoid copy in loop

* declare ptr earlier
  • Loading branch information
3nids authored Dec 12, 2018
1 parent 2f7d634 commit 0a01725
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
40 changes: 22 additions & 18 deletions src/app/locator/qgsinbuiltlocatorfilters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
* *
***************************************************************************/

#include <QToolButton>
#include <QClipboard>

#include "qgsinbuiltlocatorfilters.h"
#include "qgsproject.h"
Expand All @@ -25,8 +27,8 @@
#include "qgsmaplayermodel.h"
#include "qgslayoutmanager.h"
#include "qgsmapcanvas.h"
#include <QToolButton>
#include <QClipboard>
#include "qgsvectorlayerfeatureiterator.h"


QgsLayerTreeLocatorFilter::QgsLayerTreeLocatorFilter( QObject *parent )
: QgsLocatorFilter( parent )
Expand Down Expand Up @@ -342,6 +344,7 @@ void QgsAllLayersFeaturesLocatorFilter::prepare( const QString &string, const Qg
if ( string.length() < 3 && !context.usingPrefix )
return;

mPreparedLayers.clear();
const QMap<QString, QgsMapLayer *> layers = QgsProject::instance()->mapLayers();
for ( auto it = layers.constBegin(); it != layers.constEnd(); ++it )
{
Expand All @@ -359,17 +362,17 @@ void QgsAllLayersFeaturesLocatorFilter::prepare( const QString &string, const Qg
if ( !expression.needsGeometry() )
req.setFlags( QgsFeatureRequest::NoGeometry );
req.setFilterExpression( QStringLiteral( "%1 ILIKE '%%2%'" )
.arg( layer->displayExpression(),
string ) );
.arg( layer->displayExpression(), string ) );
req.setLimit( 30 );

PreparedLayer preparedLayer;
preparedLayer.expression = expression;
preparedLayer.context = context;
preparedLayer.layerId = layer->id();
preparedLayer.layerName = layer->name();
preparedLayer.iterator = layer->getFeatures( req );
preparedLayer.layerIcon = QgsMapLayerModel::iconForLayer( layer );
std::shared_ptr<PreparedLayer> preparedLayer( new PreparedLayer() );
preparedLayer->expression = expression;
preparedLayer->context = context;
preparedLayer->layerId = layer->id();
preparedLayer->layerName = layer->name();
preparedLayer->featureSource.reset( new QgsVectorLayerFeatureSource( layer ) );
preparedLayer->request = req;
preparedLayer->layerIcon = QgsMapLayerModel::iconForLayer( layer );

mPreparedLayers.append( preparedLayer );
}
Expand All @@ -382,23 +385,24 @@ void QgsAllLayersFeaturesLocatorFilter::fetchResults( const QString &string, con
QgsFeature f;

// we cannot used const loop since iterator::nextFeature is not const
for ( PreparedLayer preparedLayer : mPreparedLayers )
for ( auto preparedLayer : qgis::as_const( mPreparedLayers ) )
{
foundInCurrentLayer = 0;
while ( preparedLayer.iterator.nextFeature( f ) )
QgsFeatureIterator it = preparedLayer->featureSource->getFeatures( preparedLayer->request );
while ( it.nextFeature( f ) )
{
if ( feedback->isCanceled() )
return;

QgsLocatorResult result;
result.group = preparedLayer.layerName;
result.group = preparedLayer->layerName;

preparedLayer.context.setFeature( f );
preparedLayer->context.setFeature( f );

result.displayString = preparedLayer.expression.evaluate( &( preparedLayer.context ) ).toString();
result.displayString = preparedLayer->expression.evaluate( &( preparedLayer->context ) ).toString();

result.userData = QVariantList() << f.id() << preparedLayer.layerId;
result.icon = preparedLayer.layerIcon;
result.userData = QVariantList() << f.id() << preparedLayer->layerId;
result.icon = preparedLayer->layerIcon;
result.score = static_cast< double >( string.length() ) / result.displayString.size();
emit resultFetched( result );

Expand Down
7 changes: 5 additions & 2 deletions src/app/locator/qgsinbuiltlocatorfilters.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "qgslocatorfilter.h"
#include "qgsexpressioncontext.h"
#include "qgsfeatureiterator.h"
#include "qgsvectorlayerfeatureiterator.h"


class QAction;

Expand Down Expand Up @@ -124,7 +126,8 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
public:
QgsExpression expression;
QgsExpressionContext context;
QgsFeatureIterator iterator;
std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;
QgsFeatureRequest request;
QString layerName;
QString layerId;
QIcon layerIcon;
Expand All @@ -144,7 +147,7 @@ class APP_EXPORT QgsAllLayersFeaturesLocatorFilter : public QgsLocatorFilter
private:
int mMaxResultsPerLayer = 6;
int mMaxTotalResults = 12;
QList<PreparedLayer> mPreparedLayers;
QList<std::shared_ptr<PreparedLayer>> mPreparedLayers;


};
Expand Down

0 comments on commit 0a01725

Please sign in to comment.