mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Rework how composer map cache is invalidated
Avoids unnecessary redraws and defers cache update until when item is actually visible
This commit is contained in:
parent
91b046a743
commit
abe8ead1a5
@ -640,6 +640,7 @@ and setAtlasScalingMode() instead.
|
||||
- setMapCanvas() was removed. This is no longer required to draw map annotations, which are instead retrieved from the composition's
|
||||
associated project's annotationManager()
|
||||
- setDrawCanvasItems() and drawCanvasItems() were renamed to setDrawAnnotations() and drawAnnotations()
|
||||
- setCacheUpdated(), updateCachedImage() and cache() were removed. Use invalidateCache() instead.
|
||||
|
||||
|
||||
QgsComposerMapGrid {#qgis_api_break_3_0_QgsComposerMapGrid}
|
||||
|
@ -122,7 +122,6 @@ core/composer/qgscomposeritemcommand.sip
|
||||
core/composer/qgscomposeritemgroup.sip
|
||||
core/composer/qgscomposerlabel.sip
|
||||
core/composer/qgscomposerlegend.sip
|
||||
core/composer/qgscomposermap.sip
|
||||
core/composer/qgscomposermapgrid.sip
|
||||
core/composer/qgscomposermapitem.sip
|
||||
core/composer/qgscomposermapoverview.sip
|
||||
|
@ -230,12 +230,14 @@ void QgsComposerItemWidget::on_mBackgroundColorButton_colorChanged( const QColor
|
||||
|
||||
//if the item is a composer map, we need to regenerate the map image
|
||||
//because it usually is cached
|
||||
QgsComposerMap *cm = dynamic_cast<QgsComposerMap *>( mItem );
|
||||
if ( cm )
|
||||
if ( QgsComposerMap *cm = qobject_cast<QgsComposerMap *>( mItem ) )
|
||||
{
|
||||
cm->cache();
|
||||
cm->invalidateCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
mItem->updateItem();
|
||||
}
|
||||
mItem->update();
|
||||
mItem->endCommand();
|
||||
}
|
||||
|
||||
@ -350,13 +352,14 @@ void QgsComposerItemWidget::on_mBackgroundGroupBox_toggled( bool state )
|
||||
|
||||
//if the item is a composer map, we need to regenerate the map image
|
||||
//because it usually is cached
|
||||
QgsComposerMap *cm = dynamic_cast<QgsComposerMap *>( mItem );
|
||||
if ( cm )
|
||||
if ( QgsComposerMap *cm = qobject_cast<QgsComposerMap *>( mItem ) )
|
||||
{
|
||||
cm->cache();
|
||||
cm->invalidateCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
mItem->updateItem();
|
||||
}
|
||||
|
||||
mItem->update();
|
||||
mItem->endCommand();
|
||||
}
|
||||
|
||||
|
@ -195,8 +195,7 @@ void QgsComposerMapWidget::followVisibilityPresetSelected( int currentIndex )
|
||||
mFollowVisibilityPresetCheckBox->setChecked( true );
|
||||
mComposerMap->setFollowVisibilityPresetName( presetName );
|
||||
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
void QgsComposerMapWidget::keepLayersVisibilityPresetSelected()
|
||||
@ -216,8 +215,7 @@ void QgsComposerMapWidget::keepLayersVisibilityPresetSelected()
|
||||
|
||||
mComposerMap->setLayerStyleOverrides( QgsProject::instance()->mapThemeCollection()->mapThemeStyleOverrides( presetName ) );
|
||||
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
@ -301,8 +299,7 @@ void QgsComposerMapWidget::mapCrsChanged( const QgsCoordinateReferenceSystem &cr
|
||||
if ( updateExtent )
|
||||
mComposerMap->zoomToExtent( newExtent );
|
||||
mComposerMap->endCommand();
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
void QgsComposerMapWidget::on_mAtlasCheckBox_toggled( bool checked )
|
||||
@ -369,8 +366,7 @@ void QgsComposerMapWidget::updateMapForAtlas()
|
||||
else
|
||||
{
|
||||
//redraw map
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
@ -466,8 +462,7 @@ void QgsComposerMapWidget::on_mPreviewModeComboBox_activated( int i )
|
||||
mUpdatePreviewButton->setEnabled( false );
|
||||
}
|
||||
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
void QgsComposerMapWidget::on_mScaleLineEdit_editingFinished()
|
||||
@ -503,8 +498,7 @@ void QgsComposerMapWidget::rotationChanged()
|
||||
mComposerMap->beginCommand( tr( "Map rotation changed" ), QgsComposerMergeCommand::ComposerMapRotation );
|
||||
mComposerMap->setMapRotation( mMapRotationSpinBox->value() );
|
||||
mComposerMap->endCommand();
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
void QgsComposerMapWidget::on_mSetToMapCanvasExtentButton_clicked()
|
||||
@ -869,9 +863,7 @@ void QgsComposerMapWidget::on_mUpdatePreviewButton_clicked()
|
||||
|
||||
mUpdatePreviewButton->setEnabled( false ); //prevent crashes because of many button clicks
|
||||
|
||||
mComposerMap->setCacheUpdated( false );
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
|
||||
mUpdatePreviewButton->setEnabled( true );
|
||||
}
|
||||
@ -891,8 +883,7 @@ void QgsComposerMapWidget::on_mFollowVisibilityPresetCheckBox_stateChanged( int
|
||||
mKeepLayerListCheckBox->setCheckState( Qt::Unchecked );
|
||||
mKeepLayerStylesCheckBox->setCheckState( Qt::Unchecked );
|
||||
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -924,7 +915,7 @@ void QgsComposerMapWidget::on_mKeepLayerListCheckBox_stateChanged( int state )
|
||||
else
|
||||
{
|
||||
mKeepLayerStylesCheckBox->setChecked( Qt::Unchecked );
|
||||
mComposerMap->updateCachedImage();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
mKeepLayerStylesCheckBox->setEnabled( state == Qt::Checked );
|
||||
@ -959,9 +950,7 @@ void QgsComposerMapWidget::on_mDrawCanvasItemsCheckBox_stateChanged( int state )
|
||||
mComposerMap->beginCommand( tr( "Canvas items toggled" ) );
|
||||
mComposerMap->setDrawAnnotations( state == Qt::Checked );
|
||||
mUpdatePreviewButton->setEnabled( false ); //prevent crashes because of many button clicks
|
||||
mComposerMap->setCacheUpdated( false );
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
mComposerMap->invalidateCache();
|
||||
mUpdatePreviewButton->setEnabled( true );
|
||||
mComposerMap->endCommand();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ void QgsAtlasComposition::updateAtlasMaps()
|
||||
continue;
|
||||
}
|
||||
|
||||
currentMap->cache();
|
||||
currentMap->invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +426,7 @@ bool QgsAtlasComposition::prepareForFeature( const int featureI, const bool upda
|
||||
{
|
||||
// map is not atlas driven, so manually force a redraw (to reflect possibly atlas
|
||||
// dependent symbology)
|
||||
( *mit )->cache();
|
||||
( *mit )->invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ QgsMapSettings QgsComposerMap::mapSettings( const QgsRectangle &extent, QSizeF s
|
||||
return jobMapSettings;
|
||||
}
|
||||
|
||||
void QgsComposerMap::cache()
|
||||
void QgsComposerMap::recreateCachedImageInBackground()
|
||||
{
|
||||
if ( mPreviewMode == Rectangle )
|
||||
{
|
||||
@ -286,6 +286,7 @@ void QgsComposerMap::cache()
|
||||
mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
|
||||
}
|
||||
|
||||
mCacheInvalidated = false;
|
||||
mPainter.reset( new QPainter( mCacheRenderingImage.get() ) );
|
||||
QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheRenderingImage->logicalDpiX() ) );
|
||||
mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) );
|
||||
@ -298,7 +299,6 @@ void QgsComposerMap::painterJobFinished()
|
||||
mPainter->end();
|
||||
mPainterJob.reset( nullptr );
|
||||
mPainter.reset( nullptr );
|
||||
mCacheUpdated = true;
|
||||
mCacheFinalImage = std::move( mCacheRenderingImage );
|
||||
mLastRenderedImageOffsetX = 0;
|
||||
mLastRenderedImageOffsetY = 0;
|
||||
@ -351,11 +351,17 @@ void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *,
|
||||
if ( !mPainterJob )
|
||||
{
|
||||
// this is the map's very first paint - trigger a cache update
|
||||
cache();
|
||||
recreateCachedImageInBackground();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mCacheInvalidated )
|
||||
{
|
||||
// cache was invalidated - trigger a background update
|
||||
recreateCachedImageInBackground();
|
||||
}
|
||||
|
||||
//Background color is already included in cached image, so no need to draw
|
||||
|
||||
double imagePixelWidth = mCacheFinalImage->width(); //how many pixels of the image are for the map extent?
|
||||
@ -436,6 +442,12 @@ void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *,
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
void QgsComposerMap::invalidateCache()
|
||||
{
|
||||
mCacheInvalidated = true;
|
||||
updateItem();
|
||||
}
|
||||
|
||||
int QgsComposerMap::numberExportLayers() const
|
||||
{
|
||||
return
|
||||
@ -495,26 +507,14 @@ bool QgsComposerMap::shouldDrawPart( PartType part ) const
|
||||
return true; // for Layer
|
||||
}
|
||||
|
||||
void QgsComposerMap::updateCachedImage()
|
||||
{
|
||||
mCacheUpdated = false;
|
||||
cache();
|
||||
update();
|
||||
}
|
||||
|
||||
void QgsComposerMap::renderModeUpdateCachedImage()
|
||||
{
|
||||
if ( mPreviewMode == Render )
|
||||
{
|
||||
updateCachedImage();
|
||||
invalidateCache();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsComposerMap::setCacheUpdated( bool u )
|
||||
{
|
||||
mCacheUpdated = u;
|
||||
}
|
||||
|
||||
QList<QgsMapLayer *> QgsComposerMap::layersToRender( const QgsExpressionContext *context ) const
|
||||
{
|
||||
QgsExpressionContext scopedContext = createExpressionContext();
|
||||
@ -635,8 +635,7 @@ void QgsComposerMap::moveContent( double dx, double dy )
|
||||
//in case data defined extents are set, these override the calculated values
|
||||
refreshMapExtents();
|
||||
|
||||
cache();
|
||||
update();
|
||||
invalidateCache();
|
||||
emit itemChanged();
|
||||
emit extentChanged();
|
||||
}
|
||||
@ -709,8 +708,7 @@ void QgsComposerMap::zoomContent( const double factor, const QPointF point, cons
|
||||
//recalculate data defined scale and extents, since that may override zoom
|
||||
refreshMapExtents();
|
||||
|
||||
cache();
|
||||
update();
|
||||
invalidateCache();
|
||||
emit itemChanged();
|
||||
emit extentChanged();
|
||||
}
|
||||
@ -729,10 +727,8 @@ void QgsComposerMap::setSceneRect( const QRectF &rectangle )
|
||||
|
||||
//recalculate data defined scale and extents
|
||||
refreshMapExtents();
|
||||
mCacheUpdated = false;
|
||||
|
||||
updateBoundingRect();
|
||||
updateItem();
|
||||
invalidateCache();
|
||||
emit itemChanged();
|
||||
emit extentChanged();
|
||||
}
|
||||
@ -796,8 +792,7 @@ void QgsComposerMap::zoomToExtent( const QgsRectangle &extent )
|
||||
//recalculate data defined scale and extents, since that may override extent
|
||||
refreshMapExtents();
|
||||
|
||||
mCacheUpdated = false;
|
||||
updateItem();
|
||||
invalidateCache();
|
||||
emit itemChanged();
|
||||
emit extentChanged();
|
||||
}
|
||||
@ -836,9 +831,8 @@ void QgsComposerMap::setNewAtlasFeatureExtent( const QgsRectangle &extent )
|
||||
//recalculate data defined scale and extents, since that may override extents
|
||||
refreshMapExtents();
|
||||
|
||||
mCacheUpdated = false;
|
||||
emit preparedForAtlas();
|
||||
updateItem();
|
||||
invalidateCache();
|
||||
emit itemChanged();
|
||||
emit extentChanged();
|
||||
}
|
||||
@ -913,11 +907,9 @@ void QgsComposerMap::setNewScale( double scaleDenominator, bool forceUpdate )
|
||||
mExtent.scale( scaleRatio );
|
||||
}
|
||||
|
||||
mCacheUpdated = false;
|
||||
invalidateCache();
|
||||
if ( forceUpdate )
|
||||
{
|
||||
cache();
|
||||
update();
|
||||
emit itemChanged();
|
||||
}
|
||||
emit extentChanged();
|
||||
@ -939,9 +931,9 @@ void QgsComposerMap::setMapRotation( double r )
|
||||
{
|
||||
mMapRotation = r;
|
||||
mEvaluatedMapRotation = mMapRotation;
|
||||
invalidateCache();
|
||||
emit mapRotationChanged( r );
|
||||
emit itemChanged();
|
||||
update();
|
||||
}
|
||||
|
||||
double QgsComposerMap::mapRotation( QgsComposerObject::PropertyValueType valueType ) const
|
||||
@ -1078,21 +1070,6 @@ void QgsComposerMap::refreshMapExtents( const QgsExpressionContext *context )
|
||||
mEvaluatedMapRotation = mapRotation;
|
||||
emit mapRotationChanged( mapRotation );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QgsComposerMap::updateItem()
|
||||
{
|
||||
if ( !updatesEnabled() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mPreviewMode != QgsComposerMap::Rectangle && !mCacheUpdated )
|
||||
{
|
||||
cache();
|
||||
}
|
||||
QgsComposerItem::updateItem();
|
||||
}
|
||||
|
||||
bool QgsComposerMap::containsWmsLayer() const
|
||||
@ -1182,7 +1159,7 @@ void QgsComposerMap::connectUpdateSlot()
|
||||
connect( project, &QgsProject::layersRemoved, this, &QgsComposerMap::renderModeUpdateCachedImage );
|
||||
connect( project, &QgsProject::legendLayersAdded, this, &QgsComposerMap::renderModeUpdateCachedImage );
|
||||
}
|
||||
connect( mComposition, &QgsComposition::refreshItemsTriggered, this, &QgsComposerMap::updateCachedImage );
|
||||
connect( mComposition, &QgsComposition::refreshItemsTriggered, this, &QgsComposerMap::invalidateCache );
|
||||
}
|
||||
|
||||
bool QgsComposerMap::writeXml( QDomElement &elem, QDomDocument &doc ) const
|
||||
@ -1448,7 +1425,7 @@ bool QgsComposerMap::readXml( const QDomElement &itemElem, const QDomDocument &d
|
||||
|
||||
mDrawing = false;
|
||||
mNumCachedLayers = 0;
|
||||
mCacheUpdated = false;
|
||||
mCacheInvalidated = true;
|
||||
|
||||
//overviews
|
||||
mOverviewStack->readXml( itemElem, doc );
|
||||
@ -1870,7 +1847,7 @@ void QgsComposerMap::refreshDataDefinedProperty( const QgsComposerObject::DataDe
|
||||
}
|
||||
|
||||
//force redraw
|
||||
mCacheUpdated = false;
|
||||
mCacheInvalidated = true;
|
||||
|
||||
QgsComposerItem::refreshDataDefinedProperty( property, evalContext );
|
||||
}
|
||||
|
@ -99,9 +99,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
//! \brief Reimplementation of QCanvasItem::paint - draw on canvas
|
||||
void paint( QPainter *painter, const QStyleOptionGraphicsItem *itemStyle, QWidget *pWidget ) override;
|
||||
|
||||
//! \brief Create cache image
|
||||
void cache();
|
||||
|
||||
/** Return map settings that would be used for drawing of the map
|
||||
* \since QGIS 2.6 */
|
||||
QgsMapSettings mapSettings( const QgsRectangle &extent, QSizeF size, int dpi ) const;
|
||||
@ -279,9 +276,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
* \since QGIS 2.16 */
|
||||
void setFollowVisibilityPresetName( const QString &name ) { mFollowVisibilityPresetName = name; }
|
||||
|
||||
// Set cache outdated
|
||||
void setCacheUpdated( bool u = false );
|
||||
|
||||
QgsRectangle extent() const {return mExtent;}
|
||||
|
||||
//! Sets offset values to shift image (useful for live updates when moving item content)
|
||||
@ -355,8 +349,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
*/
|
||||
double mapRotation( QgsComposerObject::PropertyValueType valueType = QgsComposerObject::EvaluatedValue ) const;
|
||||
|
||||
void updateItem() override;
|
||||
|
||||
/**
|
||||
* Sets whether annotations are drawn within the composer map.
|
||||
* \see drawAnnotations()
|
||||
@ -476,8 +468,11 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
|
||||
public slots:
|
||||
|
||||
//! Forces an update of the cached map image
|
||||
void updateCachedImage();
|
||||
/**
|
||||
* Forces a deferred update of the cached map image on next paint.
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
void invalidateCache();
|
||||
|
||||
/** Updates the cached map image if the map is set to Render mode
|
||||
* \see updateCachedImage
|
||||
@ -526,8 +521,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
std::unique_ptr< QImage > mCacheFinalImage;
|
||||
std::unique_ptr< QImage > mCacheRenderingImage;
|
||||
|
||||
// Is cache up to date
|
||||
bool mCacheUpdated = false;
|
||||
//! True if cached map image must be recreated
|
||||
bool mCacheInvalidated = true;
|
||||
|
||||
//! \brief Preview style
|
||||
PreviewMode mPreviewMode = QgsComposerMap::Cache;
|
||||
@ -572,6 +567,9 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
||||
* is true. May be overridden by data-defined expression. */
|
||||
QString mFollowVisibilityPresetName;
|
||||
|
||||
//! \brief Create cache image
|
||||
void recreateCachedImage();
|
||||
|
||||
//! Establishes signal/slot connection for update in case of layer change
|
||||
void connectUpdateSlot();
|
||||
|
||||
|
@ -311,11 +311,11 @@ void QgsComposerMapOverview::overviewExtentChanged()
|
||||
mComposerMap->refreshDataDefinedProperty( QgsComposerObject::MapScale );
|
||||
|
||||
//must invalidate cache so that map gets redrawn
|
||||
mComposerMap->cache();
|
||||
mComposerMap->invalidateCache();
|
||||
}
|
||||
|
||||
//repaint map so that overview gets updated
|
||||
mComposerMap->update();
|
||||
mComposerMap->updateItem();
|
||||
}
|
||||
|
||||
|
||||
|
@ -2059,10 +2059,9 @@ void QgsComposerView::wheelZoom( QWheelEvent *event )
|
||||
QList<QGraphicsItem *>::iterator itemIt = itemList.begin();
|
||||
for ( ; itemIt != itemList.end(); ++itemIt )
|
||||
{
|
||||
QgsComposerMap *mypItem = dynamic_cast<QgsComposerMap *>( *itemIt );
|
||||
if ( ( mypItem ) && ( mypItem->previewMode() == QgsComposerMap::Render ) )
|
||||
if ( QgsComposerMap *mypItem = qobject_cast<QgsComposerMap *>( *itemIt ) )
|
||||
{
|
||||
mypItem->updateCachedImage();
|
||||
mypItem->invalidateCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user