Skip to content

Commit

Permalink
update the stats gatherer to use qgstask
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Feb 7, 2018
1 parent 715677e commit 0885414
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 112 deletions.
81 changes: 38 additions & 43 deletions src/app/qgsstatisticalsummarydockwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ QgsStatisticalSummaryDockWidget::~QgsStatisticalSummaryDockWidget()
{
if ( mGatherer )
{
mGatherer->stop();
mGatherer->wait(); // mGatherer is deleted when wait completes
mGatherer->cancel();
}
}

Expand Down Expand Up @@ -148,43 +147,43 @@ void QgsStatisticalSummaryDockWidget::refreshStatistics()

if ( mGatherer )
{
mGatherer->stop();
mGatherer->wait();
mGatherer->cancel();
}

switch ( mFieldType )
bool ok;
QgsFeatureIterator fit = QgsVectorLayerUtils::getValuesIterator( mLayer, sourceFieldExp, ok, selectedOnly );
if ( ok )
{
case DataType::Numeric:
mGatherer = new QgsStatisticsValueGatherer( mLayer, sourceFieldExp, selectedOnly );
connect( mGatherer, &QgsStatisticsValueGatherer::gatheredValues, this, &QgsStatisticalSummaryDockWidget::updateNumericStatistics );
break;
case DataType::String:
mGatherer = new QgsStatisticsValueGatherer( mLayer, sourceFieldExp, selectedOnly );
connect( mGatherer, &QgsStatisticsValueGatherer::gatheredValues, this, &QgsStatisticalSummaryDockWidget::updateStringStatistics );
break;
case DataType::DateTime:
mGatherer = new QgsStatisticsValueGatherer( mLayer, sourceFieldExp, selectedOnly );
connect( mGatherer, &QgsStatisticsValueGatherer::gatheredValues, this, &QgsStatisticalSummaryDockWidget::updateDateTimeStatistics );
break;
default:
break;
int featureCount = selectedOnly ? mLayer->selectedFeatureCount() : mLayer->featureCount();
mGatherer = new QgsStatisticsValueGatherer( mLayer, fit, featureCount, sourceFieldExp );
switch ( mFieldType )
{
case DataType::Numeric:
connect( mGatherer, &QgsStatisticsValueGatherer::taskCompleted, this, &QgsStatisticalSummaryDockWidget::updateNumericStatistics );
break;
case DataType::String:
connect( mGatherer, &QgsStatisticsValueGatherer::taskCompleted, this, &QgsStatisticalSummaryDockWidget::updateStringStatistics );
break;
case DataType::DateTime:
connect( mGatherer, &QgsStatisticsValueGatherer::taskCompleted, this, &QgsStatisticalSummaryDockWidget::updateDateTimeStatistics );
break;
default:
break;
}
connect( mGatherer, &QgsStatisticsValueGatherer::progressChanged, mCalculatingProgressBar, &QProgressBar::setValue );
connect( mCancelButton, &QPushButton::clicked, mGatherer, &QgsStatisticsValueGatherer::cancel );
mCalculatingProgressBar->setMinimum( 0 );
mCalculatingProgressBar->setMaximum( featureCount > 0 ? 100 : 0 );
mCalculatingProgressBar->setValue( 0 );
mCancelButton->show();
mCalculatingProgressBar->show();

QgsApplication::taskManager()->addTask( mGatherer );
}

connect( mGatherer, &QgsStatisticsValueGatherer::finished, this, &QgsStatisticalSummaryDockWidget::gathererThreadFinished );
connect( mGatherer, &QgsStatisticsValueGatherer::progressChanged, mCalculatingProgressBar, &QProgressBar::setValue );
connect( mCancelButton, &QPushButton::clicked, mGatherer, &QgsStatisticsValueGatherer::stop );
mCalculatingProgressBar->setMinimum( 0 );
mCalculatingProgressBar->setMaximum( 0 );
mCalculatingProgressBar->setValue( 0 );
mCancelButton->show();
mCalculatingProgressBar->show();

mGatherer->start();
}

