Skip to content

Commit

Permalink
Avoid possible crash in rendering loop
Browse files Browse the repository at this point in the history
As soon as QgsMapLayer::setCacheImage is called while rendering is active, a crash occurs.
Due to the fact, that processEvents is called from the main rendering loop, such situations cannot always be foreseen.
  • Loading branch information
m-kuhn committed Apr 3, 2013
1 parent 80f7b5a commit 45cd49d
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/app/qgsfieldsproperties.cpp
Expand Up @@ -103,6 +103,7 @@ void QgsAttributesTree::dragMoveEvent( QDragMoveEvent *event )

bool QgsAttributesTree::dropMimeData( QTreeWidgetItem * parent, int index, const QMimeData * data, Qt::DropAction action )
{
Q_UNUSED( index )
bool bDropSuccessful = false;

if ( action == Qt::IgnoreAction )
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsmaplayer.cpp
Expand Up @@ -1249,6 +1249,7 @@ void QgsMapLayer::setCacheImage( QImage * thepImage )

if ( mpCacheImage )
{
onCacheImageDelete();
delete mpCacheImage;
}
mpCacheImage = thepImage;
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsmaplayer.h
Expand Up @@ -331,6 +331,12 @@ class CORE_EXPORT QgsMapLayer : public QObject
* @note This method was added in QGIS 1.4 **/
void setCacheImage( QImage * thepImage );

/**
* @brief Is called when the cache image is being deleted. Overwrite and use to clean up.
* @note added in 2.0
*/
virtual void onCacheImageDelete() {};

public slots:

/** Event handler for when a coordinate transform fails due to bad vertex error */
Expand Down
3 changes: 2 additions & 1 deletion src/core/qgsmaprenderer.cpp
Expand Up @@ -544,7 +544,8 @@ void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
delete mRenderContext.painter();
mRenderContext.setPainter( mypContextPainter );
//draw from cached image that we created further up
mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
if ( ml->cacheImage() )
mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
}
}
disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
Expand Down
21 changes: 17 additions & 4 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -107,6 +107,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mDiagramLayerSettings( 0 )
, mValidExtent( false )
, mSymbolFeatureCounted( false )
, mCurrentRendererContext( 0 )

{
mActions = new QgsAttributeAction( this );

Expand Down Expand Up @@ -718,6 +720,8 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext&
if ( !hasGeometryType() )
return;

mCurrentRendererContext = &rendererContext;

QSettings settings;
bool vertexMarkerOnlyForSelection = settings.value( "/qgis/digitizing/marker_only_for_selected", false ).toBool();

Expand All @@ -735,10 +739,6 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext&
if ( !fet.geometry() )
continue; // skip features without geometry

if ( rendererContext.renderingStopped() )
{
break;
}
#ifndef Q_WS_MAC //MH: disable this on Mac for now to avoid problems with resizing
#ifdef Q_WS_X11
if ( !mEnableBackbuffer ) // do not handle events, as we're already inside a paint event
Expand All @@ -760,6 +760,11 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext&
#endif // Q_WS_X11
#endif // Q_WS_MAC

if ( rendererContext.renderingStopped() )
{
break;
}

bool sel = mSelectedFeatureIds.contains( fet.id() );
bool drawMarker = ( mEditBuffer && ( !vertexMarkerOnlyForSelection || sel ) );

Expand Down Expand Up @@ -798,6 +803,8 @@ void QgsVectorLayer::drawRendererV2( QgsFeatureIterator &fit, QgsRenderContext&

stopRendererV2( rendererContext, NULL );

mCurrentRendererContext = NULL;

#ifndef Q_WS_MAC
QgsDebugMsg( QString( "Total features processed %1" ).arg( featureCount ) );
#endif
Expand Down Expand Up @@ -4386,6 +4393,12 @@ QString QgsVectorLayer::metadata()
return myMetadata;
}

void QgsVectorLayer::onCacheImageDelete()
{
if ( mCurrentRendererContext )
mCurrentRendererContext->setRenderingStopped( true );
}

QgsVectorLayer::ValueRelationData &QgsVectorLayer::valueRelation( int idx )
{
const QgsFields &fields = pendingFields();
Expand Down
8 changes: 8 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -879,6 +879,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer

inline QgsGeometryCache* cache() { return mCache; }

/**
* @brief Is called when the cache image is being deleted. Overwrite and use to clean up.
* @note added in 2.0
*/
virtual void onCacheImageDelete();

signals:

/** This signal is emited when selection was changed */
Expand Down Expand Up @@ -1108,6 +1114,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
// Feature counts for each renderer symbol
QMap<QgsSymbolV2*, long> mSymbolFeatureCountMap;

QgsRenderContext* mCurrentRendererContext;

friend class QgsVectorLayerFeatureIterator;
};

Expand Down

0 comments on commit 45cd49d

Please sign in to comment.