Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qcssparser.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcssparser_p.h"
5
6#include <QtCore/qmap.h>
7#include <qdebug.h>
8#include <qicon.h>
9#include <qcolor.h>
10#include <qfont.h>
11#include <qfileinfo.h>
12#include <qfontmetrics.h>
13#include <qbrush.h>
14#include <qimagereader.h>
15
16#include <algorithm>
17
18#ifndef QT_NO_CSSPARSER
19
21
22using namespace Qt::StringLiterals;
23
27
28#include "qcssscanner.cpp"
29
30using namespace QCss;
31
33{
34 const char name[28];
36};
37
39 { "-qt-background-role", QtBackgroundRole },
40 { "-qt-block-indent", QtBlockIndent },
41 { "-qt-fg-texture-cachekey", QtForegroundTextureCacheKey },
42 { "-qt-line-height-type", QtLineHeightType },
43 { "-qt-list-indent", QtListIndent },
44 { "-qt-list-number-prefix", QtListNumberPrefix },
45 { "-qt-list-number-suffix", QtListNumberSuffix },
46 { "-qt-paragraph-type", QtParagraphType },
47 { "-qt-style-features", QtStyleFeatures },
48 { "-qt-table-type", QtTableType },
49 { "-qt-user-state", QtUserState },
50 { "accent-color", QtAccentColor },
51 { "alternate-background-color", QtAlternateBackground },
52 { "background", Background },
53 { "background-attachment", BackgroundAttachment },
54 { "background-clip", BackgroundClip },
55 { "background-color", BackgroundColor },
56 { "background-image", BackgroundImage },
57 { "background-origin", BackgroundOrigin },
58 { "background-position", BackgroundPosition },
59 { "background-repeat", BackgroundRepeat },
60 { "border", Border },
61 { "border-bottom", BorderBottom },
62 { "border-bottom-color", BorderBottomColor },
63 { "border-bottom-left-radius", BorderBottomLeftRadius },
64 { "border-bottom-right-radius", BorderBottomRightRadius },
65 { "border-bottom-style", BorderBottomStyle },
66 { "border-bottom-width", BorderBottomWidth },
67 { "border-collapse", BorderCollapse },
68 { "border-color", BorderColor },
69 { "border-image", BorderImage },
70 { "border-left", BorderLeft },
71 { "border-left-color", BorderLeftColor },
72 { "border-left-style", BorderLeftStyle },
73 { "border-left-width", BorderLeftWidth },
74 { "border-radius", BorderRadius },
75 { "border-right", BorderRight },
76 { "border-right-color", BorderRightColor },
77 { "border-right-style", BorderRightStyle },
78 { "border-right-width", BorderRightWidth },
79 { "border-style", BorderStyles },
80 { "border-top", BorderTop },
81 { "border-top-color", BorderTopColor },
82 { "border-top-left-radius", BorderTopLeftRadius },
83 { "border-top-right-radius", BorderTopRightRadius },
84 { "border-top-style", BorderTopStyle },
85 { "border-top-width", BorderTopWidth },
86 { "border-width", BorderWidth },
87 { "bottom", Bottom },
88 { "color", Color },
89 { "float", Float },
90 { "font", Font },
91 { "font-family", FontFamily },
92 { "font-kerning", FontKerning },
93 { "font-size", FontSize },
94 { "font-style", FontStyle },
95 { "font-variant", FontVariant },
96 { "font-weight", FontWeight },
97 { "height", Height },
98 { "icon", QtIcon },
99 { "image", QtImage },
100 { "image-position", QtImageAlignment },
101 { "left", Left },
102 { "letter-spacing", LetterSpacing },
103 { "line-height", LineHeight },
104 { "list-style", ListStyle },
105 { "list-style-type", ListStyleType },
106 { "margin" , Margin },
107 { "margin-bottom", MarginBottom },
108 { "margin-left", MarginLeft },
109 { "margin-right", MarginRight },
110 { "margin-top", MarginTop },
111 { "max-height", MaximumHeight },
112 { "max-width", MaximumWidth },
113 { "min-height", MinimumHeight },
114 { "min-width", MinimumWidth },
115 { "outline", Outline },
116 { "outline-bottom-left-radius", OutlineBottomLeftRadius },
117 { "outline-bottom-right-radius", OutlineBottomRightRadius },
118 { "outline-color", OutlineColor },
119 { "outline-offset", OutlineOffset },
120 { "outline-radius", OutlineRadius },
121 { "outline-style", OutlineStyle },
122 { "outline-top-left-radius", OutlineTopLeftRadius },
123 { "outline-top-right-radius", OutlineTopRightRadius },
124 { "outline-width", OutlineWidth },
125 { "padding", Padding },
126 { "padding-bottom", PaddingBottom },
127 { "padding-left", PaddingLeft },
128 { "padding-right", PaddingRight },
129 { "padding-top", PaddingTop },
130 { "page-break-after", PageBreakAfter },
131 { "page-break-before", PageBreakBefore },
132 { "placeholder-text-color", QtPlaceHolderTextColor },
133 { "position", Position },
134 { "right", Right },
135 { "selection-background-color", QtSelectionBackground },
136 { "selection-color", QtSelectionForeground },
137 { "spacing", QtSpacing },
138 { "subcontrol-origin", QtOrigin },
139 { "subcontrol-position", QtPosition },
140 { "text-align", TextAlignment },
141 { "text-decoration", TextDecoration },
142 { "text-decoration-color", TextDecorationColor },
143 { "text-indent", TextIndent },
144 { "text-transform", TextTransform },
145 { "text-underline-style", TextUnderlineStyle },
146 { "top", Top },
147 { "vertical-align", VerticalAlignment },
148 { "white-space", Whitespace },
149 { "width", Width },
150 { "word-spacing", WordSpacing }
151};
152
154 { "active", Value_Active },
155 { "alternate-base", Value_AlternateBase },
156 { "always", Value_Always },
157 { "auto", Value_Auto },
158 { "base", Value_Base },
159 { "bold", Value_Bold },
160 { "bottom", Value_Bottom },
161 { "bright-text", Value_BrightText },
162 { "button", Value_Button },
163 { "button-text", Value_ButtonText },
164 { "center", Value_Center },
165 { "circle", Value_Circle },
166 { "dark", Value_Dark },
167 { "dashed", Value_Dashed },
168 { "decimal", Value_Decimal },
169 { "disabled", Value_Disabled },
170 { "disc", Value_Disc },
171 { "dot-dash", Value_DotDash },
172 { "dot-dot-dash", Value_DotDotDash },
173 { "dotted", Value_Dotted },
174 { "double", Value_Double },
175 { "groove", Value_Groove },
176 { "highlight", Value_Highlight },
177 { "highlighted-text", Value_HighlightedText },
178 { "inset", Value_Inset },
179 { "italic", Value_Italic },
180 { "large", Value_Large },
181 { "left", Value_Left },
182 { "light", Value_Light },
183 { "line-through", Value_LineThrough },
184 { "link", Value_Link },
185 { "link-visited", Value_LinkVisited },
186 { "lower-alpha", Value_LowerAlpha },
187 { "lower-roman", Value_LowerRoman },
188 { "lowercase", Value_Lowercase },
189 { "medium", Value_Medium },
190 { "mid", Value_Mid },
191 { "middle", Value_Middle },
192 { "midlight", Value_Midlight },
193 { "native", Value_Native },
194 { "none", Value_None },
195 { "normal", Value_Normal },
196 { "nowrap", Value_NoWrap },
197 { "oblique", Value_Oblique },
198 { "off", Value_Off },
199 { "on", Value_On },
200 { "outset", Value_Outset },
201 { "overline", Value_Overline },
202 { "pre", Value_Pre },
203 { "pre-line", Value_PreLine },
204 { "pre-wrap", Value_PreWrap },
205 { "ridge", Value_Ridge },
206 { "right", Value_Right },
207 { "selected", Value_Selected },
208 { "shadow", Value_Shadow },
209 { "small" , Value_Small },
210 { "small-caps", Value_SmallCaps },
211 { "solid", Value_Solid },
212 { "square", Value_Square },
213 { "sub", Value_Sub },
214 { "super", Value_Super },
215 { "text", Value_Text },
216 { "top", Value_Top },
217 { "transparent", Value_Transparent },
218 { "underline", Value_Underline },
219 { "upper-alpha", Value_UpperAlpha },
220 { "upper-roman", Value_UpperRoman },
221 { "uppercase", Value_Uppercase },
222 { "wave", Value_Wave },
223 { "window", Value_Window },
224 { "window-text", Value_WindowText },
225 { "x-large", Value_XLarge },
226 { "xx-large", Value_XXLarge }
227};
228
229//Map id to strings as they appears in the 'values' array above
230static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 50, 55, 35, 26, 71, 72, 25, 43, 5, 64, 48,
231 29, 59, 60, 27, 52, 62, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 51, 24, 46, 68, 37, 3, 2, 40, 63, 16,
232 11, 58, 14, 32, 65, 33, 66, 56, 67, 34, 70, 8, 28, 38, 12, 36, 61, 7, 9, 4, 69, 54, 22, 23, 30, 31,
233 1, 15, 0, 53, 45, 44 };
234
236{
237 if (type == KnownIdentifier) {
239 } else {
240 return variant.toString();
241 }
242}
243
244static const QCssKnownValue pseudos[NumPseudos - 1] = {
245 { "active", PseudoClass_Active },
246 { "adjoins-item", PseudoClass_Item },
247 { "alternate", PseudoClass_Alternate },
248 { "bottom", PseudoClass_Bottom },
249 { "checked", PseudoClass_Checked },
250 { "closable", PseudoClass_Closable },
251 { "closed", PseudoClass_Closed },
252 { "default", PseudoClass_Default },
253 { "disabled", PseudoClass_Disabled },
254 { "edit-focus", PseudoClass_EditFocus },
255 { "editable", PseudoClass_Editable },
256 { "enabled", PseudoClass_Enabled },
257 { "exclusive", PseudoClass_Exclusive },
258 { "first", PseudoClass_First },
259 { "flat", PseudoClass_Flat },
260 { "floatable", PseudoClass_Floatable },
261 { "focus", PseudoClass_Focus },
262 { "has-children", PseudoClass_Children },
263 { "has-siblings", PseudoClass_Sibling },
264 { "horizontal", PseudoClass_Horizontal },
265 { "hover", PseudoClass_Hover },
266 { "indeterminate" , PseudoClass_Indeterminate },
267 { "last", PseudoClass_Last },
268 { "left", PseudoClass_Left },
269 { "maximized", PseudoClass_Maximized },
270 { "middle", PseudoClass_Middle },
271 { "minimized", PseudoClass_Minimized },
272 { "movable", PseudoClass_Movable },
273 { "next-selected", PseudoClass_NextSelected },
274 { "no-frame", PseudoClass_Frameless },
275 { "non-exclusive", PseudoClass_NonExclusive },
276 { "off", PseudoClass_Unchecked },
277 { "on", PseudoClass_Checked },
278 { "only-one", PseudoClass_OnlyOne },
279 { "open", PseudoClass_Open },
280 { "pressed", PseudoClass_Pressed },
281 { "previous-selected", PseudoClass_PreviousSelected },
282 { "read-only", PseudoClass_ReadOnly },
283 { "right", PseudoClass_Right },
284 { "selected", PseudoClass_Selected },
285 { "top", PseudoClass_Top },
286 { "unchecked" , PseudoClass_Unchecked },
287 { "vertical", PseudoClass_Vertical },
288 { "window", PseudoClass_Window }
289};
290
292 { "border", Origin_Border },
293 { "content", Origin_Content },
294 { "margin", Origin_Margin }, // not in css
295 { "padding", Origin_Padding }
296};
297
299 { "no-repeat", Repeat_None },
300 { "repeat-x", Repeat_X },
301 { "repeat-xy", Repeat_XY },
302 { "repeat-y", Repeat_Y }
303};
304
306 { "repeat", TileMode_Repeat },
307 { "round", TileMode_Round },
308 { "stretch", TileMode_Stretch },
309};
310
312 { "absolute", PositionMode_Absolute },
313 { "fixed", PositionMode_Fixed },
314 { "relative", PositionMode_Relative },
315 { "static", PositionMode_Static }
316};
317
319 { "fixed", Attachment_Fixed },
320 { "scroll", Attachment_Scroll }
321};
322
324 { "background-color", StyleFeature_BackgroundColor },
325 { "background-gradient", StyleFeature_BackgroundGradient },
326 { "none", StyleFeature_None }
327};
328
329static bool operator<(const QString &name, const QCssKnownValue &prop)
330{
332}
333
334static bool operator<(const QCssKnownValue &prop, const QString &name)
335{
337}
338
339static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
340{
341 const QCssKnownValue *end = start + numValues - 1;
342 const QCssKnownValue *prop = std::lower_bound(start, end, name);
343 if ((prop == end) || (name < *prop))
344 return 0;
345 return prop->id;
346}
347
348static inline bool isInheritable(Property propertyId)
349{
350 switch (propertyId) {
351 case Font:
352 case FontKerning:
353 case FontFamily:
354 case FontSize:
355 case FontStyle:
356 case FontWeight:
357 case TextIndent:
358 case Whitespace:
359 case ListStyleType:
360 case ListStyle:
361 case TextAlignment:
362 case FontVariant:
363 case TextTransform:
364 case LineHeight:
365 case LetterSpacing:
366 case WordSpacing:
367 return true;
368 default:
369 break;
370 }
371 return false;
372}
373
375// Value Extractor
377: declarations(decls), adjustment(0), fontExtracted(false), pal(pal)
378{
379}
380
381LengthData ValueExtractor::lengthValue(const Value& v)
382{
383 const QString str = v.variant.toString();
386 data.unit = LengthData::None;
387 if (s.endsWith(u"px", Qt::CaseInsensitive))
388 data.unit = LengthData::Px;
389 else if (s.endsWith(u"ex", Qt::CaseInsensitive))
390 data.unit = LengthData::Ex;
391 else if (s.endsWith(u"em", Qt::CaseInsensitive))
392 data.unit = LengthData::Em;
393
394 if (data.unit != LengthData::None)
395 s.chop(2);
396
397 data.number = s.toDouble();
398 return data;
399}
400
401static int lengthValueFromData(const LengthData& data, const QFont& f)
402{
403 const int scale = (data.unit == LengthData::Ex ? QFontMetrics(f).xHeight()
404 : data.unit == LengthData::Em ? QFontMetrics(f).height() : 1);
405 // raised lower limit due to the implementation of qRound()
406 return qRound(qBound(double(INT_MIN) + 0.1, scale * data.number, double(INT_MAX)));
407}
408
409int ValueExtractor::lengthValue(const Declaration &decl)
410{
411 if (decl.d->parsed.isValid())
412 return lengthValueFromData(qvariant_cast<LengthData>(decl.d->parsed), f);
413 if (decl.d->values.size() < 1)
414 return 0;
415 LengthData data = lengthValue(decl.d->values.at(0));
416 decl.d->parsed = QVariant::fromValue<LengthData>(data);
417 return lengthValueFromData(data,f);
418}
419
421{
422 if (decl.d->parsed.isValid()) {
423 QList<QVariant> v = decl.d->parsed.toList();
424 Q_ASSERT(v.size() == 4);
425 for (int i = 0; i < 4; i++)
426 m[i] = lengthValueFromData(qvariant_cast<LengthData>(v.at(i)), f);
427 return;
428 }
429
430 LengthData datas[4];
431 int i;
432 for (i = 0; i < qMin(decl.d->values.size(), 4); i++)
433 datas[i] = lengthValue(decl.d->values[i]);
434
435 if (i == 0) {
437 datas[0] = datas[1] = datas[2] = datas[3] = zero;
438 } else if (i == 1) {
439 datas[3] = datas[2] = datas[1] = datas[0];
440 } else if (i == 2) {
441 datas[2] = datas[0];
442 datas[3] = datas[1];
443 } else if (i == 3) {
444 datas[3] = datas[1];
445 }
446
448 v.reserve(4);
449 for (i = 0; i < 4; i++) {
450 v += QVariant::fromValue<LengthData>(datas[i]);
451 m[i] = lengthValueFromData(datas[i], f);
452 }
453 decl.d->parsed = v;
454}
455
456bool ValueExtractor::extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh)
457{
458 extractFont();
459 bool hit = false;
460 for (int i = 0; i < declarations.size(); i++) {
461 const Declaration &decl = declarations.at(i);
462 switch (decl.d->propertyId) {
463 case Width: *w = lengthValue(decl); break;
464 case Height: *h = lengthValue(decl); break;
465 case MinimumWidth: *minw = lengthValue(decl); break;
466 case MinimumHeight: *minh = lengthValue(decl); break;
467 case MaximumWidth: *maxw = lengthValue(decl); break;
468 case MaximumHeight: *maxh = lengthValue(decl); break;
469 default: continue;
470 }
471 hit = true;
472 }
473
474 return hit;
475}
476
478 Qt::Alignment *position, QCss::PositionMode *mode, Qt::Alignment *textAlignment)
479{
480 extractFont();
481 bool hit = false;
482 for (int i = 0; i < declarations.size(); i++) {
483 const Declaration &decl = declarations.at(i);
484 switch (decl.d->propertyId) {
485 case Left: *left = lengthValue(decl); break;
486 case Top: *top = lengthValue(decl); break;
487 case Right: *right = lengthValue(decl); break;
488 case Bottom: *bottom = lengthValue(decl); break;
489 case QtOrigin: *origin = decl.originValue(); break;
490 case QtPosition: *position = decl.alignmentValue(); break;
491 case TextAlignment: *textAlignment = decl.alignmentValue(); break;
492 case Position: *mode = decl.positionValue(); break;
493 default: continue;
494 }
495 hit = true;
496 }
497
498 return hit;
499}
500
501bool ValueExtractor::extractBox(int *margins, int *paddings, int *spacing)
502{
503 extractFont();
504 bool hit = false;
505 for (int i = 0; i < declarations.size(); i++) {
506 const Declaration &decl = declarations.at(i);
507 switch (decl.d->propertyId) {
508 case PaddingLeft: paddings[LeftEdge] = lengthValue(decl); break;
509 case PaddingRight: paddings[RightEdge] = lengthValue(decl); break;
510 case PaddingTop: paddings[TopEdge] = lengthValue(decl); break;
511 case PaddingBottom: paddings[BottomEdge] = lengthValue(decl); break;
512 case Padding: lengthValues(decl, paddings); break;
513
514 case MarginLeft: margins[LeftEdge] = lengthValue(decl); break;
515 case MarginRight: margins[RightEdge] = lengthValue(decl); break;
516 case MarginTop: margins[TopEdge] = lengthValue(decl); break;
517 case MarginBottom: margins[BottomEdge] = lengthValue(decl); break;
518 case Margin: lengthValues(decl, margins); break;
519 case QtSpacing: if (spacing) *spacing = lengthValue(decl); break;
520
521 default: continue;
522 }
523 hit = true;
524 }
525
526 return hit;
527}
528
530{
531 int features = StyleFeature_None;
532 for (int i = 0; i < declarations.size(); i++) {
533 const Declaration &decl = declarations.at(i);
534 if (decl.d->propertyId == QtStyleFeatures)
535 features = decl.styleFeaturesValue();
536 }
537 return features;
538}
539
540QSize ValueExtractor::sizeValue(const Declaration &decl)
541{
542 if (decl.d->parsed.isValid()) {
543 QList<QVariant> v = decl.d->parsed.toList();
544 return QSize(lengthValueFromData(qvariant_cast<LengthData>(v.at(0)), f),
545 lengthValueFromData(qvariant_cast<LengthData>(v.at(1)), f));
546 }
547
548 LengthData x[2] = { {0, LengthData::None }, {0, LengthData::None} };
549 if (decl.d->values.size() > 0)
550 x[0] = lengthValue(decl.d->values.at(0));
551 if (decl.d->values.size() > 1)
552 x[1] = lengthValue(decl.d->values.at(1));
553 else
554 x[1] = x[0];
556 v << QVariant::fromValue<LengthData>(x[0]) << QVariant::fromValue<LengthData>(x[1]);
557 decl.d->parsed = v;
559}
560
561void ValueExtractor::sizeValues(const Declaration &decl, QSize *radii)
562{
563 radii[0] = sizeValue(decl);
564 for (int i = 1; i < 4; i++)
565 radii[i] = radii[0];
566}
567
569 QSize *radii)
570{
571 extractFont();
572 bool hit = false;
573 for (int i = 0; i < declarations.size(); i++) {
574 const Declaration &decl = declarations.at(i);
575 switch (decl.d->propertyId) {
576 case BorderLeftWidth: borders[LeftEdge] = lengthValue(decl); break;
577 case BorderRightWidth: borders[RightEdge] = lengthValue(decl); break;
578 case BorderTopWidth: borders[TopEdge] = lengthValue(decl); break;
579 case BorderBottomWidth: borders[BottomEdge] = lengthValue(decl); break;
580 case BorderWidth: lengthValues(decl, borders); break;
581
582 case BorderLeftColor: colors[LeftEdge] = decl.brushValue(pal); break;
583 case BorderRightColor: colors[RightEdge] = decl.brushValue(pal); break;
584 case BorderTopColor: colors[TopEdge] = decl.brushValue(pal); break;
585 case BorderBottomColor: colors[BottomEdge] = decl.brushValue(pal); break;
586 case BorderColor: decl.brushValues(colors, pal); break;
587
588 case BorderTopStyle: styles[TopEdge] = decl.styleValue(); break;
589 case BorderBottomStyle: styles[BottomEdge] = decl.styleValue(); break;
590 case BorderLeftStyle: styles[LeftEdge] = decl.styleValue(); break;
591 case BorderRightStyle: styles[RightEdge] = decl.styleValue(); break;
592 case BorderStyles: decl.styleValues(styles); break;
593
594 case BorderTopLeftRadius: radii[0] = sizeValue(decl); break;
595 case BorderTopRightRadius: radii[1] = sizeValue(decl); break;
596 case BorderBottomLeftRadius: radii[2] = sizeValue(decl); break;
597 case BorderBottomRightRadius: radii[3] = sizeValue(decl); break;
598 case BorderRadius: sizeValues(decl, radii); break;
599
600 case BorderLeft:
601 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
602 break;
603 case BorderTop:
604 borderValue(decl, &borders[TopEdge], &styles[TopEdge], &colors[TopEdge]);
605 break;
606 case BorderRight:
607 borderValue(decl, &borders[RightEdge], &styles[RightEdge], &colors[RightEdge]);
608 break;
609 case BorderBottom:
610 borderValue(decl, &borders[BottomEdge], &styles[BottomEdge], &colors[BottomEdge]);
611 break;
612 case Border:
613 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
614 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];
615 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];
617 break;
618
619 default: continue;
620 }
621 hit = true;
622 }
623
624 return hit;
625}
626
628 QSize *radii, int *offsets)
629{
630 extractFont();
631 bool hit = false;
632 for (int i = 0; i < declarations.size(); i++) {
633 const Declaration &decl = declarations.at(i);
634 switch (decl.d->propertyId) {
635 case OutlineWidth: lengthValues(decl, borders); break;
636 case OutlineColor: decl.brushValues(colors, pal); break;
637 case OutlineStyle: decl.styleValues(styles); break;
638
639 case OutlineTopLeftRadius: radii[0] = sizeValue(decl); break;
640 case OutlineTopRightRadius: radii[1] = sizeValue(decl); break;
641 case OutlineBottomLeftRadius: radii[2] = sizeValue(decl); break;
642 case OutlineBottomRightRadius: radii[3] = sizeValue(decl); break;
643 case OutlineRadius: sizeValues(decl, radii); break;
644 case OutlineOffset: lengthValues(decl, offsets); break;
645
646 case Outline:
647 borderValue(decl, &borders[LeftEdge], &styles[LeftEdge], &colors[LeftEdge]);
648 borders[TopEdge] = borders[RightEdge] = borders[BottomEdge] = borders[LeftEdge];
649 styles[TopEdge] = styles[RightEdge] = styles[BottomEdge] = styles[LeftEdge];
651 break;
652
653 default: continue;
654 }
655 hit = true;
656 }
657
658 return hit;
659}
660
661static Qt::Alignment parseAlignment(const QCss::Value *values, int count)
662{
663 Qt::Alignment a[2] = { { }, { } };
664 for (int i = 0; i < qMin(2, count); i++) {
666 break;
667 switch (values[i].variant.toInt()) {
668 case Value_Left: a[i] = Qt::AlignLeft; break;
669 case Value_Right: a[i] = Qt::AlignRight; break;
670 case Value_Top: a[i] = Qt::AlignTop; break;
671 case Value_Bottom: a[i] = Qt::AlignBottom; break;
672 case Value_Center: a[i] = Qt::AlignCenter; break;
673 default: break;
674 }
675 }
676
677 if (a[0] == Qt::AlignCenter && a[1] != 0 && a[1] != Qt::AlignCenter)
679 if ((a[1] == 0 || a[1] == Qt::AlignCenter) && a[0] != Qt::AlignCenter)
681 return a[0] | a[1];
682}
683
685{
686 if (v.type == Value::Identifier || v.type == Value::String) {
687 v.variant.convert(QMetaType::fromType<QColor>());
689 }
690
691 if (v.type == Value::Color)
692 return qvariant_cast<QColor>(v.variant);
693
694 if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent)
695 return QColor(Qt::transparent);
696
697 if (v.type != Value::Function)
698 return ColorData();
699
700 QStringList lst = v.variant.toStringList();
701 if (lst.size() != 2)
702 return ColorData();
703
704 const QString &identifier = lst.at(0);
705 if ((identifier.compare("palette"_L1, Qt::CaseInsensitive)) == 0) {
706 int role = findKnownValue(lst.at(1).trimmed(), values, NumKnownValues);
707 if (role >= Value_FirstColorRole && role <= Value_LastColorRole)
709
710 return ColorData();
711 }
712
713 const bool rgb = identifier.startsWith("rgb"_L1);
714 const bool hsv = !rgb && identifier.startsWith("hsv"_L1);
715 const bool hsl = !rgb && !hsv && identifier.startsWith("hsl"_L1);
716
717 if (!rgb && !hsv && !hsl)
718 return ColorData();
719
720 const bool hasAlpha = identifier.size() == 4 && identifier.at(3) == u'a';
721 if (identifier.size() > 3 && !hasAlpha)
722 return ColorData();
723
724 Parser p(lst.at(1));
725 if (!p.testExpr())
726 return ColorData();
727
728 QList<QCss::Value> colorDigits;
729 if (!p.parseExpr(&colorDigits))
730 return ColorData();
731 const int tokenCount = colorDigits.size();
732
733 for (int i = 0; i < qMin(tokenCount, 7); i += 2) {
734 if (colorDigits.at(i).type == Value::Percentage) {
735 const qreal maxRange = (rgb || i != 0) ? 255. : 359.;
736 colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (maxRange / 100.);
737 colorDigits[i].type = Value::Number;
738 } else if (colorDigits.at(i).type != Value::Number) {
739 return ColorData();
740 }
741 }
742
743
744 if (tokenCount < 5)
745 return ColorData();
746
747 if (hasAlpha && tokenCount != 7) {
748 qWarning("QCssParser::parseColorValue: Specified color with alpha value but no alpha given: '%s'", qPrintable(lst.join(u' ')));
749 return ColorData();
750 }
751 if (!hasAlpha && tokenCount != 5) {
752 qWarning("QCssParser::parseColorValue: Specified color without alpha value but alpha given: '%s'", qPrintable(lst.join(u' ')));
753 return ColorData();
754 }
755
756 int v1 = colorDigits.at(0).variant.toInt();
757 int v2 = colorDigits.at(2).variant.toInt();
758 int v3 = colorDigits.at(4).variant.toInt();
759 int alpha = 255;
760 if (tokenCount == 7) {
761 int alphaValue = colorDigits.at(6).variant.toInt();
762 if (alphaValue <= 1)
763 alpha = colorDigits.at(6).variant.toReal() * 255.;
764 else
765 alpha = alphaValue;
766 }
767
768 if (rgb)
769 return QColor::fromRgb(v1, v2, v3, alpha);
770 if (hsv)
771 return QColor::fromHsv(v1, v2, v3, alpha);
772 return QColor::fromHsl(v1, v2, v3, alpha);
773}
774
775static QColor colorFromData(const ColorData& c, const QPalette &pal)
776{
777 if (c.type == ColorData::Color) {
778 return c.color;
779 } else if (c.type == ColorData::Role) {
780 return pal.color(c.role);
781 }
782 return QColor();
783}
784
786{
788 if (c.type == ColorData::Color) {
789 return QBrush(c.color);
790 } else if (c.type == ColorData::Role) {
791 return c.role;
792 }
793
794 if (v.type != Value::Function)
795 return BrushData();
796
797 QStringList lst = v.variant.toStringList();
798 if (lst.size() != 2)
799 return BrushData();
800
801 QStringList gradFuncs;
802 gradFuncs << "qlineargradient"_L1 << "qradialgradient"_L1 << "qconicalgradient"_L1 << "qgradient"_L1;
803 int gradType = -1;
804
805 if ((gradType = gradFuncs.indexOf(lst.at(0).toLower())) == -1)
806 return BrushData();
807
810
811 int spread = -1;
812 QStringList spreads;
813 spreads << "pad"_L1 << "reflect"_L1 << "repeat"_L1;
814
815 bool dependsOnThePalette = false;
816 Parser parser(lst.at(1));
817 while (parser.hasNext()) {
818 parser.skipSpace();
819 if (!parser.test(IDENT))
820 return BrushData();
821 QString attr = parser.lexem();
822 parser.skipSpace();
823 if (!parser.test(COLON))
824 return BrushData();
825 parser.skipSpace();
826 if (attr.compare("stop"_L1, Qt::CaseInsensitive) == 0) {
827 QCss::Value stop, color;
828 parser.next();
829 if (!parser.parseTerm(&stop)) return BrushData();
830 parser.skipSpace();
831 parser.next();
832 if (!parser.parseTerm(&color)) return BrushData();
834 if (cd.type == ColorData::Role)
835 dependsOnThePalette = true;
836 stops.append(QGradientStop(stop.variant.toReal(), colorFromData(cd, pal)));
837 } else {
838 parser.next();
840 (void)parser.parseTerm(&value);
841 if (attr.compare("spread"_L1, Qt::CaseInsensitive) == 0) {
842 spread = spreads.indexOf(value.variant.toString());
843 } else {
844 vars[attr] = value.variant.toReal();
845 }
846 }
847 parser.skipSpace();
848 (void)parser.test(COMMA);
849 }
850
851 if (gradType == 0) {
852 QLinearGradient lg(vars.value("x1"_L1), vars.value("y1"_L1),
853 vars.value("x2"_L1), vars.value("y2"_L1));
855 lg.setStops(stops);
856 if (spread != -1)
857 lg.setSpread(QGradient::Spread(spread));
858 BrushData bd = QBrush(lg);
859 if (dependsOnThePalette)
861 return bd;
862 }
863
864 if (gradType == 1) {
865 QRadialGradient rg(vars.value("cx"_L1), vars.value("cy"_L1),
866 vars.value("radius"_L1), vars.value("fx"_L1),
867 vars.value("fy"_L1));
869 rg.setStops(stops);
870 if (spread != -1)
871 rg.setSpread(QGradient::Spread(spread));
872 BrushData bd = QBrush(rg);
873 if (dependsOnThePalette)
875 return bd;
876 }
877
878 if (gradType == 2) {
879 QConicalGradient cg(vars.value("cx"_L1), vars.value("cy"_L1), vars.value("angle"_L1));
881 cg.setStops(stops);
882 if (spread != -1)
883 cg.setSpread(QGradient::Spread(spread));
884 BrushData bd = QBrush(cg);
885 if (dependsOnThePalette)
887 return bd;
888 }
889
890 return BrushData();
891}
892
893static QBrush brushFromData(const BrushData& c, const QPalette &pal)
894{
895 if (c.type == BrushData::Role) {
896 return pal.color(c.role);
897 } else {
898 return c.brush;
899 }
900}
901
903{
904 if (v.type == Value::KnownIdentifier) {
905 switch (v.variant.toInt()) {
906 case Value_None:
907 return BorderStyle_None;
908 case Value_Dotted:
909 return BorderStyle_Dotted;
910 case Value_Dashed:
911 return BorderStyle_Dashed;
912 case Value_Solid:
913 return BorderStyle_Solid;
914 case Value_Double:
915 return BorderStyle_Double;
916 case Value_DotDash:
917 return BorderStyle_DotDash;
918 case Value_DotDotDash:
920 case Value_Groove:
921 return BorderStyle_Groove;
922 case Value_Ridge:
923 return BorderStyle_Ridge;
924 case Value_Inset:
925 return BorderStyle_Inset;
926 case Value_Outset:
927 return BorderStyle_Outset;
928 case Value_Native:
929 return BorderStyle_Native;
930 default:
931 break;
932 }
933 }
934
935 return BorderStyle_Unknown;
936}
937
938void ValueExtractor::borderValue(const Declaration &decl, int *width, QCss::BorderStyle *style, QBrush *color)
939{
940 if (decl.d->parsed.isValid()) {
941 BorderData data = qvariant_cast<BorderData>(decl.d->parsed);
942 *width = lengthValueFromData(data.width, f);
943 *style = data.style;
944 *color = data.color.type != BrushData::Invalid ? brushFromData(data.color, pal) : QBrush(QColor());
945 return;
946 }
947
948 *width = 0;
949 *style = BorderStyle_None;
950 *color = QColor();
951
952 if (decl.d->values.isEmpty())
953 return;
954
956 data.width.number = 0;
957 data.width.unit = LengthData::None;
958 data.style = BorderStyle_None;
959
960 int i = 0;
961 if (decl.d->values.at(i).type == Value::Length || decl.d->values.at(i).type == Value::Number) {
962 data.width = lengthValue(decl.d->values.at(i));
963 *width = lengthValueFromData(data.width, f);
964 if (++i >= decl.d->values.size()) {
965 decl.d->parsed = QVariant::fromValue<BorderData>(data);
966 return;
967 }
968 }
969
970 data.style = parseStyleValue(decl.d->values.at(i));
971 if (data.style != BorderStyle_Unknown) {
972 *style = data.style;
973 if (++i >= decl.d->values.size()) {
974 decl.d->parsed = QVariant::fromValue<BorderData>(data);
975 return;
976 }
977 } else {
978 data.style = BorderStyle_None;
979 }
980
981 data.color = parseBrushValue(decl.d->values.at(i), pal);
982 *color = brushFromData(data.color, pal);
983 if (data.color.type != BrushData::DependsOnThePalette)
984 decl.d->parsed = QVariant::fromValue<BorderData>(data);
985}
986
988{
989 *brush = BrushData();
990 *image = QString();
991 *repeat = Repeat_XY;
993
994 for (int i = 0; i < values.size(); ++i) {
995 const QCss::Value &v = values.at(i);
996 if (v.type == Value::Uri) {
997 *image = v.variant.toString();
998 continue;
999 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_None) {
1000 *image = QString();
1001 continue;
1002 } else if (v.type == Value::KnownIdentifier && v.variant.toInt() == Value_Transparent) {
1004 }
1005
1006 Repeat repeatAttempt = static_cast<Repeat>(findKnownValue(v.variant.toString(),
1008 if (repeatAttempt != Repeat_Unknown) {
1009 *repeat = repeatAttempt;
1010 continue;
1011 }
1012
1013 if (v.type == Value::KnownIdentifier) {
1014 const int start = i;
1015 int count = 1;
1016 if (i < values.size() - 1
1017 && values.at(i + 1).type == Value::KnownIdentifier) {
1018 ++i;
1019 ++count;
1020 }
1021 Qt::Alignment a = parseAlignment(values.constData() + start, count);
1022 if (int(a) != 0) {
1023 *alignment = a;
1024 continue;
1025 }
1026 i -= count - 1;
1027 }
1028
1029 *brush = parseBrushValue(v, pal);
1030 }
1031}
1032
1034 Qt::Alignment *alignment, Origin *origin, Attachment *attachment,
1035 Origin *clip)
1036{
1037 bool hit = false;
1038 for (int i = 0; i < declarations.size(); ++i) {
1039 const Declaration &decl = declarations.at(i);
1040 if (decl.d->values.isEmpty())
1041 continue;
1042 const QCss::Value &val = decl.d->values.at(0);
1043 switch (decl.d->propertyId) {
1044 case BackgroundColor:
1045 *brush = decl.brushValue();
1046 break;
1047 case BackgroundImage:
1048 if (val.type == Value::Uri)
1049 *image = val.variant.toString();
1050 break;
1051 case BackgroundRepeat:
1052 if (decl.d->parsed.isValid()) {
1053 *repeat = static_cast<Repeat>(decl.d->parsed.toInt());
1054 } else {
1055 *repeat = static_cast<Repeat>(findKnownValue(val.variant.toString(),
1057 decl.d->parsed = *repeat;
1058 }
1059 break;
1060 case BackgroundPosition:
1061 *alignment = decl.alignmentValue();
1062 break;
1063 case BackgroundOrigin:
1064 *origin = decl.originValue();
1065 break;
1066 case BackgroundClip:
1067 *clip = decl.originValue();
1068 break;
1069 case Background:
1070 if (decl.d->parsed.isValid()) {
1071 BackgroundData data = qvariant_cast<BackgroundData>(decl.d->parsed);
1072 *brush = brushFromData(data.brush, pal);
1073 *image = data.image;
1074 *repeat = data.repeat;
1075 *alignment = data.alignment;
1076 } else {
1077 BrushData brushData;
1078 parseShorthandBackgroundProperty(decl.d->values, &brushData, image, repeat, alignment, pal);
1079 *brush = brushFromData(brushData, pal);
1080 if (brushData.type != BrushData::DependsOnThePalette) {
1081 BackgroundData data = { brushData, *image, *repeat, *alignment };
1082 decl.d->parsed = QVariant::fromValue<BackgroundData>(data);
1083 }
1084 }
1085 break;
1087 *attachment = decl.attachmentValue();
1088 break;
1089 default: continue;
1090 }
1091 hit = true;
1092 }
1093 return hit;
1094}
1095
1096static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment)
1097{
1098 if (value.type == Value::KnownIdentifier) {
1099 bool valid = true;
1100 switch (value.variant.toInt()) {
1101 case Value_Small: *fontSizeAdjustment = -1; break;
1102 case Value_Medium: *fontSizeAdjustment = 0; break;
1103 case Value_Large: *fontSizeAdjustment = 1; break;
1104 case Value_XLarge: *fontSizeAdjustment = 2; break;
1105 case Value_XXLarge: *fontSizeAdjustment = 3; break;
1106 default: valid = false; break;
1107 }
1108 return valid;
1109 }
1110 if (value.type != Value::Length)
1111 return false;
1112
1113 bool valid = false;
1114 QString s = value.variant.toString();
1115 if (s.endsWith("pt"_L1, Qt::CaseInsensitive)) {
1116 s.chop(2);
1117 value.variant = s;
1118 if (value.variant.convert(QMetaType::fromType<qreal>())) {
1119 font->setPointSizeF(qBound(qreal(0), value.variant.toReal(), qreal(1 << 24) - 1));
1120 valid = true;
1121 }
1122 } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1123 s.chop(2);
1124 value.variant = s;
1125 if (value.variant.convert(QMetaType::fromType<int>())) {
1126 font->setPixelSize(qBound(0, value.variant.toInt(), (1 << 24) - 1));
1127 valid = true;
1128 }
1129 }
1130 return valid;
1131}
1132
1134{
1135 if (value.type != Value::KnownIdentifier)
1136 return false ;
1137 switch (value.variant.toInt()) {
1138 case Value_Normal: font->setStyle(QFont::StyleNormal); return true;
1139 case Value_Italic: font->setStyle(QFont::StyleItalic); return true;
1140 case Value_Oblique: font->setStyle(QFont::StyleOblique); return true;
1141 default: break;
1142 }
1143 return false;
1144}
1145
1147{
1148 if (value.type != Value::KnownIdentifier)
1149 return false ;
1150 switch (value.variant.toInt()) {
1151 case Value_Normal: font->setKerning(true); return true;
1152 case Value_None: font->setKerning(false); return true;
1153 case Value_Auto: return true;
1154 default: break;
1155 }
1156 return false;
1157}
1158
1160{
1161 if (value.type == Value::KnownIdentifier) {
1162 switch (value.variant.toInt()) {
1163 case Value_Normal: font->setWeight(QFont::Normal); return true;
1164 case Value_Bold: font->setWeight(QFont::Bold); return true;
1165 default: break;
1166 }
1167 return false;
1168 }
1169 if (value.type != Value::Number)
1170 return false;
1171 // .toInt() would call qRound64() and might overflow the long long there
1172 font->setWeight(QFont::Weight(qRound(qBound(0.0, value.variant.toDouble(), 1001.0))));
1173 return true;
1174}
1175
1182{
1183 QString family;
1184 QStringList families;
1185 bool shouldAddSpace = false;
1186 for (int i = start; i < values.size(); ++i) {
1187 const QCss::Value &v = values.at(i);
1188 if (v.type == Value::TermOperatorComma) {
1189 families << family;
1190 family.clear();
1191 shouldAddSpace = false;
1192 continue;
1193 }
1194 const QString str = v.variant.toString();
1195 if (str.isEmpty())
1196 break;
1197 if (shouldAddSpace)
1198 family += u' ';
1199 family += str;
1200 shouldAddSpace = true;
1201 }
1202 if (!family.isEmpty())
1203 families << family;
1204 if (families.isEmpty())
1205 return false;
1206 font->setFamilies(families);
1207 return true;
1208}
1209
1211{
1212 for (int i = 0; i < values.size(); ++i) {
1213 if (values.at(i).type != Value::KnownIdentifier)
1214 continue;
1215 switch (values.at(i).variant.toInt()) {
1216 case Value_Underline: font->setUnderline(true); break;
1217 case Value_Overline: font->setOverline(true); break;
1218 case Value_LineThrough: font->setStrikeOut(true); break;
1219 case Value_None:
1220 font->setUnderline(false);
1221 font->setOverline(false);
1222 font->setStrikeOut(false);
1223 break;
1224 default: break;
1225 }
1226 }
1227}
1228
1230{
1231 QString s = value.variant.toString();
1232 qreal val;
1233 bool ok = false;
1234 if (s.endsWith("em"_L1, Qt::CaseInsensitive)) {
1235 s.chop(2);
1236 val = s.toDouble(&ok);
1237 if (ok)
1239 } else if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1240 s.chop(2);
1241 val = s.toDouble(&ok);
1242 if (ok)
1244 }
1245}
1246
1248{
1249 QString s = value.variant.toString();
1250 if (s.endsWith("px"_L1, Qt::CaseInsensitive)) {
1251 s.chop(2);
1252 qreal val;
1253 bool ok = false;
1254 val = s.toDouble(&ok);
1255 if (ok)
1257 }
1258}
1259
1260static void parseShorthandFontProperty(const QList<QCss::Value> &values, QFont *font, int *fontSizeAdjustment)
1261{
1264 *fontSizeAdjustment = -255;
1265
1266 int i = 0;
1267 while (i < values.size()) {
1270 ++i;
1271 else
1272 break;
1273 }
1274
1275 if (i < values.size()) {
1276 setFontSizeFromValue(values.at(i), font, fontSizeAdjustment);
1277 ++i;
1278 }
1279
1280 if (i < values.size()) {
1282 }
1283}
1284
1286{
1287 if (value.type == Value::KnownIdentifier) {
1288 switch (value.variant.toInt()) {
1291 default: break;
1292 }
1293 }
1294}
1295
1297{
1298 if (value.type == Value::KnownIdentifier) {
1299 switch (value.variant.toInt()) {
1303 default: break;
1304 }
1305 }
1306}
1307
1308bool ValueExtractor::extractFont(QFont *font, int *fontSizeAdjustment)
1309{
1310 if (fontExtracted) {
1311 *font = f;
1312 *fontSizeAdjustment = adjustment;
1313 return fontExtracted == 1;
1314 }
1315
1316 bool hit = false;
1317 for (int i = 0; i < declarations.size(); ++i) {
1318 const Declaration &decl = declarations.at(i);
1319 if (decl.d->values.isEmpty())
1320 continue;
1321 const QCss::Value &val = decl.d->values.at(0);
1322 switch (decl.d->propertyId) {
1323 case FontSize: setFontSizeFromValue(val, font, fontSizeAdjustment); break;
1324 case FontStyle: setFontStyleFromValue(val, font); break;
1326 case FontFamily: setFontFamilyFromValues(decl.d->values, font); break;
1328 case TextDecoration: setTextDecorationFromValues(decl.d->values, font); break;
1329 case Font: parseShorthandFontProperty(decl.d->values, font, fontSizeAdjustment); break;
1334 default: continue;
1335 }
1336 hit = true;
1337 }
1338
1339 f = *font;
1340 adjustment = *fontSizeAdjustment;
1341 fontExtracted = hit ? 1 : 2;
1342 return hit;
1343}
1344
1346 QBrush *selectedForeground,
1347 QBrush *selectedBackground,
1348 QBrush *alternateBackground,
1349 QBrush *placeHolderTextForeground,
1350 QBrush *accentColor)
1351{
1352 bool hit = false;
1353 for (int i = 0; i < declarations.size(); ++i) {
1354 const Declaration &decl = declarations.at(i);
1355 switch (decl.d->propertyId) {
1356 case Color: *foreground = decl.brushValue(pal); break;
1357 case QtSelectionForeground: *selectedForeground = decl.brushValue(pal); break;
1358 case QtSelectionBackground: *selectedBackground = decl.brushValue(pal); break;
1359 case QtAlternateBackground: *alternateBackground = decl.brushValue(pal); break;
1360 case QtPlaceHolderTextColor: *placeHolderTextForeground = decl.brushValue(pal); break;
1361 case QtAccentColor: *accentColor = decl.brushValue(pal); break;
1362 default: continue;
1363 }
1364 hit = true;
1365 }
1366 return hit;
1367}
1368
1369void ValueExtractor::extractFont()
1370{
1371 if (fontExtracted)
1372 return;
1373 int dummy = -255;
1374 extractFont(&f, &dummy);
1375}
1376
1378{
1379 bool hit = false;
1380 for (int i = 0; i < declarations.size(); ++i) {
1381 const Declaration &decl = declarations.at(i);
1382 switch (decl.d->propertyId) {
1383 case QtImage:
1384 *icon = decl.iconValue();
1385 if (decl.d->values.size() > 0 && decl.d->values.at(0).type == Value::Uri) {
1386 // try to pull just the size from the image...
1387 QImageReader imageReader(decl.d->values.at(0).variant.toString());
1388 if ((*size = imageReader.size()).isNull()) {
1389 // but we'll have to load the whole image if the
1390 // format doesn't support just reading the size
1391 *size = imageReader.read().size();
1392 }
1393 }
1394 break;
1395 case QtImageAlignment: *a = decl.alignmentValue(); break;
1396 default: continue;
1397 }
1398 hit = true;
1399 }
1400 return hit;
1401}
1402
1404{
1405 // Find last declaration that specifies an icon
1406 const auto declaration = std::find_if(
1407 declarations.rbegin(), declarations.rend(),
1408 [](const Declaration &decl) { return decl.d->propertyId == QtIcon; });
1409 if (declaration == declarations.rend())
1410 return false;
1411
1412 *icon = declaration->iconValue();
1413
1414 // If the value contains a URI, try to get the size of the icon
1415 if (declaration->d->values.isEmpty())
1416 return true;
1417
1418 const auto &propertyValue = declaration->d->values.constFirst();
1419 if (propertyValue.type != Value::Uri)
1420 return true;
1421
1422 // First try to read just the size from the image without loading it
1423 const QString url(propertyValue.variant.toString());
1424 QImageReader imageReader(url);
1425 *size = imageReader.size();
1426 if (!size->isNull())
1427 return true;
1428
1429 // Get the size by loading the image instead
1430 *size = imageReader.read().size();
1431 return true;
1432}
1433
1435// Declaration
1437{
1438 if (d->values.size() != 1)
1439 return QColor();
1440
1441 if (d->parsed.isValid()) {
1442 switch (d->parsed.typeId()) {
1443 case qMetaTypeId<QColor>():
1444 return qvariant_cast<QColor>(d->parsed);
1445 case qMetaTypeId<int>():
1446 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));
1447 case qMetaTypeId<QList<QVariant>>():
1448 if (d->parsed.toList().size() == 1) {
1449 auto parsedList = d->parsed.toList();
1450 const auto &value = parsedList.at(0);
1451 return qvariant_cast<QColor>(value);
1452 }
1453 break;
1454 }
1455 }
1456
1457 ColorData color = parseColorValue(d->values.at(0));
1458 if (color.type == ColorData::Role) {
1459 d->parsed = QVariant::fromValue<int>(color.role);
1460 return pal.color((QPalette::ColorRole)(color.role));
1461 } else {
1462 d->parsed = QVariant::fromValue<QColor>(color.color);
1463 return color.color;
1464 }
1465}
1466
1468{
1469 if (d->values.size() != 1)
1470 return QBrush();
1471
1472 if (d->parsed.isValid()) {
1473 if (d->parsed.userType() == QMetaType::QBrush)
1474 return qvariant_cast<QBrush>(d->parsed);
1475 if (d->parsed.userType() == QMetaType::Int)
1476 return pal.color((QPalette::ColorRole)(d->parsed.toInt()));
1477 }
1478
1479 BrushData data = parseBrushValue(d->values.at(0), pal);
1480
1481 if (data.type == BrushData::Role) {
1482 d->parsed = QVariant::fromValue<int>(data.role);
1483 return pal.color((QPalette::ColorRole)(data.role));
1484 } else {
1486 d->parsed = QVariant::fromValue<QBrush>(data.brush);
1487 return data.brush;
1488 }
1489}
1490
1492{
1493 int needParse = 0x1f; // bits 0..3 say if we should parse the corresponding value.
1494 // the bit 4 say we need to update d->parsed
1495 int i = 0;
1496 if (d->parsed.isValid()) {
1497 needParse = 0;
1498 Q_ASSERT(d->parsed.metaType() == QMetaType::fromType<QList<QVariant>>());
1499 QList<QVariant> v = d->parsed.toList();
1500 for (i = 0; i < qMin(v.size(), 4); i++) {
1501 if (v.at(i).userType() == QMetaType::QBrush) {
1502 c[i] = qvariant_cast<QBrush>(v.at(i));
1503 } else if (v.at(i).userType() == QMetaType::Int) {
1504 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));
1505 } else {
1506 needParse |= (1<<i);
1507 }
1508 }
1509 }
1510 if (needParse != 0) {
1512 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1513 if (!(needParse & (1<<i)))
1514 continue;
1515 BrushData data = parseBrushValue(d->values.at(i), pal);
1516 if (data.type == BrushData::Role) {
1517 v += QVariant::fromValue<int>(data.role);
1518 c[i] = pal.color((QPalette::ColorRole)(data.role));
1519 } else {
1521 v += QVariant::fromValue<QBrush>(data.brush);
1522 } else {
1523 v += QVariant();
1524 }
1525 c[i] = data.brush;
1526 }
1527 }
1528 if (needParse & 0x10)
1529 d->parsed = v;
1530 }
1531 if (i == 0) c[0] = c[1] = c[2] = c[3] = QBrush();
1532 else if (i == 1) c[3] = c[2] = c[1] = c[0];
1533 else if (i == 2) c[2] = c[0], c[3] = c[1];
1534 else if (i == 3) c[3] = c[1];
1535}
1536
1537bool Declaration::realValue(qreal *real, const char *unit) const
1538{
1539 if (d->values.size() != 1)
1540 return false;
1541 const Value &v = d->values.at(0);
1542 if (unit && v.type != Value::Length)
1543 return false;
1544 const QString str = v.variant.toString();
1545 QStringView s(str);
1546 if (unit) {
1547 const QLatin1StringView unitStr(unit);
1548 if (!s.endsWith(unitStr, Qt::CaseInsensitive))
1549 return false;
1550 s.chop(unitStr.size());
1551 }
1552 bool ok = false;
1553 qreal val = s.toDouble(&ok);
1554 if (ok)
1555 *real = val;
1556 return ok;
1557}
1558
1559static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
1560{
1561 if (unit && v.type != Value::Length)
1562 return false;
1563 const QString str = v.variant.toString();
1564 QStringView s(str);
1565 if (unit) {
1566 const QLatin1StringView unitStr(unit);
1567 if (!s.endsWith(unitStr, Qt::CaseInsensitive))
1568 return false;
1569 s.chop(unitStr.size());
1570 }
1571 bool ok = false;
1572 int val = s.toInt(&ok);
1573 if (ok)
1574 *i = val;
1575 return ok;
1576}
1577
1578bool Declaration::intValue(int *i, const char *unit) const
1579{
1580 if (d->values.size() != 1)
1581 return false;
1582 return intValueHelper(d->values.at(0), i, unit);
1583}
1584
1586{
1587 if (d->parsed.isValid())
1588 return qvariant_cast<QSize>(d->parsed);
1589
1590 int x[2] = { 0, 0 };
1591 const int count = d->values.size();
1592 for (int i = 0; i < count; ++i) {
1593 if (i > 1) {
1594 qWarning("QCssParser::sizeValue: Too many values provided");
1595 break;
1596 }
1597 const auto &value = d->values.at(i);
1598 const QString valueString = value.variant.toString();
1599 if (valueString.endsWith(u"pt", Qt::CaseInsensitive)) {
1600 intValueHelper(value, &x[i], "pt");
1601 // according to https://www.w3.org/TR/css3-values/#absolute-lengths
1602 // 1pt = 1/72th of 1 inch, and 1px = 1/96th of 1 inch
1603 x[i] = (x[i] * 72) / 96;
1604 } else {
1605 // by default we use 'px'
1606 intValueHelper(value, &x[i], "px");
1607 }
1608 }
1609 if (count == 1)
1610 x[1] = x[0];
1611 QSize size(x[0], x[1]);
1612 d->parsed = QVariant::fromValue<QSize>(size);
1613 return size;
1614}
1615
1617{
1618 if (d->values.size() != 1)
1619 return QRect();
1620
1621 if (d->parsed.isValid())
1622 return qvariant_cast<QRect>(d->parsed);
1623
1624 const QCss::Value &v = d->values.at(0);
1625 if (v.type != Value::Function)
1626 return QRect();
1627 const QStringList func = v.variant.toStringList();
1628 if (func.size() != 2 || func.at(0).compare("rect"_L1) != 0)
1629 return QRect();
1630 const auto args = QStringView{func[1]}.split(u' ', Qt::SkipEmptyParts);
1631 if (args.size() != 4)
1632 return QRect();
1633 QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
1634 d->parsed = QVariant::fromValue<QRect>(rect);
1635 return rect;
1636}
1637
1639{
1640 int i;
1641 if (d->parsed.isValid()) {
1642 QList<QVariant> v = d->parsed.toList();
1643 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1644 if (v.at(i).userType() == QMetaType::QColor) {
1645 c[i] = qvariant_cast<QColor>(v.at(i));
1646 } else {
1647 c[i] = pal.color((QPalette::ColorRole)(v.at(i).toInt()));
1648 }
1649 }
1650 } else {
1652 for (i = 0; i < qMin(d->values.size(), 4); i++) {
1653 ColorData color = parseColorValue(d->values.at(i));
1654 if (color.type == ColorData::Role) {
1655 v += QVariant::fromValue<int>(color.role);
1656 c[i] = pal.color((QPalette::ColorRole)(color.role));
1657 } else {
1658 v += QVariant::fromValue<QColor>(color.color);
1659 c[i] = color.color;
1660 }
1661 }
1662 d->parsed = v;
1663 }
1664
1665 if (i == 0) c[0] = c[1] = c[2] = c[3] = QColor();
1666 else if (i == 1) c[3] = c[2] = c[1] = c[0];
1667 else if (i == 2) c[2] = c[0], c[3] = c[1];
1668 else if (i == 3) c[3] = c[1];
1669}
1670
1672{
1673 if (d->values.size() != 1)
1674 return BorderStyle_None;
1675 return parseStyleValue(d->values.at(0));
1676}
1677
1679{
1680 int i;
1681 for (i = 0; i < qMin(d->values.size(), 4); i++)
1682 s[i] = parseStyleValue(d->values.at(i));
1683 if (i == 0) s[0] = s[1] = s[2] = s[3] = BorderStyle_None;
1684 else if (i == 1) s[3] = s[2] = s[1] = s[0];
1685 else if (i == 2) s[2] = s[0], s[3] = s[1];
1686 else if (i == 3) s[3] = s[1];
1687}
1688
1690{
1691 if (d->parsed.isValid())
1692 return static_cast<Repeat>(d->parsed.toInt());
1693 if (d->values.size() != 1)
1694 return Repeat_Unknown;
1695 int v = findKnownValue(d->values.at(0).variant.toString(),
1697 d->parsed = v;
1698 return static_cast<Repeat>(v);
1699}
1700
1702{
1703 if (d->parsed.isValid())
1704 return static_cast<Origin>(d->parsed.toInt());
1705 if (d->values.size() != 1)
1706 return Origin_Unknown;
1707 int v = findKnownValue(d->values.at(0).variant.toString(),
1709 d->parsed = v;
1710 return static_cast<Origin>(v);
1711}
1712
1714{
1715 if (d->parsed.isValid())
1716 return static_cast<PositionMode>(d->parsed.toInt());
1717 if (d->values.size() != 1)
1718 return PositionMode_Unknown;
1719 int v = findKnownValue(d->values.at(0).variant.toString(),
1721 d->parsed = v;
1722 return static_cast<PositionMode>(v);
1723}
1724
1726{
1727 if (d->parsed.isValid())
1728 return static_cast<Attachment>(d->parsed.toInt());
1729 if (d->values.size() != 1)
1730 return Attachment_Unknown;
1731 int v = findKnownValue(d->values.at(0).variant.toString(),
1733 d->parsed = v;
1734 return static_cast<Attachment>(v);
1735}
1736
1738{
1739 Q_ASSERT(d->propertyId == QtStyleFeatures);
1740 if (d->parsed.isValid())
1741 return d->parsed.toInt();
1742 int features = StyleFeature_None;
1743 for (int i = 0; i < d->values.size(); i++) {
1744 features |= static_cast<int>(findKnownValue(d->values.value(i).variant.toString(),
1746 }
1747 d->parsed = features;
1748 return features;
1749}
1750
1752{
1753 if (d->values.isEmpty() || d->values.at(0).type != Value::Uri)
1754 return QString();
1755 return d->values.at(0).variant.toString();
1756}
1757
1758Qt::Alignment Declaration::alignmentValue() const
1759{
1760 if (d->parsed.isValid())
1761 return Qt::Alignment(d->parsed.toInt());
1762 if (d->values.isEmpty() || d->values.size() > 2)
1763 return Qt::AlignLeft | Qt::AlignTop;
1764
1765 Qt::Alignment v = parseAlignment(d->values.constData(), d->values.size());
1766 d->parsed = int(v);
1767 return v;
1768}
1769
1771 TileMode *h, TileMode *v) const
1772{
1773 const DeclarationData *d = this->d.data(); // make it const and shadow d
1774 *image = uriValue();
1775 for (int i = 0; i < 4; i++)
1776 cuts[i] = -1;
1777 *h = *v = TileMode_Stretch;
1778
1779 if (d->values.size() < 2)
1780 return;
1781
1782 if (d->values.at(1).type == Value::Number) { // cuts!
1783 int i;
1784 for (i = 0; i < qMin(d->values.size()-1, 4); i++) {
1785 const Value& v = d->values.at(i+1);
1786 if (v.type != Value::Number)
1787 break;
1788 cuts[i] = v.variant.toString().toInt();
1789 }
1790 if (i == 0) cuts[0] = cuts[1] = cuts[2] = cuts[3] = 0;
1791 else if (i == 1) cuts[3] = cuts[2] = cuts[1] = cuts[0];
1792 else if (i == 2) cuts[2] = cuts[0], cuts[3] = cuts[1];
1793 else if (i == 3) cuts[3] = cuts[1];
1794 }
1795
1796 if (d->values.last().type == Value::Identifier) {
1797 *v = static_cast<TileMode>(findKnownValue(d->values.last().variant.toString(),
1799 }
1800 if (d->values[d->values.size() - 2].type == Value::Identifier) {
1801 *h = static_cast<TileMode>
1802 (findKnownValue(d->values[d->values.size()-2].variant.toString(),
1804 } else
1805 *h = *v;
1806}
1807
1809{
1810 if (d->values.size() != 1)
1811 return false;
1812 else
1813 return d->values.at(0).toString() == "collapse"_L1;
1814}
1815
1817{
1818 if (d->parsed.isValid())
1819 return qvariant_cast<QIcon>(d->parsed);
1820
1821 QIcon icon;
1822 for (int i = 0; i < d->values.size();) {
1823 const Value &value = d->values.at(i++);
1824 if (value.type != Value::Uri)
1825 break;
1826 QString uri = value.variant.toString();
1829 for (int j = 0; j < 2; j++) {
1830 if (i != d->values.size() && d->values.at(i).type == Value::KnownIdentifier) {
1831 switch (d->values.at(i).variant.toInt()) {
1832 case Value_Disabled: mode = QIcon::Disabled; break;
1833 case Value_Active: mode = QIcon::Active; break;
1834 case Value_Selected: mode = QIcon::Selected; break;
1835 case Value_Normal: mode = QIcon::Normal; break;
1836 case Value_On: state = QIcon::On; break;
1837 case Value_Off: state = QIcon::Off; break;
1838 default: break;
1839 }
1840 ++i;
1841 } else {
1842 break;
1843 }
1844 }
1845
1846 // QIcon is soo broken
1847 if (icon.isNull())
1848 icon = QIcon(uri);
1849 else
1850 icon.addPixmap(uri, mode, state);
1851
1852 if (i == d->values.size())
1853 break;
1854
1855 if (d->values.at(i).type == Value::TermOperatorComma)
1856 i++;
1857 }
1858
1859 d->parsed = QVariant::fromValue<QIcon>(icon);
1860 return icon;
1861}
1862
1864// Selector
1866{
1867 int val = 0;
1868 for (int i = 0; i < basicSelectors.size(); ++i) {
1869 const BasicSelector &sel = basicSelectors.at(i);
1870 if (!sel.elementName.isEmpty())
1871 val += 1;
1872
1873 val += (sel.pseudos.size() + sel.attributeSelectors.size()) * 0x10;
1874 val += sel.ids.size() * 0x100;
1875 }
1876 return val;
1877}
1878
1880{
1881 const BasicSelector& bs = basicSelectors.last();
1882 if (!bs.pseudos.isEmpty() && bs.pseudos.at(0).type == PseudoClass_Unknown)
1883 return bs.pseudos.at(0).name;
1884 return QString();
1885}
1886
1888{
1889 const BasicSelector& bs = basicSelectors.last();
1890 if (bs.pseudos.isEmpty())
1893 for (int i = !pseudoElement().isEmpty(); i < bs.pseudos.size(); i++) {
1894 const Pseudo &pseudo = bs.pseudos.at(i);
1895 if (pseudo.type == PseudoClass_Unknown)
1896 return PseudoClass_Unknown;
1897 if (!pseudo.negated)
1898 pc |= pseudo.type;
1899 else if (negated)
1900 *negated |= pseudo.type;
1901 }
1902 return pc;
1903}
1904
1906// StyleSheet
1908{
1909 QList<StyleRule> universals;
1910 for (int i = 0; i < styleRules.size(); ++i) {
1911 const StyleRule &rule = styleRules.at(i);
1912 QList<Selector> universalsSelectors;
1913 for (int j = 0; j < rule.selectors.size(); ++j) {
1914 const Selector& selector = rule.selectors.at(j);
1915
1916 if (selector.basicSelectors.isEmpty())
1917 continue;
1918
1919 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
1920 if (selector.basicSelectors.size() != 1)
1921 continue;
1922 } else if (selector.basicSelectors.size() <= 1) {
1923 continue;
1924 }
1925
1926 const BasicSelector &sel = selector.basicSelectors.at(selector.basicSelectors.size() - 1);
1927
1928 if (!sel.ids.isEmpty()) {
1929 StyleRule nr;
1930 nr.selectors += selector;
1931 nr.declarations = rule.declarations;
1932 nr.order = i;
1933 idIndex.insert(sel.ids.at(0), nr);
1934 } else if (!sel.elementName.isEmpty()) {
1935 StyleRule nr;
1936 nr.selectors += selector;
1937 nr.declarations = rule.declarations;
1938 nr.order = i;
1939 QString name = sel.elementName;
1940 if (nameCaseSensitivity == Qt::CaseInsensitive)
1941 name = std::move(name).toLower();
1942 nameIndex.insert(name, nr);
1943 } else {
1944 universalsSelectors += selector;
1945 }
1946 }
1947 if (!universalsSelectors.isEmpty()) {
1948 StyleRule nr;
1949 nr.selectors = universalsSelectors;
1950 nr.declarations = rule.declarations;
1951 nr.order = i;
1952 universals << nr;
1953 }
1954 }
1955 styleRules = universals;
1956}
1957
1959// StyleSelector
1961{
1962}
1963
1964bool StyleSelector::nodeNameEquals(NodePtr node, const QString& nodeName) const
1965{
1966 return nodeNames(node).contains(nodeName, nameCaseSensitivity);
1967}
1968
1970{
1972}
1973
1974bool StyleSelector::selectorMatches(const Selector &selector, NodePtr node)
1975{
1976 if (selector.basicSelectors.isEmpty())
1977 return false;
1978
1979 if (selector.basicSelectors.at(0).relationToNext == BasicSelector::NoRelation) {
1980 if (selector.basicSelectors.size() != 1)
1981 return false;
1982 return basicSelectorMatches(selector.basicSelectors.at(0), node);
1983 }
1984 if (selector.basicSelectors.size() <= 1)
1985 return false;
1986
1987 int i = selector.basicSelectors.size() - 1;
1988 node = duplicateNode(node);
1989 bool match = true;
1990
1991 BasicSelector sel = selector.basicSelectors.at(i);
1992 do {
1993 match = basicSelectorMatches(sel, node);
1994 if (!match) {
1995 if (i == selector.basicSelectors.size() - 1) // first element must always match!
1996 break;
1999 break;
2000 }
2001
2004 --i;
2005
2006 if (i < 0)
2007 break;
2008
2009 sel = selector.basicSelectors.at(i);
2012
2013 NodePtr nextParent = parentNode(node);
2014 freeNode(node);
2015 node = nextParent;
2018 NodePtr previousSibling = previousSiblingNode(node);
2019 freeNode(node);
2020 node = previousSibling;
2021 }
2022 if (isNullNode(node)) {
2023 match = false;
2024 break;
2025 }
2028
2029 freeNode(node);
2030
2031 return match;
2032}
2033
2034bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
2035{
2036 if (!sel.attributeSelectors.isEmpty()) {
2037 if (!hasAttributes(node))
2038 return false;
2039
2040 for (int i = 0; i < sel.attributeSelectors.size(); ++i) {
2042
2043 const QString attrValue = attributeValue(node, a);
2044 if (attrValue.isNull())
2045 return false;
2046
2047 switch (a.valueMatchCriterium) {
2049 break;
2051 if (attrValue != a.value)
2052 return false;
2053 break;
2055 const auto lst = QStringView{attrValue}.tokenize(u' ');
2056 bool found = false;
2057 for (auto s : lst) {
2058 if (s == a.value) {
2059 found = true;
2060 break;
2061 }
2062 }
2063 if (!found)
2064 return false;
2065 break;
2066 }
2068 const QString dashPrefix = a.value + u'-';
2069 if (attrValue != a.value && !attrValue.startsWith(dashPrefix))
2070 return false;
2071 break;
2072 }
2074 if (!attrValue.startsWith(a.value))
2075 return false;
2076 break;
2078 if (!attrValue.endsWith(a.value))
2079 return false;
2080 break;
2082 if (!attrValue.contains(a.value))
2083 return false;
2084 break;
2085 }
2086 }
2087 }
2088
2089 if (!sel.elementName.isEmpty()
2090 && !nodeNameEquals(node, sel.elementName))
2091 return false;
2092
2093 if (!sel.ids.isEmpty()
2094 && sel.ids != nodeIds(node))
2095 return false;
2096
2097 return true;
2098}
2099
2100void StyleSelector::matchRule(NodePtr node, const StyleRule &rule, StyleSheetOrigin origin,
2101 int depth, QMultiMap<uint, StyleRule> *weightedRules)
2102{
2103 for (int j = 0; j < rule.selectors.size(); ++j) {
2104 const Selector& selector = rule.selectors.at(j);
2105 if (selectorMatches(selector, node)) {
2106 uint weight = rule.order
2107 + selector.specificity() *0x100
2108 + (uint(origin) + depth)*0x100000;
2109 StyleRule newRule = rule;
2110 if (rule.selectors.size() > 1) {
2111 newRule.selectors.resize(1);
2112 newRule.selectors[0] = selector;
2113 }
2114 //We might have rules with the same weight if they came from a rule with several selectors
2115 weightedRules->insert(weight, newRule);
2116 }
2117 }
2118}
2119
2120// Returns style rules that are in ascending order of specificity
2121// Each of the StyleRule returned will contain exactly one Selector
2123{
2124 QList<StyleRule> rules;
2125 if (styleSheets.isEmpty())
2126 return rules;
2127
2128 QMultiMap<uint, StyleRule> weightedRules; // (spec, rule) that will be sorted below
2129
2130 //prune using indexed stylesheet
2131 for (int sheetIdx = 0; sheetIdx < styleSheets.size(); ++sheetIdx) {
2132 const StyleSheet &styleSheet = styleSheets.at(sheetIdx);
2133 for (int i = 0; i < styleSheet.styleRules.size(); ++i) {
2134 matchRule(node, styleSheet.styleRules.at(i), styleSheet.origin, styleSheet.depth, &weightedRules);
2135 }
2136
2137 if (!styleSheet.idIndex.isEmpty()) {
2138 QStringList ids = nodeIds(node);
2139 for (int i = 0; i < ids.size(); i++) {
2140 const QString &key = ids.at(i);
2142 while (it != styleSheet.idIndex.constEnd() && it.key() == key) {
2143 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
2144 ++it;
2145 }
2146 }
2147 }
2148 if (!styleSheet.nameIndex.isEmpty()) {
2149 QStringList names = nodeNames(node);
2150 for (int i = 0; i < names.size(); i++) {
2151 QString name = names.at(i);
2153 name = std::move(name).toLower();
2155 while (it != styleSheet.nameIndex.constEnd() && it.key() == name) {
2156 matchRule(node, it.value(), styleSheet.origin, styleSheet.depth, &weightedRules);
2157 ++it;
2158 }
2159 }
2160 }
2161 if (!medium.isEmpty()) {
2162 for (int i = 0; i < styleSheet.mediaRules.size(); ++i) {
2163 if (styleSheet.mediaRules.at(i).media.contains(medium, Qt::CaseInsensitive)) {
2164 for (int j = 0; j < styleSheet.mediaRules.at(i).styleRules.size(); ++j) {
2165 matchRule(node, styleSheet.mediaRules.at(i).styleRules.at(j), styleSheet.origin,
2166 styleSheet.depth, &weightedRules);
2167 }
2168 }
2169 }
2170 }
2171 }
2172
2173 rules.reserve(weightedRules.size());
2175 for ( ; it != weightedRules.constEnd() ; ++it)
2176 rules += *it;
2177
2178 return rules;
2179}
2180
2181// for qtexthtmlparser which requires just the declarations with Enabled state
2182// and without pseudo elements
2184{
2185 QList<Declaration> decls;
2186 QList<StyleRule> rules = styleRulesForNode(node);
2187 for (int i = 0; i < rules.size(); i++) {
2188 const Selector& selector = rules.at(i).selectors.at(0);
2189 const QString pseudoElement = selector.pseudoElement();
2190
2191 if (extraPseudo && pseudoElement == QLatin1StringView(extraPseudo)) {
2192 decls += rules.at(i).declarations;
2193 continue;
2194 }
2195
2196 if (!pseudoElement.isEmpty()) // skip rules with pseudo elements
2197 continue;
2198 quint64 pseudoClass = selector.pseudoClass();
2199 if (pseudoClass == PseudoClass_Enabled || pseudoClass == PseudoClass_Unspecified)
2200 decls += rules.at(i).declarations;
2201 }
2202 return decls;
2203}
2204
2205static inline bool isHexDigit(const char c)
2206{
2207 return (c >= '0' && c <= '9')
2208 || (c >= 'a' && c <= 'f')
2209 || (c >= 'A' && c <= 'F')
2210 ;
2211}
2212
2213QString Scanner::preprocess(const QString &input, bool *hasEscapeSequences)
2214{
2216
2217 if (hasEscapeSequences)
2218 *hasEscapeSequences = false;
2219
2220 int i = 0;
2221 while (i < output.size()) {
2222 if (output.at(i) == u'\\') {
2223
2224 ++i;
2225 // test for unicode hex escape
2226 int hexCount = 0;
2227 const int hexStart = i;
2228 while (i < output.size()
2229 && isHexDigit(output.at(i).toLatin1())
2230 && hexCount < 7) {
2231 ++hexCount;
2232 ++i;
2233 }
2234 if (hexCount == 0) {
2235 if (hasEscapeSequences)
2236 *hasEscapeSequences = true;
2237 continue;
2238 }
2239
2240 hexCount = qMin(hexCount, 6);
2241 bool ok = false;
2242 const char16_t code = QStringView{output}.mid(hexStart, hexCount).toUShort(&ok, 16);
2243 if (ok) {
2244 output.replace(hexStart - 1, hexCount + 1, code);
2245 i = hexStart;
2246 } else {
2247 i = hexStart;
2248 }
2249 } else {
2250 ++i;
2251 }
2252 }
2253 return output;
2254}
2255
2257{
2258 while (pos < input.size() - 1) {
2259 if (input.at(pos) == u'*' && input.at(pos + 1) == u'/') {
2260 pos += 2;
2261 break;
2262 }
2263 ++pos;
2264 }
2265 return S;
2266}
2267
2268void Scanner::scan(const QString &preprocessedInput, QList<Symbol> *symbols)
2269{
2270 QCssScanner_Generated scanner(preprocessedInput);
2271 Symbol sym;
2272 int tok = scanner.lex();
2273 while (tok != -1) {
2274 sym.token = static_cast<QCss::TokenType>(tok);
2275 sym.text = scanner.input;
2276 sym.start = scanner.lexemStart;
2277 sym.len = scanner.lexemLength;
2278 symbols->append(sym);
2279 tok = scanner.lex();
2280 }
2281}
2282
2284{
2286 if (len > 0)
2287 result.reserve(len);
2288 for (int i = 0; i < len; ++i) {
2289 if (text.at(start + i) == u'\\' && i < len - 1)
2290 ++i;
2291 result += text.at(start + i);
2292 }
2293 return result;
2294}
2295
2296Parser::Parser(const QString &css, bool isFile)
2297{
2298 init(css, isFile);
2299}
2300
2302{
2303 index = 0;
2304 errorIndex = -1;
2305 hasEscapeSequences = false;
2306}
2307
2308void Parser::init(const QString &css, bool isFile)
2309{
2310 QString styleSheet = css;
2311 if (isFile) {
2312 QFile file(css);
2313 if (file.open(QFile::ReadOnly)) {
2314 sourcePath = QFileInfo(styleSheet).absolutePath() + u'/';
2316 styleSheet = stream.readAll();
2317 } else {
2318 qWarning() << "QCss::Parser - Failed to load file " << css;
2319 styleSheet.clear();
2320 }
2321 } else {
2322 sourcePath.clear();
2323 }
2324
2325 hasEscapeSequences = false;
2326 symbols.clear();
2327 symbols.reserve(8);
2329 index = 0;
2330 errorIndex = -1;
2331}
2332
2333bool Parser::parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity)
2334{
2335 if (testTokenAndEndsWith(ATKEYWORD_SYM, "charset"_L1)) {
2336 while (test(S) || test(CDO) || test(CDC)) {}
2337 if (!next(STRING)) return false;
2338 if (!next(SEMICOLON)) return false;
2339 }
2340
2341 while (test(S) || test(CDO) || test(CDC)) {}
2342
2343 while (testImport()) {
2345 if (!parseImport(&rule)) return false;
2346 styleSheet->importRules.append(rule);
2347 while (test(S) || test(CDO) || test(CDC)) {}
2348 }
2349
2350 do {
2351 if (testMedia()) {
2353 if (!parseMedia(&rule)) return false;
2354 styleSheet->mediaRules.append(rule);
2355 } else if (testPage()) {
2356 PageRule rule;
2357 if (!parsePage(&rule)) return false;
2358 styleSheet->pageRules.append(rule);
2359 } else if (testRuleset()) {
2361 if (!parseRuleset(&rule)) return false;
2362 styleSheet->styleRules.append(rule);
2363 } else if (test(ATKEYWORD_SYM)) {
2364 if (!until(RBRACE)) return false;
2365 } else if (hasNext()) {
2366 return false;
2367 }
2368 while (test(S) || test(CDO) || test(CDC)) {}
2369 } while (hasNext());
2370 styleSheet->buildIndexes(nameCaseSensitivity);
2371 return true;
2372}
2373
2375{
2376 if (errorIndex == -1) return Symbol();
2377 return symbols.at(errorIndex);
2378}
2379
2381{
2382 if (!str->startsWith(u'\'') && !str->startsWith(u'\"'))
2383 return;
2384 str->remove(0, 1);
2385 str->chop(1);
2386}
2387
2389{
2390 skipSpace();
2391
2392 if (test(STRING)) {
2393 importRule->href = lexem();
2394 } else {
2395 if (!testAndParseUri(&importRule->href)) return false;
2396 }
2397 removeOptionalQuotes(&importRule->href);
2398
2399 skipSpace();
2400
2401 if (testMedium()) {
2402 if (!parseMedium(&importRule->media)) return false;
2403
2404 while (test(COMMA)) {
2405 skipSpace();
2406 if (!parseNextMedium(&importRule->media)) return false;
2407 }
2408 }
2409
2410 if (!next(SEMICOLON)) return false;
2411
2412 skipSpace();
2413 return true;
2414}
2415
2417{
2418 do {
2419 skipSpace();
2420 if (!parseNextMedium(&mediaRule->media)) return false;
2421 } while (test(COMMA));
2422
2423 if (!next(LBRACE)) return false;
2424 skipSpace();
2425
2426 while (testRuleset()) {
2428 if (!parseRuleset(&rule)) return false;
2429 mediaRule->styleRules.append(rule);
2430 }
2431
2432 if (!next(RBRACE)) return false;
2433 skipSpace();
2434 return true;
2435}
2436
2438{
2439 media->append(lexem());
2440 skipSpace();
2441 return true;
2442}
2443
2445{
2446 skipSpace();
2447
2448 if (testPseudoPage())
2449 if (!parsePseudoPage(&pageRule->selector)) return false;
2450
2451 skipSpace();
2452 if (!next(LBRACE)) return false;
2453
2454 do {
2455 skipSpace();
2456 Declaration decl;
2457 if (!parseNextDeclaration(&decl)) return false;
2458 if (!decl.isEmpty())
2459 pageRule->declarations.append(decl);
2460 } while (test(SEMICOLON));
2461
2462 if (!next(RBRACE)) return false;
2463 skipSpace();
2464 return true;
2465}
2466
2468{
2469 if (!next(IDENT)) return false;
2470 *selector = lexem();
2471 return true;
2472}
2473
2475{
2476 if (!hasNext()) return true;
2477 switch (next()) {
2478 case SLASH: value->type = Value::TermOperatorSlash; skipSpace(); break;
2479 case COMMA: value->type = Value::TermOperatorComma; skipSpace(); break;
2480 default: prev(); break;
2481 }
2482 return true;
2483}
2484
2486{
2487 *relation = BasicSelector::NoRelation;
2488 if (lookup() == S) {
2490 skipSpace();
2491 } else {
2492 prev();
2493 }
2494 if (test(PLUS)) {
2496 } else if (test(GREATER)) {
2498 } else if (test(TILDE)) {
2500 }
2501 skipSpace();
2502 return true;
2503}
2504
2506{
2507 decl->d->property = lexem();
2508 decl->d->propertyId = static_cast<Property>(findKnownValue(decl->d->property, properties, NumProperties));
2509 decl->d->inheritable = isInheritable(decl->d->propertyId);
2510 skipSpace();
2511 return true;
2512}
2513
2515{
2516 Selector sel;
2517 if (!parseSelector(&sel)) return false;
2518 styleRule->selectors.append(sel);
2519
2520 while (test(COMMA)) {
2521 skipSpace();
2522 Selector sel;
2523 if (!parseNextSelector(&sel)) return false;
2524 styleRule->selectors.append(sel);
2525 }
2526
2527 skipSpace();
2528 if (!next(LBRACE)) return false;
2529 const int declarationStart = index;
2530
2531 do {
2532 skipSpace();
2533 Declaration decl;
2534 const int rewind = index;
2535 if (!parseNextDeclaration(&decl)) {
2536 index = rewind;
2537 const bool foundSemicolon = until(SEMICOLON);
2538 const int semicolonIndex = index;
2539
2540 index = declarationStart;
2541 const bool foundRBrace = until(RBRACE);
2542
2543 if (foundSemicolon && semicolonIndex < index) {
2544 decl = Declaration();
2545 index = semicolonIndex - 1;
2546 } else {
2547 skipSpace();
2548 return foundRBrace;
2549 }
2550 }
2551 if (!decl.isEmpty())
2552 styleRule->declarations.append(decl);
2553 } while (test(SEMICOLON));
2554
2555 if (!next(RBRACE)) return false;
2556 skipSpace();
2557 return true;
2558}
2559
2561{
2562 BasicSelector basicSel;
2563 if (!parseSimpleSelector(&basicSel)) return false;
2564 while (testCombinator()) {
2565 if (!parseCombinator(&basicSel.relationToNext)) return false;
2566
2567 if (!testSimpleSelector()) break;
2568 sel->basicSelectors.append(basicSel);
2569
2570 basicSel = BasicSelector();
2571 if (!parseSimpleSelector(&basicSel)) return false;
2572 }
2573 sel->basicSelectors.append(basicSel);
2574 return true;
2575}
2576
2578{
2579 int minCount = 0;
2580 if (lookupElementName()) {
2581 if (!parseElementName(&basicSel->elementName)) return false;
2582 } else {
2583 prev();
2584 minCount = 1;
2585 }
2586 bool onceMore;
2587 int count = 0;
2588 do {
2589 onceMore = false;
2590 if (test(HASH)) {
2591 QString theid = lexem();
2592 // chop off leading #
2593 theid.remove(0, 1);
2594 basicSel->ids.append(theid);
2595 onceMore = true;
2596 } else if (testClass()) {
2597 onceMore = true;
2599 a.name = "class"_L1;
2600 a.valueMatchCriterium = AttributeSelector::MatchIncludes;
2601 if (!parseClass(&a.value)) return false;
2602 basicSel->attributeSelectors.append(a);
2603 } else if (testAttrib()) {
2604 onceMore = true;
2606 if (!parseAttrib(&a)) return false;
2607 basicSel->attributeSelectors.append(a);
2608 } else if (testPseudo()) {
2609 onceMore = true;
2610 Pseudo ps;
2611 if (!parsePseudo(&ps)) return false;
2612 basicSel->pseudos.append(ps);
2613 }
2614 if (onceMore) ++count;
2615 } while (onceMore);
2616 return count >= minCount;
2617}
2618
2620{
2621 if (!next(IDENT)) return false;
2622 *name = lexem();
2623 return true;
2624}
2625
2627{
2628 switch (lookup()) {
2629 case STAR: name->clear(); break;
2630 case IDENT: *name = lexem(); break;
2631 default: return false;
2632 }
2633 return true;
2634}
2635
2637{
2638 skipSpace();
2639 if (!next(IDENT)) return false;
2640 attr->name = lexem();
2641 skipSpace();
2642
2643 if (test(EQUAL)) {
2645 } else if (test(INCLUDES)) {
2647 } else if (test(DASHMATCH)) {
2649 } else if (test(BEGINSWITH)) {
2651 } else if (test(ENDSWITH)) {
2653 } else if (test(CONTAINS)) {
2655 } else {
2656 return next(RBRACKET);
2657 }
2658
2659 skipSpace();
2660
2661 if (!test(IDENT) && !test(STRING)) return false;
2662 attr->value = unquotedLexem();
2663
2664 skipSpace();
2665 return next(RBRACKET);
2666}
2667
2669{
2670 (void)test(COLON);
2671 pseudo->negated = test(EXCLAMATION_SYM);
2672 if (test(IDENT)) {
2673 pseudo->name = lexem();
2674 pseudo->type = static_cast<quint64>(findKnownValue(pseudo->name, pseudos, NumPseudos));
2675 return true;
2676 }
2677 if (!next(FUNCTION)) return false;
2678 pseudo->function = lexem();
2679 // chop off trailing parenthesis
2680 pseudo->function.chop(1);
2681 skipSpace();
2682 if (!test(IDENT)) return false;
2683 pseudo->name = lexem();
2684 skipSpace();
2685 return next(RPAREN);
2686}
2687
2689{
2690 if (!testProperty())
2691 return true; // not an error!
2692 if (!parseProperty(decl)) return false;
2693 if (!next(COLON)) return false;
2694 skipSpace();
2695 if (!parseNextExpr(&decl->d->values)) return false;
2696 if (testPrio())
2697 if (!parsePrio(decl)) return false;
2698 return true;
2699}
2700
2702{
2703 const int rewind = index;
2704 if (!test(EXCLAMATION_SYM)) return false;
2705 skipSpace();
2706 if (!test(IDENT)) {
2707 index = rewind;
2708 return false;
2709 }
2710 if (lexem().compare("important"_L1, Qt::CaseInsensitive) != 0) {
2711 index = rewind;
2712 return false;
2713 }
2714 return true;
2715}
2716
2718{
2719 declaration->d->important = true;
2720 skipSpace();
2721 return true;
2722}
2723
2725{
2726 Value val;
2727 if (!parseTerm(&val)) return false;
2728 values->append(val);
2729 bool onceMore;
2730 do {
2731 onceMore = false;
2732 val = Value();
2733 if (!parseNextOperator(&val)) return false;
2734 if (val.type != QCss::Value::Unknown)
2735 values->append(val);
2736 if (testTerm()) {
2737 onceMore = true;
2738 val = Value();
2739 if (!parseTerm(&val)) return false;
2740 values->append(val);
2741 }
2742 } while (onceMore);
2743 return true;
2744}
2745
2747{
2748 return test(PLUS) || test(MINUS)
2749 || test(NUMBER)
2750 || test(PERCENTAGE)
2751 || test(LENGTH)
2752 || test(STRING)
2753 || test(IDENT)
2754 || testHexColor()
2755 || testFunction();
2756}
2757
2759{
2760 QString str = lexem();
2761 bool haveUnary = false;
2762 if (lookup() == PLUS || lookup() == MINUS) {
2763 haveUnary = true;
2764 if (!hasNext()) return false;
2765 next();
2766 str += lexem();
2767 }
2768
2769 value->variant = str;
2770 value->type = QCss::Value::String;
2771 switch (lookup()) {
2772 case NUMBER:
2773 value->type = Value::Number;
2774 value->variant.convert(QMetaType::fromType<double>());
2775 break;
2776 case PERCENTAGE:
2777 value->type = Value::Percentage;
2778 str.chop(1); // strip off %
2779 value->variant = str;
2780 break;
2781 case LENGTH:
2782 value->type = Value::Length;
2783 break;
2784
2785 case STRING:
2786 if (haveUnary) return false;
2787 value->type = Value::String;
2788 str.chop(1);
2789 str.remove(0, 1);
2790 value->variant = str;
2791 break;
2792 case IDENT: {
2793 if (haveUnary) return false;
2794 value->type = Value::Identifier;
2795 const int theid = findKnownValue(str, values, NumKnownValues);
2796 if (theid != 0) {
2798 value->variant = theid;
2799 }
2800 break;
2801 }
2802 default: {
2803 if (haveUnary) return false;
2804 prev();
2805 if (testHexColor()) {
2806 QColor col;
2807 if (!parseHexColor(&col)) return false;
2808 value->type = Value::Color;
2809 value->variant = col;
2810 } else if (testFunction()) {
2811 QString name, args;
2812 if (!parseFunction(&name, &args)) return false;
2813 if (name == "url"_L1) {
2814 value->type = Value::Uri;
2818 }
2819 value->variant = args;
2820 } else {
2821 value->type = Value::Function;
2822 value->variant = QStringList() << name << args;
2823 }
2824 } else {
2825 return recordError();
2826 }
2827 return true;
2828 }
2829 }
2830 skipSpace();
2831 return true;
2832}
2833
2835{
2836 *name = lexem();
2837 name->chop(1);
2838 // until(RPAREN) needs FUNCTION token at index-1 to work properly
2839 int start = index;
2840 skipSpace();
2841 std::swap(start, index);
2842 if (!until(RPAREN)) return false;
2843 for (int i = start; i < index - 1; ++i)
2844 args->append(symbols.at(i).lexem());
2845 /*
2846 if (!nextExpr(&arguments)) return false;
2847 if (!next(RPAREN)) return false;
2848 */
2849 skipSpace();
2850 return true;
2851}
2852
2854{
2855 *col = QColor::fromString(lexem());
2856 if (!col->isValid()) {
2857 qWarning("QCssParser::parseHexColor: Unknown color name '%s'",lexem().toLatin1().constData());
2858 return false;
2859 }
2860 skipSpace();
2861 return true;
2862}
2863
2865{
2866 const int rewind = index;
2867 if (!testFunction()) return false;
2868
2869 QString name, args;
2870 if (!parseFunction(&name, &args)) {
2871 index = rewind;
2872 return false;
2873 }
2874 if (name.compare("url"_L1, Qt::CaseInsensitive) != 0) {
2875 index = rewind;
2876 return false;
2877 }
2878 *uri = args;
2880 return true;
2881}
2882
2884{
2885 return testElementName()
2886 || (test(HASH))
2887 || testClass()
2888 || testAttrib()
2889 || testPseudo();
2890}
2891
2893{
2894 if (hasNext() && next() == t)
2895 return true;
2896 return recordError();
2897}
2898
2900{
2901 if (index >= symbols.size())
2902 return false;
2903 if (symbols.at(index).token == t) {
2904 ++index;
2905 return true;
2906 }
2907 return false;
2908}
2909
2911{
2912 QString s = lexem();
2913 if (lookup() == STRING) {
2914 s.chop(1);
2915 s.remove(0, 1);
2916 }
2917 return s;
2918}
2919
2921{
2922 QString lexem;
2923 while (hasNext() && next() != t)
2924 lexem += symbol().lexem();
2925 return lexem;
2926}
2927
2929{
2930 int braceCount = 0;
2931 int brackCount = 0;
2932 int parenCount = 0;
2933 if (index) {
2934 switch(symbols.at(index-1).token) {
2935 case LBRACE: ++braceCount; break;
2936 case LBRACKET: ++brackCount; break;
2937 case FUNCTION:
2938 case LPAREN: ++parenCount; break;
2939 default: ;
2940 }
2941 }
2942 while (index < symbols.size()) {
2944 switch (t) {
2945 case LBRACE: ++braceCount; break;
2946 case RBRACE: --braceCount; break;
2947 case LBRACKET: ++brackCount; break;
2948 case RBRACKET: --brackCount; break;
2949 case FUNCTION:
2950 case LPAREN: ++parenCount; break;
2951 case RPAREN: --parenCount; break;
2952 default: break;
2953 }
2954 if ((t == target || (target2 != NONE && t == target2))
2955 && braceCount <= 0
2956 && brackCount <= 0
2957 && parenCount <= 0)
2958 return true;
2959
2960 if (braceCount < 0 || brackCount < 0 || parenCount < 0) {
2961 --index;
2962 break;
2963 }
2964 }
2965 return false;
2966}
2967
2969{
2970 if (!test(t)) return false;
2971 if (!lexem().endsWith(str, Qt::CaseInsensitive)) {
2972 prev();
2973 return false;
2974 }
2975 return true;
2976}
2977
2979#endif // QT_NO_CSSPARSER
\inmodule QtGui
Definition qbrush.h:30
QChar toLower() const noexcept
Returns the lowercase equivalent if the character is uppercase or titlecase; otherwise returns the ch...
Definition qchar.h:448
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition qcolor.h:31
static QColor fromRgb(QRgb rgb) noexcept
Static convenience function that returns a QColor constructed from the given QRgb value rgb.
Definition qcolor.cpp:2369
static QColor fromString(QAnyStringView name) noexcept
Definition qcolor.cpp:980
static QColor fromHsv(int h, int s, int v, int a=255)
Static convenience function that returns a QColor constructed from the HSV color values,...
Definition qcolor.cpp:2499
static QColor fromHsl(int h, int s, int l, int a=255)
Definition qcolor.cpp:2562
bool isValid() const noexcept
Returns true if the color is valid; otherwise returns false.
Definition qcolor.h:285
\inmodule QtGui
Definition qbrush.h:446
bool testPseudoPage()
bool hasNext() const
bool parsePseudoPage(QString *selector)
bool parseFunction(QString *name, QString *args)
bool testFunction()
bool until(TokenType target, TokenType target2=NONE)
bool testAttrib()
TokenType lookup() const
bool test(TokenType t)
bool parseSelector(Selector *sel)
bool parseSimpleSelector(BasicSelector *basicSel)
bool parseRuleset(StyleRule *styleRule)
bool parsePage(PageRule *pageRule)
void init(const QString &css, bool file=false)
bool testTokenAndEndsWith(TokenType t, QLatin1StringView str)
bool parse(StyleSheet *styleSheet, Qt::CaseSensitivity nameCaseSensitivity=Qt::CaseSensitive)
bool testSimpleSelector()
bool parseCombinator(BasicSelector::Relation *relation)
bool parseNextOperator(Value *value)
bool parseNextMedium(QStringList *media)
bool parseMedium(QStringList *media)
const Symbol & symbol() const
QString unquotedLexem() const
bool testPseudo()
bool parsePseudo(Pseudo *pseudo)
Symbol errorSymbol()
QString lexem() const
bool parseClass(QString *name)
bool parseProperty(Declaration *decl)
bool testRuleset()
bool parseMedia(MediaRule *mediaRule)
bool parseNextExpr(QList< Value > *values)
bool parseNextSelector(Selector *sel)
bool testImport()
bool parseAttrib(AttributeSelector *attr)
bool parseTerm(Value *value)
bool recordError()
QString lexemUntil(TokenType t)
QString sourcePath
bool testHexColor()
bool parseNextDeclaration(Declaration *declaration)
bool lookupElementName() const
bool testCombinator()
bool testMedium()
TokenType next()
bool testElementName()
bool testAndParseUri(QString *uri)
bool hasEscapeSequences
bool parseExpr(QList< Value > *values)
bool parseElementName(QString *name)
QList< Symbol > symbols
bool testProperty()
bool parseHexColor(QColor *col)
bool parsePrio(Declaration *declaration)
bool parseImport(ImportRule *importRule)
static QString preprocess(const QString &input, bool *hasEscapeSequences=nullptr)
static void scan(const QString &preprocessedInput, QList< Symbol > *symbols)
virtual NodePtr parentNode(NodePtr node) const =0
virtual QStringList nodeNames(NodePtr node) const =0
virtual bool nodeNameEquals(NodePtr node, const QString &nodeName) const
virtual NodePtr previousSiblingNode(NodePtr node) const =0
virtual void freeNode(NodePtr node) const =0
virtual bool hasAttributes(NodePtr node) const =0
virtual bool isNullNode(NodePtr node) const =0
QList< StyleSheet > styleSheets
virtual NodePtr duplicateNode(NodePtr node) const =0
virtual QString attributeValue(NodePtr node, const QCss::AttributeSelector &aSelector) const =0
Qt::CaseSensitivity nameCaseSensitivity
virtual QStringList nodeIds(NodePtr node) const
QList< StyleRule > styleRulesForNode(NodePtr node)
QList< Declaration > declarationsForNode(NodePtr node, const char *extraPseudo=nullptr)
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString absolutePath() const
Returns a file's path absolute path.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
\reentrant \inmodule QtGui
int height() const
Returns the height of the font.
int xHeight() const
Returns the 'x' height of the font.
\reentrant
Definition qfont.h:20
void setStyle(Style style)
Sets the style of the font to style.
Definition qfont.cpp:1101
void setOverline(bool)
If enable is true, sets overline on; otherwise sets overline off.
Definition qfont.cpp:1273
void setStrikeOut(bool)
If enable is true, sets strikeout on; otherwise sets strikeout off.
Definition qfont.cpp:1300
@ AllLowercase
Definition qfont.h:97
@ AllUppercase
Definition qfont.h:96
@ MixedCase
Definition qfont.h:95
@ SmallCaps
Definition qfont.h:98
void setFamilies(const QStringList &)
Definition qfont.cpp:2491
void setCapitalization(Capitalization)
Definition qfont.cpp:1702
void setWordSpacing(qreal spacing)
Definition qfont.cpp:1667
@ AbsoluteSpacing
Definition qfont.h:105
@ PercentageSpacing
Definition qfont.h:104
void setLetterSpacing(SpacingType type, qreal spacing)
Definition qfont.cpp:1615
void setKerning(bool)
Enables kerning for this font if enable is true; otherwise disables it.
Definition qfont.cpp:1360
void setPixelSize(int)
Sets the font size to pixelSize pixels, with a maxiumum size of an unsigned 16-bit integer.
Definition qfont.cpp:1034
void setUnderline(bool)
If enable is true, sets underline on; otherwise sets underline off.
Definition qfont.cpp:1247
void setPointSizeF(qreal)
Sets the point size to pointSize.
Definition qfont.cpp:995
Weight
Qt uses a weighting scale from 1 to 1000 compatible with OpenType.
Definition qfont.h:60
@ Bold
Definition qfont.h:67
@ Normal
Definition qfont.h:64
void setWeight(Weight weight)
Sets the weight of the font to weight, using the scale defined by \l QFont::Weight enumeration.
Definition qfont.cpp:1190
@ StyleItalic
Definition qfont.h:75
@ StyleNormal
Definition qfont.h:74
@ StyleOblique
Definition qfont.h:76
void setSpread(Spread spread)
Specifies the spread method that should be used for this gradient.
Definition qbrush.h:390
void setCoordinateMode(CoordinateMode mode)
Definition qbrush.cpp:1683
void setStops(const QGradientStops &stops)
Replaces the current set of stop points with the given stopPoints.
Definition qbrush.cpp:1608
@ ObjectBoundingMode
Definition qbrush.h:156
Spread
Specifies how the area outside the gradient area should be filled.
Definition qbrush.h:146
\inmodule QtCore
Definition qhash.h:818
T value(const Key &key) const noexcept
Definition qhash.h:1044
The QIcon class provides scalable icons in different modes and states.
Definition qicon.h:20
void addPixmap(const QPixmap &pixmap, Mode mode=Normal, State state=Off)
Adds pixmap to the icon, as a specialization for mode and state.
Definition qicon.cpp:1014
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition qicon.cpp:973
Mode
This enum type describes the mode for which a pixmap is intended to be used.
Definition qicon.h:22
@ Disabled
Definition qicon.h:22
@ Selected
Definition qicon.h:22
@ Normal
Definition qicon.h:22
@ Active
Definition qicon.h:22
State
This enum describes the state for which a pixmap is intended to be used.
Definition qicon.h:23
@ Off
Definition qicon.h:23
@ On
Definition qicon.h:23
The QImageReader class provides a format independent interface for reading images from files or other...
constexpr qsizetype size() const noexcept
\inmodule QtGui
Definition qbrush.h:394
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void prepend(rvalue_ref t)
Definition qlist.h:456
void reserve(qsizetype size)
Definition qlist.h:746
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
static constexpr QMetaType fromType()
Definition qmetatype.h:2612
\inmodule QtCore
Definition qhash.h:1748
const_iterator constEnd() const
Definition qmap.h:1302
iterator insert(const Key &key, const T &value)
Definition qmap.h:1425
size_type size() const
Definition qmap.h:911
const_iterator constBegin() const
Definition qmap.h:1298
The QPalette class contains color groups for each widget state.
Definition qpalette.h:19
const QColor & color(ColorGroup cg, ColorRole cr) const
Returns the color in the specified color group, used for the given color role.
Definition qpalette.h:66
\inmodule QtGui
Definition qbrush.h:412
\inmodule QtCore\reentrant
Definition qrect.h:30
\inmodule QtCore
Definition qsize.h:25
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:7987
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
void chop(qsizetype n)
Removes n characters from the end of the string.
Definition qstring.cpp:6180
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
Definition qstring.h:1079
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
QString toLower() const &
Definition qstring.h:368
bool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.h:1217
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition qstring.cpp:3435
auto tokenize(Needle &&needle, Flags...flags) const &noexcept(noexcept(qTokenize(std::declval< const QString & >(), std::forward< Needle >(needle), flags...))) -> decltype(qTokenize(*this, std::forward< Needle >(needle), flags...))
Definition qstring.h:528
\inmodule QtCore
\inmodule QtCore
Definition qvariant.h:64
qreal toReal(bool *ok=nullptr) const
Returns the variant as a qreal if the variant has userType() \l QMetaType::Double,...
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
QString str
[2]
qreal spacing
QSet< QString >::iterator it
rect
[4]
uint alignment
else opt state
[0]
const quint64 PseudoClass_Unknown
const quint64 PseudoClass_Floatable
const quint64 PseudoClass_Movable
@ BottomEdge
@ RightEdge
const int NumPseudos
const quint64 PseudoClass_Children
const quint64 PseudoClass_Disabled
const quint64 PseudoClass_Sibling
const quint64 PseudoClass_ReadOnly
const quint64 PseudoClass_Closed
const quint64 PseudoClass_Maximized
const quint64 PseudoClass_Default
@ Repeat_XY
@ Repeat_Unknown
@ Repeat_None
@ NumKnownRepeats
const quint64 PseudoClass_Bottom
const quint64 PseudoClass_EditFocus
const quint64 PseudoClass_Focus
const quint64 PseudoClass_Enabled
const quint64 PseudoClass_Editable
const quint64 PseudoClass_Vertical
const quint64 PseudoClass_Flat
const quint64 PseudoClass_NonExclusive
@ Origin_Padding
@ Origin_Content
@ NumKnownOrigins
@ Origin_Unknown
@ Origin_Margin
@ Origin_Border
@ ATKEYWORD_SYM
@ DASHMATCH
@ PERCENTAGE
@ BEGINSWITH
@ SEMICOLON
@ EXCLAMATION_SYM
const quint64 PseudoClass_Pressed
const quint64 PseudoClass_Item
const quint64 PseudoClass_Alternate
const quint64 PseudoClass_PreviousSelected
const quint64 PseudoClass_Closable
const quint64 PseudoClass_Horizontal
const quint64 PseudoClass_Active
const quint64 PseudoClass_NextSelected
@ StyleFeature_BackgroundGradient
@ NumKnownStyleFeatures
@ StyleFeature_BackgroundColor
@ StyleFeature_None
const quint64 PseudoClass_Open
const quint64 PseudoClass_Frameless
const quint64 PseudoClass_Checked
const quint64 PseudoClass_Selected
@ Attachment_Fixed
@ NumKnownAttachments
@ Attachment_Scroll
@ Attachment_Unknown
const quint64 PseudoClass_Right
@ Value_Disc
@ Value_Bottom
@ Value_Wave
@ Value_UpperRoman
@ Value_Oblique
@ Value_Selected
@ Value_XXLarge
@ Value_Decimal
@ Value_PreWrap
@ Value_Link
@ Value_Active
@ Value_Button
@ Value_Left
@ Value_Circle
@ Value_Medium
@ Value_Midlight
@ Value_Pre
@ Value_Normal
@ Value_LineThrough
@ Value_DotDotDash
@ Value_Square
@ Value_Small
@ Value_Groove
@ Value_Transparent
@ Value_LowerAlpha
@ Value_Off
@ Value_Solid
@ Value_Disabled
@ Value_Light
@ Value_Super
@ Value_NoWrap
@ Value_LastColorRole
@ Value_Base
@ Value_Outset
@ NumKnownValues
@ Value_Shadow
@ Value_Native
@ Value_ButtonText
@ Value_FirstColorRole
@ Value_LowerRoman
@ Value_Top
@ Value_None
@ Value_Highlight
@ Value_Bold
@ Value_Dark
@ Value_Center
@ Value_Right
@ Value_Sub
@ Value_Text
@ Value_PreLine
@ Value_HighlightedText
@ Value_WindowText
@ Value_Underline
@ Value_DotDash
@ Value_Uppercase
@ Value_Auto
@ Value_Inset
@ Value_Large
@ Value_XLarge
@ Value_SmallCaps
@ Value_Double
@ Value_AlternateBase
@ Value_Mid
@ Value_Overline
@ Value_Ridge
@ Value_UpperAlpha
@ Value_Dashed
@ Value_BrightText
@ Value_Always
@ Value_LinkVisited
@ Value_Dotted
@ Value_Middle
@ Value_Window
@ Value_Lowercase
@ Value_Italic
@ BorderImage
@ BorderTopLeftRadius
@ BackgroundColor
@ Whitespace
@ OutlineTopLeftRadius
@ MarginLeft
@ QtAlternateBackground
@ BorderTopColor
@ QtPlaceHolderTextColor
@ MarginRight
@ BorderBottomLeftRadius
@ QtTableType
@ BorderBottom
@ Padding
@ QtStyleFeatures
@ BorderTopStyle
@ OutlineBottomRightRadius
@ FontKerning
@ NumProperties
@ BorderRightWidth
@ PaddingRight
@ BackgroundOrigin
@ BorderBottomColor
@ MarginTop
@ TextUnderlineStyle
@ QtListIndent
@ PaddingLeft
@ PaddingTop
@ QtSpacing
@ BorderLeftColor
@ OutlineTopRightRadius
@ BorderRightColor
@ QtSelectionForeground
@ PaddingBottom
@ LetterSpacing
@ BorderBottomRightRadius
@ QtListNumberPrefix
@ OutlineWidth
@ PageBreakAfter
@ BorderRight
@ OutlineColor
@ OutlineBottomLeftRadius
@ FontWeight
@ QtBackgroundRole
@ QtForegroundTextureCacheKey
@ TextIndent
@ QtPosition
@ BorderColor
@ MarginBottom
@ MaximumWidth
@ QtUserState
@ OutlineStyle
@ BorderLeftWidth
@ BorderCollapse
@ QtBlockIndent
@ BackgroundPosition
@ WordSpacing
@ BackgroundImage
@ BorderRightStyle
@ FontStyle
@ TextTransform
@ FontFamily
@ FontVariant
@ BorderWidth
@ VerticalAlignment
@ LineHeight
@ QtParagraphType
@ QtSelectionBackground
@ QtAccentColor
@ BorderStyles
@ BorderLeft
@ TextDecoration
@ BorderTopRightRadius
@ ListStyleType
@ OutlineOffset
@ BorderRadius
@ ListStyle
@ BorderBottomWidth
@ Background
@ BorderTopWidth
@ OutlineRadius
@ MinimumWidth
@ BackgroundAttachment
@ TextAlignment
@ BackgroundClip
@ TextDecorationColor
@ QtListNumberSuffix
@ QtImageAlignment
@ BorderBottomStyle
@ BorderTop
@ FontSize
@ PageBreakBefore
@ QtLineHeightType
@ BackgroundRepeat
@ BorderLeftStyle
@ MinimumHeight
@ MaximumHeight
const quint64 PseudoClass_Window
const quint64 PseudoClass_Minimized
@ TileMode_Repeat
@ NumKnownTileModes
@ TileMode_Round
@ TileMode_Stretch
StyleSheetOrigin
const quint64 PseudoClass_Unspecified
const quint64 PseudoClass_Unchecked
const quint64 PseudoClass_First
const quint64 PseudoClass_Indeterminate
const quint64 PseudoClass_Middle
@ PositionMode_Absolute
@ PositionMode_Relative
@ PositionMode_Unknown
@ PositionMode_Static
@ PositionMode_Fixed
@ NumKnownPositionModes
const quint64 PseudoClass_Top
const quint64 PseudoClass_Hover
@ BorderStyle_Dotted
@ BorderStyle_Solid
@ BorderStyle_Double
@ BorderStyle_DotDash
@ BorderStyle_Ridge
@ BorderStyle_Unknown
@ BorderStyle_Dashed
@ BorderStyle_Outset
@ BorderStyle_Groove
@ BorderStyle_Native
@ BorderStyle_None
@ BorderStyle_DotDotDash
@ BorderStyle_Inset
const quint64 PseudoClass_Left
const quint64 PseudoClass_Last
const quint64 PseudoClass_OnlyOne
const quint64 PseudoClass_Exclusive
Combined button and popup list for selecting options.
@ AlignRight
Definition qnamespace.h:145
@ AlignBottom
Definition qnamespace.h:153
@ AlignVCenter
Definition qnamespace.h:154
@ AlignTop
Definition qnamespace.h:152
@ AlignHCenter
Definition qnamespace.h:147
@ AlignCenter
Definition qnamespace.h:162
@ AlignLeft
Definition qnamespace.h:143
@ transparent
Definition qnamespace.h:46
CaseSensitivity
@ CaseInsensitive
@ SkipEmptyParts
Definition qnamespace.h:127
Definition brush.cpp:5
Definition image.cpp:4
QPair< qreal, QColor > QGradientStop
Definition qbrush.h:131
#define rgb(r, g, b)
Definition qcolor.cpp:124
static void setTextDecorationFromValues(const QList< QCss::Value > &values, QFont *font)
static void removeOptionalQuotes(QString *str)
static bool setFontFamilyFromValues(const QList< QCss::Value > &values, QFont *font, int start=0)
static bool setFontWeightFromValue(const QCss::Value &value, QFont *font)
static const QCssKnownValue origins[NumKnownOrigins - 1]
static int lengthValueFromData(const LengthData &data, const QFont &f)
static void setTextTransformFromValue(const QCss::Value &value, QFont *font)
static bool setFontSizeFromValue(QCss::Value value, QFont *font, int *fontSizeAdjustment)
static const QCssKnownValue pseudos[NumPseudos - 1]
static bool setFontStyleFromValue(const QCss::Value &value, QFont *font)
static ColorData parseColorValue(QCss::Value v)
static BorderStyle parseStyleValue(const QCss::Value &v)
static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1]
static void setFontVariantFromValue(const QCss::Value &value, QFont *font)
static bool intValueHelper(const QCss::Value &v, int *i, const char *unit)
static quint64 findKnownValue(const QString &name, const QCssKnownValue *start, int numValues)
static const QCssKnownValue positions[NumKnownPositionModes - 1]
static Qt::Alignment parseAlignment(const QCss::Value *values, int count)
static void setLetterSpacingFromValue(const QCss::Value &value, QFont *font)
static BrushData parseBrushValue(const QCss::Value &v, const QPalette &pal)
static const QCssKnownValue properties[NumProperties - 1]
static bool isHexDigit(const char c)
static bool isInheritable(Property propertyId)
static bool setFontKerningFromValue(const QCss::Value &value, QFont *font)
static void parseShorthandBackgroundProperty(const QList< QCss::Value > &values, BrushData *brush, QString *image, Repeat *repeat, Qt::Alignment *alignment, const QPalette &pal)
static void parseShorthandFontProperty(const QList< QCss::Value > &values, QFont *font, int *fontSizeAdjustment)
static const QCssKnownValue tileModes[NumKnownTileModes - 1]
static QBrush brushFromData(const BrushData &c, const QPalette &pal)
static const short indexOfId[NumKnownValues]
static void setWordSpacingFromValue(const QCss::Value &value, QFont *font)
static const QCssKnownValue repeats[NumKnownRepeats - 1]
static QColor colorFromData(const ColorData &c, const QPalette &pal)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char * rule
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
int qRound(qfloat16 d) noexcept
Definition qfloat16.h:281
#define qWarning
Definition qlogging.h:162
#define QT_IMPL_METATYPE_EXTERN_TAGGED(TYPE, TAG)
Definition qmetatype.h:1363
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
GLint GLfloat GLfloat GLfloat v2
GLenum GLsizei GLsizei GLint * values
[15]
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum mode
const GLfloat * m
GLuint64 key
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei const GLuint * ids
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLfloat GLfloat f
GLuint GLuint GLfloat weight
GLint GLsizei width
GLint left
GLenum type
GLint GLint bottom
GLenum target
GLint GLfloat GLfloat v1
GLsizei const GLenum * attachments
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint GLfloat GLfloat GLfloat GLfloat v3
GLenum attachment
GLuint name
GLfloat GLfloat GLfloat GLfloat h
GLenum func
Definition qopenglext.h:663
const GLubyte * c
GLuint GLfloat * val
GLuint GLuint * names
GLuint GLsizei const GLuint const GLintptr * offsets
GLenum GLsizei len
GLdouble GLdouble t
Definition qopenglext.h:243
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLenum GLuint GLenum target2
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
GLfloat GLfloat GLfloat alpha
Definition qopenglext.h:418
GLenum GLenum GLenum GLenum GLenum scale
GLenum GLenum GLenum input
@ Bottom
@ Top
@ Left
@ Right
static bool hasAlpha(const QImage &image)
static QT_BEGIN_NAMESPACE bool isRelative(const QString &path)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
static QT_BEGIN_NAMESPACE const QRgb colors[][14]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
static bool operator<(const QSettingsIniKey &k1, const QSettingsIniKey &k2)
#define qPrintable(string)
Definition qstring.h:1391
#define zero
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
static int compare(quint64 a, quint64 b)
unsigned long long quint64
Definition qtypes.h:56
unsigned int uint
Definition qtypes.h:29
double qreal
Definition qtypes.h:92
static int toInt(const QChar &qc, int R)
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QFileSelector selector
[1]
QUrl url("example.com")
[constructor-url-reference]
QVariant variant
[1]
QJSValueList args
const char name[28]
ValueMatchType valueMatchCriterium
QList< Pseudo > pseudos
QList< AttributeSelector > attributeSelectors
enum QCss::BrushData::@403 type
enum QCss::ColorData::@401 type
void colorValues(QColor *c, const QPalette &=QPalette()) const
int styleFeaturesValue() const
Attachment attachmentValue() const
Origin originValue() const
QIcon iconValue() const
void styleValues(BorderStyle *s) const
Qt::Alignment alignmentValue() const
bool realValue(qreal *r, const char *unit=nullptr) const
QExplicitlySharedDataPointer< DeclarationData > d
QColor colorValue(const QPalette &=QPalette()) const
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const
void brushValues(QBrush *c, const QPalette &=QPalette()) const
bool intValue(int *i, const char *unit=nullptr) const
QRect rectValue() const
BorderStyle styleValue() const
Repeat repeatValue() const
PositionMode positionValue() const
bool borderCollapseValue() const
QBrush brushValue(const QPalette &=QPalette()) const
bool isEmpty() const
QString uriValue() const
QSize sizeValue() const
QStringList media
QStringList media
QList< StyleRule > styleRules
QList< Declaration > declarations
QString function
int specificity() const
QList< BasicSelector > basicSelectors
QString pseudoElement() const
quint64 pseudoClass(quint64 *negated=nullptr) const
QList< Selector > selectors
QList< Declaration > declarations
QList< StyleRule > styleRules
QList< MediaRule > mediaRules
Q_GUI_EXPORT void buildIndexes(Qt::CaseSensitivity nameCaseSensitivity=Qt::CaseSensitive)
QMultiHash< QString, StyleRule > idIndex
QMultiHash< QString, StyleRule > nameIndex
StyleSheetOrigin origin
QList< ImportRule > importRules
QList< PageRule > pageRules
TokenType token
Q_GUI_EXPORT QString lexem() const
bool extractIcon(QIcon *icon, QSize *size)
bool extractPosition(int *l, int *t, int *r, int *b, QCss::Origin *, Qt::Alignment *, QCss::PositionMode *, Qt::Alignment *)
bool extractGeometry(int *w, int *h, int *minw, int *minh, int *maxw, int *maxh)
bool extractBox(int *margins, int *paddings, int *spacing=nullptr)
bool extractFont(QFont *font, int *fontSizeAdjustment)
void lengthValues(const Declaration &decl, int *m)
bool extractPalette(QBrush *foreground, QBrush *selectedForeground, QBrush *selectedBackground, QBrush *alternateBackground, QBrush *placeHolderTextForeground, QBrush *accentColor)
ValueExtractor(const QList< Declaration > &declarations, const QPalette &=QPalette())
bool extractBorder(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii)
bool extractImage(QIcon *icon, Qt::Alignment *a, QSize *size)
bool extractOutline(int *borders, QBrush *colors, BorderStyle *Styles, QSize *radii, int *offsets)
bool extractBackground(QBrush *, QString *, Repeat *, Qt::Alignment *, QCss::Origin *, QCss::Attachment *, QCss::Origin *)
QVariant variant
Q_GUI_EXPORT QString toString() const