void QgsStatisticalSummaryDockWidget::gathererThreadFinished()
void QgsStatisticalSummaryDockWidget::gathererFinished()
{
mGatherer->deleteLater();
mGatherer = nullptr;
mCalculatingProgressBar->setValue( -1 );
mCancelButton->hide();
Expand All @@ -193,7 +192,7 @@ void QgsStatisticalSummaryDockWidget::gathererThreadFinished()

void QgsStatisticalSummaryDockWidget::updateNumericStatistics()
{
if ( !mGatherer || mGatherer->wasCanceled() )
if ( !mGatherer )
return;

QList< QVariant > variantValues = mGatherer->values();
Expand Down Expand Up @@ -252,13 +251,12 @@ void QgsStatisticalSummaryDockWidget::updateNumericStatistics()
row++;
}

mCancelButton->hide();
mCalculatingProgressBar->hide();
gathererFinished();
}

void QgsStatisticalSummaryDockWidget::updateStringStatistics()
{
if ( !mGatherer || mGatherer->wasCanceled() )
if ( !mGatherer )
return;

QVariantList values = mGatherer->values();//mLayer->getValues( field, ok, selectedOnly );
Expand Down Expand Up @@ -290,8 +288,7 @@ void QgsStatisticalSummaryDockWidget::updateStringStatistics()
row++;
}

mCancelButton->hide();
mCalculatingProgressBar->hide();
gathererFinished();
}

void QgsStatisticalSummaryDockWidget::layerChanged( QgsMapLayer *layer )
Expand All @@ -313,8 +310,7 @@ void QgsStatisticalSummaryDockWidget::layerChanged( QgsMapLayer *layer )

if ( mGatherer )
{
mGatherer->stop();
mGatherer->wait();
mGatherer->cancel();
}

if ( mFieldExpressionWidget->currentField().isEmpty() )
Expand Down Expand Up @@ -378,7 +374,7 @@ void QgsStatisticalSummaryDockWidget::layerSelectionChanged()

void QgsStatisticalSummaryDockWidget::updateDateTimeStatistics()
{
if ( !mGatherer || mGatherer->wasCanceled() )
if ( !mGatherer )
return;

QVariantList values = mGatherer->values();
Expand Down Expand Up @@ -415,8 +411,7 @@ void QgsStatisticalSummaryDockWidget::updateDateTimeStatistics()
row++;
}

mCancelButton->hide();
mCalculatingProgressBar->hide();
gathererFinished();
}

