tags:

views:

400

answers:

3

Hi,

I'm using a QWebPage without a QWebView because I want to render the contents of an HTML file onto a QPixmap/QImage.

I want the loading of the page to be done synchronously, not asynchronously which is the default. The default way is to call QWebFrame::setHtml() or QWebFrame::setContent(), but this loads images asynchronously. What I want is some sort of blocking function call, something like QWebFrame::waitUntilLoadFinished() after which I could just call render() and be done with it.

I can't find a way to do this. Am I missing something?

+1  A: 

That approach has the problem that you basically have to wait for an undetermined amount of time and if you're issuing the call from the main thread you're blocking event processing and thus signals like loadFinished.

While you could get around that by explictly pumping event, i don't see an inherent problem that could prevent you from issuing the page-load and just do the processing when loadFinished occured.
If you need secondary threads to wait for the page, you could always let those threads wait by using synchronisation mechanisms.

Georg Fritzsche
Waiting is not a problem, the resources are from disk and I control them. They're very small. But you've given me an idea with QFutureWatcher...
Lucas
Also, I explicitly want to avoid waiting for a signal. I just want to load a small page from disk, render it to an image and return that image. That should be one function, not several + slot + waiting for the signal etc...
Lucas
As Qt doesn't provide that itself, you have to wait for the signal somewhere - even if its just hidden by some code. I haven't tried Qts future watcher yet, but the example looks like it can do exactly what you want - waiting for signals.
Georg Fritzsche
But you need something that returns a QFuture, and nothing in QtWebkit does.
Lucas
I might have looked wrong then - but then there are other synchronization mechanisms that you can use for a wrapper.
Georg Fritzsche
A: 

If anyone's interested, I implemented this using a special "PageRasterizer" class.

The class creates a QWebPage in the constructor and sets a bool loading flag to false. A connect() call connects the loadFinished signal to a member slot that merely sets the loading flag to true.

A special RenderPage() member function that returns an image does all the work: it accepts the HTML string and calls setHtml(). After that comes a while loop that waits on the flag; while the flag is false, qApp->processEvents() is called so signals get emitted and the flag setting slot is eventually called. When it is, the loop breaks and now you can render the page to a QImage (don't forget to set the flag back to false before returning).

If you're interested in the rendering process, look at this Qt example (the Thumbnailer::render() function).

For bonus points, you can make this class a functor.

Lucas
I definitely recommend not using busy polling via a loop but proper synchronization like wait conditions.
Georg Fritzsche
Signals will not be emitted unless the Qt event loop is running. But the event loop processes events and then returns. My solution merely runs the Qt event processing until Webkit is done loading.I'd like to see your code using QWaitConditions _when you don't have access to the Webkit threads_...
Lucas
I said *recommend* and of course i assume that you are not using the main thread as the worker thread which means you simply don't have to poll events manually.
Georg Fritzsche
I hope you are no professional programmer, hotspinning is the worst thing you can do.And a snippet of coed often helps a lot more than explaining difficult structure.Your example does not require hotspinning either.
penguinpower
It's hardly hotspinning, I'm merely running the Qt event loop.
Lucas
+1  A: 

I suggest you to do it the Qt way and do it async, it helps a lot.

In case you still want to do it in Sync, use QEventLoop in a seperate QThread.

Note: do not forget to call moveToThread(this); within the thread header, or all signals will go over the QApplication execution loop.

penguinpower
See now _that's_ useful information. I didn't know about QEventLoop. Now I can push it to a new thread and wait for that to finish.
Lucas
Rather sad I still got now "solved" nor upvote :P
penguinpower