summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextodfwriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qtextodfwriter.cpp')
-rw-r--r--src/gui/text/qtextodfwriter.cpp261
1 files changed, 235 insertions, 26 deletions
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 30f5bc1051..d8218ab613 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -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)
{
Q_ASSERT(frame);
@@ -190,8 +219,21 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
if (table) { // Start a table.
writer.writeStartElement(tableNS, QString::fromLatin1("table"));
- writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
- writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"), QString::number(table->columns()));
+ writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
+ 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
writer.writeStartElement(textNS, QString::fromLatin1("section"));
}
@@ -219,7 +261,15 @@ void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *fram
if (cell.rowSpan() > 1)
writer.writeAttribute(tableNS, QString::fromLatin1("number-rows-spanned"), QString::number(cell.rowSpan()));
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);
@@ -326,7 +376,10 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
if (i < fragmentText.count()) {
if (character.unicode() == 0x2028) { // soft-return
//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"));
exportedIndex = i+1;
continue;
@@ -367,7 +420,6 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());
- // vvv Copy pasted mostly from Qt =================
QImage image;
QString name = imageFormat.name();
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
@@ -387,26 +439,33 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
}
}
- // ^^^ Copy pasted mostly from Qt =================
if (! image.isNull()) {
QBuffer imageBytes;
- QImageWriter imageWriter(&imageBytes, "png");
- imageWriter.write(image);
QString filename = m_strategy->createUniqueImageName();
- m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
-
+ int imgQuality = imageFormat.quality();
+ if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) {
+ QImageWriter imageWriter(&imageBytes, "png");
+ imageWriter.write(image);
+ m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
+ } else {
+ // Write images without alpha channel as jpg with quality set by QTextImageFormat
+ QImageWriter imageWriter(&imageBytes, "jpg");
+ imageWriter.setQuality(imgQuality);
+ imageWriter.write(image);
+ m_strategy->addFile(filename, QString::fromLatin1("image/jpg"), imageBytes.data());
+ }
// 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));
- 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.writeStartElement(drawNS, QString::fromLatin1("image"));
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
writer.writeEndElement(); // image
}
}
-
writer.writeEndElement(); // frame
}
@@ -421,7 +480,7 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
switch (textFormat.type()) {
case QTextFormat::CharFormat:
if (textFormat.isTableCellFormat())
- writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex);
+ writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex, allStyles);
else
writeCharacterFormat(writer, textFormat.toCharFormat(), formatIndex);
break;
@@ -432,10 +491,15 @@ void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &for
writeListFormat(writer, textFormat.toListFormat(), formatIndex);
break;
case QTextFormat::FrameFormat:
- writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
+ if (textFormat.isTableFormat())
+ writeTableFormat(writer, textFormat.toTableFormat(), formatIndex);
+ else
+ writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
break;
case QTextFormat::TableFormat:
- ;break;
+ // this case never happens, because TableFormat is a FrameFormat
+ Q_UNREACHABLE();
+ break;
}
}
@@ -449,6 +513,36 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph"));
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)) {
const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
QString value;
@@ -693,14 +787,108 @@ void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat
// 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.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.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();
if (padding > 0 && padding == format.bottomPadding()
&& padding == format.leftPadding() && padding == format.rightPadding()) {
@@ -710,16 +898,19 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
if (padding > 0)
writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
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)
- writer.writeAttribute(foNS, QString::fromLatin1("padding-left"), pixelToPoint(format.leftPadding()));
+ writer.writeAttribute(foNS, QString::fromLatin1("padding-left"),
+ pixelToPoint(format.leftPadding()));
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)) {
QString pos;
- switch (format.verticalAlignment()) {
+ switch (format.verticalAlignment()) { // TODO - review: doesn't handle all cases
case QTextCharFormat::AlignMiddle:
pos = QString::fromLatin1("middle"); break;
case QTextCharFormat::AlignTop:
@@ -736,8 +927,6 @@ void QTextOdfWriter::writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCe
// ODF just search for style-table-cell-properties-attlist)
// QTextFormat::BackgroundImageUrl
// format.background
- // QTextFormat::FrameBorder
-
writer.writeEndElement(); // style
}
@@ -815,8 +1004,28 @@ bool QTextOdfWriter::writeAll()
const QList<int> copy = formats.toList();
for (auto index : copy) {
QTextObject *object = m_document->objectForFormat(allFormats[index]);
- if (object)
+ if (object) {
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);