185void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer,
const QTextFrame *frame)
188 const QTextTable *table = qobject_cast<
const QTextTable*> (frame);
191 writer.writeStartElement(tableNS, QString::fromLatin1(
"table"));
192 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
193 QString::fromLatin1(
"Table%1").arg(table->formatIndex()));
195 if (m_tableFormatsWithColWidthConstraints.contains(table->formatIndex())) {
196 for (
int colit = 0; colit < table->columns(); ++colit) {
197 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-column"));
198 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
199 QString::fromLatin1(
"Table%1.%2").arg(table->formatIndex()).arg(colit));
200 writer.writeEndElement();
203 writer.writeEmptyElement(tableNS, QString::fromLatin1(
"table-column"));
204 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-columns-repeated"),
205 QString::number(table->columns()));
207 }
else if (frame->document() && frame->document()->rootFrame() != frame) {
208 writer.writeStartElement(textNS, QString::fromLatin1(
"section"));
211 QTextFrame::iterator iterator = frame->begin();
212 QTextFrame *child =
nullptr;
215 while (! iterator.atEnd()) {
216 if (iterator.currentFrame() && child != iterator.currentFrame())
217 writeFrame(writer, iterator.currentFrame());
219 QTextBlock block = iterator.currentBlock();
221 QTextTableCell cell = table->cellAt(block.position());
222 if (tableRow < cell.row()) {
224 writer.writeEndElement();
225 tableRow = cell.row();
226 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-row"));
228 writer.writeStartElement(tableNS, QString::fromLatin1(
"table-cell"));
229 if (cell.columnSpan() > 1)
230 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-columns-spanned"), QString::number(cell.columnSpan()));
231 if (cell.rowSpan() > 1)
232 writer.writeAttribute(tableNS, QString::fromLatin1(
"number-rows-spanned"), QString::number(cell.rowSpan()));
233 if (cell.format().isTableCellFormat()) {
234 if (m_cellFormatsInTablesWithBorders.contains(cell.tableCellFormatIndex()) ) {
236 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
237 QString::fromLatin1(
"TB%1.%2").arg(table->formatIndex())
238 .arg(cell.tableCellFormatIndex()));
240 writer.writeAttribute(tableNS, QString::fromLatin1(
"style-name"),
241 QString::fromLatin1(
"T%1").arg(cell.tableCellFormatIndex()));
245 writeBlock(writer, block);
247 writer.writeEndElement();
249 child = iterator.currentFrame();
253 writer.writeEndElement();
255 if (table || (frame->document() && frame->document()->rootFrame() != frame))
256 writer.writeEndElement();
259void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer,
const QTextBlock &block)
261 if (block.textList()) {
262 const int listLevel = block.textList()->format().indent();
263 if (m_listStack.isEmpty() || m_listStack.top() != block.textList()) {
265 while (m_listStack.size() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) {
267 writer.writeEndElement();
268 if (m_listStack.size())
269 writer.writeEndElement();
271 while (m_listStack.size() < listLevel) {
272 if (m_listStack.size())
273 writer.writeStartElement(textNS, QString::fromLatin1(
"list-item"));
274 writer.writeStartElement(textNS, QString::fromLatin1(
"list"));
275 if (m_listStack.size() == listLevel - 1) {
276 m_listStack.push(block.textList());
277 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"L%1")
278 .arg(block.textList()->formatIndex()));
281 m_listStack.push(
nullptr);
285 writer.writeStartElement(textNS, QString::fromLatin1(
"list-item"));
288 while (! m_listStack.isEmpty()) {
290 writer.writeEndElement();
291 if (m_listStack.size())
292 writer.writeEndElement();
296 if (block.length() == 1) {
297 writer.writeEmptyElement(textNS, QString::fromLatin1(
"p"));
298 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"p%1")
299 .arg(block.blockFormatIndex()));
300 if (block.textList())
301 writer.writeEndElement();
304 writer.writeStartElement(textNS, QString::fromLatin1(
"p"));
305 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"p%1")
306 .arg(block.blockFormatIndex()));
307 for (QTextBlock::Iterator frag = block.begin(); !frag.atEnd(); ++frag) {
308 bool isHyperlink = frag.fragment().charFormat().hasProperty(QTextFormat::AnchorHref);
310 QString value = frag.fragment().charFormat().property(QTextFormat::AnchorHref).toString();
311 writer.writeStartElement(textNS, QString::fromLatin1(
"a"));
312 writer.writeAttribute(xlinkNS, QString::fromLatin1(
"href"), value);
314 writer.writeCharacters(QString());
315 writer.writeStartElement(textNS, QString::fromLatin1(
"span"));
317 QString fragmentText = frag.fragment().text();
318 if (fragmentText.size() == 1 && fragmentText[0] == u'\xFFFC') {
319 writeInlineCharacter(writer, frag.fragment());
320 writer.writeEndElement();
324 writer.writeAttribute(textNS, QString::fromLatin1(
"style-name"), QString::fromLatin1(
"c%1")
325 .arg(frag.fragment().charFormatIndex()));
326 bool escapeNextSpace =
true;
327 int precedingSpaces = 0;
328 int exportedIndex = 0;
329 for (
int i=0; i <= fragmentText.size(); ++i) {
330 QChar character = (i == fragmentText.size() ? QChar() : fragmentText.at(i));
331 bool isSpace = character.unicode() ==
' ';
334 if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
335 const bool startParag = exportedIndex == 0 && i == precedingSpaces;
337 writer.writeCharacters(fragmentText.mid(exportedIndex, i - precedingSpaces + 1 - exportedIndex));
338 writer.writeEmptyElement(textNS, QString::fromLatin1(
"s"));
339 const int count = precedingSpaces - (startParag?0:1);
341 writer.writeAttribute(textNS, QString::fromLatin1(
"c"), QString::number(count));
346 if (i < fragmentText.size()) {
347 if (character.unicode() == 0x2028) {
349 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
352 writer.writeEmptyElement(textNS, QString::fromLatin1(
"tab"));
353 writer.writeEmptyElement(textNS, QString::fromLatin1(
"line-break"));
356 }
else if (character.unicode() ==
'\t') {
358 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
359 writer.writeEmptyElement(textNS, QString::fromLatin1(
"tab"));
362 }
else if (isSpace) {
364 escapeNextSpace =
true;
365 }
else if (!isSpace) {
371 writer.writeCharacters(fragmentText.mid(exportedIndex));
372 writer.writeEndElement();
373 writer.writeCharacters(QString());
375 writer.writeEndElement();
377 writer.writeCharacters(QString());
378 writer.writeEndElement();
379 if (block.textList())
380 writer.writeEndElement();
406void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer,
const QTextFragment &fragment)
const
408 writer.writeStartElement(drawNS, QString::fromLatin1(
"frame"));
409 if (m_strategy ==
nullptr) {
412 else if (fragment.charFormat().isImageFormat()) {
413 QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
414 writer.writeAttribute(drawNS, QString::fromLatin1(
"name"), imageFormat.name());
422 QString name = imageFormat.name();
423 if (name.startsWith(
":/"_L1))
424 name.prepend(
"qrc"_L1);
425 QUrl url = QUrl(name);
426 const QVariant variant = m_document->resource(QTextDocument::ImageResource, url);
427 if (variant.userType() == QMetaType::QPixmap || variant.userType() == QMetaType::QImage) {
428 image = qvariant_cast<QImage>(variant);
429 }
else if (variant.userType() == QMetaType::QByteArray) {
430 data = variant.toByteArray();
432 QBuffer buffer(&data);
433 buffer.open(QIODevice::ReadOnly);
434 probeImageData(&buffer, &image, &mimeType, &width, &height);
437 QFile file(imageFormat.name());
438 if (file.open(QIODevice::ReadOnly) && !probeImageData(&file, &image, &mimeType, &width, &height)) {
440 data = file.readAll();
444 if (! image.isNull()) {
447 int imgQuality = imageFormat.quality();
448 if (imgQuality >= 100 || imgQuality <= 0 || image.hasAlphaChannel()) {
449 QImageWriter imageWriter(&imageBytes,
"png");
450 imageWriter.write(image);
452 data = imageBytes.data();
453 mimeType = QStringLiteral(
"image/png");
456 QImageWriter imageWriter(&imageBytes,
"jpg");
457 imageWriter.setQuality(imgQuality);
458 imageWriter.write(image);
460 data = imageBytes.data();
461 mimeType = QStringLiteral(
"image/jpg");
464 width = image.width();
465 height = image.height();
468 if (!data.isEmpty()) {
469 if (imageFormat.hasProperty(QTextFormat::ImageWidth)) {
470 width = imageFormat.width();
472 if (imageFormat.hasProperty(QTextFormat::ImageHeight)) {
473 height = imageFormat.height();
476 QString filename = m_strategy->createUniqueImageName();
478 m_strategy->addFile(filename, mimeType, data);
480 writer.writeAttribute(svgNS, QString::fromLatin1(
"width"), pixelToPoint(width));
481 writer.writeAttribute(svgNS, QString::fromLatin1(
"height"), pixelToPoint(height));
482 writer.writeAttribute(textNS, QStringLiteral(
"anchor-type"), QStringLiteral(
"as-char"));
483 writer.writeStartElement(drawNS, QString::fromLatin1(
"image"));
484 writer.writeAttribute(xlinkNS, QString::fromLatin1(
"href"), filename);
485 writer.writeEndElement();
488 writer.writeEndElement();
522void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format,
int formatIndex)
const
524 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
525 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"p%1").arg(formatIndex));
526 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"paragraph"));
527 writer.writeStartElement(styleNS, QString::fromLatin1(
"paragraph-properties"));
529 if (format.hasProperty(QTextBlockFormat::LineHeightType)) {
530 const int blockLineHeightType = format.lineHeightType();
531 const qreal blockLineHeight = format.lineHeight();
533 switch (blockLineHeightType) {
534 case QTextBlockFormat::SingleHeight:
535 type = QString::fromLatin1(
"line-height");
536 value = QString::fromLatin1(
"100%");
538 case QTextBlockFormat::ProportionalHeight:
539 type = QString::fromLatin1(
"line-height");
540 value = QString::number(blockLineHeight) + QString::fromLatin1(
"%");
542 case QTextBlockFormat::FixedHeight:
543 type = QString::fromLatin1(
"line-height");
544 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
546 case QTextBlockFormat::MinimumHeight:
547 type = QString::fromLatin1(
"line-height-at-least");
548 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
550 case QTextBlockFormat::LineDistanceHeight:
551 type = QString::fromLatin1(
"line-spacing");
552 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
556 writer.writeAttribute(styleNS, type, value);
559 if (format.hasProperty(QTextFormat::BlockAlignment)) {
560 const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
562 if (alignment == Qt::AlignLeading)
563 value = QString::fromLatin1(
"start");
564 else if (alignment == Qt::AlignTrailing)
565 value = QString::fromLatin1(
"end");
566 else if (alignment == (Qt::AlignLeft | Qt::AlignAbsolute))
567 value = QString::fromLatin1(
"left");
568 else if (alignment == (Qt::AlignRight | Qt::AlignAbsolute))
569 value = QString::fromLatin1(
"right");
570 else if (alignment == Qt::AlignHCenter)
571 value = QString::fromLatin1(
"center");
572 else if (alignment == Qt::AlignJustify)
573 value = QString::fromLatin1(
"justify");
575 qWarning() <<
"QTextOdfWriter: unsupported paragraph alignment; " << format.alignment();
576 if (! value.isNull())
577 writer.writeAttribute(foNS, QString::fromLatin1(
"text-align"), value);
580 if (format.hasProperty(QTextFormat::BlockTopMargin))
581 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
582 if (format.hasProperty(QTextFormat::BlockBottomMargin))
583 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
584 if (format.hasProperty(QTextFormat::BlockLeftMargin) || format.hasProperty(QTextFormat::BlockIndent))
585 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-left"), pixelToPoint(qMax(qreal(0.),
586 format.leftMargin() + format.indent())));
587 if (format.hasProperty(QTextFormat::BlockRightMargin))
588 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
589 if (format.hasProperty(QTextFormat::TextIndent))
590 writer.writeAttribute(foNS, QString::fromLatin1(
"text-indent"), pixelToPoint(format.textIndent()));
591 if (format.hasProperty(QTextFormat::PageBreakPolicy)) {
592 if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore)
593 writer.writeAttribute(foNS, QString::fromLatin1(
"break-before"), QString::fromLatin1(
"page"));
594 if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysAfter)
595 writer.writeAttribute(foNS, QString::fromLatin1(
"break-after"), QString::fromLatin1(
"page"));
597 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
598 QBrush brush = format.background();
599 writer.writeAttribute(foNS, QString::fromLatin1(
"background-color"), brush.color().name());
601 if (format.hasProperty(QTextFormat::BlockNonBreakableLines))
602 writer.writeAttribute(foNS, QString::fromLatin1(
"keep-together"),
603 format.nonBreakableLines() ? QString::fromLatin1(
"true") : QString::fromLatin1(
"false"));
604 if (format.hasProperty(QTextFormat::TabPositions)) {
605 QList<QTextOption::Tab> tabs = format.tabPositions();
606 writer.writeStartElement(styleNS, QString::fromLatin1(
"tab-stops"));
607 QList<QTextOption::Tab>::Iterator iterator = tabs.begin();
608 while(iterator != tabs.end()) {
609 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"tab-stop"));
610 writer.writeAttribute(styleNS, QString::fromLatin1(
"position"), pixelToPoint(iterator->position) );
612 switch(iterator->type) {
613 case QTextOption::DelimiterTab: type = QString::fromLatin1(
"char");
break;
614 case QTextOption::LeftTab: type = QString::fromLatin1(
"left");
break;
615 case QTextOption::RightTab: type = QString::fromLatin1(
"right");
break;
616 case QTextOption::CenterTab: type = QString::fromLatin1(
"center");
break;
618 writer.writeAttribute(styleNS, QString::fromLatin1(
"type"), type);
619 if (!iterator->delimiter.isNull())
620 writer.writeAttribute(styleNS, QString::fromLatin1(
"char"), iterator->delimiter);
624 writer.writeEndElement();
627 writer.writeEndElement();
628 writer.writeEndElement();
631void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format,
int formatIndex)
const
633 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
634 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"c%1").arg(formatIndex));
635 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"text"));
636 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"text-properties"));
638 const QFont defaultFont = m_document->defaultFont();
639 const uint defaultFontResolveMask = defaultFont.resolveMask();
641 if (format.hasProperty(QTextFormat::FontItalic)
642 || (defaultFontResolveMask & QFont::StyleResolved)) {
643 const bool italic = format.hasProperty(QTextFormat::FontItalic) ? format.fontItalic() : defaultFont.italic();
645 writer.writeAttribute(foNS, QString::fromLatin1(
"font-style"), QString::fromLatin1(
"italic"));
648 if (format.hasProperty(QTextFormat::FontWeight)
649 || (defaultFontResolveMask & QFont::WeightResolved)) {
650 int weight = format.hasProperty(QTextFormat::FontWeight)
651 ? format.fontWeight()
652 : defaultFont.weight();
654 if (weight != QFont::Normal) {
656 if (weight == QFont::Bold)
657 value = QString::fromLatin1(
"bold");
659 value = QString::number(weight);
660 writer.writeAttribute(foNS, QString::fromLatin1(
"font-weight"), value);
664 if (format.hasProperty(QTextFormat::OldFontFamily)
665 || format.hasProperty(QTextFormat::FontFamilies)
666 || (defaultFontResolveMask & QFont::FamiliesResolved)) {
667 const QString fontFamily = (format.hasProperty(QTextFormat::OldFontFamily)
668 || format.hasProperty(QTextFormat::FontFamilies))
669 ? format.fontFamilies().toStringList().value(0, QString())
670 : defaultFont.family();
671 writer.writeAttribute(foNS, QString::fromLatin1(
"font-family"), fontFamily);
673 writer.writeAttribute(foNS, QString::fromLatin1(
"font-family"), QString::fromLatin1(
"Sans"));
676 if (format.hasProperty(QTextFormat::FontPointSize)
677 || (defaultFontResolveMask & QFont::SizeResolved)) {
678 const qreal pointSize = format.hasProperty(QTextFormat::FontPointSize)
679 ? format.fontPointSize()
680 : defaultFont.pointSizeF();
681 writer.writeAttribute(foNS, QString::fromLatin1(
"font-size"), QString::fromLatin1(
"%1pt").arg(pointSize));
684 if (format.hasProperty(QTextFormat::FontCapitalization)
685 || (defaultFontResolveMask & QFont::CapitalizationResolved)) {
686 QFont::Capitalization capitalization = format.hasProperty(QTextFormat::FontCapitalization)
687 ? format.fontCapitalization()
688 : defaultFont.capitalization();
689 switch(capitalization) {
690 case QFont::MixedCase:
691 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"none"));
break;
692 case QFont::AllUppercase:
693 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"uppercase"));
break;
694 case QFont::AllLowercase:
695 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"lowercase"));
break;
696 case QFont::Capitalize:
697 writer.writeAttribute(foNS, QString::fromLatin1(
"text-transform"), QString::fromLatin1(
"capitalize"));
break;
698 case QFont::SmallCaps:
699 writer.writeAttribute(foNS, QString::fromLatin1(
"font-variant"), QString::fromLatin1(
"small-caps"));
break;
703 if (format.hasProperty(QTextFormat::FontLetterSpacing) ||
704 (defaultFontResolveMask & QFont::LetterSpacingResolved)) {
705 const qreal letterSpacing = format.hasProperty(QTextFormat::FontLetterSpacing)
706 ? format.fontLetterSpacing()
707 : defaultFont.letterSpacing();
708 writer.writeAttribute(foNS, QString::fromLatin1(
"letter-spacing"), pixelToPoint(letterSpacing));
711 if (format.hasProperty(QTextFormat::FontWordSpacing)
712 || (defaultFontResolveMask & QFont::WordSpacingResolved)) {
713 const qreal wordSpacing = format.hasProperty(QTextFormat::FontWordSpacing)
714 ? format.fontWordSpacing()
715 : defaultFont.wordSpacing();
716 if (wordSpacing != 0)
717 writer.writeAttribute(foNS, QString::fromLatin1(
"word-spacing"), pixelToPoint(wordSpacing));
720 if (format.hasProperty(QTextFormat::FontUnderline)
721 || ((defaultFontResolveMask & QFont::UnderlineResolved)
722 && !format.hasProperty(QTextFormat::TextUnderlineStyle))) {
723 const bool underline = format.hasProperty(QTextFormat::FontUnderline)
724 ? format.fontUnderline()
725 : defaultFont.underline();
726 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-type"),
727 underline ? QString::fromLatin1(
"single") : QString::fromLatin1(
"none"));
730 if (format.hasProperty(QTextFormat::FontOverline)) {
734 if (format.hasProperty(QTextFormat::FontStrikeOut)
735 || (defaultFontResolveMask & QFont::StrikeOutResolved)) {
736 const bool strikeOut = format.hasProperty(QTextFormat::FontStrikeOut)
737 ? format.fontStrikeOut()
738 : defaultFont.strikeOut();
739 writer.writeAttribute(styleNS,QString::fromLatin1(
"text-line-through-type"),
740 strikeOut ? QString::fromLatin1(
"single") : QString::fromLatin1(
"none"));
743 if (format.hasProperty(QTextFormat::TextUnderlineColor))
744 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-color"), format.underlineColor().name());
745 if (format.hasProperty(QTextFormat::FontFixedPitch)) {
748 if (format.hasProperty(QTextFormat::TextUnderlineStyle)) {
750 switch (format.underlineStyle()) {
751 case QTextCharFormat::NoUnderline: value = QString::fromLatin1(
"none");
break;
752 case QTextCharFormat::SingleUnderline: value = QString::fromLatin1(
"solid");
break;
753 case QTextCharFormat::DashUnderline: value = QString::fromLatin1(
"dash");
break;
754 case QTextCharFormat::DotLine: value = QString::fromLatin1(
"dotted");
break;
755 case QTextCharFormat::DashDotLine: value = QString::fromLatin1(
"dash-dot");
break;
756 case QTextCharFormat::DashDotDotLine: value = QString::fromLatin1(
"dot-dot-dash");
break;
757 case QTextCharFormat::WaveUnderline: value = QString::fromLatin1(
"wave");
break;
758 case QTextCharFormat::SpellCheckUnderline: value = QString::fromLatin1(
"none");
break;
760 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-underline-style"), value);
762 if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
764 switch (format.verticalAlignment()) {
765 case QTextCharFormat::AlignMiddle:
766 case QTextCharFormat::AlignNormal: value = QString::fromLatin1(
"0%");
break;
767 case QTextCharFormat::AlignSuperScript: value = QString::fromLatin1(
"super");
break;
768 case QTextCharFormat::AlignSubScript: value = QString::fromLatin1(
"sub");
break;
769 case QTextCharFormat::AlignTop: value = QString::fromLatin1(
"100%");
break;
770 case QTextCharFormat::AlignBottom : value = QString::fromLatin1(
"-100%");
break;
771 case QTextCharFormat::AlignBaseline:
break;
773 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-position"), value);
775 if (format.hasProperty(QTextFormat::TextOutline))
776 writer.writeAttribute(styleNS, QString::fromLatin1(
"text-outline"), QString::fromLatin1(
"true"));
777 if (format.hasProperty(QTextFormat::TextToolTip)) {
780 if (format.hasProperty(QTextFormat::IsAnchor)) {
783 if (format.hasProperty(QTextFormat::AnchorHref)) {
786 if (format.hasProperty(QTextFormat::AnchorName)) {
789 if (format.hasProperty(QTextFormat::ForegroundBrush)) {
790 QBrush brush = format.foreground();
791 writer.writeAttribute(foNS, QString::fromLatin1(
"color"), brush.color().name());
793 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
794 QBrush brush = format.background();
795 writer.writeAttribute(foNS, QString::fromLatin1(
"background-color"), brush.color().name());
798 writer.writeEndElement();
801void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat format,
int formatIndex)
const
803 writer.writeStartElement(textNS, QString::fromLatin1(
"list-style"));
804 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"L%1").arg(formatIndex));
806 QTextListFormat::Style style = format.style();
807 if (style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha
808 || style == QTextListFormat::ListUpperAlpha
809 || style == QTextListFormat::ListLowerRoman
810 || style == QTextListFormat::ListUpperRoman) {
811 writer.writeStartElement(textNS, QString::fromLatin1(
"list-level-style-number"));
812 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-format"), bulletChar(style));
814 if (format.hasProperty(QTextFormat::ListNumberSuffix))
815 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-suffix"), format.numberSuffix());
817 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-suffix"), QString::fromLatin1(
"."));
819 if (format.hasProperty(QTextFormat::ListNumberPrefix))
820 writer.writeAttribute(styleNS, QString::fromLatin1(
"num-prefix"), format.numberPrefix());
823 writer.writeStartElement(textNS, QString::fromLatin1(
"list-level-style-bullet"));
824 writer.writeAttribute(textNS, QString::fromLatin1(
"bullet-char"), bulletChar(style));
827 writer.writeAttribute(textNS, QString::fromLatin1(
"level"), QString::number(format.indent()));
828 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"list-level-properties"));
829 writer.writeAttribute(foNS, QString::fromLatin1(
"text-align"), QString::fromLatin1(
"start"));
830 QString spacing = QString::fromLatin1(
"%1mm").arg(format.indent() * 8);
831 writer.writeAttribute(textNS, QString::fromLatin1(
"space-before"), spacing);
834 writer.writeEndElement();
835 writer.writeEndElement();
838void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format,
int formatIndex)
const
840 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
841 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"s%1").arg(formatIndex));
842 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"section"));
843 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"section-properties"));
844 if (format.hasProperty(QTextFormat::FrameTopMargin))
845 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
846 if (format.hasProperty(QTextFormat::FrameBottomMargin))
847 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
848 if (format.hasProperty(QTextFormat::FrameLeftMargin))
849 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin())) );
850 if (format.hasProperty(QTextFormat::FrameRightMargin))
851 writer.writeAttribute(foNS, QString::fromLatin1(
"margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
853 writer.writeEndElement();
866void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format,
int formatIndex)
const
869 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
870 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
871 QString::fromLatin1(
"Table%1").arg(formatIndex));
872 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table"));
873 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-properties"));
875 if (m_tableFormatsWithBorders.contains(formatIndex)) {
877 writer.writeAttribute(tableNS, QString::fromLatin1(
"border-model"),
878 QString::fromLatin1(
"collapsing"));
880 const char* align =
nullptr;
881 switch (format.alignment()) {
888 case Qt::AlignHCenter:
891 case Qt::AlignJustify:
896 writer.writeAttribute(tableNS, QString::fromLatin1(
"align"), QString::fromLatin1(align));
897 if (format.width().rawValue()) {
898 writer.writeAttribute(styleNS, QString::fromLatin1(
"width"),
899 QString::number(format.width().rawValue()) +
"pt"_L1);
901 writer.writeEndElement();
903 if (format.columnWidthConstraints().size()) {
905 m_tableFormatsWithColWidthConstraints.insert(formatIndex);
906 for (
int colit = 0; colit < format.columnWidthConstraints().size(); ++colit) {
907 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
908 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
909 QString::fromLatin1(
"Table%1.%2").arg(formatIndex).arg(colit));
910 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table-column"));
911 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-column-properties"));
913 if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
914 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
916 }
else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
917 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
921 columnWidth = QString::number(100 / format.columnWidthConstraints().size())
924 writer.writeAttribute(styleNS, QString::fromLatin1(
"column-width"), columnWidth);
925 writer.writeEndElement();
949void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer,
const int &formatIndex,
950 const QTextTableCellFormat &format,
951 bool hasBorder,
int tableId,
952 const QTextTableFormat tableFormatTmp)
const {
953 writer.writeStartElement(styleNS, QString::fromLatin1(
"style"));
955 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"),
956 QString::fromLatin1(
"TB%1.%2").arg(tableId).arg(formatIndex));
958 writer.writeAttribute(styleNS, QString::fromLatin1(
"name"), QString::fromLatin1(
"T%1").arg(formatIndex));
960 writer.writeAttribute(styleNS, QString::fromLatin1(
"family"), QString::fromLatin1(
"table-cell"));
961 writer.writeEmptyElement(styleNS, QString::fromLatin1(
"table-cell-properties"));
963 writer.writeAttribute(foNS, QString::fromLatin1(
"border"),
964 pixelToPoint(tableFormatTmp.border()) +
" "_L1
965 + borderStyleName(tableFormatTmp.borderStyle()) +
" "_L1
966 + tableFormatTmp.borderBrush().color().name(QColor::HexRgb));
968 qreal topPadding = format.topPadding();
969 qreal padding = topPadding + tableFormatTmp.cellPadding();
970 if (padding > 0 && topPadding == format.bottomPadding()
971 && topPadding == format.leftPadding() && topPadding == format.rightPadding()) {
972 writer.writeAttribute(foNS, QString::fromLatin1(
"padding"), pixelToPoint(padding));
976 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-top"), pixelToPoint(padding));
977 padding = format.bottomPadding() + tableFormatTmp.cellPadding();
979 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-bottom"),
980 pixelToPoint(padding));
981 padding = format.leftPadding() + tableFormatTmp.cellPadding();
983 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-left"),
984 pixelToPoint(padding));
985 padding = format.rightPadding() + tableFormatTmp.cellPadding();
987 writer.writeAttribute(foNS, QString::fromLatin1(
"padding-right"),
988 pixelToPoint(padding));
991 if (format.hasProperty(QTextFormat::TextVerticalAlignment)) {
993 switch (format.verticalAlignment()) {
994 case QTextCharFormat::AlignMiddle:
995 pos = QString::fromLatin1(
"middle");
break;
996 case QTextCharFormat::AlignTop:
997 pos = QString::fromLatin1(
"top");
break;
998 case QTextCharFormat::AlignBottom:
999 pos = QString::fromLatin1(
"bottom");
break;
1001 pos = QString::fromLatin1(
"automatic");
break;
1003 writer.writeAttribute(styleNS, QString::fromLatin1(
"vertical-align"), pos);
1010 writer.writeEndElement();
1031bool QTextOdfWriter::writeAll()
1033 if (m_createArchive)
1034 m_strategy =
new QZipStreamStrategy(m_device);
1036 m_strategy =
new QXmlStreamStrategy(m_device);
1038 if (!m_device->isWritable() && ! m_device->open(QIODevice::WriteOnly)) {
1039 qWarning(
"QTextOdfWriter::writeAll: the device cannot be opened for writing");
1042 QXmlStreamWriter writer(m_strategy->contentStream);
1044 writer.setAutoFormatting(
true);
1045 writer.setAutoFormattingIndent(2);
1047 writer.writeNamespace(officeNS, QString::fromLatin1(
"office"));
1048 writer.writeNamespace(textNS, QString::fromLatin1(
"text"));
1049 writer.writeNamespace(styleNS, QString::fromLatin1(
"style"));
1050 writer.writeNamespace(foNS, QString::fromLatin1(
"fo"));
1051 writer.writeNamespace(tableNS, QString::fromLatin1(
"table"));
1052 writer.writeNamespace(drawNS, QString::fromLatin1(
"draw"));
1053 writer.writeNamespace(xlinkNS, QString::fromLatin1(
"xlink"));
1054 writer.writeNamespace(svgNS, QString::fromLatin1(
"svg"));
1055 writer.writeStartDocument();
1056 writer.writeStartElement(officeNS, QString::fromLatin1(
"document-content"));
1057 writer.writeAttribute(officeNS, QString::fromLatin1(
"version"), QString::fromLatin1(
"1.2"));
1060 QTextDocumentPrivate::FragmentIterator fragIt = QTextDocumentPrivate::get(m_document)->begin();
1062 while (fragIt != QTextDocumentPrivate::get(m_document)->end()) {
1063 const QTextFragmentData *
const frag = fragIt.value();
1064 formats << frag->format;
1069 QTextDocumentPrivate::BlockMap &blocks =
const_cast<QTextDocumentPrivate *>(QTextDocumentPrivate::get(m_document))->blockMap();
1070 QTextDocumentPrivate::BlockMap::Iterator blockIt = blocks.begin();
1071 while (blockIt != blocks.end()) {
1072 const QTextBlockData *
const block = blockIt.value();
1073 formats << block->format;
1078 const QList<QTextFormat> allFormats = m_document->allFormats();
1079 const QList<
int> copy = formats.values();
1080 for (
auto index : copy) {
1081 QTextObject *object = m_document->objectForFormat(allFormats[index]);
1083 formats << object->formatIndex();
1084 if (
auto *tableobject = qobject_cast<QTextTable *>(object)) {
1085 if (tableobject->format().borderStyle()) {
1086 int tableID = tableobject->formatIndex();
1087 m_tableFormatsWithBorders.insert(tableID);
1090 for (
int rowindex = 0; rowindex < tableobject->rows(); ++rowindex) {
1091 for (
int colindex = 0; colindex < tableobject->columns(); ++colindex) {
1092 const int cellFormatID = tableobject->cellAt(rowindex, colindex).tableCellFormatIndex();
1093 QList<
int> tableIdsTmp;
1094 if (m_cellFormatsInTablesWithBorders.contains(cellFormatID))
1095 tableIdsTmp = m_cellFormatsInTablesWithBorders.value(cellFormatID);
1096 if (!tableIdsTmp.contains(tableID))
1097 tableIdsTmp.append(tableID);
1098 m_cellFormatsInTablesWithBorders.insert(cellFormatID, tableIdsTmp);
1106 writeFormats(writer, formats);
1108 writer.writeStartElement(officeNS, QString::fromLatin1(
"body"));
1109 writer.writeStartElement(officeNS, QString::fromLatin1(
"text"));
1110 QTextFrame *rootFrame = m_document->rootFrame();
1111 writeFrame(writer, rootFrame);
1112 writer.writeEndElement();
1113 writer.writeEndElement();
1114 writer.writeEndElement();
1115 writer.writeEndDocument();
1117 m_strategy =
nullptr;