summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNils Jeisecke <jeisecke@saltation.de>2015-12-17 16:38:15 +0100
committerNils Jeisecke <nils.jeisecke@saltation.com>2019-08-19 20:59:12 +0200
commitd8a9bec35fb0c60a0e5990c1a12ffe6f39fdbf2d (patch)
treef2682539a00af01d617d744f1c28510988639beb
parent8240c24866550c4c083a7c1020d0b1b1bb7c8329 (diff)
QTextDocument: add css-styling of table cell borders to HTML import/export
Supported style attributes: <table> style: supports "border-collapse: collapse" and "border-color". border: width of the outer border bordercolor: basic color for all borders <tr> style: not supported <td>/</th> style: supports the "border", "border-[top|left|bottom|right]]" shorthand styles and the "border-width", "border-color" and "border-style" (and the top/left/bottom/right variants) attributes <table border=1 style="border-collapse: collapse"> will render a simple 1px table grid. Notes: The QTextDocument table model is much simpler than the HTML table model. It basically only has <table> and <td> support. So the HTML parser is forced to map markup and styling to the QTextDocument model which is not without loss. In other words: While QTextDocument -> HTML -> QTextDocument should preserve the QTextDocument structure, HTML -> QTextDocument -> HTML does not preserve the HTML DOM at all. So for now the HTML importer and writer only support border styles on the <td> and <th> nodes. In future updates, the HTML parser might be enhanced to map <tr> and <table> CSS styles to the cells. Change-Id: If9e7312fa6cbf270cf8f7b3c72ba1fa094107517 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/gui/text/qcssparser.cpp9
-rw-r--r--src/gui/text/qcssparser_p.h2
-rw-r--r--src/gui/text/qtextdocument.cpp80
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp26
-rw-r--r--src/gui/text/qtexthtmlparser.cpp34
-rw-r--r--src/gui/text/qtexthtmlparser_p.h8
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp29
-rw-r--r--tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp134
-rw-r--r--tests/auto/gui/text/qtexttable/tst_qtexttable.cpp108
9 files changed, 401 insertions, 29 deletions
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 45f1ca596e..0b2dedf5dc 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -92,6 +92,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "border-bottom-right-radius", BorderBottomRightRadius },
{ "border-bottom-style", BorderBottomStyle },
{ "border-bottom-width", BorderBottomWidth },
+ { "border-collapse", BorderCollapse },
{ "border-color", BorderColor },
{ "border-image", BorderImage },
{ "border-left", BorderLeft },
@@ -1732,6 +1733,14 @@ void Declaration::borderImageValue(QString *image, int *cuts,
*h = *v;
}
+bool Declaration::borderCollapseValue() const
+{
+ if (d->values.count() != 1)
+ return false;
+ else
+ return d->values.at(0).toString() == QLatin1String("collapse");
+}
+
QIcon Declaration::iconValue() const
{
if (d->parsed.isValid())
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index ddc46803ae..ab85e76cf3 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -122,6 +122,7 @@ enum Property {
BorderRight,
BorderTop,
BorderBottom,
+ BorderCollapse,
Padding,
PaddingLeft,
PaddingRight,
@@ -478,6 +479,7 @@ struct Q_GUI_EXPORT Declaration
QIcon iconValue() const;
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
+ bool borderCollapseValue() const;
};
QT_CSS_DECLARE_TYPEINFO(Declaration, Q_MOVABLE_TYPE)
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index dc34a96918..c80617f929 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2593,51 +2593,43 @@ void QTextHtmlExporter::emitFloatStyle(QTextFrameFormat::Position pos, StyleMode
html += QLatin1Char('\"');
}
-void QTextHtmlExporter::emitBorderStyle(QTextFrameFormat::BorderStyle style)
+static QLatin1String richtextBorderStyleToHtmlBorderStyle(QTextFrameFormat::BorderStyle style)
{
- Q_ASSERT(style <= QTextFrameFormat::BorderStyle_Outset);
-
- html += QLatin1String(" border-style:");
-
switch (style) {
case QTextFrameFormat::BorderStyle_None:
- html += QLatin1String("none");
- break;
+ return QLatin1String("none");
case QTextFrameFormat::BorderStyle_Dotted:
- html += QLatin1String("dotted");
- break;
+ return QLatin1String("dotted");
case QTextFrameFormat::BorderStyle_Dashed:
- html += QLatin1String("dashed");
- break;
+ return QLatin1String("dashed");
case QTextFrameFormat::BorderStyle_Solid:
- html += QLatin1String("solid");
- break;
+ return QLatin1String("solid");
case QTextFrameFormat::BorderStyle_Double:
- html += QLatin1String("double");
- break;
+ return QLatin1String("double");
case QTextFrameFormat::BorderStyle_DotDash:
- html += QLatin1String("dot-dash");
- break;
+ return QLatin1String("dot-dash");
case QTextFrameFormat::BorderStyle_DotDotDash:
- html += QLatin1String("dot-dot-dash");
- break;
+ return QLatin1String("dot-dot-dash");
case QTextFrameFormat::BorderStyle_Groove:
- html += QLatin1String("groove");
- break;
+ return QLatin1String("groove");
case QTextFrameFormat::BorderStyle_Ridge:
- html += QLatin1String("ridge");
- break;
+ return QLatin1String("ridge");
case QTextFrameFormat::BorderStyle_Inset:
- html += QLatin1String("inset");
- break;
+ return QLatin1String("inset");
case QTextFrameFormat::BorderStyle_Outset:
- html += QLatin1String("outset");
- break;
+ return QLatin1String("outset");
default:
- Q_ASSERT(false);
- break;
+ Q_UNREACHABLE();
};
+ return QLatin1String("");
+}
+
+void QTextHtmlExporter::emitBorderStyle(QTextFrameFormat::BorderStyle style)
+{
+ Q_ASSERT(style <= QTextFrameFormat::BorderStyle_Outset);
+ html += QLatin1String(" border-style:");
+ html += richtextBorderStyleToHtmlBorderStyle(style);
html += QLatin1Char(';');
}
@@ -3204,6 +3196,33 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
if (cellFormat.hasProperty(QTextFormat::TableCellBottomPadding))
styleString += QLatin1String(" padding-bottom:") + QString::number(cellFormat.bottomPadding()) + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellTopBorder))
+ styleString += QLatin1String(" border-top:") + QString::number(cellFormat.topBorder()) + QLatin1String("px;");
+ if (cellFormat.hasProperty(QTextFormat::TableCellRightBorder))
+ styleString += QLatin1String(" border-right:") + QString::number(cellFormat.rightBorder()) + QLatin1String("px;");
+ if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorder))
+ styleString += QLatin1String(" border-bottom:") + QString::number(cellFormat.bottomBorder()) + QLatin1String("px;");
+ if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorder))
+ styleString += QLatin1String(" border-left:") + QString::number(cellFormat.leftBorder()) + QLatin1String("px;");
+
+ if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderBrush))
+ styleString += QLatin1String(" border-top-color:") + cellFormat.topBorderBrush().color().name() + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderBrush))
+ styleString += QLatin1String(" border-right-color:") + cellFormat.rightBorderBrush().color().name() + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderBrush))
+ styleString += QLatin1String(" border-bottom-color:") + cellFormat.bottomBorderBrush().color().name() + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderBrush))
+ styleString += QLatin1String(" border-left-color:") + cellFormat.leftBorderBrush().color().name() + QLatin1Char(';');
+
+ if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderStyle))
+ styleString += QLatin1String(" border-top-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.topBorderStyle()) + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderStyle))
+ styleString += QLatin1String(" border-right-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.rightBorderStyle()) + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderStyle))
+ styleString += QLatin1String(" border-bottom-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.bottomBorderStyle()) + QLatin1Char(';');
+ if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderStyle))
+ styleString += QLatin1String(" border-left-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.leftBorderStyle()) + QLatin1Char(';');
+
if (!styleString.isEmpty())
html += QLatin1String(" style=\"") + styleString + QLatin1Char('\"');
@@ -3310,6 +3329,9 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType
QString::number(format.leftMargin()),
QString::number(format.rightMargin()));
+ if (format.property(QTextFormat::TableBorderCollapse).toBool())
+ html += QLatin1String(" border-collapse:collapse;");
+
if (html.length() == originalHtmlLength) // nothing emitted?
html.chop(styleAttribute.size());
else
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index 8ad1300e6c..778493d4bc 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -986,6 +986,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
tableFmt.setColumns(table.columns);
tableFmt.setColumnWidthConstraints(columnWidths);
tableFmt.setHeaderRowCount(tableHeaderRowCount);
+ tableFmt.setBorderCollapse(node.borderCollapse);
fmt = tableFmt;
}
@@ -1061,6 +1062,31 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode()
fmt.setLeftPadding(leftPadding(currentNodeIdx));
if (rightPadding(currentNodeIdx) >= 0)
fmt.setRightPadding(rightPadding(currentNodeIdx));
+ if (tableCellBorder(currentNodeIdx, QCss::TopEdge) > 0)
+ fmt.setTopBorder(tableCellBorder(currentNodeIdx, QCss::TopEdge));
+ if (tableCellBorder(currentNodeIdx, QCss::RightEdge) > 0)
+ fmt.setRightBorder(tableCellBorder(currentNodeIdx, QCss::RightEdge));
+ if (tableCellBorder(currentNodeIdx, QCss::BottomEdge) > 0)
+ fmt.setBottomBorder(tableCellBorder(currentNodeIdx, QCss::BottomEdge));
+ if (tableCellBorder(currentNodeIdx, QCss::LeftEdge) > 0)
+ fmt.setLeftBorder(tableCellBorder(currentNodeIdx, QCss::LeftEdge));
+ if (tableCellBorderStyle(currentNodeIdx, QCss::TopEdge) != QTextFrameFormat::BorderStyle_None)
+ fmt.setTopBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::TopEdge));
+ if (tableCellBorderStyle(currentNodeIdx, QCss::RightEdge) != QTextFrameFormat::BorderStyle_None)
+ fmt.setRightBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::RightEdge));
+ if (tableCellBorderStyle(currentNodeIdx, QCss::BottomEdge) != QTextFrameFormat::BorderStyle_None)
+ fmt.setBottomBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::BottomEdge));
+ if (tableCellBorderStyle(currentNodeIdx, QCss::LeftEdge) != QTextFrameFormat::BorderStyle_None)
+ fmt.setLeftBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::LeftEdge));
+ if (tableCellBorderBrush(currentNodeIdx, QCss::TopEdge) != Qt::NoBrush)
+ fmt.setTopBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::TopEdge));
+ if (tableCellBorderBrush(currentNodeIdx, QCss::RightEdge) != Qt::NoBrush)
+ fmt.setRightBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::RightEdge));
+ if (tableCellBorderBrush(currentNodeIdx, QCss::BottomEdge) != Qt::NoBrush)
+ fmt.setBottomBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::BottomEdge));
+ if (tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge) != Qt::NoBrush)
+ fmt.setLeftBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge));
+
cell.setFormat(fmt);
cursor.setPosition(cell.firstPosition());
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 43b32e7e2c..5d37982a8b 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -491,12 +491,19 @@ QTextHtmlParserNode::QTextHtmlParserNode()
listStyle(QTextListFormat::ListStyleUndefined), imageWidth(-1), imageHeight(-1), tableBorder(0),
tableCellRowSpan(1), tableCellColSpan(1), tableCellSpacing(2), tableCellPadding(0),
borderBrush(Qt::darkGray), borderStyle(QTextFrameFormat::BorderStyle_Outset),
+ borderCollapse(false),
userState(-1), cssListIndent(0), wsm(WhiteSpaceModeUndefined)
{
margin[QTextHtmlParser::MarginLeft] = 0;
margin[QTextHtmlParser::MarginRight] = 0;
margin[QTextHtmlParser::MarginTop] = 0;
margin[QTextHtmlParser::MarginBottom] = 0;
+
+ for (int i = 0; i < 4; ++i) {
+ tableCellBorderStyle[i] = QTextFrameFormat::BorderStyle_None;
+ tableCellBorder[i] = 0;
+ tableCellBorderBrush[i] = Qt::NoBrush;
+ }
}
void QTextHtmlParser::dumpHtml()
@@ -1169,6 +1176,25 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
QCss::ValueExtractor extractor(declarations);
extractor.extractBox(margin, padding);
+ if (id == Html_td || id == Html_th) {
+ QCss::BorderStyle cssStyles[4];
+ int cssBorder[4];
+ QSize cssRadii[4]; // unused
+ for (int i = 0; i < 4; ++i) {
+ cssStyles[i] = QCss::BorderStyle_None;
+ cssBorder[i] = 0;
+ }
+ // this will parse (and cache) "border-width" as a list so the
+ // QCss::BorderWidth parsing below which expects a single value
+ // will not work as expected - which in this case does not matter
+ // because tableBorder is not relevant for cells.
+ extractor.extractBorder(cssBorder, tableCellBorderBrush, cssStyles, cssRadii);
+ for (int i = 0; i < 4; ++i) {
+ tableCellBorderStyle[i] = static_cast<QTextFrameFormat::BorderStyle>(cssStyles[i] - 1);
+ tableCellBorder[i] = static_cast<qreal>(cssBorder[i]);
+ }
+ }
+
for (int i = 0; i < declarations.count(); ++i) {
const QCss::Declaration &decl = declarations.at(i);
if (decl.d->values.isEmpty()) continue;
@@ -1186,6 +1212,9 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::BorderWidth:
tableBorder = extractor.lengthValue(decl);
break;
+ case QCss::BorderCollapse:
+ borderCollapse = decl.borderCollapseValue();
+ break;
case QCss::Color: charFormat.setForeground(decl.colorValue()); break;
case QCss::Float:
cssFloat = QTextFrameFormat::InFlow;
@@ -1654,6 +1683,11 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setBackground(c);
+ } else if (key == QLatin1String("bordercolor")) {
+ QColor c; c.setNamedColor(value);
+ if (!c.isValid())
+ qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
+ node->borderBrush = c;
} else if (key == QLatin1String("background")) {
node->applyBackgroundImage(value, resourceProvider);
} else if (key == QLatin1String("cellspacing")) {
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index ff5f5b4c35..31f558709f 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -195,8 +195,12 @@ struct QTextHtmlParserNode {
int tableCellColSpan;
qreal tableCellSpacing;
qreal tableCellPadding;
+ qreal tableCellBorder[4];
+ QBrush tableCellBorderBrush[4];
+ QTextFrameFormat::BorderStyle tableCellBorderStyle[4];
QBrush borderBrush;
QTextFrameFormat::BorderStyle borderStyle;
+ bool borderCollapse;
int userState;
int cssListIndent;
@@ -290,6 +294,10 @@ public:
inline int leftPadding(int i) const { return at(i).padding[MarginLeft]; }
inline int rightPadding(int i) const { return at(i).padding[MarginRight]; }
+ inline qreal tableCellBorder(int i, int edge) const { return at(i).tableCellBorder[edge]; }
+ inline QTextFrameFormat::BorderStyle tableCellBorderStyle(int i, int edge) const { return at(i).tableCellBorderStyle[edge]; }
+ inline QBrush tableCellBorderBrush(int i, int edge) const { return at(i).tableCellBorderBrush[edge]; }
+
void dumpHtml();
void parse(const QString &text, const QTextDocument *resourceProvider);
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 58810f73c1..52e56feb5a 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -50,6 +50,7 @@
#include <QDomDocument>
#include "common.h"
+// #define DEBUG_WRITE_OUTPUT
QT_FORWARD_DECLARE_CLASS(QTextDocument)
@@ -196,6 +197,7 @@ private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
static QString cssFontSizeString(const QFont &font);
+ void writeActualAndExpected(const char* testTag, const QString &actual, const QString &expected);
QTextDocument *doc;
QTextCursor cursor;
@@ -224,6 +226,27 @@ QString tst_QTextDocument::cssFontSizeString(const QFont &font)
: QString::number(font.pixelSize()) + QStringLiteral("px");
}
+void tst_QTextDocument::writeActualAndExpected(const char *testTag, const QString &actual, const QString &expected)
+{
+#ifdef DEBUG_WRITE_OUTPUT
+ {
+ QFile out(QDir::temp().absoluteFilePath(QLatin1String(testTag) + QLatin1String("-actual.html")));
+ out.open(QFile::WriteOnly);
+ out.write(actual.toUtf8());
+ out.close();
+ } {
+ QFile out(QDir::temp().absoluteFilePath(QLatin1String(testTag) + QLatin1String("-expected.html")));
+ out.open(QFile::WriteOnly);
+ out.write(expected.toUtf8());
+ out.close();
+ }
+#else
+ Q_UNUSED(testTag)
+ Q_UNUSED(actual)
+ Q_UNUSED(expected)
+#endif
+}
+
// Testing get/set functions
void tst_QTextDocument::getSetCheck()
{
@@ -1765,6 +1788,8 @@ void tst_QTextDocument::toHtml()
QString output = doc->toHtml();
+ writeActualAndExpected(QTest::currentDataTag(), output, expectedOutput);
+
QCOMPARE(output, expectedOutput);
QDomDocument document;
@@ -1962,6 +1987,8 @@ void tst_QTextDocument::toHtmlRootFrameProperties()
expectedOutput.replace("DEFAULTBLOCKSTYLE", "style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"");
expectedOutput.append(htmlTail);
+ writeActualAndExpected(QTest::currentTestFunction(), doc.toHtml(), expectedOutput);
+
QCOMPARE(doc.toHtml(), expectedOutput);
}
@@ -2734,6 +2761,8 @@ void tst_QTextDocument::backgroundImage_checkExpectedHtml(const QTextDocument &d
.arg(defaultFont.weight() * 8)
.arg((defaultFont.italic() ? "italic" : "normal"));
+ writeActualAndExpected(QTest::currentTestFunction(), doc.toHtml(), expectedHtml);
+
QCOMPARE(doc.toHtml(), expectedHtml);
}
diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
index c5243d1535..b6917f1208 100644
--- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
+++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp
@@ -181,6 +181,11 @@ private slots:
void html_tableCellBackground();
void css_bodyBackground();
void css_tableCellBackground();
+ void css_tableCellBorder();
+ void css_tableCellBorderShorthand();
+ void css_tableCellAllBordersShorthand();
+ void css_tableCellOverrideOneBorder();
+ void css_tableBorderCollapse();
void css_fontWeight();
void css_float();
void css_textIndent();
@@ -1753,6 +1758,135 @@ void tst_QTextDocumentFragment::css_tableCellBackground()
QCOMPARE(cell.format().background().style(), Qt::TexturePattern);
}
+void tst_QTextDocumentFragment::css_tableCellBorder()
+{
+ const char html[] = "<body><table><tr><td style=\"border-width:8px;border-color:green;border-style:groove;border-left-style:dashed;border-left-color:red;border-left-width:4px\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(4));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(8));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(8));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(8));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Groove);
+}
+
+void tst_QTextDocumentFragment::css_tableCellBorderShorthand()
+{
+ const char html[] = "<body><table><tr><td style=\"border-left:1px solid green;border-right:2px dashed red;border-bottom:3px dotted yellow;border-top:4px dot-dash blue\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(1));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Solid);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(3));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("yellow")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dotted);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(4));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("blue")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_DotDash);
+}
+
+void tst_QTextDocumentFragment::css_tableCellAllBordersShorthand()
+{
+ const char html[] = "<body><table><tr><td style=\"border:2px dashed green\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(2));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(2));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(2));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+}
+
+void tst_QTextDocumentFragment::css_tableCellOverrideOneBorder()
+{
+ const char html[] = "<body><table><tr><td style=\"border:2px dashed green;border-left:4px solid red\">Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QTextTableCell cell = table->cellAt(0, 0);
+ QTextTableCellFormat cellFormat = cell.format().toTableCellFormat();
+ QCOMPARE(cellFormat.leftBorder(), qreal(4));
+ QCOMPARE(cellFormat.leftBorderBrush(), QBrush(QColor("red")));
+ QCOMPARE(cellFormat.leftBorderStyle(), QTextFrameFormat::BorderStyle_Solid);
+
+ QCOMPARE(cellFormat.rightBorder(), qreal(2));
+ QCOMPARE(cellFormat.rightBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.rightBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.bottomBorder(), qreal(2));
+ QCOMPARE(cellFormat.bottomBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.bottomBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+
+ QCOMPARE(cellFormat.topBorder(), qreal(2));
+ QCOMPARE(cellFormat.topBorderBrush(), QBrush(QColor("green")));
+ QCOMPARE(cellFormat.topBorderStyle(), QTextFrameFormat::BorderStyle_Dashed);
+}
+
+void tst_QTextDocumentFragment::css_tableBorderCollapse()
+{
+ const char html[] = "<body><table style=\"border-collapse:collapse\"><tr><td>Foo</td></tr></table></body>";
+ doc->setHtml(html);
+
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::NextBlock);
+ QTextTable *table = cursor.currentTable();
+ QVERIFY(table);
+
+ QCOMPARE(table->format().borderCollapse(), true);
+}
+
void tst_QTextDocumentFragment::css_cellPaddings()
{
const char html[] = "<body><table><tr><td style=\"padding-left:1\">Foo</td>"
diff --git a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
index f21b969aa7..7b2ff4cc10 100644
--- a/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
+++ b/tests/auto/gui/text/qtexttable/tst_qtexttable.cpp
@@ -50,6 +50,8 @@ typedef QList<int> IntList;
QT_FORWARD_DECLARE_CLASS(QTextDocument)
+Q_DECLARE_METATYPE(QTextFrameFormat::BorderStyle);
+
class tst_QTextTable : public QObject
{
Q_OBJECT
@@ -95,6 +97,8 @@ private slots:
#if !defined(QT_NO_PRINTER) && defined(QT_BUILD_INTERNAL)
void QTBUG31330_renderBackground();
#endif
+ void checkBorderAttributes_data();
+ void checkBorderAttributes();
private:
QTextTable *create2x2Table();
@@ -1170,5 +1174,109 @@ void tst_QTextTable::QTBUG31330_renderBackground()
}
#endif
+void tst_QTextTable::checkBorderAttributes_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<qreal>("topBorderWidth");
+ QTest::addColumn<qreal>("bottomBorderWidth");
+ QTest::addColumn<qreal>("leftBorderWidth");
+ QTest::addColumn<qreal>("rightBorderWidth");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("topBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("bottomBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("leftBorderStyle");
+ QTest::addColumn<QTextFrameFormat::BorderStyle>("rightBorderStyle");
+ QTest::addColumn<QBrush>("topBorderBrush");
+ QTest::addColumn<QBrush>("bottomBorderBrush");
+ QTest::addColumn<QBrush>("leftBorderBrush");
+ QTest::addColumn<QBrush>("rightBorderBrush");
+
+ const QString tableHtmlStart = QStringLiteral("<html><head><style>");
+ const QString tableHtmlEnd = QStringLiteral("</style></head><body>"
+ "<table border=\"1\"><tr><td>One</td><td>Two</td></tr>"
+ "<tr><td>Three</td><td>Four</td></tr></table></body></html>");
+ QTest::newRow("1px-solid-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 1px solid blue;"
+ "border-left: 1px solid green;"
+ "border-right: 1px solid yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 1.0 << 1.0 << 1.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+ QTest::newRow("MixedWidth-solid-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 2px solid blue;"
+ "border-left: 3px solid green;"
+ "border-right: 4px solid yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 2.0 << 3.0 << 4.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Solid
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+ QTest::newRow("MixedWidth-MixedStyle-colors")
+ << QString("%1"
+ "td {"
+ "border-top: 1px solid red;"
+ "border-bottom: 2px dotted blue;"
+ "border-left: 3px dashed green;"
+ "border-right: 4px inset yellow;"
+ "}"
+ "%2").arg(tableHtmlStart).arg(tableHtmlEnd)
+ << 1.0 << 2.0 << 3.0 << 4.0
+ << QTextFrameFormat::BorderStyle_Solid << QTextFrameFormat::BorderStyle_Dotted
+ << QTextFrameFormat::BorderStyle_Dashed << QTextFrameFormat::BorderStyle_Inset
+ << QBrush(Qt::red) << QBrush(Qt::blue) << QBrush(Qt::darkGreen) << QBrush(Qt::yellow);
+}
+
+void tst_QTextTable::checkBorderAttributes()
+{
+ QFETCH(QString, html);
+ QFETCH(qreal, topBorderWidth);
+ QFETCH(qreal, bottomBorderWidth);
+ QFETCH(qreal, leftBorderWidth);
+ QFETCH(qreal, rightBorderWidth);
+ QFETCH(QTextFrameFormat::BorderStyle, topBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, bottomBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, leftBorderStyle);
+ QFETCH(QTextFrameFormat::BorderStyle, rightBorderStyle);
+ QFETCH(QBrush, topBorderBrush);
+ QFETCH(QBrush, bottomBorderBrush);
+ QFETCH(QBrush, leftBorderBrush);
+ QFETCH(QBrush, rightBorderBrush);
+
+ QTextDocument doc;
+ doc.setHtml(html);
+ QTextCursor cursor(doc.firstBlock());
+ cursor.movePosition(QTextCursor::Right);
+
+ QTextTable *currentTable = cursor.currentTable();
+ QVERIFY(currentTable);
+ for (int row = 0; row < 2; row++) {
+ for (int column = 0; column < 2; column++) {
+ QTextTableCell cell = currentTable->cellAt(row, column);
+ QTextCharFormat cellFormat = cell.format();
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellTopBorder), topBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellBottomBorder), bottomBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellLeftBorder), leftBorderWidth);
+ QCOMPARE(cellFormat.doubleProperty(QTextFormat::TableCellRightBorder), rightBorderWidth);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellTopBorderStyle), topBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellBottomBorderStyle), bottomBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellLeftBorderStyle), leftBorderStyle);
+ QCOMPARE(cellFormat.property(QTextFormat::TableCellRightBorderStyle), rightBorderStyle);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellTopBorderBrush), topBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellBottomBorderBrush), bottomBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellLeftBorderBrush), leftBorderBrush);
+ QCOMPARE(cellFormat.brushProperty(QTextFormat::TableCellRightBorderBrush), rightBorderBrush);
+ }
+ }
+}
+
QTEST_MAIN(tst_QTextTable)
#include "tst_qtexttable.moc"