QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgsvectorlayerfeaturecounter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayerfeaturecounter.cpp
3  ---------------------
4  begin : May 2017
5  copyright : (C) 2017 by Matthias Kuhn
6  email : matthias at opengis dot ch
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 #include "qgsvectorlayer.h"
18 
20  : QgsTask( tr( "Counting features in %1" ).arg( layer->name() ), QgsTask::CanCancel )
21  , mSource( new QgsVectorLayerFeatureSource( layer ) )
22  , mRenderer( layer->renderer()->clone() )
23  , mExpressionContext( context )
24  , mFeatureCount( layer->featureCount() )
25 {
26  if ( !mExpressionContext.scopeCount() )
27  {
28  mExpressionContext = layer->createExpressionContext();
29  }
30 }
31 
33 {
34  QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems();
35  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
36 
37  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
38  {
39  mSymbolFeatureCountMap.insert( symbolIt->label(), 0 );
40  }
41 
42  // If there are no features to be counted, we can spare us the trouble
43  if ( mFeatureCount > 0 )
44  {
45  int featuresCounted = 0;
46 
47  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
48  QgsRenderContext renderContext;
49  renderContext.setRendererScale( 0 );
50  renderContext.setExpressionContext( mExpressionContext );
51 
52  QgsFeatureRequest request;
53  if ( !mRenderer->filterNeedsGeometry() )
55  request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mSource->fields() );
56  QgsFeatureIterator fit = mSource->getFeatures( request );
57 
58  // TODO: replace QgsInterruptionChecker with QgsFeedback
59  // fit.setInterruptionChecker( mFeedback );
60 
61  mRenderer->startRender( renderContext, mSource->fields() );
62 
63  double progress = 0;
64  QgsFeature f;
65  while ( fit.nextFeature( f ) )
66  {
67  renderContext.expressionContext().setFeature( f );
68  QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
69  const auto constFeatureKeyList = featureKeyList;
70  for ( const QString &key : constFeatureKeyList )
71  {
72  mSymbolFeatureCountMap[key] += 1;
73  }
74  ++featuresCounted;
75 
76  double p = ( static_cast< double >( featuresCounted ) / mFeatureCount ) * 100;
77  if ( p - progress > 1 )
78  {
79  progress = p;
80  setProgress( progress );
81  }
82 
83  if ( isCanceled() )
84  {
85  mRenderer->stopRender( renderContext );
86  return false;
87  }
88  }
89  mRenderer->stopRender( renderContext );
90  }
91 
92  setProgress( 100 );
93 
94  emit symbolsCounted();
95  return true;
96 }
97 
99 {
100  return mSymbolFeatureCountMap;
101 }
102 
103 long QgsVectorLayerFeatureCounter::featureCount( const QString &legendKey ) const
104 {
105  return mSymbolFeatureCountMap.value( legendKey, -1 );
106 }
Wrapper for iterator of features from vector data provider or vector layer.
void setProgress(double progress)
Sets the task&#39;s current progress.
QList< QgsLegendSymbolItem > QgsLegendSymbolList
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
bool run() override
Performs the task&#39;s operation.
void setRendererScale(double scale)
Sets the renderer map scale.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
bool isCanceled() const
Will return true if task should terminate ASAP.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QgsVectorLayerFeatureCounter(QgsVectorLayer *layer, const QgsExpressionContext &context=QgsExpressionContext())
Create a new feature counter for layer.
void symbolsCounted()
Emitted when the symbols have been counted.
long featureCount(const QString &legendKey) const
Gets the feature count for a particular legendKey.
int scopeCount() const
Returns the number of scopes contained in the context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Abstract base class for long running background tasks.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Partial snapshot of vector layer&#39;s state (only the members necessary for access to features) ...
QgsExpressionContext & expressionContext()
Gets the expression context.
Contains information about the context of a rendering operation.
double progress() const
Returns the task&#39;s progress (between 0.0 and 100.0)
QHash< QString, long > symbolFeatureCountMap() const
Gets the count for each symbol.
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Represents a vector layer which manages a vector based data sets.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.