📄 qtexthtmlparser.cpp
字号:
{ ++pos; if (hasPrefix(QLatin1Char('-'),1) && hasPrefix(QLatin1Char('-'),2)) { pos += 3; // eat comments int end = txt.indexOf(QLatin1String("-->"), pos); pos = (end >= 0 ? end + 3 : len); } else { // eat internal tags while (pos < len) { QChar c = txt.at(pos++); if (c == QLatin1Char('>')) break; } }}// parses an entity after "&", and returns itQString QTextHtmlParser::parseEntity(){ int recover = pos; QString entity; while (pos < len) { QChar c = txt.at(pos++); if (c.isSpace() || pos - recover > 8) { goto error; } if (c == QLatin1Char(';')) break; entity += c; } { QChar resolved = resolveEntity(entity); if (!resolved.isNull()) return QString(resolved); } if (entity.length() > 1 && entity.at(0) == QLatin1Char('#')) { entity.remove(0, 1); // removing leading # int base = 10; bool ok = false; if (entity.at(0).toLower() == QLatin1Char('x')) { // hex entity? entity.remove(0, 1); base = 16; } int uc = entity.toInt(&ok, base); if (ok) { if (uc == 151) // ### hack for designer manual uc = '-'; QString str; if (uc > 0xffff) { // surrogate pair uc -= 0x10000; ushort high = uc/0x400 + 0xd800; ushort low = uc%0x400 + 0xdc00; str.append(QChar(high)); str.append(QChar(low)); } else { str.append(QChar(uc)); } return str; } }error: pos = recover; return QLatin1String("&");}// parses one word, possibly quoted, and returns itQString QTextHtmlParser::parseWord(){ QString word; if (hasPrefix(QLatin1Char('\"'))) { // double quotes ++pos; while (pos < len) { QChar c = txt.at(pos++); if (c == QLatin1Char('\"')) break; else if (c == QLatin1Char('&')) word += parseEntity(); else word += c; } } else if (hasPrefix(QLatin1Char('\''))) { // single quotes ++pos; while (pos < len) { QChar c = txt.at(pos++); if (c == QLatin1Char('\'')) break; else word += c; } } else { // normal text while (pos < len) { QChar c = txt.at(pos++); if (c == QLatin1Char('>') || (c == '/' && hasPrefix(QLatin1Char('>'), 1)) || c == QLatin1Char('<') || c == QLatin1Char('=') || c.isSpace()) { --pos; break; } if (c == QLatin1Char('&')) word += parseEntity(); else word += c; } } return word;}// gives the new node the right parentvoid QTextHtmlParser::resolveParent(){ QTextHtmlParserNode *node = &nodes.last(); int p = node->parent; // permit invalid html by letting block elements be children // of inline elements with the exception of paragraphs: // // a new paragraph closes parent inline elements (while loop), // unless they themselves are children of a non-paragraph block // element (if statement) // // For example: // // <body><p><b>Foo<p>Bar <-- second <p> implicitly closes <b> that // belongs to the first <p>. The self-nesting // check further down prevents the second <p> // from nesting into the first one then. // so Bar is not bold. // // <body><b><p>Foo <-- Foo should be bold. // // <body><b><p>Foo<p>Bar <-- Foo and Bar should be bold. // if (node->id == Html_p) { while (p && !at(p).isBlock) p = at(p).parent; if (!p || at(p).id != Html_p) p = node->parent; } // some elements are not self nesting if (node->id == at(p).id && node->isNotSelfNesting()) p = at(p).parent; // some elements are not allowed in certain contexts while (p && !node->allowedInContext(at(p).id) // ### make new styles aware of empty tags || at(p).mayNotHaveChildren() ) { p = at(p).parent; } node->parent = p; // makes it easier to traverse the tree, later nodes[p].children.append(nodes.count() - 1);}// sets all properties on the new nodevoid QTextHtmlParser::resolveNode(){ QTextHtmlParserNode *node = &nodes.last(); const QTextHtmlParserNode *parent = &nodes.at(node->parent); node->initializeProperties(parent, this);}bool QTextHtmlParserNode::isNestedList(const QTextHtmlParser *parser) const{ if (!isListStart) return false; int p = parent; while (p) { if (parser->at(p).isListStart) return true; p = parser->at(p).parent; } return false;}void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent, const QTextHtmlParser *parser){ // inherit properties from parent element isAnchor = parent->isAnchor; fontItalic = parent->fontItalic; fontUnderline = parent->fontUnderline; fontOverline = parent->fontOverline; fontStrikeOut = parent->fontStrikeOut; fontFixedPitch = parent->fontFixedPitch; fontFamily = parent->fontFamily; hasFontPointSize = parent->hasFontPointSize; fontPointSize = parent->fontPointSize; fontSizeAdjustment = parent->fontSizeAdjustment; hasFontSizeAdjustment = parent->hasFontSizeAdjustment; fontWeight = parent->fontWeight; color = parent->color; verticalAlignment = parent->verticalAlignment; if (parent->displayMode == QTextHtmlElement::DisplayNone) displayMode = QTextHtmlElement::DisplayNone; if (parent->id != Html_table) { alignment = parent->alignment; } // we don't paint per-row background colors, yet. so as an // exception inherit the background color here if (parent->id == Html_tr && isTableCell) { bgColor = parent->bgColor; } listStyle = parent->listStyle; anchorHref = parent->anchorHref; // makes no sense to inherit that property, a named anchor is a single point // in the document, which is set by the DocumentFragment //anchorName = parent->anchorName; wsm = parent->wsm; // initialize remaining properties margin[QTextHtmlParser::MarginLeft] = 0; margin[QTextHtmlParser::MarginRight] = 0; margin[QTextHtmlParser::MarginTop] = 0; margin[QTextHtmlParser::MarginBottom] = 0; cssFloat = QTextFrameFormat::InFlow; const int oldFontPointSize = fontPointSize; // set element specific attributes switch (id) { case Html_a: isAnchor = true; break; case Html_em: case Html_i: case Html_cite: case Html_address: case Html_var: case Html_dfn: fontItalic = On; break; case Html_big: fontSizeAdjustment = 1; hasFontSizeAdjustment = true; break; case Html_small: fontSizeAdjustment = -1; hasFontSizeAdjustment = true; break; case Html_strong: case Html_b: fontWeight = QFont::Bold; break; case Html_h1: fontWeight = QFont::Bold; fontSizeAdjustment = 3; hasFontSizeAdjustment = true; margin[QTextHtmlParser::MarginTop] = 18; margin[QTextHtmlParser::MarginBottom] = 12; break; case Html_h2: fontWeight = QFont::Bold; fontSizeAdjustment = 2; hasFontSizeAdjustment = true; margin[QTextHtmlParser::MarginTop] = 16; margin[QTextHtmlParser::MarginBottom] = 12; break; case Html_h3: fontWeight = QFont::Bold; fontSizeAdjustment = 1; hasFontSizeAdjustment = true; margin[QTextHtmlParser::MarginTop] = 14; margin[QTextHtmlParser::MarginBottom] = 12; break; case Html_h4: fontWeight = QFont::Bold; fontSizeAdjustment = 0; hasFontSizeAdjustment = true; margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; break; case Html_h5: fontWeight = QFont::Bold; fontSizeAdjustment = -1; hasFontSizeAdjustment = true; margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 4; break; case Html_p: margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; break; case Html_center: alignment = Qt::AlignCenter; break; case Html_ul: listStyle = QTextListFormat::ListDisc; // nested lists don't have margins, except for the toplevel one if (!isNestedList(parser)) { margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; } // no left margin as we use indenting instead break; case Html_ol: listStyle = QTextListFormat::ListDecimal; // nested lists don't have margins, except for the toplevel one if (!isNestedList(parser)) { margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; } // no left margin as we use indenting instead break; case Html_code: case Html_tt: case Html_kbd: case Html_samp: fontFamily = QString::fromLatin1("Courier New,courier"); // <tt> uses a fixed font, so set the property fontFixedPitch = On; break; case Html_br: text = QChar(QChar::LineSeparator); break; // ##### sub / sup case Html_pre: fontFamily = QString::fromLatin1("Courier New,courier"); wsm = WhiteSpacePre; margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; // <pre> uses a fixed font fontFixedPitch = On; break; case Html_blockquote: margin[QTextHtmlParser::MarginLeft] = 40; margin[QTextHtmlParser::MarginRight] = 40; break; case Html_dl: margin[QTextHtmlParser::MarginTop] = 8; margin[QTextHtmlParser::MarginBottom] = 8; break; case Html_dd: margin[QTextHtmlParser::MarginLeft] = 30; break; case Html_u: fontUnderline = On; break; case Html_s: fontStrikeOut = On; break; case Html_nobr: wsm = WhiteSpaceNoWrap; break; case Html_th: fontWeight = QFont::Bold; alignment = Qt::AlignCenter; break; case Html_td: alignment = Qt::AlignLeft; break; case Html_sub: verticalAlignment = QTextCharFormat::AlignSubScript; break; case Html_sup: verticalAlignment = QTextCharFormat::AlignSuperScript; break; default: break; } if (fontPointSize != oldFontPointSize) hasFontPointSize = true;}static bool setIntAttribute(int *destination, const QString &value){ bool ok = false; int val = value.toInt(&ok); if (ok) *destination = val; return ok;}static bool setFloatAttribute(qreal *destination, const QString &value){ bool ok = false; qreal val = value.toDouble(&ok); if (ok) *destination = val; return ok;}static void setWidthAttribute(QTextLength *width, QString value){ qreal realVal; bool ok = false; realVal = value.toDouble(&ok); if (ok) { *width = QTextLength(QTextLength::FixedLength, realVal); } else { value = value.trimmed(); if (!value.isEmpty() && value.at(value.length() - 1) == QLatin1Char('%')) { value.chop(1); realVal = value.toDouble(&ok); if (ok) *width = QTextLength(QTextLength::PercentageLength, realVal); } }}static QTextHtmlParserNode::WhiteSpaceMode stringToWhiteSpaceMode(const QString &s){ if (s == QLatin1String("normal")) return QTextHtmlParserNode::WhiteSpaceNormal;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -