mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
Send feature counting to background task
This commit is contained in:
parent
f264370130
commit
964d9ac70a
@ -165,6 +165,7 @@
|
|||||||
%Include qgsvectorlayercache.sip
|
%Include qgsvectorlayercache.sip
|
||||||
%Include qgsvectorlayereditbuffer.sip
|
%Include qgsvectorlayereditbuffer.sip
|
||||||
%Include qgsvectorlayereditpassthrough.sip
|
%Include qgsvectorlayereditpassthrough.sip
|
||||||
|
%Include qgsvectorlayerfeaturecounter.sip
|
||||||
%Include qgsvectorlayerimport.sip
|
%Include qgsvectorlayerimport.sip
|
||||||
%Include qgsvectorlayerjoinbuffer.sip
|
%Include qgsvectorlayerjoinbuffer.sip
|
||||||
%Include qgsvectorlayerjoininfo.sip
|
%Include qgsvectorlayerjoininfo.sip
|
||||||
|
@ -841,7 +841,7 @@ Return the provider type for this layer
|
|||||||
.. versionadded:: 2.10
|
.. versionadded:: 2.10
|
||||||
%End
|
%End
|
||||||
|
|
||||||
bool countSymbolFeatures( bool showProgress = true );
|
bool countSymbolFeatures();
|
||||||
%Docstring
|
%Docstring
|
||||||
Count features for symbols. Feature counts may be get by featureCount().
|
Count features for symbols. Feature counts may be get by featureCount().
|
||||||
\param showProgress show progress dialog
|
\param showProgress show progress dialog
|
||||||
@ -2000,6 +2000,12 @@ Signal emitted when setLayerTransparency() is called
|
|||||||
.. versionadded:: 3.0
|
.. versionadded:: 3.0
|
||||||
%End
|
%End
|
||||||
|
|
||||||
|
void symbolFeatureCountMapChanged();
|
||||||
|
%Docstring
|
||||||
|
Emitted when the feature count for symbols on this layer has been recalculated.
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
%End
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void setExtent( const QgsRectangle &rect );
|
virtual void setExtent( const QgsRectangle &rect );
|
||||||
|
45
python/core/qgsvectorlayerfeaturecounter.sip
Normal file
45
python/core/qgsvectorlayerfeaturecounter.sip
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgsvectorlayerfeaturecounter.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
class QgsVectorLayerFeatureCounter : QgsTask
|
||||||
|
{
|
||||||
|
%Docstring
|
||||||
|
|
||||||
|
Counts the features in a QgsVectorLayer in task.
|
||||||
|
You should most likely not use this directly and instead call
|
||||||
|
QgsVectorLayer.countSymbolFeatures() and connect to the signal
|
||||||
|
QgsVectorLayer.symbolFeatureCountMapChanged().
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgsvectorlayerfeaturecounter.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
QgsVectorLayerFeatureCounter( QgsVectorLayer *layer );
|
||||||
|
%Docstring
|
||||||
|
Create a new feature counter for ``layer``.
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual bool run();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void symbolsCounted( const QHash<QString, long> &symbolFeatureCountMap );
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/core/qgsvectorlayerfeaturecounter.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -263,6 +263,7 @@ SET(QGIS_CORE_SRCS
|
|||||||
qgsvectorfilewriter.cpp
|
qgsvectorfilewriter.cpp
|
||||||
qgsvectorfilewritertask.cpp
|
qgsvectorfilewritertask.cpp
|
||||||
qgsvectorlayer.cpp
|
qgsvectorlayer.cpp
|
||||||
|
qgsvectorlayerfeaturecounter.cpp
|
||||||
qgsvectorlayercache.cpp
|
qgsvectorlayercache.cpp
|
||||||
qgsvectorlayerdiagramprovider.cpp
|
qgsvectorlayerdiagramprovider.cpp
|
||||||
qgsvectorlayereditbuffer.cpp
|
qgsvectorlayereditbuffer.cpp
|
||||||
@ -569,6 +570,7 @@ SET(QGIS_CORE_MOC_HDRS
|
|||||||
qgsvectorlayereditbuffer.h
|
qgsvectorlayereditbuffer.h
|
||||||
qgsvectorlayereditpassthrough.h
|
qgsvectorlayereditpassthrough.h
|
||||||
qgsvectorlayer.h
|
qgsvectorlayer.h
|
||||||
|
qgsvectorlayerfeaturecounter.h
|
||||||
qgsvectorlayerjoinbuffer.h
|
qgsvectorlayerjoinbuffer.h
|
||||||
qgsvectorlayertools.h
|
qgsvectorlayertools.h
|
||||||
qgsmapthemecollection.h
|
qgsmapthemecollection.h
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
#include "qgsvectorlayerlabeling.h"
|
#include "qgsvectorlayerlabeling.h"
|
||||||
#include "qgsvectorlayerrenderer.h"
|
#include "qgsvectorlayerrenderer.h"
|
||||||
#include "qgsvectorlayerundocommand.h"
|
#include "qgsvectorlayerundocommand.h"
|
||||||
|
#include "qgsvectorlayerfeaturecounter.h"
|
||||||
#include "qgspointv2.h"
|
#include "qgspointv2.h"
|
||||||
#include "qgsrenderer.h"
|
#include "qgsrenderer.h"
|
||||||
#include "qgssymbollayer.h"
|
#include "qgssymbollayer.h"
|
||||||
@ -83,6 +84,7 @@
|
|||||||
#include "qgsfeedback.h"
|
#include "qgsfeedback.h"
|
||||||
#include "qgsxmlutils.h"
|
#include "qgsxmlutils.h"
|
||||||
#include "qgsunittypes.h"
|
#include "qgsunittypes.h"
|
||||||
|
#include "qgstaskmanager.h"
|
||||||
|
|
||||||
#include "diagram/qgsdiagram.h"
|
#include "diagram/qgsdiagram.h"
|
||||||
|
|
||||||
@ -126,6 +128,7 @@ typedef bool deleteStyleById_t(
|
|||||||
QString &errCause
|
QString &errCause
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
|
QgsVectorLayer::QgsVectorLayer( const QString &vectorLayerPath,
|
||||||
const QString &baseName,
|
const QString &baseName,
|
||||||
const QString &providerKey,
|
const QString &providerKey,
|
||||||
@ -674,7 +677,7 @@ class QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures: public QgsInte
|
|||||||
QProgressDialog *mDialog = nullptr;
|
QProgressDialog *mDialog = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
|
bool QgsVectorLayer::countSymbolFeatures()
|
||||||
{
|
{
|
||||||
if ( mSymbolFeatureCounted )
|
if ( mSymbolFeatureCounted )
|
||||||
return true;
|
return true;
|
||||||
@ -697,103 +700,16 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems();
|
if ( !mFeatureCounter )
|
||||||
QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
|
|
||||||
|
|
||||||
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
|
|
||||||
{
|
{
|
||||||
mSymbolFeatureCountMap.insert( symbolIt->first, 0 );
|
mFeatureCounter.reset( new QgsVectorLayerFeatureCounter( this ) );
|
||||||
|
connect( mFeatureCounter.get(), &QgsVectorLayerFeatureCounter::symbolsCounted, this, &QgsVectorLayer::onSymbolsCounted );
|
||||||
|
connect( mFeatureCounter.get(), &QgsTask::taskCompleted, [ = ]() { mFeatureCounter.reset(); } );
|
||||||
|
connect( mFeatureCounter.get(), &QgsTask::taskTerminated, [ = ]() { mFeatureCounter.reset(); } );
|
||||||
|
|
||||||
|
QgsApplication::taskManager()->addTask( mFeatureCounter.get() );
|
||||||
}
|
}
|
||||||
|
|
||||||
long nFeatures = featureCount();
|
|
||||||
|
|
||||||
QWidget *mainWindow = nullptr;
|
|
||||||
Q_FOREACH ( QWidget *widget, qApp->topLevelWidgets() )
|
|
||||||
{
|
|
||||||
if ( widget->objectName() == QLatin1String( "QgisApp" ) )
|
|
||||||
{
|
|
||||||
mainWindow = widget;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QProgressDialog progressDialog( tr( "Updating feature count for layer %1" ).arg( name() ), tr( "Abort" ), 0, nFeatures, mainWindow );
|
|
||||||
progressDialog.setWindowTitle( tr( "QGIS" ) );
|
|
||||||
progressDialog.setWindowModality( Qt::WindowModal );
|
|
||||||
if ( showProgress )
|
|
||||||
{
|
|
||||||
// Properly initialize to 0 as recommended in doc so that the evaluation
|
|
||||||
// of the total time properly works
|
|
||||||
progressDialog.setValue( 0 );
|
|
||||||
}
|
|
||||||
int featuresCounted = 0;
|
|
||||||
|
|
||||||
// Renderer (rule based) may depend on context scale, with scale is ignored if 0
|
|
||||||
QgsRenderContext renderContext;
|
|
||||||
renderContext.setRendererScale( 0 );
|
|
||||||
renderContext.expressionContext().appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( this ) );
|
|
||||||
|
|
||||||
QgsFeatureRequest request;
|
|
||||||
if ( !mRenderer->filterNeedsGeometry() )
|
|
||||||
request.setFlags( QgsFeatureRequest::NoGeometry );
|
|
||||||
request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mFields );
|
|
||||||
QgsFeatureIterator fit = getFeatures( request );
|
|
||||||
QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures interruptionCheck( &progressDialog );
|
|
||||||
if ( showProgress )
|
|
||||||
{
|
|
||||||
fit.setInterruptionChecker( &interruptionCheck );
|
|
||||||
}
|
|
||||||
|
|
||||||
mRenderer->startRender( renderContext, fields() );
|
|
||||||
|
|
||||||
QgsFeature f;
|
|
||||||
QTime time;
|
|
||||||
time.start();
|
|
||||||
while ( fit.nextFeature( f ) )
|
|
||||||
{
|
|
||||||
renderContext.expressionContext().setFeature( f );
|
|
||||||
QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
|
|
||||||
Q_FOREACH ( const QString &key, featureKeyList )
|
|
||||||
{
|
|
||||||
mSymbolFeatureCountMap[key] += 1;
|
|
||||||
}
|
|
||||||
++featuresCounted;
|
|
||||||
|
|
||||||
if ( showProgress )
|
|
||||||
{
|
|
||||||
// Refresh progress every 50 features or second
|
|
||||||
if ( ( featuresCounted % 50 == 0 ) || time.elapsed() > 1000 )
|
|
||||||
{
|
|
||||||
time.restart();
|
|
||||||
if ( featuresCounted > nFeatures ) //sometimes the feature count is not correct
|
|
||||||
{
|
|
||||||
progressDialog.setMaximum( 0 );
|
|
||||||
}
|
|
||||||
progressDialog.setValue( featuresCounted );
|
|
||||||
}
|
|
||||||
// So that we get a chance of hitting the Abort button
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
// For some reason on Windows hasPendingEvents() always return true,
|
|
||||||
// but one iteration is actually enough on Windows to get good interactivity
|
|
||||||
// whereas on Linux we must allow for far more iterations.
|
|
||||||
// For safety limit the number of iterations
|
|
||||||
int nIters = 0;
|
|
||||||
while ( QCoreApplication::hasPendingEvents() && ++nIters < 100 )
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
if ( progressDialog.wasCanceled() )
|
|
||||||
{
|
|
||||||
mSymbolFeatureCountMap.clear();
|
|
||||||
mRenderer->stopRender( renderContext );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mRenderer->stopRender( renderContext );
|
|
||||||
progressDialog.setValue( nFeatures );
|
|
||||||
mSymbolFeatureCounted = true;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3983,6 +3899,13 @@ void QgsVectorLayer::onRelationsLoaded()
|
|||||||
mEditFormConfig.onRelationsLoaded();
|
mEditFormConfig.onRelationsLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayer::onSymbolsCounted( const QHash<QString, long> &symbolFeatureCountMap )
|
||||||
|
{
|
||||||
|
mSymbolFeatureCountMap = symbolFeatureCountMap;
|
||||||
|
mSymbolFeatureCounted = true;
|
||||||
|
emit symbolFeatureCountMapChanged();
|
||||||
|
}
|
||||||
|
|
||||||
QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
|
QList<QgsRelation> QgsVectorLayer::referencingRelations( int idx ) const
|
||||||
{
|
{
|
||||||
return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
|
return QgsProject::instance()->relationManager()->referencingRelations( this, idx );
|
||||||
|
@ -65,6 +65,7 @@ class QgsSymbol;
|
|||||||
class QgsVectorLayerJoinInfo;
|
class QgsVectorLayerJoinInfo;
|
||||||
class QgsVectorLayerEditBuffer;
|
class QgsVectorLayerEditBuffer;
|
||||||
class QgsVectorLayerJoinBuffer;
|
class QgsVectorLayerJoinBuffer;
|
||||||
|
class QgsVectorLayerFeatureCounter;
|
||||||
class QgsAbstractVectorLayerLabeling;
|
class QgsAbstractVectorLayerLabeling;
|
||||||
class QgsPointV2;
|
class QgsPointV2;
|
||||||
class QgsFeedback;
|
class QgsFeedback;
|
||||||
@ -810,7 +811,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
|||||||
* \param showProgress show progress dialog
|
* \param showProgress show progress dialog
|
||||||
* \returns true if calculated, false if failed or was canceled by user
|
* \returns true if calculated, false if failed or was canceled by user
|
||||||
*/
|
*/
|
||||||
bool countSymbolFeatures( bool showProgress = true );
|
bool countSymbolFeatures();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the string (typically sql) used to define a subset of the layer
|
* Set the string (typically sql) used to define a subset of the layer
|
||||||
@ -1846,11 +1847,18 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
|||||||
*/
|
*/
|
||||||
void readOnlyChanged();
|
void readOnlyChanged();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emitted when the feature count for symbols on this layer has been recalculated.
|
||||||
|
*
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
|
void symbolFeatureCountMapChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onJoinedFieldsChanged();
|
void onJoinedFieldsChanged();
|
||||||
void onFeatureDeleted( QgsFeatureId fid );
|
void onFeatureDeleted( QgsFeatureId fid );
|
||||||
void onRelationsLoaded();
|
void onRelationsLoaded();
|
||||||
|
void onSymbolsCounted( const QHash<QString, long> &symbolFeatureCountMap );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Set the extent
|
//! Set the extent
|
||||||
@ -1883,7 +1891,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private: // Private attributes
|
private: // Private attributes
|
||||||
|
|
||||||
QgsConditionalLayerStyles *mConditionalStyles = nullptr;
|
QgsConditionalLayerStyles *mConditionalStyles = nullptr;
|
||||||
|
|
||||||
//! Pointer to data provider derived from the abastract base class QgsDataProvider
|
//! Pointer to data provider derived from the abastract base class QgsDataProvider
|
||||||
@ -2001,6 +2008,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
|||||||
|
|
||||||
mutable QMutex mFeatureSourceConstructorMutex;
|
mutable QMutex mFeatureSourceConstructorMutex;
|
||||||
|
|
||||||
|
std::unique_ptr<QgsVectorLayerFeatureCounter> mFeatureCounter;
|
||||||
|
|
||||||
friend class QgsVectorLayerFeatureSource;
|
friend class QgsVectorLayerFeatureSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
69
src/core/qgsvectorlayerfeaturecounter.cpp
Normal file
69
src/core/qgsvectorlayerfeaturecounter.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#include "qgsvectorlayerfeaturecounter.h"
|
||||||
|
|
||||||
|
QgsVectorLayerFeatureCounter::QgsVectorLayerFeatureCounter( QgsVectorLayer *layer )
|
||||||
|
: mSource( new QgsVectorLayerFeatureSource( layer ) )
|
||||||
|
, mRenderer( layer->renderer()->clone() )
|
||||||
|
, mExpressionContextScopes( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) )
|
||||||
|
, mFeatureCount( layer->featureCount() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsVectorLayerFeatureCounter::run()
|
||||||
|
{
|
||||||
|
QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems();
|
||||||
|
QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin();
|
||||||
|
|
||||||
|
for ( ; symbolIt != symbolList.constEnd(); ++symbolIt )
|
||||||
|
{
|
||||||
|
mSymbolFeatureCountMap.insert( symbolIt->first, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int featuresCounted = 0;
|
||||||
|
|
||||||
|
// Renderer (rule based) may depend on context scale, with scale is ignored if 0
|
||||||
|
QgsRenderContext renderContext;
|
||||||
|
renderContext.setRendererScale( 0 );
|
||||||
|
renderContext.expressionContext().appendScopes( mExpressionContextScopes );
|
||||||
|
|
||||||
|
QgsFeatureRequest request;
|
||||||
|
if ( !mRenderer->filterNeedsGeometry() )
|
||||||
|
request.setFlags( QgsFeatureRequest::NoGeometry );
|
||||||
|
request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mSource->fields() );
|
||||||
|
QgsFeatureIterator fit = mSource->getFeatures( request );
|
||||||
|
|
||||||
|
// TODO: replace QgsInterruptionChecker with QgsFeedback
|
||||||
|
// fit.setInterruptionChecker( mFeedback );
|
||||||
|
|
||||||
|
mRenderer->startRender( renderContext, mSource->fields() );
|
||||||
|
|
||||||
|
double progress = 0;
|
||||||
|
QgsFeature f;
|
||||||
|
while ( fit.nextFeature( f ) )
|
||||||
|
{
|
||||||
|
renderContext.expressionContext().setFeature( f );
|
||||||
|
QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext );
|
||||||
|
Q_FOREACH ( const QString &key, featureKeyList )
|
||||||
|
{
|
||||||
|
mSymbolFeatureCountMap[key] += 1;
|
||||||
|
}
|
||||||
|
++featuresCounted;
|
||||||
|
|
||||||
|
double p = ( featuresCounted / mFeatureCount ) * 100;
|
||||||
|
if ( p - progress > 1 )
|
||||||
|
{
|
||||||
|
progress = p;
|
||||||
|
setProgress( progress );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isCanceled() )
|
||||||
|
{
|
||||||
|
mRenderer->stopRender( renderContext );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mRenderer->stopRender( renderContext );
|
||||||
|
setProgress( 100 );
|
||||||
|
|
||||||
|
emit symbolsCounted( mSymbolFeatureCountMap );
|
||||||
|
return true;
|
||||||
|
}
|
43
src/core/qgsvectorlayerfeaturecounter.h
Normal file
43
src/core/qgsvectorlayerfeaturecounter.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef QGSVECTORLAYERFEATURECOUNTER_H
|
||||||
|
#define QGSVECTORLAYERFEATURECOUNTER_H
|
||||||
|
|
||||||
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsvectorlayerfeatureiterator.h"
|
||||||
|
#include "qgsrenderer.h"
|
||||||
|
#include "qgstaskmanager.h"
|
||||||
|
|
||||||
|
/** \ingroup core
|
||||||
|
*
|
||||||
|
* Counts the features in a QgsVectorLayer in task.
|
||||||
|
* You should most likely not use this directly and instead call
|
||||||
|
* QgsVectorLayer::countSymbolFeatures() and connect to the signal
|
||||||
|
* QgsVectorLayer::symbolFeatureCountMapChanged().
|
||||||
|
*
|
||||||
|
* \since QGIS 3.0
|
||||||
|
*/
|
||||||
|
class CORE_EXPORT QgsVectorLayerFeatureCounter : public QgsTask
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new feature counter for \a layer.
|
||||||
|
*/
|
||||||
|
QgsVectorLayerFeatureCounter( QgsVectorLayer *layer );
|
||||||
|
|
||||||
|
virtual bool run() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void symbolsCounted( const QHash<QString, long> &symbolFeatureCountMap );
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
|
||||||
|
std::unique_ptr<QgsFeatureRenderer> mRenderer;
|
||||||
|
QList<QgsExpressionContextScope *> mExpressionContextScopes;
|
||||||
|
QHash<QString, long> mSymbolFeatureCountMap;
|
||||||
|
int mFeatureCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QGSVECTORLAYERFEATURECOUNTER_H
|
Loading…
x
Reference in New Issue
Block a user