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). ...