Allow cancellation of PAL labeling computation

This commit is contained in:
Martin Dobias 2013-11-18 14:28:55 +07:00
parent 1110aafa43
commit 68e29511c3
5 changed files with 75 additions and 0 deletions

View File

@ -85,6 +85,9 @@ namespace pal
// do not init and exit GEOS - we do it inside QGIS
//initGEOS( geosNotice, geosError );
fnIsCancelled = 0;
fnIsCancelledContext = 0;
layers = new QList<Layer*>();
lyrsMutex = new SimpleMutex();
@ -316,6 +319,9 @@ namespace pal
double scale = (( FilterContext* ) ctx )->scale;
Pal* pal = (( FilterContext* )ctx )->pal;
if ( pal->isCancelled() )
return false; // do not continue searching
double amin[2], amax[2];
pset->getBoundingBox( amin, amax );
@ -509,6 +515,13 @@ namespace pal
filterCtx.pal = this;
obstacles->Search( amin, amax, filteringCallback, ( void* ) &filterCtx );
if ( isCancelled() )
{
delete fFeats;
delete prob;
delete obstacles;
return 0;
}
int idlp = 0;
for ( i = 0; i < prob->nbft; i++ ) /* foreach feature into prob */
@ -580,6 +593,14 @@ namespace pal
j = 0;
while ( fFeats->size() > 0 ) // foreach feature
{
if ( isCancelled() )
{
delete fFeats;
delete prob;
delete obstacles;
return 0;
}
feat = fFeats->pop_front();
for ( i = 0; i < feat->nblp; i++, idlp++ ) // foreach label candidate
{
@ -798,6 +819,12 @@ namespace pal
return solution;
}
void Pal::registerCancellationCallback(Pal::FnIsCancelled fnCancelled, void *context)
{
fnIsCancelled = fnCancelled;
fnIsCancelledContext = context;
}
Problem* Pal::extractProblem( double scale, double bbox[4] )
{
// find out: nbLayers, layersName, layersFactor

View File

@ -172,6 +172,13 @@ namespace pal
*/
bool showPartial;
typedef bool (*FnIsCancelled)(void* ctx);
/** Callback that may be called from PAL to check whether the job has not been cancelled in meanwhile */
FnIsCancelled fnIsCancelled;
/** Application-specific context for the cancellation check function */
void* fnIsCancelledContext;
/**
* \brief Problem factory
* Extract features to label and generates candidates for them,
@ -339,6 +346,11 @@ namespace pal
PalStat **stat,
bool displayAll );
/** Register a function that returns whether this job has been cancelled - PAL calls it during the computation */
void registerCancellationCallback( FnIsCancelled fnCancelled, void* context );
/** Check whether the job has been cancelled */
inline bool isCancelled() { return fnIsCancelled ? fnIsCancelled( fnIsCancelledContext ) : false; }
Problem* extractProblem( double scale, double bbox[4] );

View File

@ -349,6 +349,13 @@ namespace pal
while ( list->getSize() > 0 ) // O (log size)
{
if ( pal->isCancelled() )
{
delete context;
delete list;
return;
}
label = list->getBest(); // O (log size)

View File

@ -3818,12 +3818,21 @@ void QgsPalLabeling::dataDefinedDropShadow( QgsPalLayerSettings& tmpLyr,
}
}
// helper function for checking for job cancellation within PAL
static bool _palIsCancelled( void* ctx )
{
return ( ( QgsRenderContext* ) ctx )->renderingStopped();
}
void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
{
Q_ASSERT( mMapSettings != NULL );
QPainter* painter = context.painter();
QgsRectangle extent = context.extent();
mPal->registerCancellationCallback( &_palIsCancelled, &context );
delete mResults;
mResults = new QgsLabelingResults;
@ -3849,6 +3858,9 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
return;
}
if ( context.renderingStopped() )
return; // it has been cancelled
const QgsMapToPixel& xform = mMapSettings->mapToPixel();
// draw rectangles with all candidates
@ -3876,12 +3888,23 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
QgsDebugMsgLevel( QString( "LABELING work: %1 ms ... labels# %2" ).arg( t.elapsed() ).arg( labels->size() ), 4 );
t.restart();
if ( context.renderingStopped() )
{
delete problem;
delete labels;
deleteTemporaryData();
return;
}
painter->setRenderHint( QPainter::Antialiasing );
// draw the labels
std::list<LabelPosition*>::iterator it = labels->begin();
for ( ; it != labels->end(); ++it )
{
if ( context.renderingStopped() )
break;
QgsPalGeometry* palGeometry = dynamic_cast< QgsPalGeometry* >(( *it )->getFeaturePart()->getUserGeometry() );
if ( !palGeometry )
{
@ -3996,7 +4019,11 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context )
delete problem;
delete labels;
deleteTemporaryData();
}
void QgsPalLabeling::deleteTemporaryData()
{
// delete all allocated geometries for features
QHash<QgsVectorLayer*, QgsPalLayerSettings>::iterator lit;
for ( lit = mActiveLayers.begin(); lit != mActiveLayers.end(); ++lit )

View File

@ -813,6 +813,8 @@ class CORE_EXPORT QgsPalLabeling : public QgsLabelingEngineInterface
void dataDefinedDropShadow( QgsPalLayerSettings& tmpLyr,
const QMap< QgsPalLayerSettings::DataDefinedProperties, QVariant >& ddValues );
void deleteTemporaryData();
// hashtable of layer settings, being filled during labeling
QHash<QgsVectorLayer*, QgsPalLayerSettings> mActiveLayers;
// hashtable of active diagram layers