1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
36 | ** |
37 | ** |
38 | ** $QT_END_LICENSE$ |
39 | ** |
40 | ****************************************************************************/ |
41 | |
42 | #ifndef QCSSPARSER_P_H |
43 | #define QCSSPARSER_P_H |
44 | |
45 | // |
46 | // W A R N I N G |
47 | // ------------- |
48 | // |
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. |
52 | // |
53 | // We mean it. |
54 | // |
55 | |
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 <QtGui/QIcon> |
65 | #include <QtCore/QSharedData> |
66 | |
67 | |
68 | #ifndef QT_NO_CSSPARSER |
69 | |
70 | // VxWorks defines NONE as (-1) "for times when NULL won't do" |
71 | #if defined(Q_OS_VXWORKS) && defined(NONE) |
72 | # undef NONE |
73 | #endif |
74 | #if defined(Q_OS_INTEGRITY) |
75 | # undef Value |
76 | #endif |
77 | |
78 | QT_BEGIN_NAMESPACE |
79 | |
80 | namespace QCss |
81 | { |
82 | |
83 | enum Property { |
84 | UnknownProperty, |
85 | BackgroundColor, |
86 | Color, |
87 | Float, |
88 | Font, |
89 | FontFamily, |
90 | FontSize, |
91 | FontStyle, |
92 | FontWeight, |
93 | Margin, |
94 | MarginBottom, |
95 | MarginLeft, |
96 | MarginRight, |
97 | MarginTop, |
98 | QtBlockIndent, |
99 | QtListIndent, |
100 | QtParagraphType, |
101 | QtTableType, |
102 | QtUserState, |
103 | TextDecoration, |
104 | TextIndent, |
105 | TextUnderlineStyle, |
106 | VerticalAlignment, |
107 | Whitespace, |
108 | QtSelectionForeground, |
109 | QtSelectionBackground, |
110 | Border, |
111 | BorderLeft, |
112 | BorderRight, |
113 | BorderTop, |
114 | BorderBottom, |
115 | Padding, |
116 | PaddingLeft, |
117 | PaddingRight, |
118 | PaddingTop, |
119 | PaddingBottom, |
120 | PageBreakBefore, |
121 | PageBreakAfter, |
122 | QtAlternateBackground, |
123 | BorderLeftStyle, |
124 | BorderRightStyle, |
125 | BorderTopStyle, |
126 | BorderBottomStyle, |
127 | BorderStyles, |
128 | BorderLeftColor, |
129 | BorderRightColor, |
130 | BorderTopColor, |
131 | BorderBottomColor, |
132 | BorderColor, |
133 | BorderLeftWidth, |
134 | BorderRightWidth, |
135 | BorderTopWidth, |
136 | BorderBottomWidth, |
137 | BorderWidth, |
138 | BorderTopLeftRadius, |
139 | BorderTopRightRadius, |
140 | BorderBottomLeftRadius, |
141 | BorderBottomRightRadius, |
142 | BorderRadius, |
143 | Background, |
144 | BackgroundOrigin, |
145 | BackgroundClip, |
146 | BackgroundRepeat, |
147 | BackgroundPosition, |
148 | BackgroundAttachment, |
149 | BackgroundImage, |
150 | BorderImage, |
151 | QtSpacing, |
152 | Width, |
153 | Height, |
154 | MinimumWidth, |
155 | MinimumHeight, |
156 | MaximumWidth, |
157 | MaximumHeight, |
158 | QtImage, |
159 | Left, |
160 | Right, |
161 | Top, |
162 | Bottom, |
163 | QtOrigin, |
164 | QtPosition, |
165 | Position, |
166 | QtStyleFeatures, |
167 | QtBackgroundRole, |
168 | ListStyleType, |
169 | ListStyle, |
170 | QtImageAlignment, |
171 | TextAlignment, |
172 | Outline, |
173 | OutlineOffset, |
174 | OutlineWidth, |
175 | OutlineColor, |
176 | OutlineStyle, |
177 | OutlineRadius, |
178 | OutlineTopLeftRadius, |
179 | OutlineTopRightRadius, |
180 | OutlineBottomLeftRadius, |
181 | OutlineBottomRightRadius, |
182 | FontVariant, |
183 | TextTransform, |
184 | QtListNumberPrefix, |
185 | QtListNumberSuffix, |
186 | LineHeight, |
187 | NumProperties |
188 | }; |
189 | |
190 | enum KnownValue { |
191 | UnknownValue, |
192 | Value_Normal, |
193 | Value_Pre, |
194 | Value_NoWrap, |
195 | Value_PreWrap, |
196 | Value_Small, |
197 | Value_Medium, |
198 | Value_Large, |
199 | Value_XLarge, |
200 | Value_XXLarge, |
201 | Value_Italic, |
202 | Value_Oblique, |
203 | Value_Bold, |
204 | Value_Underline, |
205 | Value_Overline, |
206 | Value_LineThrough, |
207 | Value_Sub, |
208 | Value_Super, |
209 | Value_Left, |
210 | Value_Right, |
211 | Value_Top, |
212 | Value_Bottom, |
213 | Value_Center, |
214 | Value_Native, |
215 | Value_Solid, |
216 | Value_Dotted, |
217 | Value_Dashed, |
218 | Value_DotDash, |
219 | Value_DotDotDash, |
220 | Value_Double, |
221 | Value_Groove, |
222 | Value_Ridge, |
223 | Value_Inset, |
224 | Value_Outset, |
225 | Value_Wave, |
226 | Value_Middle, |
227 | Value_Auto, |
228 | Value_Always, |
229 | Value_None, |
230 | Value_Transparent, |
231 | Value_Disc, |
232 | Value_Circle, |
233 | Value_Square, |
234 | Value_Decimal, |
235 | Value_LowerAlpha, |
236 | Value_UpperAlpha, |
237 | Value_LowerRoman, |
238 | Value_UpperRoman, |
239 | Value_SmallCaps, |
240 | Value_Uppercase, |
241 | Value_Lowercase, |
242 | |
243 | /* keep these in same order as QPalette::ColorRole */ |
244 | Value_FirstColorRole, |
245 | Value_WindowText = Value_FirstColorRole, |
246 | Value_Button, |
247 | Value_Light, |
248 | Value_Midlight, |
249 | Value_Dark, |
250 | Value_Mid, |
251 | Value_Text, |
252 | Value_BrightText, |
253 | Value_ButtonText, |
254 | Value_Base, |
255 | Value_Window, |
256 | Value_Shadow, |
257 | Value_Highlight, |
258 | Value_HighlightedText, |
259 | Value_Link, |
260 | Value_LinkVisited, |
261 | Value_AlternateBase, |
262 | Value_LastColorRole = Value_AlternateBase, |
263 | |
264 | Value_Disabled, |
265 | Value_Active, |
266 | Value_Selected, |
267 | Value_On, |
268 | Value_Off, |
269 | |
270 | NumKnownValues |
271 | }; |
272 | |
273 | enum BorderStyle { |
274 | BorderStyle_Unknown, |
275 | BorderStyle_None, |
276 | BorderStyle_Dotted, |
277 | BorderStyle_Dashed, |
278 | BorderStyle_Solid, |
279 | BorderStyle_Double, |
280 | BorderStyle_DotDash, |
281 | BorderStyle_DotDotDash, |
282 | BorderStyle_Groove, |
283 | BorderStyle_Ridge, |
284 | BorderStyle_Inset, |
285 | BorderStyle_Outset, |
286 | BorderStyle_Native, |
287 | NumKnownBorderStyles |
288 | }; |
289 | |
290 | enum Edge { |
291 | TopEdge, |
292 | RightEdge, |
293 | BottomEdge, |
294 | LeftEdge, |
295 | NumEdges |
296 | }; |
297 | |
298 | enum Corner { |
299 | TopLeftCorner, |
300 | TopRightCorner, |
301 | BottomLeftCorner, |
302 | BottomRightCorner |
303 | }; |
304 | |
305 | enum TileMode { |
306 | TileMode_Unknown, |
307 | TileMode_Round, |
308 | TileMode_Stretch, |
309 | TileMode_Repeat, |
310 | NumKnownTileModes |
311 | }; |
312 | |
313 | enum Repeat { |
314 | Repeat_Unknown, |
315 | Repeat_None, |
316 | Repeat_X, |
317 | Repeat_Y, |
318 | Repeat_XY, |
319 | NumKnownRepeats |
320 | }; |
321 | |
322 | enum Origin { |
323 | Origin_Unknown, |
324 | Origin_Padding, |
325 | Origin_Border, |
326 | Origin_Content, |
327 | Origin_Margin, |
328 | NumKnownOrigins |
329 | }; |
330 | |
331 | enum PositionMode { |
332 | PositionMode_Unknown, |
333 | PositionMode_Static, |
334 | PositionMode_Relative, |
335 | PositionMode_Absolute, |
336 | PositionMode_Fixed, |
337 | NumKnownPositionModes |
338 | }; |
339 | |
340 | enum Attachment { |
341 | Attachment_Unknown, |
342 | Attachment_Fixed, |
343 | Attachment_Scroll, |
344 | NumKnownAttachments |
345 | }; |
346 | |
347 | enum StyleFeature { |
348 | StyleFeature_None = 0, |
349 | StyleFeature_BackgroundColor = 1, |
350 | StyleFeature_BackgroundGradient = 2, |
351 | NumKnownStyleFeatures = 4 |
352 | }; |
353 | |
354 | struct Q_GUI_EXPORT Value |
355 | { |
356 | enum Type { |
357 | Unknown, |
358 | Number, |
359 | Percentage, |
360 | Length, |
361 | String, |
362 | Identifier, |
363 | KnownIdentifier, |
364 | Uri, |
365 | Color, |
366 | Function, |
367 | TermOperatorSlash, |
368 | TermOperatorComma |
369 | }; |
370 | inline Value() : type(Unknown) { } |
371 | Type type; |
372 | QVariant variant; |
373 | QString toString() const; |
374 | }; |
375 | |
376 | struct ColorData { |
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) {} |
380 | QColor color; |
381 | QPalette::ColorRole role; |
382 | enum { Invalid, Color, Role} type; |
383 | }; |
384 | |
385 | struct BrushData { |
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) {} |
389 | QBrush brush; |
390 | QPalette::ColorRole role; |
391 | enum { Invalid, Brush, Role, DependsOnThePalette } type; |
392 | }; |
393 | |
394 | struct BackgroundData { |
395 | BrushData brush; |
396 | QString image; |
397 | Repeat repeat; |
398 | Qt::Alignment alignment; |
399 | }; |
400 | |
401 | struct LengthData { |
402 | qreal number; |
403 | enum { None, Px, Ex, Em } unit; |
404 | }; |
405 | |
406 | struct BorderData { |
407 | LengthData width; |
408 | BorderStyle style; |
409 | BrushData color; |
410 | }; |
411 | |
412 | |
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; |
418 | |
419 | struct Q_AUTOTEST_EXPORT Declaration |
420 | { |
421 | struct DeclarationData : public QSharedData |
422 | { |
423 | inline DeclarationData() : propertyId(UnknownProperty), important(false) {} |
424 | QString property; |
425 | Property propertyId; |
426 | QVector<Value> values; |
427 | QVariant parsed; |
428 | bool important; |
429 | }; |
430 | QExplicitlySharedDataPointer<DeclarationData> d; |
431 | inline Declaration() : d(new DeclarationData()) {} |
432 | inline bool isEmpty() const { return d->property.isEmpty() && d->propertyId == UnknownProperty; } |
433 | |
434 | // helper functions |
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; |
439 | |
440 | BorderStyle styleValue() const; |
441 | void styleValues(BorderStyle *s) const; |
442 | |
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; |
449 | |
450 | bool intValue(int *i, const char *unit = 0) const; |
451 | bool realValue(qreal *r, const char *unit = 0) const; |
452 | |
453 | QSize sizeValue() const; |
454 | QRect rectValue() const; |
455 | QString uriValue() const; |
456 | QIcon iconValue() const; |
457 | |
458 | void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const; |
459 | }; |
460 | |
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; |
510 | |
511 | struct Pseudo |
512 | { |
513 | Pseudo() : type(0), negated(false) { } |
514 | quint64 type; |
515 | QString name; |
516 | QString function; |
517 | bool negated; |
518 | }; |
519 | |
520 | struct AttributeSelector |
521 | { |
522 | enum ValueMatchType { |
523 | NoMatch, |
524 | MatchEqual, |
525 | MatchContains, |
526 | MatchBeginsWith |
527 | }; |
528 | inline AttributeSelector() : valueMatchCriterium(NoMatch) {} |
529 | |
530 | QString name; |
531 | QString value; |
532 | ValueMatchType valueMatchCriterium; |
533 | }; |
534 | |
535 | struct BasicSelector |
536 | { |
537 | inline BasicSelector() : relationToNext(NoRelation) {} |
538 | |
539 | enum Relation { |
540 | NoRelation, |
541 | MatchNextSelectorIfAncestor, |
542 | MatchNextSelectorIfParent, |
543 | MatchNextSelectorIfPreceeds |
544 | }; |
545 | |
546 | QString elementName; |
547 | |
548 | QStringList ids; |
549 | QVector<Pseudo> pseudos; |
550 | QVector<AttributeSelector> attributeSelectors; |
551 | |
552 | Relation relationToNext; |
553 | }; |
554 | |
555 | struct Q_AUTOTEST_EXPORT Selector |
556 | { |
557 | QVector<BasicSelector> basicSelectors; |
558 | int specificity() const; |
559 | quint64 pseudoClass(quint64 *negated = 0) const; |
560 | QString pseudoElement() const; |
561 | }; |
562 | |
563 | struct StyleRule; |
564 | struct MediaRule; |
565 | struct PageRule; |
566 | struct ImportRule; |
567 | |
568 | struct Q_AUTOTEST_EXPORT |
569 | { |
570 | (const QVector<Declaration> &declarations, const QPalette & = QPalette()); |
571 | |
572 | bool (QFont *font, int *fontSizeAdjustment); |
573 | bool (QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *, |
574 | QCss::Origin *); |
575 | bool (int *w, int *h, int *minw, int *minh, int *maxw, int *maxh); |
576 | bool (int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *, |
577 | QCss::PositionMode *, Qt::Alignment *); |
578 | bool (int *margins, int *paddings, int *spacing = 0); |
579 | bool (int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii); |
580 | bool (int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets); |
581 | bool (QBrush *fg, QBrush *sfg, QBrush *sbg, QBrush *abg); |
582 | int (); |
583 | bool (QIcon *icon, Qt::Alignment *a, QSize *size); |
584 | |
585 | int (const Declaration &decl); |
586 | |
587 | private: |
588 | void (); |
589 | void (const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color); |
590 | LengthData (const Value& v); |
591 | void (const Declaration &decl, int *m); |
592 | QSize (const Declaration &decl); |
593 | void (const Declaration &decl, QSize *radii); |
594 | |
595 | QVector<Declaration> ; |
596 | QFont ; |
597 | int ; |
598 | int ; |
599 | QPalette ; |
600 | }; |
601 | |
602 | struct StyleRule |
603 | { |
604 | StyleRule() : order(0) { } |
605 | QVector<Selector> selectors; |
606 | QVector<Declaration> declarations; |
607 | int order; |
608 | }; |
609 | |
610 | struct MediaRule |
611 | { |
612 | QStringList media; |
613 | QVector<StyleRule> styleRules; |
614 | }; |
615 | |
616 | struct |
617 | { |
618 | QString ; |
619 | QVector<Declaration> ; |
620 | }; |
621 | |
622 | struct ImportRule |
623 | { |
624 | QString href; |
625 | QStringList media; |
626 | }; |
627 | |
628 | enum StyleSheetOrigin { |
629 | StyleSheetOrigin_Unspecified, |
630 | StyleSheetOrigin_UserAgent, |
631 | StyleSheetOrigin_User, |
632 | StyleSheetOrigin_Author, |
633 | StyleSheetOrigin_Inline |
634 | }; |
635 | |
636 | struct StyleSheet |
637 | { |
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> ; |
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); |
648 | }; |
649 | |
650 | class Q_GUI_EXPORT StyleSelector |
651 | { |
652 | public: |
653 | StyleSelector() : nameCaseSensitivity(Qt::CaseSensitive) {} |
654 | virtual ~StyleSelector(); |
655 | |
656 | union NodePtr { |
657 | void *ptr; |
658 | int id; |
659 | }; |
660 | |
661 | QVector<StyleRule> styleRulesForNode(NodePtr node); |
662 | QVector<Declaration> declarationsForNode(NodePtr node, const char * = 0); |
663 | |
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; |
674 | |
675 | QVector<StyleSheet> styleSheets; |
676 | QString medium; |
677 | Qt::CaseSensitivity nameCaseSensitivity; |
678 | private: |
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); |
683 | }; |
684 | |
685 | enum TokenType { |
686 | NONE, |
687 | |
688 | S, |
689 | |
690 | CDO, |
691 | CDC, |
692 | INCLUDES, |
693 | DASHMATCH, |
694 | |
695 | LBRACE, |
696 | PLUS, |
697 | GREATER, |
698 | COMMA, |
699 | |
700 | STRING, |
701 | INVALID, |
702 | |
703 | IDENT, |
704 | |
705 | HASH, |
706 | |
707 | ATKEYWORD_SYM, |
708 | |
709 | EXCLAMATION_SYM, |
710 | |
711 | LENGTH, |
712 | |
713 | PERCENTAGE, |
714 | NUMBER, |
715 | |
716 | FUNCTION, |
717 | |
718 | COLON, |
719 | SEMICOLON, |
720 | RBRACE, |
721 | SLASH, |
722 | MINUS, |
723 | DOT, |
724 | STAR, |
725 | LBRACKET, |
726 | RBRACKET, |
727 | EQUAL, |
728 | LPAREN, |
729 | RPAREN, |
730 | OR |
731 | }; |
732 | |
733 | struct Q_GUI_EXPORT Symbol |
734 | { |
735 | inline Symbol() : token(NONE), start(0), len(-1) {} |
736 | TokenType token; |
737 | QString text; |
738 | int start, len; |
739 | QString lexem() const; |
740 | }; |
741 | |
742 | class Q_AUTOTEST_EXPORT Scanner |
743 | { |
744 | public: |
745 | static QString preprocess(const QString &input, bool *hasEscapeSequences = 0); |
746 | static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols); |
747 | }; |
748 | |
749 | class Q_GUI_EXPORT Parser |
750 | { |
751 | public: |
752 | Parser(); |
753 | Parser(const QString &css, bool file = false); |
754 | |
755 | void init(const QString &css, bool file = false); |
756 | bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity = Qt::CaseSensitive); |
757 | Symbol errorSymbol(); |
758 | |
759 | bool parseImport(ImportRule *importRule); |
760 | bool parseMedia(MediaRule *mediaRule); |
761 | bool parseMedium(QStringList *media); |
762 | bool (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); |
781 | |
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); } |
799 | bool testTerm(); |
800 | inline bool testExpr() { return testTerm(); } |
801 | inline bool parseNextExpr(QVector<Value> *values) { if (!testExpr()) return recordError(); return parseExpr(values); } |
802 | bool testPrio(); |
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); } |
806 | |
807 | inline bool lookupElementName() const { return lookup() == IDENT || lookup() == STAR; } |
808 | |
809 | inline void skipSpace() { while (test(S)) {}; } |
810 | |
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; |
823 | } |
824 | |
825 | bool testTokenAndEndsWith(TokenType t, const QLatin1String &str); |
826 | |
827 | inline bool recordError() { errorIndex = index; return false; } |
828 | |
829 | QVector<Symbol> symbols; |
830 | int index; |
831 | int errorIndex; |
832 | bool hasEscapeSequences; |
833 | QString sourcePath; |
834 | }; |
835 | |
836 | } // namespace QCss |
837 | |
838 | QT_END_NAMESPACE |
839 | |
840 | Q_DECLARE_METATYPE( QCss::BackgroundData ) |
841 | Q_DECLARE_METATYPE( QCss::LengthData ) |
842 | Q_DECLARE_METATYPE( QCss::BorderData ) |
843 | |
844 | |
845 | #endif // QT_NO_CSSPARSER |
846 | |
847 | #endif |
848 | |