Branch data Line data Source code
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 : : 16 : : #include "qgsvectorlayerfeaturecounter.h" 17 : : #include "qgsvectorlayer.h" 18 : : #include "qgsfeatureid.h" 19 : : 20 : 0 : QgsVectorLayerFeatureCounter::QgsVectorLayerFeatureCounter( QgsVectorLayer *layer, const QgsExpressionContext &context, bool storeSymbolFids ) 21 : 0 : : QgsTask( tr( "Counting features in %1" ).arg( layer->name() ), QgsTask::CanCancel ) 22 : 0 : , mSource( new QgsVectorLayerFeatureSource( layer ) ) 23 : 0 : , mRenderer( layer->renderer()->clone() ) 24 : 0 : , mExpressionContext( context ) 25 : 0 : , mWithFids( storeSymbolFids ) 26 : 0 : , mFeatureCount( layer->featureCount() ) 27 : 0 : { 28 : 0 : if ( !mExpressionContext.scopeCount() ) 29 : : { 30 : 0 : mExpressionContext = layer->createExpressionContext(); 31 : 0 : } 32 : 0 : } 33 : : 34 : 0 : bool QgsVectorLayerFeatureCounter::run() 35 : : { 36 : 0 : mSymbolFeatureCountMap.clear(); 37 : 0 : mSymbolFeatureIdMap.clear(); 38 : 0 : QgsLegendSymbolList symbolList = mRenderer->legendSymbolItems(); 39 : 0 : QgsLegendSymbolList::const_iterator symbolIt = symbolList.constBegin(); 40 : : 41 : 0 : for ( ; symbolIt != symbolList.constEnd(); ++symbolIt ) 42 : : { 43 : 0 : mSymbolFeatureCountMap.insert( symbolIt->ruleKey(), 0 ); 44 : 0 : if ( mWithFids ) 45 : 0 : mSymbolFeatureIdMap.insert( symbolIt->ruleKey(), QgsFeatureIds() ); 46 : 0 : } 47 : : 48 : : // If there are no features to be counted, we can spare us the trouble 49 : 0 : if ( mFeatureCount > 0 ) 50 : : { 51 : 0 : int featuresCounted = 0; 52 : : 53 : : // Renderer (rule based) may depend on context scale, with scale is ignored if 0 54 : 0 : QgsRenderContext renderContext; 55 : 0 : renderContext.setRendererScale( 0 ); 56 : 0 : renderContext.setExpressionContext( mExpressionContext ); 57 : : 58 : 0 : QgsFeatureRequest request; 59 : 0 : if ( !mRenderer->filterNeedsGeometry() ) 60 : 0 : request.setFlags( QgsFeatureRequest::NoGeometry ); 61 : 0 : request.setSubsetOfAttributes( mRenderer->usedAttributes( renderContext ), mSource->fields() ); 62 : 0 : QgsFeatureIterator fit = mSource->getFeatures( request ); 63 : : 64 : : // TODO: replace QgsInterruptionChecker with QgsFeedback 65 : : // fit.setInterruptionChecker( mFeedback ); 66 : : 67 : 0 : mRenderer->startRender( renderContext, mSource->fields() ); 68 : : 69 : 0 : double progress = 0; 70 : 0 : QgsFeature f; 71 : 0 : while ( fit.nextFeature( f ) ) 72 : : { 73 : 0 : renderContext.expressionContext().setFeature( f ); 74 : : 75 : 0 : const QSet<QString> featureKeyList = mRenderer->legendKeysForFeature( f, renderContext ); 76 : 0 : for ( const QString &key : featureKeyList ) 77 : : { 78 : 0 : mSymbolFeatureCountMap[key] += 1; 79 : 0 : if ( mWithFids ) 80 : 0 : mSymbolFeatureIdMap[key].insert( f.id() ); 81 : : } 82 : 0 : ++featuresCounted; 83 : : 84 : 0 : double p = ( static_cast< double >( featuresCounted ) / mFeatureCount ) * 100; 85 : 0 : if ( p - progress > 1 ) 86 : : { 87 : 0 : progress = p; 88 : 0 : setProgress( progress ); 89 : 0 : } 90 : : 91 : 0 : if ( isCanceled() ) 92 : : { 93 : 0 : mRenderer->stopRender( renderContext ); 94 : 0 : return false; 95 : : } 96 : 0 : } 97 : 0 : mRenderer->stopRender( renderContext ); 98 : 0 : } 99 : 0 : setProgress( 100 ); 100 : 0 : emit symbolsCounted(); 101 : 0 : return true; 102 : 0 : } 103 : : 104 : 0 : QHash<QString, long> QgsVectorLayerFeatureCounter::symbolFeatureCountMap() const 105 : : { 106 : 0 : return mSymbolFeatureCountMap; 107 : : } 108 : : 109 : 0 : long QgsVectorLayerFeatureCounter::featureCount( const QString &legendKey ) const 110 : : { 111 : 0 : return mSymbolFeatureCountMap.value( legendKey, -1 ); 112 : : } 113 : : 114 : 0 : QHash<QString, QgsFeatureIds> QgsVectorLayerFeatureCounter::symbolFeatureIdMap() const 115 : : { 116 : 0 : return mSymbolFeatureIdMap; 117 : : } 118 : : 119 : 0 : QgsFeatureIds QgsVectorLayerFeatureCounter::featureIds( const QString &symbolkey ) const 120 : : { 121 : 0 : return mSymbolFeatureIdMap.value( symbolkey, QgsFeatureIds() ); 122 : 0 : }