diff options
author | Liang Qi <liang.qi@qt.io> | 2022-12-09 02:19:50 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2022-12-09 02:19:50 +0100 |
commit | f756c201c56454f4162de05a3c6bc264e8b7a758 (patch) | |
tree | ffb3a0a48acbed663c04faf1f25f07cedd0511ce | |
parent | 21bf976a411a65a1c945aae994afbcb8590e50e4 (diff) | |
parent | 871fe574cf942c0a1ddb936a169553cdb6a93249 (diff) |
Merge "Merge remote-tracking branch 'origin/wip/material3' into dev"
23 files changed, 795 insertions, 202 deletions
diff --git a/src/quickcontrols/doc/src/external-pages.qdoc b/src/quickcontrols/doc/src/external-pages.qdoc index 591533c2c7..d78f94cc12 100644 --- a/src/quickcontrols/doc/src/external-pages.qdoc +++ b/src/quickcontrols/doc/src/external-pages.qdoc @@ -10,3 +10,8 @@ \externalpage https://doc.qt.io/qtcreator/creator-project-creating.html#selecting-project-type \title Qt Creator: Project Types */ + +/*! + \externalpage https://m3.material.io/styles/shape/overview + \title Material Style: Shape +*/ diff --git a/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc b/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc index 36e3b96a97..7b17b23a59 100644 --- a/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc +++ b/src/quickcontrols/doc/src/qtquickcontrols-material.qdoc @@ -19,6 +19,7 @@ \li \l {material-foreground-attached-prop}{\b foreground} : color \li \l {material-primary-attached-prop}{\b primary} : color \li \l {material-theme-attached-prop}{\b theme} : enumeration + \li \l {material-roundedScale-attached-prop}{\b roundedScale} : enumeration \endlist \section1 Attached Methods @@ -355,6 +356,29 @@ \endstyleproperty + \styleproperty {Material.roundedScale} {enumeration} {material-roundedScale-attached-prop} + \target material-roundedScale-attached-prop + This attached property holds the radius of rounded corners used on the + target control. The property can be attached to any window or item, but + only some controls support it. + + The default value is control-specific. + + Available scales: + \value Material.NotRounded Square corners + \value Material.ExtraSmallScale Extra small rounded corners + \value Material.SmallScale Small rounded corners + \value Material.MediumScale Medium rounded corners + \value Material.LargeScale Large rounded corners + \value Material.ExtraLargeScale Extra large rounded corners + \value Material.FullScale Fully rounded corners + + This property was added in Qt 6.5. + + See also: \l {Material Style: Shape}. + + \endstyleproperty + \section1 Attached Method Documentation \stylemethod2 {color} {color} {enumeration} {predefined} {enumeration} {shade} {material-color-attached-method} diff --git a/src/quickcontrols/material/Button.qml b/src/quickcontrols/material/Button.qml index f2828b1eeb..e2bbb58687 100644 --- a/src/quickcontrols/material/Button.qml +++ b/src/quickcontrols/material/Button.qml @@ -17,19 +17,22 @@ T.Button { topInset: 6 bottomInset: 6 - padding: 12 - horizontalPadding: padding - 4 - spacing: 6 + verticalPadding: 14 + // https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382 + leftPadding: !flat ? (!hasIcon ? 24 : 16) : 12 + rightPadding: !flat ? 24 : (!hasIcon ? 12 : 16) + spacing: 8 icon.width: 24 icon.height: 24 icon.color: !enabled ? Material.hintTextColor : - flat && highlighted ? Material.accentColor : + (control.flat && control.highlighted) || (control.checked && !control.highlighted) ? Material.accentColor : highlighted ? Material.primaryHighlightedTextColor : Material.foreground - Material.elevation: flat ? control.down || (enabled && control.hovered) ? 2 : 0 - : control.down ? 8 : 2 - Material.background: flat ? "transparent" : undefined + readonly property bool hasIcon: icon.name.length > 0 || icon.source.toString().length > 0 + + Material.elevation: control.down ? 8 : 2 + Material.roundedScale: Material.FullScale contentItem: IconLabel { spacing: control.spacing @@ -40,7 +43,7 @@ T.Button { text: control.text font: control.font color: !control.enabled ? control.Material.hintTextColor : - control.flat && control.highlighted ? control.Material.accentColor : + (control.flat && control.highlighted) || (control.checked && !control.highlighted) ? control.Material.accentColor : control.highlighted ? control.Material.primaryHighlightedTextColor : control.Material.foreground } @@ -48,32 +51,22 @@ T.Button { implicitWidth: 64 implicitHeight: control.Material.buttonHeight - radius: 2 - color: !control.enabled ? control.Material.buttonDisabledColor : - control.highlighted ? (control.checked ? control.Material.highlightedCheckedButtonColor : - control.Material.highlightedButtonColor) : control.Material.buttonColor - - PaddedRectangle { - y: parent.height - 4 - width: parent.width - height: 4 - radius: 2 - topPadding: -2 - clip: true - visible: control.checkable && (!control.highlighted || control.flat) - color: control.checked && control.enabled ? control.Material.accentColor : control.Material.secondaryTextColor - } + radius: control.Material.roundedScale === Material.FullScale ? height / 2 : control.Material.roundedScale + color: control.Material.buttonColor(control.Material.theme, control.Material.background, + control.Material.accent, control.enabled, control.flat, control.highlighted, control.checked) // The layer is disabled when the button color is transparent so you can do // Material.background: "transparent" and get a proper flat button without needing // to set Material.elevation as well - layer.enabled: control.enabled && control.Material.buttonColor.a > 0 - layer.effect: ElevationEffect { + layer.enabled: control.enabled && color.a > 0 && !control.flat + layer.effect: RoundedElevationEffect { elevation: control.Material.elevation + roundedScale: control.background.radius } Ripple { - clipRadius: 2 + clip: true + clipRadius: parent.radius width: parent.width height: parent.height pressed: control.pressed diff --git a/src/quickcontrols/material/DelayButton.qml b/src/quickcontrols/material/DelayButton.qml index f050d57a39..b18550541c 100644 --- a/src/quickcontrols/material/DelayButton.qml +++ b/src/quickcontrols/material/DelayButton.qml @@ -43,7 +43,8 @@ T.DelayButton { implicitHeight: control.Material.buttonHeight radius: 2 - color: !control.enabled ? control.Material.buttonDisabledColor : control.Material.buttonColor + color: control.Material.buttonColor(control.Material.theme, control.Material.background, + control.Material.accent, control.enabled, false /*flat*/, false /*highlighted*/, false /*checked*/) PaddedRectangle { y: parent.height - 4 @@ -65,7 +66,7 @@ T.DelayButton { } } - layer.enabled: control.enabled && control.Material.buttonColor.a > 0 + layer.enabled: control.enabled && color.a > 0 && !control.flat layer.effect: ElevationEffect { elevation: control.Material.elevation } diff --git a/src/quickcontrols/material/RoundButton.qml b/src/quickcontrols/material/RoundButton.qml index 3484fb9460..4e3db36fca 100644 --- a/src/quickcontrols/material/RoundButton.qml +++ b/src/quickcontrols/material/RoundButton.qml @@ -28,8 +28,7 @@ T.RoundButton { flat && highlighted ? Material.accentColor : highlighted ? Material.primaryHighlightedTextColor : Material.foreground - Material.elevation: flat ? control.down || control.hovered ? 2 : 0 - : control.down ? 12 : 6 + Material.elevation: control.down ? 8 : 2 Material.background: flat ? "transparent" : undefined contentItem: IconLabel { @@ -51,8 +50,8 @@ T.RoundButton { implicitHeight: control.Material.buttonHeight radius: control.radius - color: !control.enabled ? control.Material.buttonDisabledColor - : control.checked || control.highlighted ? control.Material.highlightedButtonColor : control.Material.buttonColor + color: control.Material.buttonColor(control.Material.theme, control.Material.background, + control.Material.accent, control.enabled, control.flat, control.highlighted, false /*checked*/) Rectangle { width: parent.width @@ -73,7 +72,7 @@ T.RoundButton { // The layer is disabled when the button color is transparent so that you can do // Material.background: "transparent" and get a proper flat button without needing // to set Material.elevation as well - layer.enabled: control.enabled && control.Material.buttonColor.a > 0 + layer.enabled: control.enabled && color.a > 0 && !control.flat layer.effect: ElevationEffect { elevation: control.Material.elevation } diff --git a/src/quickcontrols/material/impl/BoxShadow.qml b/src/quickcontrols/material/impl/BoxShadow.qml index f77412d554..d702389cdf 100644 --- a/src/quickcontrols/material/impl/BoxShadow.qml +++ b/src/quickcontrols/material/impl/BoxShadow.qml @@ -16,6 +16,12 @@ RectangularGlow { property int blurRadius property int spreadRadius + // The strength of the shadow. We have this because RectangularGlow spreads + // out the shadow thinly, whereas lower elevation levels in Material 3 + // are less spread out and stronger. This is only used for items with fully-rounded + // corners, like buttons. + property real strength + // The source item the shadow is being applied to, used for correctly // calculating the corner radious property Item source @@ -23,6 +29,10 @@ RectangularGlow { property bool fullWidth property bool fullHeight + // qmllint disable unqualified + // Intentionally duck-typed (QTBUG-94807) + readonly property real sourceRadius: source && source.radius || 0 + x: (parent.width - width)/2 + offsetX y: (parent.height - height)/2 + offsetY @@ -32,8 +42,7 @@ RectangularGlow { width: implicitWidth + 2 * spreadRadius + (fullWidth ? 2 * cornerRadius : 0) height: implicitHeight + 2 * spreadRadius + (fullHeight ? 2 * cornerRadius : 0) glowRadius: blurRadius/2 - spread: 0.05 - // qmllint disable unqualified - // Intentionally duck-typed (QTBUG-94807) - cornerRadius: blurRadius + (source && source.radius || 0) + spread: strength + + cornerRadius: blurRadius + sourceRadius } diff --git a/src/quickcontrols/material/impl/CMakeLists.txt b/src/quickcontrols/material/impl/CMakeLists.txt index 8b8e2311b4..ebf3e1cbf3 100644 --- a/src/quickcontrols/material/impl/CMakeLists.txt +++ b/src/quickcontrols/material/impl/CMakeLists.txt @@ -12,6 +12,7 @@ set(qml_files "ElevationEffect.qml" "RadioIndicator.qml" "RectangularGlow.qml" + "RoundedElevationEffect.qml" "SliderHandle.qml" "SwitchIndicator.qml" ) diff --git a/src/quickcontrols/material/impl/ElevationEffect.qml b/src/quickcontrols/material/impl/ElevationEffect.qml index 6690567617..29ec742f4a 100644 --- a/src/quickcontrols/material/impl/ElevationEffect.qml +++ b/src/quickcontrols/material/impl/ElevationEffect.qml @@ -75,106 +75,113 @@ Item { The shadows to use for each possible elevation. There are three shadows that when combined make up the elevation. */ - readonly property var _shadows: [ - [{offset: 0, blur: 0, spread: 0}, - {offset: 0, blur: 0, spread: 0}, - {offset: 0, blur: 0, spread: 0}], - - [{offset: 1, blur: 3, spread: 0}, - {offset: 1, blur: 1, spread: 0}, - {offset: 2, blur: 1, spread: -1}], - - [{offset: 1, blur: 5, spread: 0}, - {offset: 2, blur: 2, spread: 0}, - {offset: 3, blur: 1, spread: -2}], - - [{offset: 1, blur: 8, spread: 0}, - {offset: 3, blur: 4, spread: 0}, - {offset: 3, blur: 3, spread: -2}], - - [{offset: 2, blur: 4, spread: -1}, - {offset: 4, blur: 5, spread: 0}, - {offset: 1, blur: 10, spread: 0}], - - [{offset: 3, blur: 5, spread: -1}, - {offset: 5, blur: 8, spread: 0}, - {offset: 1, blur: 14, spread: 0}], - - [{offset: 3, blur: 5, spread: -1}, - {offset: 6, blur: 10, spread: 0}, - {offset: 1, blur: 18, spread: 0}], - - [{offset: 4, blur: 5, spread: -2}, - {offset: 7, blur: 10, spread: 1}, - {offset: 2, blur: 16, spread: 1}], - - [{offset: 5, blur: 5, spread: -3}, - {offset: 8, blur: 10, spread: 1}, - {offset: 3, blur: 14, spread: 2}], - - [{offset: 5, blur: 6, spread: -3}, - {offset: 9, blur: 12, spread: 1}, - {offset: 3, blur: 16, spread: 2}], - - [{offset: 6, blur: 6, spread: -3}, - {offset: 10, blur: 14, spread: 1}, - {offset: 4, blur: 18, spread: 3}], - - [{offset: 6, blur: 7, spread: -4}, - {offset: 11, blur: 15, spread: 1}, - {offset: 4, blur: 20, spread: 3}], - - [{offset: 7, blur: 8, spread: -4}, - {offset: 12, blur: 17, spread: 2}, - {offset: 5, blur: 22, spread: 4}], - - [{offset: 7, blur: 8, spread: -4}, - {offset: 13, blur: 19, spread: 2}, - {offset: 5, blur: 24, spread: 4}], - - [{offset: 7, blur: 9, spread: -4}, - {offset: 14, blur: 21, spread: 2}, - {offset: 5, blur: 26, spread: 4}], - - [{offset: 8, blur: 9, spread: -5}, - {offset: 15, blur: 22, spread: 2}, - {offset: 6, blur: 28, spread: 5}], - - [{offset: 8, blur: 10, spread: -5}, - {offset: 16, blur: 24, spread: 2}, - {offset: 6, blur: 30, spread: 5}], - - [{offset: 8, blur: 11, spread: -5}, - {offset: 17, blur: 26, spread: 2}, - {offset: 6, blur: 32, spread: 5}], - - [{offset: 9, blur: 11, spread: -5}, - {offset: 18, blur: 28, spread: 2}, - {offset: 7, blur: 34, spread: 6}], - - [{offset: 9, blur: 12, spread: -6}, - {offset: 19, blur: 29, spread: 2}, - {offset: 7, blur: 36, spread: 6}], - - [{offset: 10, blur: 13, spread: -6}, - {offset: 20, blur: 31, spread: 3}, - {offset: 8, blur: 38, spread: 7}], - - [{offset: 10, blur: 13, spread: -6}, - {offset: 21, blur: 33, spread: 3}, - {offset: 8, blur: 40, spread: 7}], - - [{offset: 10, blur: 14, spread: -6}, - {offset: 22, blur: 35, spread: 3}, - {offset: 8, blur: 42, spread: 7}], - - [{offset: 11, blur: 14, spread: -7}, - {offset: 23, blur: 36, spread: 3}, - {offset: 9, blur: 44, spread: 8}], - - [{offset: 11, blur: 15, spread: -7}, - {offset: 24, blur: 38, spread: 3}, - {offset: 9, blur: 46, spread: 8}] + property var _shadows: _defaultShadows + + readonly property var _defaultShadows: [ + { // 0 + angularValues: [ + {offset: 0, blur: 0, spread: 0}, + {offset: 0, blur: 0, spread: 0}, + {offset: 0, blur: 0, spread: 0} + ], + strength: 0.05 + }, + { // 1 + angularValues: [ + {offset: 1, blur: 3, spread: 0}, + {offset: 1, blur: 1, spread: 0}, + {offset: 2, blur: 1, spread: -1} + ], + strength: 0.05 + }, + { // 2 + angularValues: [ + {offset: 1, blur: 5, spread: 0}, + {offset: 2, blur: 2, spread: 0}, + {offset: 3, blur: 1, spread: -2} + ], + strength: 0.05 + }, + { // 3 + angularValues: [ + {offset: 1, blur: 8, spread: 0}, + {offset: 3, blur: 4, spread: 0}, + {offset: 3, blur: 3, spread: -2} + ], + strength: 0.05 + }, + { // 4 + angularValues: [ + {offset: 2, blur: 4, spread: -1}, + {offset: 4, blur: 5, spread: 0}, + {offset: 1, blur: 10, spread: 0} + ], + strength: 0.05 + }, + { // 5 + angularValues: [ + {offset: 3, blur: 5, spread: -1}, + {offset: 5, blur: 8, spread: 0}, + {offset: 1, blur: 14, spread: 0} + ], + strength: 0.05 + }, + { // 6 + angularValues: [ + {offset: 3, blur: 5, spread: -1}, + {offset: 6, blur: 10, spread: 0}, + {offset: 1, blur: 18, spread: 0} + ], + strength: 0.05 + }, + { // 7 + angularValues: [ + {offset: 4, blur: 5, spread: -2}, + {offset: 7, blur: 10, spread: 1}, + {offset: 2, blur: 16, spread: 1} + ], + strength: 0.05 + }, + { // 8 + angularValues: [ + {offset: 5, blur: 5, spread: -3}, + {offset: 8, blur: 10, spread: 1}, + {offset: 3, blur: 14, spread: 2} + ], + strength: 0.05 + }, + { // 9 + angularValues: [ + {offset: 5, blur: 6, spread: -3}, + {offset: 9, blur: 12, spread: 1}, + {offset: 3, blur: 16, spread: 2} + ], + strength: 0.05 + }, + { // 10 + angularValues: [ + {offset: 6, blur: 6, spread: -3}, + {offset: 10, blur: 14, spread: 1}, + {offset: 4, blur: 18, spread: 3} + ], + strength: 0.05 + }, + { // 11 + angularValues: [ + {offset: 6, blur: 7, spread: -4}, + {offset: 11, blur: 15, spread: 1}, + {offset: 4, blur: 20, spread: 3} + ], + strength: 0.05 + }, + { // 12 + angularValues: [ + {offset: 7, blur: 8, spread: -4}, + {offset: 12, blur: 17, spread: 2}, + {offset: 5, blur: 22, spread: 4} + ], + strength: 0.05 + } ] /* @@ -202,9 +209,10 @@ Item { // the size of the parent, so we don't need to worry about the extra padding // in the parent Item BoxShadow { - offsetY: effect._shadow[0].offset - blurRadius: effect._shadow[0].blur - spreadRadius: effect._shadow[0].spread + offsetY: effect._shadow.angularValues[0].offset + blurRadius: effect._shadow.angularValues[0].blur + spreadRadius: effect._shadow.angularValues[0].spread + strength: effect._shadow.strength color: Qt.rgba(0,0,0, 0.2) fullWidth: effect.fullWidth @@ -213,9 +221,10 @@ Item { } BoxShadow { - offsetY: effect._shadow[1].offset - blurRadius: effect._shadow[1].blur - spreadRadius: effect._shadow[1].spread + offsetY: effect._shadow.angularValues[1].offset + blurRadius: effect._shadow.angularValues[1].blur + spreadRadius: effect._shadow.angularValues[1].spread + strength: effect._shadow.strength color: Qt.rgba(0,0,0, 0.14) fullWidth: effect.fullWidth @@ -224,9 +233,10 @@ Item { } BoxShadow { - offsetY: effect._shadow[2].offset - blurRadius: effect._shadow[2].blur - spreadRadius: effect._shadow[2].spread + offsetY: effect._shadow.angularValues[2].offset + blurRadius: effect._shadow.angularValues[2].blur + spreadRadius: effect._shadow.angularValues[2].spread + strength: effect._shadow.strength color: Qt.rgba(0,0,0, 0.12) fullWidth: effect.fullWidth diff --git a/src/quickcontrols/material/impl/RoundedElevationEffect.qml b/src/quickcontrols/material/impl/RoundedElevationEffect.qml new file mode 100644 index 0000000000..c197823dc6 --- /dev/null +++ b/src/quickcontrols/material/impl/RoundedElevationEffect.qml @@ -0,0 +1,35 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import QtQuick.Controls.Material +import QtQuick.Controls.Material.impl + +ElevationEffect { + required property int roundedScale + + _shadows: roundedScale === Material.NotRounded ? _defaultShadows : roundedShadows() + + function roundedShadows() { + // Make a deep copy. + let shadows = [..._defaultShadows] + for (let i = 0, strength = 0.95; i < shadows.length; ++i) { + // See comment on BoxShadow's strength property for why we do this. + shadows[i].strength = strength + // We don't want the strength to be too high for the controls with very slightly rounded + // corners, as they are quite close to the non-rounded ones in terms of not needing adjustments. + // This is still not great for the higher elevations for ExtraSmallScale, but it's as good + // as I can get it. + strength = Math.max(0.05, strength - (roundedScale > Material.ExtraSmallScale ? 0.1 : 0.3)) + + // The values at index 0 are already 0, and we don't want our Math.max(1, ...) code to affect them. + if (i > 0) { + // The blur values for e.g. buttons with rounded corners are too large, so we reduce them. + for (let angularShadowIndex = 0; angularShadowIndex < shadows[i].angularValues.length; ++angularShadowIndex) { + shadows[i].angularValues[angularShadowIndex].blur = + Math.max(1, Math.floor(shadows[i].angularValues[angularShadowIndex].blur / 4)) + } + } + } + return shadows + } +} diff --git a/src/quickcontrols/material/impl/qquickmaterialripple.cpp b/src/quickcontrols/material/impl/qquickmaterialripple.cpp index 04e171f190..89648182d4 100644 --- a/src/quickcontrols/material/impl/qquickmaterialripple.cpp +++ b/src/quickcontrols/material/impl/qquickmaterialripple.cpp @@ -227,7 +227,6 @@ void QQuickMaterialRipple::setClipRadius(qreal radius) return; m_clipRadius = radius; - setClip(!qFuzzyIsNull(radius)); update(); } @@ -323,8 +322,7 @@ QSGNode *QQuickMaterialRipple::updatePaintNode(QSGNode *oldNode, UpdatePaintNode QQuickItemPrivate *d = QQuickItemPrivate::get(this); QQuickDefaultClipNode *clipNode = d->clipNode(); if (clipNode) { - // TODO: QTBUG-51894 - // clipNode->setRadius(m_clipRadius); + clipNode->setRadius(m_clipRadius); clipNode->setRect(boundingRect()); clipNode->update(); } diff --git a/src/quickcontrols/material/qquickmaterialstyle.cpp b/src/quickcontrols/material/qquickmaterialstyle.cpp index dbe7347acc..ce745500a2 100644 --- a/src/quickcontrols/material/qquickmaterialstyle.cpp +++ b/src/quickcontrols/material/qquickmaterialstyle.cpp @@ -486,8 +486,6 @@ void QQuickMaterialStyle::themeChange() emit themeChanged(); emit themeOrAccentChanged(); emit primaryHighlightedTextColor(); - emit buttonColorChanged(); - emit buttonDisabledColorChanged(); emit dialogColorChanged(); emit tooltipColorChanged(); emit toolBarColorChanged(); @@ -619,7 +617,6 @@ void QQuickMaterialStyle::accentChange() { emit accentChanged(); emit themeOrAccentChanged(); - emit buttonColorChanged(); } QVariant QQuickMaterialStyle::foreground() const @@ -753,7 +750,6 @@ void QQuickMaterialStyle::resetBackground() void QQuickMaterialStyle::backgroundChange() { emit backgroundChanged(); - emit buttonColorChanged(); emit dialogColorChanged(); emit tooltipColorChanged(); emit toolBarColorChanged(); @@ -781,7 +777,25 @@ void QQuickMaterialStyle::resetElevation() void QQuickMaterialStyle::elevationChange() { emit elevationChanged(); - emit buttonDisabledColorChanged(); +} + +QQuickMaterialStyle::RoundedScale QQuickMaterialStyle::roundedScale() const +{ + return m_roundedScale; +} + +void QQuickMaterialStyle::setRoundedScale(RoundedScale roundedScale) +{ + if (m_roundedScale == roundedScale) + return; + + m_roundedScale = roundedScale; + emit roundedScaleChanged(); +} + +void QQuickMaterialStyle::resetRoundedScale() +{ + setRoundedScale(RoundedScale::NotRounded); } QColor QQuickMaterialStyle::primaryColor() const @@ -874,9 +888,24 @@ QColor QQuickMaterialStyle::iconDisabledColor() const return QColor::fromRgba(m_theme == Light ? iconDisabledColorLight : iconDisabledColorDark); } -QColor QQuickMaterialStyle::buttonColor(bool highlighted, bool checked) const +QColor QQuickMaterialStyle::buttonColor(Theme theme, const QVariant &background, const QVariant &accent, + bool enabled, bool flat, bool highlighted, bool checked) const { + if (flat) + return Qt::transparent; + + if (!enabled) { + return QColor::fromRgba(m_theme == Light + ? raisedButtonDisabledColorLight : raisedButtonDisabledColorDark); + } + + // We don't use theme (and other arguments) here even though we pass it in, as it's + // simpler to just re-use themeShade. We still need the arguments because they allow + // us to be re-called whenever they change. Shade shade = themeShade(); + Q_UNUSED(theme); + Q_UNUSED(background); + Q_UNUSED(accent); QColor color = Qt::transparent; @@ -891,7 +920,8 @@ QColor QQuickMaterialStyle::buttonColor(bool highlighted, bool checked) const // A highlighted + checked button should become darker. color = accentColor(checked ? Shade100 : shade); } - } else if (elevation() > 0) { + } else { + // Even if the elevation is zero, it should still have a background if it's not flat. color = QColor::fromRgba(m_theme == Light ? raisedButtonColorLight : raisedButtonColorDark); } @@ -899,31 +929,6 @@ QColor QQuickMaterialStyle::buttonColor(bool highlighted, bool checked) const return color; } -QColor QQuickMaterialStyle::buttonColor() const -{ - return buttonColor(false); -} - -QColor QQuickMaterialStyle::buttonDisabledColor() const -{ - if (elevation() > 0) { - return QColor::fromRgba(m_theme == Light ? raisedButtonDisabledColorLight - : raisedButtonDisabledColorDark); - } else { - return Qt::transparent; - } -} - -QColor QQuickMaterialStyle::highlightedButtonColor() const -{ - return buttonColor(true); -} - -QColor QQuickMaterialStyle::highlightedCheckedButtonColor() const -{ - return buttonColor(true, true); -} - QColor QQuickMaterialStyle::frameColor() const { return QColor::fromRgba(m_theme == Light ? frameColorLight : frameColorDark); @@ -1168,8 +1173,8 @@ int QQuickMaterialStyle::touchTarget() const int QQuickMaterialStyle::buttonHeight() const { - // https://material.io/guidelines/components/buttons.html#buttons-style - return globalVariant == Dense ? 32 : 36; + // https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382 + return globalVariant == Dense ? 32 : 40; } int QQuickMaterialStyle::delegateHeight() const diff --git a/src/quickcontrols/material/qquickmaterialstyle_p.h b/src/quickcontrols/material/qquickmaterialstyle_p.h index 99344a6192..56e541ce07 100644 --- a/src/quickcontrols/material/qquickmaterialstyle_p.h +++ b/src/quickcontrols/material/qquickmaterialstyle_p.h @@ -30,6 +30,8 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator Q_PROPERTY(QVariant foreground READ foreground WRITE setForeground RESET resetForeground NOTIFY foregroundChanged FINAL) Q_PROPERTY(QVariant background READ background WRITE setBackground RESET resetBackground NOTIFY backgroundChanged FINAL) Q_PROPERTY(int elevation READ elevation WRITE setElevation RESET resetElevation NOTIFY elevationChanged FINAL) + Q_PROPERTY(RoundedScale roundedScale READ roundedScale WRITE setRoundedScale RESET resetRoundedScale + NOTIFY roundedScaleChanged FINAL) Q_PROPERTY(QColor primaryColor READ primaryColor NOTIFY primaryChanged FINAL) // TODO: remove? Q_PROPERTY(QColor accentColor READ accentColor NOTIFY accentChanged FINAL) // TODO: remove? @@ -43,10 +45,6 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator Q_PROPERTY(QColor dividerColor READ dividerColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor iconColor READ iconColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor iconDisabledColor READ iconDisabledColor NOTIFY themeChanged FINAL) - Q_PROPERTY(QColor buttonColor READ buttonColor NOTIFY buttonColorChanged FINAL) - Q_PROPERTY(QColor buttonDisabledColor READ buttonDisabledColor NOTIFY buttonDisabledColorChanged FINAL) - Q_PROPERTY(QColor highlightedButtonColor READ highlightedButtonColor NOTIFY buttonColorChanged FINAL) - Q_PROPERTY(QColor highlightedCheckedButtonColor READ highlightedCheckedButtonColor NOTIFY buttonColorChanged FINAL REVISION(6, 2)) Q_PROPERTY(QColor frameColor READ frameColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor rippleColor READ rippleColor NOTIFY themeChanged FINAL) Q_PROPERTY(QColor highlightedRippleColor READ highlightedRippleColor NOTIFY themeOrAccentChanged FINAL) @@ -134,10 +132,21 @@ public: ShadeA700, }; + enum class RoundedScale { + NotRounded, + ExtraSmallScale = 4, + SmallScale = 8, + MediumScale = 12, + LargeScale = 16, + ExtraLargeScale = 28, + FullScale = 0xFF // For full we use half the height of the item. + }; + Q_ENUM(Theme) Q_ENUM(Variant) Q_ENUM(Color) Q_ENUM(Shade) + Q_ENUM(RoundedScale) explicit QQuickMaterialStyle(QObject *parent = nullptr); @@ -183,6 +192,10 @@ public: void resetElevation(); void elevationChange(); + RoundedScale roundedScale() const; + void setRoundedScale(RoundedScale roundedScale); + void resetRoundedScale(); + QColor primaryColor() const; QColor accentColor() const; QColor backgroundColor() const; @@ -195,11 +208,8 @@ public: QColor dividerColor() const; QColor iconColor() const; QColor iconDisabledColor() const; - QColor buttonColor() const; - QColor buttonDisabledColor() const; - QColor highlightedButtonColor() const; - QColor highlightedCheckedButtonColor() const; - QColor highlightedButtonDisabledColor() const; + Q_INVOKABLE QColor buttonColor(Theme theme, const QVariant &background, const QVariant &accent, + bool enabled, bool flat, bool highlighted, bool checked) const; QColor frameColor() const; QColor rippleColor() const; QColor highlightedRippleColor() const; @@ -249,12 +259,11 @@ Q_SIGNALS: void themeOrAccentChanged(); void primaryHighlightedTextColorChanged(); - void buttonColorChanged(); - void buttonDisabledColorChanged(); void dialogColorChanged(); void tooltipColorChanged(); void toolBarColorChanged(); void toolTextColorChanged(); + void roundedScaleChanged(); protected: void attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent) override; @@ -265,7 +274,7 @@ private: QColor backgroundColor(Shade shade) const; QColor accentColor(Shade shade) const; - QColor buttonColor(bool highlighted, bool checked = false) const; + Shade themeShade() const; // These reflect whether a color value was explicitly set on the specific @@ -295,6 +304,7 @@ private: uint m_foreground = 0; uint m_background = 0; int m_elevation = 0; + RoundedScale m_roundedScale = RoundedScale::NotRounded; }; QT_END_NAMESPACE diff --git a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml index 34754420d0..fd62a5693b 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml +++ b/tests/auto/quickcontrols/qquickmaterialstyle/data/tst_material.qml @@ -35,6 +35,7 @@ TestCase { Material.accent: Material.DeepPurple Material.background: Material.Green Material.foreground: Material.Blue + Material.roundedScale: Material.SmallScale } } @@ -158,6 +159,8 @@ TestCase { compare(control.Material.foreground, "#dd000000") compare(control.Material.background, "#fafafa") compare(control.Material.theme, Material.Light) + // This doesn't propagate but we check its default anyway. + compare(control.Material.roundedScale, Material.FullScale) } function test_set() { @@ -168,11 +171,13 @@ TestCase { control.Material.background = Material.Red control.Material.foreground = Material.Blue control.Material.theme = Material.Dark + control.Material.roundedScale = Material.SmallScale compare(control.Material.primary, Material.color(Material.Green)) compare(control.Material.accent, Material.color(Material.Brown, themeshade(control.Material.theme))) compare(control.Material.background, Material.color(Material.Red, themeshade(control.Material.theme))) compare(control.Material.foreground, Material.color(Material.Blue)) compare(control.Material.theme, Material.Dark) + compare(control.Material.roundedScale, Material.SmallScale) } function test_reset() { @@ -183,16 +188,21 @@ TestCase { compare(control.Material.background, Material.color(Material.Green, themeshade(control.Material.theme))) compare(control.Material.foreground, Material.color(Material.Blue)) compare(control.Material.theme, Material.Dark) + compare(control.Material.roundedScale, Material.SmallScale) control.Material.primary = undefined control.Material.accent = undefined control.Material.background = undefined control.Material.foreground = undefined control.Material.theme = undefined + control.Material.roundedScale = undefined compare(control.Material.primary, testCase.Material.primary) compare(control.Material.accent, testCase.Material.accent) compare(control.Material.background, testCase.Material.background) compare(control.Material.foreground, testCase.Material.foreground) compare(control.Material.theme, testCase.Material.theme) + // Button's default is FullyRounded, but it specifies that default in QML, + // which means we have no way of knowing how to reset that in resetRoundedScale(). + compare(control.Material.roundedScale, Material.NotRounded) } function test_inheritance_data() { @@ -817,9 +827,6 @@ TestCase { property Component row_foregroundToDividerColor: Item { Material.foreground: Material.dividerColor } property Component row_foregroundToIconColor: Item { Material.foreground: Material.iconColor } property Component row_foregroundToIconDisabledColor: Item { Material.foreground: Material.iconDisabledColor } - property Component row_foregroundToButtonColor: Item { Material.foreground: Material.buttonColor } - property Component row_foregroundToButtonDisabledColor: Item { Material.foreground: Material.buttonDisabledColor } - property Component row_foregroundToHighlightedButtonColor: Item { Material.foreground: Material.highlightedButtonColor } property Component row_foregroundToFrameColor: Item { Material.foreground: Material.frameColor } property Component row_foregroundToRippleColor: Item { Material.foreground: Material.rippleColor } property Component row_foregroundToHighlightedRippleColor: Item { Material.foreground: Material.highlightedRippleColor } diff --git a/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp b/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp index 722f846d90..cec4149149 100644 --- a/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp +++ b/tests/auto/quickcontrols/qquickmaterialstyleconf/tst_qquickmaterialstyleconf.cpp @@ -58,8 +58,8 @@ void tst_qquickmaterialstyleconf::variants_data() // Just to ensure that the correct conf is loaded. QTest::addColumn<QColor>("expectedColor"); - // (36 button height + 12 touchable area) - QTest::newRow("normal") << QByteArray(":/variant-normal.conf") << 48 << QColor::fromRgb(0x123456); + // (40 button height + 12 touchable area) + QTest::newRow("normal") << QByteArray(":/variant-normal.conf") << 52 << QColor::fromRgb(0x123456); // We specified a custom variant (dense), so the button should be small. // (32 button height + 12 touchable area) QTest::newRow("dense") << QByteArray(":/variant-dense.conf") << 44 << QColor::fromRgb(0x789abc); diff --git a/tests/manual/quickcontrols/material/CMakeLists.txt b/tests/manual/quickcontrols/material/CMakeLists.txt new file mode 100644 index 0000000000..1cd3a98d0f --- /dev/null +++ b/tests/manual/quickcontrols/material/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(material LANGUAGES C CXX ASM) + find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_manual_test(material + GUI + SOURCES + material.cpp + LIBRARIES + Qt::Gui + Qt::Qml + Qt::QuickControls2 +) + +set(qmake_immediate_resource_files + "material.qml" + "Constants.qml" + "pages/ButtonPage.qml" + "pages/DelayButtonPage.qml" + "pages/RoundButtonPage.qml" + "qmldir" +) + +qt_internal_add_resource(material "qmake_immediate" + PREFIX + "/" + FILES + ${qmake_immediate_resource_files} +) diff --git a/tests/manual/quickcontrols/material/Constants.qml b/tests/manual/quickcontrols/material/Constants.qml new file mode 100644 index 0000000000..51b9b6ff23 --- /dev/null +++ b/tests/manual/quickcontrols/material/Constants.qml @@ -0,0 +1,11 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +pragma Singleton + +import QtQml + +QtObject { + readonly property url iconSource: "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png" + readonly property int pageTopPadding: 20 + readonly property int spacing: 40 +} diff --git a/tests/manual/quickcontrols/material/material.cpp b/tests/manual/quickcontrols/material/material.cpp new file mode 100644 index 0000000000..2e257b0902 --- /dev/null +++ b/tests/manual/quickcontrols/material/material.cpp @@ -0,0 +1,32 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QSettings> + +int main(int argc, char *argv[]) +{ + QGuiApplication::setApplicationName("material"); + QGuiApplication::setOrganizationName("QtProject"); + + QGuiApplication app(argc, argv); + + const char *variantEnvVar = "QT_QUICK_CONTROLS_MATERIAL_VARIANT"; + if (!qEnvironmentVariableIsSet(variantEnvVar)) { + QSettings settings; + const char *variant = "variant"; + if (settings.contains(variant)) + qputenv(variantEnvVar, settings.value(variant).toByteArray()); + } + + QQmlApplicationEngine engine; + const QUrl url(QStringLiteral("qrc:/material.qml")); + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/tests/manual/quickcontrols/material/material.qml b/tests/manual/quickcontrols/material/material.qml new file mode 100644 index 0000000000..720ff0a5ec --- /dev/null +++ b/tests/manual/quickcontrols/material/material.qml @@ -0,0 +1,126 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtCore +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Layouts + +ApplicationWindow { + id: window + title: "Material" + width: screen.desktopAvailableWidth * 0.8 + height: screen.desktopAvailableHeight * 0.8 + visible: true + + Material.theme: settings.theme + + Settings { + id: settings + + property alias windowX: window.x + property alias windowY: window.y + property alias windowWidth: window.width + property alias windowHeight: window.height + + property int theme: darkThemeSwitch.checked ? Material.Dark : Material.Light + property string variant: denseSwitch.checked ? "Dense" : "Normal" + + property alias currentControlIndex: listView.currentIndex + } + + Shortcut { + sequences: ["Esc", "Back"] + onActivated: openDrawerAction.trigger() + } + + Shortcut { + sequence: "Ctrl+Q" + onActivated: Qt.quit() + } + + Action { + id: openDrawerAction + text: "Controls" + onTriggered: drawer.open() + } + + header: ToolBar { + RowLayout { + spacing: 20 + anchors.fill: parent + + Material.theme: Material.Dark + + ToolButton { + action: openDrawerAction + } + + Label { + id: titleLabel + text: listView.currentItem ? listView.currentItem.text : "Material" + font.pixelSize: 20 + elide: Label.ElideRight + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + Layout.fillWidth: true + } + + Item { + Layout.fillWidth: true + } + + Switch { + id: darkThemeSwitch + text: "Dark" + checked: settings.theme === Material.Dark + } + + Switch { + id: denseSwitch + text: "Dense" + checked: settings.variant === "Dense" + + ToolTip.text: "Requires restart" + ToolTip.visible: hovered + } + } + } + + Drawer { + id: drawer + width: window.width / 3 + height: window.height + interactive: stackView.depth === 1 + + ListView { + id: listView + focus: true + currentIndex: settings.currentControlIndex + anchors.fill: parent + model: ["Button", "DelayButton", "RoundButton"] + delegate: ItemDelegate { + width: listView.width + text: modelData + highlighted: ListView.isCurrentItem + onClicked: listView.currentIndex = index + } + + ScrollIndicator.vertical: ScrollIndicator { } + + // Need to wait until our count is non-zero before setting a default currentIndex. + // This also allows us to use an alias for the settings property. + Component.onCompleted: if (currentIndex === -1) currentIndex = 0 + + onCurrentIndexChanged: { + if (currentIndex >= 0 && currentIndex < count) + stackView.replace("qrc:/pages/" + model[currentIndex] + "Page.qml") + drawer.close() + } + } + } + + StackView { + id: stackView + anchors.fill: parent + } +} diff --git a/tests/manual/quickcontrols/material/pages/ButtonPage.qml b/tests/manual/quickcontrols/material/pages/ButtonPage.qml new file mode 100644 index 0000000000..3f861e7a70 --- /dev/null +++ b/tests/manual/quickcontrols/material/pages/ButtonPage.qml @@ -0,0 +1,125 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Layouts + +import ".." + +Page { + topPadding: 20 + + property var backgroundColor + + header: RowLayout { + CheckBox { + id: iconCheckBox + text: "Icon" + } + + CheckBox { + id: disabledCheckBox + text: "Disabled" + } + + Item { + Layout.fillWidth: true + } + } + + component RoundedScaleLayout: ColumnLayout { + id: roundedScaleLayout + enabled: !disabledCheckBox.checked + + property bool allowFlat + property var backgroundColor: undefined + property var foregroundColor: undefined + + property int contentLeftMargin + property int contentRightMargin + + RowLayout { + enabled: roundedScaleLayout.allowFlat + + CheckBox { + id: flatCheckBox + text: "Flat" + + Layout.leftMargin: roundedScaleLayout.contentLeftMargin + } + } + + RowLayout { + spacing: Constants.spacing + + Repeater { + id: roundedScaleRepeater + model: ListModel { + ListElement { displayName: "NotRounded"; roundedScale: Material.NotRounded } + ListElement { displayName: "ExtraSmall"; roundedScale: Material.ExtraSmallScale } + ListElement { displayName: "Small"; roundedScale: Material.SmallScale } + ListElement { displayName: "Medium"; roundedScale: Material.MediumScale } + ListElement { displayName: "Large"; roundedScale: Material.LargeScale } + ListElement { displayName: "ExtraLarge"; roundedScale: Material.ExtraLargeScale } + ListElement { displayName: "Full"; roundedScale: Material.FullScale } + } + + // Workaround for QTBUG-98859. + delegate: Component { + ColumnLayout { + id: scaleLayout + spacing: Constants.spacing + + required property int index + required property string displayName + required property int roundedScale + + Layout.leftMargin: index === 0 ? roundedScaleLayout.contentLeftMargin : 0 + Layout.rightMargin: index === roundedScaleRepeater.count - 1 ? roundedScaleLayout.contentRightMargin : 0 + Layout.bottomMargin: Constants.spacing + + Label { + text: scaleLayout.displayName + + Layout.alignment: Qt.AlignHCenter + } + + Repeater { + model: 13 + + Button { + text: modelData + flat: flatCheckBox.checked + icon.source: iconCheckBox.checked ? "qrc:/qt-project.org/imports/QtQuick/Controls/Basic/images/check.png" : "" + + Material.background: roundedScaleLayout.backgroundColor + Material.foreground: roundedScaleLayout.foregroundColor + Material.elevation: modelData + Material.roundedScale: scaleLayout.roundedScale + } + } + } + } + } + } + } + + ScrollView { + anchors.fill: parent + + RowLayout { + spacing: Constants.spacing + + RoundedScaleLayout { + contentLeftMargin: Constants.spacing + allowFlat: true + } + + RoundedScaleLayout { + backgroundColor: Material.Teal + foregroundColor: "white" + contentRightMargin: Constants.spacing + } + } + } +} diff --git a/tests/manual/quickcontrols/material/pages/DelayButtonPage.qml b/tests/manual/quickcontrols/material/pages/DelayButtonPage.qml new file mode 100644 index 0000000000..ee9c12f446 --- /dev/null +++ b/tests/manual/quickcontrols/material/pages/DelayButtonPage.qml @@ -0,0 +1,73 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Layouts + +import ".." + +Page { + topPadding: 20 + + property var backgroundColor + + header: RowLayout { + CheckBox { + id: disabledCheckBox + text: "Disabled" + } + + Item { + Layout.fillWidth: true + } + } + + component ElevationLayout: ColumnLayout { + id: elevationLayout + enabled: !disabledCheckBox.checked + + property var backgroundColor: undefined + property var foregroundColor: undefined + + property int contentLeftMargin + property int contentRightMargin + + ColumnLayout { + spacing: Constants.spacing + + Repeater { + model: 13 + + DelayButton { + text: modelData + + Material.background: elevationLayout.backgroundColor + Material.foreground: elevationLayout.foregroundColor + Material.elevation: modelData + + Layout.leftMargin: elevationLayout.contentLeftMargin + } + } + + Layout.bottomMargin: Constants.spacing + } + } + + ScrollView { + anchors.fill: parent + + RowLayout { + spacing: Constants.spacing + + ElevationLayout { + contentLeftMargin: Constants.spacing + } + + ElevationLayout { + backgroundColor: Material.Teal + foregroundColor: "white" + contentRightMargin: Constants.spacing + } + } + } +} diff --git a/tests/manual/quickcontrols/material/pages/RoundButtonPage.qml b/tests/manual/quickcontrols/material/pages/RoundButtonPage.qml new file mode 100644 index 0000000000..1fbcbf2e45 --- /dev/null +++ b/tests/manual/quickcontrols/material/pages/RoundButtonPage.qml @@ -0,0 +1,93 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +import QtQuick +import QtQuick.Controls.Material +import QtQuick.Layouts + +import ".." + +Page { + topPadding: 20 + + property var backgroundColor + + header: RowLayout { + CheckBox { + id: iconCheckBox + text: "Icon" + } + + CheckBox { + id: disabledCheckBox + text: "Disabled" + } + + Item { + Layout.fillWidth: true + } + } + + component ElevationLayout: ColumnLayout { + id: elevationLayout + enabled: !disabledCheckBox.checked + + property bool allowFlat + property var backgroundColor: undefined + property var foregroundColor: undefined + + property int contentLeftMargin + property int contentRightMargin + + RowLayout { + enabled: elevationLayout.allowFlat + + CheckBox { + id: flatCheckBox + text: "Flat" + + Layout.leftMargin: elevationLayout.contentLeftMargin + } + } + + ColumnLayout { + spacing: Constants.spacing + + Repeater { + model: 13 + + RoundButton { + text: iconCheckBox.checked ? "" : modelData + flat: flatCheckBox.checked + icon.source: iconCheckBox.checked ? Constants.iconSource : "" + + Material.background: elevationLayout.backgroundColor + Material.foreground: elevationLayout.foregroundColor + Material.elevation: modelData + + Layout.leftMargin: elevationLayout.contentLeftMargin + } + } + + Layout.bottomMargin: Constants.spacing + } + } + + ScrollView { + anchors.fill: parent + + RowLayout { + spacing: Constants.spacing + + ElevationLayout { + contentLeftMargin: Constants.spacing + allowFlat: true + } + + ElevationLayout { + backgroundColor: Material.Teal + foregroundColor: "white" + contentRightMargin: Constants.spacing + } + } + } +} diff --git a/tests/manual/quickcontrols/material/qmldir b/tests/manual/quickcontrols/material/qmldir new file mode 100644 index 0000000000..e56896abb6 --- /dev/null +++ b/tests/manual/quickcontrols/material/qmldir @@ -0,0 +1,2 @@ +module MaterialHelper +singleton Constants 1.0 Constants.qml diff --git a/tests/manual/quickcontrols/testbench/testbench.qml b/tests/manual/quickcontrols/testbench/testbench.qml index c9185e35d0..c88e16425a 100644 --- a/tests/manual/quickcontrols/testbench/testbench.qml +++ b/tests/manual/quickcontrols/testbench/testbench.qml @@ -430,8 +430,8 @@ Ui.ApplicationWindow { Label { text: statesAsString.length > 0 ? statesAsString : "normal" - // 4 is the most states for any element (Button) - Layout.preferredHeight: (fontMetrics.lineSpacing) * (rootDelegate.maxStateCombinations + 1) + // Ensure that each row of the Flow has the same height for the labels. + Layout.preferredHeight: fontMetrics.lineSpacing * rootDelegate.maxStateCombinations } ControlContainer { |