27 virtual bool match(
const QDomElement &) = 0;
29 virtual QString
toString()
const {
return QString(); }
41 bool match(
const QDomElement &)
override
60 bool match(
const QDomElement &e)
override
62 return e.tagName() ==
m_type;
84 if (
id.startsWith(
'#'))
87 bool match(
const QDomElement &e)
override
89 return e.attribute(
"id") ==
m_id;
110 QString pattern = attribute;
111 if (pattern.startsWith(
'['))
113 if (pattern.endsWith(
']'))
114 pattern.remove(pattern.length()-1,1);
115 int equalPos = pattern.indexOf(
'=');
116 if (equalPos == -1) {
119 }
else if (equalPos > 0){
120 if (pattern[equalPos-1] ==
'~') {
123 }
else if(pattern[equalPos-1] ==
'|') {
130 m_value = pattern.mid(equalPos+1);
131 if (
m_value.startsWith(QLatin1Char(
'"')))
133 if (
m_value.endsWith(QLatin1Char(
'"')))
138 bool match(
const QDomElement &e)
override
150 return tokens.contains(
m_value);
202 bool match(
const QDomElement &e)
override
205 QDomNode parent = e.parentNode();
206 if (parent.isNull()) {
209 QDomNode firstChild = parent.firstChild();
210 while(!firstChild.isElement() || firstChild.isNull()) {
211 firstChild = firstChild.nextSibling();
213 return firstChild == e;
245 bool match(
const QDomElement &e)
override
292 QString expr =
m_token + QChar();
299 while((state != Finish) && (state != Bad) && (i < expr.length())) {
309 state = InPseudoClass;
311 state = InClassAttribute;
332 case InClassAttribute:
335 if (sep.contains(ch) || ch.isNull()) {
338 else if (state == InId)
340 else if ( state == InClassAttribute)
342 else if (state == InPseudoClass) {
346 state = ch.isNull() ? Finish : Start;
383 for(
int i = 0; i < selectorCount-1; ++i) {
392 bool match(
const QDomElement &e)
override
397 if (selectorCount-combinatorCount != 1)
400 QDomElement currentElement = e;
403 for(
int i = 0; i < selectorCount; ++i) {
405 if (!curr->
match(currentElement)) {
409 if(i == selectorCount-1)
414 if (combinator ==
' ') {
415 bool matched =
false;
417 QDomNode parent = currentElement.parentNode();
418 while(!parent.isNull()) {
419 currentElement = parent.toElement();
420 if (next->match(currentElement)) {
424 parent = currentElement.parentNode();
428 }
else if (combinator ==
'>') {
430 QDomNode parent = currentElement.parentNode();
433 QDomElement parentElement = parent.toElement();
434 if (next->match(parentElement)) {
435 currentElement = parentElement;
439 }
else if (combinator ==
'+') {
440 QDomNode neighbor = currentElement.previousSibling();
441 while(!neighbor.isNull() && !neighbor.isElement())
442 neighbor = neighbor.previousSibling();
443 if (neighbor.isNull() || !neighbor.isElement())
445 QDomElement neighborElement = neighbor.toElement();
446 if (next->match(neighborElement)) {
447 currentElement = neighborElement;
469 Q_FOREACH (
const CssToken &token, tokens) {
493 qDeleteAll(rule.first);
501 QStringList selectors = pattern.split(
',', Qt::SkipEmptyParts);
502 for (
int i = 0; i < selectors.count(); ++i ) {
505 group.append(selector);
513 QString expr = selector + QChar();
522 int selectorStart = 0;
527 if (ch.isSpace() || ch ==
'>' || ch ==
'+') {
528 debugFlake <<
"selector starting with combinator is not allowed:" << selector;
537 while((state != Finish) && (state != Bad) && (i < expr.length())) {
542 if( ch ==
'>' || ch ==
'+') {
543 if( ! combinator.isSpace() ) {
550 }
else if (!ch.isSpace()) {
554 combinator = QChar();
559 if (ch.isSpace() || ch ==
'>' || ch ==
'+') {
560 state = InCombinator;
562 }
else if (ch.isNull()) {
565 if (state != InSelector) {
566 QString simpleSelector = selector.mid(selectorStart, i-selectorStart);
582 if (tokenList.isEmpty())
585 if (tokenList.count() == 1) {
588 }
else if (tokenList.count() > 2) {
613 if (e.hasChildNodes()) {
614 QDomNode c = e.firstChild();
615 if (c.isCDATASection()) {
616 QDomCDATASection cdata = c.toCDATASection();
617 data = cdata.data().simplified();
618 }
else if (c.isText()) {
619 QDomText text = c.toText();
620 data = text.data().simplified();
627 QRegExp commentExp(
"\\/\\*.*\\*\\/");
628 commentExp.setMinimal(
true);
629#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
630 data.remove(commentExp);
632 commentExp.removeIn(data);
635 QStringList defs = data.split(
'}', Qt::SkipEmptyParts);
636 for (
int i = 0; i < defs.count(); ++i) {
638 if( def.count() != 2 )
640 QString pattern = def[0].simplified();
641 if (pattern.isEmpty())
643 QString style = def[1].simplified();
646 QStringList selectors = pattern.split(
',', Qt::SkipEmptyParts);
647 for (
int i = 0; i < selectors.count(); ++i ) {
648 QString selector = selectors[i].simplified();
658 QMap<int, QString> prioritizedRules;
662 bool matched = s->
match(element);
664 prioritizedRules[s->
priority()] = rule.second;
669 QString styleAttribute = element.attribute(
"style").simplified();
670 if (!styleAttribute.isEmpty())
671 prioritizedRules[100] = styleAttribute;
675 QMapIterator<int, QString> it(prioritizedRules);
676 while (it.hasNext()) {
678 cssStyles.append(it.value());
CssTokenType
Token types used for tokenizing complex selectors.
@ SelectorToken
a selector token
@ CombinatorToken
a combinator token
QPair< CssTokenType, QString > CssToken
A token used for tokenizing complex selectors.
QList< CssSelectorBase * > SelectorGroup
A group of selectors (comma separated in css style sheet)
QPair< SelectorGroup, QString > CssRule
A css rule consisting of group of selectors corresponding to a style.
Attribute selector, matching existence or content of attributes.
AttributeSelector(const QString &attribute)
bool match(const QDomElement &e) override
Matches the given element.
QString toString() const override
Returns string representation of selector.
@ Unknown
unknown -> error state
@ StartsWith
[att|=val] -> attribute starts with val-
@ Exists
[att] -> attribute exists
@ InList
[att~=val] -> attribute is whitespace separated list where one is val
@ Equals
[att=val] -> attribute value matches exactly val
Complex selector, i.e. a combination of simple selectors.
QList< CssSelectorBase * > m_selectors
bool match(const QDomElement &e) override
Matches the given element.
QString toString() const override
Returns string representation of selector.
void compile(const QList< CssToken > &tokens)
CssComplexSelector(const QList< CssToken > &tokens)
~CssComplexSelector() override
Selector base class, merely an interface.
virtual bool match(const QDomElement &)=0
Matches the given element.
virtual ~CssSelectorBase()
virtual QString toString() const
Returns string representation of selector.
A simple selector, i.e. a type/universal selector followed by attribute, id or pseudo-class selectors...
bool match(const QDomElement &e) override
Matches the given element.
CssSimpleSelector(const QString &token)
~CssSimpleSelector() override
QString toString() const override
Returns string representation of selector.
QList< CssSelectorBase * > m_selectors
Id selector, matching the id attribute.
QString toString() const override
Returns string representation of selector.
IdSelector(const QString &id)
bool match(const QDomElement &e) override
Matches the given element.
QString toString() const override
Returns string representation of selector.
bool match(const QDomElement &e) override
Matches the given element.
PseudoClassSelector(const QString &pseudoClass)
QList< CssToken > tokenize(const QString &selector)
QList< CssRule > cssRules
QMap< QString, QString > cssStyles
SelectorGroup parsePattern(const QString &pattern)
CssSelectorBase * compileSelector(const QString &selector)
QStringList matchStyles(const QDomElement &element) const
void parseStylesheet(const QDomElement &)
Parses css style sheet in given xml element.
Type selector, matching the type of an element.
QString toString() const override
Returns string representation of selector.
bool match(const QDomElement &e) override
Matches the given element.
TypeSelector(const QString &type)
Universal selector, matching anything.
QString toString() const override
Returns string representation of selector.
bool match(const QDomElement &) override
Matches the given element.