Skip to content

Commit

Permalink
[wfs] Avoid widget access from non main thread
Browse files Browse the repository at this point in the history
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

(cherry-picked from 291224e)
  • Loading branch information
nyalldawson committed Aug 16, 2018
1 parent 01b4ede commit 491095c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
34 changes: 23 additions & 11 deletions src/providers/wfs/qgswfsfeatureiterator.cpp
Expand Up @@ -155,9 +155,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" ) );
Expand Down Expand Up @@ -425,17 +444,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
Expand Down Expand Up @@ -550,7 +562,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 )
{
Expand Down Expand Up @@ -586,7 +598,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 );
}
}
Expand Down
1 change: 1 addition & 0 deletions src/providers/wfs/qgswfsfeatureiterator.h
Expand Up @@ -153,6 +153,7 @@ class QgsWFSFeatureDownloader: public QgsWfsRequest
bool mSupportsPaging;
bool mRemoveNSPrefix;
int mNumberMatched;
bool mUseProgressDialog = false;
QWidget *mMainWindow = nullptr;
QTimer *mTimer = nullptr;
QgsWFSFeatureHitsAsyncRequest mFeatureHitsAsyncRequest;
Expand Down

0 comments on commit 491095c

Please sign in to comment.