26 #include <QtConcurrentMap>    27 #include <QtConcurrentRun>    50   mStatus = RenderingLayers;
    52   mLabelingEngineV2.reset();
    57     mLabelingEngineV2->setMapSettings( 
mSettings );
    61   mLayerJobs = 
prepareJobs( 
nullptr, mLabelingEngineV2.get() );
    64   QgsDebugMsg( QStringLiteral( 
"QThreadPool max thread count is %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
    68   connect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderLayersFinished );
    70   mFuture = QtConcurrent::map( mLayerJobs, renderLayerStatic );
    71   mFutureWatcher.setFuture( mFuture );
    79   QgsDebugMsg( QStringLiteral( 
"PARALLEL cancel at status %1" ).arg( mStatus ) );
    81   mLabelJob.context.setRenderingStopped( 
true );
    82   for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
    84     it->context.setRenderingStopped( 
true );
    85     if ( it->renderer && it->renderer->feedback() )
    86       it->renderer->feedback()->cancel();
    89   if ( mStatus == RenderingLayers )
    91     disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderLayersFinished );
    93     mFutureWatcher.waitForFinished();
    95     renderLayersFinished();
    98   if ( mStatus == RenderingLabels )
   100     disconnect( &mLabelingFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderingFinished );
   102     mLabelingFutureWatcher.waitForFinished();
   107   Q_ASSERT( mStatus == Idle );
   115   QgsDebugMsg( QStringLiteral( 
"PARALLEL cancel at status %1" ).arg( mStatus ) );
   117   mLabelJob.context.setRenderingStopped( 
true );
   118   for ( LayerRenderJobs::iterator it = mLayerJobs.begin(); it != mLayerJobs.end(); ++it )
   120     it->context.setRenderingStopped( 
true );
   121     if ( it->renderer && it->renderer->feedback() )
   122       it->renderer->feedback()->cancel();
   125   if ( mStatus == RenderingLayers )
   127     disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderLayersFinished );
   128     connect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderingFinished );
   137   if ( mStatus == RenderingLayers )
   139     disconnect( &mFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderLayersFinished );
   144     mFutureWatcher.waitForFinished();
   146     QgsDebugMsg( QStringLiteral( 
"waitForFinished (1): %1 ms" ).arg( t.elapsed() / 1000.0 ) );
   148     renderLayersFinished();
   151   if ( mStatus == RenderingLabels )
   153     disconnect( &mLabelingFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderingFinished );
   158     mLabelingFutureWatcher.waitForFinished();
   160     QgsDebugMsg( QStringLiteral( 
"waitForFinished (2): %1 ms" ).arg( t.elapsed() / 1000.0 ) );
   165   Q_ASSERT( mStatus == Idle );
   170   return mStatus != Idle;
   175   return mLabelJob.cached;
   180   if ( mLabelingEngineV2 )
   181     return mLabelingEngineV2->takeResults();
   188   if ( mStatus == RenderingLayers )
   194 void QgsMapRendererParallelJob::renderLayersFinished()
   196   Q_ASSERT( mStatus == RenderingLayers );
   198   LayerRenderJobs::const_iterator it = mLayerJobs.constBegin();
   199   for ( ; it != mLayerJobs.constEnd(); ++it )
   201     if ( !it->errors.isEmpty() )
   203       mErrors.append( 
Error( it->layer->id(), it->errors.join( 
',' ) ) );
   210   QgsDebugMsg( QStringLiteral( 
"PARALLEL layers finished" ) );
   214     mStatus = RenderingLabels;
   216     connect( &mLabelingFutureWatcher, &QFutureWatcher<void>::finished, 
this, &QgsMapRendererParallelJob::renderingFinished );
   219     mLabelingFuture = QtConcurrent::run( renderLabelsStatic, 
this );
   220     mLabelingFutureWatcher.setFuture( mLabelingFuture );
   229 void QgsMapRendererParallelJob::renderingFinished()
   231   QgsDebugMsg( QStringLiteral( 
"PARALLEL finished" ) );
   246 void QgsMapRendererParallelJob::renderLayerStatic( LayerRenderJob &job )
   248   if ( job.context.renderingStopped() )
   257     job.imageInitialized = 
true;
   262   QgsDebugMsgLevel( QStringLiteral( 
"job %1 start (layer %2)" ).arg( reinterpret_cast< quint64 >( &job ), 0, 16 ).arg( job.layer ? job.layer->id() : QString() ), 2 );
   265     job.renderer->render();
   272   catch ( std::exception &e )
   275     QgsDebugMsg( 
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
   279     QgsDebugMsg( QStringLiteral( 
"Caught unhandled unknown exception" ) );
   282   job.errors = job.renderer->errors();
   283   job.renderingTime += t.elapsed();
   284   QgsDebugMsgLevel( QStringLiteral( 
"job %1 end [%2 ms] (layer %3)" ).arg( reinterpret_cast< quint64 >( &job ), 0, 16 ).arg( job.renderingTime ).arg( job.layer ? job.layer->id() : QString() ), 2 );
   290   LabelRenderJob &job = 
self->mLabelJob;
   301       painter.begin( job.img );
   305       painter.begin( &self->mFinalImage );
   311       drawLabeling( job.context, self->mLabelingEngineV2.get(), &painter );
   318     catch ( std::exception &e )
   321       QgsDebugMsg( 
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
   325       QgsDebugMsg( QStringLiteral( 
"Caught unhandled unknown exception" ) );
   330     job.renderingTime = labelTime.elapsed();
   332     job.participatingLayers = _qgis_listRawToQPointer( self->mLabelingEngineV2->participatingLayers() );
   335       self->mFinalImage = 
composeImage( self->mSettings, self->mLayerJobs, self->mLabelJob );
 void finished()
emitted when asynchronous rendering is finished (or canceled). 
 
void waitForFinished() override
Block until the job has finished. 
 
void cleanupJobs(LayerRenderJobs &jobs)
 
static Q_DECL_DEPRECATED void drawLabeling(const QgsMapSettings &settings, QgsRenderContext &renderContext, QgsLabelingEngine *labelingEngine2, QPainter *painter)
 
~QgsMapRendererParallelJob() override
 
void renderingLayersFinished()
Emitted when the layers are rendered. 
 
void cancel() override
Stop the rendering job - does not return until the job has terminated. 
 
Enable drawing of labels on top of the map. 
 
The QgsMapSettings class contains configuration for rendering of the map. 
 
QgsMapRendererParallelJob(const QgsMapSettings &settings)
 
static QImage composeImage(const QgsMapSettings &settings, const LayerRenderJobs &jobs, const LabelRenderJob &labelJob)
 
LabelRenderJob prepareLabelingJob(QPainter *painter, QgsLabelingEngine *labelingEngine2, bool canUseLabelCache=true)
Prepares a labeling job. 
 
bool usedCachedLabels() const override
Returns true if the render job was able to use a cached labeling solution. 
 
bool prepareLabelCache() const
Prepares the cache for storing the result of labeling. 
 
#define QgsDebugMsgLevel(str, level)
 
Job implementation that renders all layers in parallel. 
 
void cleanupLabelJob(LabelRenderJob &job)
Handles clean up tasks for a label job, including deletion of images and storing cached label results...
 
The QgsLabelingEngine class provides map labeling functionality. 
 
LayerRenderJobs prepareJobs(QPainter *painter, QgsLabelingEngine *labelingEngine2)
 
void logRenderingTime(const LayerRenderJobs &jobs, const LabelRenderJob &labelJob)
 
void cancelWithoutBlocking() override
Triggers cancelation of the rendering job without blocking. 
 
Intermediate base class adding functionality that allows client to query the rendered image...
 
void start() override
Start the rendering job and immediately return. 
 
Class that stores computed placement from labeling engine. 
 
bool testFlag(Flag flag) const
Check whether a particular flag is enabled. 
 
Defines a QGIS exception class. 
 
bool isActive() const override
Tell whether the rendering job is currently running in background. 
 
QImage renderedImage() override
Gets a preview/resulting image. 
 
QgsLabelingResults * takeLabelingResults() override
Gets pointer to internal labeling engine (in order to get access to the results). ...