[Development] CSS styling, XML, HTML etc. (was Re: Assistant WebKit/WebEngine support)

Shawn Rutledge Shawn.Rutledge at qt.io
Tue May 21 16:06:42 CEST 2019


> On 20 May 2019, at 18:56, Bastiaan Veelo <Bastiaan at Veelo.net> wrote:
> 
> On 20/05/2019 17:56, Konstantin Tokarev wrote:
>> 20.05.2019, 18:27, "Bastiaan Veelo" <bastiaan at veelo.net>:
>>> On 20/05/2019 16:51, Konstantin Tokarev wrote:
>>> ...
>> However, it would better to avoid duplicating work with Qt Creator,
>> which also implements HelpViewer interface with different backends.
>> Some time ago there was a discussion that such shared interface & plugin
>> system should belong to Qt Web View module. But that would  probably
>> require more work to be done.

If there is really a need to use WebEngine, a plugin makes sense.  Sharing a plugin between Creator and Assistant makes sense.  But I do worry about the runtime memory bloat that it will introduce.

>>> Or do you think that removing WebKit support from Assistant completely
>>> would be better, if WebEngine shows to be working well?
>> As for me, I'm totally fine with QTextBrowser
> 
> I wish that were true for me. We need colours in table cell borders and SVG images (and better CSS support would be real nice). This might help, but is stalled: https://codereview.qt-project.org/c/qt/qtbase/+/177256

I was just putting some thought into CSS over the last few days, but wasn’t aware of that patch.

I don’t like the limitation we have, that CSS can be applied only while parsing HTML, because after the parsing is done, there is no DOM: a lot of structural information from HTML is lost.  This is a limiting factor for my work with supporting Markdown in QTD lately: after you have read HTML, not enough information is saved to be able to write markdown as nicely as I’d like (it’s mostly possible to work around, but e.g. <pre> results in a separate block per line, and <blockquote> results in an indented plain paragraph, so the markdown writer has to reconstruct some of the structure by detecting those idiosyncrasies).  And of course there’s no support for applying CSS to markdown, precisely because of the fact that it can be applied only while the HTML parser is running, and in the markdown case there’s no HTML parser instance.  I’m loathe to take the same approach with markdown (apply CSS only while parsing), but I’d like to have CSS support for it.  For both HTML and Markdown it would be nice if CSS could be applied dynamically to an existing QTextDocument.  I don’t see a real reason why we shouldn’t be able to, as long as QTD stores enough information about the original structure (i.e. <H1> is not just a block with a particular font size and style: 310daae53926628f80c08e4415b94b90ad525c8f took care of that, because I couldn’t realistically get started with markdown support unless the heading blocks could at least remember their own heading levels).  Similar fixes could gradually turn QTD into something almost like a DOM, and could also turn the HTML-writing support into a lot less of a mess (be able to write out HTML that looks more like what you read in).  But it’s kindof frustrating work: I just keep wondering why stuff like that still needs to be done in 2019.

So I wonder if we should gradually fix that, or we would be better off replacing the guts of QTD with a proper DOM of some sort.  But of course it’s a slippery slope: QTextBrowser should never be as complex as a real browser.  So the knee-jerk reaction is to say “forget about it, use webengine”; but the other side of the argument is that it’s quite nice to have such a compact implementation as QTD/QTB are, and there are so many applications where a real browser engine is such terrible overkill.  I suspect that Konqueror must have had a time period where it had a suitably compact but architecturally better design, but I haven’t dug in deep enough to figure that out; several people should already know, anyway.

BTW, there is a movement to ditch qtxmlpatterns and replace it in the one use case that matters to Qt Quick (XmlListModel) with some other XML parser, something good enough for all use cases in the rest of Qt.  (Based on libxml2 maybe?)  So can we perhaps say these things are related: it’s OK to support only well-formed XHTML, not loosely-structured HTML, maybe we could use the same XML parser for both use cases, to reduce the code size and get a real DOM at the same time?  But it doesn’t make the CSS work any easier; the question is how much would QTD change if we take that approach.  And the DOM in qtxmlpatterns seems kindof cool too (feature-wise, although I don’t know much about the implementation); it’s just that nobody wants to support it.  But libxml2 has a DOM too, they say.  (I haven’t looked at the API yet.)

