qreal KDReports::TextDocReportLayout::layoutAsOnePage(qreal docWidth) { m_textDocument.layoutWithTextWidth(docWidth); qreal docHeight = m_textDocument.contentDocument().size().height(); #if QT_VERSION <= 0x040300 // Qt-4.2 bug, fixed in Qt-4.3: QTextDocumentLayout::dynamicPageCount() // returns docheight/pageheight + 1. So if the doc is just as high as the page, I get 2 pages. docHeight += 1; #endif // We need to get rid of all page breaks... // Unittest: PageLayout::testEndlessPrinterWithPageBreaks() QTextCursor c(&m_textDocument.contentDocument()); c.beginEditBlock(); QTextBlock block = m_textDocument.contentDocument().firstBlock(); do { //qDebug() << "addBlock: Looking at block" << block.blockNumber(); QTextBlockFormat format = block.blockFormat(); if ( format.pageBreakPolicy() != QTextBlockFormat::PageBreak_Auto ) format.setPageBreakPolicy( QTextBlockFormat::PageBreak_Auto ); c.setPosition( block.position() ); c.setBlockFormat( format ); block = block.next(); } while ( block.isValid() ); c.endEditBlock(); setPageContentSize(QSizeF(docWidth, docHeight)); qDebug() << "m_textDocument.layoutDocument().setPageSize" << docWidth << "x" << docHeight << numberOfPages() << "pages"; qreal newDocHeight = m_textDocument.contentDocument().size().height(); if (newDocHeight > docHeight) { // QTextDocument is playing tricks on us; it was able to layout as docWidth x docHeight // but once we set that as the page size, we end up with more height... // Unittest: PageLayout::testEndlessPrinterBug() qDebug() << "newDocHeight=" << newDocHeight << "expected" << docHeight; setPageContentSize(QSizeF(docWidth, newDocHeight)); newDocHeight = m_textDocument.contentDocument().size().height(); qDebug() << "final newDocHeight=" << newDocHeight << numberOfPages() << "pages"; } Q_ASSERT(numberOfPages() == 1); return newDocHeight; }
void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat format, int formatIndex) const { writer.writeStartElement(styleNS, QString::fromLatin1("style")); writer.writeAttribute(styleNS, QString::fromLatin1("name"), QString::fromLatin1("p%1").arg(formatIndex)); writer.writeAttribute(styleNS, QString::fromLatin1("family"), QString::fromLatin1("paragraph")); writer.writeStartElement(styleNS, QString::fromLatin1("paragraph-properties")); if (format.hasProperty(QTextFormat::BlockAlignment)) { const Qt::Alignment alignment = format.alignment() & Qt::AlignHorizontal_Mask; QString value; if (alignment == Qt::AlignLeading) value = QString::fromLatin1("start"); else if (alignment == Qt::AlignTrailing) value = QString::fromLatin1("end"); else if (alignment == (Qt::AlignLeft | Qt::AlignAbsolute)) value = QString::fromLatin1("left"); else if (alignment == (Qt::AlignRight | Qt::AlignAbsolute)) value = QString::fromLatin1("right"); else if (alignment == Qt::AlignHCenter) value = QString::fromLatin1("center"); else if (alignment == Qt::AlignJustify) value = QString::fromLatin1("justify"); else qWarning() << "QTextOdfWriter: unsupported paragraph alignment; " << format.alignment(); if (! value.isNull()) writer.writeAttribute(foNS, QString::fromLatin1("text-align"), value); } if (format.hasProperty(QTextFormat::BlockTopMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-top"), pixelToPoint(qMax(qreal(0.), format.topMargin())) ); if (format.hasProperty(QTextFormat::BlockBottomMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-bottom"), pixelToPoint(qMax(qreal(0.), format.bottomMargin())) ); if (format.hasProperty(QTextFormat::BlockLeftMargin) || format.hasProperty(QTextFormat::BlockIndent)) writer.writeAttribute(foNS, QString::fromLatin1("margin-left"), pixelToPoint(qMax(qreal(0.), format.leftMargin() + format.indent()))); if (format.hasProperty(QTextFormat::BlockRightMargin)) writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) ); if (format.hasProperty(QTextFormat::TextIndent)) writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), pixelToPoint(format.textIndent())); if (format.hasProperty(QTextFormat::PageBreakPolicy)) { if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore) writer.writeAttribute(foNS, QString::fromLatin1("break-before"), QString::fromLatin1("page")); if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysAfter) writer.writeAttribute(foNS, QString::fromLatin1("break-after"), QString::fromLatin1("page")); } if (format.hasProperty(QTextFormat::BackgroundBrush)) { QBrush brush = format.background(); writer.writeAttribute(foNS, QString::fromLatin1("background-color"), brush.color().name()); } if (format.hasProperty(QTextFormat::BlockNonBreakableLines)) writer.writeAttribute(foNS, QString::fromLatin1("keep-together"), format.nonBreakableLines() ? QString::fromLatin1("true") : QString::fromLatin1("false")); if (format.hasProperty(QTextFormat::TabPositions)) { QList<QTextOption::Tab> tabs = format.tabPositions(); writer.writeStartElement(styleNS, QString::fromLatin1("tab-stops")); QList<QTextOption::Tab>::Iterator iterator = tabs.begin(); while(iterator != tabs.end()) { writer.writeEmptyElement(styleNS, QString::fromLatin1("tab-stop")); writer.writeAttribute(styleNS, QString::fromLatin1("position"), pixelToPoint(iterator->position) ); QString type; switch(iterator->type) { case QTextOption::DelimiterTab: type = QString::fromLatin1("char"); break; case QTextOption::LeftTab: type = QString::fromLatin1("left"); break; case QTextOption::RightTab: type = QString::fromLatin1("right"); break; case QTextOption::CenterTab: type = QString::fromLatin1("center"); break; } writer.writeAttribute(styleNS, QString::fromLatin1("type"), type); if (iterator->delimiter != 0) writer.writeAttribute(styleNS, QString::fromLatin1("char"), iterator->delimiter); ++iterator; } writer.writeEndElement(); // tab-stops } writer.writeEndElement(); // paragraph-properties writer.writeEndElement(); // style }
void QTextHtmlImporter::import() { cursor.beginEditBlock(); hasBlock = true; forceBlockMerging = false; compressNextWhitespace = RemoveWhiteSpace; blockTagClosed = false; for (currentNodeIdx = 0; currentNodeIdx < count(); ++currentNodeIdx) { currentNode = &at(currentNodeIdx); wsm = textEditMode ? QTextHtmlParserNode::WhiteSpacePreWrap : currentNode->wsm; /* * process each node in three stages: * 1) check if the hierarchy changed and we therefore passed the * equivalent of a closing tag -> we may need to finish off * some structures like tables * * 2) check if the current node is a special node like a * <table>, <ul> or <img> tag that requires special processing * * 3) if the node should result in a QTextBlock create one and * finally insert text that may be attached to the node */ /* emit 'closing' table blocks or adjust current indent level * if we * 1) are beyond the first node * 2) the current node not being a child of the previous node * means there was a tag closing in the input html */ if (currentNodeIdx > 0 && (currentNode->parent != currentNodeIdx - 1)) { blockTagClosed = closeTag(); // visually collapse subsequent block tags, but if the element after the closed block tag // is for example an inline element (!isBlock) we have to make sure we start a new paragraph by setting // hasBlock to false. if (blockTagClosed && !currentNode->isBlock() && currentNode->id != Html_unknown) { hasBlock = false; } else if (hasBlock) { // when collapsing subsequent block tags we need to clear the block format QTextBlockFormat blockFormat = currentNode->blockFormat; blockFormat.setIndent(indent); QTextBlockFormat oldFormat = cursor.blockFormat(); if (oldFormat.hasProperty(QTextFormat::PageBreakPolicy)) { QTextFormat::PageBreakFlags pageBreak = oldFormat.pageBreakPolicy(); if (pageBreak == QTextFormat::PageBreak_AlwaysAfter) /* We remove an empty paragrah that requested a page break after. moving that request to the next paragraph means we also need to make that a pagebreak before to keep the same visual appearance. */ pageBreak = QTextFormat::PageBreak_AlwaysBefore; blockFormat.setPageBreakPolicy(pageBreak); } cursor.setBlockFormat(blockFormat); } } if (currentNode->displayMode == QTextHtmlElement::DisplayNone) { if (currentNode->id == Html_title) doc->setMetaInformation(QTextDocument::DocumentTitle, currentNode->text); // ignore explicitly 'invisible' elements continue; } if (processSpecialNodes() == ContinueWithNextNode) continue; // make sure there's a block for 'Blah' after <ul><li>foo</ul>Blah if (blockTagClosed && !hasBlock && !currentNode->isBlock() && !currentNode->text.isEmpty() && !currentNode->hasOnlyWhitespace() && currentNode->displayMode == QTextHtmlElement::DisplayInline) { QTextBlockFormat block = currentNode->blockFormat; block.setIndent(indent); appendBlock(block, currentNode->charFormat); hasBlock = true; } if (currentNode->isBlock()) { if (processBlockNode() == ContinueWithNextNode) continue; } if (currentNode->charFormat.isAnchor() && !currentNode->charFormat.anchorName().isEmpty()) { namedAnchors.append(currentNode->charFormat.anchorName()); } if (appendNodeText()) hasBlock = false; // if we actually appended text then we don't // have an empty block anymore } cursor.endEditBlock(); }