mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-01 00:03:42 -05:00
Merge pull request #4510 from qgis/revert-4494-composer_async
Revert "Asyncronously render composer map previews "
This commit is contained in:
commit
ddbb1702ba
@ -115,16 +115,9 @@ QgsComposerMap::~QgsComposerMap()
|
|||||||
{
|
{
|
||||||
delete mOverviewStack;
|
delete mOverviewStack;
|
||||||
delete mGridStack;
|
delete mGridStack;
|
||||||
|
|
||||||
if ( mPainterJob )
|
|
||||||
{
|
|
||||||
disconnect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsComposerMap::painterJobFinished );
|
|
||||||
mPainterJob->cancel();
|
|
||||||
mPainter->end();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called by paint() to render the map. It does not override any functions
|
/* This function is called by paint() and cache() to render the map. It does not override any functions
|
||||||
from QGraphicsItem. */
|
from QGraphicsItem. */
|
||||||
void QgsComposerMap::draw( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi, double *forceWidthScale )
|
void QgsComposerMap::draw( QPainter *painter, const QgsRectangle &extent, QSizeF size, double dpi, double *forceWidthScale )
|
||||||
{
|
{
|
||||||
@ -213,28 +206,12 @@ void QgsComposerMap::cache()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mPainterJob )
|
if ( mDrawing )
|
||||||
{
|
{
|
||||||
disconnect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsComposerMap::painterJobFinished );
|
return;
|
||||||
QgsMapRendererCustomPainterJob *oldJob = mPainterJob.release();
|
|
||||||
QPainter *oldPainter = mPainter.release();
|
|
||||||
QImage *oldImage = mCacheRenderingImage.release();
|
|
||||||
connect( oldJob, &QgsMapRendererCustomPainterJob::finished, this, [oldPainter, oldJob, oldImage]
|
|
||||||
{
|
|
||||||
oldJob->deleteLater();
|
|
||||||
delete oldPainter;
|
|
||||||
delete oldImage;
|
|
||||||
} );
|
|
||||||
oldJob->cancelWithoutBlocking();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mCacheRenderingImage.reset( nullptr );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT( !mPainterJob );
|
mDrawing = true;
|
||||||
Q_ASSERT( !mPainter );
|
|
||||||
Q_ASSERT( !mCacheRenderingImage );
|
|
||||||
|
|
||||||
double horizontalVScaleFactor = horizontalViewScaleFactor();
|
double horizontalVScaleFactor = horizontalViewScaleFactor();
|
||||||
if ( horizontalVScaleFactor < 0 )
|
if ( horizontalVScaleFactor < 0 )
|
||||||
@ -265,51 +242,38 @@ void QgsComposerMap::cache()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( w <= 0 || h <= 0 )
|
mCacheImage = QImage( w, h, QImage::Format_ARGB32 );
|
||||||
return;
|
|
||||||
|
|
||||||
mCacheRenderingImage.reset( new QImage( w, h, QImage::Format_ARGB32 ) );
|
|
||||||
|
|
||||||
// set DPI of the image
|
// set DPI of the image
|
||||||
mCacheRenderingImage->setDotsPerMeterX( 1000 * w / widthMM );
|
mCacheImage.setDotsPerMeterX( 1000 * w / widthMM );
|
||||||
mCacheRenderingImage->setDotsPerMeterY( 1000 * h / heightMM );
|
mCacheImage.setDotsPerMeterY( 1000 * h / heightMM );
|
||||||
|
|
||||||
if ( hasBackground() )
|
if ( hasBackground() )
|
||||||
{
|
{
|
||||||
//Initially fill image with specified background color. This ensures that layers with blend modes will
|
//Initially fill image with specified background color. This ensures that layers with blend modes will
|
||||||
//preview correctly
|
//preview correctly
|
||||||
mCacheRenderingImage->fill( backgroundColor().rgba() );
|
mCacheImage.fill( backgroundColor().rgba() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//no background, but start with empty fill to avoid artifacts
|
//no background, but start with empty fill to avoid artifacts
|
||||||
mCacheRenderingImage->fill( QColor( 255, 255, 255, 0 ).rgba() );
|
mCacheImage.fill( QColor( 255, 255, 255, 0 ).rgba() );
|
||||||
}
|
}
|
||||||
|
|
||||||
mPainter.reset( new QPainter( mCacheRenderingImage.get() ) );
|
QPainter p( &mCacheImage );
|
||||||
QgsMapSettings settings( mapSettings( ext, QSizeF( w, h ), mCacheRenderingImage->logicalDpiX() ) );
|
|
||||||
mPainterJob.reset( new QgsMapRendererCustomPainterJob( settings, mPainter.get() ) );
|
|
||||||
connect( mPainterJob.get(), &QgsMapRendererCustomPainterJob::finished, this, &QgsComposerMap::painterJobFinished );
|
|
||||||
mPainterJob->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsComposerMap::painterJobFinished()
|
draw( &p, ext, QSizeF( w, h ), mCacheImage.logicalDpiX() );
|
||||||
{
|
p.end();
|
||||||
mPainter->end();
|
|
||||||
mPainterJob.reset( nullptr );
|
|
||||||
mPainter.reset( nullptr );
|
|
||||||
mCacheUpdated = true;
|
mCacheUpdated = true;
|
||||||
mCacheFinalImage = std::move( mCacheRenderingImage );
|
|
||||||
mLastRenderedImageOffsetX = 0;
|
mDrawing = false;
|
||||||
mLastRenderedImageOffsetY = 0;
|
|
||||||
updateItem();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *pWidget )
|
void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *pWidget )
|
||||||
{
|
{
|
||||||
Q_UNUSED( pWidget );
|
Q_UNUSED( pWidget );
|
||||||
|
|
||||||
if ( !mComposition || !painter || !painter->device() )
|
if ( !mComposition || !painter )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -319,9 +283,6 @@ void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
|
QRectF thisPaintRect = QRectF( 0, 0, QGraphicsRectItem::rect().width(), QGraphicsRectItem::rect().height() );
|
||||||
if ( thisPaintRect.width() == 0 || thisPaintRect.height() == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setClipRect( thisPaintRect );
|
painter->setClipRect( thisPaintRect );
|
||||||
|
|
||||||
@ -336,40 +297,22 @@ void QgsComposerMap::paint( QPainter *painter, const QStyleOptionGraphicsItem *,
|
|||||||
}
|
}
|
||||||
else if ( mComposition->plotStyle() == QgsComposition::Preview )
|
else if ( mComposition->plotStyle() == QgsComposition::Preview )
|
||||||
{
|
{
|
||||||
if ( !mCacheFinalImage || mCacheFinalImage->isNull() )
|
if ( mCacheImage.isNull() )
|
||||||
{
|
cache();
|
||||||
// No initial render available - so draw some preview text alerting user
|
|
||||||
drawBackground( painter );
|
|
||||||
painter->setBrush( QBrush( QColor( 125, 125, 125, 125 ) ) );
|
|
||||||
painter->drawRect( thisPaintRect );
|
|
||||||
painter->setBrush( Qt::NoBrush );
|
|
||||||
QFont messageFont;
|
|
||||||
messageFont.setPointSize( 12 );
|
|
||||||
painter->setFont( messageFont );
|
|
||||||
painter->setPen( QColor( 255, 255, 255, 255 ) );
|
|
||||||
painter->drawText( thisPaintRect, Qt::AlignCenter | Qt::AlignHCenter, tr( "Rendering map" ) );
|
|
||||||
if ( !mPainterJob )
|
|
||||||
{
|
|
||||||
// this is the map's very first paint - trigger a cache update
|
|
||||||
cache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//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?
|
//Background color is already included in cached image, so no need to draw
|
||||||
double scale = rect().width() / imagePixelWidth;
|
|
||||||
|
|
||||||
painter->save();
|
double imagePixelWidth = mCacheImage.width(); //how many pixels of the image are for the map extent?
|
||||||
|
double scale = rect().width() / imagePixelWidth;
|
||||||
|
|
||||||
painter->translate( mLastRenderedImageOffsetX + mXOffset, mLastRenderedImageOffsetY + mYOffset );
|
painter->save();
|
||||||
painter->scale( scale, scale );
|
|
||||||
painter->drawImage( 0, 0, *mCacheFinalImage );
|
|
||||||
|
|
||||||
//restore rotation
|
painter->translate( mXOffset, mYOffset );
|
||||||
painter->restore();
|
painter->scale( scale, scale );
|
||||||
}
|
painter->drawImage( 0, 0, mCacheImage );
|
||||||
|
|
||||||
|
//restore rotation
|
||||||
|
painter->restore();
|
||||||
}
|
}
|
||||||
else if ( mComposition->plotStyle() == QgsComposition::Print ||
|
else if ( mComposition->plotStyle() == QgsComposition::Print ||
|
||||||
mComposition->plotStyle() == QgsComposition::Postscript )
|
mComposition->plotStyle() == QgsComposition::Postscript )
|
||||||
@ -622,8 +565,6 @@ void QgsComposerMap::resize( double dx, double dy )
|
|||||||
|
|
||||||
void QgsComposerMap::moveContent( double dx, double dy )
|
void QgsComposerMap::moveContent( double dx, double dy )
|
||||||
{
|
{
|
||||||
mLastRenderedImageOffsetX -= dx;
|
|
||||||
mLastRenderedImageOffsetY -= dy;
|
|
||||||
if ( !mDrawing )
|
if ( !mDrawing )
|
||||||
{
|
{
|
||||||
transformShift( dx, dy );
|
transformShift( dx, dy );
|
||||||
@ -732,7 +673,7 @@ void QgsComposerMap::setSceneRect( const QRectF &rectangle )
|
|||||||
mCacheUpdated = false;
|
mCacheUpdated = false;
|
||||||
|
|
||||||
updateBoundingRect();
|
updateBoundingRect();
|
||||||
updateItem();
|
update();
|
||||||
emit itemChanged();
|
emit itemChanged();
|
||||||
emit extentChanged();
|
emit extentChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,6 @@ class QgsFillSymbol;
|
|||||||
class QgsLineSymbol;
|
class QgsLineSymbol;
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
class QgsAnnotation;
|
class QgsAnnotation;
|
||||||
class QgsMapRendererCustomPainterJob;
|
|
||||||
|
|
||||||
/** \ingroup core
|
/** \ingroup core
|
||||||
* \class QgsComposerMap
|
* \class QgsComposerMap
|
||||||
@ -492,8 +491,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
|||||||
private slots:
|
private slots:
|
||||||
void layersAboutToBeRemoved( QList<QgsMapLayer *> layers );
|
void layersAboutToBeRemoved( QList<QgsMapLayer *> layers );
|
||||||
|
|
||||||
void painterJobFinished();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//! Unique identifier
|
//! Unique identifier
|
||||||
@ -516,15 +513,8 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
|||||||
// to manually tweak each atlas preview page without affecting the actual original map extent.
|
// to manually tweak each atlas preview page without affecting the actual original map extent.
|
||||||
QgsRectangle mAtlasFeatureExtent;
|
QgsRectangle mAtlasFeatureExtent;
|
||||||
|
|
||||||
// We have two images used for rendering/storing cached map images.
|
// Cache used in composer preview
|
||||||
// the first (mCacheFinalImage) is used ONLY for storing the most recent completed map render. It's always
|
QImage mCacheImage;
|
||||||
// used when drawing map item previews. The second (mCacheRenderingImage) is used temporarily while
|
|
||||||
// rendering a new preview image in the background. If (and only if) the background render completes, then
|
|
||||||
// mCacheRenderingImage is pushed into mCacheFinalImage, and used from then on when drawing the item preview.
|
|
||||||
// This ensures that something is always shown in the map item, even while refreshing the preview image in the
|
|
||||||
// background
|
|
||||||
std::unique_ptr< QImage > mCacheFinalImage;
|
|
||||||
std::unique_ptr< QImage > mCacheRenderingImage;
|
|
||||||
|
|
||||||
// Is cache up to date
|
// Is cache up to date
|
||||||
bool mCacheUpdated = false;
|
bool mCacheUpdated = false;
|
||||||
@ -543,9 +533,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
|||||||
//! Offset in y direction for showing map cache image
|
//! Offset in y direction for showing map cache image
|
||||||
double mYOffset = 0.0;
|
double mYOffset = 0.0;
|
||||||
|
|
||||||
double mLastRenderedImageOffsetX = 0.0;
|
|
||||||
double mLastRenderedImageOffsetY = 0.0;
|
|
||||||
|
|
||||||
//! Map rotation
|
//! Map rotation
|
||||||
double mMapRotation = 0;
|
double mMapRotation = 0;
|
||||||
|
|
||||||
@ -600,10 +587,6 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
|
|||||||
//! Margin size for atlas driven extents (percentage of feature size) - when in auto scaling mode
|
//! Margin size for atlas driven extents (percentage of feature size) - when in auto scaling mode
|
||||||
double mAtlasMargin = 0.10;
|
double mAtlasMargin = 0.10;
|
||||||
|
|
||||||
std::unique_ptr< QPainter > mPainter;
|
|
||||||
std::unique_ptr< QgsMapRendererCustomPainterJob > mPainterJob;
|
|
||||||
bool mPainterCancelWait = false;
|
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
//! Resets the item tooltip to reflect current map id
|
//! Resets the item tooltip to reflect current map id
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from qgis.PyQt.QtCore import QRect, QRectF, QSize, QSizeF, qDebug, QThreadPool
|
from qgis.PyQt.QtCore import QRect, QRectF, QSize, QSizeF, qDebug
|
||||||
from qgis.PyQt.QtGui import QImage, QColor, QPainter
|
from qgis.PyQt.QtGui import QImage, QColor, QPainter
|
||||||
from qgis.PyQt.QtPrintSupport import QPrinter
|
from qgis.PyQt.QtPrintSupport import QPrinter
|
||||||
from qgis.PyQt.QtSvg import QSvgRenderer, QSvgGenerator
|
from qgis.PyQt.QtSvg import QSvgRenderer, QSvgGenerator
|
||||||
@ -88,8 +88,6 @@ class TestComposerBase(TestQgsPalLabeling):
|
|||||||
TestQgsPalLabeling.tearDownClass()
|
TestQgsPalLabeling.tearDownClass()
|
||||||
cls.removeMapLayer(cls.layer)
|
cls.removeMapLayer(cls.layer)
|
||||||
cls.layer = None
|
cls.layer = None
|
||||||
# avoid crash on finish, probably related to https://bugreports.qt.io/browse/QTBUG-35760
|
|
||||||
QThreadPool.globalInstance().waitForDone()
|
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Run before each test."""
|
"""Run before each test."""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user