Another reason CSS came up is in the context of what to do with QStyle in Qt 6.  QSS is another thing that Qt developers have always been loathe to support, and yet the users keep on using it.  But there is a case where CSS can really be applied at runtime.  It has a reputation for being terrible for performance, but I didn’t really understand why until looking at a bug a couple of days ago (QTBUG-73251).  Still not sure how much of the performance penalty is endemic to the architecture (doing lots of runtime lookups in data structures to figure out what to do) vs. having a bit too much delegation going on between different style classes, such that there is even a loop detector to prevent infinite loops.  Anyway QSS is a case where the styling _is_ being applied at runtime, and that’s done by making another subclass of StyleSelector… so I just barely started going in the direction of maybe making another one that can try to apply styles directly to QTD at runtime.  But I’m doubtful about whether that could be a waste of time if we end up deciding that the current CSS implementation should be replaced, or changed drastically, or if QTD internals will be changed drastically.

Another idea: qml looks a bit like CSS, so maybe we should use QML for the styling language (just the declarative syntax, no JS, no imperative syntax at all).  One disadvantage is that web developers know CSS, so this would limit the opportunities for reusing stylesheets, and of course break backwards compatibility with QSS; but I wonder if we could get away with that, since these are minority use cases anyway (of all Qt applications, only a minority use either QSS or CSS), and writing styles shouldn’t be too hard (if it is, you’re making it too complicated).  Maybe we could write a converter or something.

Anyway I think Assistant is one of those cases where I would prefer to keep using QTextBrowser and fix it up a bit more to suit, rather than switching to a real browser engine.  Light weight is a real advantage.  Creator already takes up enough memory as it is, with its code model especially.  And documentation doesn’t need most of the fancy HTML features either.


Footnote: I tried to do a hand-wavey translation of a trivial CSS file to QML to see if the syntax could possibly make sense.  Didn’t really think about cascading or about CSS classes much, but the objects created by the declarations could have “class” properties I guess.  I don’t think QTD supports CSS classes in HTML yet either (?)

----

a { text-decoration: none; color: #660066; }
body { font: normal 400 28px/1.2 times, serif; }
blockquote {
  font: 32px italic helvetica, sans-serif;
  margin-top: 10px;
  margin-bottom: 10px;
  margin-left: 50px;
  padding-left: 15px;
  border-left: 3px solid #ccc;
}

----

import QtStyle 1.0 // hypothetical plugin that defines objects to hold CSS-like rules

// To make this work, we should ideally add:
// - units in QML
// - colors can be unquoted
// - multiple font families to have fallback
// - should declarations be Capitalized even though HTML and CSS tags often aren’t?

Anchor { // Or A, because that's how it is in HTML?
    font.underline: false
    color: "#6600FF" // Just color? should it be font.color?
}

Body {
    font {
        weight: Font.Normal
        pixelSize: 28
        // size: 28px would be better
        family: "Times"
        // families: ["Times", "Serif"] // order of preference would be better
        italic: true
    }
}

Blockquote { // This declaration says "When you see a blockquote, style it like this"
    font {
        pixelSize: 32
        family: "Helvetica"
        italic: true
    }
    margin {
        top: 10
        bottom: 10
        left: 50
    }
    padding.left: 15
    Border { // This nested declaration probably creates something (painter commands or SG node)
        sides: Border.left
        width: 3
        color: "#ccc" // ugh, I've always hated quoting colors: they aren't strings!
    }
}

----

Hmm which one would you rather write?  ;-)  QML is more familiar to developers but also more verbose.



More information about the Development mailing list