Skip to content

Commit 7aa93c0

Browse files
committedJun 20, 2014
Hopefully fix #10599 (blank composer map when rendering rasters)
When printing on Windows, the printing does not seem to work well in the worker thread as QImages get converted to QPixmaps. Therefore we force the map rendering into main thread to avoid the issues. I do not have a printer, so I can't confirm the fix really helps
1 parent 98959bb commit 7aa93c0

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed
 

‎python/core/qgsmaprendererjob.sip

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,17 @@ class QgsMapRendererCustomPainterJob : QgsMapRendererJob
218218
*/
219219
void waitForFinishedWithEventLoop( QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents );
220220

221+
/**
222+
* Render the map synchronously in this thread. The function does not return until the map
223+
* is completely rendered.
224+
*
225+
* This is an alternative to ordinary API (using start() + waiting for finished() signal).
226+
* Users are discouraged to use this method unless they have a strong reason for doing it.
227+
* The synchronous rendering blocks the main thread, making the application unresponsive.
228+
* Also, it is not possible to cancel rendering while it is in progress.
229+
*/
230+
void renderSynchronously();
231+
221232
protected slots:
222233
void futureFinished();
223234

‎src/core/composer/qgscomposermap.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,10 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const
221221

222222
// render
223223
QgsMapRendererCustomPainterJob job( jobMapSettings, painter );
224-
job.start();
225-
// wait, but allow network requests to be processed
226-
job.waitForFinishedWithEventLoop( QEventLoop::ExcludeUserInputEvents );
224+
// Render the map in this thread. This is done because of problems
225+
// with printing to printer on Windows (printing to PDF is fine though).
226+
// Raster images were not displayed - see #10599
227+
job.renderSynchronously();
227228
}
228229

229230
void QgsComposerMap::cache( void )

‎src/core/qgsmaprendererjob.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ QgsMapRendererCustomPainterJob::QgsMapRendererCustomPainterJob( const QgsMapSett
182182
, mPainter( painter )
183183
, mLabelingEngine( 0 )
184184
, mActive( false )
185+
, mRenderSynchronously( false )
185186
{
186187
QgsDebugMsg( "QPAINTER construct" );
187188
}
@@ -237,6 +238,13 @@ void QgsMapRendererCustomPainterJob::start()
237238

238239
QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) );
239240

241+
if ( mRenderSynchronously )
242+
{
243+
// do the rendering right now!
244+
doRender();
245+
return;
246+
}
247+
240248
// now we are ready to start rendering!
241249
connect( &mFutureWatcher, SIGNAL( finished() ), SLOT( futureFinished() ) );
242250

@@ -311,6 +319,15 @@ void QgsMapRendererCustomPainterJob::waitForFinishedWithEventLoop( QEventLoop::P
311319
}
312320

313321

322+
void QgsMapRendererCustomPainterJob::renderSynchronously()
323+
{
324+
mRenderSynchronously = true;
325+
start();
326+
futureFinished();
327+
mRenderSynchronously = false;
328+
}
329+
330+
314331
void QgsMapRendererCustomPainterJob::futureFinished()
315332
{
316333
mActive = false;

‎src/core/qgsmaprendererjob.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,17 @@ class CORE_EXPORT QgsMapRendererCustomPainterJob : public QgsMapRendererJob
278278
*/
279279
void waitForFinishedWithEventLoop( QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents );
280280

281+
/**
282+
* Render the map synchronously in this thread. The function does not return until the map
283+
* is completely rendered.
284+
*
285+
* This is an alternative to ordinary API (using start() + waiting for finished() signal).
286+
* Users are discouraged to use this method unless they have a strong reason for doing it.
287+
* The synchronous rendering blocks the main thread, making the application unresponsive.
288+
* Also, it is not possible to cancel rendering while it is in progress.
289+
*/
290+
void renderSynchronously();
291+
281292
protected slots:
282293
void futureFinished();
283294

@@ -296,6 +307,7 @@ class CORE_EXPORT QgsMapRendererCustomPainterJob : public QgsMapRendererJob
296307

297308
bool mActive;
298309
LayerRenderJobs mLayerJobs;
310+
bool mRenderSynchronously;
299311
};
300312

301313

3 commit comments

Comments
 (3)

nyalldawson commented on Jun 20, 2014

@nyalldawson
Collaborator

@wonder-sk this seems a bit unfortunate.. Do you think it would be possible to render synchronously only when printing, so that interactions with composer maps remains quick? We could do this via a setting for the composer map (setRenderSynchronously) or via a composition property (forceSynchronousRendering) which is true only when printing?

wonder-sk commented on Jun 20, 2014

@wonder-sk
MemberAuthor

@nyalldawson It should be still possible to have asynchronous rendering when drawing on screen.

The code in composer right now cannot take advantage of the background rendering anyway - it will require some more code changes to handle it nicely... I.e. instead of waiting until the map is completely rendered, the redraw even will only start the rendering - and when finished, it would trigger update of composer map - similar to how it is done in map canvas.

nyalldawson commented on Jun 20, 2014

@nyalldawson
Collaborator

@Martin-SK Ahh, I think I misunderstood (I'm away from my computer and not able to test at the moment). I thought this change disabled multithreaded rendering too.

Please sign in to comment.