How to print a QQuickView's contents to PDF? - qt

I'm upgrading some Qt (C++ & QML) code from Qt4.8 to Qt5.1.
The Qt4.8 code is a trivial C++ "QML viewer" app subclassing a QDeclarativeView, and a bunch of QML.
It's been easy enough to change this to use Qt5/QtQuick2's QQuickView except for one thing:
The Qt4.8 app has a method for printing to PDF:
void MyQMLViewer::printToPDF(const QString& filename) const {
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setPageSize(QPrinter::A3);
printer.setOutputFileName(filename);
printer.setOrientation(QPrinter::Landscape);
QPainter painter(&printer);
render(&painter);
}
There were a few "environment" changes needed for Qt5.1 to get a QPrinter (ie add QT += printsupport to the project .pro file and #include <QtPrintSupport>), but there seems to be a more fundamental problem that QQuickView doesn't provide anything which is obviously compatible with the QGraphicsView/QPainter/QPaintDevice world of QPrinter (specifically, QQuickView has no render method, and all the drawing/painting/rendering-related methods it does have seem very tied up with OpenGL).
Any suggestions for how to best obtain high-quality PDF output from a QQuickView ?
(Note that I am not simply looking to screenshot the view; with QDeclarativeView, the code above generates PDFs with much better resolution even than the app fullscreened on my largest monitor).
I see the "QDeclarativeItem and QDeclarativeView" section of the "Porting QML Applications to Qt 5" guide does mention the loss of QGraphicsView-specific functionality, but doesn't offer any solutions (although it does mention workrounds for the case of items with custom QPainter-based rendering being bought into the new regime).
Update with some additional background info: an example of a PDF printed from QDeclarativeView using the above code can be found here. There's a png of the same view on a decent size monitor here. (This is actually the last slide in a series of slides; it's actually a gallery of the previous slides which bounces each slide onto the screen; if I had the time I'd look into the feasibility of the gallery being the only thing and transforming each scattered slide into view for a Prezi-style presentation; suspect QDeclarative isn't really performant enough though, which is one reason for wanting to get onto QtQuick2+Qt5.2's new scene graph stuff). Anyway, If you zoom the PDF up to 100% you'll see the text is... well it's better than anything a sanely sized image file will manage I think, although the sloping text baselines perhaps look a little uneven. There is also an issue with opacity values not being represented in the PDF (so the drop shadows and "bubbles" come out solid); another one of my motivations for trying for a QtQuick2 version was actually to see if translucent elements were dealt with any better. I assume the PDF just contains rasterized (or maybe vector outlines) of all the elements as utilities like "pdftotext" can't extract anything from it. I don't know enough about PDF tools to know how to inspect the internal structure of the thing but I assume there's some hierarchy there and the QML element tree is all laid out using a similar structure of nested transforms to the QML. Just for comparison and the sort of richness I'm potentially working towards here's a poster I did with LaTeX/Beamerposter; I find Beamerposter's rigid block structure rather limiting (and fiddly) compared with the possibilities QML seems to offer though. BTW, another thing on my wishlist/todolist is a QML element which can render LaTeX source, math and all, just to get the best of both worlds.
Update: Recent Qt blog post on all the backend changes in Qt5.8 has a comment linking to this Qt issue to use the new possibility of QPainter-rendered QtQuick scenes to render PDFs.

At the moment, there is no code in Qt that supports rendering of a scene graph to a pdf. The underlying data that is used to render Qt Quick 2 is held in the scene graph. As Laszlo suggests, you'd need to iterate the scene graph and generate PDF primitives. There's some impedance mismatch there, but it should be doable with some sweat. I think a proof of concept could be small enough to fit here, so I'll see how easy it could be :)
If you really want a PDF, you currently have no choice but to render it to a large image at 300dpi and wrap that in a PDF. The image doesn't have to be large if the poster has large areas of solid color. PDF can do do TIFF encoding and also JPEG encoding.

Related

Print QWebPage to pixmap

I'm not the most experienced in Qt or desktop development, so I hope this isn't too much of an ignorant question.
I am trying to use QWebKit [1] to store a webpage to images as if printed on paper. Unfortunately it seems that QPainter works only for printing to pdf, postscript or a real printer, and QWebFrame doesn't have methods to set the media to CSS in case of rendering to a QPainter.
I can see that inside Qt QPrintPreviewWidgetPrivate uses printer->d_func()->previewPages(); to get a preview of the images that will be sent to the printer, however this is a private method and not a publicly available API and therefore I cannot use it even if it were possible to get the images at a desired resolution.
At this point I am at a loss and might actually start delving into how QPrinter and QWebFrame interact and just re-implement the methods in hope that it isn't too big of an undertaking.
[1] Unfortunately can't upgrade to Qt5 and QWebEngine yet.

Zooming a view in PyQt?

I have a simple to do tree application that displays a QTreeView inside of a QMainWindow. I want to give the user the ability to change the magnification level of the content (using a spinbox most likely), but without actually changing the underlying font size of the text.
Is there a way to do this without changing my whole app to a QGraphicsScene? The app is just showing a good-old fashioned tree with text, no graphics or anything fancy other than wanting to change the magnification of the view; hence, I am thinking that switching to a graphics scene would be overkill.
Or, am I wrong, and switching to a graphics scene is the only simple way to do it?
Note a trimmed down version of the app is at Code Review. It contains a SSCCE, but is a bit long to post here.
In a site discussing how to put widgets on a scene, trolltech wrote (emphasis added):
I myself and several other Trolls’ve spent some time researching this
topic [how to embed a widget in a QGraphicsScene]. It’s not trivial;
most solutions to embedding widgets into a scene end up with several
serious drawbacks. That’s also why Qt doesn’t have any off-the-shelf
solution to this.
Widgets cannot be scaled or rotated, but graphics items can.
This suggests I cannot perform, in a simple way, the operations I want to on my QWidget by itself. That is, perhaps I need to add it to a scene, which is what I was trying to avoid. If that is the answer, then I'll accept it and start a new question if I get stuck doing that.
Note I just found this question, which is pretty much a duplicate, and does not have an (accepted) answer.
Related content
http://www.qtcentre.org/threads/62745-Zoom-a-view
QTableView Zoom In/Out
Drawing widgets (such as buttons) over QGraphicsView
QGraphicsView Zooming in and out under mouse position using mouse wheel
https://forum.qt.io/topic/15308/qgraphicsview-zooming-with-qslider
https://wiki.qt.io/Smooth_Zoom_In_QGraphicsView
As suggested by the docs quoted from trolltech in the original question, there is no built-in method to zoom on a view.
If the goal is to avoid the use of QGraphicsViews, the simplest way to separate the size of the font on the screen, versus the size of the font saved or printed, is to basically have two fonts. One to be displayed on the screen you can call 'zoom', versus the other to be saved/printed and call that 'font size'.
I got this idea from qtcentre (in a post I added to the original post too):
http://www.qtcentre.org/threads/62745-Zoom-a-view

trying to make a bitmap editor in qt

I want to make a program using qt.
I have to make a bitmap editor for special purposes.
I had been looking widgets that could allow me to get this task done, one of them is QGraphicsView with QGraphicsScene.
As expected, I want my program to have many features.
They are listed below:
Exporting to image formats such as .bmp.
Support for clipboard, copy and paste. I hope this clipboard can be compatible with other similar programs.
The image must have a resolution. I mean the pixels of the screen can be bigger than the pixels of the image and vice-versa.
Selecting squared areas.
So, what I need to know is if I am using the correct widget. If not, which widget can I use? which are the member functions of the widget that I need to know?
There several ways to achieve what you want, but as your question is too broad, I would suggest looking at the Qt Scribble example and come back with specific questions relating to what it doesn't do.
The link suggested previously was replaced with a new one that points to the corresponding Qt 5 example.

How to render custom video data in Qt ?

I have never done a Qt video application - newbie in this area. I have a custom video file format to render using Qt. The video file format is 256-byte header, then pixel data, then 256-byte header, then pixel data and so on.
The header consist info like width, height in pixels, bytes per pixels, frame rate etc and the pixel data is in Bayer (GBRG). I may have to process data before display - like convert to RGB (not sure yet). I see there are lot of video related classes like QGL*, QMovie, QVideo* ... don't know where to start ? I have seen mandelbrotwidget example which looks like a good place to start but still need some advice. Also, do I have to write a Qt Image plugin for Bayer pattern?
Thank you.
Good advice is to do all by yourself. If you have simple data structure read it by simple C++-code.
Conversation from Bayer RGB to RGB like here you can also make without using any Qt objects.
And now, when you'll got trivial RGB-image (even in your own structure) per frame, you can show it on widgets such as QGL* -- if you prefer OpenGL rendering, or Qt's classes such as QPainter, QImage...
Some more links: C++ GUI Programming with Qt4, 2nd Edition, Graphics View Framework
The best place to start is by learning the basics of custom drawing in Qt. In short, a very simple implementation would require you to:
Create a custom QWidget subclass
Override the paintEvent() method
Use a QPainter/QImage to decode your raw video data into image data and draw it on screen
Qt has lots of good sample code to get you started, such as:
http://qt-project.org/doc/qt-4.8/examples-painting.html
Once you have a simple implementation up and running, and a basic grasp of Qt concepts/classes, then you'll be ready to profile, optimize, and make use of more advanced Qt functionality (GL, video) as needed.

Qt - subclassing to provide an alternative view for a text widget?

Currently, I am in the design phase of a Qt widget like what one would see in a typical hex editor. It seemed simple enough to begin with, but as I dig into its implementation details I’m having some confusion.
Basically, the widget would consist of 3 core components: It will inherit QAbstractScrollArea or QScrollArea to provide scrolling and, in the viewport margin, it will display the file offset of each line. Then there will be two text editors; one with the hexadecimal value of each byte of the file, and one with the plaintext character representation.
I, of course, first checked qt-apps.org for any existing widgets, but a search for “hex” only returned QHexEdit and qPHexEditor, neither of which are very complete. I then considered creating a widget completely from scratch as they had, but felt like there should be a more elegant solution. Qt already has much text-editor functionality built into QTextEdit and QPlainTextEdit; why reinvent the wheel?
Now, while the “plaintext view” would be as simple as using a QPlainTextEdit with a fixed-width font and a width of 16 characters, the “hex view” is giving me a headache. I’ve been poring over QTextEdit, QAbstractTextDocumentLayout, etc., trying to figure out a way to present the desired appearance. For those who have never used a hex editor, it should function like so: – Using a fixed-width font, widget should be the width of 47 characters – Widget should display 2 hexadecimal characters per byte, with a blank space between bytes—-16 bytes per line
Since that thought, I’ve been trying to figure out how to subclass any related classes to provide the desired formatting. Unfortunately, the text editing classes don’t seem to follow the model/view framework as closely as I’d hoped, so deriving a new “view” for it doesn’t seem easy. Ideally, the widget would function like so:
One document/model for both the “hex” and “plaintext” views. Editing either view would adjust this model and update the other view appropriately. Signals/Slots at its best.
Because QTextEdit and QPlainTextEdit already provide much of the functionality needed (visible cursor, selections, undo/redo, native look and feel, etc), it would be ideal to re-use this.
So, does anyone have any recommendations? I appreciate any input on this.
QHexEdit2 is a quite complete editor widget for binary data. It can edit very big files, is available for Qt4, Qt5, PyQt4, PyQt4 with python 2 and 3.
see https://github.com/Simsys/qhexedit2

Resources