Try (and fail) to avoid a qApp->processEvents() call

I just can't find any other reliable way to wait until javascript
execution in a web page has completed.
This commit is contained in:
Nyall Dawson 2017-12-28 13:15:05 +10:00
parent 88a839061d
commit 8de8bb387f
3 changed files with 47 additions and 3 deletions

View File

@ -261,6 +261,7 @@ Recalculates the frame sizes for the current viewport dimensions
};
/************************************************************************
* This file has been generated automatically from *
* *

View File

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

View File

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