Search code examples
multithreadingqtevent-handlingqwebviewqtembedded

QWebView setContent in a separate thread


I have an application that requires to use QWebView::setContent() to load some HTML content to a QWebView. All of this happens on an embedded device with ARMv5 processor (think 400 MHz). Most of the time, I can load the page in reasonable time (up to 5 seconds), however sometimes I have content that takes long time to load (~30 seconds for 300KB of content).

The problem is that the setContent call blocks the main thread. I need to be able to process events during the loading, and maybe even cancel the load if the user decides not to wait any longer.

I was thinking about running the setContent call in other thread, so that it does not block the event processing and I can cancel it if necessary. However, I get the dreaded "widgets must be created in the GUI thread", and I see no way of solving this easily.

Is it possible to run QWebView::setContent in a separate thread? If so, how? If not, is it possible to handle GUI events while setContent is running? Is it possible to "cancel" the setContent call?

EDIT

To clarify a bit more, what really interests me is how to be able to stop the setContent call and/or handle GUI messages, so that the interface remains responsive, with large amounts of data passed using setContent.

EDIT 2

To clarify even further, I am dealing with long, static content, i.e. no JavaScript, just a lot of static HTML, through which the user wants to scroll even while it is loading more content. The main idea is to allow her/him to go down a page even when the page is not fully loaded.


Solution

  • Since QWebView::setContent() is a blocking call, I ended up using a work-around. The main idea is that XML processing is much faster than rendering the page. Therefore I do the following:

    1. Parse the document as XML DOM document (a reasonable assumption in my case), and find the body element.
    2. Keep only a pre-defined number of child elements of body (something like 20 elements). Store the remaining elements in another XML DOM document.
    3. Show the initial document (serialized XML) using QWebView::setContent(), which is relatively fast. Start a timer with timeout 0 on SLOT(loadNextChunk()).
    4. loadNextChunk() moves another 20 or so elements from the backup document at the end of the body using body->appendInside(html), where body is a QWebElement.
    5. Stop when no more elements are available.

    This works because in between the calls to loadNextChunk(), the GUI has a chance to react to events.