📄 qtexthtmlparser.cpp
字号:
void QTextHtmlParser::applyAttributes(const QStringList &attributes){ // local state variable for qt3 textedit mode bool seenQt3Richtext = false; QString linkHref; QString linkType; if (attributes.count() % 2 == 1) return; QTextHtmlParserNode *node = &nodes.last(); for (int i = 0; i < attributes.count(); i += 2) { QString key = attributes.at(i); QString value = attributes.at(i + 1); switch (node->id) { case Html_font: // the infamous font tag if (key == QLatin1String("size") && value.size()) { int n = value.toInt(); if (value.at(0) != QLatin1Char('+') && value.at(0) != QLatin1Char('-')) n -= 3; node->charFormat.setProperty(QTextFormat::FontSizeAdjustment, n); } else if (key == QLatin1String("face")) { node->charFormat.setFontFamily(value); } else if (key == QLatin1String("color")) { QColor c; c.setNamedColor(value); node->charFormat.setForeground(c); } break; case Html_ol: case Html_ul: if (key == QLatin1String("type")) { node->hasOwnListStyle = true; if (value == QLatin1String("1")) { node->listStyle = QTextListFormat::ListDecimal; } else if (value == QLatin1String("a")) { node->listStyle = QTextListFormat::ListLowerAlpha; } else if (value == QLatin1String("A")) { node->listStyle = QTextListFormat::ListUpperAlpha; } else { value = value.toLower(); if (value == QLatin1String("square")) node->listStyle = QTextListFormat::ListSquare; else if (value == QLatin1String("disc")) node->listStyle = QTextListFormat::ListDisc; else if (value == QLatin1String("circle")) node->listStyle = QTextListFormat::ListCircle; } } break; case Html_a: if (key == QLatin1String("href")) node->charFormat.setAnchorHref(value); else if (key == QLatin1String("name")) node->charFormat.setAnchorName(value); break; case Html_img: if (key == QLatin1String("src") || key == QLatin1String("source")) { node->imageName = value; } else if (key == QLatin1String("width")) { setFloatAttribute(&node->imageWidth, value); } else if (key == QLatin1String("height")) { setFloatAttribute(&node->imageHeight, value); } break; case Html_tr: case Html_body: if (key == QLatin1String("bgcolor")) { QColor c; c.setNamedColor(value); node->charFormat.setBackground(c); } break; case Html_th: case Html_td: if (key == QLatin1String("width")) { setWidthAttribute(&node->width, value); } else if (key == QLatin1String("bgcolor")) { QColor c; c.setNamedColor(value); node->charFormat.setBackground(c); } else if (key == QLatin1String("rowspan")) { if (setIntAttribute(&node->tableCellRowSpan, value)) node->tableCellRowSpan = qMax(1, node->tableCellRowSpan); } else if (key == QLatin1String("colspan")) { if (setIntAttribute(&node->tableCellColSpan, value)) node->tableCellColSpan = qMax(1, node->tableCellColSpan); } break; case Html_table: if (key == QLatin1String("border")) { setFloatAttribute(&node->tableBorder, value); } else if (key == QLatin1String("bgcolor")) { QColor c; c.setNamedColor(value); node->charFormat.setBackground(c); } else if (key == QLatin1String("cellspacing")) { setFloatAttribute(&node->tableCellSpacing, value); } else if (key == QLatin1String("cellpadding")) { setFloatAttribute(&node->tableCellPadding, value); } else if (key == QLatin1String("width")) { setWidthAttribute(&node->width, value); } else if (key == QLatin1String("height")) { setWidthAttribute(&node->height, value); } break; case Html_meta: if (key == QLatin1String("name") && value == QLatin1String("qrichtext")) { seenQt3Richtext = true; } if (key == QLatin1String("content") && value == QLatin1String("1") && seenQt3Richtext) { textEditMode = true; } break; case Html_hr: if (key == QLatin1String("width")) setWidthAttribute(&node->width, value); break; case Html_link: if (key == QLatin1String("href")) linkHref = value; else if (key == QLatin1String("type")) linkType = value; break; default: break; } if (key == QLatin1String("style")) { node->parseStyleAttribute(value, resourceProvider); } else if (key == QLatin1String("align")) { value = value.toLower(); bool alignmentSet = true; if (value == QLatin1String("left")) node->blockFormat.setAlignment(Qt::AlignLeft|Qt::AlignAbsolute); else if (value == QLatin1String("right")) node->blockFormat.setAlignment(Qt::AlignRight|Qt::AlignAbsolute); else if (value == QLatin1String("center")) node->blockFormat.setAlignment(Qt::AlignHCenter); else if (value == QLatin1String("justify")) node->blockFormat.setAlignment(Qt::AlignJustify); else alignmentSet = false; if (node->id == Html_img) { // HTML4 compat if (alignmentSet) { if (node->blockFormat.alignment() & Qt::AlignLeft) node->cssFloat = QTextFrameFormat::FloatLeft; else if (node->blockFormat.alignment() & Qt::AlignRight) node->cssFloat = QTextFrameFormat::FloatRight; } else if (value == QLatin1String("middle")) { node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle); } else if (value == QLatin1String("top")) { node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop); } } } else if (key == QLatin1String("valign")) { value = value.toLower(); if (value == QLatin1String("top")) node->charFormat.setVerticalAlignment(QTextCharFormat::AlignTop); else if (value == QLatin1String("middle")) node->charFormat.setVerticalAlignment(QTextCharFormat::AlignMiddle); else if (value == QLatin1String("bottom")) node->charFormat.setVerticalAlignment(QTextCharFormat::AlignBottom); } else if (key == QLatin1String("dir")) { value = value.toLower(); if (value == QLatin1String("ltr")) node->blockFormat.setLayoutDirection(Qt::LeftToRight); else if (value == QLatin1String("rtl")) node->blockFormat.setLayoutDirection(Qt::RightToLeft); } else if (key == QLatin1String("title")) { node->charFormat.setToolTip(value); } else if (key == QLatin1String("id")) { node->charFormat.setAnchor(true); node->charFormat.setAnchorName(value); } } if (resourceProvider && !linkHref.isEmpty() && linkType == QLatin1String("text/css")) importStyleSheet(linkHref);}class QTextHtmlStyleSelector : public QCss::StyleSelector{public: inline QTextHtmlStyleSelector(const QTextHtmlParser *parser) : parser(parser) {} virtual bool nodeNameEquals(NodePtr node, const QString& name) const; virtual QString attribute(NodePtr node, const QString &name) const; virtual bool hasAttribute(NodePtr node, const QString &name) const; virtual bool hasAttributes(NodePtr node) const; virtual bool isNullNode(NodePtr node) const; virtual NodePtr parentNode(NodePtr node) const; virtual NodePtr previousSiblingNode(NodePtr node) const; virtual NodePtr duplicateNode(NodePtr node) const; virtual void freeNode(NodePtr node) const;private: const QTextHtmlParser *parser;};bool QTextHtmlStyleSelector::nodeNameEquals(NodePtr node, const QString& name) const{ return QString::compare(parser->at(node.id).tag, name, Qt::CaseInsensitive) == 0;}static inline int findAttribute(const QStringList &attributes, const QString &name){ int idx = -1; do { idx = attributes.indexOf(name, idx + 1); } while (idx != -1 && (idx % 2 == 1)); return idx;}QString QTextHtmlStyleSelector::attribute(NodePtr node, const QString &name) const{ const QStringList &attributes = parser->at(node.id).attributes; const int idx = findAttribute(attributes, name); if (idx == -1) return QString(); return attributes.at(idx + 1);}bool QTextHtmlStyleSelector::hasAttribute(NodePtr node, const QString &name) const{ const QStringList &attributes = parser->at(node.id).attributes; return findAttribute(attributes, name) != -1;}bool QTextHtmlStyleSelector::hasAttributes(NodePtr node) const{ const QStringList &attributes = parser->at(node.id).attributes; return !attributes.isEmpty();}bool QTextHtmlStyleSelector::isNullNode(NodePtr node) const{ return node.id == 0;}QCss::StyleSelector::NodePtr QTextHtmlStyleSelector::parentNode(NodePtr node) const{ NodePtr parent; parent.id = 0; if (node.id) { parent.id = parser->at(node.id).parent; } return parent;}QCss::StyleSelector::NodePtr QTextHtmlStyleSelector::duplicateNode(NodePtr node) const{ return node;}QCss::StyleSelector::NodePtr QTextHtmlStyleSelector::previousSiblingNode(NodePtr node) const{ NodePtr sibling; sibling.id = 0; if (!node.id) return sibling; int parent = parser->at(node.id).parent; if (!parent) return sibling; const int childIdx = parser->at(parent).children.indexOf(node.id); if (childIdx <= 0) return sibling; sibling.id = parser->at(parent).children.at(childIdx - 1); return sibling;}void QTextHtmlStyleSelector::freeNode(NodePtr) const{}void QTextHtmlParser::resolveStyleSheetImports(const QCss::StyleSheet &sheet){ for (int i = 0; i < sheet.importRules.count(); ++i) { const QCss::ImportRule &rule = sheet.importRules.at(i); if (rule.media.isEmpty() || rule.media.contains(QLatin1String("screen"), Qt::CaseInsensitive)) importStyleSheet(rule.href); }}void QTextHtmlParser::importStyleSheet(const QString &href){ if (!resourceProvider) return; for (int i = 0; i < externalStyleSheets.count(); ++i) if (externalStyleSheets.at(i).url == href) return; QVariant res = resourceProvider->resource(QTextDocument::StyleSheetResource, href); QString css; if (res.type() == QVariant::String) { css = res.toString(); } else if (res.type() == QVariant::ByteArray) { // #### detect @charset css = QString::fromUtf8(res.toByteArray()); } if (!css.isEmpty()) { QCss::Parser parser(css); QCss::StyleSheet sheet; parser.parse(&sheet); externalStyleSheets.append(ExternalStyleSheet(href, sheet)); resolveStyleSheetImports(sheet); }}QVector<QCss::Declaration> QTextHtmlParser::declarationsForNode(int node) const{ QVector<QCss::Declaration> decls; QTextHtmlStyleSelector selector(this); int idx = 0; selector.styleSheets.resize((resourceProvider ? 1 : 0) + externalStyleSheets.count() + inlineStyleSheets.count()); if (resourceProvider) selector.styleSheets[idx++] = resourceProvider->docHandle()->parsedDefaultStyleSheet; for (int i = 0; i < externalStyleSheets.count(); ++i, ++idx) selector.styleSheets[idx] = externalStyleSheets.at(i).sheet; for (int i = 0; i < inlineStyleSheets.count(); ++i, ++idx) selector.styleSheets[idx] = inlineStyleSheets.at(i); selector.medium = QLatin1String("screen"); QCss::StyleSelector::NodePtr n; n.id = node; const char *extraPseudo = 0; if (nodes.at(node).id == Html_a && nodes.at(node).hasHref) extraPseudo = "link"; decls = selector.declarationsForNode(n, extraPseudo); return decls;}bool QTextHtmlParser::nodeIsChildOf(int i, QTextHTMLElements id) const{ while (i) { if (at(i).id == id) return true; i = at(i).parent; } return false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -