0

From here, I know that I can use QWebEngineView::render, passing in a pointer to my QPrinter object to programmatically print a web page.

But if the print request was invoked by javascript (from the window.print() javascript function for instance), I don't know how to catch that request to then hand off to my print function.

Community
  • 1
  • 1
Jason
  • 93
  • 10

2 Answers2

2

Two years later I finally came up with a solution to this problem.

Qt 5.8 does support printing, however chooses to completely ignore javascript invoked window.print() requests.

The solution is to inject some javascript to override the window.print() function:

class JavascriptInvokedPrintComm : public QWebChannel
{
    Q_OBJECT
public:
    JavascriptInvokedPrintComm(QObject *parent) : QWebChannel(parent)
    {
        registerObject("webEngineViewBridge", this);
    }

public slots:
    void print()
    {
        emit printRequest();
    }

signals:
    void printRequest();
};

class MyWebEngineView : public QWebEngineView
{
    Q_OBJECT
public:
    MyWebEngineView(QWdidget *parent) :  QWebEngineView(parent)
    {
        // Inject qwebchannel.js so that we can handle javascript invoked printing
        QWebEngineScript webChannelJs;
        webChannelJs.setInjectionPoint(QWebEngineScript::DocumentCreation);
        webChannelJs.setWorldId(QWebEngineScript::MainWorld);
        webChannelJs.setName("qwebchannel.js");
        webChannelJs.setRunsOnSubFrames(true);
        {
            QFile webChannelJsFile(":/qtwebchannel/qwebchannel.js");
            webChannelJsFile.open(QFile::ReadOnly);
            webChannelJs.setSourceCode(webChannelJsFile.readAll());
        }
        page()->scripts().insert(webChannelJs);

        // Inject some javascript to override the window.print() function so that we can actually catch and handle
        // javascript invoked print requests
        QWebEngineScript overrideJsPrint;
        overrideJsPrint.setInjectionPoint(QWebEngineScript::DocumentCreation);
        overrideJsPrint.setWorldId(QWebEngineScript::MainWorld);
        overrideJsPrint.setName("overridejsprint.js");
        overrideJsPrint.setRunsOnSubFrames(true);
        overrideJsPrint.setSourceCode(
                    "window.print = function() { "
                    "   new QWebChannel(qt.webChannelTransport, function(channel) { "
                    "       var webEngineViewBridge = channel.objects.webEngineViewBridge; "
                    "       webEngineViewBridge.print(); "
                    "   });"
                    "};"
                    );
        page()->scripts().insert(overrideJsPrint);

        JavascriptInvokedPrintComm *jsInvokedPrintComm = new JavascriptInvokedPrintComm(this);
        connect(jsInvokedPrintComm, &JavascriptInvokedPrintComm::printRequest, [this]()
        {
            QPrintDialog *prntDlg = new QPrintDialog(this);
            if(!prntDlg->exec())
            {
                prntDlg->deleteLater();
                return;
            }

            page()->print(prntDlg->printer(),
                [prntDlg](bool ok)
                {
                    Q_UNUSED(ok);
                    prntDlg->deleteLater();
                }
            );
        });
    }
}

*Not compile tested, but conceptual this should work

Jason
  • 93
  • 10
  • so how can i use ``MyWebEngineView`` in QML files? – Mahdi Khalili Nov 26 '18 at 09:27
  • I don't use QML so I can't give you specifics, but I'm pretty sure instead of subclassing QWebEngineView, you would subclass the WebEngineView QML type. If you don't know how to extend QML types, a quick google found me this: http://doc.qt.io/qt-5/qtqml-referenceexamples-coercion-example.html – Jason Nov 27 '18 at 12:45
0

Which version of Qt do you use? Currently printing is not supported under version 5.6.

See the plan: https://trello.com/c/JE5kosmC/72-printing-support

heinob
  • 19,127
  • 5
  • 41
  • 61
Jusnoo
  • 1
  • Im using 5.5.1 right now, but will probably wait until 5.6 comes out before I finish my project. I've heard from a support person from qt.io that they are pushing to move QtWebEngine printing support from 5.7 to 5.6. I presume javascript invoked printing will come when true print support is included. The suggested hack I linked to above is just that, a hack. – Jason Nov 11 '15 at 16:46