Skip to content

Commit b0a36e9

Browse files
authoredDec 5, 2017
Merge pull request #5789 from nyalldawson/render_jobs
[Rendering] Only render in preview jobs layers that are fast enough
2 parents b26c14e + 38cca6c commit b0a36e9

File tree

12 files changed

+128
-12
lines changed

12 files changed

+128
-12
lines changed
 

‎python/core/qgis.sip

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ const double DEFAULT_LINE_WIDTH;
241241
const double DEFAULT_SEGMENT_EPSILON;
242242

243243

244+
245+
244246
typedef unsigned long long qgssize;
245247

246248

‎python/core/qgsdataprovider.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ Current time stamp of data source
380380
.. versionadded:: 3.0
381381
%End
382382

383+
383384
signals:
384385

385386
void fullExtentCalculated();

‎python/core/qgsmaprendererjob.sip

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,12 @@ List of errors that happened during the rendering job - available when the rende
137137

138138
int renderingTime() const;
139139
%Docstring
140-
Find out how long it took to finish the job (in milliseconds)
140+
Returns the total time it took to finish the job (in milliseconds).
141+
.. seealso:: perLayerRenderingTime()
141142
:rtype: int
142143
%End
143144

145+
144146
const QgsMapSettings &mapSettings() const;
145147
%Docstring
146148
Return map settings with which this job was started.
@@ -179,6 +181,7 @@ emitted when asynchronous rendering is finished (or canceled).
179181

180182

181183

184+
182185
};
183186

184187

‎src/core/qgis.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,18 @@ const double DEFAULT_LINE_WIDTH = 0.26;
440440
//! Default snapping tolerance for segments
441441
const double DEFAULT_SEGMENT_EPSILON = 1e-8;
442442

443+
///@cond PRIVATE
444+
#ifndef SIP_RUN
445+
446+
//! Delay between the scheduling of 2 preview jobs
447+
const int PREVIEW_JOB_DELAY_MS = 250;
448+
449+
//! Maximum rendering time for a layer of a preview job
450+
const int MAXIMUM_LAYER_PREVIEW_TIME_MS = 250;
451+
#endif
452+
453+
///@endcond
454+
443455
typedef QMap<QString, QString> QgsStringMap SIP_SKIP;
444456

445457
/**

‎src/core/qgsdataprovider.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,7 @@ void QgsDataProvider::setListening( bool isListening )
4242
Q_UNUSED( isListening );
4343
}
4444

45+
bool QgsDataProvider::renderInPreview( const PreviewContext &context )
46+
{
47+
return context.lastRenderingTimeMs <= context.maxRenderingTimeMs;
48+
}

‎src/core/qgsdataprovider.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,37 @@ class CORE_EXPORT QgsDataProvider : public QObject
461461
*/
462462
virtual void setListening( bool isListening );
463463

464+
#ifndef SIP_RUN
465+
466+
/**
467+
* Stores settings related to the context in which a preview job runs.
468+
* \note Not available in Python bindings
469+
* \since QGIS 3.0
470+
*/
471+
struct PreviewContext
472+
{
473+
//! Previous rendering time for the layer, in ms
474+
double lastRenderingTimeMs = -1;
475+
476+
//! Default maximum allowable render time, in ms
477+
double maxRenderingTimeMs = MAXIMUM_LAYER_PREVIEW_TIME_MS;
478+
};
479+
#endif
480+
481+
/**
482+
* Returns whether the layer must be rendered in preview jobs.
483+
*
484+
* The \a context argument gives useful information which can be used
485+
* to determine whether the layer should be rendered or not.
486+
*
487+
* The base implementation returns true if lastRenderingTimeMs <= maxRenderingTimeMs.
488+
*
489+
* \since QGIS 3.0
490+
*
491+
* \note not available in Python bindings
492+
*/
493+
virtual bool renderInPreview( const QgsDataProvider::PreviewContext &context ); // SIP_SKIP
494+
464495
signals:
465496

