Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Do map rendering inside of QgsMapCanvas
QgsMapCanvasMap is now just a simple map canvas item storing an image,
all rendering logic has been moved to QgsMapCanvas.
Restored functionality of map decorations and cancellation of rendering.
When map is going to be refreshed, the old rendered map stays visible
for a small amount of time (scaled) and then it is replaced by the new map.
  • Loading branch information
wonder-sk committed Nov 15, 2013
1 parent d49f7ac commit 1110aaf
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 196 deletions.
4 changes: 3 additions & 1 deletion src/core/qgsmaprendererjob.cpp
Expand Up @@ -57,6 +57,7 @@ void QgsMapRendererSequentialJob::cancel()
{
if (mInternalJob)
{
qDebug("sequential - cancel internal");
mInternalJob->cancel();
delete mInternalJob;
mInternalJob = 0;
Expand Down Expand Up @@ -132,7 +133,6 @@ void QgsMapRendererCustomPainterJob::start()
mFutureWatcher.setFuture(mFuture);
}

#include <QApplication>

void QgsMapRendererCustomPainterJob::cancel()
{
Expand All @@ -154,6 +154,8 @@ void QgsMapRendererCustomPainterJob::cancel()

qDebug("QPAINTER cancelled");
}
else
qDebug("QPAINTER not running!");
}

void QgsMapRendererCustomPainterJob::waitForFinished()
Expand Down
117 changes: 92 additions & 25 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -48,6 +48,7 @@ email : sherman at mrcc.com
#include "qgsmaptopixel.h"
#include "qgsmapoverviewcanvas.h"
#include "qgsmaprenderer.h"
#include "qgsmaprendererjob.h"
#include "qgsmessagelog.h"
#include "qgsmessageviewer.h"
#include "qgspallabeling.h"
Expand All @@ -56,6 +57,7 @@ email : sherman at mrcc.com
#include "qgsvectorlayer.h"
#include <math.h>


/** @deprecated to be deleted, stuff from here should be moved elsewhere */
class QgsMapCanvas::CanvasProperties
{
Expand All @@ -82,9 +84,9 @@ class QgsMapCanvas::CanvasProperties
QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
: QGraphicsView( parent )
, mCanvasProperties( new CanvasProperties )
, mJob( 0 )
, mJobCancelled( false )
, mLabelingResults( 0 )
//, mNewSize( QSize() )
//, mPainting( false )
{
setObjectName( name );
mScene = new QGraphicsScene();
Expand Down Expand Up @@ -113,7 +115,6 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
// create map canvas item which will show the map
mMap = new QgsMapCanvasMap( this );
mScene->addItem( mMap );
mScene->update(); // porting??

connect( mMapRenderer, SIGNAL( drawError( QgsMapLayer* ) ), this, SLOT( showError( QgsMapLayer* ) ) );

Expand All @@ -129,12 +130,14 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
mSettings.setFlag( QgsMapSettings::DrawEditingInfo );

mSettings.setOutputSize( size() );
mMap->resize( size() );
setSceneRect( 0, 0, size().width(), size().height() );
mScene->setSceneRect( QRectF( 0, 0, size().width(), size().height() ) );

moveCanvasContents( true );

connect(&mMapUpdateTimer, SIGNAL( timeout() ), SLOT( mapUpdateTimeout() ) );
mMapUpdateTimer.setInterval( 400 );

#ifdef Q_OS_WIN
// Enable touch event on Windows.
// Qt on Windows needs to be told it can take touch events or else it ignores them.
Expand Down Expand Up @@ -171,6 +174,12 @@ QgsMapCanvas::~QgsMapCanvas()
// mCanvasProperties auto-deleted via std::auto_ptr
// CanvasProperties struct has its own dtor for freeing resources

if ( mJob )
{
mJob->cancel();
Q_ASSERT( mJob == 0 );
}

delete mLabelingResults;

} // dtor
Expand Down Expand Up @@ -221,7 +230,8 @@ double QgsMapCanvas::scale()

void QgsMapCanvas::setDirty( bool dirty )
{
mDirty = dirty;
if ( dirty )
refresh();
}

bool QgsMapCanvas::isDirty() const
Expand All @@ -233,7 +243,7 @@ bool QgsMapCanvas::isDirty() const

bool QgsMapCanvas::isDrawing()
{
return false;
return mJob != 0;
} // isDrawing


Expand Down Expand Up @@ -399,12 +409,6 @@ const QgsLabelingResults *QgsMapCanvas::labelingResults() const
return mLabelingResults;
}

