Skip to content

Commit

Permalink
Try (and fail) to avoid a qApp->processEvents() call
Browse files Browse the repository at this point in the history
I just can't find any other reliable way to wait until javascript
execution in a web page has completed.
  • Loading branch information
nyalldawson committed Jan 5, 2018
1 parent 88a8390 commit 8de8bb3
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 3 deletions.
1 change: 1 addition & 0 deletions python/core/layout/qgslayoutitemhtml.sip
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ Recalculates the frame sizes for the current viewport dimensions

};


/************************************************************************
* This file has been generated automatically from *
* *
Expand Down
31 changes: 28 additions & 3 deletions src/core/layout/qgslayoutitemhtml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,12 @@ void QgsLayoutItemHtml::loadHtml( const bool useCache, const QgsExpressionContex
//inject JSON feature
if ( !mAtlasFeatureJSON.isEmpty() )
{
mWebPage->mainFrame()->evaluateJavaScript( QStringLiteral( "if ( typeof setFeature === \"function\" ) { setFeature(%1); }" ).arg( mAtlasFeatureJSON ) );
//needs an extra process events here to give JavaScript a chance to execute
qApp->processEvents();
JavascriptExecutorLoop jsLoop;

mWebPage->mainFrame()->addToJavaScriptWindowObject( "loop", &jsLoop );
mWebPage->mainFrame()->evaluateJavaScript( QStringLiteral( "if ( typeof setFeature === \"function\" ) { setFeature(%1); }; loop.done();" ).arg( mAtlasFeatureJSON ) );

jsLoop.execIfNotDone();
}

recalculateFrameSizes();
Expand Down Expand Up @@ -533,3 +536,25 @@ void QgsLayoutItemHtml::refreshDataDefinedProperty( const QgsLayoutObject::DataD
loadHtml( true, &context );
}
}

//JavascriptExecutorLoop
///@cond PRIVATE

void JavascriptExecutorLoop::done()
{
mDone = true;
quit();
}

void JavascriptExecutorLoop::execIfNotDone()
{
if ( !mDone )
exec( QEventLoop::ExcludeUserInputEvents );

// gross, but nothing else works, so f*** it.. it's not worth spending a day trying to find a non-hacky way
// to force the web page to update following the js execution
for ( int i = 0; i < 100; i++ )
qApp->processEvents();
}

///@endcond
18 changes: 18 additions & 0 deletions src/core/layout/qgslayoutitemhtml.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,22 @@ class CORE_EXPORT QgsLayoutItemHtml: public QgsLayoutMultiFrame
void refreshExpressionContext();
};

///@cond PRIVATE
#ifndef SIP_RUN
class JavascriptExecutorLoop : public QEventLoop
{
Q_OBJECT
public slots:

void done();
void execIfNotDone();

private:

bool mDone = false;

};
#endif
///@endcond

#endif // QGSLAYOUTITEMHTML_H

0 comments on commit 8de8bb3

Please sign in to comment.