QString MercurialEditor::fileNameFromDiffSpecification(const QTextBlock &diffFileSpec) const { const QString filechangeId(QLatin1String("+++ b/")); QTextBlock::iterator iterator; for (iterator = diffFileSpec.begin(); !(iterator.atEnd()); iterator++) { QTextFragment fragment = iterator.fragment(); if(fragment.isValid()) { if (fragment.text().startsWith(filechangeId)) { const QString filename = fragment.text().remove(0, filechangeId.size()); return findDiffFile(filename, MercurialPlugin::instance()->versionControl()); } } } return QString(); }
void XmlWriter::readFragment(const QTextBlock ¤tBlock, QDomElement blockElement, QDomDocument *document) { //! [3] //! [4] QTextBlock::iterator it; for (it = currentBlock.begin(); !(it.atEnd()); ++it) { QTextFragment currentFragment = it.fragment(); if (currentFragment.isValid()) //! [3] //! [5] processFragment(currentFragment); //! [4] //! [5] if (currentFragment.isValid()) { QDomElement fragmentElement = document->createElement("fragment"); blockElement.appendChild(fragmentElement); fragmentElement.setAttribute("length", currentFragment.length()); QDomText fragmentText = document->createTextNode(currentFragment.text()); fragmentElement.appendChild(fragmentText); } //! [6] //! [7] } //! [7] //! [6] }
FormattedMessage FormattedMessage::parse(const QTextDocument *document) { FormattedMessage result; QString text; QTextBlock block = document->firstBlock(); bool firstParagraph = true; while (block.isValid()) { bool firstFragment = true; for (QTextBlock::iterator it = block.begin(); !it.atEnd(); ++it) { QTextFragment fragment = it.fragment(); if (!fragment.isValid()) continue; if (!firstParagraph && firstFragment) text = '\n' + fragment.text(); else text = fragment.text(); QTextCharFormat format = fragment.charFormat(); parseImages(result, text, format.font().bold(), format.font().italic(), format.font().underline(), format.foreground().color()); firstFragment = false; } if (firstFragment) parseImages(result, "\n", false, false, false, QColor()); block = block.next(); firstParagraph = false; } return result; }
/*! Replaces the entire contents of the document with the given HTML-formatted text in the \a text string */ void RichString::setHtml(const QString &text) { QTextDocument doc; doc.setHtml(text); QTextBlock block = doc.firstBlock(); QTextBlock::iterator it; for (it = block.begin(); !(it.atEnd()); ++it) { QTextFragment textFragment = it.fragment(); if (textFragment.isValid()) { Format fmt; fmt.setFont(textFragment.charFormat().font()); fmt.setFontColor(textFragment.charFormat().foreground().color()); addFragment(textFragment.text(), fmt); } } }
void XmlWriter::processBlock(QDomElement &parent, const QTextBlock &block) { QDomElement blockElement = document->createElement("block"); blockElement.setAttribute("position", block.position()); blockElement.setAttribute("length", block.length()); parent.appendChild(blockElement); QTextBlock::iterator it; for (it = block.begin(); !(it.atEnd()); ++it) { QTextFragment fragment = it.fragment(); if (fragment.isValid()) { QDomElement fragmentElement = document->createElement("fragment"); blockElement.appendChild(fragmentElement); fragmentElement.setAttribute("length", fragment.length()); QDomText fragmentText = document->createTextNode(fragment.text()); fragmentElement.appendChild(fragmentText); } } }
QString RichTextLineEdit::toSimpleHtml() const { QString html; for (QTextBlock block = document()->begin(); block.isValid(); block = block.next()) { for (QTextBlock::iterator i = block.begin(); !i.atEnd(); ++i) { QTextFragment fragment = i.fragment(); if (fragment.isValid()) { QTextCharFormat format = fragment.charFormat(); QColor color = format.foreground().color(); //QString text = Qt::escape(fragment.text()); //deleted for Qt5 QString text = QString(fragment.text()).toHtmlEscaped(); //added for Qt5 QStringList tags; if (format.verticalAlignment() == QTextCharFormat::AlignSubScript) tags << "sub"; else if (format.verticalAlignment() == QTextCharFormat::AlignSuperScript) tags << "sup"; if (format.fontItalic()) tags << "i"; if (format.fontWeight() > QFont::Normal) tags << "b"; if (format.fontStrikeOut()) tags << "s"; while (!tags.isEmpty()) text = QString("<%1>%2</%1>") .arg(tags.takeFirst()).arg(text); if (color != QColor(Qt::black)) text = QString("<font color=\"%1\">%2</font>") .arg(color.name()).arg(text); html += text; } } } return html; }
QString TextDocumentSerializer::processFragment(QTextFragment fragment) { QTextCharFormat format = fragment.charFormat(); QString text = fragment.text(); if(format.isImageFormat()) text = getImageTag(format.toImageFormat()); if(format.fontFamily().contains("Courier")) text = QString("<code>%1</code>").arg(text); if(format.fontWeight() == QFont::Bold) text = QString("<b>%1</b>").arg(text); if(format.fontItalic()) text = QString("<i>%1</i>").arg(text); text = text.replace(QChar(0x2028), "<br>"); return text; }
QString Dialog::toStringFromDocument() { QTextDocument *doc = message()->document(); QString txt; for (QTextBlock bl = doc->begin(); bl != doc->end(); bl = bl.next()) if (bl.isValid()) { for (QTextBlock::iterator it = bl.begin(); !it.atEnd(); ++it) { QTextFragment fragm = it.fragment(); if (fragm.isValid() && fragm.charFormat().isImageFormat()) { QString imgName = fragm.charFormat().toImageFormat().name(); txt += imgName; } else if (fragm.isValid()) txt += fragm.text(); } if (bl != doc->begin()) txt += "\n"; } int i = (int)txt.size() - 1; while (i >= 0 && (txt[i] == ' ' || txt[i] == '\n')) --i; txt.remove(i + 1, txt.size() - i - 1); return txt; }
void QSGTextNode::addTextBlock(const QPointF &position, QTextDocument *textDocument, const QTextBlock &block, const QColor &overrideColor, QSGText::TextStyle style, const QColor &styleColor) { if (!block.isValid()) return; QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft(); QTextBlock::iterator it = block.begin(); while (!it.atEnd()) { QTextFragment fragment = it.fragment(); if (!fragment.text().isEmpty()) { QTextCharFormat charFormat = fragment.charFormat(); QColor color = overrideColor.isValid() ? overrideColor : charFormat.foreground().color(); QList<QGlyphRun> glyphsList = fragment.glyphRuns(); for (int i=0; i<glyphsList.size(); ++i) { QGlyphRun glyphs = glyphsList.at(i); QRawFont font = glyphs.rawFont(); QSGGlyphNode *glyphNode = addGlyphs(position + blockPosition + QPointF(0, font.ascent()), glyphs, color, style, styleColor); int decorations = (glyphs.overline() ? Overline : 0) | (glyphs.strikeOut() ? StrikeOut : 0) | (glyphs.underline() ? Underline : 0); if (decorations) { QPointF baseLine = glyphNode->baseLine(); qreal width = glyphNode->boundingRect().width(); addTextDecorations(Decoration(decorations), baseLine, color, width, font.lineThickness(), font.underlinePosition(), font.ascent()); } } } ++it; } }
void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QTextBlock &block, const QPointF &position, const QColor &textColor, const QColor &anchorColor, int selectionStart, int selectionEnd) { Q_ASSERT(textDocument); #ifndef QT_NO_IM int preeditLength = block.isValid() ? block.layout()->preeditAreaText().length() : 0; int preeditPosition = block.isValid() ? block.layout()->preeditAreaPosition() : -1; #endif QVarLengthArray<QTextLayout::FormatRange> colorChanges; mergeFormats(block.layout(), &colorChanges); QPointF blockPosition = textDocument->documentLayout()->blockBoundingRect(block).topLeft() + position; if (QTextList *textList = block.textList()) { QPointF pos = blockPosition; QTextLayout *layout = block.layout(); if (layout->lineCount() > 0) { QTextLine firstLine = layout->lineAt(0); Q_ASSERT(firstLine.isValid()); setCurrentLine(firstLine); QRectF textRect = firstLine.naturalTextRect(); pos += textRect.topLeft(); if (block.textDirection() == Qt::RightToLeft) pos.rx() += textRect.width(); const QTextCharFormat charFormat = block.charFormat(); QFont font(charFormat.font()); QFontMetricsF fontMetrics(font); QTextListFormat listFormat = textList->format(); QString listItemBullet; switch (listFormat.style()) { case QTextListFormat::ListCircle: listItemBullet = QChar(0x25E6); // White bullet break; case QTextListFormat::ListSquare: listItemBullet = QChar(0x25AA); // Black small square break; case QTextListFormat::ListDecimal: case QTextListFormat::ListLowerAlpha: case QTextListFormat::ListUpperAlpha: case QTextListFormat::ListLowerRoman: case QTextListFormat::ListUpperRoman: listItemBullet = textList->itemText(block); break; default: listItemBullet = QChar(0x2022); // Black bullet break; }; QSizeF size(fontMetrics.width(listItemBullet), fontMetrics.height()); qreal xoff = fontMetrics.width(QLatin1Char(' ')); if (block.textDirection() == Qt::LeftToRight) xoff = -xoff - size.width(); setPosition(pos + QPointF(xoff, 0)); QTextLayout layout; layout.setFont(font); layout.setText(listItemBullet); // Bullet layout.beginLayout(); QTextLine line = layout.createLine(); line.setPosition(QPointF(0, 0)); layout.endLayout(); QList<QGlyphRun> glyphRuns = layout.glyphRuns(); for (int i=0; i<glyphRuns.size(); ++i) addUnselectedGlyphs(glyphRuns.at(i)); } } int textPos = block.position(); QTextBlock::iterator blockIterator = block.begin(); while (!blockIterator.atEnd()) { QTextFragment fragment = blockIterator.fragment(); QString text = fragment.text(); if (text.isEmpty()) continue; QTextCharFormat charFormat = fragment.charFormat(); QFont font(charFormat.font()); QFontMetricsF fontMetrics(font); int fontHeight = fontMetrics.descent() + fontMetrics.ascent(); int valign = charFormat.verticalAlignment(); if (valign == QTextCharFormat::AlignSuperScript) setPosition(QPointF(blockPosition.x(), blockPosition.y() - fontHeight / 2)); else if (valign == QTextCharFormat::AlignSubScript) setPosition(QPointF(blockPosition.x(), blockPosition.y() + fontHeight / 6)); else setPosition(blockPosition); if (text.contains(QChar::ObjectReplacementCharacter)) { QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat)); if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) { int blockRelativePosition = textPos - block.position(); QTextLine line = block.layout()->lineForTextPosition(blockRelativePosition); if (!currentLine().isValid() || line.lineNumber() != currentLine().lineNumber()) { setCurrentLine(line); } QQuickTextNodeEngine::SelectionState selectionState = (selectionStart < textPos + text.length() && selectionEnd >= textPos) ? QQuickTextNodeEngine::Selected : QQuickTextNodeEngine::Unselected; addTextObject(QPointF(), charFormat, selectionState, textDocument, textPos); } textPos += text.length(); } else { if (charFormat.foreground().style() != Qt::NoBrush) setTextColor(charFormat.foreground().color()); else if (charFormat.isAnchor()) setTextColor(anchorColor); else setTextColor(textColor); int fragmentEnd = textPos + fragment.length(); #ifndef QT_NO_IM if (preeditPosition >= 0 && (preeditPosition + block.position()) >= textPos && (preeditPosition + block.position()) <= fragmentEnd) { fragmentEnd += preeditLength; } #endif if (charFormat.background().style() != Qt::NoBrush) { QTextLayout::FormatRange additionalFormat; additionalFormat.start = textPos - block.position(); additionalFormat.length = fragmentEnd - textPos; additionalFormat.format = charFormat; colorChanges << additionalFormat; } textPos = addText(block, charFormat, textColor, colorChanges, textPos, fragmentEnd, selectionStart, selectionEnd); } ++blockIterator; } #ifndef QT_NO_IM if (preeditLength >= 0 && textPos <= block.position() + preeditPosition) { setPosition(blockPosition); textPos = block.position() + preeditPosition; QTextLine line = block.layout()->lineForTextPosition(preeditPosition); if (!currentLine().isValid() || line.lineNumber() != currentLine().lineNumber()) { setCurrentLine(line); } textPos = addText(block, block.charFormat(), textColor, colorChanges, textPos, textPos + preeditLength, selectionStart, selectionEnd); } #endif setCurrentLine(QTextLine()); // Reset current line because the text layout changed m_hasContents = true; }
QString TextEditEx::getPlainText(int _from, int _to) const { if (_from == _to) return ""; if (_to != -1 && _to < _from) { assert(!"invalid data"); return ""; } QString out_string; QTextStream result(&out_string); int pos_start = 0; int length = 0; bool first = true; for (QTextBlock it_block = document()->begin(); it_block != document()->end(); it_block = it_block.next()) { if (!first) result << '\n'; pos_start = it_block.position(); if (_to != -1 && pos_start >= _to) break; for (QTextBlock::iterator it_fragment = it_block.begin(); it_fragment != it_block.end(); ++it_fragment) { QTextFragment currentFragment = it_fragment.fragment(); if (currentFragment.isValid()) { pos_start = currentFragment.position(); length = currentFragment.length(); if (pos_start + length <= _from) continue; if (_to != -1 && pos_start >= _to) break; first = false; if (currentFragment.charFormat().isImageFormat()) { if (pos_start < _from) continue; QTextImageFormat imgFmt = currentFragment.charFormat().toImageFormat(); auto iter = resource_index_.find(imgFmt.name()); if (iter != resource_index_.end()) result << iter->second; } else { QString fragment_text = currentFragment.text(); int c_start = std::max((_from - pos_start), 0); int count = -1; if (_to != -1 && _to <= pos_start + length) count = _to - pos_start - c_start; QString txt = fragment_text.mid(c_start, count); txt.remove(QChar::SoftHyphen); QChar *uc = txt.data(); QChar *e = uc + txt.size(); for (; uc != e; ++uc) { switch (uc->unicode()) { case 0xfdd0: // QTextBeginningOfFrame case 0xfdd1: // QTextEndOfFrame case QChar::ParagraphSeparator: case QChar::LineSeparator: *uc = QLatin1Char('\n'); break; case QChar::Nbsp: *uc = QLatin1Char(' '); break; default: ; } } result << txt; } } } } return out_string; }
void Dialog::appendToHistory(const QString& name, const QDateTime& sendTime, QTextDocument *document, InsertingMode mode) { QListWidgetItem *item = new QListWidgetItem(); QTextEdit *te = new QTextEdit(); lwHistory->addItem(item); te->setReadOnly(true); reloadResource(te); lwHistory->setItemWidget(item, te); QString color; if (name == "You") color = "blue"; else color = "red"; te->append(QString("<font color = \"%1\"> <b>" + name + "</b> (" + sendTime.toString("dd-MM-yyyy hh:mm:ss") + "):</font>").arg(color)); te->moveCursor(QTextCursor::End); te->textCursor().insertBlock(); te->textCursor().insertFragment(QTextDocumentFragment(document)); int heig = 17, widthTe = parentWidget()->width(); int curLine = 0; int mx = 0; for (QTextBlock bl = te->document()->begin(); bl != te->document()->end(); bl = bl.next()) if (bl.isValid()) { if (bl.begin().atEnd()) { heig += 17 + mx;//&&& curLine = mx = 0; continue; } for (QTextBlock::iterator it = bl.begin(); !it.atEnd(); ++it) { QTextFragment fragm = it.fragment(); int curw, curh; if (fragm.isValid() && fragm.charFormat().isImageFormat()) { curw = smiles->width() / W_CNT; curh = smiles->height() / H_CNT; processCalc(heig, mx, curLine, curw, curh); } else if (fragm.isValid()) { QString s = fragm.text(); QFontMetrics me(fragm.charFormat().font()); curh = me.lineSpacing(); for (int j = 0; j < s.size(); ++j) { curw = me.width(s[j]); processCalc(heig, mx, curLine, curw, curh); } } } heig += mx; mx = curLine = 0; } te->setStyleSheet(QString("QFrame {" "border: 2px solid #f3f2f1;" "border-radius: 4px;" "padding: 2px;}")); item->setSizeHint(QSize(0, heig + 18)); te->resize(QSize(widthTe, heig)); lwHistory->scrollToBottom(); if (mode == ReceivedMessage && !dgReadByUser) { setUnreadMessage(unreadMessage + 1); queUnreadWrote.push_back(te); te->setStyleSheet("QTextEdit { background-color: #FFFCCC; }"); } else if (mode == LoadHistory) { if (unreadMessage != 0) { queUnreadWrote.push_back(te); te->setStyleSheet("QTextEdit { background-color: #FFFCCC; }"); if (queUnreadWrote.size() > unreadMessage) { queUnreadWrote.front()->setStyleSheet("QTextEdit { background-color: #FFFFFF; }"); queUnreadWrote.pop_front(); } } if (wroteMessage != 0) { queUnreadWrote.push_back(te); te->setStyleSheet("QTextEdit { background-color: #DFFFCC; }"); if (queUnreadWrote.size() > wroteMessage) { queUnreadWrote.front()->setStyleSheet("QTextEdit { background-color: #FFFFFF; }"); queUnreadWrote.pop_front(); } } } else if (mode == SendMessage) { teMessage->setFocus(); te->setStyleSheet("QTextEdit { background-color: #DFFFCC; }"); wroteMessage++; queUnreadWrote.push_back(te); } }
//绘制stub面板上的显示效果 只显示恶性数据竞争的那一行 void DrcDockWidget::stubDrawText() { QTextDocument *document = ui->resultStubEdit->document(); QTextBlock currentBlock = document->begin(); QTextBlock::iterator it; QTextCursor cursor = ui->resultStubEdit->textCursor(); //此处需要注意的是临时变量的生命周期!!! QString tempStr; int tempPos; while( true) { // 在修改chatformat时会改变当前Block的fragment // 所以++it的处理类似std::map中的erase操作 for (it = currentBlock.begin(); !(it.atEnd()); ) { QTextFragment currentFragment = it.fragment(); if (currentFragment.isValid()) { ++it; int pos = currentFragment.position(); QString strText = currentFragment.text(); QTextCharFormat fmt; QFont font; font.setBold(true); fmt.setFont(font); fmt.setForeground(QBrush(QColor(255, 0, 0))); QTextCursor helper = cursor; char str = strText.at(0).toLatin1(); if(str == 'A') { QString strPart2 = strText.split(':').at(1); if(strPart2.toInt() == 1) { helper.setPosition(tempPos); helper.setPosition(tempPos + tempStr.length(), QTextCursor::KeepAnchor); helper.setCharFormat(fmt); helper.setPosition(pos); helper.setPosition(pos + strText.length(), QTextCursor::KeepAnchor); helper.setCharFormat(fmt); } } else { tempStr = strText; tempPos = pos; } } } currentBlock = currentBlock.next(); if(!currentBlock.isValid()) break; } // 光标移动到最后, 并设置拥有焦点 QTextCursor c = ui->resultStubEdit->textCursor(); c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); ui->resultStubEdit->setTextCursor(c); ui->resultStubEdit->setFocus(Qt::MouseFocusReason); }
void KoTextWriter::saveParagraph(const QTextBlock &block, int from, int to) { QString changeName = QString(); QTextBlockFormat blockFormat = block.blockFormat(); int outlineLevel = blockFormat.intProperty(KoParagraphStyle::OutlineLevel); if (outlineLevel > 0) { d->writer->startElement("text:h", false); d->writer->addAttribute("text:outline-level", outlineLevel); } else d->writer->startElement("text:p", false); QString styleName = saveParagraphStyle(block); if (!styleName.isEmpty()) d->writer->addAttribute("text:style-name", styleName); // Write the fragments and their formats QTextCursor cursor(block); QTextCharFormat blockCharFormat = cursor.blockCharFormat(); QTextCharFormat previousCharFormat; QTextBlock::iterator it; for (it = block.begin(); !(it.atEnd()); ++it) { QTextFragment currentFragment = it.fragment(); const int fragmentStart = currentFragment.position(); const int fragmentEnd = fragmentStart + currentFragment.length(); if (to != -1 && fragmentStart >= to) break; if (currentFragment.isValid()) { QTextCharFormat charFormat = currentFragment.charFormat(); QTextCharFormat compFormat = charFormat; bool identical; previousCharFormat.clearProperty(KoCharacterStyle::ChangeTrackerId); compFormat.clearProperty(KoCharacterStyle::ChangeTrackerId); if (previousCharFormat == compFormat) identical = true; else identical = false; if ( d->changeTracker && d->changeTracker->containsInlineChanges(charFormat) && d->changeTracker->elementById(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt())->isEnabled()) { KoGenChange change; d->changeTracker->saveInlineChange(charFormat.property(KoCharacterStyle::ChangeTrackerId).toInt(), change); changeName = d->sharedData->genChanges().insert(change); d->writer->startElement("text:change-start", false); d->writer->addAttribute("text:change-id", changeName); d->writer->endElement(); } KoInlineObject *inlineObject = d->layout->inlineTextObjectManager()->inlineTextObject(charFormat); if (currentFragment.length() == 1 && inlineObject && currentFragment.text()[0].unicode() == QChar::ObjectReplacementCharacter) { inlineObject->saveOdf(d->context); } else { QString styleName = saveCharacterStyle(charFormat, blockCharFormat); if (charFormat.isAnchor()) { d->writer->startElement("text:a", false); d->writer->addAttribute("xlink:type", "simple"); d->writer->addAttribute("xlink:href", charFormat.anchorHref()); } else if (!styleName.isEmpty() /*&& !identical*/) { d->writer->startElement("text:span", false); d->writer->addAttribute("text:style-name", styleName); } QString text = currentFragment.text(); int spanFrom = fragmentStart >= from ? 0 : from; int spanTo = to == -1 ? fragmentEnd : (fragmentEnd > to ? to : fragmentEnd); if (spanFrom != fragmentStart || spanTo != fragmentEnd) { // avoid mid, if possible d->writer->addTextSpan(text.mid(spanFrom - fragmentStart, spanTo - spanFrom)); } else { d->writer->addTextSpan(text); } if ((!styleName.isEmpty() /*&& !identical*/) || charFormat.isAnchor()) d->writer->endElement(); } // if (inlineObject) if (!changeName.isEmpty()) { d->writer->startElement("text:change-end", false); d->writer->addAttribute("text:change-id",changeName); d->writer->endElement(); changeName=QString(); } previousCharFormat = charFormat; } // if (fragment.valid()) } // foeach(fragment) d->writer->endElement(); }
bool RTF::Writer::write(QIODevice* device, QTextDocument* text) { if (m_codec == 0) { return false; } device->write(m_header); for (QTextBlock block = text->begin(); block.isValid(); block = block.next()) { QByteArray par("{\\pard\\plain"); QTextBlockFormat block_format = block.blockFormat(); bool rtl = block_format.layoutDirection() == Qt::RightToLeft; if (rtl) { par += "\\rtlpar"; } Qt::Alignment align = block_format.alignment(); if (rtl && (align & Qt::AlignLeft)) { par += "\\ql"; } else if (align & Qt::AlignRight) { par += "\\qr"; } else if (align & Qt::AlignCenter) { par += "\\qc"; } else if (align & Qt::AlignJustify) { par += "\\qj"; } if (block_format.indent() > 0) { par += "\\li" + QByteArray::number(block_format.indent() * 15); } device->write(par); if (block.begin() != block.end()) { device->write(" "); for (QTextBlock::iterator iter = block.begin(); iter != block.end(); ++iter) { QTextFragment fragment = iter.fragment(); QTextCharFormat char_format = fragment.charFormat(); QByteArray style; if (char_format.fontWeight() == QFont::Bold) { style += "\\b"; } if (char_format.fontItalic()) { style += "\\i"; } if (char_format.fontUnderline()) { style += "\\ul"; } if (char_format.fontStrikeOut()) { style += "\\strike"; } if (char_format.verticalAlignment() == QTextCharFormat::AlignSuperScript) { style += "\\super"; } else if (char_format.verticalAlignment() == QTextCharFormat::AlignSubScript) { style += "\\sub"; } if (!style.isEmpty()) { device->write("{" + style + " " + fromUnicode(fragment.text()) + "}"); } else { device->write(fromUnicode(fragment.text())); } } } device->write("\\par}\n"); } device->write("\n}"); return true; }
void OdtWriter::writeBody(const QTextDocument* document) { m_xml.writeStartElement(QString::fromLatin1("office:body")); m_xml.writeStartElement(QString::fromLatin1("office:text")); for (QTextBlock block = document->begin(); block.isValid(); block = block.next()) { int heading = block.blockFormat().property(QTextFormat::UserProperty).toInt(); if (!heading) { m_xml.writeStartElement(QString::fromLatin1("text:p")); } else { m_xml.writeStartElement(QString::fromLatin1("text:h")); m_xml.writeAttribute(QString::fromLatin1("text:outline-level"), QString::number(heading)); } m_xml.writeAttribute(QString::fromLatin1("text:style-name"), m_styles.value(block.blockFormatIndex())); m_xml.setAutoFormatting(false); for (QTextBlock::iterator iter = block.begin(); !(iter.atEnd()); ++iter) { QTextFragment fragment = iter.fragment(); QString style = m_styles.value(fragment.charFormatIndex()); if (!style.isEmpty()) { m_xml.writeStartElement(QString::fromLatin1("text:span")); m_xml.writeAttribute(QString::fromLatin1("text:style-name"), style); } QString text = fragment.text(); int start = 0; int spaces = -1; for (int i = 0; i < text.length(); ++i) { QChar c = text.at(i); if (c.unicode() == 0x0009) { m_xml.writeCharacters(text.mid(start, i - start)); m_xml.writeEmptyElement(QString::fromLatin1("text:tab")); start = i + 1; } else if (c.unicode() == 0x2028) { m_xml.writeCharacters(text.mid(start, i - start)); m_xml.writeEmptyElement(QString::fromLatin1("text:line-break")); start = i + 1; } else if (c.unicode() == 0x0020) { ++spaces; } else if (spaces > 0) { m_xml.writeCharacters(text.mid(start, i - spaces - start)); m_xml.writeEmptyElement(QString::fromLatin1("text:s")); m_xml.writeAttribute(QString::fromLatin1("text:c"), QString::number(spaces)); spaces = -1; start = i; } else { spaces = -1; } } if (spaces > 0) { m_xml.writeCharacters(text.mid(start, text.length() - spaces - start)); m_xml.writeEmptyElement(QString::fromLatin1("text:s")); m_xml.writeAttribute(QString::fromLatin1("text:c"), QString::number(spaces)); } else { m_xml.writeCharacters(text.mid(start)); } if (!style.isEmpty()) { m_xml.writeEndElement(); } } m_xml.writeEndElement(); m_xml.setAutoFormatting(true); } m_xml.writeEndElement(); m_xml.writeEndElement(); }
void TextContent::updateTextConstraints() { // 1. actual content stretch double prevXScale = 1.0; double prevYScale = 1.0; /* if (m_textRect.width() > 0 && m_textRect.height() > 0) { QRect cRect = contentRect(); prevXScale = (qreal)cRect.width() / (qreal)m_textRect.width(); prevYScale = (qreal)cRect.height() / (qreal)m_textRect.height(); }*/ // 2. LAYOUT TEXT. find out Block rects and Document rect int minCharSide = 0; m_blockRects.clear(); m_textRect = QRect(0, 0, 0, 0); for (QTextBlock tb = m_text->begin(); tb.isValid(); tb = tb.next()) { if (!tb.isVisible()) continue; // 2.1.A. calc the Block size uniting Fragments bounding rects QRect blockRect(0, 0, 0, 0); for (QTextBlock::iterator tbIt = tb.begin(); !(tbIt.atEnd()); ++tbIt) { QTextFragment frag = tbIt.fragment(); if (!frag.isValid()) continue; QString text = frag.text(); if (text.trimmed().isEmpty()) continue; QFontMetrics metrics(frag.charFormat().font()); if (!minCharSide || metrics.height() > minCharSide) minCharSide = metrics.height(); // TODO: implement superscript / subscript (it's in charFormat's alignment) // it must be implemented in paint too QRect textRect = metrics.boundingRect(text); if (textRect.left() > 9999) continue; if (textRect.top() < blockRect.top()) blockRect.setTop(textRect.top()); if (textRect.bottom() > blockRect.bottom()) blockRect.setBottom(textRect.bottom()); int textWidth = metrics.width(text); blockRect.setWidth(blockRect.width() + textWidth); } // 2.1.B. calc the Block size of blank lines if (tb.begin() == tb.end()) { QFontMetrics metrics(tb.charFormat().font()); int textHeight = metrics.height(); blockRect.setWidth(1); blockRect.setHeight(textHeight); } // 2.2. add the Block's margins QTextBlockFormat tbFormat = tb.blockFormat(); blockRect.adjust(-tbFormat.leftMargin(), -tbFormat.topMargin(), tbFormat.rightMargin(), tbFormat.bottomMargin()); // 2.3. store the original block rect m_blockRects.append(blockRect); // 2.4. enlarge the Document rect (uniting the Block rect) blockRect.translate(0, m_textRect.bottom() - blockRect.top() + 1); if (blockRect.left() < m_textRect.left()) m_textRect.setLeft(blockRect.left()); if (blockRect.right() > m_textRect.right()) m_textRect.setRight(blockRect.right()); if (blockRect.top() < m_textRect.top()) m_textRect.setTop(blockRect.top()); if (blockRect.bottom() > m_textRect.bottom()) m_textRect.setBottom(blockRect.bottom()); } m_textRect.adjust(-m_textMargin, -m_textMargin, m_textMargin, m_textMargin); // 3. use shape-based rendering if (hasShape()) { #if 1 // more precise, but too close to the path m_shapeRect = m_shapePath.boundingRect().toRect(); #else // faster, but less precise (as it uses the controls points to determine // the path rect, instead of the path itself) m_shapeRect = m_shapePath.controlPointRect().toRect(); #endif minCharSide = qBound(10, minCharSide, 500); m_shapeRect.adjust(-minCharSide, -minCharSide, minCharSide, minCharSide); // FIXME: layout, save layouting and calc the exact size! //int w = m_shapeRect.width(); //int h = m_shapeRect.height(); //resizeContents(QRect(-w / 2, -h / 2, w, h)); resizeContents(m_shapeRect); // moveBy(m_shapeRect.left(), m_shapeRect.top()); // m_shapePath.translate(-m_shapeRect.left(), -m_shapeRect.top()); //setPos(m_shapeRect.center()); return; } // 4. resize content keeping stretch int w = (int)(prevXScale * (qreal)m_textRect.width()); int h = (int)(prevYScale * (qreal)m_textRect.height()); resizeContents(QRect(-w / 2, -h / 2, w, h)); }
void TextContent::drawContent(QPainter * painter, const QRect & targetRect, Qt::AspectRatioMode ratio) { Q_UNUSED(ratio) // check whether we're drawing shaped const bool shapedPaint = hasShape() && !m_shapeRect.isEmpty(); QPointF shapeOffset = m_shapeRect.topLeft(); // scale painter for adapting the Text Rect to the Contents Rect QRect sourceRect = shapedPaint ? m_shapeRect : m_textRect; painter->save(); painter->translate(targetRect.topLeft()); if (sourceRect.width() > 0 && sourceRect.height() > 0) { qreal xScale = (qreal)targetRect.width() / (qreal)sourceRect.width(); qreal yScale = (qreal)targetRect.height() / (qreal)sourceRect.height(); if (!qFuzzyCompare(xScale, (qreal)1.0) || !qFuzzyCompare(yScale, (qreal)1.0)) painter->scale(xScale, yScale); } // shape //const bool drawHovering = RenderOpts::HQRendering ? false : isSelected(); if (shapedPaint) painter->translate(-shapeOffset); //if (shapedPaint && drawHovering) // painter->strokePath(m_shapePath, QPen(Qt::red, 0)); // TEMP - for PDF exporting - standard rich text document drawing if (RenderOpts::PDFExporting) { if (shapedPaint) QMessageBox::information(0, tr("PDF Export Warning"), tr("Shaped text could not be exported in PDF"), QMessageBox::Ok); QAbstractTextDocumentLayout::PaintContext pCtx; m_text->documentLayout()->draw(painter, pCtx); } else { // manual drawing QPointF blockPos = shapedPaint ? QPointF(0, 0) : -m_textRect.topLeft(); // 1. for each Text Block int blockRectIdx = 0; for (QTextBlock tb = m_text->begin(); tb.isValid(); tb = tb.next()) { if (!tb.isVisible() || blockRectIdx > m_blockRects.size()) continue; // 1.1. compute text insertion position const QRect & blockRect = m_blockRects[blockRectIdx++]; QPointF iPos = shapedPaint ? blockPos : blockPos - blockRect.topLeft(); blockPos += QPointF(0, blockRect.height()); qreal curLen = 8; // 1.2. iterate over text fragments for (QTextBlock::iterator tbIt = tb.begin(); !(tbIt.atEnd()); ++tbIt) { QTextFragment frag = tbIt.fragment(); if (!frag.isValid()) continue; // 1.2.1. setup painter and metrics for text fragment QTextCharFormat format = frag.charFormat(); QFont font = format.font(); painter->setFont(font); painter->setPen(format.foreground().color()); painter->setBrush(Qt::NoBrush); QFontMetrics metrics(font); // 1.2.2. draw each character QString text = frag.text(); foreach (const QChar & textChar, text) { const qreal charWidth = metrics.width(textChar); if (shapedPaint) { // find point on shape and angle qreal t = m_shapePath.percentAtLength(curLen); QPointF pt = m_shapePath.pointAtPercent(t); qreal angle = -m_shapePath.angleAtPercent(t); if (m_shakeRadius > 0) pt += QPointF(1 + (qrand() % m_shakeRadius) - m_shakeRadius/2, 1 + (qrand() % (2*m_shakeRadius)) - m_shakeRadius); // draw rotated letter painter->save(); painter->translate(pt); painter->rotate(angle); painter->drawText(iPos, textChar); painter->restore(); curLen += charWidth; } else { painter->drawText(iPos, textChar); iPos += QPointF(charWidth, 0); } } } } } painter->restore(); }
QString ChatView::getCardNameUnderMouse(QTextFragment frag) const { if (frag.charFormat().foreground().color() == Qt::blue) return frag.text(); return QString(); }
QString Format::frameToString( QTextFrame *frame ) { QString out; QTextFrame::iterator it; for( it = frame->begin(); it != frame->end(); ++it ) { QTextBlock block = it.currentBlock(); if ( block.isValid() ) { out += "<block"; QTextCursor c( block ); QDateTime dt = TextFormats::lastModified( c ); if ( dt.isValid() ) { out += " lastmodified=\"" + dt.toString( Qt::ISODate ) + "\""; } if ( TextFormats::isTitle( c ) ) { out += " titlestyle=\"title\""; } else if ( TextFormats::isSubTitle( c ) ) { out += " titlestyle=\"subtitle\""; } QTextBlockFormat blockFormat = block.blockFormat(); if ( blockFormat.isValid() ) { QTextList *list = block.textList(); if ( list ) { QTextListFormat f = list->format(); out += " liststyle=\""; switch( f.style() ) { default: case QTextListFormat::ListDisc: out += "disc"; break; case QTextListFormat::ListDecimal: out += "decimal"; break; } out += "\""; out += " listindent=\"" + QString::number( f.indent() ) + "\""; } else { if ( blockFormat.indent() != 0 ) { out += " blockindent=\"" + QString::number( blockFormat.indent() ) + "\""; } } } out += ">\n"; QTextBlock::iterator it2; for( it2 = block.begin(); it2 != block.end(); ++it2 ) { QTextFragment fragment = it2.fragment(); if ( !fragment.isValid() ) continue; QString text = fragment.text(); QString outText; for( int i = 0; i < text.size(); ++i ) { if ( text.at( i ) == 0xfffc ) { outText += "<todo status=\""; QTextImageFormat imageFormat = fragment.charFormat().toImageFormat(); if ( imageFormat.isValid() ) { if ( imageFormat.name().contains( "done" ) ) outText += "done"; else outText += "todo"; } else { dbg() << "NO IMAGE FORMAT" << endl; } outText += "\"/>"; } else { outText += escape( QString( text.at( i ) ) ); } } out += " <fragment"; QTextCharFormat format = fragment.charFormat(); if ( !format.anchorHref().isEmpty() ) { out += " link=\"" + escape( format.anchorHref() ) + "\""; } if ( format.fontWeight() == QFont::Bold ) { out += " bold=\"true\""; } if ( format.fontItalic() ) { out += " italic=\"true\""; } if ( format.hasProperty( QTextFormat::FontPointSize ) && format.fontPointSize() != 10 ) { out += " fontsize=\"" + QString::number( format.fontPointSize() ) + "\""; } if ( outText.trimmed().isEmpty() ) outText.replace( " ", "[FIXME:space]" ); out += ">" + outText + "</fragment>\n"; } out += "</block>"; out += "\n"; } QTextFrame *f = it.currentFrame(); if ( f ) { QTextFrameFormat format = f->frameFormat(); out += "<frame"; if ( format.hasProperty( TextFormats::FrameType ) ) { out += " type="; if ( format.property( TextFormats::FrameType ) == TextFormats::CodeFrame ) { out += "\"code\""; } else { out += "\"undefined\""; } } out += ">\n"; out += frameToString( f ); out += "</frame>\n"; } } return out; }
QString Tools::textDocumentToMinimalHTML(QTextDocument* document) { QString result = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; margin: 0px; }\n" "</style></head><body>\n"; QFont defaultFont; for (QTextBlock blockIt = document->begin(); blockIt != document->end(); blockIt = blockIt.next()) { result += HTM::PAR; for (QTextBlock::iterator subIt = blockIt.begin(); !(subIt.atEnd()); ++subIt) { QTextFragment currentFragment = subIt.fragment(); if (currentFragment.isValid()) { QTextCharFormat charFmt = currentFragment.charFormat(); const QColor& textColor = charFmt.foreground().color(); bool isTextBlack = (textColor == QColor() || textColor == QColor(Qt::black)); if (charFmt.font() == defaultFont && isTextBlack) { result += Qt::escape(currentFragment.text()); continue; } //If we use charFmt.fontWeight, setting a tag overrides it and all characters become non-bold. //So we use <b> </b> instead bool bold = (charFmt.fontWeight() >= QFont::Bold); if (bold) result += "<b>"; //Compose style string (font and color) result += "<span style=\""; if (charFmt.fontFamily() != defaultFont.family() && !charFmt.fontFamily().isEmpty()) result += QString(HTM::FONT_FAMILY).arg(charFmt.fontFamily()); if (charFmt.fontItalic()) result += QString(HTM::FONT_STYLE).arg(HTM::ITALIC); if (charFmt.fontUnderline()) result += QString(HTM::TEXT_DECORATION).arg(HTM::UNDERLINE); if (charFmt.fontStrikeOut()) result += QString(HTM::TEXT_DECORATION).arg(HTM::LINE_THROUGH); /*if (charFmt.fontWeight() != defaultFont.weight()) { QFont::Weight weight = (charFmt.fontWeight() >= QFont::Bold) ? QFont::Bold : QFont::Normal; result += QString(HTM::FONT_WEIGHT).arg(weight); }*/ if (charFmt.fontPointSize() != defaultFont.pointSize() && charFmt.fontPointSize() != 0) result += QString(HTM::FONT_SIZE).arg(charFmt.fontPointSize()); if (!isTextBlack) result += QString(HTM::COLOR).arg(textColor.name()); result += "\">" + Qt::escape(currentFragment.text()) + "</span>"; if (bold) result += "</b>"; } } result += HTM::_PAR; } result += "</body></html>"; return result; }
void HtmlExporter::emitFragment( const QTextFragment &fragment, const QTextBlockFormat &blockFormat ) { // kDebug() << "html" << html; const QTextCharFormat format = fragment.charFormat(); bool closeAnchor = false; bool anchorIsOpen = false; if ( format.isAnchor() ) { // const QStringList names = format.anchorNames(); // if (!names.isEmpty()) { // html += QLatin1String("<a name=\""); // html += names.at(0); // html += QLatin1String("\" "); // anchorIsOpen = true; // } const QString href = format.anchorHref(); if ( !href.isEmpty() ) { // if (!anchorIsOpen) { // html += QLatin1String("<a "); // anchorIsOpen = true; // } html += QLatin1String( "<a href=\"" ); html += href; html += QLatin1String( "\"" ); anchorIsOpen = true; // closeAnchor = true; // html += QLatin1String("\""); } if ( format.hasProperty( BilboTextFormat::AnchorTitle ) ) { const QString title = format.stringProperty( BilboTextFormat::AnchorTitle ); if ( !title.isEmpty() ) { html += QLatin1String( " title=\"" ); html += title; html += QLatin1String( "\"" ); } } if ( format.hasProperty( BilboTextFormat::AnchorTarget ) ) { const QString target = format.stringProperty( BilboTextFormat::AnchorTarget ); if ( !target.isEmpty() ) { html += QLatin1String( " target=\"" ); html += target; html += QLatin1String( "\"" ); } } if ( anchorIsOpen ) { html += QLatin1String( ">" ); closeAnchor = true; } } QList<tag> tags = emitCharFormatStyle( format, blockFormat ); // if ( !format.anchorHref().isNull() ) { // html += QLatin1String(">"); // closeAnchor = true; // } // kDebug() << "tags count" << tags.count() << endl; for ( int i = 0; i < tags.count(); ++i ) { switch ( tags.at( i ) ) { case span: break; //Jump // case h1: // html += QLatin1String( "<h1>" ); // break; // case h2: // html += QLatin1String( "<h2>" ); // break; // case h3: // html += QLatin1String( "<h3>" ); // break; // case h4: // html += QLatin1String( "<h4>" ); // break; // case h5: // html += QLatin1String( "<h5>" ); // break; case strong: html += QLatin1String( "<strong>" ); break; case em: html += QLatin1String( "<em>" ); break; case s: html += QLatin1String( "<s>" ); break; case u: if ( !closeAnchor ) html += QLatin1String( "<u>" ); break; case code: html += QLatin1String( "<code>" ); break; case sub: html += QLatin1String( "<sub>" ); break; case sup: html += QLatin1String( "<sup>" ); break; } } /* QLatin1String styleTag("<span style=\""); html += styleTag; const bool attributesEmitted = emitCharFormatStyle(format); if (attributesEmitted) html += QLatin1String("\">"); else html.chop(qstrlen(styleTag.latin1())); */ QString txt = fragment.text(); // kDebug() << txt ; 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( BilboTextFormat::ImageTitle ) ) { const QString title = imgFmt.stringProperty( BilboTextFormat::ImageTitle ); if ( !title.isEmpty() ) { emitAttribute( "title", imgFmt.stringProperty( BilboTextFormat::ImageTitle ) ); } } if ( imgFmt.hasProperty( BilboTextFormat::ImageAlternateText ) ) { const QString alternate = imgFmt.stringProperty( BilboTextFormat::ImageAlternateText ); if ( !alternate.isEmpty() ) { emitAttribute( "alt", imgFmt.stringProperty( BilboTextFormat::ImageAlternateText ) ); } } 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. //and to convert LineSeparators to <br /> tags. html += lines.at( i ); } } // kDebug() << html ; //Close Tags //if (!closeAnchor) for ( int i = tags.count(); i > 0; --i ) { switch ( tags.at( i - 1 ) ) { case span: html += QLatin1String( "</span>" ); break; //Jump // case h1: // html += QLatin1String( "</h1>" ); // break; // case h2: // html += QLatin1String( "</h2>" ); // break; // case h3: // html += QLatin1String( "</h3>" ); // break; // case h4: // html += QLatin1String( "</h4>" ); // break; // case h5: // html += QLatin1String( "</h5>" ); // break; case strong: html += QLatin1String( "</strong>" ); break; case em: html += QLatin1String( "</em>" ); break; case s: html += QLatin1String( "</s>" ); break; case u: if ( !closeAnchor ) html += QLatin1String( "</u>" ); break; case code: html += QLatin1String( "</code>" ); break; case sub: html += QLatin1String( "</sub>" ); break; case sup: html += QLatin1String( "</sup>" ); break; } } /* if (attributesEmitted) html += QLatin1String("</span>"); */ if ( closeAnchor ) { html += QLatin1String( "</a>" ); } // kDebug() << "html=>" << html; }
//绘制klee面板上的显示效果 void DrcDockWidget::kleeDrawText() { QTextDocument *document = ui->resultKleeEdit->document(); QTextBlock currentBlock = document->begin(); QTextBlock::iterator it; QTextCursor cursor = ui->resultKleeEdit->textCursor(); while( true) { // 在修改chatformat时会改变当前Block的fragment // 所以++it的处理类似std::map中的erase操作 for (it = currentBlock.begin(); !(it.atEnd()); ) { QTextFragment currentFragment = it.fragment(); if (currentFragment.isValid()) { ++it; int pos = currentFragment.position(); QString strText = currentFragment.text(); qDebug() << "strText: " << strText; if(strText.contains(':')) { char str = strText.at(0).toLatin1(); QTextCharFormat fmt; QColor col; QFont font; font.setBold(true); fmt.setFont(font); fmt.setForeground(QBrush(QColor(255, 0, 0))); QTextCursor helper = cursor; QString strPart1 = strText.split(':').at(0); QString strPart2 = strText.split(':').at(1); switch(str) { case 'V': case 'h': case 'M': pos += strPart1.length() + 1; helper.setPosition(pos); helper.setPosition(pos + strPart2.length(), QTextCursor::KeepAnchor); fmt.setForeground(QBrush(QColor(255, 0, 0))); helper.setCharFormat(fmt); break; case 'i': case '/': pos += strPart1.length() + 1; helper.setPosition(pos); helper.setPosition(pos + strPart2.length(), QTextCursor::KeepAnchor); fmt.setForeground(QBrush(QColor(34, 139, 34))); helper.setCharFormat(fmt); break; case 'T': QString strPart3 = strText.split(':').at(2); //线程ID QString strPart4 = strPart2.split(',').at(0); pos += strPart1.length() + 1; helper.setPosition(pos); helper.setPosition(pos + strPart4.length(), QTextCursor::KeepAnchor); fmt.setForeground(QBrush(QColor(148, 0, 211))); helper.setCharFormat(fmt); pos += strPart2.length() + 1; //读写类型 helper.setPosition(pos); helper.setPosition(pos + strPart3.length(), QTextCursor::KeepAnchor); fmt.setForeground(QBrush(QColor(0, 0, 139))); helper.setCharFormat(fmt); break; } } } } currentBlock = currentBlock.next(); if(!currentBlock.isValid()) break; } // 光标移动到最后, 并设置拥有焦点 QTextCursor c = ui->resultKleeEdit->textCursor(); c.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); ui->resultKleeEdit->setTextCursor(c); ui->resultKleeEdit->setFocus(Qt::MouseFocusReason); }