void QgsMapCanvas::assignLabelingResults( QgsLabelingResults* results )
{
delete mLabelingResults;
mLabelingResults = results;
}


void QgsMapCanvas::updateOverview()
{
Expand All @@ -424,7 +428,11 @@ QgsMapLayer* QgsMapCanvas::currentLayer()

void QgsMapCanvas::refresh()
{
mMap->refresh();
stopRendering(); // if any...

qDebug("CANVAS calling update");
mDirty = true;
update();

/*
// we can't draw again if already drawing...
Expand Down Expand Up @@ -478,9 +486,51 @@ void QgsMapCanvas::refresh()

} // refresh


void QgsMapCanvas::rendererJobFinished()
{
qDebug("CANVAS finish! %d", !mJobCancelled );

mMapUpdateTimer.stop();

mDirty = false;

if ( !mJobCancelled )
{
QImage img = mJob->renderedImage();

// emit renderComplete to get our decorations drawn
QPainter p( &img );
emit renderComplete( &p );
p.end();

mMap->setContent( img, mSettings.visibleExtent() );

delete mLabelingResults;
mLabelingResults = mJob->takeLabelingResults();
}

delete mJob;
mJob = 0;
}

void QgsMapCanvas::mapUpdateTimeout()
{
qDebug("CANVAS update timer!");

mMap->setContent( mJob->renderedImage(), mSettings.visibleExtent() );
}


void QgsMapCanvas::stopRendering()
{
// TODO: implement stopping (?)
if ( mJob )
{
qDebug("CANVAS stop rendering!");
mJobCancelled = true;
mJob->cancel();
Q_ASSERT( mJob == 0 ); // no need to delete here: already deleted in finished()
}
}

void QgsMapCanvas::updateMap()
Expand All @@ -507,11 +557,11 @@ void QgsMapCanvas::saveAsImage( QString theFileName, QPixmap * theQPixmap, QStri
else //use the map view
{
// TODO[MD]: fix
QPixmap *pixmap = dynamic_cast<QPixmap *>( &mMap->paintDevice() );
if ( !pixmap )
QImage *img = dynamic_cast<QImage *>( &mMap->paintDevice() );
if ( !img)
return;

pixmap->save( theFileName, theFormat.toLocal8Bit().data() );
img->save( theFileName, theFormat.toLocal8Bit().data() );
}
//create a world file to go with the image...
QgsRectangle myRect = mapSettings().visibleExtent();
Expand Down Expand Up @@ -611,9 +661,7 @@ void QgsMapCanvas::updateScale()

void QgsMapCanvas::clear()
{
// Indicate to the next paint event that we need to rebuild the canvas contents
setDirty( true );

refresh();
} // clear


Expand Down Expand Up @@ -985,9 +1033,6 @@ void QgsMapCanvas::resizeEvent( QResizeEvent * e )

mSettings.setOutputSize( lastSize );

//set map size before scene size helps keep scene indexes updated properly
// this was the cause of rubberband artifacts
mMap->resize( lastSize );
mScene->setSceneRect( QRectF( 0, 0, lastSize.width(), lastSize.height() ) );

moveCanvasContents( true );
Expand All @@ -1004,6 +1049,30 @@ void QgsMapCanvas::resizeEvent( QResizeEvent * e )

void QgsMapCanvas::paintEvent( QPaintEvent *e )
{
qDebug("CANVAS paint()");

if ( mDirty )
{
if ( mJob )
{
qDebug("CANVAS already rendering");
}
else
{
qDebug("CANVAS need to render");

// create the renderer job
Q_ASSERT( mJob == 0 );
mJobCancelled = false;
mJob = new QgsMapRendererSequentialJob( mSettings );
connect(mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
mJob->start();

mMapUpdateTimer.start();
}
}


QGraphicsView::paintEvent( e );
} // paintEvent

Expand Down Expand Up @@ -1312,8 +1381,6 @@ void QgsMapCanvas::panActionEnd( QPoint releasePoint )
// move map image and other items to standard position
moveCanvasContents( true ); // true means reset

mMap->mapDragged( releasePoint - mCanvasProperties->rubberStartPoint );

// use start and end box points to calculate the extent
QgsPoint start = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->rubberStartPoint );
QgsPoint end = getCoordinateTransform()->toMapCoordinates( releasePoint );
Expand Down
50 changes: 27 additions & 23 deletions src/gui/qgsmapcanvas.h
Expand Up @@ -60,6 +60,7 @@ class QgsVectorLayer;

class QgsLabelingResults;
class QgsMapRenderer;
class QgsMapRendererSequentialJob;
class QgsMapSettings;
class QgsMapCanvasMap;
class QgsMapOverviewCanvas;
Expand Down Expand Up @@ -136,11 +137,6 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! @note added in 2.1
const QgsLabelingResults* labelingResults() const;

//! Store newly generated labeling results (may be null) and take ownership of the object.
//! Only meant for communication with QgsMapCanvasMap
//! @note added in 2.1
void assignLabelingResults( QgsLabelingResults* results );

//! @deprecated since 2.1 - there could be more than just one "map" items
QgsMapCanvasMap* map();

Expand All @@ -155,7 +151,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
double scale();

//! Clear the map canvas
void clear();
//! @deprecated since 2.1 - use refresh() - clear does the same thing
Q_DECL_DEPRECATED void clear();

//! Returns the mapUnitsPerPixel (map units per pixel) for the canvas
double mapUnitsPerPixel() const;
Expand Down Expand Up @@ -237,7 +234,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
bool isFrozen();

//! Flag the canvas as dirty and needed a refresh
void setDirty( bool _dirty );
//! @deprecated since 2.1 - use refresh() to trigger a refresh (clients should not decide explicitly whether canvas is dirty or not)
Q_DECL_DEPRECATED void setDirty( bool _dirty );

//! Return the state of the canvas (dirty or not)
bool isDirty() const;
Expand All @@ -251,7 +249,7 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! Get the current coordinate transform
const QgsMapToPixel* getCoordinateTransform();

//! @deprecated in 2.1 - always returns false
//! Find out whether rendering is in progress
bool isDrawing();

//! returns current layer (set by legend widget)
Expand Down Expand Up @@ -325,9 +323,9 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! @deprecated in 2.1 - does nothing - kept for API compatibility
Q_DECL_DEPRECATED void updateMap();

//! added in 2.1
//! @note probably it is not necessary to allow any client to stop rendering - should be handled just be canvas
Q_DECL_DEPRECATED void stopRendering();
//! stop rendering (if there is any right now)
//! @note added in 2.1
void stopRendering();

//! show whatever error is exposed by the QgsMapLayer.
void showError( QgsMapLayer * mapLayer );
Expand All @@ -342,6 +340,11 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! called when current maptool is destroyed
void mapToolDestroyed();

//! called when a renderer job has finished successfully or when it was cancelled
void rendererJobFinished();

void mapUpdateTimeout();

signals:
/** Let the owner know how far we are with render operations */
//! @deprecated since 2.1 - already unused in 2.0 anyway
Expand All @@ -365,9 +368,10 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
being rendered onto a pixmap other than the mapCanvas own pixmap member.
*/
//! @deprecated since 2.1 - anything related to rendering progress is not visible outside of map canvas
//! TODO: deprecate when decorations are reimplemented as map canvas items
//! - anything related to rendering progress is not visible outside of map canvas
//! - additional drawing shall be done directly within the renderer job or independently as a map canvas item
Q_DECL_DEPRECATED void renderComplete( QPainter * );
void renderComplete( QPainter * );

/** Emitted when canvas finished a refresh request.
\note Added in 2.0 */
Expand Down Expand Up @@ -501,11 +505,6 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! determines whether user has requested to suppress rendering
bool mRenderFlag;

/**Resize events that have been ignored because the canvas is busy with
rendering may put their sizes into this list. The canvas then picks up
the last entry in case a lot of resize events arrive in short time*/
QList< QPair<int, int> > mResizeQueue;

//! current layer in legend
QgsMapLayer* mCurrentLayer;

Expand All @@ -528,13 +527,18 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
//! Mouse wheel action
WheelAction mWheelAction;

QgsLabelingResults* mLabelingResults;
//! Timer that periodically fires while map rendering is in progress to update the visible map
QTimer mMapUpdateTimer;

//! Job that takes care of map rendering in background
QgsMapRendererSequentialJob* mJob;

//! resize canvas size
//QSize mNewSize;
//! Flag determining whether the active job has been cancelled
bool mJobCancelled;

//! Labeling results from the recently rendered map
QgsLabelingResults* mLabelingResults;

//! currently in paint event
//bool mPainting;
}; // class QgsMapCanvas


Expand Down

0 comments on commit 1110aaf

Please sign in to comment.