[Development] Probably too late, but re: rich text and Qt 5
elhedran at mac.com
Fri Dec 23 01:12:02 CET 2011
This post is probably too late. It was attempted via various paths as early as October but I somehow missed or forgot that the dev list was public and the people I did contact didn't point me this way until recently.
I'm not sure how many people have heard of Scrivener. I'm sure though that a quick search should help find enough information on Scrivener for Windows for those that are interested. The bottom line is its pushed the rich text component of Qt 4, hard. We have been in the position of changing Qt (under commercial) for most of the project.
The biggest help would be to untie QTextLayout from QTextDocumentLayout, and update the API of QTextLayout to be easier to subclass. To this end the minimum I'd like to help see done in Qt 5.0 is better encapsulation. Some specific actions towards this would be:
QTextDocumentLayout in a public header and exported
QTextFrameLayout in a public header and exported
QTextLayout handling its own line layout (rather than having this code in QTextDocumentLayout). Search for uses of beginLayout
some API changes to QTextLayout
QTextLayout API changes to encourage subclassing (e.g. virtual draw, draw cursor, and 'block layout' functions)
and a factory approach where there is a function you can override in QTextDocumentLayout that creates QTextFrameLayouts, and in turn a factory function in QTextFrameLayout that creates QTextLayouts.
This is pretty much the approach Scrivener takes at the moment with the exception that QTextFrameLayout isn't exposed (we don't change frame layouts much yet). It means that we don't have to use QSyntaxHighlighter (and don't as its api is tied to documents rather than layouts and lead to some unfortunate performance issues). It also allows an incremental improvement on the layout rather than starting from scratch, which is unfortunately the only approach in the current API as QTextDocumentLayout and QTextEngine are both private. And before anyone says "Well, thats just your project" they might want to review the logs for how much writing Qt Creator resulted in non-API feature changes in Qt rich text.
This won't get Scrivener back to vanilla Qt though. Below are the rest of the 'We needed to break the API' changes and issues we ran into. If there is assistance in writing tests, cleaning up function names and writing documentation it may be worth Scrivener making the patches below public. They are most certainly not at Qt standard at the moment
- QTextDocuments manage multiple child document layouts, rather than just a single. setDocumentLayout and documentLayout() functions have been removed. This allows showing the same document side by side (and with live edit's replicated across) with different layouts (editor widths, syntax highlight on or off, find highlights).
- Zooming uses paint device metrics rather than font height. A QImage is created and its dpi is set based on the zoom. This is then used as the paint device for the layout. This allows things like margins, tabs and other aspects to zoom along with font height
- QTextEdit has a 'don't set page size' option, so can be used in other scroll contexts.
- No 'indent', just left margin and textIndent. the current 'indent' code is from html and interfers with editable rich text behavior
- QTextLine responsible for textIndent, leftIndent, rightIndent (to get tabs right, and hanging indents right)
- use of a template string for list bullets rather than an enum. Allows for hierarchal lists as well (e.g. 1., 1.1, 1.2)
- 'lazy' document layout information exposed to editor. This allows a progress bar to show user current state of document layout. (see Word and Pages, and watch the page count)
- 'printing' documents moved out of document, which can't print without a layout, and into layout.
In the not done but plan to do list.
- non root frames in QTextDocument (e.g. for footers, headers, word style annotations)
- QTextLines to be positioned only in terms of QTextLayouts. These in turn will keep track of their own clip region. Rather than shifting each line if a paragraph moves down, just the layout will be shifted. Lines only affected if the clip shape of the paragraph changes.
- QTextLayout to QObject. This is so we get Q_PROPERTY and start being able to enable animation hooks.
So, once again sorry for not posting this to dev earlier, and sorry if its too late in the process for this to matter. In practical terms I can only do minor work and advice on the above until mid-January, which may further hinder the ability of any of this to make it into Qt 5.
And I know someone is going to ask so I'm just going to explain why this wasn't done under LGPL (or pushed to Qt) in the first place. It represents close to a years worth of man hours. That means for it to be worth pushing to a public project like Qt the return has to be visible, otherwise you just are paying developers to give competitors a leg up in competing with you. That return would be help in maintaining said features (and in this case, Qt's QA). Very little of what has been done in Scrivener would have been accepted into the 4 series so we didn't even look to get it integrated into the 4 series.
More information about the Development