📄 qtextdocument.cpp
字号:
if (mode == EmitStyleTag) html += QLatin1String(" style=\"float:"); else html += QLatin1String(" float:"); if (pos == QTextFrameFormat::FloatLeft) html += QLatin1String(" left;"); else if (pos == QTextFrameFormat::FloatRight) html += QLatin1String(" right;"); else Q_ASSERT_X(0, "QTextHtmlExporter::emitFloatStyle()", "pos should be a valid enum type"); if (mode == EmitStyleTag) html += QLatin1Char('\"');}void QTextHtmlExporter::emitMargins(const QString &top, const QString &bottom, const QString &left, const QString &right){ html += QLatin1String(" margin-top:"); html += top; html += QLatin1String("px;"); html += QLatin1String(" margin-bottom:"); html += bottom; html += QLatin1String("px;"); html += QLatin1String(" margin-left:"); html += left; html += QLatin1String("px;"); html += QLatin1String(" margin-right:"); html += right; html += QLatin1String("px;");}void QTextHtmlExporter::emitFragment(const QTextFragment &fragment){ const QTextCharFormat format = fragment.charFormat(); bool closeAnchor = false; if (format.isAnchor()) { const QString name = format.anchorName(); if (!name.isEmpty()) { html += QLatin1String("<a name=\""); html += name; html += QLatin1String("\"></a>"); } const QString href = format.anchorHref(); if (!href.isEmpty()) { html += QLatin1String("<a href=\""); html += href; html += QLatin1String("\">"); closeAnchor = true; } } QLatin1String styleTag("<span style=\""); html += styleTag; const bool attributesEmitted = emitCharFormatStyle(format); if (attributesEmitted) html += QLatin1String("\">"); else html.chop(qstrlen(styleTag.latin1())); // qt 4.0.0's parser only supports logical font sizes through the // font tag, not through css, so we have to emit <font> here ;( const bool emittedFontTag = emitLogicalFontSize(format); QString txt = fragment.text(); if (txt.count() == 1 && txt.at(0) == QChar::ObjectReplacementCharacter) { if (format.isImageFormat()) { QTextImageFormat imgFmt = format.toImageFormat(); html += QLatin1String("<img"); if (imgFmt.hasProperty(QTextFormat::ImageName)) emitAttribute("src", imgFmt.name()); if (imgFmt.hasProperty(QTextFormat::ImageWidth)) emitAttribute("width", QString::number(imgFmt.width())); if (imgFmt.hasProperty(QTextFormat::ImageHeight)) emitAttribute("height", QString::number(imgFmt.height())); if (QTextFrame *imageFrame = qobject_cast<QTextFrame *>(doc->objectForFormat(imgFmt))) emitFloatStyle(imageFrame->frameFormat().position()); html += QLatin1String(" />"); } } else { Q_ASSERT(!txt.contains(QChar::ObjectReplacementCharacter)); txt = Qt::escape(txt); // split for [\n{LineSeparator}] QString forcedLineBreakRegExp = QString::fromLatin1("[\\na]"); forcedLineBreakRegExp[3] = QChar::LineSeparator; const QStringList lines = txt.split(QRegExp(forcedLineBreakRegExp)); for (int i = 0; i < lines.count(); ++i) { if (i > 0) html += QLatin1String("<br />"); // space on purpose for compatibility with Netscape, Lynx & Co. html += lines.at(i); } } if (emittedFontTag) html += QLatin1String("</font>"); if (attributesEmitted) html += QLatin1String("</span>"); if (closeAnchor) html += QLatin1String("</a>");}static bool isOrderedList(int style){ return style == QTextListFormat::ListDecimal || style == QTextListFormat::ListLowerAlpha || style == QTextListFormat::ListUpperAlpha;}void QTextHtmlExporter::emitBlockAttributes(const QTextBlock &block){ QTextBlockFormat format = block.blockFormat(); emitAlignment(format.alignment()); Qt::LayoutDirection dir = format.layoutDirection(); if (dir == Qt::LeftToRight) { // assume default to not bloat the html too much // html += QLatin1String(" dir='ltr'"); } else { html += QLatin1String(" dir='rtl'"); } QLatin1String style(" style=\""); html += style; if (block.begin().atEnd()) { html += "-qt-paragraph-type:empty;"; } emitMargins(QString::number(format.topMargin()), QString::number(format.bottomMargin()), QString::number(format.leftMargin()), QString::number(format.rightMargin())); html += QLatin1String(" -qt-block-indent:"); html += QString::number(format.indent()); html += QLatin1Char(';'); html += QLatin1String(" text-indent:"); html += QString::number(format.indent()); html += QLatin1String("px;"); QTextCharFormat diff = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat(); if (!diff.properties().isEmpty()) emitCharFormatStyle(diff); html += QLatin1Char('"'); QBrush bg = format.background(); if (bg != Qt::NoBrush) emitAttribute("bgcolor", bg.color().name());}void QTextHtmlExporter::emitBlock(const QTextBlock &block){ if (block.begin().atEnd()) { // ### HACK, remove once QTextFrame::Iterator is fixed int p = block.position(); if (p > 0) --p; QTextDocumentPrivate::FragmentIterator frag = doc->docHandle()->find(p); QChar ch = doc->docHandle()->buffer().at(frag->stringPosition); if (ch == QTextBeginningOfFrame || ch == QTextEndOfFrame) return; } // save and later restore, in case we 'change' the default format by // emitting block char format information QTextCharFormat oldDefaultCharFormat = defaultCharFormat; QTextList *list = block.textList(); if (list) { if (list->itemNumber(block) == 0) { // first item? emit <ul> or appropriate const QTextListFormat format = list->format(); const int style = format.style(); switch (style) { case QTextListFormat::ListDecimal: html += QLatin1String("<ol"); break; case QTextListFormat::ListDisc: html += QLatin1String("<ul"); break; case QTextListFormat::ListCircle: html += QLatin1String("<ul type=circle"); break; case QTextListFormat::ListSquare: html += QLatin1String("<ul type=square"); break; case QTextListFormat::ListLowerAlpha: html += QLatin1String("<ol type=a"); break; case QTextListFormat::ListUpperAlpha: html += QLatin1String("<ol type=A"); break; default: html += QLatin1String("<ul"); // ### should not happen } if (format.hasProperty(QTextFormat::ListIndent)) { html += QLatin1String(" style=\"-qt-list-indent: "); html += QString::number(format.indent()); html += QLatin1String(";\""); } html += QLatin1Char('>'); } html += QLatin1String("<li"); const QTextCharFormat blockFmt = formatDifference(defaultCharFormat, block.charFormat()).toCharFormat(); if (!blockFmt.properties().isEmpty()) { html += QLatin1String(" style=\""); emitCharFormatStyle(blockFmt); html += QLatin1Char('\"'); defaultCharFormat.merge(block.charFormat()); } } const QTextBlockFormat blockFormat = block.blockFormat(); if (blockFormat.hasProperty(QTextFormat::BlockTrailingHorizontalRulerWidth)) { html += QLatin1String("<hr"); QTextLength width = blockFormat.lengthProperty(QTextFormat::BlockTrailingHorizontalRulerWidth); if (width.type() != QTextLength::VariableLength) emitTextLength("width", width); else html += QLatin1Char(' '); html += QLatin1String("/>"); return; } const bool pre = blockFormat.nonBreakableLines(); if (pre) { if (list) html += QLatin1Char('>'); html += QLatin1String("<pre"); } else if (!list) { html += QLatin1String("<p"); } emitBlockAttributes(block); html += QLatin1Char('>'); const QTextCharFormat blockCharFmt = block.charFormat(); const QTextCharFormat diff = formatDifference(defaultCharFormat, blockCharFmt).toCharFormat(); const bool emittedFontTag = emitLogicalFontSize(diff); defaultCharFormat.merge(blockCharFmt); QTextBlock::Iterator it = block.begin(); if (fragmentMarkers && !it.atEnd() && block == doc->begin()) html += QLatin1String("<!--StartFragment-->"); for (; !it.atEnd(); ++it) emitFragment(it.fragment()); if (fragmentMarkers && block.position() + block.length() == doc->docHandle()->length()) html += QLatin1String("<!--EndFragment-->"); if (emittedFontTag) html += QLatin1String("</font>"); if (pre) html += QLatin1String("</pre>"); else if (!list) html += QLatin1String("</p>"); if (list) { if (list->itemNumber(block) == list->count() - 1) { // last item? close list if (isOrderedList(list->format().style())) html += QLatin1String("</ol>"); else html += QLatin1String("</ul>"); } } defaultCharFormat = oldDefaultCharFormat;}void QTextHtmlExporter::emitTable(const QTextTable *table){ QTextTableFormat format = table->format(); html += QLatin1String("<table"); if (format.hasProperty(QTextFormat::FrameBorder)) emitAttribute("border", QString::number(format.border())); emitFloatStyle(format.position()); emitAlignment(format.alignment()); emitTextLength("width", format.width()); if (format.hasProperty(QTextFormat::TableCellSpacing)) emitAttribute("cellspacing", QString::number(format.cellSpacing())); if (format.hasProperty(QTextFormat::TableCellPadding)) emitAttribute("cellpadding", QString::number(format.cellPadding())); QBrush bg = format.background(); if (bg != Qt::NoBrush) emitAttribute("bgcolor", bg.color().name()); html += QLatin1Char('>'); const int rows = table->rows(); const int columns = table->columns(); QVector<QTextLength> columnWidths = format.columnWidthConstraints(); if (columnWidths.isEmpty()) { columnWidths.resize(columns); columnWidths.fill(QTextLength()); } Q_ASSERT(columnWidths.count() == columns); QVarLengthArray<bool> widthEmittedForColumn(columns); for (int i = 0; i < columns; ++i) widthEmittedForColumn[i] = false; for (int row = 0; row < rows; ++row) { html += QLatin1String("<tr>"); 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("<td"); if (!widthEmittedForColumn[col]) { emitTextLength("width", columnWidths.at(col)); widthEmittedForColumn[col] = true; } if (cell.columnSpan() > 1) emitAttribute("colspan", QString::number(cell.columnSpan())); if (cell.rowSpan() > 1) emitAttribute("rowspan", QString::number(cell.rowSpan())); const QTextCharFormat cellFormat = cell.format(); QBrush bg = cellFormat.background(); if (bg != Qt::NoBrush) emitAttribute("bgcolor", bg.color().name()); html += QLatin1Char('>'); emitFrame(cell.begin()); html += QLatin1String("</td>"); } html += QLatin1String("</tr>"); } html += QLatin1String("</table>");}void QTextHtmlExporter::emitFrame(QTextFrame::Iterator frameIt){ if (!frameIt.atEnd()) { QTextFrame::Iterator next = frameIt; ++next; if (next.atEnd() && frameIt.currentFrame() == 0 && 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<QTextTable *>(f)) { emitTable(table); } else { html += QLatin1String("<table"); QTextFrameFormat format = f->frameFormat(); if (format.hasProperty(QTextFormat::FrameBorder)) emitAttribute("border", QString::number(format.border())); html += QLatin1String(" style=\"-qt-table-type: frame;"); emitFloatStyle(format.position(), OmitStyleTag); if (format.hasProperty(QTextFormat::FrameMargin)) { const QString margin = QString::number(format.margin()); emitMargins(margin, margin, margin, margin); } html += QLatin1Char('\"'); emitTextLength("width", format.width()); emitTextLength("height", format.height()); QBrush bg = format.background(); if (bg != Qt::NoBrush) emitAttribute("bgcolor", bg.color().name()); html += QLatin1Char('>'); html += QLatin1String("<tr><td style=\"border: none;\">"); emitFrame(f->begin()); html += QLatin1String("</td></tr></table>"); } } else if (it.currentBlock().isValid()) { emitBlock(it.currentBlock()); } }}/*! Returns a string containing an HTML representation of the document. The \a encoding parameter specifies the value for the charset attribute in the html header. For example if 'utf-8' is specified then the beginning of the generated html will look like this: \code <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body>... \endcode If no encoding is specified then no such meta information is generated. If you later on convert the returned html string into a byte array for transmission over a network or when saving to disk you should specify the encoding you're going to use for the conversion to a byte array here. \sa {Supported HTML Subset}*/QString QTextDocument::toHtml(const QByteArray &encoding) const{ return QTextHtmlExporter(this).toHtml(encoding);}/*! Returns a vector of text formats for all the formats used in the document.*/QVector<QTextFormat> QTextDocument::allFormats() const{ Q_D(const QTextDocument); return d->formatCollection()->formats;}/*! \internal So that not all classes have to be friends of each other...*/QTextDocumentPrivate *QTextDocument::docHandle() const{ Q_D(const QTextDocument); return const_cast<QTextDocumentPrivate *>(d);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -