diff options
-rw-r--r-- | src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc | 3 | ||||
-rw-r--r-- | src/widgets/styles/qstylesheetstyle.cpp | 72 | ||||
-rw-r--r-- | tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp | 28 |
3 files changed, 80 insertions, 23 deletions
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index f4edfb92dc..44f20ca0ae 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -3027,7 +3027,8 @@ \list \li \c px: pixels \li \c pt: the size of one point (i.e., 1/72 of an inch) - \li \c em: the em width of the font (i.e., the width of 'M') + \li \c em: the size relative to the font size of the element + (e.g., 2em means 2 times the size of the font) \li \c ex: the x-height of the font (i.e., the height of 'x') \endlist diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index bc23dfd6ac..d5eafa2e9d 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -1051,31 +1051,59 @@ QRenderRule::QRenderRule(const QList<Declaration> &declarations, const QObject * for (int i = 0; i < numKnownStyleHints; i++) { QLatin1String styleHint(knownStyleHints[i]); if (decl.d->property.compare(styleHint) == 0) { - QString hintName = QString(styleHint); - QVariant hintValue; - if (hintName.endsWith(QLatin1String("alignment"))) { - hintValue = (int) decl.alignmentValue(); - } else if (hintName.endsWith(QLatin1String("color"))) { - hintValue = (int) decl.colorValue().rgba(); - } else if (hintName.endsWith(QLatin1String("size"))) { - hintValue = decl.sizeValue(); - } else if (hintName.endsWith(QLatin1String("icon"))) { - hintValue = decl.iconValue(); - } else if (hintName == QLatin1String("button-layout") - && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) { - hintValue = subControlLayout(decl.d->values.at(0).variant.toString()); - } else { - int integer; - decl.intValue(&integer); - hintValue = integer; - } - styleHints[decl.d->property] = hintValue; - knownStyleHint = true; - break; + QString hintName = QString(styleHint); + QVariant hintValue; + if (hintName.endsWith(QLatin1String("alignment"))) { + hintValue = (int) decl.alignmentValue(); + } else if (hintName.endsWith(QLatin1String("color"))) { + hintValue = (int) decl.colorValue().rgba(); + } else if (hintName.endsWith(QLatin1String("size"))) { + // Check only for the 'em' case + const QString valueString = decl.d->values.at(0).variant.toString(); + const bool isEmSize = valueString.endsWith(u"em", Qt::CaseInsensitive); + if (isEmSize || valueString.endsWith(u"ex", Qt::CaseInsensitive)) { + // 1em == size of font; 1ex == xHeight of font + // See lengthValueFromData helper in qcssparser.cpp + QFont fontForSize(font); + // if no font is specified, then use the widget font if possible + if (const QWidget *widget; !hasFont && (widget = qobject_cast<const QWidget*>(object))) + fontForSize = widget->font(); + + const QFontMetrics fontMetrics(fontForSize); + qreal pixelSize = isEmSize ? fontMetrics.height() : fontMetrics.xHeight(); + + // Transform size according to the 'em'/'ex' value + qreal emexSize = {}; + if (decl.realValue(&emexSize, isEmSize ? "em" : "ex") && emexSize > 0) { + pixelSize *= emexSize; + const QSizeF newSize(pixelSize, pixelSize); + decl.d->parsed = QVariant::fromValue<QSizeF>(newSize); + hintValue = newSize; + } else { + qWarning("Invalid '%s' size for %s. Skipping.", + isEmSize ? "em" : "ex", qPrintable(valueString)); + } + } else { + // Normal case where we receive a 'px' or 'pt' unit + hintValue = decl.sizeValue(); + } + } else if (hintName.endsWith(QLatin1String("icon"))) { + hintValue = decl.iconValue(); + } else if (hintName == QLatin1String("button-layout") + && decl.d->values.count() != 0 && decl.d->values.at(0).type == Value::String) { + hintValue = subControlLayout(decl.d->values.at(0).variant.toString()); + } else { + int integer; + decl.intValue(&integer); + hintValue = integer; + } + styleHints[decl.d->property] = hintValue; + knownStyleHint = true; + break; } } if (!knownStyleHint) - qDebug("Unknown property %s", qPrintable(decl.d->property)); + qWarning("Unknown property %s", qPrintable(decl.d->property)); } } diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 63db23f3b0..272c175042 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -2352,12 +2352,40 @@ void tst_QStyleSheetStyle::iconSizes_data() smallFont.setPointSizeF(9.0); QFont largeFont; largeFont.setPointSizeF(24.0); + QFont hugeFont; + hugeFont.setPointSizeF(40.0); QTest::addRow("default") << QString() << QFont() << QSize(defaultSize, defaultSize); QTest::addRow("pixels") << "icon-size: 50px" << QFont() << QSize(50, 50); QTest::addRow("points") << "icon-size: 20pt" << QFont() << QSize(15, 15); QTest::addRow("pixels with font") << "icon-size: 50px" << smallFont << QSize(50, 50); QTest::addRow("points with font") << "icon-size: 20pt" << largeFont << QSize(15, 15); + + const QFontMetrics defaultMetrics{QFont()}; + const QFontMetrics smallMetrics(smallFont); + const QFontMetrics largeMetrics(largeFont); + const QFontMetrics hugeMetrics(hugeFont); + QTest::addRow("1em, default font") << "icon-size: 1em" + << QFont() << QSize(defaultMetrics.height(), defaultMetrics.height()); + QTest::addRow("1em, small font") << "icon-size: 1em" + << smallFont << QSize(smallMetrics.height(), smallMetrics.height()); + QTest::addRow("1em, large font") << "icon-size: 1em" + << largeFont << QSize(largeMetrics.height(), largeMetrics.height()); + QTest::addRow("1.5em, lage font") << "icon-size: 1.5em" + << largeFont << QSize(largeMetrics.height(), largeMetrics.height()) * 1.5; + QTest::addRow("2em with styled font") << "font-size: 40pt; icon-size: 2em" + << QFont() << QSize(hugeMetrics.height(), hugeMetrics.height()) * 2; + + QTest::addRow("1ex, default font") << "icon-size: 1ex" + << QFont() << QSize(defaultMetrics.xHeight(), defaultMetrics.xHeight()); + QTest::addRow("1ex, small font") << "icon-size: 1ex" + << smallFont << QSize(smallMetrics.xHeight(), smallMetrics.xHeight()); + QTest::addRow("1ex, large font") << "icon-size: 1ex" + << largeFont << QSize(largeMetrics.xHeight(), largeMetrics.xHeight()); + QTest::addRow("1.5ex, lage font") << "icon-size: 1.5ex" + << largeFont << QSize(largeMetrics.xHeight(), largeMetrics.xHeight()) * 1.5; + QTest::addRow("2ex with styled font") << "font-size: 40pt; icon-size: 2ex" + << QFont() << QSize(hugeMetrics.xHeight(), hugeMetrics.xHeight()) * 2; } void tst_QStyleSheetStyle::iconSizes() |