Add more formatting to QTextDocumentWriter when writing ODF files
QTextDocumentWriter only supports a small subset of table formatting when exporting to ODF-format. This patch adds more formatting capabilities to the ODF exporter: - table border support - table alignment - table width - respect column constraints (column widths) - add a tab before soft line breaks. This will avoid causing the last line to stretch all over the cell in justified paragraphs. With this patch, line height settings are now exported, too. [ChangeLog][QtGui][QDocumentWriter] QDocumentWriter now supports table borders, table alignment, table width, column widths, line height and image resolution when exporting QTextDocuments to ODF files. Task-number: QTBUG-63581 Change-Id: I2d269ef0f842e73af64d48bfef531d5fa3078088 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
f8e551cf08
commit
6a4b6971f4
@ -183,6 +183,35 @@ static QString bulletChar(QTextListFormat::Style style)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString borderStyleName(QTextFrameFormat::BorderStyle style)
|
||||||
|
{
|
||||||
|
switch (style) {
|
||||||
|
case QTextFrameFormat::BorderStyle_None:
|
||||||
|
return QString::fromLatin1("none");
|
||||||
|
case QTextFrameFormat::BorderStyle_Dotted:
|
||||||
|
return QString::fromLatin1("dotted");
|
||||||
|
case QTextFrameFormat::BorderStyle_Dashed:
|
||||||
|
return QString::fromLatin1("dashed");
|
||||||
|
case QTextFrameFormat::BorderStyle_Solid:
|
||||||
|
return QString::fromLatin1("solid");
|
||||||
|
case QTextFrameFormat::BorderStyle_Double:
|
||||||
|
return QString::fromLatin1("double");
|
||||||
|
case QTextFrameFormat::BorderStyle_DotDash:
|
||||||
|
return QString::fromLatin1("dashed");
|
||||||
|
case QTextFrameFormat::BorderStyle_DotDotDash:
|
||||||
|
return QString::fromLatin1("dotted");
|
||||||
|
case QTextFrameFormat::BorderStyle_Groove:
|
||||||
|
return QString::fromLatin1("groove");
|
||||||
|
case QTextFrameFormat::BorderStyle_Ridge:
|
||||||
|
return QString::fromLatin1("ridge");
|
||||||
|
case QTextFrameFormat::BorderStyle_Inset:
|
||||||
|
return QString::fromLatin1("inset");
|
||||||
|
case QTextFrameFormat::BorderStyle_Outset:
|
||||||
|
return QString::fromLatin1("outset");
|
||||||
|
}
|
||||||
|
return QString::fromLatin1("");
|
||||||
|
}
|
||||||
|
|
||||||
void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame)
|
void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame)
|
||||||
{
|
{
|
||||||
Q_ASSERT(frame);
|
Q_ASSERT(frame);
|
||||||
@ -190,8 +219,21 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
|
|||||||
|
|
||||||
if (table) { // Start a table.
|
if (table) { // Start a table.
|
||||||
writer.writeStartElement(tableNS, QString::fromLatin1("table"));
|
writer.writeStartElement(tableNS, QString::fromLatin1("table"));
|
||||||
writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
|
writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
|
||||||
writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"), QString::number(table->columns()));
|
QString::fromLatin1("Table%1").arg(table->formatIndex()));
|
||||||
|
// check if column widths are set, if so add TableNS line above for all columns and link to style
|
||||||
|
if (m_tableFormatsWithColWidthConstraints.contains(table->formatIndex())) {
|
||||||
|
for (int colit = 0; colit < table->columns(); ++colit) {
|
||||||
|
writer.writeStartElement(tableNS, QString::fromLatin1("table-column"));
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
|
||||||
|
QString::fromLatin1("Table%1.%2").arg(table->formatIndex()).arg(colit));
|
||||||
|
writer.writeEndElement();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"),
|
||||||
|
QString::number(table->columns()));
|
||||||
|
}
|
||||||
} else if (frame->document() && frame->document()->rootFrame() != frame) { // start a section
|
} else if (frame->document() && frame->document()->rootFrame() != frame) { // start a section
|
||||||
writer.writeStartElement(textNS, QString::fromLatin1("section"));
|
writer.writeStartElement(textNS, QString::fromLatin1("section"));
|
||||||
}
|
}
|
||||||
@ -219,7 +261,15 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
|
|||||||
if (cell.rowSpan() > 1)
|
if (cell.rowSpan() > 1)
|
||||||
writer.writeAttribute(tableNS, QString::fromLatin1("number-rows-spanned"), QString::number(cell.rowSpan()));
|
writer.writeAttribute(tableNS, QString::fromLatin1("number-rows-spanned"), QString::number(cell.rowSpan()));
|
||||||
if (cell.format().isTableCellFormat()) {
|
if (cell.format().isTableCellFormat()) {
|
||||||
writer.writeAttribute(tableNS, QString::fromLatin1("style-name"), QString::fromLatin1("T%1").arg(cell.tableCellFormatIndex()));
|
if (m_cellFormatsInTablesWithBorders.contains(cell.tableCellFormatIndex()) ) {
|
||||||
|
// writing table:style-name tag in <table:table-cell> element
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
|
||||||
|
QString::fromLatin1("TB%1.%2").arg(table->formatIndex())
|
||||||
|
.arg(cell.tableCellFormatIndex()));
|
||||||
|
} else {
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
|
||||||
|
QString::fromLatin1("T%1").arg(cell.tableCellFormatIndex()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeBlock(writer, block);
|
writeBlock(writer, block);
|
||||||
@ -326,7 +376,10 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
|
|||||||
if (i < fragmentText.count()) {
|
if (i < fragmentText.count()) {
|
||||||
if (character.unicode() == 0x2028) { // soft-return
|
if (character.unicode() == 0x2028) { // soft-return
|
||||||
//if (exportedIndex < i)
|
//if (exportedIndex < i)
|
||||||
writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
|
writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
|
||||||
|
// adding tab before line-break, so last line in justified paragraph
|
||||||
|
// will not stretch to the end
|
||||||
|
writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
|
||||||
writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
|
writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
|
||||||
exportedIndex = i+1;
|
exportedIndex = i+1;
|
||||||
continue;
|
continue;
|
||||||
@ -387,7 +440,6 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ^^^ Copy pasted mostly from Qt =================
|
|
||||||
if (! image.isNull()) {
|
if (! image.isNull()) {
|
||||||
QBuffer imageBytes;
|
QBuffer imageBytes;
|
||||||
QImageWriter imageWriter(&imageBytes, "png");
|
QImageWriter imageWriter(&imageBytes, "png");
|
||||||
@ -396,17 +448,17 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
|
|||||||
m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
|
m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
|
||||||
|
|
||||||
// get the width/height from the format.
|
// get the width/height from the format.
|
||||||
qreal width = (imageFormat.hasProperty(QTextFormat::ImageWidth)) ? imageFormat.width() : image.width();
|
qreal width = imageFormat.hasProperty(QTextFormat::ImageWidth)
|
||||||
|
? imageFormat.width() : image.width();
|
||||||
writer.writeAttribute(svgNS, QString::fromLatin1("width"), pixelToPoint(width));
|
writer.writeAttribute(svgNS, QString::fromLatin1("width"), pixelToPoint(width));
|
||||||
qreal height = (imageFormat.hasProperty(QTextFormat::ImageHeight)) ? imageFormat.height() : image.height();
|
qreal height = imageFormat.hasProperty(QTextFormat::ImageHeight)
|
||||||
|
? imageFormat.height() : image.height();
|
||||||
writer.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height));
|
writer.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height));
|
||||||
|
|
||||||
writer.writeStartElement(drawNS, QString::fromLatin1("image"));
|
writer.writeStartElement(drawNS, QString::fromLatin1("image"));
|
||||||
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
|
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
|
||||||
writer.writeEndElement(); // image
|
writer.writeEndElement(); // image
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeEndElement(); // frame
|
writer.writeEndElement(); // frame
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,7 +473,7 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
|
|||||||
switch (textFormat.type()) {
|
switch (textFormat.type()) {
|
||||||
case QTextFormat::CharFormat:
|
case QTextFormat::CharFormat:
|
||||||
if (textFormat.isTableCellFormat())
|
if (textFormat.isTableCellFormat())
|
||||||
writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex);
|
writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex, allStyles);
|
||||||
else
|
else
|
||||||
writeCharacterFormat(writer, textFormat.toCharFormat(), formatIndex);
|
writeCharacterFormat(writer, textFormat.toCharFormat(), formatIndex);
|
||||||
break;
|
break;
|
||||||
@ -432,10 +484,15 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
|
|||||||
writeListFormat(writer, textFormat.toListFormat(), formatIndex);
|
writeListFormat(writer, textFormat.toListFormat(), formatIndex);
|
||||||
break;
|
break;
|
||||||
case QTextFormat::FrameFormat:
|
case QTextFormat::FrameFormat:
|
||||||
writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
|
if (textFormat.isTableFormat())
|
||||||
|
writeTableFormat(writer, textFormat.toTableFormat(), formatIndex);
|
||||||
|
else
|
||||||
|
writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
|
||||||
break;
|
break;
|
||||||
case QTextFormat::TableFormat:
|
case QTextFormat::TableFormat:
|
||||||
;break;
|
// this case never happens, because TableFormat is a FrameFormat
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -449,6 +506,36 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
|
|||||||
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph"));
|
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph"));
|
||||||
writer.writeStartElement(styleNS, QString::fromLatin1("paragraph-properties"));
|
writer.writeStartElement(styleNS, QString::fromLatin1("paragraph-properties"));
|
||||||
|
|
||||||
|
if (format.hasProperty(QTextBlockFormat::LineHeightType)) {
|
||||||
|
const int blockLineHeightType = format.lineHeightType();
|
||||||
|
const qreal blockLineHeight = format.lineHeight();
|
||||||
|
QString type, value;
|
||||||
|
switch (blockLineHeightType) {
|
||||||
|
case QTextBlockFormat::SingleHeight:
|
||||||
|
type = QString::fromLatin1("line-height");
|
||||||
|
value = QString::fromLatin1("100%");
|
||||||
|
break;
|
||||||
|
case QTextBlockFormat::ProportionalHeight:
|
||||||
|
type = QString::fromLatin1("line-height");
|
||||||
|
value = QString::number(blockLineHeight) + QString::fromLatin1("%");
|
||||||
|
break;
|
||||||
|
case QTextBlockFormat::FixedHeight:
|
||||||
|
type = QString::fromLatin1("line-height");
|
||||||
|
value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
|
||||||
|
break;
|
||||||
|
case QTextBlockFormat::MinimumHeight:
|
||||||
|
type = QString::fromLatin1("line-height-at-least");
|
||||||
|
value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
|
||||||
|
break;
|
||||||
|
case QTextBlockFormat::LineDistanceHeight:
|
||||||
|
type = QString::fromLatin1("line-spacing");
|
||||||
|
value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!type.isNull())
|
||||||
|
writer.writeAttribute(styleNS, type, value);
|
||||||
|
}
|
||||||
|
|
||||||
if (format.hasProperty(QTextFormat::BlockAlignment)) {
|
if (format.hasProperty(QTextFormat::BlockAlignment)) {
|
||||||
const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
|
const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
|
||||||
QString value;
|
QString value;
|
||||||
@ -693,14 +780,108 @@ void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat
|
|||||||
// PageBreakFlags pageBreakPolicy () const
|
// PageBreakFlags pageBreakPolicy () const
|
||||||
}
|
}
|
||||||
|
|
||||||
void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex) const
|
void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const
|
||||||
{
|
{
|
||||||
|
// start writing table style element
|
||||||
writer.writeStartElement(styleNS, QString::fromLatin1("style"));
|
writer.writeStartElement(styleNS, QString::fromLatin1("style"));
|
||||||
writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
|
writer.writeAttribute(styleNS, QString::fromLatin1("name"),
|
||||||
|
QString::fromLatin1("Table%1").arg(formatIndex));
|
||||||
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table"));
|
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table"));
|
||||||
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-properties"));
|
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-properties"));
|
||||||
|
|
||||||
|
if (m_tableFormatsWithBorders.contains(formatIndex)) {
|
||||||
|
// write border format collapsing to table style
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("border-model"),
|
||||||
|
QString::fromLatin1("collapsing"));
|
||||||
|
}
|
||||||
|
const char* align = nullptr;
|
||||||
|
switch (format.alignment()) {
|
||||||
|
case Qt::AlignLeft:
|
||||||
|
align = "left";
|
||||||
|
break;
|
||||||
|
case Qt::AlignRight:
|
||||||
|
align = "right";
|
||||||
|
break;
|
||||||
|
case Qt::AlignHCenter:
|
||||||
|
align = "center";
|
||||||
|
break;
|
||||||
|
case Qt::AlignJustify:
|
||||||
|
align = "margins";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (align)
|
||||||
|
writer.writeAttribute(tableNS, QString::fromLatin1("align"), QString::fromLatin1(align));
|
||||||
|
if (format.width().rawValue()) {
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("width"),
|
||||||
|
QString::number(format.width().rawValue()) + QLatin1String("pt"));
|
||||||
|
}
|
||||||
|
writer.writeEndElement();
|
||||||
|
// start writing table-column style element
|
||||||
|
if (format.columnWidthConstraints().size()) {
|
||||||
|
// write table-column-properties for columns with constraints
|
||||||
|
m_tableFormatsWithColWidthConstraints.insert(formatIndex); // needed for linking of columns to styles
|
||||||
|
for (int colit = 0; colit < format.columnWidthConstraints().size(); ++colit) {
|
||||||
|
writer.writeStartElement(styleNS, QString::fromLatin1("style"));
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("name"),
|
||||||
|
QString::fromLatin1("Table%1.%2").arg(formatIndex).arg(colit));
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-column"));
|
||||||
|
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-column-properties"));
|
||||||
|
QString columnWidth;
|
||||||
|
if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
|
||||||
|
columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
|
||||||
|
+ QLatin1String("%");
|
||||||
|
} else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
|
||||||
|
columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
|
||||||
|
+ QLatin1String("pt");
|
||||||
|
} else {
|
||||||
|
//!! HARD-CODING variableWidth Constraints to 100% / nr constraints
|
||||||
|
columnWidth = QString::number(100 / format.columnWidthConstraints().size())
|
||||||
|
+ QLatin1String("%");
|
||||||
|
}
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("column-width"), columnWidth);
|
||||||
|
writer.writeEndElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format,
|
||||||
|
int formatIndex, QVector<QTextFormat> &styles) const
|
||||||
|
{
|
||||||
|
// check for all table cells here if they are in a table with border
|
||||||
|
if (m_cellFormatsInTablesWithBorders.contains(formatIndex)) {
|
||||||
|
const QVector<int> tableIdVector = m_cellFormatsInTablesWithBorders.value(formatIndex);
|
||||||
|
for (const auto &tableId : tableIdVector) {
|
||||||
|
const auto &tmpStyle = styles.at(tableId);
|
||||||
|
if (tmpStyle.isTableFormat()) {
|
||||||
|
QTextTableFormat tableFormatTmp = tmpStyle.toTableFormat();
|
||||||
|
tableCellStyleElement(writer, formatIndex, format, true, tableId, tableFormatTmp);
|
||||||
|
} else {
|
||||||
|
qDebug("QTextOdfWriter::writeTableCellFormat: ERROR writing table border format");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tableCellStyleElement(writer, formatIndex, format, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex,
|
||||||
|
const QTextTableCellFormat &format,
|
||||||
|
bool hasBorder, int tableId,
|
||||||
|
const QTextTableFormat tableFormatTmp) const {
|
||||||
|
writer.writeStartElement(styleNS, QString::fromLatin1("style"));
|
||||||
|
if (hasBorder) {
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("name"),
|
||||||
|
QString::fromLatin1("TB%1.%2").arg(tableId).arg(formatIndex));
|
||||||
|
} else {
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
|
||||||
|
}
|
||||||
|
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-cell"));
|
||||||
|
writer.writeEmptyElement(styleNS, QString::fromLatin1("table-cell-properties"));
|
||||||
|
if (hasBorder) {
|
||||||
|
writer.writeAttribute(foNS, QString::fromLatin1("border"),
|
||||||
|
pixelToPoint(tableFormatTmp.border()) + QLatin1String(" ")
|
||||||
|
+ borderStyleName(tableFormatTmp.borderStyle())
|
||||||
|
+ QLatin1String(" #000000")); //!! HARD-CODING color black
|
||||||
|
}
|
||||||
qreal padding = format.topPadding();
|
qreal padding = format.topPadding();
|
||||||
if (padding > 0 && padding == format.bottomPadding()
|
if (padding > 0 && padding == format.bottomPadding()
|
||||||
&& padding == format.leftPadding() && padding == format.rightPadding()) {
|
&& padding == format.leftPadding() && padding == format.rightPadding()) {
|
||||||
@ -710,16 +891,19 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
|
|||||||
if (padding > 0)
|
if (padding > 0)
|
||||||
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
|
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
|
||||||
if (format.bottomPadding() > 0)
|
if (format.bottomPadding() > 0)
|
||||||
writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"), pixelToPoint(format.bottomPadding()));
|
writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"),
|
||||||
|
pixelToPoint(format.bottomPadding()));
|
||||||
if (format.leftPadding() > 0)
|
if (format.leftPadding() > 0)
|
||||||
writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding()));
|
writer.writeAttribute(foNS, QString::fromLatin1("padding-left"),
|
||||||
|
pixelToPoint(format.leftPadding()));
|
||||||
if (format.rightPadding() > 0)
|
if (format.rightPadding() > 0)
|
||||||
writer.writeAttribute(foNS, QString::fromLatin1("padding-right"), pixelToPoint(format.rightPadding()));
|
writer.writeAttribute(foNS, QString::fromLatin1("padding-right"),
|
||||||
|
pixelToPoint(format.rightPadding()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
|
if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
|
||||||
QString pos;
|
QString pos;
|
||||||
switch (format.verticalAlignment()) {
|
switch (format.verticalAlignment()) { // TODO - review: doesn't handle all cases
|
||||||
case QTextCharFormat::AlignMiddle:
|
case QTextCharFormat::AlignMiddle:
|
||||||
pos = QString::fromLatin1("middle"); break;
|
pos = QString::fromLatin1("middle"); break;
|
||||||
case QTextCharFormat::AlignTop:
|
case QTextCharFormat::AlignTop:
|
||||||
@ -736,8 +920,6 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
|
|||||||
// ODF just search for style-table-cell-properties-attlist)
|
// ODF just search for style-table-cell-properties-attlist)
|
||||||
// QTextFormat::BackgroundImageUrl
|
// QTextFormat::BackgroundImageUrl
|
||||||
// format.background
|
// format.background
|
||||||
// QTextFormat::FrameBorder
|
|
||||||
|
|
||||||
writer.writeEndElement(); // style
|
writer.writeEndElement(); // style
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,8 +997,28 @@ bool QTextOdfWriter::writeAll()
|
|||||||
const QList<int> copy = formats.toList();
|
const QList<int> copy = formats.toList();
|
||||||
for (auto index : copy) {
|
for (auto index : copy) {
|
||||||
QTextObject *object = m_document->objectForFormat(allFormats[index]);
|
QTextObject *object = m_document->objectForFormat(allFormats[index]);
|
||||||
if (object)
|
if (object) {
|
||||||
formats << object->formatIndex();
|
formats << object->formatIndex();
|
||||||
|
if (auto *tableobject = qobject_cast<QTextTable *>(object)) {
|
||||||
|
if (tableobject->format().borderStyle()) {
|
||||||
|
int tableID = tableobject->formatIndex();
|
||||||
|
m_tableFormatsWithBorders.insert(tableID);
|
||||||
|
// loop through all rows and cols of table and store cell IDs,
|
||||||
|
// create Hash with cell ID as Key and table IDs as Vector
|
||||||
|
for (int rowindex = 0; rowindex < tableobject->rows(); ++rowindex) {
|
||||||
|
for (int colindex = 0; colindex < tableobject->columns(); ++colindex) {
|
||||||
|
const int cellFormatID = tableobject->cellAt(rowindex, colindex).tableCellFormatIndex();
|
||||||
|
QVector<int> tableIdsTmp;
|
||||||
|
if (m_cellFormatsInTablesWithBorders.contains(cellFormatID))
|
||||||
|
tableIdsTmp = m_cellFormatsInTablesWithBorders.value(cellFormatID);
|
||||||
|
if (!tableIdsTmp.contains(tableID))
|
||||||
|
tableIdsTmp.append(tableID);
|
||||||
|
m_cellFormatsInTablesWithBorders.insert(cellFormatID, tableIdsTmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFormats(writer, formats);
|
writeFormats(writer, formats);
|
||||||
|
@ -56,8 +56,10 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/QXmlStreamWriter>
|
#include <QtCore/QXmlStreamWriter>
|
||||||
|
#include <QtCore/qhash.h>
|
||||||
#include <QtCore/qset.h>
|
#include <QtCore/qset.h>
|
||||||
#include <QtCore/qstack.h>
|
#include <QtCore/qstack.h>
|
||||||
|
#include <QtCore/qvector.h>
|
||||||
|
|
||||||
#include "qtextdocument_p.h"
|
#include "qtextdocument_p.h"
|
||||||
#include "qtextdocumentwriter.h"
|
#include "qtextdocumentwriter.h"
|
||||||
@ -94,11 +96,21 @@ public:
|
|||||||
void writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const;
|
void writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const;
|
||||||
void writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const;
|
void writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const;
|
||||||
void writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const;
|
void writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const;
|
||||||
void writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex) const;
|
void writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const;
|
||||||
|
void writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex,
|
||||||
|
QVector<QTextFormat> &styles) const;
|
||||||
void writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame);
|
void writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame);
|
||||||
void writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const;
|
void writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const;
|
||||||
|
|
||||||
const QString officeNS, textNS, styleNS, foNS, tableNS, drawNS, xlinkNS, svgNS;
|
const QString officeNS, textNS, styleNS, foNS, tableNS, drawNS, xlinkNS, svgNS;
|
||||||
|
const int defaultImageResolution = 11811; // 11811 dots per meter = (about) 300 dpi
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex,
|
||||||
|
const QTextTableCellFormat &format,
|
||||||
|
bool hasBorder, int tableId = 0,
|
||||||
|
const QTextTableFormat tableFormatTmp = QTextTableFormat()) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QTextDocument *m_document;
|
const QTextDocument *m_document;
|
||||||
QIODevice *m_device;
|
QIODevice *m_device;
|
||||||
@ -108,6 +120,10 @@ private:
|
|||||||
bool m_createArchive;
|
bool m_createArchive;
|
||||||
|
|
||||||
QStack<QTextList *> m_listStack;
|
QStack<QTextList *> m_listStack;
|
||||||
|
|
||||||
|
QHash<int, QVector<int>> m_cellFormatsInTablesWithBorders;
|
||||||
|
QSet<int> m_tableFormatsWithBorders;
|
||||||
|
mutable QSet<int> m_tableFormatsWithColWidthConstraints;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -131,7 +131,7 @@ void tst_QTextOdfWriter::testWriteParagraph_data()
|
|||||||
QTest::newRow("misc2") << "\t \tFoo" <<
|
QTest::newRow("misc2") << "\t \tFoo" <<
|
||||||
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\"><text:tab/> <text:s text:c=\"4\"/><text:tab/>Foo</text:span></text:p>";
|
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\"><text:tab/> <text:s text:c=\"4\"/><text:tab/>Foo</text:span></text:p>";
|
||||||
QTest::newRow("linefeed") << (QStringLiteral("line1") + QChar(0x2028) + QStringLiteral("line2")) <<
|
QTest::newRow("linefeed") << (QStringLiteral("line1") + QChar(0x2028) + QStringLiteral("line2")) <<
|
||||||
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">line1<text:line-break/>line2</text:span></text:p>";
|
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">line1<text:tab/><text:line-break/>line2</text:span></text:p>";
|
||||||
QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" <<
|
QTest::newRow("spaces") << "The quick brown fox jumped over the lazy dog" <<
|
||||||
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">The quick brown fox jumped over the lazy dog</text:span></text:p>";
|
"<text:p text:style-name=\"p1\"><text:span text:style-name=\"c0\">The quick brown fox jumped over the lazy dog</text:span></text:p>";
|
||||||
}
|
}
|
||||||
@ -378,7 +378,7 @@ void tst_QTextOdfWriter::testWriteTable()
|
|||||||
odfWriter->writeFrame(*xmlWriter, document->rootFrame());
|
odfWriter->writeFrame(*xmlWriter, document->rootFrame());
|
||||||
QString xml = QString::fromLatin1(
|
QString xml = QString::fromLatin1(
|
||||||
"<text:p text:style-name=\"p1\"/>"
|
"<text:p text:style-name=\"p1\"/>"
|
||||||
"<table:table>"
|
"<table:table table:style-name=\"Table2\">"
|
||||||
"<table:table-column table:number-columns-repeated=\"3\"/>"
|
"<table:table-column table:number-columns-repeated=\"3\"/>"
|
||||||
"<table:table-row>"
|
"<table:table-row>"
|
||||||
"<table:table-cell table:style-name=\"T3\">"
|
"<table:table-cell table:style-name=\"T3\">"
|
||||||
|
Loading…
Reference in New Issue
Block a user