Register Guidelines E-Books Search Today's Posts Mark Forums Read

Go Back   MobileRead Forums > E-Book Software > Calibre > Development

Notices

Reply
 
Thread Tools Search this Thread
Old 04-04-2017, 12:27 PM   #1
KevinH
Wizard
KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.KevinH ought to be getting tired of karma fortunes by now.
 
Posts: 2,499
Karma: 772404
Join Date: Nov 2009
Device: many
Pick your brain on QtWebEngine

Hi Kovid,

I wanted to pick your brain a bit. I am playing around with a port our Preview Window (not BookView) to QWebEngine to see if it is possible and what performance is like. I have been trying to figure out a good way to synchronously wait for a return value from running a Javascript. I saw your PyQt5 post on the subject and so tried a Functor approach and ended up with the overly elaborate approach for C++ as follows:

Code:
struct JSResult {
  QVariant res;
  bool     finished;
  JSResult() : res(QVariant("")), finished(false) {}
  JSResult(JSResult * pRes) : res(pRes->res),  finished(pRes->finished) {}
  bool isFinished() { return finished; }
};

struct SetJavascriptResultFunctor {
    JSResult * pres;
    SetJavascriptResultFunctor(JSResult * pres) : pres(pres) {}
    void operator()(const QVariant &result) {
        pres->res.setValue(result);
        pres->finished = true;
    }
};

QVariant ViewPreview::EvaluateJavascript(const QString &javascript)
{
    JSResult * pres = new JSResult();
    page()->runJavaScript(javascript,SetJavascriptResultFunctor(pres));
    while(!pres->isFinished()) {
        qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers, 100;
    }
    QVariant res = pres->res;
    delete pres;
    return res;
}
This basically followed your recommended PyQt5 idea but since a QVariant does not have a "None" value and C++ does not support internal functions, I needed added a structure to keep a boolean finished flag. That grew things considerably. It does seem to work but the code is ugly.

So I have been looking for a simpler approach and found the following in QupZilla 2.1.2 code which is a full browser that supports QWebEngine:

Code:
QVariant WebPage::execJavaScript(const QString &scriptSource, quint32 worldId, int timeout)
{
    QPointer<QEventLoop> loop = new QEventLoop;
    QVariant result;
    QTimer::singleShot(timeout, loop.data(), &QEventLoop::quit);

    runJavaScript(scriptSource, worldId, [loop, &result](const QVariant &res) {
        if (loop && loop->isRunning()) {
            result = res;
            loop->quit();
        }
    });

    loop->exec();
    delete loop;

    return result;
}
It does not use the main app event loop and instead uses a separate QEventLoop.

I was wondering what you thought of this approach.

To me it seems to have an inherent race in that a truly asynchronous javascript run could complete and make the callback in the interval after runJavascript and before loop->exec() is invoked. Doesn't the loop->IsRunning() test in the callback return false if loop.exec() has not been called yet?

Also, I was wondering about your experiences with QtWebEngine.

For what it is worth, I have found that QWebEngine in Qt 5.6.2 is really slow to load almost everything (at least on my Mac) - very slow as in 3 to 5 seconds to load a display a simple xhtml page with a single image link in it. I do not think the xhtml code paths have been tested much as it seems to be highly prone to segfaults when loading incorrect "xhtml" documents using setContent with an xhtml mimetype (something editing in CodeView will make happen easily). I am hoping that things are much much improved in Qt 5.8.0 when it comes to QtWebEngine.

Aside from the insecure WebInspector issues (I saw your bug report), what have your experiences been with QtWebEngine?

Thanks,

KevinH
KevinH is offline   Reply With Quote
Advert
Old 04-04-2017, 01:49 PM   #2
kovidgoyal
creator of calibre
kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.kovidgoyal ought to be getting tired of karma fortunes by now.
 
kovidgoyal's Avatar
 
Posts: 31,298
Karma: 8154029
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
QtWebEngine is fairly buggy and crash prone. I have written several applications using it (see my github profile for iv and vise) and in my opinion it is not really ready for production use. I have experienced lots of crashes and rendering bugs with it. And on top of everything else, there were a large number of regressions introduced into it in Qt 5.8.0 that still have not had a fix released, months later (search the Qt bug database for bugs against webengine in 5.8.0).

All in all, I have been pretty disappointed with web engine. I have shelved my plans for replacing webkit with it for atleast another year.

Note that there is a new community supported version of qt webkit with more up-to-date webkit versions. At least on my Arch system it is called qt-webkit-ng and I was able to use it as a drop in replacement for the old qt webkit in calibre (although the binary calibre releases still use the old qt webkit and will likely continue to do so for a while as the ng version is still in beta and it remains to be seen how viable it is in the long term).

Whether there is a race in the qupzilla code or not, depends on how runJvascript() is implemented. If it uses the event loop to dispatch the JS to the webengine process, then there is no race. If it does not, then there is a race. You can eliminate the race by using QTimer to call runJavascript after loop::exec() is called. Though that will probably make the code ungainly again.
kovidgoyal is online now   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Help brain storm toje00 Amazon Kindle 8 07-28-2015 08:54 AM
brain freeze applesauce Library Management 2 04-30-2012 09:34 AM
Free Audiobook - You Are Not Your Brain koland Deals, Freebies, and Resources (No Self-Promotion) 0 01-20-2012 08:34 PM
``Manna'' by Marshall Brain WillAdams Deals, Freebies, and Resources (No Self-Promotion) 1 02-11-2010 05:19 PM


All times are GMT -4. The time now is 12:09 AM.


MobileRead.com is a privately owned, operated and funded community.