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>
This commit is contained in:
parent
8240c24866
commit
d8a9bec35f
@ -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())
|
||||
|
@ -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)
|
||||
|
||||
|
@ -2593,51 +2593,43 @@ void QTextHtmlExporter::emitFloatStyle(QTextFrameFormat::Position pos, StyleMode
|
||||
html += QLatin1Char('\"');
|
||||
}
|
||||
|
||||
static QLatin1String richtextBorderStyleToHtmlBorderStyle(QTextFrameFormat::BorderStyle style)
|
||||
{
|
||||
switch (style) {
|
||||
case QTextFrameFormat::BorderStyle_None:
|
||||
return QLatin1String("none");
|
||||
case QTextFrameFormat::BorderStyle_Dotted:
|
||||
return QLatin1String("dotted");
|
||||
case QTextFrameFormat::BorderStyle_Dashed:
|
||||
return QLatin1String("dashed");
|
||||
case QTextFrameFormat::BorderStyle_Solid:
|
||||
return QLatin1String("solid");
|
||||
case QTextFrameFormat::BorderStyle_Double:
|
||||
return QLatin1String("double");
|
||||
case QTextFrameFormat::BorderStyle_DotDash:
|
||||
return QLatin1String("dot-dash");
|
||||
case QTextFrameFormat::BorderStyle_DotDotDash:
|
||||
return QLatin1String("dot-dot-dash");
|
||||
case QTextFrameFormat::BorderStyle_Groove:
|
||||
return QLatin1String("groove");
|
||||
case QTextFrameFormat::BorderStyle_Ridge:
|
||||
return QLatin1String("ridge");
|
||||
case QTextFrameFormat::BorderStyle_Inset:
|
||||
return QLatin1String("inset");
|
||||
case QTextFrameFormat::BorderStyle_Outset:
|
||||
return QLatin1String("outset");
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
};
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
void QTextHtmlExporter::emitBorderStyle(QTextFrameFormat::BorderStyle style)
|
||||
{
|
||||
Q_ASSERT(style <= QTextFrameFormat::BorderStyle_Outset);
|
||||
|
||||
html += QLatin1String(" border-style:");
|
||||
|
||||
switch (style) {
|
||||
case QTextFrameFormat::BorderStyle_None:
|
||||
html += QLatin1String("none");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Dotted:
|
||||
html += QLatin1String("dotted");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Dashed:
|
||||
html += QLatin1String("dashed");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Solid:
|
||||
html += QLatin1String("solid");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Double:
|
||||
html += QLatin1String("double");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_DotDash:
|
||||
html += QLatin1String("dot-dash");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_DotDotDash:
|
||||
html += QLatin1String("dot-dot-dash");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Groove:
|
||||
html += QLatin1String("groove");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Ridge:
|
||||
html += QLatin1String("ridge");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Inset:
|
||||
html += QLatin1String("inset");
|
||||
break;
|
||||
case QTextFrameFormat::BorderStyle_Outset:
|
||||
html += QLatin1String("outset");
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
};
|
||||
|
||||
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
|
||||
|
@ -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());
|
||||
|
@ -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")) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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>"
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user