QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 #include "qgsfeatureid.h"
19 #include "qgsfeedback.h"
20 #include "qgsrendercontext.h"
21 
23  : QgsTask( tr( "Counting features in %1" ).arg( layer->name() ), QgsTask::CanCancel | QgsTask::CancelWithoutPrompt | QgsTask::Silent )
24  , mSource( new QgsVectorLayerFeatureSource( layer ) )
25  , mRenderer( layer->renderer()->clone() )
26  , mExpressionContext( context )
27  , mWithFids( storeSymbolFids )
28  , mFeatureCount( layer->featureCount() )
29 {
30  if ( !mExpressionContext.scopeCount() )
31  {
32  mExpressionContext = layer->createExpressionContext();
33  }
34 }
35 
37 
39 {
40  mSymbolFeatureCountMap.clear();
41  mSymbolFeatureIdMap.clear();
42  const QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems();
43  QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
44 
45  for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
46  {
47  mSymbolFeatureCountMap.insert( symbolIt->ruleKey(), 0 );
48  if ( mWithFids )
49  mSymbolFeatureIdMap.insert( symbolIt->ruleKey(), QgsFeatureIds() );
50  }
51 
52  // If there are no features to be counted, we can spare us the trouble
53  if ( mFeatureCount > 0 )
54  {
55  mFeedback = std::make_unique< QgsFeedback >();
56 
57  int featuresCounted = 0;
58 
59  // Renderer (rule based) may depend on context scale, with scale is ignored if 0
60  QgsRenderContext renderContext;
61  renderContext.setRendererScale( 0 );
62  renderContext.setExpressionContext( mExpressionContext );
63 
64  QgsFeatureRequest request;
65  if ( !mRenderer->filterNeedsGeometry() )
67  request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mSource->fields() );
68 
69  request.setFeedback( mFeedback.get() );
70  mExpressionContext.setFeedback( mFeedback.get() );
71 
72  QgsFeatureIterator fit = mSource->getFeatures( request );
73 
74  mRenderer->startRender( renderContext, mSource->fields() );
75 
76  double progress = 0;
77  QgsFeature f;
78  while ( fit.nextFeature( f ) )
79  {
80  renderContext.expressionContext().setFeature( f );
81 
82  const QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
83  for ( const QString &key : featureKeyList )
84  {
85  mSymbolFeatureCountMap[key] += 1;
86  if ( mWithFids )
87  mSymbolFeatureIdMap[key].insert( f.id() );
88  }
89  ++featuresCounted;
90 
91  const double p = ( static_cast< double >( featuresCounted ) / mFeatureCount ) * 100;
92  if ( p - progress > 1 )
93  {
94  progress = p;
96  }
97 
98  if ( isCanceled() )
99  {
100  mRenderer->stopRender( renderContext );
101  mExpressionContext.setFeedback( nullptr );
102  mFeedback.reset();
103  return false;
104  }
105  }
106  mRenderer->stopRender( renderContext );
107  mExpressionContext.setFeedback( nullptr );
108  mFeedback.reset();
109  }
110  setProgress( 100 );
111  emit symbolsCounted();
112  return true;
113 }
114 
116 {
117  if ( mFeedback )
118  mFeedback->cancel();
119  QgsTask::cancel();
120 }
121 
123 {
124  return mSymbolFeatureCountMap;
125 }
126 
127 long long QgsVectorLayerFeatureCounter::featureCount( const QString &legendKey ) const
128 {
129  return mSymbolFeatureCountMap.value( legendKey, -1 );
130 }
131 
132 QHash<QString, QgsFeatureIds> QgsVectorLayerFeatureCounter::symbolFeatureIdMap() const
133 {
134  return mSymbolFeatureIdMap;
135 }
136 
138 {
139  return mSymbolFeatureIdMap.value( symbolkey, QgsFeatureIds() );
140 }
QgsFeatureRequest::NoGeometry
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition: qgsfeaturerequest.h:115
QgsExpressionContext
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Definition: qgsexpressioncontext.h:406
QgsRenderContext::expressionContext
QgsExpressionContext & expressionContext()
Gets the expression context.
Definition: qgsrendercontext.h:625
QgsVectorLayerFeatureCounter::symbolFeatureIdMap
QHash< QString, QgsFeatureIds > symbolFeatureIdMap() const
Returns the QgsFeatureIds for each symbol.
Definition: qgsvectorlayerfeaturecounter.cpp:132
QgsVectorLayerFeatureCounter::featureCount
long long featureCount(const QString &legendKey) const
Returns the feature count for a particular legendKey.
Definition: qgsvectorlayerfeaturecounter.cpp:127
QgsRenderContext
Contains information about the context of a rendering operation.
Definition: qgsrendercontext.h:59
qgsfeatureid.h
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
qgsvectorlayerfeaturecounter.h
QgsVectorLayerFeatureCounter::featureIds
QgsFeatureIds featureIds(const QString &symbolkey) const
Returns the feature Ids for a particular legendKey.
Definition: qgsvectorlayerfeaturecounter.cpp:137
QgsExpressionContext::setFeedback
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the expression engine to check if expressio...
Definition: qgsexpressioncontext.cpp:629
QgsExpressionContext::scopeCount
int scopeCount() const
Returns the number of scopes contained in the context.
Definition: qgsexpressioncontext.cpp:489
QgsTask::cancel
virtual void cancel()
Notifies the task that it should terminate.
Definition: qgstaskmanager.cpp:91
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
QgsTask::setProgress
void setProgress(double progress)
Sets the task's current progress.
Definition: qgstaskmanager.cpp:232
qgsrendercontext.h
QgsFeatureRequest::setFeedback
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
Definition: qgsfeaturerequest.cpp:402
QgsFeatureIds
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
QgsVectorLayerFeatureCounter::~QgsVectorLayerFeatureCounter
~QgsVectorLayerFeatureCounter() override
QgsVectorLayerFeatureCounter::symbolFeatureCountMap
QHash< QString, long long > symbolFeatureCountMap() const
Returns the count for each symbol.
Definition: qgsvectorlayerfeaturecounter.cpp:122
QgsRenderContext::setRendererScale
void setRendererScale(double scale)
Sets the renderer map scale.
Definition: qgsrendercontext.h:487
qgsvectorlayer.h
QgsVectorLayerFeatureCounter::run
bool run() override
Calculates the feature count and Ids per symbol.
Definition: qgsvectorlayerfeaturecounter.cpp:38
QgsVectorLayerFeatureCounter::cancel
void cancel() override
Notifies the task that it should terminate.
Definition: qgsvectorlayerfeaturecounter.cpp:115
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsVectorLayerFeatureSource
Partial snapshot of vector layer's state (only the members necessary for access to features)
Definition: qgsvectorlayerfeatureiterator.h:52
QgsVectorLayerFeatureCounter::QgsVectorLayerFeatureCounter
QgsVectorLayerFeatureCounter(QgsVectorLayer *layer, const QgsExpressionContext &context=QgsExpressionContext(), bool storeSymbolFids=false)
Create a new feature counter for layer.
Definition: qgsvectorlayerfeaturecounter.cpp:22
QgsVectorLayerFeatureCounter::symbolsCounted
void symbolsCounted()
Emitted when the symbols have been counted.
QgsRenderContext::setExpressionContext
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
Definition: qgsrendercontext.h:617
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsVectorLayer::createExpressionContext
QgsExpressionContext createExpressionContext() const FINAL
This method needs to be reimplemented in all classes which implement this interface and return an exp...
Definition: qgsvectorlayer.cpp:5203
QgsLegendSymbolList
QList< QgsLegendSymbolItem > QgsLegendSymbolList
Definition: qgslegendsymbolitem.h:144
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
qgsfeedback.h
QgsFeatureRequest::setFlags
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched.
Definition: qgsfeaturerequest.cpp:222
QgsTask::progress
double progress() const
Returns the task's progress (between 0.0 and 100.0)
Definition: qgstaskmanager.h:127
QgsExpressionContext::setFeature
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Definition: qgsexpressioncontext.cpp:525
QgsTask::isCanceled
bool isCanceled() const
Will return true if task should terminate ASAP.
Definition: qgstaskmanager.cpp:118
QgsTask
Abstract base class for long running background tasks. Tasks can be controlled directly,...
Definition: qgstaskmanager.h:54