Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QPrinter unable to style HTML page properly to render image in PDF document

I want to create a PDF document with properly styled HTML. This is what I am trying:

QTextDocument *doc = new QTextDocument();
const char* s1 = "<html><head><style>body { font-family: sans-serif;}.note-atomic { background: rgb(242,242,242); width: 1000px; margin: 5px auto; border: 1px solid grey; border-radius: 8px;padding: 5px;}</style></head><body><div class = 'note-atomic'>Hi</div><img src = '/Users/attitude/Desktop/RnSghvV.png' width='400' height='300' /></body></html>";
doc->setHtml(QString::fromStdString(s1));

QPrinter *printer = new QPrinter();
printer->setOutputFileName("/Users/attitude/Desktop/fool.pdf");
printer->setOutputFormat(QPrinter::PdfFormat);

QPainter *painter = new QPainter();
painter->begin( printer );
doc->drawContents(painter, printer->pageRect().translated( -printer->pageRect().x(), -    printer->pageRect().y() ));
doc->print(printer);

const char* s2 = "<html><body><div>Bye</div></body></html>";
doc->setHtml(QString::fromStdString(s2));

printer->newPage();
doc->drawContents(painter, printer->pageRect().translated( -printer->pageRect().x(), - printer->pageRect().y() ));

doc->print(printer);
painter->end();

I expect the PDF to have 2 pages - first one with text Hi, and the next and last one with text Bye. And the first page styled like it appears in a HTML page with the same markup:

enter image description here

However, the first page of the PDF comes up with content completely messed up:

enter image description here

How do I make it look as expected?

The image I am trying in the HTML doc: http://imgur.com/RnSghvV

Platform - Qt 5.3.1, 32 bit. OS X Yosemite.

like image 671
SexyBeast Avatar asked Feb 01 '16 19:02

SexyBeast


2 Answers

This is QTextDocument. It rendered rich text (it is not HTML + CSS).

Available properties and elements you may check on http://doc.qt.io/qt-5/richtext-html-subset.html (for example there is no css property border for p or div).

Also you can see how it looks in Qt Designer, if you put your html code into QTextEdit.

For rendering HTML you can use QWebView (http://doc.qt.io/qt-5/qwebframe.html#print)

webview->mainFrame()->print(printer);

like image 50
timocov Avatar answered Sep 21 '22 20:09

timocov


QTextDocument is not a web browser. It won't go fetching networked URLs for you. You need to add a QVariant QTextDocument::loadResource(int type, const QUrl & name) method to your QObject (QWidget is-a QObject!), and make the QTextDocument a child of that object. The document instance will the invoke your implementation of loadResource, where you can leverage the QNetworkAccessManager to do the fetching.

For this to have any chance of being user-friendly, you cannot block on network requests. This is accomplished by doing the processing twice. First simply take note of what URLs are to be loaded and initiate their fetching, returning an empty QVariant. Once all network requests are completed successfully and you've stored them in a cache, you can re-run the same code and it'll correctly render the page and won't block for network access.

All of this has to be done asynchronously.

like image 44
Kuba hasn't forgotten Monica Avatar answered Sep 18 '22 20:09

Kuba hasn't forgotten Monica