466497
/**

‎src/core/qgsmaprendererjob.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ void QgsMapRendererJob::setCache( QgsMapRendererCache *cache )
6464
mCache = cache;
6565
}
6666

67+
QHash<QgsMapLayer *, int> QgsMapRendererJob::perLayerRenderingTime() const
68+
{
69+
QHash<QgsMapLayer *, int> result;
70+
for ( auto it = mPerLayerRenderingTime.constBegin(); it != mPerLayerRenderingTime.constEnd(); ++it )
71+
{
72+
if ( it.key() )
73+
result.insert( it.key(), it.value() );
74+
}
75+
return result;
76+
}
77+
6778
const QgsMapSettings &QgsMapRendererJob::mapSettings() const
6879
{
6980
return mSettings;
@@ -412,8 +423,10 @@ void QgsMapRendererJob::cleanupJobs( LayerRenderJobs &jobs )
412423
delete job.renderer;
413424
job.renderer = nullptr;
414425
}
415-
}
416426

427+
if ( job.layer )
428+
mPerLayerRenderingTime.insert( job.layer, job.renderingTime );
429+
}
417430

418431
jobs.clear();
419432
}

‎src/core/qgsmaprendererjob.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,19 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
199199
*/
200200
void setCache( QgsMapRendererCache *cache );
201201

202-
//! Find out how long it took to finish the job (in milliseconds)
202+
/**
203+
* Returns the total time it took to finish the job (in milliseconds).
204+
* \see perLayerRenderingTime()
205+
*/
203206
int renderingTime() const { return mRenderingTime; }
204207

