mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Merge pull request #5789 from nyalldawson/render_jobs
[Rendering] Only render in preview jobs layers that are fast enough
This commit is contained in:
commit
b0a36e9bb1
@ -241,6 +241,8 @@ const double DEFAULT_LINE_WIDTH;
|
||||
const double DEFAULT_SEGMENT_EPSILON;
|
||||
|
||||
|
||||
|
||||
|
||||
typedef unsigned long long qgssize;
|
||||
|
||||
|
||||
|
@ -380,6 +380,7 @@ Current time stamp of data source
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
void fullExtentCalculated();
|
||||
|
@ -137,10 +137,12 @@ List of errors that happened during the rendering job - available when the rende
|
||||
|
||||
int renderingTime() const;
|
||||
%Docstring
|
||||
Find out how long it took to finish the job (in milliseconds)
|
||||
Returns the total time it took to finish the job (in milliseconds).
|
||||
.. seealso:: perLayerRenderingTime()
|
||||
:rtype: int
|
||||
%End
|
||||
|
||||
|
||||
const QgsMapSettings &mapSettings() const;
|
||||
%Docstring
|
||||
Return map settings with which this job was started.
|
||||
@ -179,6 +181,7 @@ emitted when asynchronous rendering is finished (or canceled).
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -440,6 +440,18 @@ const double DEFAULT_LINE_WIDTH = 0.26;
|
||||
//! Default snapping tolerance for segments
|
||||
const double DEFAULT_SEGMENT_EPSILON = 1e-8;
|
||||
|
||||
///@cond PRIVATE
|
||||
#ifndef SIP_RUN
|
||||
|
||||
//! Delay between the scheduling of 2 preview jobs
|
||||
const int PREVIEW_JOB_DELAY_MS = 250;
|
||||
|
||||
//! Maximum rendering time for a layer of a preview job
|
||||
const int MAXIMUM_LAYER_PREVIEW_TIME_MS = 250;
|
||||
#endif
|
||||
|
||||
///@endcond
|
||||
|
||||
typedef QMap<QString, QString> QgsStringMap SIP_SKIP;
|
||||
|
||||
/**
|
||||
|
@ -42,3 +42,7 @@ void QgsDataProvider::setListening( bool isListening )
|
||||
Q_UNUSED( isListening );
|
||||
}
|
||||
|
||||
bool QgsDataProvider::renderInPreview( const PreviewContext &context )
|
||||
{
|
||||
return context.lastRenderingTimeMs <= context.maxRenderingTimeMs;
|
||||
}
|
||||
|
@ -461,6 +461,37 @@ class CORE_EXPORT QgsDataProvider : public QObject
|
||||
*/
|
||||
virtual void setListening( bool isListening );
|
||||
|
||||
#ifndef SIP_RUN
|
||||
|
||||
/**
|
||||
* Stores settings related to the context in which a preview job runs.
|
||||
* \note Not available in Python bindings
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
struct PreviewContext
|
||||
{
|
||||
//! Previous rendering time for the layer, in ms
|
||||
double lastRenderingTimeMs = -1;
|
||||
|
||||
//! Default maximum allowable render time, in ms
|
||||
double maxRenderingTimeMs = MAXIMUM_LAYER_PREVIEW_TIME_MS;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns whether the layer must be rendered in preview jobs.
|
||||
*
|
||||
* The \a context argument gives useful information which can be used
|
||||
* to determine whether the layer should be rendered or not.
|
||||
*
|
||||
* The base implementation returns true if lastRenderingTimeMs <= maxRenderingTimeMs.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
virtual bool renderInPreview( const QgsDataProvider::PreviewContext &context ); // SIP_SKIP
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,17 @@ void QgsMapRendererJob::setCache( QgsMapRendererCache *cache )
|
||||
mCache = cache;
|
||||
}
|
||||
|
||||
QHash<QgsMapLayer *, int> QgsMapRendererJob::perLayerRenderingTime() const
|
||||
{
|
||||
QHash<QgsMapLayer *, int> result;
|
||||
for ( auto it = mPerLayerRenderingTime.constBegin(); it != mPerLayerRenderingTime.constEnd(); ++it )
|
||||
{
|
||||
if ( it.key() )
|
||||
result.insert( it.key(), it.value() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const QgsMapSettings &QgsMapRendererJob::mapSettings() const
|
||||
{
|
||||
return mSettings;
|
||||
@ -412,8 +423,10 @@ void QgsMapRendererJob::cleanupJobs( LayerRenderJobs &jobs )
|
||||
delete job.renderer;
|
||||
job.renderer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if ( job.layer )
|
||||
mPerLayerRenderingTime.insert( job.layer, job.renderingTime );
|
||||
}
|
||||
|
||||
jobs.clear();
|
||||
}
|
||||
|
@ -199,9 +199,19 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
|
||||
*/
|
||||
void setCache( QgsMapRendererCache *cache );
|
||||
|
||||
//! Find out how long it took to finish the job (in milliseconds)
|
||||
/**
|
||||
* Returns the total time it took to finish the job (in milliseconds).
|
||||
* \see perLayerRenderingTime()
|
||||
*/
|
||||
int renderingTime() const { return mRenderingTime; }
|
||||
|
||||
/**
|
||||
* Returns the render time (in ms) per layer.
|
||||
* \note Not available in Python bindings.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
QHash< QgsMapLayer *, int > perLayerRenderingTime() const SIP_SKIP;
|
||||
|
||||
/**
|
||||
* Return map settings with which this job was started.
|
||||
* \returns A QgsMapSettings instance with render settings
|
||||
@ -239,6 +249,9 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
|
||||
|
||||
int mRenderingTime = 0;
|
||||
|
||||
//! Render time (in ms) per layer, by layer ID
|
||||
QHash< QgsWeakMapLayerPointer, int > mPerLayerRenderingTime;
|
||||
|
||||
/**
|
||||
* Prepares the cache for storing the result of labeling. Returns false if
|
||||
* the render cannot use cached labels and should not cache the result.
|
||||
|
@ -66,7 +66,6 @@ email : sherman at mrcc.com
|
||||
#include "qgsmapthemecollection.h"
|
||||
#include <cmath>
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup gui
|
||||
* Deprecated to be deleted, stuff from here should be moved elsewhere.
|
||||
@ -612,6 +611,13 @@ void QgsMapCanvas::rendererJobFinished()
|
||||
p.end();
|
||||
|
||||
mMap->setContent( img, imageRect( img, mSettings ) );
|
||||
|
||||
mLastLayerRenderTime.clear();
|
||||
const auto times = mJob->perLayerRenderingTime();
|
||||
for ( auto it = times.constBegin(); it != times.constEnd(); ++it )
|
||||
{
|
||||
mLastLayerRenderTime.insert( it.key()->id(), it.value() );
|
||||
}
|
||||
if ( mUsePreviewJobs )
|
||||
startPreviewJobs();
|
||||
}
|
||||
@ -633,6 +639,13 @@ void QgsMapCanvas::previewJobFinished()
|
||||
{
|
||||
mMap->addPreviewImage( job->renderedImage(), job->mapSettings().extent() );
|
||||
mPreviewJobs.removeAll( job );
|
||||
|
||||
int number = job->property( "number" ).toInt();
|
||||
if ( number < 8 )
|
||||
{
|
||||
startPreviewJob( number + 1 );
|
||||
}
|
||||
|
||||
delete job;
|
||||
}
|
||||
}
|
||||
@ -2269,15 +2282,29 @@ void QgsMapCanvas::startPreviewJob( int number )
|
||||
jobSettings.setFlag( QgsMapSettings::DrawLabeling, false );
|
||||
jobSettings.setFlag( QgsMapSettings::RenderPreviewJob, true );
|
||||
|
||||
// truncate preview layers to fast layers
|
||||
const QList<QgsMapLayer *> layers = jobSettings.layers();
|
||||
QList< QgsMapLayer * > previewLayers;
|
||||
QgsDataProvider::PreviewContext context;
|
||||
context.maxRenderingTimeMs = MAXIMUM_LAYER_PREVIEW_TIME_MS;
|
||||
for ( QgsMapLayer *layer : layers )
|
||||
{
|
||||
context.lastRenderingTimeMs = mLastLayerRenderTime.value( layer->id(), 0 );
|
||||
if ( !layer->dataProvider()->renderInPreview( context ) )
|
||||
{
|
||||
QgsDebugMsgLevel( QString( "Layer %1 not rendered because it does not match the renderInPreview criterion %2" ).arg( layer->id() ).arg( mLastLayerRenderTime.value( layer->id() ) ), 3 );
|
||||
continue;
|
||||
}
|
||||
|
||||
previewLayers << layer;
|
||||
}
|
||||
jobSettings.setLayers( previewLayers );
|
||||
|
||||
QgsMapRendererQImageJob *job = new QgsMapRendererSequentialJob( jobSettings );
|
||||
job->setProperty( "number", number );
|
||||
mPreviewJobs.append( job );
|
||||
connect( job, &QgsMapRendererJob::finished, this, &QgsMapCanvas::previewJobFinished );
|
||||
job->start();
|
||||
|
||||
if ( number < 8 )
|
||||
{
|
||||
schedulePreviewJob( number + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapCanvas::stopPreviewJobs()
|
||||
@ -2299,7 +2326,7 @@ void QgsMapCanvas::stopPreviewJobs()
|
||||
void QgsMapCanvas::schedulePreviewJob( int number )
|
||||
{
|
||||
mPreviewTimer.setSingleShot( true );
|
||||
mPreviewTimer.setInterval( 250 );
|
||||
mPreviewTimer.setInterval( PREVIEW_JOB_DELAY_MS );
|
||||
disconnect( mPreviewTimerConnection );
|
||||
mPreviewTimerConnection = connect( &mPreviewTimer, &QTimer::timeout, this, [ = ]()
|
||||
{
|
||||
|
@ -1000,6 +1000,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
|
||||
|
||||
bool mUsePreviewJobs = false;
|
||||
|
||||
QHash< QString, int > mLastLayerRenderTime;
|
||||
|
||||
/**
|
||||
* Force a resize of the map canvas item
|
||||
* \since QGIS 2.16
|
||||
|
@ -3199,18 +3199,25 @@ QString QgsWmsProvider::lastErrorFormat()
|
||||
QString QgsWmsProvider::name() const
|
||||
{
|
||||
return WMS_KEY;
|
||||
} // QgsWmsProvider::name()
|
||||
}
|
||||
|
||||
|
||||
QString QgsWmsProvider::description() const
|
||||
{
|
||||
return WMS_DESCRIPTION;
|
||||
} // QgsWmsProvider::description()
|
||||
}
|
||||
|
||||
void QgsWmsProvider::reloadData()
|
||||
{
|
||||
}
|
||||
|
||||
bool QgsWmsProvider::renderInPreview( const QgsDataProvider::PreviewContext &context )
|
||||
{
|
||||
if ( mSettings.mTiled || mSettings.mXyz )
|
||||
return true;
|
||||
|
||||
return QgsRasterDataProvider::renderInPreview( context );
|
||||
}
|
||||
|
||||
QVector<QgsWmsSupportedFormat> QgsWmsProvider::supportedFormats()
|
||||
{
|
||||
|
@ -208,6 +208,7 @@ class QgsWmsProvider : public QgsRasterDataProvider
|
||||
QString name() const override;
|
||||
QString description() const override;
|
||||
virtual void reloadData() override;
|
||||
bool renderInPreview( const QgsDataProvider::PreviewContext &context ) override;
|
||||
|
||||
static QVector<QgsWmsSupportedFormat> supportedFormats();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user