Add css media rule support for QTextDocument::setHtml()

CSS styles can contain '@media <rule> {...}' blocks, which were
previously ignored for all values except "screen".

To use a media rule other than the default "screen" rule,
specify it before calling setHtml() with setMetaInformation()
and the new info value 'CssMedia'.

[ChangeLog][Gui][QTextDocument] Add css media rule support
for QTextDocument::setHtml()

Pick-to: 6.3
Fixes: QTBUG-98408
Change-Id: Ie05f815a6dedbd970210f467e26b116f6ee3b9ca
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Ralf Habacker 2021-11-17 13:54:32 +01:00 committed by Shawn Rutledge
parent ff97c81642
commit 2e2f1e2af7
6 changed files with 58 additions and 5 deletions

View File

@ -351,6 +351,7 @@ QTextDocument *QTextDocument::clone(QObject *parent) const
QTextDocumentPrivate *priv = doc->d_func();
priv->title = d->title;
priv->url = d->url;
priv->cssMedia = d->cssMedia;
priv->pageSize = d->pageSize;
priv->indentWidth = d->indentWidth;
priv->defaultTextOption = d->defaultTextOption;
@ -1135,6 +1136,8 @@ QString QTextDocument::metaInformation(MetaInformation info) const
return d->title;
case DocumentUrl:
return d->url;
case CssMedia:
return d->cssMedia;
}
return QString();
}
@ -1155,6 +1158,9 @@ void QTextDocument::setMetaInformation(MetaInformation info, const QString &stri
case DocumentUrl:
d->url = string;
break;
case CssMedia:
d->cssMedia = string;
break;
}
}
@ -1242,11 +1248,14 @@ void QTextDocument::setPlainText(const QString &text)
"<b>bold</b> text" will produce text where the first word has a font
weight that gives it a bold appearance: "\b{bold} text".
To select a css media rule other than the default "screen" rule,
use setMetaInformation() with 'CssMedia' as "info" parameter.
\note It is the responsibility of the caller to make sure that the
text is correctly decoded when a QString containing HTML is created
and passed to setHtml().
\sa setPlainText(), {Supported HTML Subset}
\sa setPlainText(), {Supported HTML Subset}, setMetaInformation()
*/
#ifndef QT_NO_TEXTHTMLPARSER
@ -1286,8 +1295,11 @@ void QTextDocument::setHtml(const QString &html)
\value DocumentTitle The title of the document.
\value DocumentUrl The url of the document. The loadResource() function uses
this url as the base when loading relative resources.
\value CssMedia This value is used to select the corresponding '@media'
rule, if any, from a specified CSS stylesheet when setHtml()
is called. This enum value has been introduced in Qt 6.3.
\sa metaInformation(), setMetaInformation()
\sa metaInformation(), setMetaInformation(), setHtml()
*/
static bool findInBlock(const QTextBlock &block, const QString &expression, int offset,

View File

@ -136,7 +136,8 @@ public:
enum MetaInformation {
DocumentTitle,
DocumentUrl
DocumentUrl,
CssMedia
};
void setMetaInformation(MetaInformation info, const QString &);
QString metaInformation(MetaInformation info) const;

View File

@ -187,7 +187,8 @@ QTextDocumentPrivate::QTextDocumentPrivate()
framesDirty(true),
rtFrame(nullptr),
initialBlockCharFormatIndex(-1), // set correctly later in init()
resourceProvider(nullptr)
resourceProvider(nullptr),
cssMedia(QStringLiteral("screen"))
{
editBlock = 0;
editBlockCursorPosition = -1;

View File

@ -384,6 +384,7 @@ public:
QSizeF pageSize;
QString title;
QString url;
QString cssMedia;
qreal indentWidth;
qreal documentMargin;
QUrl baseUrl;

View File

@ -2165,7 +2165,7 @@ QList<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const
for (int i = 0; i < inlineStyleSheets.count(); ++i, ++idx)
selector.styleSheets[idx] = inlineStyleSheets.at(i);
selector.medium = QLatin1String("screen");
selector.medium = resourceProvider ? resourceProvider->metaInformation(QTextDocument::CssMedia) : QLatin1String("screen");
QCss::StyleSelector::NodePtr n;
n.id = node;

View File

@ -96,6 +96,7 @@ private slots:
void toHtml2();
void setFragmentMarkersInHtmlExport();
void setMediaRule();
void toHtmlBodyBgColor();
void toHtmlBodyBgColorRgba();
@ -1910,6 +1911,39 @@ void tst_QTextDocument::setFragmentMarkersInHtmlExport()
}
}
void tst_QTextDocument::setMediaRule()
{
{
CREATE_DOC_AND_CURSOR();
doc.setDefaultStyleSheet("@media screen { p { background:#000000 } } @media print { p { background:#ffffff } }");
doc.setHtml("<p>Hello World</p>");
QString expected = htmlHead;
expected += QString("<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#000000;\"><span style=\" background-color:#000000;\">Hello World</span></p>") + htmlTail;
QCOMPARE(doc.toHtml(), expected);
}
{
CREATE_DOC_AND_CURSOR();
doc.setDefaultStyleSheet("@media screen { p { background:#000000 } } @media print { p { background:#ffffff } }");
doc.setMetaInformation(QTextDocument::CssMedia, "screen");
doc.setHtml("<p>Hello World</p>");
QString expected = htmlHead;
expected += QString("<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#000000;\"><span style=\" background-color:#000000;\">Hello World</span></p>") + htmlTail;
QCOMPARE(doc.toHtml(), expected);
}
{
CREATE_DOC_AND_CURSOR();
doc.setDefaultStyleSheet("@media screen { p { background:#000000 } } @media print { p { background:#ffffff } }");
doc.setMetaInformation(QTextDocument::CssMedia, "print");
doc.setHtml("<p>Hello World</p>");
QString expected = htmlHead;
expected += QString("<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;\"><span style=\" background-color:#ffffff;\">Hello World</span></p>") + htmlTail;
QCOMPARE(doc.toHtml(), expected);
}
}
void tst_QTextDocument::toHtmlBodyBgColor()
{
CREATE_DOC_AND_CURSOR();
@ -2294,14 +2328,18 @@ void tst_QTextDocument::clonePreservesMetaInformation()
{
const QString title("Foobar");
const QString url("about:blank");
const QString media("print");
doc->setHtml("<html><head><title>" + title + "</title></head><body>Hrm</body></html>");
doc->setMetaInformation(QTextDocument::DocumentUrl, url);
doc->setMetaInformation(QTextDocument::CssMedia, media);
QCOMPARE(doc->metaInformation(QTextDocument::DocumentTitle), title);
QCOMPARE(doc->metaInformation(QTextDocument::DocumentUrl), url);
QCOMPARE(doc->metaInformation(QTextDocument::CssMedia), media);
QTextDocument *clone = doc->clone();
QCOMPARE(clone->metaInformation(QTextDocument::DocumentTitle), title);
QCOMPARE(clone->metaInformation(QTextDocument::DocumentUrl), url);
QCOMPARE(clone->metaInformation(QTextDocument::CssMedia), media);
delete clone;
}