Question

Both QWebFrame and QWebPage have void loadFinished(bool ok) signal which can be used to detect when a web page is completely loaded. The problem is when a web page has some content loaded asynchronously (ajax). How to know when the page is completely loaded in this case?

Was it helpful?

Solution

I haven't actually done this, but I think you may be able to achieve your solution using QNetworkAccessManager.

You can get the QNetworkAccessManager from your QWebPage using the networkAccessManager() function. QNetworkAccessManager has a signal finished ( QNetworkReply * reply ) which is fired whenever a file is requested by the QWebPage instance.

The finished signal gives you a QNetworkReply instance, from which you can get a copy of the original request made, in order to identify the request.

So, create a slot to attach to the finished signal, use the passed-in QNetworkReply's methods to figure out which file has just finished downloading and if it's your Ajax request, do whatever processing you need to do.

My only caveat is that I've never done this before, so I'm not 100% sure that it would work.

Another alternative might be to use QWebFrame's methods to insert objects into the page's object model and also insert some JavaScript which then notifies your object when the Ajax request is complete. This is a slightly hackier way of doing it, but should definitely work.

EDIT:

The second option seems better to me. The workflow is as follows:

Attach a slot to the QWebFrame::javascriptWindowObjectCleared() signal. At this point, call QWebFrame::evaluateJavascript() to add code similar to the following: window.onload = function() { // page has fully loaded }

Put whatever code you need in that function. You might want to add a QObject to the page via QWebFrame::addToJavaScriptWindowObject() and then call a function on that object. This code will only execute when the page is fully loaded.

Hopefully this answers the question!

OTHER TIPS

When your initial html/images/etc finishes loading, that's it. It is completely loaded. This fact doesn't change if you then decide to use some javascript to get some extra data, page views or whatever after the fact.

That said, what I suspect you want to do here is expose a QtScript object/interface to your view that you can invoke from your page's script, effectively providing a "callback" into your C++ once you've decided (from the page script) that you've have "completely loaded".

Hope this helps give you a direction to try...

To check the load of specific element you can use a QTimer. Something like this in python:

@pyqtSlot()
def on_webView_loadFinished(self): 
    self.tObject = QTimer()
    self.tObject.setInterval(1000)
    self.tObject.setSingleShot(True)
    self.tObject.timeout.connect(self.on_tObject_timeout)
    self.tObject.start()

@pyqtSlot()
def on_tObject_timeout(self):
    dElement = self.webView.page().currentFrame().documentElement()
    element  = dElement.findFirst("css selector")
    if element.isNull():
        self.tObject.start()

    else:
        print "Page loaded"

The OP thought it was due to delayed AJAX requests but there also could be another reason that also explains why a very short time delay fixes the problem. There is a bug that causes the described behaviour:

https://bugreports.qt-project.org/browse/QTBUG-37377

To work around this problem the loadingFinished() signal must be connected using queued connection.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top