Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtextodfwriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <qglobal.h>
5
6#ifndef QT_NO_TEXTODFWRITER
7
8#include "qtextodfwriter_p.h"
9
10#include <QImageReader>
11#include <QImageWriter>
12#include <QTextListFormat>
13#include <QTextList>
14#include <QBuffer>
15#include <QUrl>
16
17#include "qtextdocument_p.h"
18#include "qtexttable.h"
19#include "qtextcursor.h"
20#include "qtextimagehandler_p.h"
21
22#include <QDebug>
23#include <QtCore/private/qzipwriter_p.h>
24
25
27
28using namespace Qt::StringLiterals;
29
32{
33 // we hardcode 96 DPI, we do the same in the ODF importer to have a perfect roundtrip.
34 return QString::number(pixels * 72 / 96) + "pt"_L1;
35}
36
37// strategies
39public:
41 virtual ~QOutputStrategy() {}
42 virtual void addFile(const QString &fileName, const QString &mimeType, const QByteArray &bytes) = 0;
43
45 {
46 return QString::fromLatin1("Pictures/Picture%1").arg(counter++);
47 }
48
51};
52
54public:
59
65 virtual void addFile(const QString &, const QString &, const QByteArray &) override
66 {
67 // we ignore this...
68 }
69};
70
72public:
74 : zip(device),
75 manifestWriter(&manifest)
76 {
77 QByteArray mime("application/vnd.oasis.opendocument.text");
79 zip.addFile(QString::fromLatin1("mimetype"), mime); // for mime-magick
81 contentStream = &content;
83 manifest.open(QIODevice::WriteOnly);
84
85 manifestNS = QString::fromLatin1("urn:oasis:names:tc:opendocument:xmlns:manifest:1.0");
86 // prettyfy
87 manifestWriter.setAutoFormatting(true);
88 manifestWriter.setAutoFormattingIndent(1);
89
90 manifestWriter.writeNamespace(manifestNS, QString::fromLatin1("manifest"));
91 manifestWriter.writeStartDocument();
92 manifestWriter.writeStartElement(manifestNS, QString::fromLatin1("manifest"));
93 manifestWriter.writeAttribute(manifestNS, QString::fromLatin1("version"), QString::fromLatin1("1.2"));
94 addFile(QString::fromLatin1("/"), QString::fromLatin1("application/vnd.oasis.opendocument.text"));
95 addFile(QString::fromLatin1("content.xml"), QString::fromLatin1("text/xml"));
96 }
97
99 {
100 manifestWriter.writeEndDocument();
101 manifest.close();
102 zip.addFile(QString::fromLatin1("META-INF/manifest.xml"), &manifest);
103 content.close();
104 zip.addFile(QString::fromLatin1("content.xml"), &content);
105 zip.close();
106 }
107
108 virtual void addFile(const QString &fileName, const QString &mimeType, const QByteArray &bytes) override
109 {
110 zip.addFile(fileName, bytes);
112 }
113
114private:
115 void addFile(const QString &fileName, const QString &mimeType)
116 {
117 manifestWriter.writeEmptyElement(manifestNS, QString::fromLatin1("file-entry"));
118 manifestWriter.writeAttribute(manifestNS, QString::fromLatin1("media-type"), mimeType);
119 manifestWriter.writeAttribute(manifestNS, QString::fromLatin1("full-path"), fileName);
120 }
121
122 QBuffer content;
123 QBuffer manifest;
124 QZipWriter zip;
125 QXmlStreamWriter manifestWriter;
126 QString manifestNS;
127};
128
130{
131 static_assert(int(QTextListFormat::ListDisc) == -1);
132 static_assert(int(QTextListFormat::ListUpperRoman) == -8);
133 static const char16_t chars[] = {
134 u'\x25cf', // bullet character
135 u'\x25cb', // white circle
136 u'\x25a1', // white square
137 u'1',
138 u'a',
139 u'A',
140 u'i',
141 u'I',
142 };
143 const auto map = [](QTextListFormat::Style s) { return -int(s) - 1; };
144 static_assert(uint(map(QTextListFormat::ListUpperRoman)) == std::size(chars) - 1);
145 const auto idx = map(style);
146 if (idx < 0)
147 return nullptr;
148 else
149 return {chars + idx, 1};
150}
151
153{
154 return bullet_char(style).toString();
155}
156
185
186void QTextOdfWriter::writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame)
187{
189 const QTextTable *table = qobject_cast<const QTextTable*> (frame);
190
191 if (table) { // Start a table.
192 writer.writeStartElement(tableNS, QString::fromLatin1("table"));
193 writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
194 QString::fromLatin1("Table%1").arg(table->formatIndex()));
195 // check if column widths are set, if so add TableNS line above for all columns and link to style
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();
202 }
203 } else {
204 writer.writeEmptyElement(tableNS, QString::fromLatin1("table-column"));
205 writer.writeAttribute(tableNS, QString::fromLatin1("number-columns-repeated"),
206 QString::number(table->columns()));
207 }
208 } else if (frame->document() && frame->document()->rootFrame() != frame) { // start a section
209 writer.writeStartElement(textNS, QString::fromLatin1("section"));
210 }
211
212 QTextFrame::iterator iterator = frame->begin();
213 QTextFrame *child = nullptr;
214
215 int tableRow = -1;
216 while (! iterator.atEnd()) {
217 if (iterator.currentFrame() && child != iterator.currentFrame())
218 writeFrame(writer, iterator.currentFrame());
219 else { // no frame, its a block
220 QTextBlock block = iterator.currentBlock();
221 if (table) {
222 QTextTableCell cell = table->cellAt(block.position());
223 if (tableRow < cell.row()) {
224 if (tableRow >= 0)
225 writer.writeEndElement(); // close table row
226 tableRow = cell.row();
227 writer.writeStartElement(tableNS, QString::fromLatin1("table-row"));
228 }
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()) ) {
236 // writing table:style-name tag in <table:table-cell> element
237 writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
238 QString::fromLatin1("TB%1.%2").arg(table->formatIndex())
239 .arg(cell.tableCellFormatIndex()));
240 } else {
241 writer.writeAttribute(tableNS, QString::fromLatin1("style-name"),
243 }
244 }
245 }
246 writeBlock(writer, block);
247 if (table)
248 writer.writeEndElement(); // table-cell
249 }
250 child = iterator.currentFrame();
251 ++iterator;
252 }
253 if (tableRow >= 0)
254 writer.writeEndElement(); // close table-row
255
256 if (table || (frame->document() && frame->document()->rootFrame() != frame))
257 writer.writeEndElement(); // close table or section element
258}
259
260void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &block)
261{
262 if (block.textList()) { // its a list-item
263 const int listLevel = block.textList()->format().indent();
264 if (m_listStack.isEmpty() || m_listStack.top() != block.textList()) {
265 // not the same list we were in.
266 while (m_listStack.size() >= listLevel && !m_listStack.isEmpty() && m_listStack.top() != block.textList() ) { // we need to close tags
267 m_listStack.pop();
268 writer.writeEndElement(); // list
269 if (m_listStack.size())
270 writer.writeEndElement(); // list-item
271 }
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()));
280 }
281 else {
282 m_listStack.push(nullptr);
283 }
284 }
285 }
286 writer.writeStartElement(textNS, QString::fromLatin1("list-item"));
287 }
288 else {
289 while (! m_listStack.isEmpty()) {
290 m_listStack.pop();
291 writer.writeEndElement(); // list
292 if (m_listStack.size())
293 writer.writeEndElement(); // list-item
294 }
295 }
296
297 if (block.length() == 1) { // only a linefeed
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(); // numbered-paragraph
303 return;
304 }
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);
310 if (isHyperlink) {
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);
314 }
315 writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed in front of it.
316 writer.writeStartElement(textNS, QString::fromLatin1("span"));
317
318 QString fragmentText = frag.fragment().text();
319 if (fragmentText.size() == 1 && fragmentText[0] == u'\xFFFC') { // its an inline character.
320 writeInlineCharacter(writer, frag.fragment());
321 writer.writeEndElement(); // span
322 continue;
323 }
324
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() == ' ';
333
334 // find more than one space. -> <text:s text:c="2" />
335 if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
336 const bool startParag = exportedIndex == 0 && i == precedingSpaces;
337 if (!startParag)
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);
341 if (count > 1)
342 writer.writeAttribute(textNS, QString::fromLatin1("c"), QString::number(count));
343 precedingSpaces = 0;
344 exportedIndex = i;
345 }
346
347 if (i < fragmentText.size()) {
348 if (character.unicode() == 0x2028) { // soft-return
349 //if (exportedIndex < i)
350 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
351 // adding tab before line-break, so last line in justified paragraph
352 // will not stretch to the end
353 writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
354 writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
355 exportedIndex = i+1;
356 continue;
357 } else if (character.unicode() == '\t') { // Tab
358 //if (exportedIndex < i)
359 writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
360 writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
361 exportedIndex = i+1;
362 precedingSpaces = 0;
363 } else if (isSpace) {
364 ++precedingSpaces;
365 escapeNextSpace = true;
366 } else if (!isSpace) {
367 precedingSpaces = 0;
368 }
369 }
370 }
371
372 writer.writeCharacters(fragmentText.mid(exportedIndex));
373 writer.writeEndElement(); // span
374 writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed behind it.
375 if (isHyperlink)
376 writer.writeEndElement(); // a
377 }
378 writer.writeCharacters(QString()); // Trick to make sure that the span gets no linefeed behind it.
379 writer.writeEndElement(); // p
380 if (block.textList())
381 writer.writeEndElement(); // list-item
382}
383
385{
386 QImageReader reader(device);
387 const QByteArray format = reader.format().toLower();
388 if (format == "png") {
389 *mimeType = QStringLiteral("image/png");
390 } else if (format == "jpg") {
391 *mimeType = QStringLiteral("image/jpg");
392 } else if (format == "svg") {
393 *mimeType = QStringLiteral("image/svg+xml");
394 } else {
395 *image = reader.read();
396 return false;
397 }
398
399 const QSize size = reader.size();
400
401 *width = size.width();
402 *height = size.height();
403
404 return true;
405}
406
407void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const
408{
409 writer.writeStartElement(drawNS, QString::fromLatin1("frame"));
410 if (m_strategy == nullptr) {
411 // don't do anything.
412 }
413 else if (fragment.charFormat().isImageFormat()) {
414 QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
415 writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());
416
419 qreal width = 0;
420 qreal height = 0;
421
423 QString name = imageFormat.name();
424 if (name.startsWith(":/"_L1)) // auto-detect resources
425 name.prepend("qrc"_L1);
426 QUrl url = QUrl(name);
428 if (variant.userType() == QMetaType::QPixmap || variant.userType() == QMetaType::QImage) {
429 image = qvariant_cast<QImage>(variant);
430 } else if (variant.userType() == QMetaType::QByteArray) {
432
436 } else {
437 // try direct loading
438 QFile file(imageFormat.name());
440 file.seek(0);
441 data = file.readAll();
442 }
443 }
444
445 if (! image.isNull()) {
446 QBuffer imageBytes;
447
448 int imgQuality = imageFormat.quality();
449 if (imgQuality >= 100 || imgQuality <= 0 || image.hasAlphaChannel()) {
450 QImageWriter imageWriter(&imageBytes, "png");
451 imageWriter.write(image);
452
453 data = imageBytes.data();
454 mimeType = QStringLiteral("image/png");
455 } else {
456 // Write images without alpha channel as jpg with quality set by QTextImageFormat
457 QImageWriter imageWriter(&imageBytes, "jpg");
458 imageWriter.setQuality(imgQuality);
459 imageWriter.write(image);
460
461 data = imageBytes.data();
462 mimeType = QStringLiteral("image/jpg");
463 }
464
465 width = image.width();
466 height = image.height();
467 }
468
469 if (!data.isEmpty()) {
470 if (imageFormat.hasProperty(QTextFormat::ImageWidth)) {
471 width = imageFormat.width();
472 }
473 if (imageFormat.hasProperty(QTextFormat::ImageHeight)) {
474 height = imageFormat.height();
475 }
476
477 QString filename = m_strategy->createUniqueImageName();
478
479 m_strategy->addFile(filename, mimeType, data);
480
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(); // image
487 }
488 }
489 writer.writeEndElement(); // frame
490}
491
492void QTextOdfWriter::writeFormats(QXmlStreamWriter &writer, const QSet<int> &formats) const
493{
494 writer.writeStartElement(officeNS, QString::fromLatin1("automatic-styles"));
495 QList<QTextFormat> allStyles = m_document->allFormats();
496 for (int formatIndex : formats) {
497 QTextFormat textFormat = allStyles.at(formatIndex);
498 switch (textFormat.type()) {
500 if (textFormat.isTableCellFormat())
501 writeTableCellFormat(writer, textFormat.toTableCellFormat(), formatIndex, allStyles);
502 else
503 writeCharacterFormat(writer, textFormat.toCharFormat(), formatIndex);
504 break;
506 writeBlockFormat(writer, textFormat.toBlockFormat(), formatIndex);
507 break;
509 writeListFormat(writer, textFormat.toListFormat(), formatIndex);
510 break;
512 if (textFormat.isTableFormat())
513 writeTableFormat(writer, textFormat.toTableFormat(), formatIndex);
514 else
515 writeFrameFormat(writer, textFormat.toFrameFormat(), formatIndex);
516 break;
517 }
518 }
519
520 writer.writeEndElement(); // automatic-styles
521}
522
523void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format, int formatIndex) const
524{
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"));
529
530 if (format.hasProperty(QTextBlockFormat::LineHeightType)) {
531 const int blockLineHeightType = format.lineHeightType();
532 const qreal blockLineHeight = format.lineHeight();
534 switch (blockLineHeightType) {
536 type = QString::fromLatin1("line-height");
537 value = QString::fromLatin1("100%");
538 break;
540 type = QString::fromLatin1("line-height");
541 value = QString::number(blockLineHeight) + QString::fromLatin1("%");
542 break;
544 type = QString::fromLatin1("line-height");
545 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
546 break;
548 type = QString::fromLatin1("line-height-at-least");
549 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
550 break;
552 type = QString::fromLatin1("line-spacing");
553 value = pixelToPoint(qMax(qreal(0.), blockLineHeight));
554 }
555
556 if (!type.isNull())
557 writer.writeAttribute(styleNS, type, value);
558 }
559
560 if (format.hasProperty(QTextFormat::BlockAlignment)) {
561 const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask;
564 value = QString::fromLatin1("start");
565 else if (alignment == Qt::AlignTrailing)
566 value = QString::fromLatin1("end");
568 value = QString::fromLatin1("left");
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");
575 else
576 qWarning() << "QTextOdfWriter: unsupported paragraph alignment; " << format.alignment();
577 if (! value.isNull())
578 writer.writeAttribute(foNS, QString::fromLatin1("text-align"), value);
579 }
580
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())) );
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"));
597 }
598 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
599 QBrush brush = format.background();
600 writer.writeAttribute(foNS, QString::fromLatin1("background-color"), brush.color().name());
601 }
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) {
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;
618 }
619 writer.writeAttribute(styleNS, QString::fromLatin1("type"), type);
620 if (!iterator->delimiter.isNull())
621 writer.writeAttribute(styleNS, QString::fromLatin1("char"), iterator->delimiter);
622 ++iterator;
623 }
624
625 writer.writeEndElement(); // tab-stops
626 }
627
628 writer.writeEndElement(); // paragraph-properties
629 writer.writeEndElement(); // style
630}
631
632void QTextOdfWriter::writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const
633{
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"));
638 if (format.fontItalic())
639 writer.writeAttribute(foNS, QString::fromLatin1("font-style"), QString::fromLatin1("italic"));
640 if (format.hasProperty(QTextFormat::FontWeight) && format.fontWeight() != QFont::Normal) {
642 if (format.fontWeight() == QFont::Bold)
643 value = QString::fromLatin1("bold");
644 else
645 value = QString::number(format.fontWeight());
646 writer.writeAttribute(foNS, QString::fromLatin1("font-weight"), value);
647 }
648 if (format.hasProperty(QTextFormat::OldFontFamily))
649 writer.writeAttribute(foNS, QString::fromLatin1("font-family"), format.fontFamilies().toStringList().value(0, QString()));
650 else
651 writer.writeAttribute(foNS, QString::fromLatin1("font-family"), QString::fromLatin1("Sans")); // Qt default
652 if (format.hasProperty(QTextFormat::FontPointSize))
653 writer.writeAttribute(foNS, QString::fromLatin1("font-size"), QString::fromLatin1("%1pt").arg(format.fontPointSize()));
654 if (format.hasProperty(QTextFormat::FontCapitalization)) {
655 switch(format.fontCapitalization()) {
656 case QFont::MixedCase:
657 writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("none")); break;
659 writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("uppercase")); break;
661 writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("lowercase")); break;
663 writer.writeAttribute(foNS, QString::fromLatin1("text-transform"), QString::fromLatin1("capitalize")); break;
664 case QFont::SmallCaps:
665 writer.writeAttribute(foNS, QString::fromLatin1("font-variant"), QString::fromLatin1("small-caps")); break;
666 }
667 }
668 if (format.hasProperty(QTextFormat::FontLetterSpacing))
669 writer.writeAttribute(foNS, QString::fromLatin1("letter-spacing"), pixelToPoint(format.fontLetterSpacing()));
670 if (format.hasProperty(QTextFormat::FontWordSpacing) && format.fontWordSpacing() != 0)
671 writer.writeAttribute(foNS, QString::fromLatin1("word-spacing"), pixelToPoint(format.fontWordSpacing()));
672 if (format.hasProperty(QTextFormat::FontUnderline))
673 writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-type"),
674 format.fontUnderline() ? QString::fromLatin1("single") : QString::fromLatin1("none"));
675 if (format.hasProperty(QTextFormat::FontOverline)) {
676 // bool fontOverline () const TODO
677 }
678 if (format.hasProperty(QTextFormat::FontStrikeOut))
679 writer.writeAttribute(styleNS,QString::fromLatin1( "text-line-through-type"),
680 format.fontStrikeOut() ? QString::fromLatin1("single") : QString::fromLatin1("none"));
682 writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-color"), format.underlineColor().name());
683 if (format.hasProperty(QTextFormat::FontFixedPitch)) {
684 // bool fontFixedPitch () const TODO
685 }
686 if (format.hasProperty(QTextFormat::TextUnderlineStyle)) {
688 switch (format.underlineStyle()) {
692 case QTextCharFormat::DotLine: value = QString::fromLatin1("dotted"); break;
693 case QTextCharFormat::DashDotLine: value = QString::fromLatin1("dash-dot"); break;
694 case QTextCharFormat::DashDotDotLine: value = QString::fromLatin1("dot-dot-dash"); break;
697 }
698 writer.writeAttribute(styleNS, QString::fromLatin1("text-underline-style"), value);
699 }
702 switch (format.verticalAlignment()) {
710 }
711 writer.writeAttribute(styleNS, QString::fromLatin1("text-position"), value);
712 }
713 if (format.hasProperty(QTextFormat::TextOutline))
714 writer.writeAttribute(styleNS, QString::fromLatin1("text-outline"), QString::fromLatin1("true"));
715 if (format.hasProperty(QTextFormat::TextToolTip)) {
716 // QString toolTip () const TODO
717 }
718 if (format.hasProperty(QTextFormat::IsAnchor)) {
719 // bool isAnchor () const TODO
720 }
721 if (format.hasProperty(QTextFormat::AnchorHref)) {
722 // QString anchorHref () const TODO
723 }
724 if (format.hasProperty(QTextFormat::AnchorName)) {
725 // QString anchorName () const TODO
726 }
727 if (format.hasProperty(QTextFormat::ForegroundBrush)) {
728 QBrush brush = format.foreground();
729 writer.writeAttribute(foNS, QString::fromLatin1("color"), brush.color().name());
730 }
731 if (format.hasProperty(QTextFormat::BackgroundBrush)) {
732 QBrush brush = format.background();
733 writer.writeAttribute(foNS, QString::fromLatin1("background-color"), brush.color().name());
734 }
735
736 writer.writeEndElement(); // style
737}
738
739void QTextOdfWriter::writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const
740{
741 writer.writeStartElement(textNS, QString::fromLatin1("list-style"));
742 writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("L%1").arg(formatIndex));
743
744 QTextListFormat::Style style = format.style();
749 writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-number"));
750 writer.writeAttribute(styleNS, QString::fromLatin1("num-format"), bulletChar(style));
751
752 if (format.hasProperty(QTextFormat::ListNumberSuffix))
753 writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), format.numberSuffix());
754 else
755 writer.writeAttribute(styleNS, QString::fromLatin1("num-suffix"), QString::fromLatin1("."));
756
757 if (format.hasProperty(QTextFormat::ListNumberPrefix))
758 writer.writeAttribute(styleNS, QString::fromLatin1("num-prefix"), format.numberPrefix());
759
760 } else {
761 writer.writeStartElement(textNS, QString::fromLatin1("list-level-style-bullet"));
762 writer.writeAttribute(textNS, QString::fromLatin1("bullet-char"), bulletChar(style));
763 }
764
765 writer.writeAttribute(textNS, QString::fromLatin1("level"), QString::number(format.indent()));
766 writer.writeEmptyElement(styleNS, QString::fromLatin1("list-level-properties"));
767 writer.writeAttribute(foNS, QString::fromLatin1("text-align"), QString::fromLatin1("start"));
768 QString spacing = QString::fromLatin1("%1mm").arg(format.indent() * 8);
769 writer.writeAttribute(textNS, QString::fromLatin1("space-before"), spacing);
770 //writer.writeAttribute(textNS, QString::fromLatin1("min-label-width"), spacing);
771
772 writer.writeEndElement(); // list-level-style-*
773 writer.writeEndElement(); // list-style
774}
775
776void QTextOdfWriter::writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const
777{
778 writer.writeStartElement(styleNS, QString::fromLatin1("style"));
779 writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("s%1").arg(formatIndex));
780 writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("section"));
781 writer.writeEmptyElement(styleNS, QString::fromLatin1("section-properties"));
782 if (format.hasProperty(QTextFormat::FrameTopMargin))
783 writer.writeAttribute(foNS, QString::fromLatin1("margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) );
784 if (format.hasProperty(QTextFormat::FrameBottomMargin))
785 writer.writeAttribute(foNS, QString::fromLatin1("margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) );
786 if (format.hasProperty(QTextFormat::FrameLeftMargin))
787 writer.writeAttribute(foNS, QString::fromLatin1("margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin())) );
788 if (format.hasProperty(QTextFormat::FrameRightMargin))
789 writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
790
791 writer.writeEndElement(); // style
792
793// TODO consider putting the following properties in a qt-namespace.
794// Position position () const
795// qreal border () const
796// QBrush borderBrush () const
797// BorderStyle borderStyle () const
798// qreal padding () const
799// QTextLength width () const
800// QTextLength height () const
801// PageBreakFlags pageBreakPolicy () const
802}
803
804void QTextOdfWriter::writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const
805{
806 // start writing table style element
807 writer.writeStartElement(styleNS, QString::fromLatin1("style"));
808 writer.writeAttribute(styleNS, QString::fromLatin1("name"),
809 QString::fromLatin1("Table%1").arg(formatIndex));
810 writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table"));
811 writer.writeEmptyElement(styleNS, QString::fromLatin1("table-properties"));
812
813 if (m_tableFormatsWithBorders.contains(formatIndex)) {
814 // write border format collapsing to table style
815 writer.writeAttribute(tableNS, QString::fromLatin1("border-model"),
816 QString::fromLatin1("collapsing"));
817 }
818 const char* align = nullptr;
819 switch (format.alignment()) {
820 case Qt::AlignLeft:
821 align = "left";
822 break;
823 case Qt::AlignRight:
824 align = "right";
825 break;
826 case Qt::AlignHCenter:
827 align = "center";
828 break;
829 case Qt::AlignJustify:
830 align = "margins";
831 break;
832 }
833 if (align)
834 writer.writeAttribute(tableNS, QString::fromLatin1("align"), QString::fromLatin1(align));
835 if (format.width().rawValue()) {
836 writer.writeAttribute(styleNS, QString::fromLatin1("width"),
837 QString::number(format.width().rawValue()) + "pt"_L1);
838 }
839 writer.writeEndElement();
840 // start writing table-column style element
841 if (format.columnWidthConstraints().size()) {
842 // write table-column-properties for columns with constraints
843 m_tableFormatsWithColWidthConstraints.insert(formatIndex); // needed for linking of columns to styles
844 for (int colit = 0; colit < format.columnWidthConstraints().size(); ++colit) {
845 writer.writeStartElement(styleNS, QString::fromLatin1("style"));
846 writer.writeAttribute(styleNS, QString::fromLatin1("name"),
847 QString::fromLatin1("Table%1.%2").arg(formatIndex).arg(colit));
848 writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-column"));
849 writer.writeEmptyElement(styleNS, QString::fromLatin1("table-column-properties"));
850 QString columnWidth;
851 if (format.columnWidthConstraints().at(colit).type() == QTextLength::PercentageLength) {
852 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
853 + "%"_L1;
854 } else if (format.columnWidthConstraints().at(colit).type() == QTextLength::FixedLength) {
855 columnWidth = QString::number(format.columnWidthConstraints().at(colit).rawValue())
856 + "pt"_L1;
857 } else {
859 columnWidth = QString::number(100 / format.columnWidthConstraints().size())
860 + "%"_L1;
861 }
862 writer.writeAttribute(styleNS, QString::fromLatin1("column-width"), columnWidth);
863 writer.writeEndElement();
864 }
865 }
866}
867
869 int formatIndex, QList<QTextFormat> &styles) const
870{
871 // check for all table cells here if they are in a table with border
872 if (m_cellFormatsInTablesWithBorders.contains(formatIndex)) {
873 const QList<int> tableIdVector = m_cellFormatsInTablesWithBorders.value(formatIndex);
874 for (const auto &tableId : tableIdVector) {
875 const auto &tmpStyle = styles.at(tableId);
876 if (tmpStyle.isTableFormat()) {
877 QTextTableFormat tableFormatTmp = tmpStyle.toTableFormat();
878 tableCellStyleElement(writer, formatIndex, format, true, tableId, tableFormatTmp);
879 } else {
880 qDebug("QTextOdfWriter::writeTableCellFormat: ERROR writing table border format");
881 }
882 }
883 }
884 tableCellStyleElement(writer, formatIndex, format, false);
885}
886
887void QTextOdfWriter::tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex,
889 bool hasBorder, int tableId,
890 const QTextTableFormat tableFormatTmp) const {
891 writer.writeStartElement(styleNS, QString::fromLatin1("style"));
892 if (hasBorder) {
893 writer.writeAttribute(styleNS, QString::fromLatin1("name"),
894 QString::fromLatin1("TB%1.%2").arg(tableId).arg(formatIndex));
895 } else {
896 writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("T%1").arg(formatIndex));
897 }
898 writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("table-cell"));
899 writer.writeEmptyElement(styleNS, QString::fromLatin1("table-cell-properties"));
900 if (hasBorder) {
901 writer.writeAttribute(foNS, QString::fromLatin1("border"),
902 pixelToPoint(tableFormatTmp.border()) + " "_L1
903 + borderStyleName(tableFormatTmp.borderStyle()) + " "_L1
904 + tableFormatTmp.borderBrush().color().name(QColor::HexRgb));
905 }
906 qreal topPadding = format.topPadding();
907 qreal padding = topPadding + tableFormatTmp.cellPadding();
908 if (padding > 0 && topPadding == format.bottomPadding()
909 && topPadding == format.leftPadding() && topPadding == format.rightPadding()) {
910 writer.writeAttribute(foNS, QString::fromLatin1("padding"), pixelToPoint(padding));
911 }
912 else {
913 if (padding > 0)
914 writer.writeAttribute(foNS, QString::fromLatin1("padding-top"), pixelToPoint(padding));
915 padding = format.bottomPadding() + tableFormatTmp.cellPadding();
916 if (padding > 0)
917 writer.writeAttribute(foNS, QString::fromLatin1("padding-bottom"),
918 pixelToPoint(padding));
919 padding = format.leftPadding() + tableFormatTmp.cellPadding();
920 if (padding > 0)
921 writer.writeAttribute(foNS, QString::fromLatin1("padding-left"),
922 pixelToPoint(padding));
923 padding = format.rightPadding() + tableFormatTmp.cellPadding();
924 if (padding > 0)
925 writer.writeAttribute(foNS, QString::fromLatin1("padding-right"),
926 pixelToPoint(padding));
927 }
928
930 QString pos;
931 switch (format.verticalAlignment()) { // TODO - review: doesn't handle all cases
933 pos = QString::fromLatin1("middle"); break;
935 pos = QString::fromLatin1("top"); break;
937 pos = QString::fromLatin1("bottom"); break;
938 default:
939 pos = QString::fromLatin1("automatic"); break;
940 }
941 writer.writeAttribute(styleNS, QString::fromLatin1("vertical-align"), pos);
942 }
943
944 // TODO
945 // ODF just search for style-table-cell-properties-attlist)
946 // QTextFormat::BackgroundImageUrl
947 // format.background
948 writer.writeEndElement(); // style
949}
950
952
954 : officeNS ("urn:oasis:names:tc:opendocument:xmlns:office:1.0"_L1),
955 textNS ("urn:oasis:names:tc:opendocument:xmlns:text:1.0"_L1),
956 styleNS ("urn:oasis:names:tc:opendocument:xmlns:style:1.0"_L1),
957 foNS ("urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"_L1),
958 tableNS ("urn:oasis:names:tc:opendocument:xmlns:table:1.0"_L1),
959 drawNS ("urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"_L1),
960 xlinkNS ("http://www.w3.org/1999/xlink"_L1),
961 svgNS ("urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"_L1),
962 m_document(&document),
963 m_device(device),
964 m_strategy(nullptr),
965 m_createArchive(true)
966{
967}
968
970{
971 if (m_createArchive)
972 m_strategy = new QZipStreamStrategy(m_device);
973 else
974 m_strategy = new QXmlStreamStrategy(m_device);
975
976 if (!m_device->isWritable() && ! m_device->open(QIODevice::WriteOnly)) {
977 qWarning("QTextOdfWriter::writeAll: the device cannot be opened for writing");
978 return false;
979 }
980 QXmlStreamWriter writer(m_strategy->contentStream);
981 // prettyfy
982 writer.setAutoFormatting(true);
983 writer.setAutoFormattingIndent(2);
984
985 writer.writeNamespace(officeNS, QString::fromLatin1("office"));
986 writer.writeNamespace(textNS, QString::fromLatin1("text"));
987 writer.writeNamespace(styleNS, QString::fromLatin1("style"));
988 writer.writeNamespace(foNS, QString::fromLatin1("fo"));
989 writer.writeNamespace(tableNS, QString::fromLatin1("table"));
990 writer.writeNamespace(drawNS, QString::fromLatin1("draw"));
991 writer.writeNamespace(xlinkNS, QString::fromLatin1("xlink"));
992 writer.writeNamespace(svgNS, QString::fromLatin1("svg"));
993 writer.writeStartDocument();
994 writer.writeStartElement(officeNS, QString::fromLatin1("document-content"));
995 writer.writeAttribute(officeNS, QString::fromLatin1("version"), QString::fromLatin1("1.2"));
996
997 // add fragments. (for character formats)
999 QSet<int> formats;
1000 while (fragIt != QTextDocumentPrivate::get(m_document)->end()) {
1001 const QTextFragmentData * const frag = fragIt.value();
1002 formats << frag->format;
1003 ++fragIt;
1004 }
1005
1006 // add blocks (for blockFormats)
1007 QTextDocumentPrivate::BlockMap &blocks = const_cast<QTextDocumentPrivate *>(QTextDocumentPrivate::get(m_document))->blockMap();
1009 while (blockIt != blocks.end()) {
1010 const QTextBlockData * const block = blockIt.value();
1011 formats << block->format;
1012 ++blockIt;
1013 }
1014
1015 // add objects for lists, frames and tables
1016 const QList<QTextFormat> allFormats = m_document->allFormats();
1017 const QList<int> copy = formats.values();
1018 for (auto index : copy) {
1019 QTextObject *object = m_document->objectForFormat(allFormats[index]);
1020 if (object) {
1021 formats << object->formatIndex();
1022 if (auto *tableobject = qobject_cast<QTextTable *>(object)) {
1023 if (tableobject->format().borderStyle()) {
1024 int tableID = tableobject->formatIndex();
1025 m_tableFormatsWithBorders.insert(tableID);
1026 // loop through all rows and cols of table and store cell IDs,
1027 // create Hash with cell ID as Key and table IDs as Vector
1028 for (int rowindex = 0; rowindex < tableobject->rows(); ++rowindex) {
1029 for (int colindex = 0; colindex < tableobject->columns(); ++colindex) {
1030 const int cellFormatID = tableobject->cellAt(rowindex, colindex).tableCellFormatIndex();
1031 QList<int> tableIdsTmp;
1032 if (m_cellFormatsInTablesWithBorders.contains(cellFormatID))
1033 tableIdsTmp = m_cellFormatsInTablesWithBorders.value(cellFormatID);
1034 if (!tableIdsTmp.contains(tableID))
1035 tableIdsTmp.append(tableID);
1036 m_cellFormatsInTablesWithBorders.insert(cellFormatID, tableIdsTmp);
1037 }
1038 }
1039 }
1040 }
1041 }
1042 }
1043
1044 writeFormats(writer, formats);
1045
1046 writer.writeStartElement(officeNS, QString::fromLatin1("body"));
1047 writer.writeStartElement(officeNS, QString::fromLatin1("text"));
1048 QTextFrame *rootFrame = m_document->rootFrame();
1049 writeFrame(writer, rootFrame);
1050 writer.writeEndElement(); // text
1051 writer.writeEndElement(); // body
1052 writer.writeEndElement(); // document-content
1053 writer.writeEndDocument();
1054 delete m_strategy;
1055 m_strategy = nullptr;
1056
1057 return true;
1058}
1059
1061
1062#endif // QT_NO_TEXTODFWRITER
IOBluetoothDevice * device
\inmodule QtGui
Definition qbrush.h:30
\inmodule QtCore \reentrant
Definition qbuffer.h:16
bool open(OpenMode openMode) override
\reimp
Definition qbuffer.cpp:295
void close() override
\reimp
Definition qbuffer.cpp:315
\inmodule QtCore
Definition qbytearray.h:57
QByteArray toLower() const &
Definition qbytearray.h:254
\inmodule QtCore
@ HexRgb
Definition qcolor.h:36
bool seek(qint64 offset) override
For random-access devices, this function sets the current position to pos, returning true on success,...
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
@ AllLowercase
Definition qfont.h:100
@ AllUppercase
Definition qfont.h:99
@ Capitalize
Definition qfont.h:102
@ MixedCase
Definition qfont.h:98
@ SmallCaps
Definition qfont.h:101
@ Bold
Definition qfont.h:70
@ Normal
Definition qfont.h:67
Iterator begin()
Iterator end()
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:1007
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool open(QIODeviceBase::OpenMode mode)
Opens the device and sets its OpenMode to mode.
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
bool isWritable() const
Returns true if data can be written to the device; otherwise returns false.
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
The QImageReader class provides a format independent interface for reading images from files or other...
QByteArray format() const
Returns the format QImageReader uses for reading images.
QSize size() const
Returns the size of the image, without actually reading the image contents.
QImage read()
Reads an image from the device.
The QImageWriter class provides a format independent interface for writing images to files or other d...
\inmodule QtGui
Definition qimage.h:37
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
void append(parameter_type t)
Definition qlist.h:458
virtual ~QOutputStrategy()
QIODevice * contentStream
QString createUniqueImageName()
virtual void addFile(const QString &fileName, const QString &mimeType, const QByteArray &bytes)=0
bool contains(const T &value) const
Definition qset.h:71
iterator insert(const T &value)
Definition qset.h:155
\inmodule QtCore
Definition qsize.h:25
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
T & top()
Returns a reference to the stack's top item.
Definition qstack.h:19
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
void push(const T &t)
Adds element t to the top of the stack.
Definition qstack.h:17
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5871
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
QString & prepend(QChar c)
Definition qstring.h:478
\reentrant
iterator begin() const
Returns a text block iterator pointing to the beginning of the text block.
int length() const
Returns the length of the block in characters.
int position() const
Returns the index of the block's first character within the document.
QTextList * textList() const
If the block represents a list item, returns the list that the item belongs to; otherwise returns \nu...
int blockFormatIndex() const
Returns an index into the document's internal list of block formats for the text block's format.
static const QTextDocumentPrivate * get(const QTextDocument *document)
FragmentMap::ConstIterator FragmentIterator
\reentrant \inmodule QtGui
QList< QTextFormat > allFormats() const
Returns a list of text formats for all the formats used in the document.
QTextObject * objectForFormat(const QTextFormat &) const
Returns the text object associated with the format f.
QVariant resource(int type, const QUrl &name) const
Returns data of the specified type from the resource with the given name.
QTextFrame * rootFrame() const
Returns the document's root frame.
\reentrant
Definition qtextformat.h:90
QTextCharFormat toCharFormat() const
Returns this format as a character format.
bool isTableCellFormat() const
QTextBlockFormat toBlockFormat() const
Returns this format as a block format.
@ TextVerticalAlignment
@ BlockNonBreakableLines
bool isImageFormat() const
Returns true if this text format is an image format; otherwise returns false.
QTextTableFormat toTableFormat() const
Returns this format as a table format.
QTextImageFormat toImageFormat() const
Returns this format as an image format.
QTextTableCellFormat toTableCellFormat() const
QTextListFormat toListFormat() const
Returns this format as a list format.
bool hasProperty(int propertyId) const
Returns true if the text format has a property with the given propertyId; otherwise returns false.
QTextFrameFormat toFrameFormat() const
Returns this format as a frame format.
int type() const
Returns the type of this format.
bool isTableFormat() const
Returns true if this text format is a TableFormat; otherwise returns false.
@ PageBreak_AlwaysBefore
@ PageBreak_AlwaysAfter
\reentrant
QTextCharFormat charFormat() const
Returns the text fragment's character format.
\reentrant
Definition qtextobject.h:81
qreal width() const
Returns the width of the rectangle occupied by the image.
int quality() const
qreal height() const
Returns the height of the rectangle occupied by the image.
QString name() const
Returns the name of the image.
Style
This enum describes the symbols used to decorate list items:
int indent() const
Returns the list format's indentation.
QTextListFormat format() const
Returns the list's format.
Definition qtextlist.h:37
\reentrant
Definition qtextobject.h:25
int formatIndex() const
Returns the index of the object's format in the document's internal list of formats.
void writeFrameFormat(QXmlStreamWriter &writer, QTextFrameFormat format, int formatIndex) const
void writeFormats(QXmlStreamWriter &writer, const QSet< int > &formatIds) const
const QString svgNS
const QString xlinkNS
void writeFrame(QXmlStreamWriter &writer, const QTextFrame *frame)
void writeBlock(QXmlStreamWriter &writer, const QTextBlock &block)
const QString styleNS
const QString textNS
const QString officeNS
QTextOdfWriter(const QTextDocument &document, QIODevice *device)
const QString drawNS
void writeTableFormat(QXmlStreamWriter &writer, QTextTableFormat format, int formatIndex) const
void tableCellStyleElement(QXmlStreamWriter &writer, const int &formatIndex, const QTextTableCellFormat &format, bool hasBorder, int tableId=0, const QTextTableFormat tableFormatTmp=QTextTableFormat()) const
const QString tableNS
const QString foNS
void writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format, int formatIndex) const
void writeTableCellFormat(QXmlStreamWriter &writer, QTextTableCellFormat format, int formatIndex, QList< QTextFormat > &styles) const
void writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const
void writeListFormat(QXmlStreamWriter &writer, QTextListFormat format, int formatIndex) const
void writeCharacterFormat(QXmlStreamWriter &writer, QTextCharFormat format, int formatIndex) const
\reentrant
Definition qtexttable.h:19
QTextCharFormat format() const
Returns the cell's character format.
int columnSpan() const
Returns the number of columns this cell spans.
int row() const
Returns the number of the row in the table that contains this cell.
int rowSpan() const
Returns the number of rows this cell spans.
int tableCellFormatIndex() const
\reentrant
Definition qtexttable.h:63
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:65
int userType() const
Definition qvariant.h:339
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
virtual void addFile(const QString &, const QString &, const QByteArray &) override
QXmlStreamStrategy(QIODevice *device)
QZipStreamStrategy(QIODevice *device)
virtual void addFile(const QString &fileName, const QString &mimeType, const QByteArray &bytes) override
the QZipWriter class provides a way to create a new zip archive.
void addFile(const QString &fileName, const QByteArray &data)
Add a file to the archive with data as the file contents.
Definition qzip.cpp:1257
void close()
Closes the zip file.
Definition qzip.cpp:1312
void setCompressionPolicy(CompressionPolicy policy)
Sets the policy for compressing newly added files to the new policy.
Definition qzip.cpp:1206
QMap< QString, QString > map
[6]
qreal spacing
uint alignment
EGLint EGLint * formats
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:146
@ AlignLeading
Definition qnamespace.h:145
@ AlignJustify
Definition qnamespace.h:149
@ AlignTrailing
Definition qnamespace.h:147
@ AlignHCenter
Definition qnamespace.h:148
@ AlignHorizontal_Mask
Definition qnamespace.h:151
@ AlignAbsolute
Definition qnamespace.h:150
@ AlignLeft
Definition qnamespace.h:144
Definition brush.cpp:5
Definition image.cpp:4
static jboolean copy(JNIEnv *, jobject)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * mimeType
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint buffer
GLint GLsizei width
GLenum type
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum const void * pixels
GLuint name
GLint GLsizei GLsizei GLenum format
GLuint counter
GLdouble s
[6]
Definition qopenglext.h:235
GLenum GLenum GLsizei void * table
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
SSL_CTX int void * arg
#define QStringLiteral(str)
static QString borderStyleName(QTextFrameFormat::BorderStyle style)
static QString pixelToPoint(qreal pixels)
Convert pixels to postscript point units.
static QString bulletChar(QTextListFormat::Style style)
static bool probeImageData(QIODevice *device, QImage *image, QString *mimeType, qreal *width, qreal *height)
static QStringView bullet_char(QTextListFormat::Style style)
unsigned int uint
Definition qtypes.h:34
double qreal
Definition qtypes.h:187
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
QObject::connect nullptr
QVariant variant
[1]
QLayoutItem * child
[0]
QFrame frame
[0]