+QBrush QssParser::parseBrush(const QString& str, bool* ok)
+{
+ if (ok)
+ *ok = false;
+ QColor c = parseColor(str);
+ if (c.isValid()) {
+ if (ok)
+ *ok = true;
+ return QBrush(c);
+ }
+
+ if (str.startsWith("palette")) { // Palette color role
+ // Does the palette follow the expected format? For example:
+ // palette(marker-line)
+ // palette ( system-color-0f )
+ //
+ // Match the palette marker, grabbing the name inside in case-sensitive manner
+ // palette\s*\(\s*([a-z-0-9]+)\s*\)
+ // palette Match the string 'palette'
+ // \s* Match any amount of whitespace
+ // \(, \) Match literal '(' or ')' marks
+ // (...+) Match contents between 1 and unlimited number of times
+ // [a-z-] Match any character from a-z, case sensitive
+ // [0-9] Match any digit from 0-9
+ // Note that '\' must be escaped as '\\'
+ // Helpful interactive website for debugging and explaining: https://regex101.com/
+ static const QRegExp rx(R"(palette\s*\(\s*([a-z-0-9]+)\s*\))");
+ if (!rx.exactMatch(str)) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid palette color role specification: %1").arg(str);
+ return QBrush();
+ }
+ if (_paletteColorRoles.contains(rx.cap(1)))
+ return QBrush(_palette.brush(_paletteColorRoles.value(rx.cap(1))));
+ if (_uiStyleColorRoles.contains(rx.cap(1)))
+ return QBrush(_uiStylePalette.at(static_cast<int>(_uiStyleColorRoles.value(rx.cap(1)))));
+ qWarning() << Q_FUNC_INFO << tr("Unknown palette color role: %1").arg(rx.cap(1));
+ return QBrush();
+ }
+ else if (str.startsWith("qlineargradient")) {
+ static const QString rxFloat(R"(\s*(-?\s*[0-9]*\.?[0-9]+)\s*)");
+ static const QRegExp rx(QString(R"(qlineargradient\s*\(\s*x1:%1,\s*y1:%1,\s*x2:%1,\s*y2:%1,(.+)\))").arg(rxFloat));
+ if (!rx.exactMatch(str)) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str);
+ return QBrush();
+ }
+ qreal x1 = rx.cap(1).toDouble();
+ qreal y1 = rx.cap(2).toDouble();
+ qreal x2 = rx.cap(3).toDouble();
+ qreal y2 = rx.cap(4).toDouble();
+ QGradientStops stops = parseGradientStops(rx.cap(5).trimmed());
+ if (!stops.count()) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str);
+ return QBrush();
+ }
+ QLinearGradient gradient(x1, y1, x2, y2);
+ gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ gradient.setStops(stops);
+ if (ok)
+ *ok = true;
+ return QBrush(gradient);
+ }
+ else if (str.startsWith("qconicalgradient")) {
+ static const QString rxFloat(R"(\s*(-?\s*[0-9]*\.?[0-9]+)\s*)");
+ static const QRegExp rx(QString(R"(qconicalgradient\s*\(\s*cx:%1,\s*cy:%1,\s*angle:%1,(.+)\))").arg(rxFloat));
+ if (!rx.exactMatch(str)) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str);
+ return QBrush();
+ }
+ qreal cx = rx.cap(1).toDouble();
+ qreal cy = rx.cap(2).toDouble();
+ qreal angle = rx.cap(3).toDouble();
+ QGradientStops stops = parseGradientStops(rx.cap(4).trimmed());
+ if (!stops.count()) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str);
+ return QBrush();
+ }
+ QConicalGradient gradient(cx, cy, angle);
+ gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ gradient.setStops(stops);
+ if (ok)
+ *ok = true;
+ return QBrush(gradient);
+ }
+ else if (str.startsWith("qradialgradient")) {
+ static const QString rxFloat(R"(\s*(-?\s*[0-9]*\.?[0-9]+)\s*)");
+ static const QRegExp rx(QString(R"(qradialgradient\s*\(\s*cx:%1,\s*cy:%1,\s*radius:%1,\s*fx:%1,\s*fy:%1,(.+)\))").arg(rxFloat));
+ if (!rx.exactMatch(str)) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient declaration: %1").arg(str);
+ return QBrush();
+ }
+ qreal cx = rx.cap(1).toDouble();
+ qreal cy = rx.cap(2).toDouble();
+ qreal radius = rx.cap(3).toDouble();
+ qreal fx = rx.cap(4).toDouble();
+ qreal fy = rx.cap(5).toDouble();
+ QGradientStops stops = parseGradientStops(rx.cap(6).trimmed());
+ if (!stops.count()) {
+ qWarning() << Q_FUNC_INFO << tr("Invalid gradient stops list: %1").arg(str);
+ return QBrush();
+ }
+ QRadialGradient gradient(cx, cy, radius, fx, fy);
+ gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
+ gradient.setStops(stops);
+ if (ok)
+ *ok = true;
+ return QBrush(gradient);
+ }