Skip to content

Commit

Permalink
Make raster paletted renderer classify function thread safe
Browse files Browse the repository at this point in the history
In addition to making this correctly thread safe, also avoids a
temporary UI hang during the classification if the layer rendering
is triggered before the classification finishes.

(cherry picked from commit 1f10b81)
  • Loading branch information
nyalldawson committed Dec 8, 2022
1 parent 37a509e commit 71c3c36
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 19 deletions.
35 changes: 19 additions & 16 deletions src/gui/raster/qgspalettedrendererwidget.cpp
Expand Up @@ -842,28 +842,31 @@ void QgsPalettedRendererClassGatherer::run()
mFeedback = new QgsRasterBlockFeedback();
connect( mFeedback, &QgsRasterBlockFeedback::progressChanged, this, &QgsPalettedRendererClassGatherer::progressChanged );

QgsPalettedRasterRenderer::ClassData newClasses = QgsPalettedRasterRenderer::classDataFromRaster( mLayer->dataProvider(), mBandNumber, mRamp.get(), mFeedback );

// combine existing classes with new classes
QgsPalettedRasterRenderer::ClassData::iterator classIt = newClasses.begin();
emit progressChanged( 0 );
qlonglong i = 0;
for ( ; classIt != newClasses.end(); ++classIt )
if ( mProvider )
{
// check if existing classes contains this same class
for ( const QgsPalettedRasterRenderer::Class &existingClass : std::as_const( mClasses ) )
QgsPalettedRasterRenderer::ClassData newClasses = QgsPalettedRasterRenderer::classDataFromRaster( mProvider.get(), mBandNumber, mRamp.get(), mFeedback );

// combine existing classes with new classes
QgsPalettedRasterRenderer::ClassData::iterator classIt = newClasses.begin();
emit progressChanged( 0 );
qlonglong i = 0;
for ( ; classIt != newClasses.end(); ++classIt )
{
if ( existingClass.value == classIt->value )
// check if existing classes contains this same class
for ( const QgsPalettedRasterRenderer::Class &existingClass : std::as_const( mClasses ) )
{
classIt->color = existingClass.color;
classIt->label = existingClass.label;
break;
if ( existingClass.value == classIt->value )
{
classIt->color = existingClass.color;
classIt->label = existingClass.label;
break;
}
}
i ++;
emit progressChanged( 100 * ( i / static_cast<float>( newClasses.count() ) ) );
}
i ++;
emit progressChanged( 100 * ( i / static_cast<float>( newClasses.count() ) ) );
mClasses = newClasses;
}
mClasses = newClasses;

// be overly cautious - it's *possible* stop() might be called between deleting mFeedback and nulling it
mFeedbackMutex.lock();
Expand Down
5 changes: 2 additions & 3 deletions src/gui/raster/qgspalettedrendererwidget.h
Expand Up @@ -23,7 +23,6 @@
#include "qgspalettedrasterrenderer.h"
#include "qgscolorschemelist.h"
#include "qgsrasterlayer.h"
#include "qgsrasterdataprovider.h"
#include "ui_qgspalettedrendererwidgetbase.h"
#include "qgis_gui.h"

Expand All @@ -46,7 +45,7 @@ class QgsPalettedRendererClassGatherer: public QThread

public:
QgsPalettedRendererClassGatherer( QgsRasterLayer *layer, int bandNumber, const QgsPalettedRasterRenderer::ClassData &existingClasses, QgsColorRamp *ramp = nullptr )
: mLayer( layer )
: mProvider( ( layer && layer->dataProvider() ) ? layer->dataProvider()->clone() : nullptr )
, mBandNumber( bandNumber )
, mRamp( ramp )
, mClasses( existingClasses )
Expand Down Expand Up @@ -87,7 +86,7 @@ class QgsPalettedRendererClassGatherer: public QThread

private:

QgsRasterLayer *mLayer = nullptr;
std::unique_ptr< QgsRasterDataProvider > mProvider;
int mBandNumber;
std::unique_ptr< QgsColorRamp > mRamp;
QString mSubstring;
Expand Down

0 comments on commit 71c3c36

Please sign in to comment.