therecipe / qt

Qt binding for Go (Golang) with support for Windows / macOS / Linux / FreeBSD / Android / iOS / Sailfish OS / Raspberry Pi / AsteroidOS / Ubuntu Touch / JavaScript / WebAssembly
GNU Lesser General Public License v3.0
10.41k stars 742 forks source link

How can I do print in webenginepage #560

Open kinwyb opened 6 years ago

kinwyb commented 6 years ago

webengine.QWebEnginePage do not find method print .. but in qt5.10.1 document have this method

qt document: void print(QPrinter *printer, FunctorOrLambda resultCallback)

help

therecipe commented 6 years ago

Hey

Yeah, sorry this function is currently not supported. You will probably use http://doc.qt.io/qt-5/qwebenginepage.html#printToPdf, to work around this somehow in the meantime.

chuckwagoncomputing commented 5 years ago

Is this function still not supported? I need to generate some high-resolution PDFs for printing, but printToPdf() only outputs 96 dpi PDFs.

therecipe commented 5 years ago

@chuckwagoncomputing It should be supported now with https://github.com/therecipe/qt/commit/39753cb4ef7c691bbc16c3ce73b2b64a8fa808ea by using a stub function for the QWebEngineCallback arg. This is the best I can do atm, but I will look into it again once I have some more time to properly implement a mechanism to get the QWebEngineCallback working.

I tested the changes on the internal/widgets/webengine example alonside these changes

diff --git a/internal/examples/widgets/webengine/webengine.go b/internal/examples/widgets/webengine/webengine.go
index 72e51df8..4136c700 100644
--- a/internal/examples/widgets/webengine/webengine.go
+++ b/internal/examples/widgets/webengine/webengine.go
@@ -4,6 +4,7 @@ import (
    "os"

    "github.com/therecipe/qt/core"
+   "github.com/therecipe/qt/printsupport"
    "github.com/therecipe/qt/webengine"
    "github.com/therecipe/qt/widgets"
 )
@@ -36,12 +37,15 @@ func main() {
    centralWidget.SetLayout(widgets.NewQVBoxLayout())

    var view = webengine.NewQWebEngineView(nil)
-   view.SetHtml(htmlData, core.NewQUrl())
+   view.Load(core.NewQUrl3("https://www.google.com/", 0))
    centralWidget.Layout().AddWidget(view)

    var button = widgets.NewQPushButton2("click me", nil)
    button.ConnectClicked(func(checked bool) {
-       view.Page().RunJavaScript(jsData)
+       printer := printsupport.NewQPrinter(printsupport.QPrinter__ScreenResolution)
+       printer.SetOutputFormat(printsupport.QPrinter__PdfFormat)
+       printer.SetOutputFileName(os.Getenv("HOME") + "/Downloads/some.pdf")
+       go view.Page().Print(printer)
    })
    centralWidget.Layout().AddWidget(button)

but I had problems opening the generated pdf when usingQPrinter__HighResolution on macOS (10.4.1 with Qt 5.12 and Go 1.11.4), and also could only open the PDF generated with QPrinter__ScreenResolution in Firefox. Furthermore I also haven't tested it on Linux nor Windows.

Please let me know if it works for you, if not then I will take another look.

chuckwagoncomputing commented 5 years ago

I guess I was confused and thought QML's WebEngineView had the print function, but it doesn't. Now it looks like my only option is to rewrite my program with QWidgets. Ugh.

therecipe commented 5 years ago

You could also grab the QML window and print it yourself.

Something like the following should work

main.go

package main

import (
    "os"

    "github.com/therecipe/qt/core"
    "github.com/therecipe/qt/gui"
    "github.com/therecipe/qt/printsupport"
    "github.com/therecipe/qt/quick"
    "github.com/therecipe/qt/webengine"
    "github.com/therecipe/qt/widgets"
)

func main() {
    core.QCoreApplication_SetAttribute(core.Qt__AA_EnableHighDpiScaling, true)

    widgets.NewQApplication(len(os.Args), os.Args)
    webengine.QtWebEngine_Initialize()

    view := quick.NewQQuickView(nil)
    view.SetResizeMode(quick.QQuickView__SizeRootObjectToView)
    view.SetSource(core.NewQUrl3("qrc:/qml/main.qml", 0))
    view.Show()

    pb := widgets.NewQPushButton2("Print", nil)
    pb.ConnectClicked(func(bool) {
        printer := printsupport.NewQPrinter(printsupport.QPrinter__ScreenResolution)
        printer.SetOutputFormat(printsupport.QPrinter__PdfFormat)
        printer.SetOutputFileName(os.Getenv("HOME") + "/Downloads/some.pdf")
        printer.SetFullPage(true)

        pix := view.GrabWindow()
        pageRect := printer.PageRect(1)
        targetSize := pix.Size()
        targetSize.Scale2(pageRect.Size().ToSize(), core.Qt__KeepAspectRatio)

        painter := gui.NewQPainter()
        painter.Begin(printer)
        painter.DrawImage(core.NewQRectF2(pageRect.TopLeft(), core.NewQSizeF2(targetSize)), pix, core.NewQRectF(), 0)
        painter.End()
    })
    pb.Show()

    widgets.QApplication_Exec()
}

qml/main.qml

import QtQuick 2.2
import QtWebEngine 1.8

WebEngineView {
    url: "https://www.google.com/"
    onLoadingChanged: {
        if (loadRequest.errorString)
            onsole.error(loadRequest.errorString);
    }
}

There is probably also some way to just grab or print a specific object from the QML scene, instead of the entire scene. And you probably don't even need to show the view and can maybe get it working headless as well. Also maybe take a look here https://github.com/gen2brain/url2img

chuckwagoncomputing commented 5 years ago

Those are both options I considered and decided wouldn't work. Grabbing the window to an image will only save the visible part of the view rather than the whole page. url2img/etc. would save the whole page except for modifications made by the user, which is the main point of the webview my application.

If I can't get PDF printing to work, I'll have my program export a file which can be opened in a browser and printed from there.

Thanks a lot for your help, @therecipe, you rule!

amlwwalker commented 4 years ago

@chuckwagoncomputing I don't know if this is useful to you, and I haven't compiled it for a while, but I made a PDF editor.... (sort of)

The idea is that you load in a PDF, it converts the pages to images, and then you can draw on the images and save the images out with the edits made. I know that this isn't what you are asking for, however I thought that it might give some ideas... https://github.com/amlwwalker/pdf-editor

chuckwagoncomputing commented 4 years ago

I ended up just using file export like I mentioned, but thanks!