@@ -697,6 +697,44 @@ long QgsVectorLayer::featureCount( QgsSymbolV2* symbol )
697
697
return mSymbolFeatureCountMap .value ( symbol );
698
698
}
699
699
700
+ /* * Used by QgsVectorLayer::countSymbolFeatures() to provide an interruption checker
701
+ * @note not available in Python bindings
702
+ */
703
+ class QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures : public QgsInterruptionChecker
704
+ {
705
+ public:
706
+
707
+ /* * Constructor */
708
+ QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures ( QProgressDialog* dialog )
709
+ : mDialog ( dialog )
710
+ {
711
+ }
712
+
713
+ virtual bool mustStop () const
714
+ {
715
+ if ( mDialog ->isVisible () )
716
+ {
717
+ // So that we get a chance of hitting the Abort button
718
+ #ifdef Q_OS_LINUX
719
+ // For some reason on Windows hasPendingEvents() always return true,
720
+ // but one iteration is actually enough on Windows to get good interactivity
721
+ // whereas on Linux we must allow for far more iterations.
722
+ // For safety limit the number of iterations
723
+ int nIters = 0 ;
724
+ while ( QCoreApplication::hasPendingEvents () && ++nIters < 100 )
725
+ #endif
726
+ {
727
+ QCoreApplication::processEvents ();
728
+ }
729
+ return mDialog ->wasCanceled ();
730
+ }
731
+ return false ;
732
+ }
733
+
734
+ private:
735
+ QProgressDialog* mDialog ;
736
+ };
737
+
700
738
bool QgsVectorLayer::countSymbolFeatures ( bool showProgress )
701
739
{
702
740
if ( mSymbolFeatureCounted )
@@ -729,12 +767,34 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
729
767
}
730
768
731
769
long nFeatures = featureCount ();
732
- QProgressDialog progressDialog ( tr ( " Updating feature count for layer %1" ).arg ( name () ), tr ( " Abort" ), 0 , nFeatures );
770
+
771
+ QWidget* mainWindow = nullptr ;
772
+ Q_FOREACH ( QWidget* widget, qApp->topLevelWidgets () )
773
+ {
774
+ if ( widget->objectName () == " QgisApp" )
775
+ {
776
+ mainWindow = widget;
777
+ break ;
778
+ }
779
+ }
780
+
781
+ QProgressDialog progressDialog ( tr ( " Updating feature count for layer %1" ).arg ( name () ), tr ( " Abort" ), 0 , nFeatures, mainWindow );
733
782
progressDialog.setWindowTitle ( tr ( " QGIS" ) );
734
783
progressDialog.setWindowModality ( Qt::WindowModal );
784
+ if ( showProgress )
785
+ {
786
+ // Properly initialize to 0 as recommended in doc so that the evaluation
787
+ // of the total time properly works
788
+ progressDialog.setValue ( 0 );
789
+ }
735
790
int featuresCounted = 0 ;
736
791
737
792
QgsFeatureIterator fit = getFeatures ( QgsFeatureRequest ().setFlags ( QgsFeatureRequest::NoGeometry ) );
793
+ QgsVectorLayerInterruptionCheckerDuringCountSymbolFeatures interruptionCheck ( &progressDialog );
794
+ if ( showProgress )
795
+ {
796
+ fit.setInterruptionChecker ( &interruptionCheck );
797
+ }
738
798
739
799
// Renderer (rule based) may depend on context scale, with scale is ignored if 0
740
800
QgsRenderContext renderContext;
@@ -746,6 +806,8 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
746
806
mRendererV2 ->startRender ( renderContext, fields () );
747
807
748
808
QgsFeature f;
809
+ QTime time ;
810
+ time .start ();
749
811
while ( fit.nextFeature ( f ) )
750
812
{
751
813
renderContext.expressionContext ().setFeature ( f );
@@ -758,19 +820,33 @@ bool QgsVectorLayer::countSymbolFeatures( bool showProgress )
758
820
759
821
if ( showProgress )
760
822
{
761
- if ( featuresCounted % 50 == 0 )
823
+ // Refresh progress every 50 features or second
824
+ if (( featuresCounted % 50 == 0 ) || time .elapsed () > 1000 )
762
825
{
826
+ time .restart ();
763
827
if ( featuresCounted > nFeatures ) // sometimes the feature count is not correct
764
828
{
765
829
progressDialog.setMaximum ( 0 );
766
830
}
767
831
progressDialog.setValue ( featuresCounted );
768
- if ( progressDialog.wasCanceled () )
769
- {
770
- mSymbolFeatureCountMap .clear ();
771
- mRendererV2 ->stopRender ( renderContext );
772
- return false ;
773
- }
832
+ }
833
+ // So that we get a chance of hitting the Abort button
834
+ #ifdef Q_OS_LINUX
835
+ // For some reason on Windows hasPendingEvents() always return true,
836
+ // but one iteration is actually enough on Windows to get good interactivity
837
+ // whereas on Linux we must allow for far more iterations.
838
+ // For safety limit the number of iterations
839
+ int nIters = 0 ;
840
+ while ( QCoreApplication::hasPendingEvents () && ++nIters < 100 )
841
+ #endif
842
+ {
843
+ QCoreApplication::processEvents ();
844
+ }
845
+ if ( progressDialog.wasCanceled () )
846
+ {
847
+ mSymbolFeatureCountMap .clear ();
848
+ mRendererV2 ->stopRender ( renderContext );
849
+ return false ;
774
850
}
775
851
}
776
852
}
0 commit comments