One QTextDocument in multiple QTextEdit-s with different layout
Recently I faced a problem that looks like impossible to solve with the Qt classes. I have a single QTextDocument, which is loaded in two different QTextEdit viewers. As the same QTextDocument object is loaded in both of the QTextEdit-s (and this is by design) both Viewers edit the same document contents and update properly any change performed by the other editor. This works beautifully. I needed proper text zooming(and not QTextEdit::zoom which does not scale images for example) so I modified the paint device which is set on the document layout via document()->documentLayout()->setPaintDevice(imageBuffer). It all works beautifully with a single editor, but causes issues on multiple viewers, as both viewers use the same zoom factor. This is due to the layout used by the QTextEdit, which uses the QTextDocument layout and not its own layout. As a result I cannot zoom the same document differently on two viewers. This sounds like wrong separation of data/viewer functionality with Qt. Every QTextEdit should be able to render the underlying QTextDocument with different zoom, i.e. with different layout. The layout should be part of the viewer and not part of the document.
At the end my question is: Is it possible to render the same QTextDocument with different layout in different QTextEdit-s?
However, I'm not sure I agree with your assessment that the layout isn't part of the document, but part of the view instead.
If I understand you correctly, you want to support zooming, but maintaining the layout of the document (no reflowing for instance, but also keeping images in the same size relative to the text).
If so, it seems to me you should not change the document layout, but the rendering of that layout. Perhaps that can be done using a translation matrix on the painter to do the zooming instead.
Changing the translation matrix on the painter causes bad font rendering when the text is zoomed in/out. Changing the paint device gives the best, smooth and proper zooming of the document contents and fonts. Using the translation matrix of the painter is not an option unfortunately. Neither is the qt provided QTextEdit::zoom.
The layout is like the viewer to a model. The layout renders the model(QTextDocument) in a widget(QTextEdit). You can have several different views of a model, but we cannot have several different views of a QTextDocument. It would all work, if we could set the layout on the QTextEdit and not retrieve it automatically from the QTextDocument. I hope that I am missing something, but I still have not found a way to do it and does not seem to be possible by design within Qt.
Still, thanks for your reply, Andre!
I see the issue, and I also understand why you want to solve it with layout, but in principle the layout is not the same as the viewer to a model. Not really. It is there in order to support custom layout systems with more capabilities than what Qt supports. You'd want that to work on all your views, right? So, it seems to me, that the scaling of the document when rendering should be independent from the layout itself, although the layout would probably need it.
Normally, I'd say the scaling should be passed through the translation matrix, but for font rendering that is indeed not ideal (and I know there are other issues involved there, like lines you may want to keep visible even at small rendering sizes.) On the other hand: I don't get why the TextEdit zoom feature doesn't actually zoom the whole document, but somehow goes around the layout to only change the font size of the document. That doesn't make much sense.
I think that indeed, Qt currently does not support what you want. But the fix would be in extending the way QTextEdit zoomIn/zoomOut works (perhaps by adding a zoomMode property that you can set to QTextEdit::TextOnlyZoom or QTextEdit::FullDocumentZoom).
As a workaround, I see three options at this moment:
try to render everything in the highest resolution (most zoomed-in) you need it, and then use the translation matrix to scale down instead of scaling up. That should give better results than the other way around
use two QTextDocuments, and sync them.
fix Qt to do this properly ;)
At least, file a feature request for it. It seems like there are proper use-cases for it, like having a really zooomed-out overview-view and an editing view of the same document, and keeping them in sync in terms of content.
I agree that QTextEdit should zoom properly. Unfortunately with pictures tables, etc. it is of not good use and changing base font sizes is not the way to do it. Qt should implement the paintDevice zoom internally to do proper zooming as many Qt users are already doing it in their own code. Still this is not a big issue as we have a back door to do it ourselves and it works beautifully.
Some comments about the workarounds:
- try to render everything in the highest resolution
- Indeed when I use the most zoomin approach, Qt has other issues with image buffers already when the document is very long(above appr. 80 000 words), so this will make the problem even bigger and I would not go that path.
- use two QTextDocuments, and sync them.
- This is not as straight forward as one would like it to be. I already tried implementing this approach with another task, but I faced other issues and the solution is not beautiful at all. Not to mention that data duplication is bad by design and is an open door for bugs sooner or later.
- fix Qt to do this properly.
- I also implemented this approach and it works, but I am not happy using custom Qt changes, as they cause a lot of pain especially if you need to deploy on multiple platforms and especially Android for example. You have to compile and deploy your custom Qt libraries, which is a lot of effort and also causes other problems going down that track.
I am happy to raise a change request with Qt and provide my already implemented solution, Andre. Do you know with whom I should raise my change request about the text engine? Is there an article explaining how to raise a change request with Qt? Thanks!
Yeah, there is documentation in the wiki on how to contribute. I'd also drop into the Qt development mailinglist and/or the #qt-labs IRC channel (freenode network). That's where the devs hang out.
As for who to contact: that's what we have the "maintainers list":/wiki/Maintainers for. In this case, I'd try contacting Eskil Abrahamsen Blomfeldt at firstname.lastname@example.org He might also hang out on IRC, but under what nick I don't know.
I was hoping to find an easier solution to my problem above, but it does not look like an easy one exists. If no one proposes a better solution here, I will have to raise a change request. Thanks, Andre!