Skip to content
Permalink
Browse files

Avoid possible crash in rendering loop

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 45cd49d268d27ec12f041a259d0297b9672efa86
@@ -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 )
@@ -1249,6 +1249,7 @@ void QgsMapLayer::setCacheImage( QImage * thepImage )

if ( mpCacheImage )
{
onCacheImageDelete();
delete mpCacheImage;
}
mpCacheImage = thepImage;
@@ -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 */
@@ -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 ) ) );
@@ -107,6 +107,8 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath,
, mDiagramLayerSettings( 0 )
, mValidExtent( false )
, mSymbolFeatureCounted( false )
, mCurrentRendererContext( 0 )

{
mActions = new QgsAttributeAction( this );

@@ -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();

@@ -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
@@ -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 ) );

@@ -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
@@ -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();
@@ -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 */
@@ -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;
};

0 comments on commit 45cd49d

Please sign in to comment.
You can’t perform that action at this time.