Skip to content

Commit

Permalink
optional fids counting
Browse files Browse the repository at this point in the history
  • Loading branch information
roya0045 authored and nyalldawson committed Nov 4, 2019
1 parent 78afeea commit 38fb55e
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 15 deletions.
4 changes: 3 additions & 1 deletion python/core/auto_generated/qgsvectorlayer.sip.in
Expand Up @@ -1042,13 +1042,15 @@ if the geometry type of the new data source matches the current geometry type of
virtual QString loadDefaultStyle( bool &resultFlag /Out/ ) ${SIP_FINAL};


QgsVectorLayerFeatureCounter *countSymbolFeatures();
QgsVectorLayerFeatureCounter *countSymbolFeatures( bool storeSymbolFids = false );
%Docstring
Count features for symbols.
The method will return the feature counter task. You will need to
connect to the symbolFeatureCountMapChanged() signal to be
notified when the freshly updated feature counts are ready.

:param storeSymbolFids: If ``True`` will gather the feature ids (fids) per symbol, otherwise only the count. Default ``False``.

.. note::

If the count features for symbols has been already done a
Expand Down
Expand Up @@ -24,9 +24,13 @@ QgsVectorLayer.countSymbolFeatures() and connect to the signal
%End
public:

QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context = QgsExpressionContext() );
QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context = QgsExpressionContext(), bool storeSymbolFids = false );
%Docstring
Create a new feature counter for ``layer``.

:param layer: Target QgsVectorLayer to perform counting on.
:param context: Specific QgsExpressionContext to use during the rendering step.
:param storeSymbolFids: If ``True`` will store the feature ids (fids), otherwise will only count the number of features per symbol. Default ``False``.
%End


Expand Down
14 changes: 6 additions & 8 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -730,10 +730,9 @@ QgsFeatureIds QgsVectorLayer::symbolFeatureIds( const QString &legendKey ) const

return mSymbolFeatureIdMap.value( legendKey, QgsFeatureIds() );
}

QgsVectorLayerFeatureCounter *QgsVectorLayer::countSymbolFeatures()
QgsVectorLayerFeatureCounter *QgsVectorLayer::countSymbolFeatures( bool storeSymbolFids )
{
if ( mSymbolFeatureCounted || mFeatureCounter )
if ( ( mSymbolFeatureCounted || mFeatureCounter ) && !( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) )
return mFeatureCounter;

mSymbolFeatureCountMap.clear();
Expand All @@ -755,12 +754,11 @@ QgsVectorLayerFeatureCounter *QgsVectorLayer::countSymbolFeatures()
return mFeatureCounter;
}

if ( !mFeatureCounter )
if ( !mFeatureCounter || ( mFeatureCounter && ( storeSymbolFids && mSymbolFeatureIdMap.isEmpty() ) ) )
{
mFeatureCounter = new QgsVectorLayerFeatureCounter( this );
connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted );
connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated );

mFeatureCounter = new QgsVectorLayerFeatureCounter( this, QgsExpressionContext(), storeSymbolFids );
connect( mFeatureCounter, &QgsTask::taskCompleted, this, &QgsVectorLayer::onFeatureCounterCompleted, Qt::UniqueConnection );
connect( mFeatureCounter, &QgsTask::taskTerminated, this, &QgsVectorLayer::onFeatureCounterTerminated, Qt::UniqueConnection );
QgsApplication::taskManager()->addTask( mFeatureCounter );
}

Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsvectorlayer.h
Expand Up @@ -1082,13 +1082,14 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
* connect to the symbolFeatureCountMapChanged() signal to be
* notified when the freshly updated feature counts are ready.
*
* \param storeSymbolFids If TRUE will gather the feature ids (fids) per symbol, otherwise only the count. Default FALSE.
* \note If the count features for symbols has been already done a
* NULLPTR is returned. If you need to wait for the results,
* you can call waitForFinished() on the feature counter.
*
* \since This is asynchronous since QGIS 3.0
*/
QgsVectorLayerFeatureCounter *countSymbolFeatures();
QgsVectorLayerFeatureCounter *countSymbolFeatures( bool storeSymbolFids = false );

/**
* Sets the string (typically sql) used to define a subset of the layer
Expand Down
9 changes: 6 additions & 3 deletions src/core/qgsvectorlayerfeaturecounter.cpp
Expand Up @@ -17,11 +17,12 @@
#include "qgsvectorlayer.h"
#include "qgsfeatureid.h"

QgsVectorLayerFeatureCounter::QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context )
QgsVectorLayerFeatureCounter::QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context, bool storeSymbolFids )
: QgsTask( tr( "Counting features in %1" ).arg( layer->name() ), QgsTask::CanCancel )
, mSource( new QgsVectorLayerFeatureSource( layer ) )
, mRenderer( layer->renderer()->clone() )
, mExpressionContext( context )
, mWithFids( storeSymbolFids )
, mFeatureCount( layer->featureCount() )
{
if ( !mExpressionContext.scopeCount() )
Expand All @@ -40,7 +41,8 @@ bool QgsVectorLayerFeatureCounter::run()
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
{
mSymbolFeatureCountMap.insert( symbolIt->label(), 0 );
mSymbolFeatureIdMap.insert( symbolIt->label(), QgsFeatureIds() );
if ( mWithFids )
mSymbolFeatureIdMap.insert( symbolIt->label(), QgsFeatureIds() );
}

// If there are no features to be counted, we can spare us the trouble
Expand Down Expand Up @@ -74,7 +76,8 @@ bool QgsVectorLayerFeatureCounter::run()
for ( const QString &key : featureKeyList )
{
mSymbolFeatureCountMap[key] += 1;
mSymbolFeatureIdMap[key].insert( f.id() );
if ( mWithFids )
mSymbolFeatureIdMap[key].insert( f.id() );
}
++featuresCounted;

Expand Down
6 changes: 5 additions & 1 deletion src/core/qgsvectorlayerfeaturecounter.h
Expand Up @@ -38,8 +38,11 @@ class CORE_EXPORT QgsVectorLayerFeatureCounter : public QgsTask

/**
* Create a new feature counter for \a layer.
* \param layer Target QgsVectorLayer to perform counting on.
* \param context Specific QgsExpressionContext to use during the rendering step.
* \param storeSymbolFids If TRUE will store the feature ids (fids), otherwise will only count the number of features per symbol. Default FALSE.
*/
QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context = QgsExpressionContext() );
QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context = QgsExpressionContext(), bool storeSymbolFids = false );


/**
Expand Down Expand Up @@ -92,6 +95,7 @@ class CORE_EXPORT QgsVectorLayerFeatureCounter : public QgsTask
QgsExpressionContext mExpressionContext;
QHash<QString, long> mSymbolFeatureCountMap;
QHash<QString, QgsFeatureIds> mSymbolFeatureIdMap;
bool mWithFids = false;
int mFeatureCount;

};
Expand Down

0 comments on commit 38fb55e

Please sign in to comment.