void QgsStatisticalSummaryDockWidget::addRow( int row, const QString &name, const QString &value,
Expand Down
110 changes: 49 additions & 61 deletions src/app/qgsstatisticalsummarydockwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@
#include "qgsstringstatisticalsummary.h"
#include "qgsdatetimestatisticalsummary.h"
#include "qgsdockwidget.h"
#include "qgsfeatureiterator.h"
#include "qgsfeedback.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerutils.h"
#include "qgstaskmanager.h"
#include "qgis_app.h"

class QMenu;
Expand All @@ -40,82 +41,69 @@ class QgsBrowserTreeFilterProxyModel;
* \class QgsStatisticsValueGatherer
* Calculated raster stats for paletted renderer in a thread
*/
class QgsStatisticsValueGatherer: public QThread
class QgsStatisticsValueGatherer : public QgsTask
{
Q_OBJECT

public:
QgsStatisticsValueGatherer( QgsVectorLayer *layer, QString sourceFieldExp, bool selectedOnly )
: mLayer( layer )
, mExpression( sourceFieldExp )
, mSelectedOnly( selectedOnly )
, mWasCanceled( false )
{}

void run() override
QgsStatisticsValueGatherer( QgsVectorLayer *layer, QgsFeatureIterator fit, int featureCount, QString sourceFieldExp )
: QgsTask( tr( "Fetching statistic values" ) )
, mFeatureIterator( fit )
, mFeatureCount( featureCount )
, mFieldExpression( sourceFieldExp )
{
mWasCanceled = false;

// allow responsive cancelation
mFeedback = new QgsFeedback();
connect( mFeedback, &QgsFeedback::progressChanged, this, &QgsStatisticsValueGatherer::progressChanged );

bool ok;
mValues = QgsVectorLayerUtils::getValues( mLayer, mExpression, ok, mSelectedOnly, mFeedback );
if ( !ok )
mFieldIndex = layer->fields().lookupField( mFieldExpression );
if ( mFieldIndex == -1 )
{
mWasCanceled = true;
// use expression, already validated
mExpression.reset( new QgsExpression( mFieldExpression ) );
mContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( layer ) );
}

// be overly cautious - it's *possible* stop() might be called between deleting mFeedback and nulling it
mFeedbackMutex.lock();
delete mFeedback;
mFeedback = nullptr;
mFeedbackMutex.unlock();

emit gatheredValues();
}

//! Informs the gatherer to immediately stop collecting values
void stop()
bool run() override
{
// be cautious, in case gatherer stops naturally just as we are canceling it and mFeedback gets deleted
mFeedbackMutex.lock();
if ( mFeedback )
mFeedback->cancel();
mFeedbackMutex.unlock();

mWasCanceled = true;
QgsFeature f;
int current = 0;
while ( mFeatureIterator.nextFeature( f ) )
{
if ( mExpression )
{
mContext.setFeature( f );
QVariant v = mExpression->evaluate( &mContext );
mValues << v;
}
else
{
mValues << f.attribute( mFieldIndex );
}

if ( isCanceled() )
{
return false;
}

current++;
if ( mFeatureCount > 0 )
{
setProgress( 100.0 * static_cast< double >( current ) / mFeatureCount );
}
}
return true;
}

//! Returns true if collection was canceled before completion
bool wasCanceled() const { return mWasCanceled; }

QList<QVariant> values() const { return mValues; }

signals:

/**
* Emitted when values have been collected
*/
void gatheredValues();

signals:
//! Internal routines can connect to this signal if they use event loop
void canceled();

void progressChanged( double progress );

private:

QgsVectorLayer *mLayer = nullptr;
QString mExpression;
bool mSelectedOnly = false;
QgsFeatureIterator mFeatureIterator;
int mFeatureCount;
QString mFieldExpression;
int mFieldIndex;
QList<QVariant> mValues;
int mMissingValues;
QgsFeedback *mFeedback = nullptr;
QMutex mFeedbackMutex;
bool mWasCanceled;

std::unique_ptr<QgsExpression> mExpression;
QgsExpressionContext mContext;
};

/**
Expand Down Expand Up @@ -149,7 +137,7 @@ class APP_EXPORT QgsStatisticalSummaryDockWidget : public QgsDockWidget, private
void statActionTriggered( bool checked );
void layersRemoved( const QStringList &layers );
void layerSelectionChanged();
void gathererThreadFinished();
void gathererFinished();

private:

Expand Down
12 changes: 4 additions & 8 deletions src/core/qgsvectorlayerutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,10 @@
#include "qgsvectordataprovider.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
#include "qgslogger.h"
#include "qgsfeedback.h"

QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly )
{
QgsFeatureIterator fit;

std::unique_ptr<QgsExpression> expression;
QgsExpressionContext context;

Expand All @@ -42,7 +39,7 @@ QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer
if ( expression->hasParserError() || !expression->prepare( &context ) )
{
ok = false;
return fit;
return QgsFeatureIterator();
}
}

Expand All @@ -58,16 +55,15 @@ QgsFeatureIterator QgsVectorLayerUtils::getValuesIterator( const QgsVectorLayer
QgsFeatureRequest::NoGeometry )
.setSubsetOfAttributes( lst, layer->fields() );

ok = true;
if ( !selectedOnly )
{
fit = layer->getFeatures( request );
return layer->getFeatures( request );
}
else
{
fit = layer->getSelectedFeatures( request );
return layer->getSelectedFeatures( request );
}

return fit;
}

QList<QVariant> QgsVectorLayerUtils::getValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly, QgsFeedback *feedback )
Expand Down

0 comments on commit 0885414

Please sign in to comment.