208+
/**
209+
* Returns the render time (in ms) per layer.
210+
* \note Not available in Python bindings.
211+
* \since QGIS 3.0
212+
*/
213+
QHash< QgsMapLayer *, int > perLayerRenderingTime() const SIP_SKIP;
214+
205215
/**
206216
* Return map settings with which this job was started.
207217
* \returns A QgsMapSettings instance with render settings
@@ -239,6 +249,9 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
239249

240250
int mRenderingTime = 0;
241251

252+
//! Render time (in ms) per layer, by layer ID
253+
QHash< QgsWeakMapLayerPointer, int > mPerLayerRenderingTime;
254+
242255
/**
243256
* Prepares the cache for storing the result of labeling. Returns false if
244257
* the render cannot use cached labels and should not cache the result.

‎src/gui/qgsmapcanvas.cpp

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ email : sherman at mrcc.com
6666
#include "qgsmapthemecollection.h"
6767
#include <cmath>
6868

69-
7069
/**
7170
* \ingroup gui
7271
* Deprecated to be deleted, stuff from here should be moved elsewhere.
@@ -612,6 +611,13 @@ void QgsMapCanvas::rendererJobFinished()
612611
p.end();
613612

614613
mMap->setContent( img, imageRect( img, mSettings ) );
614+
615+
mLastLayerRenderTime.clear();
616+
const auto times = mJob->perLayerRenderingTime();
617+
for ( auto it = times.constBegin(); it != times.constEnd(); ++it )
618+
{
619+
mLastLayerRenderTime.insert( it.key()->id(), it.value() );
620+
}
615621
if ( mUsePreviewJobs )
616622
startPreviewJobs();
617623
}
@@ -633,6 +639,13 @@ void QgsMapCanvas::previewJobFinished()
633639
{
634640
mMap->addPreviewImage( job->renderedImage(), job->mapSettings().extent() );
635641
mPreviewJobs.removeAll( job );
642+
643+
int number = job->property( "number" ).toInt();
644+
if ( number < 8 )
645+
{
646+
startPreviewJob( number + 1 );
647+
}
648+
636649
delete job;
637650
}
638651
}
@@ -2269,15 +2282,29 @@ void QgsMapCanvas::startPreviewJob( int number )
22692282
jobSettings.setFlag( QgsMapSettings::DrawLabeling, false );
22702283
jobSettings.setFlag( QgsMapSettings::RenderPreviewJob, true );
22712284

2285+
// truncate preview layers to fast layers
2286+
const QList<QgsMapLayer *> layers = jobSettings.layers();
2287+
QList< QgsMapLayer * > previewLayers;
2288+
QgsDataProvider::PreviewContext context;
2289+
context.maxRenderingTimeMs = MAXIMUM_LAYER_PREVIEW_TIME_MS;
2290+
for ( QgsMapLayer *layer : layers )
2291+
{
2292+
context.lastRenderingTimeMs = mLastLayerRenderTime.value( layer->id(), 0 );
2293+
if ( !layer->dataProvider()->renderInPreview( context ) )
2294+
{
2295+
QgsDebugMsgLevel( QString( "Layer %1 not rendered because it does not match the renderInPreview criterion %2" ).arg( layer->id() ).arg( mLastLayerRenderTime.value( layer->id() ) ), 3 );
2296+
continue;
2297+
}
2298+
2299+
previewLayers << layer;
2300+
}
2301+
jobSettings.setLayers( previewLayers );
2302+
22722303
QgsMapRendererQImageJob *job = new QgsMapRendererSequentialJob( jobSettings );
2304+
job->setProperty( "number", number );
22732305
mPreviewJobs.append( job );
22742306
connect( job, &QgsMapRendererJob::finished, this, &QgsMapCanvas::previewJobFinished );
22752307
job->start();
2276-
2277-
if ( number < 8 )
2278-
{
2279-
schedulePreviewJob( number + 1 );
2280-
}
22812308
}
22822309

22832310
void QgsMapCanvas::stopPreviewJobs()
@@ -2299,7 +2326,7 @@ void QgsMapCanvas::stopPreviewJobs()
22992326
void QgsMapCanvas::schedulePreviewJob( int number )
23002327
{
23012328
mPreviewTimer.setSingleShot( true );
2302-
mPreviewTimer.setInterval( 250 );
2329+
mPreviewTimer.setInterval( PREVIEW_JOB_DELAY_MS );
23032330
disconnect( mPreviewTimerConnection );
23042331
mPreviewTimerConnection = connect( &mPreviewTimer, &QTimer::timeout, this, [ = ]()
23052332
{

‎src/gui/qgsmapcanvas.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
10001000

10011001
bool mUsePreviewJobs = false;
10021002

1003+
QHash< QString, int > mLastLayerRenderTime;
1004+
10031005
/**
10041006
* Force a resize of the map canvas item
10051007
* \since QGIS 2.16

‎src/providers/wms/qgswmsprovider.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3199,18 +3199,25 @@ QString QgsWmsProvider::lastErrorFormat()
31993199
QString QgsWmsProvider::name() const
32003200
{
32013201
return WMS_KEY;
3202-
} // QgsWmsProvider::name()
3202+
}
32033203

32043204

32053205
QString QgsWmsProvider::description() const
32063206
{
32073207
return WMS_DESCRIPTION;
3208-
} // QgsWmsProvider::description()
3208+
}
32093209

32103210
void QgsWmsProvider::reloadData()
32113211
{
32123212
}
32133213

3214+
bool QgsWmsProvider::renderInPreview( const QgsDataProvider::PreviewContext &context )
3215+
{
3216+
if ( mSettings.mTiled || mSettings.mXyz )
3217+
return true;
3218+
3219+
return QgsRasterDataProvider::renderInPreview( context );
3220+
}
32143221

32153222
QVector<QgsWmsSupportedFormat> QgsWmsProvider::supportedFormats()
32163223
{

‎src/providers/wms/qgswmsprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
208208
QString name() const override;
209209
QString description() const override;
210210
virtual void reloadData() override;
211+
bool renderInPreview( const QgsDataProvider::PreviewContext &context ) override;
211212

212213
static QVector<QgsWmsSupportedFormat> supportedFormats();
213214

0 commit comments

Comments
 (0)
Please sign in to comment.