186void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer,
const QTextFrame *frame)
189 const QTextTable *table = qobject_cast<
const QTextTable*> (frame);
192 writer.writeStartElement(tableNS, QString::fromLatin1(
"table"));
193 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
194 QString::fromLatin1(
"Table%1").arg(table->formatIndex()));
196 if (m_tableFormatsWithColWidthConstraints.contains(table->formatIndex())) {
197 for (
int colit = 0; colit < table->columns(); ++colit) {
198 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-column"));
199 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
200 QString::fromLatin1(
"Table%1.%2").arg(table->formatIndex()).arg(colit));
201 writer.writeEndElement();
204 writer.writeEmptyElement(tableNS, QString::fromLatin1(
"table-column"));
205 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-columns-repeated"),
206 QString::number(table->columns()));
208 }
else if (frame->document() && frame->document()->rootFrame() != frame) {
209 writer.writeStartElement(textNS, QString::fromLatin1(
"section"));
212 QTextFrame::iterator iterator = frame->begin();
213 QTextFrame *child =
nullptr;
216 while (! iterator.atEnd()) {
217 if (iterator.currentFrame() && child != iterator.currentFrame())
218 writeFrame(writer, iterator.currentFrame());
220 QTextBlock block = iterator.currentBlock();
222 QTextTableCell cell = table->cellAt(block.position());
223 if (tableRow < cell.row()) {
225 writer.writeEndElement();
226 tableRow = cell.row();
227 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-row"));
229 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-cell"));
230 if (cell.columnSpan() > 1)
231 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-columns-spanned"), QString::number(cell.columnSpan()));
232 if (cell.rowSpan() > 1)
233 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-rows-spanned"), QString::number(cell.rowSpan()));
234 if (cell.format().isTableCellFormat()) {
235 if (m_cellFormatsInTablesWithBorders.contains(cell.tableCellFormatIndex()) ) {
237 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
238 QString::fromLatin1(
"TB%1.%2").arg(table->formatIndex())
239 .arg(cell.tableCellFormatIndex()));
241 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
242 QString::fromLatin1(
"T%1").arg(cell.tableCellFormatIndex()));
246 writeBlock(writer, block);
248 writer.writeEndElement();
250 child = iterator.currentFrame();
254 writer.writeEndElement();
256 if (table || (frame->document() && frame->document()->rootFrame() != frame))
257 writer.writeEndElement();
260void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer,
const QTextBlock &block)
262 if (block.textList()) {
263 const int listLevel = block.textList()->format().indent();
264 if (m_listStack.isEmpty() || m_listStack.top() != block.textList()) {
266 while (m_listStack.size() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) {
268 writer.writeEndElement();
269 if (m_listStack.size())
270 writer.writeEndElement();
272 while (m_listStack.size() < listLevel) {
273 if (m_listStack.size())
274 writer.writeStartElement(textNS, QString::fromLatin1(
"list-item"));
275 writer.writeStartElement(textNS, QString::fromLatin1(
"list"));
276 if (m_listStack.size() == listLevel - 1) {
277 m_listStack.push(block.textList());
278 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"L%1")
279 .arg(block.textList()->formatIndex()));
282 m_listStack.push(
nullptr);
286 writer.writeStartElement(textNS, QString::fromLatin1(
"list-item"));
289 while (! m_listStack.isEmpty()) {
291 writer.writeEndElement();
292 if (m_listStack.size())
293 writer.writeEndElement();
297 if (block.length() == 1) {
298 writer.writeEmptyElement(textNS, QString::fromLatin1(
"p"));
299 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"p%1")
300 .arg(block.blockFormatIndex()));
301 if (block.textList())
302 writer.writeEndElement();
305 writer.writeStartElement(textNS, QString::fromLatin1(
"p"));
306 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"p%1")
307 .arg(block.blockFormatIndex()));
308 for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
309 bool isHyperlink = frag.fragment().charFormat().hasProperty(QTextFormat::AnchorHref);
311 QString value = frag.fragment().charFormat().property(QTextFormat::AnchorHref).toString();
312 writer.writeStartElement(textNS, QString::fromLatin1(
"a"));
313 writer.writeAttribute(xlinkNS, QString::fromLatin1(
"href"), value);
315 writer.writeCharacters(QString());
316 writer.writeStartElement(textNS, QString::fromLatin1(
"span"));
318 QString fragmentText = frag.fragment().text();
319 if (fragmentText.size() == 1 && fragmentText[0] == u'\xFFFC') {
320 writeInlineCharacter(writer, frag.fragment());
321 writer.writeEndElement();
325 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"c%1")
326 .arg(frag.fragment().charFormatIndex()));
327 bool escapeNextSpace =
true;
328 int precedingSpaces = 0;
329 int exportedIndex = 0;
330 for (
int i=0; i <= fragmentText.size(); ++i) {
331 QChar character = (i == fragmentText.size() ? QChar() : fragmentText.at(i));
332 bool isSpace = character.unicode() ==
' ';
335 if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
336 const bool startParag = exportedIndex == 0 && i == precedingSpaces;
338 writer.writeCharacters(fragmentText.mid(exportedIndex, i - precedingSpaces + 1 - exportedIndex));
339 writer.writeEmptyElement(textNS, QString::fromLatin1(
"s"));
340 const int count = precedingSpaces - (startParag?0:1);
342 writer.writeAttribute(textNS, QString::fromLatin1(
"c"), QString::number(count));
347 if (i < fragmentText.size()) {
348 if (character.unicode() == 0x2028) {
350 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
353 writer.writeEmptyElement(textNS, QString::fromLatin1(
"tab"));
354 writer.writeEmptyElement(textNS, QString::fromLatin1(
"line-break"));
357 }
else if (character.unicode() ==
'\t') {
359 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
360 writer.writeEmptyElement(textNS, QString::fromLatin1(
"tab"));
363 }
else if (isSpace) {
365 escapeNextSpace =
true;
366 }
else if (!isSpace) {
372 writer.writeCharacters(fragmentText.mid(exportedIndex));
373 writer.writeEndElement();
374 writer.writeCharacters(QString());
376 writer.writeEndElement();
378 writer.writeCharacters(QString());
379 writer.writeEndElement();
380 if (block.textList())
381 writer.writeEndElement();
407void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer,
const QTextFragment &fragment)
const
409 writer.writeStartElement(drawNS, QString::fromLatin1(
"frame"));
410 if (m_strategy ==
nullptr) {
413 else if (fragment.charFormat().isImageFormat()) {
414 QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
415 writer.writeAttribute(drawNS, QString::fromLatin1(
"name"), imageFormat.name());
423 QString name = imageFormat.name();
424 if (name.startsWith(
":/"_L1))
425 name.prepend(
"qrc"_L1);
426 QUrl url = QUrl(name);
427 const QVariant variant = m_document->resource(QTextDocument::ImageResource, url);
428 if (variant.userType() == QMetaType::QPixmap || variant.userType() == QMetaType::QImage) {
429 image = qvariant_cast<QImage>(variant);
430 }
else if (variant.userType() == QMetaType::QByteArray) {
431 data = variant.toByteArray();
433 QBuffer buffer(&data);
434 buffer.open(QIODevice::ReadOnly);
435 probeImageData(&buffer, &image, &mimeType, &width, &height);
438 QFile file(imageFormat.name());
439 if (file.open(QIODevice::ReadOnly) && !probeImageData(&file, &image, &mimeType, &width, &height)) {
441 data = file.readAll();
445 if (! image.isNull()) {
448 int imgQuality = imageFormat.quality();
449 if (imgQuality >= 100 || imgQuality <= 0 || image.hasAlphaChannel()) {
450 QImageWriter imageWriter(&imageBytes,
"png");
451 imageWriter.write(image);
453 data = imageBytes.data();
454 mimeType = QStringLiteral(
"image/png");
457 QImageWriter imageWriter(&imageBytes,
"jpg");
458 imageWriter.setQuality(imgQuality);
459 imageWriter.write(image);
461 data = imageBytes.data();
462 mimeType = QStringLiteral(
"image/jpg");
465 width = image.width();
466 height = image.height();
469 if (!data.isEmpty()) {
470 if (imageFormat.hasProperty(QTextFormat::ImageWidth)) {
471 width = imageFormat.width();
473 if (imageFormat.hasProperty(QTextFormat::ImageHeight)) {
474 height = imageFormat.height();
477 QString filename = m_strategy->createUniqueImageName();
479 m_strategy->addFile(filename, mimeType, data);
481 writer.writeAttribute(svgNS, QString::fromLatin1(
"width"), pixelToPoint(width));
482 writer.writeAttribute(svgNS, QString::fromLatin1(
"height"), pixelToPoint(height));
483 writer.writeAttribute(textNS, QStringLiteral(
"anchor-type"), QStringLiteral(
"as-char"));
484 writer.writeStartElement(drawNS, QString::fromLatin1(
"image"));
485 writer.writeAttribute(xlinkNS, QString::fromLatin1(
"href"), filename);
486 writer.writeEndElement();
489 writer.writeEndElement();
523void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format,
int formatIndex)
const
525 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
526 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"p%1").arg(formatIndex));
527 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"paragraph"));
528 writer.writeStartElement(styleNS, QString::fromLatin1(
"paragraph-properties"));
530 if (format.hasProperty(QTextBlockFormat::LineHeightType)) {
531 const int blockLineHeightType = format.lineHeightType();
532 const qreal blockLineHeight = format.lineHeight();
534 switch (blockLineHeightType) {
535 case QTextBlockFormat::SingleHeight:
536 type = QString::fromLatin1(
"line-height");
537 value = QString::fromLatin1(
"100%");
539 case QTextBlockFormat::ProportionalHeight:
540 type = QString::fromLatin1(
"line-height");
541 value = QString::number(blockLineHeight) + QString::fromLatin1(
"%");
543 case QTextBlockFormat::FixedHeight:
544 type = QString::fromLatin1(
"line-height");
545 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
547 case QTextBlockFormat::MinimumHeight:
548 type = QString::fromLatin1(
"line-height-at-least");
549 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
551 case QTextBlockFormat::LineDistanceHeight:
552 type = QString::fromLatin1(
"line-spacing");
553 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
557 writer.writeAttribute(styleNS, type, value);
560 if (format.hasProperty(QTextFormat::BlockAlignment)) {
561 const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
563 if (alignment == Qt::AlignLeading)
564 value = QString::fromLatin1(
"start");
565 else if (alignment == Qt::AlignTrailing)
566 value = QString::fromLatin1(
"end");
567 else if (alignment == (Qt::AlignLeft | Qt::AlignAbsolute))
568 value = QString::fromLatin1(
"left");
569 else if (alignment == (Qt::AlignRight | Qt::AlignAbsolute))
570 value = QString::fromLatin1(
"right");
571 else if (alignment == Qt::AlignHCenter)
572 value = QString::fromLatin1(
"center");
573 else if (alignment == Qt::AlignJustify)
574 value = QString::fromLatin1(
"justify");
576 qWarning() <<
"QTextOdfWriter: unsupported paragraph alignment; " << format.alignment();
577 if (! value.isNull())
578 writer.writeAttribute(foNS, QString::fromLatin1(
"text-align"), value);
581 if (format.hasProperty(QTextFormat::BlockTopMargin))
582 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
583 if (format.hasProperty(QTextFormat::BlockBottomMargin))
584 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
585 if (format.hasProperty(QTextFormat::BlockLeftMargin) || format.hasProperty(QTextFormat::BlockIndent))
586 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-left"), pixelToPoint(qMax(qreal(0.),
587 format.leftMargin() + format.indent())));
588 if (format.hasProperty(QTextFormat::BlockRightMargin))
589 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
590 if (format.hasProperty(QTextFormat::TextIndent))
591 writer.writeAttribute(foNS, QString::fromLatin1(
"text-indent"), pixelToPoint(format.textIndent()));
592 if (format.hasProperty(QTextFormat::PageBreakPolicy)) {
593 if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore)
594 writer.writeAttribute(foNS, QString::fromLatin1(
"break-before"), QString::fromLatin1(
"page"));
595 if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysAfter)
596 writer.writeAttribute(foNS, QString::fromLatin1(
"break-after"), QString::fromLatin1(
"page"));
598 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
599 QBrush brush = format.background();
600 writer.writeAttribute(foNS, QString::fromLatin1(
"background-color"), brush.color().name());
602 if (format.hasProperty(QTextFormat::BlockNonBreakableLines))
603 writer.writeAttribute(foNS, QString::fromLatin1(
"keep-together"),
604 format.nonBreakableLines() ? QString::fromLatin1(
"true") : QString::fromLatin1(
"false"));
605 if (format.hasProperty(QTextFormat::TabPositions)) {
606 QList<QTextOption::Tab> tabs = format.tabPositions();
607 writer.writeStartElement(styleNS, QString::fromLatin1(
"tab-stops"));
608 QList<QTextOption::Tab>::Iterator iterator = tabs.begin();
609 while(iterator != tabs.end()) {
610 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"tab-stop"));
611 writer.writeAttribute(styleNS, QString::fromLatin1(
"position"), pixelToPoint(iterator->position) );
613 switch(iterator->type) {
614 case QTextOption::DelimiterTab: type = QString::fromLatin1(
"char");
break;
615 case QTextOption::LeftTab: type = QString::fromLatin1(
"left");
break;
616 case QTextOption::RightTab: type = QString::fromLatin1(
"right");
break;
617 case QTextOption::CenterTab: type = QString::fromLatin1(
"center");
break;
619 writer.writeAttribute(styleNS, QString::fromLatin1(
"type"), type);
620 if (!iterator->delimiter.isNull())
621 writer.writeAttribute(styleNS, QString::fromLatin1(
"char"), iterator->delimiter);
625 writer.writeEndElement();
628 writer.writeEndElement();
629 writer.writeEndElement();
632void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format,
int formatIndex)
const
634 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
635 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"c%1").arg(formatIndex));
636 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"text"));
637 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"text-properties"));
639 const QFont defaultFont = m_document->defaultFont();
640 const uint defaultFontResolveMask = defaultFont.resolveMask();
642 if (format.hasProperty(QTextFormat::FontItalic)
643 || (defaultFontResolveMask & QFont::StyleResolved)) {
644 const bool italic = format.hasProperty(QTextFormat::FontItalic) ? format.fontItalic() : defaultFont.italic();
646 writer.writeAttribute(foNS, QString::fromLatin1(
"font-style"), QString::fromLatin1(
"italic"));
649 if (format.hasProperty(QTextFormat::FontWeight)
650 || (defaultFontResolveMask & QFont::WeightResolved)) {
651 int weight = format.hasProperty(QTextFormat::FontWeight)
652 ? format.fontWeight()
653 : defaultFont.weight();
655 if (weight != QFont::Normal) {
657 if (weight == QFont::Bold)
658 value = QString::fromLatin1(
"bold");
660 value = QString::number(weight);
661 writer.writeAttribute(foNS, QString::fromLatin1(
"font-weight"), value);
665 if (format.hasProperty(QTextFormat::OldFontFamily)
666 || format.hasProperty(QTextFormat::FontFamilies)
667 || (defaultFontResolveMask & QFont::FamiliesResolved)) {
668 const QString fontFamily = (format.hasProperty(QTextFormat::OldFontFamily)
669 || format.hasProperty(QTextFormat::FontFamilies))
670 ? format.fontFamilies().toStringList().value(0, QString())
671 : defaultFont.family();
672 writer.writeAttribute(foNS, QString::fromLatin1(
"font-family"), fontFamily);
674 writer.writeAttribute(foNS, QString::fromLatin1(
"font-family"), QString::fromLatin1(
"Sans"));
677 if (format.hasProperty(QTextFormat::FontPointSize)
678 || (defaultFontResolveMask & QFont::SizeResolved)) {
679 const qreal pointSize = format.hasProperty(QTextFormat::FontPointSize)
680 ? format.fontPointSize()
681 : defaultFont.pointSizeF();
682 writer.writeAttribute(foNS, QString::fromLatin1(
"font-size"), QString::fromLatin1(
"%1pt").arg(pointSize));
685 if (format.hasProperty(QTextFormat::FontCapitalization)
686 || (defaultFontResolveMask & QFont::CapitalizationResolved)) {
687 QFont::Capitalization capitalization = format.hasProperty(QTextFormat::FontCapitalization)
688 ? format.fontCapitalization()
689 : defaultFont.capitalization();
690 switch(capitalization) {
691 case QFont::MixedCase:
692 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"none"));
break;
693 case QFont::AllUppercase:
694 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"uppercase"));
break;
695 case QFont::AllLowercase:
696 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"lowercase"));
break;
697 case QFont::Capitalize:
698 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"capitalize"));
break;
699 case QFont::SmallCaps:
700 writer.writeAttribute(foNS, QString::fromLatin1(
"font-variant"), QString::fromLatin1(
"small-caps"));
break;
704 if (format.hasProperty(QTextFormat::FontLetterSpacing) ||
705 (defaultFontResolveMask & QFont::LetterSpacingResolved)) {
706 const qreal letterSpacing = format.hasProperty(QTextFormat::FontLetterSpacing)
707 ? format.fontLetterSpacing()
708 : defaultFont.letterSpacing();
709 writer.writeAttribute(foNS, QString::fromLatin1(
"letter-spacing"), pixelToPoint(letterSpacing));
712 if (format.hasProperty(QTextFormat::FontWordSpacing)
713 || (defaultFontResolveMask & QFont::WordSpacingResolved)) {
714 const qreal wordSpacing = format.hasProperty(QTextFormat::FontWordSpacing)
715 ? format.fontWordSpacing()
716 : defaultFont.wordSpacing();
717 if (wordSpacing != 0)
718 writer.writeAttribute(foNS, QString::fromLatin1(
"word-spacing"), pixelToPoint(wordSpacing));
721 if (format.hasProperty(QTextFormat::FontUnderline)
722 || ((defaultFontResolveMask & QFont::UnderlineResolved)
723 && !format.hasProperty(QTextFormat::TextUnderlineStyle))) {
724 const bool underline = format.hasProperty(QTextFormat::FontUnderline)
725 ? format.fontUnderline()
726 : defaultFont.underline();
727 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-type"),
728 underline ? QString::fromLatin1(
"single") : QString::fromLatin1(
"none"));
731 if (format.hasProperty(QTextFormat::FontOverline)) {
735 if (format.hasProperty(QTextFormat::FontStrikeOut)
736 || (defaultFontResolveMask & QFont::StrikeOutResolved)) {
737 const bool strikeOut = format.hasProperty(QTextFormat::FontStrikeOut)
738 ? format.fontStrikeOut()
739 : defaultFont.strikeOut();
740 writer.writeAttribute(styleNS,QString::fromLatin1(
"text-line-through-type"),
741 strikeOut ? QString::fromLatin1(
"single") : QString::fromLatin1(
"none"));
744 if (format.hasProperty(QTextFormat::TextUnderlineColor))
745 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-color"), format.underlineColor().name());
746 if (format.hasProperty(QTextFormat::FontFixedPitch)) {
749 if (format.hasProperty(QTextFormat::TextUnderlineStyle)) {
751 switch (format.underlineStyle()) {
752 case QTextCharFormat::NoUnderline: value = QString::fromLatin1(
"none");
break;
753 case QTextCharFormat::SingleUnderline: value = QString::fromLatin1(
"solid");
break;
754 case QTextCharFormat::DashUnderline: value = QString::fromLatin1(
"dash");
break;
755 case QTextCharFormat::DotLine: value = QString::fromLatin1(
"dotted");
break;
756 case QTextCharFormat::DashDotLine: value = QString::fromLatin1(
"dash-dot");
break;
757 case QTextCharFormat::DashDotDotLine: value = QString::fromLatin1(
"dot-dot-dash");
break;
758 case QTextCharFormat::WaveUnderline: value = QString::fromLatin1(
"wave");
break;
759 case QTextCharFormat::SpellCheckUnderline: value = QString::fromLatin1(
"none");
break;
761 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-style"), value);
763 if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
765 switch (format.verticalAlignment()) {
766 case QTextCharFormat::AlignMiddle:
767 case QTextCharFormat::AlignNormal: value = QString::fromLatin1(
"0%");
break;
768 case QTextCharFormat::AlignSuperScript: value = QString::fromLatin1(
"super");
break;
769 case QTextCharFormat::AlignSubScript: value = QString::fromLatin1(
"sub");
break;
770 case QTextCharFormat::AlignTop: value = QString::fromLatin1(
"100%");
break;
771 case QTextCharFormat::AlignBottom : value = QString::fromLatin1(
"-100%");
break;
772 case QTextCharFormat::AlignBaseline:
break;
774 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-position"), value);
776 if (format.hasProperty(QTextFormat::TextOutline))
777 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-outline"), QString::fromLatin1(
"true"));
778 if (format.hasProperty(QTextFormat::TextToolTip)) {
781 if (format.hasProperty(QTextFormat::IsAnchor)) {
784 if (format.hasProperty(QTextFormat::AnchorHref)) {
787 if (format.hasProperty(QTextFormat::AnchorName)) {
790 if (format.hasProperty(QTextFormat::ForegroundBrush)) {
791 QBrush brush = format.foreground();
792 writer.writeAttribute(foNS, QString::fromLatin1(
"color"), brush.color().name());
794 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
795 QBrush brush = format.background();
796 writer.writeAttribute(foNS, QString::fromLatin1(
"background-color"), brush.color().name());
799 writer.writeEndElement();
802void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat format,
int formatIndex)
const
804 writer.writeStartElement(textNS, QString::fromLatin1(
"list-style"));
805 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"L%1").arg(formatIndex));
807 QTextListFormat::Style style = format.style();
808 if (style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha
809 || style == QTextListFormat::ListUpperAlpha
810 || style == QTextListFormat::ListLowerRoman
811 || style == QTextListFormat::ListUpperRoman) {
812 writer.writeStartElement(textNS, QString::fromLatin1(
"list-level-style-number"));
813 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-format"), bulletChar(style));
815 if (format.hasProperty(QTextFormat::ListNumberSuffix))
816 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-suffix"), format.numberSuffix());
818 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-suffix"), QString::fromLatin1(
"."));
820 if (format.hasProperty(QTextFormat::ListNumberPrefix))
821 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-prefix"), format.numberPrefix());
824 writer.writeStartElement(textNS, QString::fromLatin1(
"list-level-style-bullet"));
825 writer.writeAttribute(textNS, QString::fromLatin1(
"bullet-char"), bulletChar(style));
828 writer.writeAttribute(textNS, QString::fromLatin1(
"level"), QString::number(format.indent()));
829 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"list-level-properties"));
830 writer.writeAttribute(foNS, QString::fromLatin1(
"text-align"), QString::fromLatin1(
"start"));
831 QString spacing = QString::fromLatin1(
"%1mm").arg(format.indent() * 8);
832 writer.writeAttribute(textNS, QString::fromLatin1(
"space-before"), spacing);
835 writer.writeEndElement();
836 writer.writeEndElement();
839void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format,
int formatIndex)
const
841 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
842 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"s%1").arg(formatIndex));
843 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"section"));
844 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"section-properties"));
845 if (format.hasProperty(QTextFormat::FrameTopMargin))
846 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
847 if (format.hasProperty(QTextFormat::FrameBottomMargin))
848 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
849 if (format.hasProperty(QTextFormat::FrameLeftMargin))
850 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin())) );
851 if (format.hasProperty(QTextFormat::FrameRightMargin))
852 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
854 writer.writeEndElement();
867void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format,
int formatIndex)
const
870 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
871 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
872 QString::fromLatin1(
"Table%1").arg(formatIndex));
873 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table"));
874 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-properties"));
876 if (m_tableFormatsWithBorders.contains(formatIndex)) {
878 writer.writeAttribute(tableNS, QString::fromLatin1(
"border-model"),
879 QString::fromLatin1(
"collapsing"));
881 const char* align =
nullptr;
882 switch (format.alignment()) {
889 case Qt::AlignHCenter:
892 case Qt::AlignJustify:
897 writer.writeAttribute(tableNS, QString::fromLatin1(
"align"), QString::fromLatin1(align));
898 if (format.width().rawValue()) {
899 writer.writeAttribute(styleNS, QString::fromLatin1(
"width"),
900 QString::number(format.width().rawValue()) +
"pt"_L1);
902 writer.writeEndElement();
904 if (format.columnWidthConstraints().size()) {
906 m_tableFormatsWithColWidthConstraints.insert(formatIndex);
907 for (
int colit = 0; colit < format.columnWidthConstraints().size(); ++colit) {
908 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
909 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
910 QString::fromLatin1(
"Table%1.%2").arg(formatIndex).arg(colit));
911 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table-column"));
912 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-column-properties"));
914 if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
915 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
917 }
else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
918 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
922 columnWidth = QString::number(100 / format.columnWidthConstraints().size())
925 writer.writeAttribute(styleNS, QString::fromLatin1(
"column-width"), columnWidth);
926 writer.writeEndElement();
950void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer,
const int &formatIndex,
951 const QTextTableCellFormat &format,
952 bool hasBorder,
int tableId,
953 const QTextTableFormat tableFormatTmp)
const {
954 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
956 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
957 QString::fromLatin1(
"TB%1.%2").arg(tableId).arg(formatIndex));
959 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"T%1").arg(formatIndex));
961 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table-cell"));
962 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-cell-properties"));
964 writer.writeAttribute(foNS, QString::fromLatin1(
"border"),
965 pixelToPoint(tableFormatTmp.border()) +
" "_L1
966 + borderStyleName(tableFormatTmp.borderStyle()) +
" "_L1
967 + tableFormatTmp.borderBrush().color().name(QColor::HexRgb));
969 qreal topPadding = format.topPadding();
970 qreal padding = topPadding + tableFormatTmp.cellPadding();
971 if (padding > 0 && topPadding == format.bottomPadding()
972 && topPadding == format.leftPadding() && topPadding == format.rightPadding()) {
973 writer.writeAttribute(foNS, QString::fromLatin1(
"padding"), pixelToPoint(padding));
977 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-top"), pixelToPoint(padding));
978 padding = format.bottomPadding() + tableFormatTmp.cellPadding();
980 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-bottom"),
981 pixelToPoint(padding));
982 padding = format.leftPadding() + tableFormatTmp.cellPadding();
984 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-left"),
985 pixelToPoint(padding));
986 padding = format.rightPadding() + tableFormatTmp.cellPadding();
988 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-right"),
989 pixelToPoint(padding));
992 if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
994 switch (format.verticalAlignment()) {
995 case QTextCharFormat::AlignMiddle:
996 pos = QString::fromLatin1(
"middle");
break;
997 case QTextCharFormat::AlignTop:
998 pos = QString::fromLatin1(
"top");
break;
999 case QTextCharFormat::AlignBottom:
1000 pos = QString::fromLatin1(
"bottom");
break;
1002 pos = QString::fromLatin1(
"automatic");
break;
1004 writer.writeAttribute(styleNS, QString::fromLatin1(
"vertical-align"), pos);
1011 writer.writeEndElement();
1032bool QTextOdfWriter::writeAll()
1034 if (m_createArchive)
1035 m_strategy =
new QZipStreamStrategy(m_device);
1037 m_strategy =
new QXmlStreamStrategy(m_device);
1039 if (!m_device->isWritable() && ! m_device->open(QIODevice::WriteOnly)) {
1040 qWarning(
"QTextOdfWriter::writeAll: the device cannot be opened for writing");
1043 QXmlStreamWriter writer(m_strategy->contentStream);
1045 writer.setAutoFormatting(
true);
1046 writer.setAutoFormattingIndent(2);
1048 writer.writeNamespace(officeNS, QString::fromLatin1(
"office"));
1049 writer.writeNamespace(textNS, QString::fromLatin1(
"text"));
1050 writer.writeNamespace(styleNS, QString::fromLatin1(
"style"));
1051 writer.writeNamespace(foNS, QString::fromLatin1(
"fo"));
1052 writer.writeNamespace(tableNS, QString::fromLatin1(
"table"));
1053 writer.writeNamespace(drawNS, QString::fromLatin1(
"draw"));
1054 writer.writeNamespace(xlinkNS, QString::fromLatin1(
"xlink"));
1055 writer.writeNamespace(svgNS, QString::fromLatin1(
"svg"));
1056 writer.writeStartDocument();
1057 writer.writeStartElement(officeNS, QString::fromLatin1(
"document-content"));
1058 writer.writeAttribute(officeNS, QString::fromLatin1(
"version"), QString::fromLatin1(
"1.2"));
1061 QTextDocumentPrivate::FragmentIterator fragIt = QTextDocumentPrivate::get(m_document)->begin();
1063 while (fragIt != QTextDocumentPrivate::get(m_document)->end()) {
1064 const QTextFragmentData *
const frag = fragIt.value();
1065 formats << frag->format;
1070 QTextDocumentPrivate::BlockMap &blocks =
const_cast<QTextDocumentPrivate *>(QTextDocumentPrivate::get(m_document))->blockMap();
1071 QTextDocumentPrivate::BlockMap::Iterator blockIt = blocks.begin();
1072 while (blockIt != blocks.end()) {
1073 const QTextBlockData *
const block = blockIt.value();
1074 formats << block->format;
1079 const QList<QTextFormat> allFormats = m_document->allFormats();
1080 const QList<
int> copy = formats.values();
1081 for (
auto index : copy) {
1082 QTextObject *object = m_document->objectForFormat(allFormats[index]);
1084 formats << object->formatIndex();
1085 if (
auto *tableobject = qobject_cast<QTextTable *>(object)) {
1086 if (tableobject->format().borderStyle()) {
1087 int tableID = tableobject->formatIndex();
1088 m_tableFormatsWithBorders.insert(tableID);
1091 for (
int rowindex = 0; rowindex < tableobject->rows(); ++rowindex) {
1092 for (
int colindex = 0; colindex < tableobject->columns(); ++colindex) {
1093 const int cellFormatID = tableobject->cellAt(rowindex, colindex).tableCellFormatIndex();
1094 QList<
int> tableIdsTmp;
1095 if (m_cellFormatsInTablesWithBorders.contains(cellFormatID))
1096 tableIdsTmp = m_cellFormatsInTablesWithBorders.value(cellFormatID);
1097 if (!tableIdsTmp.contains(tableID))
1098 tableIdsTmp.append(tableID);
1099 m_cellFormatsInTablesWithBorders.insert(cellFormatID, tableIdsTmp);
1107 writeFormats(writer, formats);
1109 writer.writeStartElement(officeNS, QString::fromLatin1(
"body"));
1110 writer.writeStartElement(officeNS, QString::fromLatin1(
"text"));
1111 QTextFrame *rootFrame = m_document->rootFrame();
1112 writeFrame(writer, rootFrame);
1113 writer.writeEndElement();
1114 writer.writeEndElement();
1115 writer.writeEndElement();
1116 writer.writeEndDocument();
1118 m_strategy =
nullptr;