📄 qcssparser.cpp
字号:
origins, NumKnownOrigins));}PositionMode Declaration::positionValue() const{ if (values.count() != 1) return PositionMode_Unknown; return static_cast<PositionMode>(findKnownValue(values.first().variant.toString(), positions, NumKnownPositionModes));}Attachment Declaration::attachmentValue() const{ if (values.count() != 1) return Attachment_Unknown; return static_cast<Attachment>(findKnownValue(values.first().variant.toString(), attachments, NumKnownAttachments));}int Declaration::styleFeaturesValue() const{ int features = StyleFeature_None; for (int i = 0; i < values.count(); i++) { features |= static_cast<int>(findKnownValue(values.value(i).variant.toString(), styleFeatures, NumKnownStyleFeatures)); } return features;}QString Declaration::uriValue() const{ if (values.isEmpty() || values.first().type != Value::Uri) return QString(); return values.first().variant.toString();}Qt::Alignment Declaration::alignmentValue() const{ if (values.isEmpty() || values.count() > 2) return Qt::AlignLeft | Qt::AlignTop; return parseAlignment(values.constData(), values.count());}void Declaration::borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const{ *image = uriValue(); for (int i = 0; i < 4; i++) cuts[i] = -1; *h = *v = TileMode_Stretch; if (values.count() < 2) return; if (values.at(1).type == Value::Number) { // cuts! int i; for (i = 0; i < qMin(values.count()-1, 4); i++) { const Value& v = values.at(i+1); if (v.type != Value::Number) break; cuts[i] = v.variant.toString().toInt(); } if (i == 0) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0; else if (i == 1) cuts[3] = cuts[2] = cuts[1] = cuts[0]; else if (i == 2) cuts[2] = cuts[0], cuts[3] = cuts[1]; else if (i == 3) cuts[3] = cuts[1]; } if (values.last().type == Value::Identifier) { *v = static_cast<TileMode>(findKnownValue(values.last().variant.toString(), tileModes, NumKnownTileModes)); } if (values[values.count() - 2].type == Value::Identifier) { *h = static_cast<TileMode> (findKnownValue(values[values.count()-2].variant.toString(), tileModes, NumKnownTileModes)); } else *h = *v;}QIcon Declaration::iconValue() const{ QIcon icon; for (int i = 0; i < values.count(); i++) { const Value &value = values.at(i); if (value.type != Value::Uri) continue; if (icon.isNull()) icon = QIcon(value.variant.toString()); else icon.addPixmap(value.variant.toString()); } return icon;}///////////////////////////////////////////////////////////////////////////////// Selectorint Selector::specificity() const{ int val = 0; for (int i = 0; i < basicSelectors.count(); ++i) { const BasicSelector &sel = basicSelectors.at(i); if (!sel.elementName.isEmpty()) val += 1; val += (sel.pseudos.count() + sel.attributeSelectors.count()) * 0x10; val += sel.ids.count() * 0x100; } return val;}QString Selector::pseudoElement() const{ const BasicSelector& bs = basicSelectors.last(); if (!bs.pseudos.isEmpty() && bs.pseudos.first().type == PseudoClass_Unknown) return bs.pseudos.first().name; return QString();}int Selector::pseudoClass(int *negated) const{ const BasicSelector& bs = basicSelectors.last(); if (bs.pseudos.isEmpty()) return PseudoClass_Unspecified; int pc = PseudoClass_Unknown; for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.count(); i++) { const Pseudo &pseudo = bs.pseudos.at(i); if (pseudo.type == PseudoClass_Unknown) return PseudoClass_Unknown; if (!pseudo.negated) pc |= pseudo.type; else if (negated) *negated |= pseudo.type; } return pc;}///////////////////////////////////////////////////////////////////////////////// StyleSelectorStyleSelector::~StyleSelector(){}QStringList StyleSelector::nodeIds(NodePtr node) const{ return QStringList(attribute(node, QLatin1String("id")));}bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node){ if (selector.basicSelectors.isEmpty()) return false; if (selector.basicSelectors.first().relationToNext == BasicSelector::NoRelation) { if (selector.basicSelectors.count() != 1) return false; return basicSelectorMatches(selector.basicSelectors.first(), node); } if (selector.basicSelectors.count() <= 1) return false; int i = selector.basicSelectors.count() - 1; node = duplicateNode(node); bool match = true; BasicSelector sel = selector.basicSelectors.at(i); do { match = basicSelectorMatches(sel, node); if (!match) { if (sel.relationToNext == BasicSelector::MatchNextSelectorIfParent || i == selector.basicSelectors.count() - 1) // first element must always match! break; } if (match || sel.relationToNext != BasicSelector::MatchNextSelectorIfAncestor) --i; if (i < 0) break; sel = selector.basicSelectors.at(i); if (sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor || sel.relationToNext == BasicSelector::MatchNextSelectorIfParent) { NodePtr nextParent = parentNode(node); freeNode(node); node = nextParent; } else if (sel.relationToNext == BasicSelector::MatchNextSelectorIfPreceeds) { NodePtr previousSibling = previousSiblingNode(node); freeNode(node); node = previousSibling; } if (isNullNode(node)) { match = false; break; } } while (i >= 0 && (match || sel.relationToNext == BasicSelector::MatchNextSelectorIfAncestor)); freeNode(node); return match;}bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node){ if (!sel.attributeSelectors.isEmpty()) { if (!hasAttributes(node)) return false; for (int i = 0; i < sel.attributeSelectors.count(); ++i) { const QCss::AttributeSelector &a = sel.attributeSelectors.at(i); if (!hasAttribute(node, a.name)) return false; const QString attrValue = attribute(node, a.name); if (a.valueMatchCriterium == QCss::AttributeSelector::MatchContains) { QStringList lst = attrValue.split(QLatin1Char(' ')); if (!lst.contains(a.value)) return false; } else if ( (a.valueMatchCriterium == QCss::AttributeSelector::MatchEqual && attrValue != a.value) || (a.valueMatchCriterium == QCss::AttributeSelector::MatchBeginsWith && !attrValue.startsWith(a.value)) ) return false; } } if (!sel.elementName.isEmpty() && !nodeNameEquals(node, sel.elementName)) return false; if (!sel.ids.isEmpty() && sel.ids != nodeIds(node)) return false; return true;}static inline bool qcss_selectorLessThan(const QPair<int, QCss::StyleRule> &lhs, const QPair<int, QCss::StyleRule> &rhs){ return lhs.first < rhs.first;}void StyleSelector::matchRules(NodePtr node, const QVector<StyleRule> &rules, StyleSheetOrigin origin, int depth, QVector<QPair<int, StyleRule> > *weightedRules){ for (int i = 0; i < rules.count(); ++i) { const StyleRule &rule = rules.at(i); for (int j = 0; j < rule.selectors.count(); ++j) { const Selector& selector = rule.selectors.at(j); if (selectorMatches(selector, node)) { QPair<int, StyleRule> weightedRule; weightedRule.first = selector.specificity() + (origin == StyleSheetOrigin_Inline)*0x1000*depth; weightedRule.second.selectors.append(selector); weightedRule.second.declarations = rule.declarations; weightedRules->append(weightedRule); } } }}// Returns style rules that are in ascending order of specificity// Each of the StyleRule returned will contain exactly one SelectorQVector<StyleRule> StyleSelector::styleRulesForNode(NodePtr node){ QVector<StyleRule> rules; if (styleSheets.isEmpty()) return rules; QVector<QPair<int, StyleRule> > weightedRules; // (spec, rule) that will be sorted below for (int sheetIdx = 0; sheetIdx < styleSheets.count(); ++sheetIdx) { const StyleSheet &styleSheet = styleSheets.at(sheetIdx); matchRules(node, styleSheet.styleRules, styleSheet.origin, styleSheet.depth, &weightedRules); if (!medium.isEmpty()) { for (int i = 0; i < styleSheet.mediaRules.count(); ++i) { if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) { matchRules(node, styleSheet.mediaRules.at(i).styleRules, styleSheet.origin, styleSheet.depth, &weightedRules); } } } } qStableSort(weightedRules.begin(), weightedRules.end(), qcss_selectorLessThan); for (int j = 0; j < weightedRules.count(); j++) rules += weightedRules.at(j).second; return rules;}// for qtexthtmlparser which requires just the declarations with Enabled state// and without pseudo elementsQVector<Declaration> StyleSelector::declarationsForNode(NodePtr node, const char *extraPseudo){ QVector<Declaration> decls; QVector<StyleRule> rules = styleRulesForNode(node); for (int i = 0; i < rules.count(); i++) { const Selector& selector = rules.at(i).selectors.at(0); const QString pseudoElement = selector.pseudoElement(); if (extraPseudo && pseudoElement == QLatin1String(extraPseudo)) { decls += rules.at(i).declarations; continue; } if (!pseudoElement.isEmpty()) // skip rules with pseudo elements continue; int pseudoClass = selector.pseudoClass(); if (pseudoClass == PseudoClass_Enabled || pseudoClass == PseudoClass_Unspecified) decls += rules.at(i).declarations; } return decls;}static inline bool isHexDigit(const char c){ return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ;}QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences){ QString output = input; if (hasEscapeSequences) *hasEscapeSequences = false; int i = 0; while (i < output.size()) { if (output.at(i) == QLatin1Char('\\')) { ++i; // test for unicode hex escape int hexCount = 0; const int hexStart = i; while (i < output.size() && isHexDigit(output.at(i).toLatin1()) && hexCount < 7) { ++hexCount; ++i; } if (hexCount == 0) { if (hasEscapeSequences) *hasEscapeSequences = true; continue; } hexCount = qMin(hexCount, 6); bool ok = false; ushort code = output.mid(hexStart, hexCount).toUShort(&ok, 16); if (ok) { output.replace(hexStart - 1, hexCount + 1, QChar(code)); i = hexStart; } else { i = hexStart; } } else { ++i; } } return output;}int QCssScanner_Generated::handleCommentStart(){ while (pos < input.size() - 1) { if (input.at(pos) == QLatin1Char('*') && input.at(pos + 1) == QLatin1Char('/')) { pos += 2; break; } ++pos; } return S;}void Scanner::scan(const QString &preprocessedInput, QVector<Symbol> *symbols){ QCssScanner_Generated scanner(preprocessedInput); Symbol sym; int tok = scanner.lex(); while (tok != -1) { sym.token = static_cast<TokenType>(tok); sym.text = scanner.input; sym.start = scanner.lexemStart; sym.len = scanner.lexemLength; symbols->append(sym); tok = scanner.lex(); }}QString Symbol::lexem() const{ QString result; if (len > 0) result.reserve(len); for (int i = 0; i < len; ++i) { if (text.at(start + i) == QLatin1Char('\\') && i < len - 1) ++i; result.inline_append(text.at(start + i)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -