QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
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
18#include "qgsfeatureid.h"
19#include "qgsfeedback.h"
20#include "qgsrendercontext.h"
21#include "qgsvectorlayer.h"
22
23#include "moc_qgsvectorlayerfeaturecounter.cpp"
24
26 : QgsTask( tr( "Counting features in %1" ).arg( layer->name() ), QgsTask::CanCancel | QgsTask::CancelWithoutPrompt | QgsTask::Silent )
27 , mSource( new QgsVectorLayerFeatureSource( layer ) )
28 , mRenderer( layer->renderer()->clone() )
29 , mExpressionContext( context )
30 , mWithFids( storeSymbolFids )
31 , mFeatureCount( layer->featureCount() )
32{
33 if ( !mExpressionContext.scopeCount() )
34 {
35 mExpressionContext = layer->createExpressionContext();
36 }
37}
38
40
42{
43 mSymbolFeatureCountMap.clear();
44 mSymbolFeatureIdMap.clear();
45 const QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems();
46 QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
47
48 for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
49 {
50 mSymbolFeatureCountMap.insert( symbolIt->ruleKey(), 0 );
51 if ( mWithFids )
52 mSymbolFeatureIdMap.insert( symbolIt->ruleKey(), QgsFeatureIds() );
53 }
54
55 // If there are no features to be counted, we can spare us the trouble
56 if ( mFeatureCount > 0 )
57 {
58 mFeedback = std::make_unique< QgsFeedback >();
59
60 int featuresCounted = 0;
61
62 // Renderer (rule based) may depend on context scale, with scale is ignored if 0
63 QgsRenderContext renderContext;
64 renderContext.setRendererScale( 0 );
65 renderContext.setExpressionContext( mExpressionContext );
66
67 QgsFeatureRequest request;
68 if ( !mRenderer->filterNeedsGeometry() )
70 request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mSource->fields() );
71
72 request.setFeedback( mFeedback.get() );
73 mExpressionContext.setFeedback( mFeedback.get() );
74
75 QgsFeatureIterator fit = mSource->getFeatures( request );
76
77 mRenderer->startRender( renderContext, mSource->fields() );
78
79 double progress = 0;
80 QgsFeature f;
81 while ( fit.nextFeature( f ) )
82 {
83 renderContext.expressionContext().setFeature( f );
84
85 const QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
86 for ( const QString &key : featureKeyList )
87 {
88 mSymbolFeatureCountMap[key] += 1;
89 if ( mWithFids )
90 mSymbolFeatureIdMap[key].insert( f.id() );
91 }
92 ++featuresCounted;
93
94 const double p = ( static_cast< double >( featuresCounted ) / mFeatureCount ) * 100;
95 if ( p - progress > 1 )
96 {
97 progress = p;
99 }
100
101 if ( isCanceled() )
102 {
103 mRenderer->stopRender( renderContext );
104 mExpressionContext.setFeedback( nullptr );
105 mFeedback.reset();
106 return false;
107 }
108 }
109 mRenderer->stopRender( renderContext );
110 mExpressionContext.setFeedback( nullptr );
111 mFeedback.reset();
112 }
113 setProgress( 100 );
114 emit symbolsCounted();
115 return true;
116}
117
119{
120 if ( mFeedback )
121 mFeedback->cancel();
123}
124
126{
127 return mSymbolFeatureCountMap;
128}
129
130long long QgsVectorLayerFeatureCounter::featureCount( const QString &legendKey ) const
131{
132 return mSymbolFeatureCountMap.value( legendKey, -1 );
133}
134
135QHash<QString, QgsFeatureIds> QgsVectorLayerFeatureCounter::symbolFeatureIdMap() const
136{
137 return mSymbolFeatureIdMap;
138}
139
141{
142 return mSymbolFeatureIdMap.value( symbolkey, QgsFeatureIds() );
143}
@ NoGeometry
Geometry is not required. It may still be returned if e.g. required for a filter condition.
Definition qgis.h:2196
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFlags(Qgis::FeatureRequestFlags flags)
Sets flags that affect how features will be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
void setFeedback(QgsFeedback *feedback)
Attach a feedback object that can be queried regularly by the iterator to check if it should be cance...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsFeatureId id
Definition qgsfeature.h:66
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
double progress() const
Returns the task's progress (between 0.0 and 100.0).
virtual void cancel()
Notifies the task that it should terminate.
QgsTask(const QString &description=QString(), QgsTask::Flags flags=AllFlags)
Constructor for QgsTask.
@ CanCancel
Task can be canceled.
@ CancelWithoutPrompt
Task can be canceled without any users prompts, e.g. when closing a project or QGIS.
@ Silent
Don't show task updates (such as completion/failure messages) as operating-system level notifications...
bool isCanceled() const
Will return true if task should terminate ASAP.
void setProgress(double progress)
Sets the task's current progress.
void symbolsCounted()
Emitted when the symbols have been counted.
~QgsVectorLayerFeatureCounter() override
QgsVectorLayerFeatureCounter(QgsVectorLayer *layer, const QgsExpressionContext &context=QgsExpressionContext(), bool storeSymbolFids=false)
Create a new feature counter for layer.
bool run() override
Calculates the feature count and Ids per symbol.
QHash< QString, long long > symbolFeatureCountMap() const
Returns the count for each symbol.
void cancel() override
Notifies the task that it should terminate.
long long featureCount(const QString &legendKey) const
Returns the feature count for a particular legendKey.
QgsFeatureIds featureIds(const QString &symbolkey) const
Returns the feature Ids for a particular legendKey.
QHash< QString, QgsFeatureIds > symbolFeatureIdMap() const
Returns the QgsFeatureIds for each symbol.
Partial snapshot of vector layer's state (only the members necessary for access to features).
Represents a vector layer which manages a vector based dataset.
QSet< QgsFeatureId > QgsFeatureIds
QList< QgsLegendSymbolItem > QgsLegendSymbolList