diff --git a/qbasichtmlexporter.cpp b/qbasichtmlexporter.cpp index fe3f909..52a322b 100644 --- a/qbasichtmlexporter.cpp +++ b/qbasichtmlexporter.cpp @@ -11,358 +11,373 @@ static QTextFormat formatDifference(const QTextFormat &from, const QTextFormat &to) { - QTextFormat diff = to; - const QMap props = to.properties(); - for (QMap::ConstIterator it = props.begin(), end = props.end(); - it != end; ++it) - if (it.value() == from.property(it.key())) - diff.clearProperty(it.key()); - return diff; + QTextFormat diff = to; + const QMap props = to.properties(); + for (QMap::ConstIterator it = props.begin(), end = props.end(); + it != end; ++it) + if (it.value() == from.property(it.key())) + diff.clearProperty(it.key()); + return diff; } QBasicHtmlExporter::QBasicHtmlExporter(QTextDocument *_doc) { - doc = _doc; - const QFont defaultFont = doc->defaultFont(); - defaultCharFormat.setFont(defaultFont); - // don't export those for the default font since we cannot turn them off with CSS - defaultCharFormat.clearProperty(QTextFormat::FontUnderline); - defaultCharFormat.clearProperty(QTextFormat::FontOverline); - defaultCharFormat.clearProperty(QTextFormat::FontStrikeOut); - defaultCharFormat.clearProperty(QTextFormat::TextUnderlineStyle); + doc = _doc; + const QFont defaultFont = doc->defaultFont(); + defaultCharFormat.setFont(defaultFont); + // don't export those for the default font since we cannot turn them off with CSS + defaultCharFormat.clearProperty(QTextFormat::FontUnderline); + defaultCharFormat.clearProperty(QTextFormat::FontOverline); + defaultCharFormat.clearProperty(QTextFormat::FontStrikeOut); + defaultCharFormat.clearProperty(QTextFormat::TextUnderlineStyle); } QString QBasicHtmlExporter::toHtml() { - html = QLatin1String(""); - emitFrame(doc->rootFrame()->begin()); + html = QLatin1String(""); + emitFrame(doc->rootFrame()->begin()); - // Remove newlines at beginning - html.remove(QRegExp("^[\r\n]+")); + // Remove newlines at beginning + html.remove(QRegularExpression("^[\r\n]+")); - return html; + return html; } QBasicHtmlExporter::Heading QBasicHtmlExporter::headingType(QString name) { - if ( name == "xx-large" ) return h1; - if ( name == "x-large" ) return h2; - if ( name == "large" ) return h3; - if ( name == "medium" ) return h4; - if ( name == "small" ) return h5; - return paragraph; + if ( name == "xx-large" ) return h1; + if ( name == "x-large" ) return h2; + if ( name == "large" ) return h3; + if ( name == "medium" ) return h4; + if ( name == "small" ) return h5; + return paragraph; } QString QBasicHtmlExporter::headingStr(QBasicHtmlExporter::Heading heading) { - switch (heading) { - case h1: - return "h1"; - case h2: - return "h2"; - case h3: - return "h3"; - case h4: - return "h4"; - case h5: - return "h5"; - default: - return "p"; - } + switch (heading) { + case h1: + return "h1"; + case h2: + return "h2"; + case h3: + return "h3"; + case h4: + return "h4"; + case h5: + return "h5"; + default: + return "p"; + } } QString QBasicHtmlExporter::getTagName(const QTextCharFormat &format) { - Heading cur_heading = paragraph; - - if (format.hasProperty(QTextFormat::FontSizeAdjustment)) { - static const char sizeNameData[] = - "small" "\0" - "medium" "\0" - "xx-large" ; - static const quint8 sizeNameOffsets[] = { - 0, // "small" - sizeof("small"), // "medium" - sizeof("small") + sizeof("medium") + 3, // "large" ) - sizeof("small") + sizeof("medium") + 1, // "x-large" )> compressed into "xx-large" - sizeof("small") + sizeof("medium"), // "xx-large" ) - }; - const char *name = nullptr; - const int idx = format.intProperty(QTextFormat::FontSizeAdjustment) + 1; - if (idx >= 0 && idx <= 4) { - name = sizeNameData + sizeNameOffsets[idx]; - } - if (name) { - cur_heading = headingType(name); - } - } - return headingStr( cur_heading ); + Heading cur_heading = paragraph; + + if (format.hasProperty(QTextFormat::FontSizeAdjustment)) { + static const char sizeNameData[] = + "small" "\0" + "medium" "\0" + "xx-large" ; + static const quint8 sizeNameOffsets[] = { + 0, // "small" + sizeof("small"), // "medium" + sizeof("small") + sizeof("medium") + 3, // "large" ) + sizeof("small") + sizeof("medium") + 1, // "x-large" )> compressed into "xx-large" + sizeof("small") + sizeof("medium"), // "xx-large" ) + }; + const char *name = nullptr; + const int idx = format.intProperty(QTextFormat::FontSizeAdjustment) + 1; + if (idx >= 0 && idx <= 4) { + name = sizeNameData + sizeNameOffsets[idx]; + } + if (name) { + cur_heading = headingType(name); + } + } + return headingStr( cur_heading ); } void QBasicHtmlExporter::emitFrame(const QTextFrame::Iterator &frameIt) { - if (!frameIt.atEnd()) { - QTextFrame::Iterator next = frameIt; - ++next; - if (next.atEnd() - && frameIt.currentFrame() == nullptr - && frameIt.parentFrame() != doc->rootFrame() - && frameIt.currentBlock().begin().atEnd()) - return; - } - for (QTextFrame::Iterator it = frameIt; - !it.atEnd(); ++it) { - if (QTextFrame *f = it.currentFrame()) { - if (QTextTable *table = qobject_cast(f)) { - emitTable(table); - } else { - emitTextFrame(f); - } - } else if (it.currentBlock().isValid()) { - emitBlock(it.currentBlock()); - } - } + if (!frameIt.atEnd()) { + QTextFrame::Iterator next = frameIt; + ++next; + if (next.atEnd() + && frameIt.currentFrame() == nullptr + && frameIt.parentFrame() != doc->rootFrame() + && frameIt.currentBlock().begin().atEnd()) + return; + } + for (QTextFrame::Iterator it = frameIt; + !it.atEnd(); ++it) { + if (QTextFrame *f = it.currentFrame()) { + if (QTextTable *table = qobject_cast(f)) { + emitTable(table); + } else { + emitTextFrame(f); + } + } else if (it.currentBlock().isValid()) { + emitBlock(it.currentBlock()); + } + } } void QBasicHtmlExporter::emitTable(const QTextTable *table) { - QTextTableFormat format = table->format(); - html += QLatin1String("\n"); - const int rows = table->rows(); - const int columns = table->columns(); - QVector columnWidths = format.columnWidthConstraints(); - if (columnWidths.isEmpty()) { - columnWidths.resize(columns); - columnWidths.fill(QTextLength()); - } - Q_ASSERT(columnWidths.count() == columns); - QVarLengthArray widthEmittedForColumn(columns); - for (int i = 0; i < columns; ++i) - widthEmittedForColumn[i] = false; - const int headerRowCount = qMin(format.headerRowCount(), rows); - if (headerRowCount > 0) - html += QLatin1String(""); - for (int row = 0; row < rows; ++row) { - html += QLatin1String("\n"); - for (int col = 0; col < columns; ++col) { - const QTextTableCell cell = table->cellAt(row, col); - // for col/rowspans - if (cell.row() != row) - continue; - if (cell.column() != col) - continue; - html += QLatin1String("\n"); - } - html += QLatin1String(""); - if (headerRowCount > 0 && row == headerRowCount - 1) - html += QLatin1String(""); - } - html += QLatin1String("
"); - emitFrame(cell.begin()); - html += QLatin1String("
"); + QTextTableFormat format = table->format(); + html += QLatin1String("\n"); + const int rows = table->rows(); + const int columns = table->columns(); + QVector columnWidths = format.columnWidthConstraints(); + if (columnWidths.isEmpty()) { + columnWidths.resize(columns); + columnWidths.fill(QTextLength()); + } + Q_ASSERT(columnWidths.count() == columns); + QVarLengthArray widthEmittedForColumn(columns); + for (int i = 0; i < columns; ++i) + widthEmittedForColumn[i] = false; + const int headerRowCount = qMin(format.headerRowCount(), rows); + if (headerRowCount > 0) + html += QLatin1String(""); + for (int row = 0; row < rows; ++row) { + html += QLatin1String("\n"); + for (int col = 0; col < columns; ++col) { + const QTextTableCell cell = table->cellAt(row, col); + // for col/rowspans + if (cell.row() != row) + continue; + if (cell.column() != col) + continue; + html += QLatin1String("\n"); + } + html += QLatin1String(""); + if (headerRowCount > 0 && row == headerRowCount - 1) + html += QLatin1String(""); + } + html += QLatin1String("
"); + emitFrame(cell.begin()); + html += QLatin1String("
"); } void QBasicHtmlExporter::emitTextFrame(const QTextFrame *f) { - html += QLatin1String("\n"); - QTextFrameFormat format = f->frameFormat(); - html += QLatin1String("\n\n"); - emitFrame(f->begin()); - html += QLatin1String("
"); + html += QLatin1String("\n"); + QTextFrameFormat format = f->frameFormat(); + html += QLatin1String("\n\n"); + emitFrame(f->begin()); + html += QLatin1String("
"); } void QBasicHtmlExporter::emitBlock(const QTextBlock &block) { - html += QLatin1Char('\n'); - // save and later restore, in case we 'change' the default format by - // emitting block char format information - QTextCharFormat oldDefaultCharFormat = defaultCharFormat; - QTextList *list = block.textList(); - bool numbered_list = false; - if (list) { - if (list->itemNumber(block) == 0) { // first item? emit
    or appropriate - const QTextListFormat format = list->format(); - const int style = format.style(); - switch (style) { - case QTextListFormat::ListDecimal: numbered_list = true; break; - case QTextListFormat::ListLowerAlpha: numbered_list = true; break; - case QTextListFormat::ListUpperAlpha: numbered_list = true; break; - case QTextListFormat::ListLowerRoman: numbered_list = true; break; - case QTextListFormat::ListUpperRoman: numbered_list = true; break; - } - - html += QString("<%1>").arg(numbered_list ? "ol" : "ul"); - } - html += QLatin1String("
  • "); - const QTextCharFormat blockFmt = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat(); - - if (!blockFmt.properties().isEmpty()) { - emitCharFormatStyle(blockFmt); - defaultCharFormat.merge(block.charFormat()); - } - } - - const QTextBlockFormat blockFormat = block.blockFormat(); - if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { - html += QLatin1String("
    "); - return; - } - - const bool pre = blockFormat.nonBreakableLines(); - static bool inPre = false; - if (pre && !inPre) { - html += QLatin1String("
    ");
    -		inPre = true;
    -	} else if (!list) {
    -		const QTextCharFormat charFmt = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat();
    -		QString tagname = getTagName(charFmt);
    -		if ( !inPre || tagname != "p" ) {
    -			html += QString("<%1>").arg( tagname );
    -		}
    -	}
    -
    -	// Text
    -	QTextBlock::Iterator it = block.begin();
    -	for (; !it.atEnd(); ++it)
    -		emitFragment(it.fragment());
    -	block.next();
    -
    -	if ((pre && !block.next().isValid()) ||
    -			(pre &&  block.next().isValid() && !block.next().blockFormat().nonBreakableLines())) {
    -		html += QLatin1String("
    "); - inPre = false; - if ( !block.next().isValid() ) { - html+="
    "; - } - } else if (list) - html += QLatin1String("
  • "); - else { - const QTextCharFormat charFmt = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat(); - QString tagname = getTagName(charFmt); - if ( !inPre ) { - html += QString("").arg( tagname ); - } - } - if (list) { - if (list->itemNumber(block) == list->count() - 1) { // last item? close list - html += QString("<%1>").arg(numbered_list ? "ol" : "ul"); - } - } - defaultCharFormat = oldDefaultCharFormat; + html += QLatin1Char('\n'); + // save and later restore, in case we 'change' the default format by + // emitting block char format information + QTextCharFormat oldDefaultCharFormat = defaultCharFormat; + QTextList *list = block.textList(); + bool numbered_list = false; + if (list) { + if (list->itemNumber(block) == 0) { // first item? emit