1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QCSSPARSER_P_H
43 #define QCSSPARSER_P_H
49 // This file is not part of the Qt API. It exists for the convenience
50 // of the QLibrary class. This header file may change from
51 // version to version without notice, or even be removed.
56 #include <QtCore/QStringList>
57 #include <QtCore/QVector>
58 #include <QtCore/QVariant>
59 #include <QtCore/QPair>
60 #include <QtCore/QSize>
61 #include <QtCore/QMultiHash>
62 #include <QtGui/QFont>
63 #include <QtGui/QPalette>
64 #include <QtCore/QSharedData>
68 #ifndef QT_NO_CSSPARSER
70 // VxWorks defines NONE as (-1) "for times when NULL won't do"
71 #if defined(Q_OS_VXWORKS) && defined(NONE)
74 #if defined(Q_OS_INTEGRITY)
108 QtSelectionForeground,
109 QtSelectionBackground,
122 QtAlternateBackground,
139 BorderTopRightRadius,
140 BorderBottomLeftRadius,
141 BorderBottomRightRadius,
148 BackgroundAttachment,
178 OutlineTopLeftRadius,
179 OutlineTopRightRadius,
180 OutlineBottomLeftRadius,
181 OutlineBottomRightRadius,
243 /* keep these in same order as QPalette::ColorRole */
244 Value_FirstColorRole,
245 Value_WindowText = Value_FirstColorRole,
258 Value_HighlightedText,
262 Value_LastColorRole = Value_AlternateBase,
281 BorderStyle_DotDotDash,
332 PositionMode_Unknown,
334 PositionMode_Relative,
335 PositionMode_Absolute,
337 NumKnownPositionModes
348 StyleFeature_None = 0,
349 StyleFeature_BackgroundColor = 1,
350 StyleFeature_BackgroundGradient = 2,
351 NumKnownStyleFeatures = 4
354 struct Q_GUI_EXPORT Value
370 inline Value() : type(Unknown) { }
373 QString toString() const;
377 ColorData() : role(QPalette::NoRole), type(Invalid) {}
378 ColorData(const QColor &col) : color(col), role(QPalette::NoRole), type(Color) {}
379 ColorData(QPalette::ColorRole r) : role(r), type(Role) {}
381 QPalette::ColorRole role;
382 enum { Invalid, Color, Role} type;
386 BrushData() : role(QPalette::NoRole), type(Invalid) {}
387 BrushData(const QBrush &br) : brush(br), role(QPalette::NoRole), type(Brush) {}
388 BrushData(QPalette::ColorRole r) : role(r), type(Role) {}
390 QPalette::ColorRole role;
391 enum { Invalid, Brush, Role, DependsOnThePalette } type;
394 struct BackgroundData {
398 Qt::Alignment alignment;
403 enum { None, Px, Ex, Em } unit;
413 // 1. StyleRule - x:hover, y:clicked > z:checked { prop1: value1; prop2: value2; }
414 // 2. QVector<Selector> - x:hover, y:clicked z:checked
415 // 3. QVector<BasicSelector> - y:clicked z:checked
416 // 4. QVector<Declaration> - { prop1: value1; prop2: value2; }
417 // 5. Declaration - prop1: value1;
419 struct Q_GUI_EXPORT Declaration
421 struct DeclarationData : public QSharedData
423 inline DeclarationData() : propertyId(UnknownProperty), important(false) {}
426 QVector<Value> values;
430 QExplicitlySharedDataPointer<DeclarationData> d;
431 inline Declaration() : d(new DeclarationData()) {}
432 inline bool isEmpty() const { return d->property.isEmpty() && d->propertyId == UnknownProperty; }
435 QColor colorValue(const QPalette & = QPalette()) const;
436 void colorValues(QColor *c, const QPalette & = QPalette()) const;
437 QBrush brushValue(const QPalette & = QPalette()) const;
438 void brushValues(QBrush *c, const QPalette & = QPalette()) const;
440 BorderStyle styleValue() const;
441 void styleValues(BorderStyle *s) const;
443 Origin originValue() const;
444 Repeat repeatValue() const;
445 Qt::Alignment alignmentValue() const;
446 PositionMode positionValue() const;
447 Attachment attachmentValue() const;
448 int styleFeaturesValue() const;
450 bool intValue(int *i, const char *unit = 0) const;
451 bool realValue(qreal *r, const char *unit = 0) const;
453 QSize sizeValue() const;
454 QRect rectValue() const;
455 QString uriValue() const;
456 // QIcon iconValue() const;
458 void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
461 const quint64 PseudoClass_Unknown = Q_UINT64_C(0x0000000000000000);
462 const quint64 PseudoClass_Enabled = Q_UINT64_C(0x0000000000000001);
463 const quint64 PseudoClass_Disabled = Q_UINT64_C(0x0000000000000002);
464 const quint64 PseudoClass_Pressed = Q_UINT64_C(0x0000000000000004);
465 const quint64 PseudoClass_Focus = Q_UINT64_C(0x0000000000000008);
466 const quint64 PseudoClass_Hover = Q_UINT64_C(0x0000000000000010);
467 const quint64 PseudoClass_Checked = Q_UINT64_C(0x0000000000000020);
468 const quint64 PseudoClass_Unchecked = Q_UINT64_C(0x0000000000000040);
469 const quint64 PseudoClass_Indeterminate = Q_UINT64_C(0x0000000000000080);
470 const quint64 PseudoClass_Unspecified = Q_UINT64_C(0x0000000000000100);
471 const quint64 PseudoClass_Selected = Q_UINT64_C(0x0000000000000200);
472 const quint64 PseudoClass_Horizontal = Q_UINT64_C(0x0000000000000400);
473 const quint64 PseudoClass_Vertical = Q_UINT64_C(0x0000000000000800);
474 const quint64 PseudoClass_Window = Q_UINT64_C(0x0000000000001000);
475 const quint64 PseudoClass_Children = Q_UINT64_C(0x0000000000002000);
476 const quint64 PseudoClass_Sibling = Q_UINT64_C(0x0000000000004000);
477 const quint64 PseudoClass_Default = Q_UINT64_C(0x0000000000008000);
478 const quint64 PseudoClass_First = Q_UINT64_C(0x0000000000010000);
479 const quint64 PseudoClass_Last = Q_UINT64_C(0x0000000000020000);
480 const quint64 PseudoClass_Middle = Q_UINT64_C(0x0000000000040000);
481 const quint64 PseudoClass_OnlyOne = Q_UINT64_C(0x0000000000080000);
482 const quint64 PseudoClass_PreviousSelected = Q_UINT64_C(0x0000000000100000);
483 const quint64 PseudoClass_NextSelected = Q_UINT64_C(0x0000000000200000);
484 const quint64 PseudoClass_Flat = Q_UINT64_C(0x0000000000400000);
485 const quint64 PseudoClass_Left = Q_UINT64_C(0x0000000000800000);
486 const quint64 PseudoClass_Right = Q_UINT64_C(0x0000000001000000);
487 const quint64 PseudoClass_Top = Q_UINT64_C(0x0000000002000000);
488 const quint64 PseudoClass_Bottom = Q_UINT64_C(0x0000000004000000);
489 const quint64 PseudoClass_Exclusive = Q_UINT64_C(0x0000000008000000);
490 const quint64 PseudoClass_NonExclusive = Q_UINT64_C(0x0000000010000000);
491 const quint64 PseudoClass_Frameless = Q_UINT64_C(0x0000000020000000);
492 const quint64 PseudoClass_ReadOnly = Q_UINT64_C(0x0000000040000000);
493 const quint64 PseudoClass_Active = Q_UINT64_C(0x0000000080000000);
494 const quint64 PseudoClass_Closable = Q_UINT64_C(0x0000000100000000);
495 const quint64 PseudoClass_Movable = Q_UINT64_C(0x0000000200000000);
496 const quint64 PseudoClass_Floatable = Q_UINT64_C(0x0000000400000000);
497 const quint64 PseudoClass_Minimized = Q_UINT64_C(0x0000000800000000);
498 const quint64 PseudoClass_Maximized = Q_UINT64_C(0x0000001000000000);
499 const quint64 PseudoClass_On = Q_UINT64_C(0x0000002000000000);
500 const quint64 PseudoClass_Off = Q_UINT64_C(0x0000004000000000);
501 const quint64 PseudoClass_Editable = Q_UINT64_C(0x0000008000000000);
502 const quint64 PseudoClass_Item = Q_UINT64_C(0x0000010000000000);
503 const quint64 PseudoClass_Closed = Q_UINT64_C(0x0000020000000000);
504 const quint64 PseudoClass_Open = Q_UINT64_C(0x0000040000000000);
505 const quint64 PseudoClass_EditFocus = Q_UINT64_C(0x0000080000000000);
506 const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000);
507 // The Any specifier is never generated, but can be used as a wildcard in searches.
508 const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff);
509 const int NumPseudos = 46;
513 Pseudo() : type(0), negated(false) { }
520 struct AttributeSelector
522 enum ValueMatchType {
528 inline AttributeSelector() : valueMatchCriterium(NoMatch) {}
532 ValueMatchType valueMatchCriterium;
537 inline BasicSelector() : relationToNext(NoRelation) {}
541 MatchNextSelectorIfAncestor,
542 MatchNextSelectorIfParent,
543 MatchNextSelectorIfPreceeds
549 QVector<Pseudo> pseudos;
550 QVector<AttributeSelector> attributeSelectors;
552 Relation relationToNext;
555 struct Q_GUI_EXPORT Selector
557 QVector<BasicSelector> basicSelectors;
558 int specificity() const;
559 quint64 pseudoClass(quint64 *negated = 0) const;
560 QString pseudoElement() const;
568 struct Q_GUI_EXPORT ValueExtractor
570 ValueExtractor(const QVector<Declaration> &declarations, const QPalette & = QPalette());
572 bool extractFont(QFont *font, int *fontSizeAdjustment);
573 bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *,
575 bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh);
576 bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *,
577 QCss::PositionMode *, Qt::Alignment *);
578 bool extractBox(int *margins, int *paddings, int *spacing = 0);
579 bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii);
580 bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets);
581 bool extractPalette(QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg);
582 int extractStyleFeatures();
583 bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size);
585 int lengthValue(const Declaration &decl);
589 void borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color);
590 LengthData lengthValue(const Value& v);
591 void lengthValues(const Declaration &decl, int *m);
592 QSize sizeValue(const Declaration &decl);
593 void sizeValues(const Declaration &decl, QSize *radii);
595 QVector<Declaration> declarations;
604 StyleRule() : order(0) { }
605 QVector<Selector> selectors;
606 QVector<Declaration> declarations;
613 QVector<StyleRule> styleRules;
619 QVector<Declaration> declarations;
628 enum StyleSheetOrigin {
629 StyleSheetOrigin_Unspecified,
630 StyleSheetOrigin_UserAgent,
631 StyleSheetOrigin_User,
632 StyleSheetOrigin_Author,
633 StyleSheetOrigin_Inline
636 struct Q_GUI_EXPORT StyleSheet
638 StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { }
639 QVector<StyleRule> styleRules; //only contains rules that are not indexed
640 QVector<MediaRule> mediaRules;
641 QVector<PageRule> pageRules;
642 QVector<ImportRule> importRules;
643 StyleSheetOrigin origin;
644 int depth; // applicable only for inline style sheets
645 QMultiHash<QString, StyleRule> nameIndex;
646 QMultiHash<QString, StyleRule> idIndex;
647 void buildIndexes(Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive);
650 class Q_GUI_EXPORT StyleSelector
653 StyleSelector() : nameCaseSensitivity(Qt::CaseSensitive) {}
654 virtual ~StyleSelector();
661 QVector<StyleRule> styleRulesForNode(NodePtr node);
662 QVector<Declaration> declarationsForNode(NodePtr node, const char *extraPseudo = 0);
664 virtual bool nodeNameEquals(NodePtr node, const QString& nodeName) const;
665 virtual QString attribute(NodePtr node, const QString &name) const = 0;
666 virtual bool hasAttributes(NodePtr node) const = 0;
667 virtual QStringList nodeIds(NodePtr node) const;
668 virtual QStringList nodeNames(NodePtr node) const = 0;
669 virtual bool isNullNode(NodePtr node) const = 0;
670 virtual NodePtr parentNode(NodePtr node) const = 0;
671 virtual NodePtr previousSiblingNode(NodePtr node) const = 0;
672 virtual NodePtr duplicateNode(NodePtr node) const = 0;
673 virtual void freeNode(NodePtr node) const = 0;
675 QVector<StyleSheet> styleSheets;
677 Qt::CaseSensitivity nameCaseSensitivity;
679 void matchRule(NodePtr node, const StyleRule &rules, StyleSheetOrigin origin,
680 int depth, QMap<uint, StyleRule> *weightedRules);
681 bool selectorMatches(const Selector &rule, NodePtr node);
682 bool basicSelectorMatches(const BasicSelector &rule, NodePtr node);
733 struct Q_GUI_EXPORT Symbol
735 inline Symbol() : token(NONE), start(0), len(-1) {}
739 QString lexem() const;
742 class Q_GUI_EXPORT Scanner
745 static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
746 static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
749 class Q_GUI_EXPORT Parser
753 Parser(const QString &css, bool file = false);
755 void init(const QString &css, bool file = false);
756 bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive);
757 Symbol errorSymbol();
759 bool parseImport(ImportRule *importRule);
760 bool parseMedia(MediaRule *mediaRule);
761 bool parseMedium(QStringList *media);
762 bool parsePage(PageRule *pageRule);
763 bool parsePseudoPage(QString *selector);
764 bool parseNextOperator(Value *value);
765 bool parseCombinator(BasicSelector::Relation *relation);
766 bool parseProperty(Declaration *decl);
767 bool parseRuleset(StyleRule *styleRule);
768 bool parseSelector(Selector *sel);
769 bool parseSimpleSelector(BasicSelector *basicSel);
770 bool parseClass(QString *name);
771 bool parseElementName(QString *name);
772 bool parseAttrib(AttributeSelector *attr);
773 bool parsePseudo(Pseudo *pseudo);
774 bool parseNextDeclaration(Declaration *declaration);
775 bool parsePrio(Declaration *declaration);
776 bool parseExpr(QVector<Value> *values);
777 bool parseTerm(Value *value);
778 bool parseFunction(QString *name, QString *args);
779 bool parseHexColor(QColor *col);
780 bool testAndParseUri(QString *uri);
782 inline bool testRuleset() { return testSelector(); }
783 inline bool testSelector() { return testSimpleSelector(); }
784 inline bool parseNextSelector(Selector *sel) { if (!testSelector()) return recordError(); return parseSelector(sel); }
785 bool testSimpleSelector();
786 inline bool parseNextSimpleSelector(BasicSelector *basicSel) { if (!testSimpleSelector()) return recordError(); return parseSimpleSelector(basicSel); }
787 inline bool testElementName() { return test(IDENT) || test(STAR); }
788 inline bool testClass() { return test(DOT); }
789 inline bool testAttrib() { return test(LBRACKET); }
790 inline bool testPseudo() { return test(COLON); }
791 inline bool testMedium() { return test(IDENT); }
792 inline bool parseNextMedium(QStringList *media) { if (!testMedium()) return recordError(); return parseMedium(media); }
793 inline bool testPseudoPage() { return test(COLON); }
794 inline bool testImport() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("import")); }
795 inline bool testMedia() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("media")); }
796 inline bool testPage() { return testTokenAndEndsWith(ATKEYWORD_SYM, QLatin1String("page")); }
797 inline bool testCombinator() { return test(PLUS) || test(GREATER) || test(S); }
798 inline bool testProperty() { return test(IDENT); }
800 inline bool testExpr() { return testTerm(); }
801 inline bool parseNextExpr(QVector<Value> *values) { if (!testExpr()) return recordError(); return parseExpr(values); }
803 inline bool testHexColor() { return test(HASH); }
804 inline bool testFunction() { return test(FUNCTION); }
805 inline bool parseNextFunction(QString *name, QString *args) { if (!testFunction()) return recordError(); return parseFunction(name, args); }
807 inline bool lookupElementName() const { return lookup() == IDENT || lookup() == STAR; }
809 inline void skipSpace() { while (test(S)) {}; }
811 inline bool hasNext() const { return index < symbols.count(); }
812 inline TokenType next() { return symbols.at(index++).token; }
813 bool next(TokenType t);
814 bool test(TokenType t);
815 inline void prev() { index--; }
816 inline const Symbol &symbol() const { return symbols.at(index - 1); }
817 inline QString lexem() const { return symbol().lexem(); }
818 QString unquotedLexem() const;
819 QString lexemUntil(TokenType t);
820 bool until(TokenType target, TokenType target2 = NONE);
821 inline TokenType lookup() const {
822 return (index - 1) < symbols.count() ? symbols.at(index - 1).token : NONE;
825 bool testTokenAndEndsWith(TokenType t, const QLatin1String &str);
827 inline bool recordError() { errorIndex = index; return false; }
829 QVector<Symbol> symbols;
832 bool hasEscapeSequences;
840 Q_DECLARE_METATYPE( QCss::BackgroundData )
841 Q_DECLARE_METATYPE( QCss::LengthData )
842 Q_DECLARE_METATYPE( QCss::BorderData )
845 #endif // QT_NO_CSSPARSER