26 #include <QtConcurrentMap> 27 #include <QtConcurrentRun> 50 mStatus = RenderingLayers;
52 mLabelingEngineV2.reset();
57 mLabelingEngineV2->setMapSettings(
mSettings );
61 mLayerJobs =
prepareJobs(
nullptr, mLabelingEngineV2.get() );
64 QgsDebugMsg( QString(
"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( QString(
"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( QString(
"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( QString(
"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( QString(
"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 );
205 mStatus = RenderingLabels;
207 connect( &mLabelingFutureWatcher, &QFutureWatcher<void>::finished,
this, &QgsMapRendererParallelJob::renderingFinished );
210 mLabelingFuture = QtConcurrent::run( renderLabelsStatic,
this );
211 mLabelingFutureWatcher.setFuture( mLabelingFuture );
220 void QgsMapRendererParallelJob::renderingFinished()
237 void QgsMapRendererParallelJob::renderLayerStatic( LayerRenderJob &job )
239 if ( job.context.renderingStopped() )
248 job.imageInitialized =
true;
253 QgsDebugMsgLevel( QString(
"job %1 start (layer %2)" ).arg( reinterpret_cast< quint64 >( &job ), 0, 16 ).arg( job.layer ? job.layer->id() : QString() ), 2 );
256 job.renderer->render();
263 catch ( std::exception &e )
266 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
270 QgsDebugMsg(
"Caught unhandled unknown exception" );
272 job.renderingTime += t.elapsed();
273 QgsDebugMsgLevel( QString(
"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 );
279 LabelRenderJob &job =
self->mLabelJob;
290 painter.begin( job.img );
294 painter.begin( &self->mFinalImage );
300 drawLabeling( self->mSettings, job.context, self->mLabelingEngineV2.get(), &painter );
307 catch ( std::exception &e )
310 QgsDebugMsg(
"Caught unhandled std::exception: " + QString::fromLatin1( e.what() ) );
314 QgsDebugMsg(
"Caught unhandled unknown exception" );
319 job.renderingTime = labelTime.elapsed();
321 job.participatingLayers = _qgis_listRawToQPointer( self->mLabelingEngineV2->participatingLayers() );
324 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 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
Get a preview/resulting image.
QgsLabelingResults * takeLabelingResults() override
Get pointer to internal labeling engine (in order to get access to the results).