Skip to content
Permalink
Browse files

[wfs] Avoid widget access from non main thread

It's not safe to loop through the app's widgets in a background
thread, so defer determination of the main window until
the progress dialog is being created in the main thread
  • Loading branch information
nyalldawson committed Aug 16, 2018
1 parent 3b861f2 commit 291224e8c75317c132016711353c2b37af6e4dcf
Showing with 24 additions and 11 deletions.
  1. +23 −11 src/providers/wfs/qgswfsfeatureiterator.cpp
  2. +1 −0 src/providers/wfs/qgswfsfeatureiterator.h
@@ -156,9 +156,28 @@ void QgsWFSFeatureDownloader::hideProgressDialog()
// Called from GUI thread
void QgsWFSFeatureDownloader::createProgressDialog()
{
Q_ASSERT( qApp->thread() == QThread::currentThread() );

if ( mStop )
return;
Q_ASSERT( !mProgressDialog );

if ( !mMainWindow )
{
const QWidgetList widgets = qApp->topLevelWidgets();
for ( QWidget *widget : widgets )
{
if ( widget->objectName() == QLatin1String( "QgisApp" ) )
{
mMainWindow = widget;
break;
}
}
}

if ( !mMainWindow )
return;

mProgressDialog = new QgsWFSProgressDialog( tr( "Loading features for layer %1" ).arg( mShared->mURI.typeName() ),
tr( "Abort" ), 0, mNumberMatched, mMainWindow );
mProgressDialog->setWindowTitle( tr( "QGIS" ) );
@@ -430,17 +449,10 @@ void QgsWFSFeatureDownloader::run( bool serializeFeatures, int maxFeatures )

if ( !mShared->mHideProgressDialog && maxFeatures != 1 && mShared->supportsHits() )
{
Q_FOREACH ( QWidget *widget, qApp->topLevelWidgets() )
{
if ( widget->objectName() == QLatin1String( "QgisApp" ) )
{
mMainWindow = widget;
break;
}
}
mUseProgressDialog = true;
}

if ( mMainWindow )
if ( mUseProgressDialog )
{
// In case the header of the GetFeature response doesn't contain the total
// number of features, or we don't get it within 4 seconds, we will issue
@@ -586,7 +598,7 @@ void QgsWFSFeatureDownloader::run( bool serializeFeatures, int maxFeatures )

// Consider if we should display a progress dialog
// We can only do that if we know how many features will be downloaded
if ( !mTimer && maxFeatures != 1 && mMainWindow )
if ( !mTimer && maxFeatures != 1 && mUseProgressDialog )
{
if ( mNumberMatched < 0 )
{
@@ -626,7 +638,7 @@ void QgsWFSFeatureDownloader::run( bool serializeFeatures, int maxFeatures )
// thread of this
connect( mTimer, &QTimer::timeout, this, &QgsWFSFeatureDownloader::createProgressDialog, Qt::DirectConnection );

mTimer->moveToThread( mMainWindow->thread() );
mTimer->moveToThread( qApp->thread() );
QMetaObject::invokeMethod( mTimer, "start", Qt::QueuedConnection );
}
}
@@ -153,6 +153,7 @@ class QgsWFSFeatureDownloader: public QgsWfsRequest
int mPageSize;
bool mRemoveNSPrefix;
int mNumberMatched;
bool mUseProgressDialog = false;
QWidget *mMainWindow = nullptr;
QTimer *mTimer = nullptr;
QgsWFSFeatureHitsAsyncRequest mFeatureHitsAsyncRequest;

0 comments on commit 291224e

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