aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/material
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols/material')
-rw-r--r--src/quickcontrols/material/Button.qml8
-rw-r--r--src/quickcontrols/material/CMakeLists.txt33
-rw-r--r--src/quickcontrols/material/ComboBox.qml64
-rw-r--r--src/quickcontrols/material/Dial.qml7
-rw-r--r--src/quickcontrols/material/Dialog.qml5
-rw-r--r--src/quickcontrols/material/Drawer.qml40
-rw-r--r--src/quickcontrols/material/Frame.qml7
-rw-r--r--src/quickcontrols/material/GroupBox.qml9
-rw-r--r--src/quickcontrols/material/HorizontalHeaderView.qml14
-rw-r--r--src/quickcontrols/material/Menu.qml16
-rw-r--r--src/quickcontrols/material/Page.qml6
-rw-r--r--src/quickcontrols/material/Pane.qml6
-rw-r--r--src/quickcontrols/material/Popup.qml11
-rw-r--r--src/quickcontrols/material/RangeSlider.qml57
-rw-r--r--src/quickcontrols/material/Slider.qml57
-rw-r--r--src/quickcontrols/material/SpinBox.qml22
-rw-r--r--src/quickcontrols/material/StackView.qml41
-rw-r--r--src/quickcontrols/material/Switch.qml3
-rw-r--r--src/quickcontrols/material/TextArea.qml63
-rw-r--r--src/quickcontrols/material/TextField.qml59
-rw-r--r--src/quickcontrols/material/TreeViewDelegate.qml8
-rw-r--r--src/quickcontrols/material/Tumbler.qml8
-rw-r--r--src/quickcontrols/material/VerticalHeaderView.qml14
-rw-r--r--src/quickcontrols/material/impl/CMakeLists.txt8
-rw-r--r--src/quickcontrols/material/impl/RadioIndicator.qml31
-rw-r--r--src/quickcontrols/material/impl/RectangularGlow.qml2
-rw-r--r--src/quickcontrols/material/impl/SliderHandle.qml15
-rw-r--r--src/quickcontrols/material/impl/SwitchIndicator.qml10
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialbusyindicator_p.h2
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialplaceholdertext.cpp321
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialplaceholdertext_p.h105
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialprogressbar.cpp4
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialprogressbar_p.h2
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialripple.cpp12
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialripple_p.h2
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialtextcontainer.cpp422
-rw-r--r--src/quickcontrols/material/impl/qquickmaterialtextcontainer_p.h122
-rw-r--r--src/quickcontrols/material/qquickmaterialstyle.cpp99
-rw-r--r--src/quickcontrols/material/qquickmaterialstyle_p.h29
-rw-r--r--src/quickcontrols/material/qquickmaterialtheme.cpp19
-rw-r--r--src/quickcontrols/material/qquickmaterialtheme_p.h4
-rw-r--r--src/quickcontrols/material/qtquickcontrols2materialstyleplugin.cpp2
-rw-r--r--src/quickcontrols/material/shaders/+glslcore/RectangularGlow.frag25
-rw-r--r--src/quickcontrols/material/shaders/+hlsl/RectangularGlow.frag21
-rw-r--r--src/quickcontrols/material/shaders/+qsb/RectangularGlow.fragbin2007 -> 0 bytes
-rw-r--r--src/quickcontrols/material/shaders/RectangularGlow.frag38
-rw-r--r--src/quickcontrols/material/shaders/RectangularGlow_rhi.frag28
-rw-r--r--src/quickcontrols/material/shaders/compile.bat4
48 files changed, 1551 insertions, 334 deletions
diff --git a/src/quickcontrols/material/Button.qml b/src/quickcontrols/material/Button.qml
index e2bbb58687..8ffe07bbc3 100644
--- a/src/quickcontrols/material/Button.qml
+++ b/src/quickcontrols/material/Button.qml
@@ -17,10 +17,10 @@ T.Button {
topInset: 6
bottomInset: 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)
+ verticalPadding: Material.buttonVerticalPadding
+ leftPadding: Material.buttonLeftPadding(flat, hasIcon && (display !== AbstractButton.TextOnly))
+ rightPadding: Material.buttonRightPadding(flat, hasIcon && (display !== AbstractButton.TextOnly),
+ (text !== "") && (display !== AbstractButton.IconOnly))
spacing: 8
icon.width: 24
diff --git a/src/quickcontrols/material/CMakeLists.txt b/src/quickcontrols/material/CMakeLists.txt
index f328e775c3..0c7416ea7f 100644
--- a/src/quickcontrols/material/CMakeLists.txt
+++ b/src/quickcontrols/material/CMakeLists.txt
@@ -94,7 +94,9 @@ set_source_files_properties(VerticalHeaderView.qml PROPERTIES
QT_QML_SOURCE_VERSIONS "2.15;6.0"
)
-qt_internal_add_qml_module(qtquickcontrols2materialstyleplugin
+add_subdirectory(impl)
+
+qt_internal_add_qml_module(QuickControls2Material
URI "QtQuick.Controls.Material"
VERSION "${PROJECT_VERSION}"
PAST_MAJOR_VERSIONS 2
@@ -109,7 +111,6 @@ qt_internal_add_qml_module(qtquickcontrols2materialstyleplugin
SOURCES
qquickmaterialstyle.cpp qquickmaterialstyle_p.h
qquickmaterialtheme.cpp qquickmaterialtheme_p.h
- qtquickcontrols2materialstyleplugin.cpp
QML_FILES
${qml_files}
DEFINES
@@ -120,12 +121,23 @@ qt_internal_add_qml_module(qtquickcontrols2materialstyleplugin
Qt::GuiPrivate
Qt::QmlPrivate
Qt::QuickControls2ImplPrivate
+ Qt::QuickControls2MaterialStyleImpl
Qt::QuickControls2Private
Qt::QuickPrivate
Qt::QuickTemplates2Private
)
-qt_internal_add_resource(qtquickcontrols2materialstyleplugin "qtquickcontrols2materialstyleplugin"
+target_sources(qtquickcontrols2materialstyleplugin
+ PRIVATE
+ qtquickcontrols2materialstyleplugin.cpp
+)
+
+target_link_libraries(qtquickcontrols2materialstyleplugin
+ PRIVATE
+ Qt::QuickControls2Private
+)
+
+qt_internal_add_resource(QuickControls2Material "qtquickcontrols2materialstyle"
PREFIX
"/qt-project.org/imports/QtQuick/Controls/Material"
FILES
@@ -141,13 +153,18 @@ qt_internal_add_resource(qtquickcontrols2materialstyleplugin "qtquickcontrols2ma
"images/drop-indicator@2x.png"
"images/drop-indicator@3x.png"
"images/drop-indicator@4x.png"
- "shaders/+glslcore/RectangularGlow.frag"
- "shaders/+hlsl/RectangularGlow.frag"
- "shaders/+qsb/RectangularGlow.frag"
- "shaders/RectangularGlow.frag"
)
-add_subdirectory(impl)
+qt_internal_add_shaders(QuickControls2Material "qtquickcontrols2materialstyle_shaders"
+ SILENT
+ BATCHABLE
+ PRECOMPILE
+ OPTIMIZED
+ PREFIX
+ "/qt-project.org/imports/QtQuick/Controls/Material"
+ FILES
+ "shaders/RectangularGlow.frag"
+)
_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2materialstyleplugin quickwindow)
_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2materialstyleplugin
diff --git a/src/quickcontrols/material/ComboBox.qml b/src/quickcontrols/material/ComboBox.qml
index 30222c4180..5694aa055c 100644
--- a/src/quickcontrols/material/ComboBox.qml
+++ b/src/quickcontrols/material/ComboBox.qml
@@ -1,6 +1,8 @@
// Copyright (C) 2017 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
+pragma ComponentBehavior: Bound
+
import QtQuick
import QtQuick.Window
import QtQuick.Controls.impl
@@ -17,20 +19,18 @@ T.ComboBox {
implicitContentHeight + topPadding + bottomPadding,
implicitIndicatorHeight + topPadding + bottomPadding)
- topInset: 6
- bottomInset: 6
-
leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
- Material.elevation: flat ? control.pressed || (enabled && control.hovered) ? 2 : 0
- : control.pressed ? 8 : 2
Material.background: flat ? "transparent" : undefined
Material.foreground: flat ? undefined : Material.primaryTextColor
delegate: MenuItem {
+ required property var model
+ required property int index
+
width: ListView.view.width
- text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
+ text: model[control.textRole]
Material.foreground: control.currentIndex === index ? ListView.view.contentItem.Material.accent : ListView.view.contentItem.Material.foreground
highlighted: control.highlightedIndex === index
hoverEnabled: control.hoverEnabled
@@ -44,9 +44,9 @@ T.ComboBox {
}
contentItem: T.TextField {
- padding: 6
- leftPadding: control.editable ? 2 : control.mirrored ? 0 : 12
- rightPadding: control.editable ? 2 : control.mirrored ? 12 : 0
+ leftPadding: Material.textFieldHorizontalPadding
+ topPadding: Material.textFieldVerticalPadding
+ bottomPadding: Material.textFieldVerticalPadding
text: control.editable ? control.editText : control.displayText
@@ -65,46 +65,25 @@ T.ComboBox {
cursorDelegate: CursorDelegate { }
}
- background: Rectangle {
+ background: MaterialTextContainer {
implicitWidth: 120
- implicitHeight: control.Material.buttonHeight
+ implicitHeight: control.Material.textFieldHeight
- radius: control.flat ? 0 : 2
- color: !control.editable ? control.Material.dialogColor : "transparent"
-
- layer.enabled: control.enabled && !control.editable && control.Material.background.a > 0
- layer.effect: ElevationEffect {
- elevation: control.Material.elevation
- }
-
- Rectangle {
- visible: control.editable
- y: parent.y + control.baselineOffset
- width: parent.width
- height: control.activeFocus ? 2 : 1
- color: control.editable && control.activeFocus ? control.Material.accentColor : control.Material.hintTextColor
- }
-
- Ripple {
- clip: control.flat
- clipRadius: control.flat ? 0 : 2
- x: control.editable && control.indicator ? control.indicator.x : 0
- width: control.editable && control.indicator ? control.indicator.width : parent.width
- height: parent.height
- pressed: control.pressed
- anchor: control.editable && control.indicator ? control.indicator : control
- active: enabled && (control.pressed || control.visualFocus || control.hovered)
- color: control.Material.rippleColor
- }
+ outlineColor: (enabled && control.hovered) ? control.Material.primaryTextColor : control.Material.hintTextColor
+ focusedOutlineColor: control.Material.accentColor
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: true
+ horizontalPadding: control.Material.textFieldHorizontalPadding
}
popup: T.Popup {
y: control.editable ? control.height - 5 : 0
width: control.width
- height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
+ height: Math.min(contentItem.implicitHeight + verticalPadding * 2, control.Window.height - topMargin - bottomMargin)
transformOrigin: Item.Top
topMargin: 12
bottomMargin: 12
+ verticalPadding: 8
Material.theme: control.Material.theme
Material.accent: control.Material.accent
@@ -133,12 +112,13 @@ T.ComboBox {
}
background: Rectangle {
- radius: 2
+ radius: 4
color: parent.Material.dialogColor
layer.enabled: control.enabled
- layer.effect: ElevationEffect {
- elevation: 8
+ layer.effect: RoundedElevationEffect {
+ elevation: 4
+ roundedScale: Material.ExtraSmallScale
}
}
}
diff --git a/src/quickcontrols/material/Dial.qml b/src/quickcontrols/material/Dial.qml
index a44938fe20..465c1f3631 100644
--- a/src/quickcontrols/material/Dial.qml
+++ b/src/quickcontrols/material/Dial.qml
@@ -33,12 +33,13 @@ T.Dial {
y: control.background.y + control.background.height / 2 - height / 2
transform: [
Translate {
- y: -control.background.height * 0.4 + control.handle.height / 2
+ y: -control.background.height * 0.4
+ + (control.handle ? control.handle.height / 2 : 0)
},
Rotation {
angle: control.angle
- origin.x: control.handle.width / 2
- origin.y: control.handle.height / 2
+ origin.x: control.handle ? control.handle.width / 2 : 0
+ origin.y: control.handle ? control.handle.height / 2 : 0
}
]
implicitWidth: 10
diff --git a/src/quickcontrols/material/Dialog.qml b/src/quickcontrols/material/Dialog.qml
index 33d8ce97d1..014fcc67c5 100644
--- a/src/quickcontrols/material/Dialog.qml
+++ b/src/quickcontrols/material/Dialog.qml
@@ -28,8 +28,7 @@ T.Dialog {
// https://m3.material.io/components/dialogs/specs#401a48c3-f50c-4fa9-b798-701f5adcf155
// Specs say level 3 (6 dp) is the default, yet the screenshots there show 0. Native Android defaults to non-zero.
Material.elevation: 6
- // https://m3.material.io/components/dialogs/specs#6771d107-624e-47cc-b6d8-2b7b620ba2f1
- Material.roundedScale: Material.ExtraLargeScale
+ Material.roundedScale: Material.dialogRoundedScale
enter: Transition {
// grow_fade_in
@@ -63,7 +62,7 @@ T.Dialog {
bottomPadding: 0
// TODO: QPlatformTheme::TitleBarFont
// https://m3.material.io/components/dialogs/specs#401a48c3-f50c-4fa9-b798-701f5adcf155
- font.pixelSize: 24
+ font.pixelSize: Material.dialogTitleFontPixelSize
background: PaddedRectangle {
radius: control.background.radius
color: control.Material.dialogColor
diff --git a/src/quickcontrols/material/Drawer.qml b/src/quickcontrols/material/Drawer.qml
index ecfe8836b9..fc31a19a84 100644
--- a/src/quickcontrols/material/Drawer.qml
+++ b/src/quickcontrols/material/Drawer.qml
@@ -3,6 +3,7 @@
import QtQuick
import QtQuick.Templates as T
+import QtQuick.Controls.impl
import QtQuick.Controls.Material
import QtQuick.Controls.Material.impl
@@ -16,33 +17,32 @@ T.Drawer {
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
- topPadding: !dim && edge === Qt.BottomEdge && Material.elevation === 0
- leftPadding: !dim && edge === Qt.RightEdge && Material.elevation === 0
- rightPadding: !dim && edge === Qt.LeftEdge && Material.elevation === 0
- bottomPadding: !dim && edge === Qt.TopEdge && Material.elevation === 0
+ topPadding: edge !== Qt.TopEdge ? Material.roundedScale : 0
+ bottomPadding: edge !== Qt.BottomEdge ? Material.roundedScale : 0
enter: Transition { SmoothedAnimation { velocity: 5 } }
exit: Transition { SmoothedAnimation { velocity: 5 } }
- Material.elevation: !interactive && !dim ? 0 : 16
+ // https://m3.material.io/components/navigation-drawer/specs#e616dc8f-d61a-4d56-a311-50c68ecda744
+ Material.elevation: !interactive && !dim ? 0 : 1
+ Material.roundedScale: Material.LargeScale
- background: Rectangle {
+ background: PaddedRectangle {
+ // https://m3.material.io/components/navigation-drawer/specs#ce8bfbcf-3dec-45d2-9d8b-5e10af1cf87d
+ implicitWidth: 360
color: control.Material.dialogColor
-
- Rectangle {
- readonly property bool horizontal: control.edge === Qt.LeftEdge || control.edge === Qt.RightEdge
- width: horizontal ? 1 : parent.width
- height: horizontal ? parent.height : 1
- color: control.Material.dividerColor
- x: control.edge === Qt.LeftEdge ? parent.width - 1 : 0
- y: control.edge === Qt.TopEdge ? parent.height - 1 : 0
- visible: !control.dim && control.Material.elevation === 0
- }
-
- layer.enabled: control.position > 0
- layer.effect: ElevationEffect {
+ // FullScale doesn't make sense for Drawer.
+ radius: control.Material.roundedScale
+ leftPadding: edge === Qt.LeftEdge ? -radius : 0
+ rightPadding: edge === Qt.RightEdge ? -radius : 0
+ topPadding: edge === Qt.TopEdge ? -radius : 0
+ bottomPadding: edge === Qt.BottomEdge ? -radius : 0
+ clip: true
+
+ layer.enabled: control.position > 0 && control.Material.elevation > 0
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
- fullHeight: true
+ roundedScale: control.background.radius
}
}
diff --git a/src/quickcontrols/material/Frame.qml b/src/quickcontrols/material/Frame.qml
index 8b6674e16f..da9cd65581 100644
--- a/src/quickcontrols/material/Frame.qml
+++ b/src/quickcontrols/material/Frame.qml
@@ -17,14 +17,17 @@ T.Frame {
padding: 12
verticalPadding: Material.frameVerticalPadding
+ Material.roundedScale: Material.ExtraSmallScale
+
background: Rectangle {
- radius: 2
+ radius: control.Material.roundedScale
color: control.Material.elevation > 0 ? control.Material.backgroundColor : "transparent"
border.color: control.Material.frameColor
layer.enabled: control.enabled && control.Material.elevation > 0
- layer.effect: ElevationEffect {
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
+ roundedScale: control.background.radius
}
}
}
diff --git a/src/quickcontrols/material/GroupBox.qml b/src/quickcontrols/material/GroupBox.qml
index be7e6fbadc..f0cee7c854 100644
--- a/src/quickcontrols/material/GroupBox.qml
+++ b/src/quickcontrols/material/GroupBox.qml
@@ -20,8 +20,10 @@ T.GroupBox {
topPadding: Material.frameVerticalPadding + (implicitLabelWidth > 0 ? implicitLabelHeight + spacing : 0)
bottomPadding: Material.frameVerticalPadding
+ Material.roundedScale: Material.ExtraSmallScale
+
label: Text {
- x: control.leftPadding
+ x: Math.max(control.leftPadding, control.Material.roundedScale)
width: control.availableWidth
text: control.title
@@ -36,13 +38,14 @@ T.GroupBox {
width: parent.width
height: parent.height - control.topPadding + control.bottomPadding
- radius: 2
+ radius: control.Material.roundedScale
color: control.Material.elevation > 0 ? control.Material.backgroundColor : "transparent"
border.color: control.Material.frameColor
layer.enabled: control.enabled && control.Material.elevation > 0
- layer.effect: ElevationEffect {
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
+ roundedScale: control.background.radius
}
}
}
diff --git a/src/quickcontrols/material/HorizontalHeaderView.qml b/src/quickcontrols/material/HorizontalHeaderView.qml
index 0a5fe4f9f5..76060d8e83 100644
--- a/src/quickcontrols/material/HorizontalHeaderView.qml
+++ b/src/quickcontrols/material/HorizontalHeaderView.qml
@@ -1,6 +1,8 @@
// Copyright (C) 2020 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
+pragma ComponentBehavior: Bound
+
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls.Material
@@ -18,6 +20,10 @@ T.HorizontalHeaderView {
implicitHeight: Math.max(1, contentHeight)
delegate: Rectangle {
+ id: delegate
+
+ required property var model
+
// Qt6: add cellPadding (and font etc) as public API in headerview
readonly property real cellPadding: 8
@@ -27,11 +33,9 @@ T.HorizontalHeaderView {
Label {
id: text
- text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole]
- : model[control.textRole])
- : modelData
- width: parent.width
- height: parent.height
+ text: delegate.model[control.textRole]
+ width: delegate.width
+ height: delegate.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: enabled ? control.Material.foreground : control.Material.hintTextColor
diff --git a/src/quickcontrols/material/Menu.qml b/src/quickcontrols/material/Menu.qml
index 4601772196..641bb7c07b 100644
--- a/src/quickcontrols/material/Menu.qml
+++ b/src/quickcontrols/material/Menu.qml
@@ -10,8 +10,6 @@ import QtQuick.Window
T.Menu {
id: control
- Material.elevation: 8
-
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
@@ -22,6 +20,9 @@ T.Menu {
transformOrigin: !cascade ? Item.Top : (mirrored ? Item.TopRight : Item.TopLeft)
+ Material.elevation: 4
+ Material.roundedScale: Material.ExtraSmallScale
+
delegate: MenuItem { }
enter: Transition {
@@ -41,8 +42,8 @@ T.Menu {
model: control.contentModel
interactive: Window.window
- ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height
- : false
+ ? contentHeight + control.topPadding + control.bottomPadding > control.height
+ : false
clip: true
currentIndex: control.currentIndex
@@ -52,13 +53,14 @@ T.Menu {
background: Rectangle {
implicitWidth: 200
implicitHeight: control.Material.menuItemHeight
-
- radius: 3
+ // FullScale doesn't make sense for Menu.
+ radius: control.Material.roundedScale
color: control.Material.dialogColor
layer.enabled: control.Material.elevation > 0
- layer.effect: ElevationEffect {
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
+ roundedScale: control.background.radius
}
}
diff --git a/src/quickcontrols/material/Page.qml b/src/quickcontrols/material/Page.qml
index f8b97a2d3e..f8a1804f32 100644
--- a/src/quickcontrols/material/Page.qml
+++ b/src/quickcontrols/material/Page.qml
@@ -4,6 +4,7 @@
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls.Material
+import QtQuick.Controls.Material.impl
T.Page {
id: control
@@ -19,5 +20,10 @@ T.Page {
background: Rectangle {
color: control.Material.backgroundColor
+
+ layer.enabled: control.enabled && control.Material.elevation > 0
+ layer.effect: ElevationEffect {
+ elevation: control.Material.elevation
+ }
}
}
diff --git a/src/quickcontrols/material/Pane.qml b/src/quickcontrols/material/Pane.qml
index a6e0ae5b33..80385a073f 100644
--- a/src/quickcontrols/material/Pane.qml
+++ b/src/quickcontrols/material/Pane.qml
@@ -15,14 +15,16 @@ T.Pane {
contentHeight + topPadding + bottomPadding)
padding: 12
+ Material.roundedScale: control.Material.elevation > 0 ? Material.ExtraSmallScale : Material.NotRounded
background: Rectangle {
color: control.Material.backgroundColor
- radius: control.Material.elevation > 0 ? 2 : 0
+ radius: control.Material.roundedScale
layer.enabled: control.enabled && control.Material.elevation > 0
- layer.effect: ElevationEffect {
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
+ roundedScale: control.background.radius
}
}
}
diff --git a/src/quickcontrols/material/Popup.qml b/src/quickcontrols/material/Popup.qml
index 7727ef0d3c..e443a1c2ff 100644
--- a/src/quickcontrols/material/Popup.qml
+++ b/src/quickcontrols/material/Popup.qml
@@ -9,8 +9,6 @@ import QtQuick.Controls.Material.impl
T.Popup {
id: control
- Material.elevation: 24
-
implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
contentWidth + leftPadding + rightPadding)
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
@@ -18,6 +16,9 @@ T.Popup {
padding: 12
+ Material.elevation: 4
+ Material.roundedScale: Material.ExtraSmallScale
+
enter: Transition {
// grow_fade_in
NumberAnimation { property: "scale"; from: 0.9; to: 1.0; easing.type: Easing.OutQuint; duration: 220 }
@@ -31,12 +32,14 @@ T.Popup {
}
background: Rectangle {
- radius: 2
+ // FullScale doesn't make sense for Popup.
+ radius: control.Material.roundedScale
color: control.Material.dialogColor
layer.enabled: control.Material.elevation > 0
- layer.effect: ElevationEffect {
+ layer.effect: RoundedElevationEffect {
elevation: control.Material.elevation
+ roundedScale: control.Material.roundedScale
}
}
diff --git a/src/quickcontrols/material/RangeSlider.qml b/src/quickcontrols/material/RangeSlider.qml
index 81507f334d..7547d3d04f 100644
--- a/src/quickcontrols/material/RangeSlider.qml
+++ b/src/quickcontrols/material/RangeSlider.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// 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
@@ -19,6 +19,17 @@ T.RangeSlider {
padding: 6
+ // The RangeSlider is discrete if all of the following requirements are met:
+ // * stepSize is positive
+ // * snapMode is set to SnapAlways
+ // * the difference between to and from is cleanly divisible by the stepSize
+ // * the number of tick marks intended to be rendered is less than the width to height ratio, or vice versa for vertical sliders.
+ readonly property real __steps: Math.abs(to - from) / stepSize
+ readonly property bool __isDiscrete: stepSize >= Number.EPSILON
+ && snapMode === Slider.SnapAlways
+ && Math.abs(Math.round(__steps) - __steps) < Number.EPSILON
+ && Math.floor(__steps) < (horizontal ? background.width / background.height : background.height / background.width)
+
first.handle: SliderHandle {
x: control.leftPadding + (control.horizontal ? control.first.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.first.visualPosition * (control.availableHeight - height))
@@ -37,23 +48,51 @@ T.RangeSlider {
handleHovered: control.second.hovered
}
- background: Rectangle {
+ background: Item {
x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2)
y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0)
implicitWidth: control.horizontal ? 200 : 48
implicitHeight: control.horizontal ? 48 : 200
width: control.horizontal ? control.availableWidth : 4
height: control.horizontal ? 4 : control.availableHeight
- scale: control.horizontal && control.mirrored ? -1 : 1
- color: control.enabled ? Color.transparent(control.Material.accentColor, 0.33) : control.Material.sliderDisabledColor
Rectangle {
- x: control.horizontal ? control.first.position * parent.width : 0
- y: control.horizontal ? 0 : control.second.visualPosition * parent.height
- width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width : 4
- height: control.horizontal ? 4 : control.second.position * parent.height - control.first.position * parent.height
+ x: (control.horizontal ? (control.first.implicitHandleWidth / 2) - (control.__isDiscrete ? 2 : 0) : 0)
+ y: (control.horizontal ? 0 : (control.first.implicitHandleHeight / 2) - (control.__isDiscrete ? 2 : 0))
+ width: parent.width - (control.horizontal ? (control.first.implicitHandleWidth - (control.__isDiscrete ? 4 : 0)) : 0)
+ height: parent.height - (control.horizontal ? 0 : (control.first.implicitHandleHeight - (control.__isDiscrete ? 4 : 0)))
+ scale: control.horizontal && control.mirrored ? -1 : 1
+ radius: Math.min(width, height) / 2
+ color: control.enabled ? Color.transparent(control.Material.accentColor, 0.33) : control.Material.sliderDisabledColor
+
+ Rectangle {
+ x: control.horizontal ? control.first.position * parent.width : 0
+ y: control.horizontal ? 0 : control.second.visualPosition * parent.height
+ width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width : 4
+ height: control.horizontal ? 4 : control.second.position * parent.height - control.first.position * parent.height
+ radius: Math.min(width, height) / 2
+ color: control.enabled ? control.Material.accentColor : control.Material.sliderDisabledColor
+ }
+
+ // Declaring this as a property (in combination with the parent binding below) avoids ids,
+ // which prevent deferred execution.
+ property Repeater repeater: Repeater {
+ parent: control.background.children[0]
+ model: control.__isDiscrete ? Math.floor(control.__steps) + 1 : 0
+ delegate: Rectangle {
+ width: 2
+ height: 2
+ radius: 2
+ x: control.horizontal ? (parent.width - width * 2) * currentPosition + (width / 2) : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : (parent.height - height * 2) * currentPosition + (height / 2)
+ color: (control.horizontal && control.first.visualPosition < currentPosition && control.second.visualPosition > currentPosition)
+ || (!control.horizontal && control.first.visualPosition > currentPosition && control.second.visualPosition < currentPosition)
+ ? control.Material.primaryHighlightedTextColor : control.Material.accentColor
- color: control.enabled ? control.Material.accentColor : control.Material.sliderDisabledColor
+ required property int index
+ readonly property real currentPosition: index / (parent.repeater.count - 1)
+ }
+ }
}
}
}
diff --git a/src/quickcontrols/material/Slider.qml b/src/quickcontrols/material/Slider.qml
index 5061ecf03f..817b3022aa 100644
--- a/src/quickcontrols/material/Slider.qml
+++ b/src/quickcontrols/material/Slider.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// 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
@@ -17,6 +17,17 @@ T.Slider {
padding: 6
+ // The Slider is discrete if all of the following requirements are met:
+ // * stepSize is positive
+ // * snapMode is set to SnapAlways
+ // * the difference between to and from is cleanly divisible by the stepSize
+ // * the number of tick marks intended to be rendered is less than the width to height ratio, or vice versa for vertical sliders.
+ readonly property real __steps: Math.abs(to - from) / stepSize
+ readonly property bool __isDiscrete: stepSize >= Number.EPSILON
+ && snapMode === Slider.SnapAlways
+ && Math.abs(Math.round(__steps) - __steps) < Number.EPSILON
+ && Math.floor(__steps) < (horizontal ? background.width / background.height : background.height / background.width)
+
handle: SliderHandle {
x: control.leftPadding + (control.horizontal ? control.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.visualPosition * (control.availableHeight - height))
@@ -26,23 +37,51 @@ T.Slider {
handleHovered: control.hovered
}
- background: Rectangle {
+ background: Item {
x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2)
y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0)
implicitWidth: control.horizontal ? 200 : 48
implicitHeight: control.horizontal ? 48 : 200
width: control.horizontal ? control.availableWidth : 4
height: control.horizontal ? 4 : control.availableHeight
- scale: control.horizontal && control.mirrored ? -1 : 1
- color: control.enabled ? Color.transparent(control.Material.accentColor, 0.33) : control.Material.sliderDisabledColor
Rectangle {
- x: control.horizontal ? 0 : (parent.width - width) / 2
- y: control.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height
- width: control.horizontal ? control.position * parent.width : 4
- height: control.horizontal ? 4 : control.position * parent.height
+ x: (control.horizontal ? (control.implicitHandleWidth / 2) - (control.__isDiscrete ? 2 : 0) : 0)
+ y: (control.horizontal ? 0 : (control.implicitHandleHeight / 2) - (control.__isDiscrete ? 2 : 0))
+ width: parent.width - (control.horizontal ? (control.implicitHandleWidth - (control.__isDiscrete ? 4 : 0)) : 0)
+ height: parent.height - (control.horizontal ? 0 : (control.implicitHandleHeight - (control.__isDiscrete ? 4 : 0)))
+ scale: control.horizontal && control.mirrored ? -1 : 1
+ radius: Math.min(width, height) / 2
+ color: control.enabled ? Color.transparent(control.Material.accentColor, 0.33) : control.Material.sliderDisabledColor
+
+ Rectangle {
+ x: control.horizontal ? 0 : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : control.visualPosition * parent.height
+ width: control.horizontal ? control.position * parent.width : 4
+ height: control.horizontal ? 4 : control.position * parent.height
+ radius: Math.min(width, height) / 2
+ color: control.enabled ? control.Material.accentColor : control.Material.sliderDisabledColor
+ }
+
+ // Declaring this as a property (in combination with the parent binding below) avoids ids,
+ // which prevent deferred execution.
+ property Repeater repeater: Repeater {
+ parent: control.background.children[0]
+ model: control.__isDiscrete ? Math.floor(control.__steps) + 1 : 0
+ delegate: Rectangle {
+ width: 2
+ height: 2
+ radius: 2
+ x: control.horizontal ? (parent.width - width * 2) * currentPosition + (width / 2) : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : (parent.height - height * 2) * currentPosition + (height / 2)
+ color: (control.horizontal && control.visualPosition > currentPosition)
+ || (!control.horizontal && control.visualPosition <= currentPosition)
+ ? control.Material.primaryHighlightedTextColor : control.Material.accentColor
- color: control.enabled ? control.Material.accentColor : control.Material.sliderDisabledColor
+ required property int index
+ readonly property real currentPosition: index / (parent.repeater.count - 1)
+ }
+ }
}
}
}
diff --git a/src/quickcontrols/material/SpinBox.qml b/src/quickcontrols/material/SpinBox.qml
index 591f5061fa..44fd59f17f 100644
--- a/src/quickcontrols/material/SpinBox.qml
+++ b/src/quickcontrols/material/SpinBox.qml
@@ -17,8 +17,8 @@ T.SpinBox {
up.implicitIndicatorHeight, down.implicitIndicatorHeight)
spacing: 6
- topPadding: 8
- bottomPadding: 16
+ topPadding: Material.textFieldVerticalPadding
+ bottomPadding: Material.textFieldVerticalPadding
leftPadding: control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0)
rightPadding: control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0)
@@ -107,16 +107,14 @@ T.SpinBox {
}
}
- background: Item {
- implicitWidth: 192
- implicitHeight: control.Material.touchTarget
+ background: MaterialTextContainer {
+ implicitWidth: 140
+ implicitHeight: control.Material.textFieldHeight
- Rectangle {
- x: parent.width / 2 - width / 2
- y: parent.y + parent.height - height - control.bottomPadding / 2
- width: control.availableWidth
- height: control.activeFocus ? 2 : 1
- color: control.activeFocus ? control.Material.accentColor : control.Material.hintTextColor
- }
+ outlineColor: (enabled && control.hovered) ? control.Material.primaryTextColor : control.Material.hintTextColor
+ focusedOutlineColor: control.Material.accentColor
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: true
+ horizontalPadding: control.Material.textFieldHorizontalPadding
}
}
diff --git a/src/quickcontrols/material/StackView.qml b/src/quickcontrols/material/StackView.qml
index 241b91f2d7..c3182442a2 100644
--- a/src/quickcontrols/material/StackView.qml
+++ b/src/quickcontrols/material/StackView.qml
@@ -8,39 +8,56 @@ import QtQuick.Controls.Material
T.StackView {
id: control
+ component LineAnimation: NumberAnimation {
+ duration: 200
+ easing.type: Easing.OutCubic
+ }
+
+ component FadeIn: LineAnimation {
+ property: "opacity"
+ from: 0.0
+ to: 1.0
+ }
+
+ component FadeOut: LineAnimation {
+ property: "opacity"
+ from: 1.0
+ to: 0.0
+ }
+
popEnter: Transition {
// slide_in_left
- NumberAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * -control.width; to: 0; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * -control.width; to: 0 }
+ FadeIn {}
}
popExit: Transition {
// slide_out_right
- NumberAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * control.width; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * control.width }
+ FadeOut {}
}
pushEnter: Transition {
// slide_in_right
- NumberAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * control.width; to: 0; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * control.width; to: 0 }
+ FadeIn {}
}
pushExit: Transition {
// slide_out_left
- NumberAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * -control.width; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * -control.width }
+ FadeOut {}
}
replaceEnter: Transition {
// slide_in_right
- NumberAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * control.width; to: 0; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: (control.mirrored ? -0.5 : 0.5) * control.width; to: 0 }
+ FadeIn {}
}
replaceExit: Transition {
// slide_out_left
- NumberAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * -control.width; duration: 200; easing.type: Easing.OutCubic }
- NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200; easing.type: Easing.OutCubic }
+ LineAnimation { property: "x"; from: 0; to: (control.mirrored ? -0.5 : 0.5) * -control.width }
+ FadeOut {}
}
}
diff --git a/src/quickcontrols/material/Switch.qml b/src/quickcontrols/material/Switch.qml
index d27621a74f..29a1297684 100644
--- a/src/quickcontrols/material/Switch.qml
+++ b/src/quickcontrols/material/Switch.qml
@@ -34,7 +34,8 @@ T.Switch {
Ripple {
x: parent.handle.x + parent.handle.width / 2 - width / 2
y: parent.handle.y + parent.handle.height / 2 - height / 2
- width: 28; height: 28
+ width: 28
+ height: 28
pressed: control.pressed
active: enabled && (control.down || control.visualFocus || control.hovered)
color: control.checked ? control.Material.highlightedRippleColor : control.Material.rippleColor
diff --git a/src/quickcontrols/material/TextArea.qml b/src/quickcontrols/material/TextArea.qml
index 242cbf691b..99efa222cf 100644
--- a/src/quickcontrols/material/TextArea.qml
+++ b/src/quickcontrols/material/TextArea.qml
@@ -14,37 +14,70 @@ T.TextArea {
implicitBackgroundWidth + leftInset + rightInset,
placeholder.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(contentHeight + topPadding + bottomPadding,
- implicitBackgroundHeight + topInset + bottomInset,
- placeholder.implicitHeight + 1 + topPadding + bottomPadding)
+ implicitBackgroundHeight + topInset + bottomInset)
- topPadding: 8
- bottomPadding: 16
+ // If we're clipped, or we're in a Flickable that's clipped, set our topInset
+ // to half the height of the placeholder text to avoid it being clipped.
+ topInset: clip || (parent?.parent as Flickable && parent?.parent.clip) ? placeholder.largestHeight / 2 : 0
+
+ leftPadding: Material.textFieldHorizontalPadding
+ rightPadding: Material.textFieldHorizontalPadding
+ // Need to account for the placeholder text when it's sitting on top.
+ topPadding: Material.containerStyle === Material.Filled && placeholderText.length > 0 && (activeFocus || length > 0)
+ ? Material.textFieldVerticalPadding + placeholder.largestHeight
+ // When the condition above is not met, the text should always sit in the middle
+ // of a default-height TextArea, which is just near the top for a higher-than-default one.
+ // Account for any topInset as well, otherwise the text will be too close to the background.
+ : ((implicitBackgroundHeight - placeholder.largestHeight) / 2) + topInset
+ bottomPadding: Material.textFieldVerticalPadding
color: enabled ? Material.foreground : Material.hintTextColor
selectionColor: Material.accentColor
selectedTextColor: Material.primaryHighlightedTextColor
- placeholderTextColor: Material.hintTextColor
+ placeholderTextColor: enabled && activeFocus ? Material.accentColor : Material.hintTextColor
+
+ Material.containerStyle: Material.Outlined
+
cursorDelegate: CursorDelegate { }
- PlaceholderText {
+ FloatingPlaceholderText {
id: placeholder
- x: control.leftPadding
- y: control.topPadding
+ // Don't set this to control.leftPadding, because we don't want it to change if the user changes leftPadding.
+ x: control.Material.textFieldHorizontalPadding
width: control.width - (control.leftPadding + control.rightPadding)
- height: control.height - (control.topPadding + control.bottomPadding)
text: control.placeholderText
font: control.font
color: control.placeholderTextColor
- verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
renderType: control.renderType
- visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
+ // When the TextArea is in a Flickable, the background is reparented to it
+ // so that decorations don't move with the content. We need to do the same.
+ // Also allow the background to be set to null; in that case we're just not visible.
+ parent: control.background?.parent ?? null
+
+ filled: control.Material.containerStyle === Material.Filled
+ verticalPadding: control.Material.textFieldVerticalPadding
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: control.length > 0
+ controlImplicitBackgroundHeight: control.implicitBackgroundHeight
+ controlHeight: control.height
}
- background: Rectangle {
- y: parent.height - height - control.bottomPadding / 2
+ background: MaterialTextContainer {
implicitWidth: 120
- height: control.activeFocus ? 2 : 1
- color: control.activeFocus ? control.Material.accentColor : control.Material.hintTextColor
+ implicitHeight: control.Material.textFieldHeight
+
+ filled: control.Material.containerStyle === Material.Filled
+ fillColor: control.Material.textFieldFilledContainerColor
+ outlineColor: (enabled && control.hovered) ? control.Material.primaryTextColor : control.Material.hintTextColor
+ focusedOutlineColor: control.Material.accentColor
+ // When the control's size is set larger than its implicit size, use whatever size is smaller
+ // so that the gap isn't too big.
+ placeholderTextWidth: Math.min(placeholder.width, placeholder.implicitWidth) * placeholder.scale
+ placeholderTextHAlign: control.effectiveHorizontalAlignment
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: control.length > 0
+ placeholderHasText: placeholder.text.length > 0
+ horizontalPadding: control.Material.textFieldHorizontalPadding
}
}
diff --git a/src/quickcontrols/material/TextField.qml b/src/quickcontrols/material/TextField.qml
index 598f66f938..9294146fac 100644
--- a/src/quickcontrols/material/TextField.qml
+++ b/src/quickcontrols/material/TextField.qml
@@ -13,40 +13,67 @@ T.TextField {
implicitWidth: implicitBackgroundWidth + leftInset + rightInset
|| Math.max(contentWidth, placeholder.implicitWidth) + leftPadding + rightPadding
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
- contentHeight + topPadding + bottomPadding,
- placeholder.implicitHeight + topPadding + bottomPadding)
+ contentHeight + topPadding + bottomPadding)
- topPadding: 8
- bottomPadding: 16
+ // If we're clipped, set topInset to half the height of the placeholder text to avoid it being clipped.
+ topInset: clip ? placeholder.largestHeight / 2 : 0
+
+ leftPadding: Material.textFieldHorizontalPadding
+ rightPadding: Material.textFieldHorizontalPadding
+ // Need to account for the placeholder text when it's sitting on top.
+ topPadding: Material.containerStyle === Material.Filled
+ ? placeholderText.length > 0 && (activeFocus || length > 0)
+ ? Material.textFieldVerticalPadding + placeholder.largestHeight
+ : Material.textFieldVerticalPadding
+ // Account for any topInset (used to avoid floating placeholder text being clipped),
+ // otherwise the text will be too close to the background.
+ : Material.textFieldVerticalPadding + topInset
+ bottomPadding: Material.textFieldVerticalPadding
color: enabled ? Material.foreground : Material.hintTextColor
selectionColor: Material.accentColor
selectedTextColor: Material.primaryHighlightedTextColor
- placeholderTextColor: Material.hintTextColor
+ placeholderTextColor: enabled && activeFocus ? Material.accentColor : Material.hintTextColor
verticalAlignment: TextInput.AlignVCenter
+ Material.containerStyle: Material.Outlined
+
cursorDelegate: CursorDelegate { }
- PlaceholderText {
+ FloatingPlaceholderText {
id: placeholder
- x: control.leftPadding
- y: control.topPadding
+ // Don't set this to control.leftPadding, because we don't want it to change if the user changes leftPadding.
+ x: control.Material.textFieldHorizontalPadding
width: control.width - (control.leftPadding + control.rightPadding)
- height: control.height - (control.topPadding + control.bottomPadding)
text: control.placeholderText
font: control.font
color: control.placeholderTextColor
- verticalAlignment: control.verticalAlignment
elide: Text.ElideRight
renderType: control.renderType
- visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
+
+ filled: control.Material.containerStyle === Material.Filled
+ verticalPadding: control.Material.textFieldVerticalPadding
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: control.length > 0
+ controlImplicitBackgroundHeight: control.implicitBackgroundHeight
+ controlHeight: control.height
}
- background: Rectangle {
- y: control.height - height - control.bottomPadding + 8
+ background: MaterialTextContainer {
implicitWidth: 120
- height: control.activeFocus || (enabled && control.hovered) ? 2 : 1
- color: control.activeFocus ? control.Material.accentColor
- : ((enabled && control.hovered) ? control.Material.primaryTextColor : control.Material.hintTextColor)
+ implicitHeight: control.Material.textFieldHeight
+
+ filled: control.Material.containerStyle === Material.Filled
+ fillColor: control.Material.textFieldFilledContainerColor
+ outlineColor: (enabled && control.hovered) ? control.Material.primaryTextColor : control.Material.hintTextColor
+ focusedOutlineColor: control.Material.accentColor
+ // When the control's size is set larger than its implicit size, use whatever size is smaller
+ // so that the gap isn't too big.
+ placeholderTextWidth: Math.min(placeholder.width, placeholder.implicitWidth) * placeholder.scale
+ placeholderTextHAlign: control.effectiveHorizontalAlignment
+ controlHasActiveFocus: control.activeFocus
+ controlHasText: control.length > 0
+ placeholderHasText: placeholder.text.length > 0
+ horizontalPadding: control.Material.textFieldHorizontalPadding
}
}
diff --git a/src/quickcontrols/material/TreeViewDelegate.qml b/src/quickcontrols/material/TreeViewDelegate.qml
index 1a6e35dadc..9f1d444383 100644
--- a/src/quickcontrols/material/TreeViewDelegate.qml
+++ b/src/quickcontrols/material/TreeViewDelegate.qml
@@ -64,6 +64,7 @@ T.TreeViewDelegate {
// The edit delegate is a separate component, and doesn't need
// to follow the same strict rules that are applied to a control.
// qmllint disable attached-property-reuse
+ // qmllint disable controls-attached-property-reuse
// qmllint disable controls-sanity
TableView.editDelegate: FocusScope {
width: parent.width
@@ -71,7 +72,7 @@ T.TreeViewDelegate {
readonly property int __role: {
let model = control.treeView.model
- let index = control.treeView.modelIndex(column, row)
+ let index = control.treeView.index(row, column)
let editText = model.data(index, Qt.EditRole)
return editText !== undefined ? Qt.EditRole : Qt.DisplayRole
}
@@ -81,17 +82,18 @@ T.TreeViewDelegate {
x: control.contentItem.x
y: (parent.height - height) / 2
width: control.contentItem.width
- text: control.treeView.model.data(control.treeView.modelIndex(column, row), __role)
+ text: control.treeView.model.data(control.treeView.index(row, column), __role)
focus: true
}
TableView.onCommit: {
- let index = TableView.view.modelIndex(column, row)
+ let index = TableView.view.index(row, column)
TableView.view.model.setData(index, textField.text, __role)
}
Component.onCompleted: textField.selectAll()
}
// qmllint enable attached-property-reuse
+ // qmllint enable controls-attached-property-reuse
// qmllint enable controls-sanity
}
diff --git a/src/quickcontrols/material/Tumbler.qml b/src/quickcontrols/material/Tumbler.qml
index 59320cf52b..48d0c2e739 100644
--- a/src/quickcontrols/material/Tumbler.qml
+++ b/src/quickcontrols/material/Tumbler.qml
@@ -14,6 +14,8 @@ T.Tumbler {
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
implicitContentHeight + topPadding + bottomPadding)
+ readonly property real __delegateHeight: availableHeight / visibleItemCount
+
delegate: Text {
text: modelData
color: control.Material.foreground
@@ -33,13 +35,11 @@ T.Tumbler {
delegate: control.delegate
path: Path {
startX: control.contentItem.width / 2
- startY: -control.contentItem.delegateHeight / 2
+ startY: -control.__delegateHeight / 2
PathLine {
x: control.contentItem.width / 2
- y: (control.visibleItemCount + 1) * control.contentItem.delegateHeight - control.contentItem.delegateHeight / 2
+ y: (control.visibleItemCount + 1) * control.__delegateHeight - control.__delegateHeight / 2
}
}
-
- property real delegateHeight: control.availableHeight / control.visibleItemCount
}
}
diff --git a/src/quickcontrols/material/VerticalHeaderView.qml b/src/quickcontrols/material/VerticalHeaderView.qml
index 6b4d9e658b..0646f6135d 100644
--- a/src/quickcontrols/material/VerticalHeaderView.qml
+++ b/src/quickcontrols/material/VerticalHeaderView.qml
@@ -1,6 +1,8 @@
// Copyright (C) 2020 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
+pragma ComponentBehavior: Bound
+
import QtQuick
import QtQuick.Templates as T
import QtQuick.Controls.Material
@@ -18,6 +20,10 @@ T.VerticalHeaderView {
implicitHeight: syncView ? syncView.height : 0
delegate: Rectangle {
+ id: delegate
+
+ required property var model
+
// Qt6: add cellPadding (and font etc) as public API in headerview
readonly property real cellPadding: 8
@@ -27,11 +33,9 @@ T.VerticalHeaderView {
Label {
id: text
- text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole]
- : model[control.textRole])
- : modelData
- width: parent.width
- height: parent.height
+ text: delegate.model[control.textRole]
+ width: delegate.width
+ height: delegate.height
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
color: enabled ? control.Material.foreground : control.Material.hintTextColor
diff --git a/src/quickcontrols/material/impl/CMakeLists.txt b/src/quickcontrols/material/impl/CMakeLists.txt
index ebf3e1cbf3..774655c2ff 100644
--- a/src/quickcontrols/material/impl/CMakeLists.txt
+++ b/src/quickcontrols/material/impl/CMakeLists.txt
@@ -17,19 +17,21 @@ set(qml_files
"SwitchIndicator.qml"
)
-qt_internal_add_qml_module(qtquickcontrols2materialstyleimplplugin
+qt_internal_add_qml_module(QuickControls2MaterialStyleImpl
URI "QtQuick.Controls.Material.impl"
VERSION "${PROJECT_VERSION}"
PAST_MAJOR_VERSIONS 2
CLASS_NAME QtQuickControls2MaterialStyleImplPlugin
DEPENDENCIES
QtQuick/auto
+ QtQuick.Controls.impl/auto
PLUGIN_TARGET qtquickcontrols2materialstyleimplplugin
- NO_PLUGIN_OPTIONAL
SOURCES
qquickmaterialbusyindicator.cpp qquickmaterialbusyindicator_p.h
+ qquickmaterialplaceholdertext.cpp qquickmaterialplaceholdertext_p.h
qquickmaterialprogressbar.cpp qquickmaterialprogressbar_p.h
qquickmaterialripple.cpp qquickmaterialripple_p.h
+ qquickmaterialtextcontainer.cpp qquickmaterialtextcontainer_p.h
QML_FILES
${qml_files}
DEFINES
@@ -38,8 +40,10 @@ qt_internal_add_qml_module(qtquickcontrols2materialstyleimplplugin
LIBRARIES
Qt::CorePrivate
Qt::Gui
+ Qt::Qml
Qt::QmlPrivate
Qt::QuickControls2ImplPrivate
+ Qt::Quick
Qt::QuickPrivate
Qt::QuickTemplates2Private
)
diff --git a/src/quickcontrols/material/impl/RadioIndicator.qml b/src/quickcontrols/material/impl/RadioIndicator.qml
index 9570065692..2cf46a69cb 100644
--- a/src/quickcontrols/material/impl/RadioIndicator.qml
+++ b/src/quickcontrols/material/impl/RadioIndicator.qml
@@ -12,19 +12,42 @@ Rectangle {
implicitHeight: 20
radius: width / 2
border.width: 2
- border.color: !control.enabled ? control.Material.hintTextColor
- : control.checked || control.down ? control.Material.accentColor : control.Material.secondaryTextColor
+ border.color: targetColor
color: "transparent"
+ // Store the target color in a separate property, because there are two animations that depend on it.
+ readonly property color targetColor: !control.enabled ? control.Material.hintTextColor
+ : control.checked || control.down ? control.Material.accentColor : control.Material.secondaryTextColor
+
property T.AbstractButton control
+ Behavior on border.color {
+ ColorAnimation {
+ duration: 100
+ easing.type: Easing.OutCubic
+ }
+ }
+
Rectangle {
x: (parent.width - width) / 2
y: (parent.height - height) / 2
width: 10
height: 10
radius: width / 2
- color: parent.border.color
- visible: indicator.control.checked || indicator.control.down
+ color: indicator.targetColor
+ scale: indicator.control.checked || indicator.control.down ? 1 : 0
+
+ Behavior on color {
+ ColorAnimation {
+ duration: 100
+ easing.type: Easing.OutCubic
+ }
+ }
+
+ Behavior on scale {
+ NumberAnimation {
+ duration: 100
+ }
+ }
}
}
diff --git a/src/quickcontrols/material/impl/RectangularGlow.qml b/src/quickcontrols/material/impl/RectangularGlow.qml
index b604049cf9..5fc649c393 100644
--- a/src/quickcontrols/material/impl/RectangularGlow.qml
+++ b/src/quickcontrols/material/impl/RectangularGlow.qml
@@ -202,6 +202,6 @@ Item {
property real spread: rootItem.spread / 2.0
property real cornerRadius: clampedCornerRadius()
- fragmentShader: "qrc:/qt-project.org/imports/QtQuick/Controls/Material/shaders/RectangularGlow.frag"
+ fragmentShader: "qrc:/qt-project.org/imports/QtQuick/Controls/Material/shaders/RectangularGlow.frag.qsb"
}
}
diff --git a/src/quickcontrols/material/impl/SliderHandle.qml b/src/quickcontrols/material/impl/SliderHandle.qml
index ca7912b91d..4681992ab0 100644
--- a/src/quickcontrols/material/impl/SliderHandle.qml
+++ b/src/quickcontrols/material/impl/SliderHandle.qml
@@ -1,4 +1,4 @@
-// Copyright (C) 2017 The Qt Company Ltd.
+// Copyright (C) 2023 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
@@ -22,14 +22,9 @@ Item {
width: parent.width
height: parent.height
radius: width / 2
- scale: root.handlePressed ? 1.5 : 1
- color: root.control.enabled ? root.control.Material.accentColor : root.control.Material.sliderDisabledColor
-
- Behavior on scale {
- NumberAnimation {
- duration: 250
- }
- }
+ color: root.control
+ ? root.control.enabled ? root.control.Material.accentColor : root.control.Material.sliderDisabledColor
+ : "transparent"
}
Ripple {
@@ -38,6 +33,6 @@ Item {
width: 22; height: 22
pressed: root.handlePressed
active: root.handlePressed || root.handleHasFocus || (enabled && root.handleHovered)
- color: root.control.Material.highlightedRippleColor
+ color: root.control ? root.control.Material.highlightedRippleColor : "transparent"
}
}
diff --git a/src/quickcontrols/material/impl/SwitchIndicator.qml b/src/quickcontrols/material/impl/SwitchIndicator.qml
index 2d48302e01..d864f3887a 100644
--- a/src/quickcontrols/material/impl/SwitchIndicator.qml
+++ b/src/quickcontrols/material/impl/SwitchIndicator.qml
@@ -9,8 +9,8 @@ import QtQuick.Controls.Material.impl
Rectangle {
id: indicator
- width: 52
- height: 32
+ width: control.Material.switchIndicatorWidth
+ height: control.Material.switchIndicatorHeight
radius: height / 2
y: parent.height / 2 - height / 2
color: control.enabled
@@ -62,9 +62,9 @@ Rectangle {
scale: indicator.control.down ? 1 : (indicator.control.checked ? checkedSize / largestSize : normalSize / largestSize)
readonly property int offset: 2
- readonly property real normalSize: !hasIcon ? 16 : checkedSize
- readonly property real checkedSize: 24
- readonly property real largestSize: 28
+ readonly property real normalSize: !hasIcon ? indicator.control.Material.switchNormalHandleHeight : checkedSize
+ readonly property real checkedSize: indicator.control.Material.switchCheckedHandleHeight
+ readonly property real largestSize: indicator.control.Material.switchLargestHandleHeight
readonly property real largestScale: largestSize / normalSize
readonly property bool hasIcon: indicator.control.icon.name.length > 0
|| indicator.control.icon.source.toString().length > 0
diff --git a/src/quickcontrols/material/impl/qquickmaterialbusyindicator_p.h b/src/quickcontrols/material/impl/qquickmaterialbusyindicator_p.h
index b6bbd925c7..c18257127d 100644
--- a/src/quickcontrols/material/impl/qquickmaterialbusyindicator_p.h
+++ b/src/quickcontrols/material/impl/qquickmaterialbusyindicator_p.h
@@ -51,6 +51,4 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMaterialBusyIndicator)
-
#endif // QQUICKMATERIALBUSYINDICATOR_P_H
diff --git a/src/quickcontrols/material/impl/qquickmaterialplaceholdertext.cpp b/src/quickcontrols/material/impl/qquickmaterialplaceholdertext.cpp
new file mode 100644
index 0000000000..2447193d6a
--- /dev/null
+++ b/src/quickcontrols/material/impl/qquickmaterialplaceholdertext.cpp
@@ -0,0 +1,321 @@
+// Copyright (C) 2023 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
+
+#include "qquickmaterialplaceholdertext_p.h"
+
+#include <QtCore/qpropertyanimation.h>
+#include <QtCore/qparallelanimationgroup.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+#include <QtQml/qqmlinfo.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+#include <QtQuickTemplates2/private/qquicktextarea_p.h>
+#include <QtQuickTemplates2/private/qquicktextfield_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const qreal floatingScale = 0.8;
+Q_GLOBAL_STATIC(QEasingCurve, animationEasingCurve, QEasingCurve::OutSine);
+
+/*
+ This class makes it easier to animate the various placeholder text changes
+ for each type of text container (filled, outlined).
+
+ By doing animations in C++, we avoid having a bunch of states, transitions,
+ and animations (which are all QObjects) declared in QML, even if that text
+ control never gets focus and hence never needs them.
+*/
+
+QQuickMaterialPlaceholderText::QQuickMaterialPlaceholderText(QQuickItem *parent)
+ : QQuickPlaceholderText(parent)
+{
+ connect(this, &QQuickMaterialPlaceholderText::effectiveHorizontalAlignmentChanged,
+ this, &QQuickMaterialPlaceholderText::adjustTransformOrigin);
+}
+
+bool QQuickMaterialPlaceholderText::isFilled() const
+{
+ return m_filled;
+}
+
+void QQuickMaterialPlaceholderText::setFilled(bool filled)
+{
+ if (filled == m_filled)
+ return;
+
+ m_filled = filled;
+ update();
+ void filledChanged();
+}
+
+bool QQuickMaterialPlaceholderText::controlHasActiveFocus() const
+{
+ return m_controlHasActiveFocus;
+}
+
+void QQuickMaterialPlaceholderText::setControlHasActiveFocus(bool controlHasActiveFocus)
+{
+ if (m_controlHasActiveFocus == controlHasActiveFocus)
+ return;
+
+ m_controlHasActiveFocus = controlHasActiveFocus;
+ if (m_controlHasActiveFocus)
+ controlGotActiveFocus();
+ else
+ controlLostActiveFocus();
+ emit controlHasActiveFocusChanged();
+}
+
+bool QQuickMaterialPlaceholderText::controlHasText() const
+{
+ return m_controlHasText;
+}
+
+void QQuickMaterialPlaceholderText::setControlHasText(bool controlHasText)
+{
+ if (m_controlHasText == controlHasText)
+ return;
+
+ m_controlHasText = controlHasText;
+ maybeSetFocusAnimationProgress();
+ emit controlHasTextChanged();
+}
+
+/*
+ Placeholder text of outlined text fields should float when:
+ - There is placeholder text, and
+ - The control has active focus, or
+ - The control has text
+*/
+bool QQuickMaterialPlaceholderText::shouldFloat() const
+{
+ const bool controlHasActiveFocusOrText = m_controlHasActiveFocus || m_controlHasText;
+ return m_filled
+ ? controlHasActiveFocusOrText
+ : !text().isEmpty() && controlHasActiveFocusOrText;
+}
+
+bool QQuickMaterialPlaceholderText::shouldAnimate() const
+{
+ return m_filled
+ ? !m_controlHasText
+ : !m_controlHasText && !text().isEmpty();
+}
+
+void QQuickMaterialPlaceholderText::updateY()
+{
+ setY(shouldFloat() ? floatingTargetY() : normalTargetY());
+}
+
+qreal controlTopInset(QQuickItem *textControl)
+{
+ if (const auto textArea = qobject_cast<QQuickTextArea *>(textControl))
+ return textArea->topInset();
+
+ if (const auto textField = qobject_cast<QQuickTextField *>(textControl))
+ return textField->topInset();
+
+ return 0;
+}
+
+qreal QQuickMaterialPlaceholderText::normalTargetY() const
+{
+ auto *textArea = qobject_cast<QQuickTextArea *>(textControl());
+ if (textArea && m_controlHeight >= textArea->implicitHeight()) {
+ // TextArea can be multiple lines in height, and we want the
+ // placeholder text to sit in the middle of its default-height
+ // (one-line) if its explicit height is greater than or equal to its
+ // implicit height - i.e. if it has room for it. If it doesn't have
+ // room, just do what TextField does.
+ // We should also account for any topInset the user might have specified,
+ // which is useful to ensure that the text doesn't get clipped.
+ return ((m_controlImplicitBackgroundHeight - m_largestHeight) / 2.0)
+ + controlTopInset(textControl());
+ }
+
+ // When the placeholder text shouldn't float, it should sit in the middle of the TextField.
+ return (m_controlHeight - height()) / 2.0;
+}
+
+qreal QQuickMaterialPlaceholderText::floatingTargetY() const
+{
+ // For filled text fields, the placeholder text sits just above
+ // the text when floating.
+ if (m_filled)
+ return m_verticalPadding;
+
+ // Outlined text fields have the placeaholder vertically centered
+ // along the outline at the top.
+ return (-m_largestHeight / 2.0) + controlTopInset(textControl());
+}
+
+/*!
+ \internal
+
+ The height of the text at its largest size that we set.
+*/
+int QQuickMaterialPlaceholderText::largestHeight() const
+{
+ return m_largestHeight;
+}
+
+qreal QQuickMaterialPlaceholderText::controlImplicitBackgroundHeight() const
+{
+ return m_controlImplicitBackgroundHeight;
+}
+
+void QQuickMaterialPlaceholderText::setControlImplicitBackgroundHeight(qreal controlImplicitBackgroundHeight)
+{
+ if (qFuzzyCompare(m_controlImplicitBackgroundHeight, controlImplicitBackgroundHeight))
+ return;
+
+ m_controlImplicitBackgroundHeight = controlImplicitBackgroundHeight;
+ updateY();
+ emit controlImplicitBackgroundHeightChanged();
+}
+
+/*!
+ \internal
+
+ Exists so that we can call updateY when the control's height changes,
+ which is necessary for some y position calculations.
+
+ We don't really need it for the actual calculations, since we already
+ have access to the control, from which the property comes, but
+ it's simpler just to use it.
+*/
+qreal QQuickMaterialPlaceholderText::controlHeight() const
+{
+ return m_controlHeight;
+}
+
+void QQuickMaterialPlaceholderText::setControlHeight(qreal controlHeight)
+{
+ if (qFuzzyCompare(m_controlHeight, controlHeight))
+ return;
+
+ m_controlHeight = controlHeight;
+ updateY();
+}
+
+qreal QQuickMaterialPlaceholderText::verticalPadding() const
+{
+ return m_verticalPadding;
+}
+
+void QQuickMaterialPlaceholderText::setVerticalPadding(qreal verticalPadding)
+{
+ if (qFuzzyCompare(m_verticalPadding, verticalPadding))
+ return;
+
+ m_verticalPadding = verticalPadding;
+ emit verticalPaddingChanged();
+}
+
+void QQuickMaterialPlaceholderText::adjustTransformOrigin()
+{
+ switch (effectiveHAlign()) {
+ case QQuickText::AlignLeft:
+ Q_FALLTHROUGH();
+ case QQuickText::AlignJustify:
+ setTransformOrigin(QQuickItem::Left);
+ break;
+ case QQuickText::AlignRight:
+ setTransformOrigin(QQuickItem::Right);
+ break;
+ case QQuickText::AlignHCenter:
+ setTransformOrigin(QQuickItem::Center);
+ break;
+ }
+}
+
+void QQuickMaterialPlaceholderText::controlGotActiveFocus()
+{
+ if (m_focusOutAnimation) {
+ // Focus changes can happen before the animations finish.
+ // In that case, stop the animation, which will eventually delete it.
+ // Until it's deleted, we clear the pointer so that our asserts don't fail
+ // for the wrong reason.
+ m_focusOutAnimation->stop();
+ m_focusOutAnimation.clear();
+ }
+
+ Q_ASSERT(!m_focusInAnimation);
+ if (shouldAnimate()) {
+ m_focusInAnimation = new QParallelAnimationGroup(this);
+
+ QPropertyAnimation *yAnimation = new QPropertyAnimation(this, "y", this);
+ yAnimation->setDuration(300);
+ yAnimation->setStartValue(y());
+ yAnimation->setEndValue(floatingTargetY());
+ yAnimation->setEasingCurve(*animationEasingCurve);
+ m_focusInAnimation->addAnimation(yAnimation);
+
+ auto *scaleAnimation = new QPropertyAnimation(this, "scale", this);
+ scaleAnimation->setDuration(300);
+ scaleAnimation->setStartValue(1);
+ scaleAnimation->setEndValue(floatingScale);
+ yAnimation->setEasingCurve(*animationEasingCurve);
+ m_focusInAnimation->addAnimation(scaleAnimation);
+
+ m_focusInAnimation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ updateY();
+ }
+}
+
+void QQuickMaterialPlaceholderText::controlLostActiveFocus()
+{
+ if (m_focusInAnimation) {
+ m_focusInAnimation->stop();
+ m_focusInAnimation.clear();
+ }
+
+ Q_ASSERT(!m_focusOutAnimation);
+ if (shouldAnimate()) {
+ m_focusOutAnimation = new QParallelAnimationGroup(this);
+
+ auto *yAnimation = new QPropertyAnimation(this, "y", this);
+ yAnimation->setDuration(300);
+ yAnimation->setStartValue(y());
+ yAnimation->setEndValue(normalTargetY());
+ yAnimation->setEasingCurve(*animationEasingCurve);
+ m_focusOutAnimation->addAnimation(yAnimation);
+
+ auto *scaleAnimation = new QPropertyAnimation(this, "scale", this);
+ scaleAnimation->setDuration(300);
+ scaleAnimation->setStartValue(floatingScale);
+ scaleAnimation->setEndValue(1);
+ yAnimation->setEasingCurve(*animationEasingCurve);
+ m_focusOutAnimation->addAnimation(scaleAnimation);
+
+ m_focusOutAnimation->start(QAbstractAnimation::DeleteWhenStopped);
+ } else {
+ updateY();
+ }
+}
+
+void QQuickMaterialPlaceholderText::maybeSetFocusAnimationProgress()
+{
+ updateY();
+ setScale(shouldFloat() ? floatingScale : 1.0);
+}
+
+void QQuickMaterialPlaceholderText::componentComplete()
+{
+ QQuickPlaceholderText::componentComplete();
+
+ adjustTransformOrigin();
+
+ m_largestHeight = implicitHeight();
+ if (m_largestHeight > 0) {
+ emit largestHeightChanged();
+ } else {
+ qmlWarning(this) << "Expected implicitHeight of placeholder text" << text()
+ << "to be greater than 0 by component completion!";
+ }
+
+ maybeSetFocusAnimationProgress();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols/material/impl/qquickmaterialplaceholdertext_p.h b/src/quickcontrols/material/impl/qquickmaterialplaceholdertext_p.h
new file mode 100644
index 0000000000..bf851d367a
--- /dev/null
+++ b/src/quickcontrols/material/impl/qquickmaterialplaceholdertext_p.h
@@ -0,0 +1,105 @@
+// Copyright (C) 2023 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
+
+#ifndef QQUICKMATERIALPLACEHOLDERTEXT_P_H
+#define QQUICKMATERIALPLACEHOLDERTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtGui/qcolor.h>
+#include <QtQuickControls2Impl/private/qquickplaceholdertext_p.h>
+
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QParallelAnimationGroup;
+
+class QQuickMaterialPlaceholderText : public QQuickPlaceholderText
+{
+ Q_OBJECT
+ Q_PROPERTY(bool filled READ isFilled WRITE setFilled NOTIFY filledChanged FINAL)
+ Q_PROPERTY(bool controlHasActiveFocus READ controlHasActiveFocus
+ WRITE setControlHasActiveFocus NOTIFY controlHasActiveFocusChanged FINAL)
+ Q_PROPERTY(bool controlHasText READ controlHasText WRITE setControlHasText NOTIFY controlHasTextChanged FINAL)
+ Q_PROPERTY(int largestHeight READ largestHeight NOTIFY largestHeightChanged FINAL)
+ Q_PROPERTY(qreal verticalPadding READ verticalPadding WRITE setVerticalPadding NOTIFY verticalPaddingChanged FINAL)
+ Q_PROPERTY(qreal controlImplicitBackgroundHeight READ controlImplicitBackgroundHeight
+ WRITE setControlImplicitBackgroundHeight NOTIFY controlImplicitBackgroundHeightChanged FINAL)
+ Q_PROPERTY(qreal controlHeight READ controlHeight WRITE setControlHeight FINAL)
+ QML_NAMED_ELEMENT(FloatingPlaceholderText)
+ QML_ADDED_IN_VERSION(6, 5)
+
+public:
+ explicit QQuickMaterialPlaceholderText(QQuickItem *parent = nullptr);
+
+ bool isFilled() const;
+ void setFilled(bool filled);
+
+ int largestHeight() const;
+
+ bool controlHasActiveFocus() const;
+ void setControlHasActiveFocus(bool controlHasActiveFocus);
+
+ bool controlHasText() const;
+ void setControlHasText(bool controlHasText);
+
+ qreal controlImplicitBackgroundHeight() const;
+ void setControlImplicitBackgroundHeight(qreal controlImplicitBackgroundHeight);
+
+ qreal controlHeight() const;
+ void setControlHeight(qreal controlHeight);
+
+ qreal verticalPadding() const;
+ void setVerticalPadding(qreal verticalPadding);
+
+signals:
+ void filledChanged();
+ void largestHeightChanged();
+ void controlHasActiveFocusChanged();
+ void controlHasTextChanged();
+ void controlImplicitBackgroundHeightChanged();
+ void verticalPaddingChanged();
+
+private slots:
+ void adjustTransformOrigin();
+
+private:
+ bool shouldFloat() const;
+ bool shouldAnimate() const;
+
+ void updateY();
+ qreal normalTargetY() const;
+ qreal floatingTargetY() const;
+
+ void controlGotActiveFocus();
+ void controlLostActiveFocus();
+
+ void maybeSetFocusAnimationProgress();
+
+ void componentComplete() override;
+
+ bool m_filled = false;
+ bool m_controlHasActiveFocus = false;
+ bool m_controlHasText = false;
+ int m_largestHeight = 0;
+ qreal m_verticalPadding = 0;
+ qreal m_controlImplicitBackgroundHeight = 0;
+ qreal m_controlHeight = 0;
+ QPointer<QParallelAnimationGroup> m_focusInAnimation;
+ QPointer<QParallelAnimationGroup> m_focusOutAnimation;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKMATERIALPLACEHOLDERTEXT_P_H
diff --git a/src/quickcontrols/material/impl/qquickmaterialprogressbar.cpp b/src/quickcontrols/material/impl/qquickmaterialprogressbar.cpp
index 67c9f614f5..19e02dc5b7 100644
--- a/src/quickcontrols/material/impl/qquickmaterialprogressbar.cpp
+++ b/src/quickcontrols/material/impl/qquickmaterialprogressbar.cpp
@@ -16,7 +16,7 @@ QT_BEGIN_NAMESPACE
static const int PauseDuration = 520;
static const int SlideDuration = 1240;
-static const int TotalDuration = SlideDuration + PauseDuration;
+static const int QmpbTotalDuration = SlideDuration + PauseDuration;
class QQuickMaterialProgressBarNode : public QQuickAnimatedNode
{
@@ -37,7 +37,7 @@ QQuickMaterialProgressBarNode::QQuickMaterialProgressBarNode(QQuickMaterialProgr
: QQuickAnimatedNode(item)
{
setLoopCount(Infinite);
- setDuration(TotalDuration);
+ setDuration(QmpbTotalDuration);
}
void QQuickMaterialProgressBarNode::updateCurrentTime(int time)
diff --git a/src/quickcontrols/material/impl/qquickmaterialprogressbar_p.h b/src/quickcontrols/material/impl/qquickmaterialprogressbar_p.h
index d250c2f76d..46d5c1b20f 100644
--- a/src/quickcontrols/material/impl/qquickmaterialprogressbar_p.h
+++ b/src/quickcontrols/material/impl/qquickmaterialprogressbar_p.h
@@ -54,6 +54,4 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMaterialProgressBar)
-
#endif // QQUICKMATERIALPROGRESSBAR_P_H
diff --git a/src/quickcontrols/material/impl/qquickmaterialripple.cpp b/src/quickcontrols/material/impl/qquickmaterialripple.cpp
index 89648182d4..2472b940a3 100644
--- a/src/quickcontrols/material/impl/qquickmaterialripple.cpp
+++ b/src/quickcontrols/material/impl/qquickmaterialripple.cpp
@@ -12,9 +12,7 @@
QT_BEGIN_NAMESPACE
-namespace {
- enum WavePhase { WaveEnter, WaveExit };
-}
+enum WavePhase { WaveEnter, WaveExit };
static const int RIPPLE_ENTER_DELAY = 80;
static const int OPACITY_ENTER_DURATION_FAST = 120;
@@ -90,6 +88,10 @@ void QQuickMaterialRippleWaveNode::updateCurrentTime(int time)
Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
rectNode->setRect(QRectF(0, 0, m_value, m_value));
rectNode->setRadius(m_value / 2);
+ rectNode->setTopLeftRadius(-1);
+ rectNode->setTopRightRadius(-1);
+ rectNode->setBottomLeftRadius(-1);
+ rectNode->setBottomRightRadius(-1);
rectNode->update();
}
@@ -176,6 +178,10 @@ void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item)
rectNode->setRect(QRectF(0, 0, w, h));
rectNode->setRadius(ripple->clipRadius());
}
+ rectNode->setTopLeftRadius(-1);
+ rectNode->setTopRightRadius(-1);
+ rectNode->setBottomLeftRadius(-1);
+ rectNode->setBottomRightRadius(-1);
setMatrix(matrix);
rectNode->setColor(ripple->color());
diff --git a/src/quickcontrols/material/impl/qquickmaterialripple_p.h b/src/quickcontrols/material/impl/qquickmaterialripple_p.h
index cdaaf13b1a..d0772052bd 100644
--- a/src/quickcontrols/material/impl/qquickmaterialripple_p.h
+++ b/src/quickcontrols/material/impl/qquickmaterialripple_p.h
@@ -83,6 +83,4 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickMaterialRipple)
-
#endif // QQUICKMATERIALRIPPLE_P_H
diff --git a/src/quickcontrols/material/impl/qquickmaterialtextcontainer.cpp b/src/quickcontrols/material/impl/qquickmaterialtextcontainer.cpp
new file mode 100644
index 0000000000..ab07c9d9b2
--- /dev/null
+++ b/src/quickcontrols/material/impl/qquickmaterialtextcontainer.cpp
@@ -0,0 +1,422 @@
+// Copyright (C) 2023 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
+
+#include "qquickmaterialtextcontainer_p.h"
+
+#include <QtCore/qpropertyanimation.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpainterpath.h>
+#include <QtQml/qqmlinfo.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ This class exists because:
+
+ - Rectangle doesn't support individual radii for each corner (QTBUG-48774).
+ - We need to draw an interrupted (where the placeholder text is) line for outlined containers.
+ - We need to animate the focus line for filled containers, and we can't use "Behavior on"
+ syntax because we only want to animate activeFocus becoming true, not also false. To do this
+ requires imperative code, and we want to keep the QML declarative.
+
+ focusAnimationProgress has to be a property even though it's only used internally,
+ because we have to use QPropertyAnimation on it.
+
+ An advantage of doing the animation in C++ is that we avoid the memory
+ overhead of an animation instance even when we're not using it, and instead
+ create it on demand and delete it when it's done. I tried doing the animation
+ declaratively with states and transitions, but it was more difficult to implement
+ and would have been harder to maintain, as well as having more overhead.
+*/
+
+QQuickMaterialTextContainer::QQuickMaterialTextContainer(QQuickItem *parent)
+ : QQuickPaintedItem(parent)
+{
+}
+
+bool QQuickMaterialTextContainer::isFilled() const
+{
+ return m_filled;
+}
+
+void QQuickMaterialTextContainer::setFilled(bool filled)
+{
+ if (filled == m_filled)
+ return;
+
+ m_filled = filled;
+ update();
+}
+
+QColor QQuickMaterialTextContainer::fillColor() const
+{
+ return m_fillColor;
+}
+
+void QQuickMaterialTextContainer::setFillColor(const QColor &fillColor)
+{
+ if (fillColor == m_fillColor)
+ return;
+
+ m_fillColor = fillColor;
+ update();
+}
+
+QColor QQuickMaterialTextContainer::outlineColor() const
+{
+ return m_outlineColor;
+}
+
+void QQuickMaterialTextContainer::setOutlineColor(const QColor &outlineColor)
+{
+ if (outlineColor == m_outlineColor)
+ return;
+
+ m_outlineColor = outlineColor;
+ update();
+}
+
+QColor QQuickMaterialTextContainer::focusedOutlineColor() const
+{
+ return m_outlineColor;
+}
+
+void QQuickMaterialTextContainer::setFocusedOutlineColor(const QColor &focusedOutlineColor)
+{
+ if (focusedOutlineColor == m_focusedOutlineColor)
+ return;
+
+ m_focusedOutlineColor = focusedOutlineColor;
+ update();
+}
+
+qreal QQuickMaterialTextContainer::focusAnimationProgress() const
+{
+ return m_focusAnimationProgress;
+}
+
+void QQuickMaterialTextContainer::setFocusAnimationProgress(qreal progress)
+{
+ if (qFuzzyCompare(progress, m_focusAnimationProgress))
+ return;
+
+ m_focusAnimationProgress = progress;
+ update();
+}
+
+qreal QQuickMaterialTextContainer::placeholderTextWidth() const
+{
+ return m_placeholderTextWidth;
+}
+
+void QQuickMaterialTextContainer::setPlaceholderTextWidth(qreal placeholderTextWidth)
+{
+ if (qFuzzyCompare(placeholderTextWidth, m_placeholderTextWidth))
+ return;
+
+ m_placeholderTextWidth = placeholderTextWidth;
+ update();
+}
+
+QQuickMaterialTextContainer::PlaceHolderHAlignment QQuickMaterialTextContainer::placeholderTextHAlign() const
+{
+ return m_placeholderTextHAlign;
+}
+
+void QQuickMaterialTextContainer::setPlaceholderTextHAlign(PlaceHolderHAlignment placeholderTextHAlign)
+{
+ if (m_placeholderTextHAlign == placeholderTextHAlign)
+ return;
+
+ m_placeholderTextHAlign = placeholderTextHAlign;
+ update();
+}
+
+bool QQuickMaterialTextContainer::controlHasActiveFocus() const
+{
+ return m_controlHasActiveFocus;
+}
+
+void QQuickMaterialTextContainer::setControlHasActiveFocus(bool controlHasActiveFocus)
+{
+ if (m_controlHasActiveFocus == controlHasActiveFocus)
+ return;
+
+ m_controlHasActiveFocus = controlHasActiveFocus;
+ if (m_controlHasActiveFocus)
+ controlGotActiveFocus();
+ else
+ controlLostActiveFocus();
+ emit controlHasActiveFocusChanged();
+}
+
+bool QQuickMaterialTextContainer::controlHasText() const
+{
+ return m_controlHasText;
+}
+
+void QQuickMaterialTextContainer::setControlHasText(bool controlHasText)
+{
+ if (m_controlHasText == controlHasText)
+ return;
+
+ m_controlHasText = controlHasText;
+ // TextArea's text length is updated after component completion,
+ // so account for that here and in setPlaceholderHasText().
+ maybeSetFocusAnimationProgress();
+ update();
+ emit controlHasTextChanged();
+}
+
+bool QQuickMaterialTextContainer::placeholderHasText() const
+{
+ return m_placeholderHasText;
+}
+
+void QQuickMaterialTextContainer::setPlaceholderHasText(bool placeholderHasText)
+{
+ if (m_placeholderHasText == placeholderHasText)
+ return;
+
+ m_placeholderHasText = placeholderHasText;
+ maybeSetFocusAnimationProgress();
+ update();
+ emit placeholderHasTextChanged();
+}
+
+int QQuickMaterialTextContainer::horizontalPadding() const
+{
+ return m_horizontalPadding;
+}
+
+/*!
+ \internal
+
+ The text field's horizontal padding.
+
+ We need this to be a property so that the QML can set it, since we can't
+ access QQuickMaterialStyle's C++ API from this plugin.
+*/
+void QQuickMaterialTextContainer::setHorizontalPadding(int horizontalPadding)
+{
+ if (m_horizontalPadding == horizontalPadding)
+ return;
+ m_horizontalPadding = horizontalPadding;
+ update();
+ emit horizontalPaddingChanged();
+}
+
+void QQuickMaterialTextContainer::paint(QPainter *painter)
+{
+ qreal w = width();
+ qreal h = height();
+ if (w <= 0 || h <= 0)
+ return;
+
+ // Account for pen width.
+ const qreal penWidth = m_filled ? 1 : (m_controlHasActiveFocus ? 2 : 1);
+ w -= penWidth;
+ h -= penWidth;
+
+ const qreal cornerRadius = 4;
+ // This is coincidentally the same as cornerRadius, but use different variable names
+ // to keep the code understandable.
+ const qreal gapPadding = 4;
+ // When animating focus on outlined containers, we need to make a gap
+ // at the top left for the placeholder text.
+ // If the text is too wide for the container, it will be elided, so
+ // we shouldn't need to clamp its width here. TODO: check that this is the case for TextArea.
+ const qreal halfPlaceholderWidth = m_placeholderTextWidth / 2;
+ // Take care of different Alignment cases for the placeholder text.
+ qreal gapCenterX;
+ switch (m_placeholderTextHAlign) {
+ case PlaceHolderHAlignment::AlignHCenter:
+ gapCenterX = width() / 2;
+ break;
+ case PlaceHolderHAlignment::AlignRight:
+ gapCenterX = width() - halfPlaceholderWidth - m_horizontalPadding;
+ break;
+ default:
+ gapCenterX = m_horizontalPadding + halfPlaceholderWidth;
+ break;
+ }
+
+ QPainterPath path;
+
+ QPointF startPos;
+
+ // Top-left rounded corner.
+ if (m_filled || m_focusAnimationProgress == 0) {
+ startPos = QPointF(cornerRadius, 0);
+ } else {
+ // Start at the center of the gap and animate outwards towards the left-hand side.
+ // Subtract gapPadding to account for the gap between the line and the placeholder text.
+ // Also subtract the pen width because otherwise it extends by that distance too much to the right.
+ // Changing the cap style to Qt::FlatCap would only fix this by half the pen width,
+ // but it has no effect anyway (perhaps it literally only affects end points and not "start" points?).
+ startPos = QPointF(gapCenterX - (m_focusAnimationProgress * halfPlaceholderWidth) - gapPadding - penWidth, 0);
+ }
+ path.moveTo(startPos);
+ path.arcTo(0, 0, cornerRadius * 2, cornerRadius * 2, 90, 90);
+
+ // Bottom-left corner.
+ if (m_filled) {
+ path.lineTo(0, h);
+ } else {
+ path.lineTo(0, h - cornerRadius * 2);
+ path.arcTo(0, h - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 180, 90);
+ }
+
+ // Bottom-right corner.
+ if (m_filled) {
+ path.lineTo(w, h);
+ } else {
+ path.lineTo(w - cornerRadius * 2, h);
+ path.arcTo(w - cornerRadius * 2, h - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 270, 90);
+ }
+
+ // Top-right rounded corner.
+ path.lineTo(w, cornerRadius);
+ path.arcTo(w - (cornerRadius * 2), 0, cornerRadius * 2, cornerRadius * 2, 0, 90);
+
+ if (m_filled || qFuzzyIsNull(m_focusAnimationProgress)) {
+ // Back to the start.
+ path.lineTo(startPos.x(), startPos.y());
+ } else {
+ path.lineTo(gapCenterX + (m_focusAnimationProgress * halfPlaceholderWidth) + gapPadding, startPos.y());
+ }
+
+ // Account for pen width.
+ painter->translate(penWidth / 2, penWidth / 2);
+
+ painter->setRenderHint(QPainter::Antialiasing, true);
+
+ auto control = textControl();
+ const bool focused = control && control->hasActiveFocus();
+ // We still want to draw the stroke when it's filled, otherwise it will be a pixel
+ // (the pen width) too narrow on either side.
+ QPen pen;
+ pen.setColor(m_filled ? m_fillColor : (focused ? m_focusedOutlineColor : m_outlineColor));
+ pen.setWidthF(penWidth);
+ painter->setPen(pen);
+ if (m_filled)
+ painter->setBrush(QBrush(m_fillColor));
+
+ // Fill or stroke the container's shape.
+ // If not filling, the default brush will be used, which is Qt::NoBrush.
+ painter->drawPath(path);
+
+ // Draw the focus line at the bottom for filled containers.
+ if (m_filled) {
+ if (!qFuzzyCompare(m_focusAnimationProgress, 1.0)) {
+ // Draw the enabled active indicator line (#10) that's at the bottom when it's not focused:
+ // https://m3.material.io/components/text-fields/specs#6d654d1d-262e-4697-858c-9a75e8e7c81d
+ // Don't bother drawing it when the animation has finished, as the focused active indicator
+ // line below will obscure it.
+ pen.setColor(m_outlineColor);
+ painter->setPen(pen);
+ painter->drawLine(0, h, w, h);
+ }
+
+ if (!qFuzzyIsNull(m_focusAnimationProgress)) {
+ // Draw the focused active indicator line (#6) that's at the bottom when it's focused.
+ // Start at the center and expand outwards.
+ const int lineLength = m_focusAnimationProgress * w;
+ const int horizontalCenter = w / 2;
+ pen.setColor(m_focusedOutlineColor);
+ pen.setWidth(2);
+ painter->setPen(pen);
+ painter->drawLine(horizontalCenter - (lineLength / 2), h,
+ horizontalCenter + (lineLength / 2) + pen.width() / 2, h);
+ }
+ }
+}
+
+bool QQuickMaterialTextContainer::shouldAnimateOutline() const
+{
+ return !m_controlHasText && m_placeholderHasText;
+}
+
+/*!
+ \internal
+
+ \sa QQuickPlaceholderText::textControl().
+*/
+QQuickItem *QQuickMaterialTextContainer::textControl() const
+{
+ return qobject_cast<QQuickItem *>(parent());
+}
+
+void QQuickMaterialTextContainer::controlGotActiveFocus()
+{
+ const bool shouldAnimate = m_filled ? !m_controlHasText : shouldAnimateOutline();
+ if (!shouldAnimate) {
+ // It does have focus, but sometimes we don't need to animate anything, just change colors.
+ if (m_filled && m_controlHasText) {
+ // When a filled container has text already entered, we should just immediately change
+ // the color and thickness of the indicator line.
+ m_focusAnimationProgress = 1;
+ }
+ update();
+ return;
+ }
+
+ startFocusAnimation();
+}
+
+void QQuickMaterialTextContainer::controlLostActiveFocus()
+{
+ // We don't want to animate the active indicator line (at the bottom) of filled containers
+ // when the control loses focus, only when it gets it.
+ if (m_filled || !shouldAnimateOutline()) {
+ // Ensure that we set this so that filled containers go back to a non-accent-colored
+ // active indicator line when losing focus.
+ if (m_filled)
+ m_focusAnimationProgress = 0;
+ update();
+ return;
+ }
+
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "focusAnimationProgress", this);
+ animation->setDuration(300);
+ animation->setStartValue(1);
+ animation->setEndValue(0);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void QQuickMaterialTextContainer::startFocusAnimation()
+{
+ // Each time setFocusAnimationProgress is called by the animation, it'll call update(),
+ // which will cause us to be re-rendered.
+ QPropertyAnimation *animation = new QPropertyAnimation(this, "focusAnimationProgress", this);
+ animation->setDuration(300);
+ animation->setStartValue(0);
+ animation->setEndValue(1);
+ animation->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+void QQuickMaterialTextContainer::maybeSetFocusAnimationProgress()
+{
+ if (m_filled)
+ return;
+
+ if (m_controlHasText && m_placeholderHasText) {
+ // Show the interrupted outline when there is text.
+ setFocusAnimationProgress(1);
+ } else if (!m_controlHasText && !m_controlHasActiveFocus) {
+ // If the text was cleared while it didn't have focus, don't animate, just close the gap.
+ setFocusAnimationProgress(0);
+ }
+}
+
+void QQuickMaterialTextContainer::componentComplete()
+{
+ QQuickPaintedItem::componentComplete();
+
+ if (!parentItem())
+ qmlWarning(this) << "Expected parent item by component completion!";
+
+ maybeSetFocusAnimationProgress();
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols/material/impl/qquickmaterialtextcontainer_p.h b/src/quickcontrols/material/impl/qquickmaterialtextcontainer_p.h
new file mode 100644
index 0000000000..648e83521f
--- /dev/null
+++ b/src/quickcontrols/material/impl/qquickmaterialtextcontainer_p.h
@@ -0,0 +1,122 @@
+// Copyright (C) 2023 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
+
+#ifndef QQUICKMATERIALTEXTCONTAINER_P_H
+#define QQUICKMATERIALTEXTCONTAINER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/private/qglobal_p.h>
+#include <QtGui/qcolor.h>
+#include <QtQuick/qquickpainteditem.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickMaterialTextContainer : public QQuickPaintedItem
+{
+ Q_OBJECT
+ Q_PROPERTY(bool filled READ isFilled WRITE setFilled FINAL)
+ Q_PROPERTY(bool controlHasActiveFocus READ controlHasActiveFocus
+ WRITE setControlHasActiveFocus NOTIFY controlHasActiveFocusChanged FINAL)
+ Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor FINAL)
+ Q_PROPERTY(QColor outlineColor READ outlineColor WRITE setOutlineColor FINAL)
+ Q_PROPERTY(QColor focusedOutlineColor READ focusedOutlineColor WRITE setFocusedOutlineColor FINAL)
+ Q_PROPERTY(qreal focusAnimationProgress READ focusAnimationProgress WRITE setFocusAnimationProgress FINAL)
+ Q_PROPERTY(qreal placeholderTextWidth READ placeholderTextWidth WRITE setPlaceholderTextWidth FINAL)
+ Q_PROPERTY(PlaceHolderHAlignment placeholderTextHAlign READ placeholderTextHAlign WRITE setPlaceholderTextHAlign FINAL)
+ Q_PROPERTY(bool controlHasText READ controlHasText WRITE setControlHasText NOTIFY controlHasTextChanged FINAL)
+ Q_PROPERTY(bool placeholderHasText READ placeholderHasText WRITE setPlaceholderHasText NOTIFY placeholderHasTextChanged FINAL)
+ Q_PROPERTY(int horizontalPadding READ horizontalPadding WRITE setHorizontalPadding NOTIFY horizontalPaddingChanged FINAL)
+ QML_NAMED_ELEMENT(MaterialTextContainer)
+ QML_ADDED_IN_VERSION(6, 5)
+
+public:
+ explicit QQuickMaterialTextContainer(QQuickItem *parent = nullptr);
+
+ enum PlaceHolderHAlignment {
+ AlignLeft = Qt::AlignLeft,
+ AlignRight = Qt::AlignRight,
+ AlignHCenter = Qt::AlignHCenter,
+ AlignJustify = Qt::AlignJustify
+ };
+ Q_ENUM(PlaceHolderHAlignment)
+
+ bool isFilled() const;
+ void setFilled(bool filled);
+
+ QColor fillColor() const;
+ void setFillColor(const QColor &fillColor);
+
+ QColor outlineColor() const;
+ void setOutlineColor(const QColor &outlineColor);
+
+ QColor focusedOutlineColor() const;
+ void setFocusedOutlineColor(const QColor &focusedOutlineColor);
+
+ qreal focusAnimationProgress() const;
+ void setFocusAnimationProgress(qreal progress);
+
+ qreal placeholderTextWidth() const;
+ void setPlaceholderTextWidth(qreal placeholderTextWidth);
+
+ bool controlHasActiveFocus() const;
+ void setControlHasActiveFocus(bool controlHasActiveFocus);
+
+ bool controlHasText() const;
+ void setControlHasText(bool controlHasText);
+
+ bool placeholderHasText() const;
+ void setPlaceholderHasText(bool placeholderHasText);
+
+ int horizontalPadding() const;
+ void setHorizontalPadding(int horizontalPadding);
+
+ void paint(QPainter *painter) override;
+
+ PlaceHolderHAlignment placeholderTextHAlign() const;
+ void setPlaceholderTextHAlign(PlaceHolderHAlignment placeHolderTextHAlign);
+
+signals:
+ void animateChanged();
+ void controlHasActiveFocusChanged();
+ void controlHasTextChanged();
+ void placeholderHasTextChanged();
+ void horizontalPaddingChanged();
+
+private:
+ bool shouldAnimateOutline() const;
+
+ QQuickItem *textControl() const;
+ void controlGotActiveFocus();
+ void controlLostActiveFocus();
+ void startFocusAnimation();
+
+ void maybeSetFocusAnimationProgress();
+
+ void componentComplete() override;
+
+ QColor m_fillColor;
+ QColor m_outlineColor;
+ QColor m_focusedOutlineColor;
+ qreal m_focusAnimationProgress = 0;
+ qreal m_placeholderTextWidth = 0;
+ bool m_filled = false;
+ bool m_controlHasActiveFocus = false;
+ bool m_controlHasText = false;
+ bool m_placeholderHasText = false;
+ int m_horizontalPadding = 0;
+ PlaceHolderHAlignment m_placeholderTextHAlign;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKMATERIALTEXTCONTAINER_P_H
diff --git a/src/quickcontrols/material/qquickmaterialstyle.cpp b/src/quickcontrols/material/qquickmaterialstyle.cpp
index d7eb72f830..f8ced5821b 100644
--- a/src/quickcontrols/material/qquickmaterialstyle.cpp
+++ b/src/quickcontrols/material/qquickmaterialstyle.cpp
@@ -4,7 +4,9 @@
#include "qquickmaterialstyle_p.h"
#include <QtCore/qdebug.h>
+#if QT_CONFIG(settings)
#include <QtCore/qsettings.h>
+#endif
#include <QtQml/qqmlinfo.h>
#include <QtQuickControls2/private/qquickstyle_p.h>
@@ -422,6 +424,8 @@ static const QRgb switchDisabledCheckedTrackColorLight = 0x1E1C1B1F;
static const QRgb switchDisabledCheckedTrackColorDark = 0x1EE6E1E5;
static const QRgb switchDisabledUncheckedIconColorLight = 0x611C1B1F;
static const QRgb switchDisabledUncheckedIconColorDark = 0x61E6E1E5;
+static const QRgb textFieldFilledContainerColorLight = 0xFFE7E0EC;
+static const QRgb textFieldFilledContainerColorDark = 0xFF49454F;
static QQuickMaterialStyle::Theme effectiveTheme(QQuickMaterialStyle::Theme theme)
{
@@ -941,10 +945,7 @@ QColor QQuickMaterialStyle::iconDisabledColor() 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) {
+ if (!enabled && !flat) {
return QColor::fromRgba(m_theme == Light
? raisedButtonDisabledColorLight : raisedButtonDisabledColorDark);
}
@@ -970,7 +971,11 @@ QColor QQuickMaterialStyle::buttonColor(Theme theme, const QVariant &background,
// A highlighted + checked button should become darker.
color = accentColor(checked ? Shade100 : shade);
}
- } else {
+ // Flat, highlighted buttons need to have a semi-transparent background,
+ // otherwise the text won't be visible.
+ if (flat)
+ color.setAlphaF(0.25);
+ } else if (!flat) {
// 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);
@@ -1158,6 +1163,11 @@ QColor QQuickMaterialStyle::sliderDisabledColor() const
return QColor::fromRgba(m_theme == Light ? sliderDisabledColorLight : sliderDisabledColorDark);
}
+QColor QQuickMaterialStyle::textFieldFilledContainerColor() const
+{
+ return QColor::fromRgba(m_theme == Light ? textFieldFilledContainerColorLight : textFieldFilledContainerColorDark);
+}
+
QColor QQuickMaterialStyle::color(QQuickMaterialStyle::Color color, QQuickMaterialStyle::Shade shade) const
{
int count = sizeof(colors) / sizeof(colors[0]);
@@ -1259,6 +1269,32 @@ int QQuickMaterialStyle::touchTarget() const
return globalVariant == Dense ? 44 : 48;
}
+int QQuickMaterialStyle::buttonVerticalPadding() const
+{
+ return globalVariant == Dense ? 10 : 14;
+}
+
+// https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382
+int QQuickMaterialStyle::buttonLeftPadding(bool flat, bool hasIcon) const
+{
+ static const int noIconPadding = globalVariant == Dense ? 12 : 24;
+ static const int iconPadding = globalVariant == Dense ? 8 : 16;
+ static const int flatPadding = globalVariant == Dense ? 6 : 12;
+ return !flat ? (!hasIcon ? noIconPadding : iconPadding) : flatPadding;
+}
+
+int QQuickMaterialStyle::buttonRightPadding(bool flat, bool hasIcon, bool hasText) const
+{
+ static const int noTextPadding = globalVariant == Dense ? 8 : 16;
+ static const int textPadding = globalVariant == Dense ? 12 : 24;
+ static const int flatNoIconPadding = globalVariant == Dense ? 6 : 12;
+ static const int flatNoTextPadding = globalVariant == Dense ? 6 : 12;
+ static const int flatTextPadding = globalVariant == Dense ? 8 : 16;
+ return !flat
+ ? (!hasText ? noTextPadding : textPadding)
+ : (!hasIcon ? flatNoIconPadding : (!hasText ? flatNoTextPadding : flatTextPadding));
+}
+
int QQuickMaterialStyle::buttonHeight() const
{
// https://m3.material.io/components/buttons/specs#256326ad-f934-40e7-b05f-0bcb41aa4382
@@ -1276,6 +1312,19 @@ int QQuickMaterialStyle::dialogButtonBoxHeight() const
return globalVariant == Dense ? 48 : 52;
}
+int QQuickMaterialStyle::dialogTitleFontPixelSize() const
+{
+ return globalVariant == Dense ? 16 : 24;
+}
+
+// https://m3.material.io/components/dialogs/specs#6771d107-624e-47cc-b6d8-2b7b620ba2f1
+QQuickMaterialStyle::RoundedScale QQuickMaterialStyle::dialogRoundedScale() const
+{
+ return globalVariant == Dense
+ ? QQuickMaterialStyle::RoundedScale::LargeScale
+ : QQuickMaterialStyle::RoundedScale::ExtraLargeScale;
+}
+
int QQuickMaterialStyle::frameVerticalPadding() const
{
return globalVariant == Dense ? 8 : 12;
@@ -1292,6 +1341,31 @@ int QQuickMaterialStyle::menuItemVerticalPadding() const
return globalVariant == Dense ? 8 : 12;
}
+int QQuickMaterialStyle::switchIndicatorWidth() const
+{
+ return globalVariant == Dense ? 40 : 52;
+}
+
+int QQuickMaterialStyle::switchIndicatorHeight() const
+{
+ return globalVariant == Dense ? 22 : 32;
+}
+
+int QQuickMaterialStyle::switchNormalHandleHeight() const
+{
+ return globalVariant == Dense ? 10 : 16;
+}
+
+int QQuickMaterialStyle::switchCheckedHandleHeight() const
+{
+ return globalVariant == Dense ? 16 : 24;
+}
+
+int QQuickMaterialStyle::switchLargestHandleHeight() const
+{
+ return globalVariant == Dense ? 18 : 28;
+}
+
int QQuickMaterialStyle::switchDelegateVerticalPadding() const
{
// SwitchDelegate's indicator is much larger than the others due to the shadow,
@@ -1299,6 +1373,21 @@ int QQuickMaterialStyle::switchDelegateVerticalPadding() const
return globalVariant == Dense ? 4 : 8;
}
+int QQuickMaterialStyle::textFieldHeight() const
+{
+ // filled: https://m3.material.io/components/text-fields/specs#8c032848-e442-46df-b25d-28f1315f234b
+ // outlined: https://m3.material.io/components/text-fields/specs#605e24f1-1c1f-4c00-b385-4bf50733a5ef
+ return globalVariant == Dense ? 44 : 56;
+}
+int QQuickMaterialStyle::textFieldHorizontalPadding() const
+{
+ return globalVariant == Dense ? 12 : 16;
+}
+int QQuickMaterialStyle::textFieldVerticalPadding() const
+{
+ return globalVariant == Dense ? 4 : 8;
+}
+
int QQuickMaterialStyle::tooltipHeight() const
{
// https://material.io/guidelines/components/tooltips.html
diff --git a/src/quickcontrols/material/qquickmaterialstyle_p.h b/src/quickcontrols/material/qquickmaterialstyle_p.h
index ab3483f04d..f7c2b256ba 100644
--- a/src/quickcontrols/material/qquickmaterialstyle_p.h
+++ b/src/quickcontrols/material/qquickmaterialstyle_p.h
@@ -18,10 +18,11 @@
#include <QtGui/qcolor.h>
#include <QtQml/qqml.h>
#include <QtQuickControls2/qquickattachedpropertypropagator.h>
+#include <QtQuickControls2Material/qtquickcontrols2materialexports.h>
QT_BEGIN_NAMESPACE
-class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator
+class Q_QUICKCONTROLS2MATERIAL_EXPORT QQuickMaterialStyle : public QQuickAttachedPropertyPropagator
{
Q_OBJECT
Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL)
@@ -73,15 +74,27 @@ class QQuickMaterialStyle : public QQuickAttachedPropertyPropagator
Q_PROPERTY(QColor toolTextColor READ toolTextColor NOTIFY toolTextColorChanged FINAL)
Q_PROPERTY(QColor spinBoxDisabledIconColor READ spinBoxDisabledIconColor NOTIFY themeChanged FINAL)
Q_PROPERTY(QColor sliderDisabledColor READ sliderDisabledColor NOTIFY themeChanged FINAL REVISION(2, 15))
+ Q_PROPERTY(QColor textFieldFilledContainerColor READ textFieldFilledContainerColor NOTIFY themeChanged FINAL)
Q_PROPERTY(int touchTarget READ touchTarget CONSTANT FINAL)
+ Q_PROPERTY(int buttonVerticalPadding READ buttonVerticalPadding CONSTANT FINAL)
Q_PROPERTY(int buttonHeight READ buttonHeight CONSTANT FINAL)
Q_PROPERTY(int delegateHeight READ delegateHeight CONSTANT FINAL)
Q_PROPERTY(int dialogButtonBoxHeight READ dialogButtonBoxHeight CONSTANT FINAL)
+ Q_PROPERTY(int dialogTitleFontPixelSize READ dialogTitleFontPixelSize CONSTANT FINAL)
+ Q_PROPERTY(RoundedScale dialogRoundedScale READ dialogRoundedScale CONSTANT FINAL)
Q_PROPERTY(int frameVerticalPadding READ frameVerticalPadding CONSTANT FINAL)
Q_PROPERTY(int menuItemHeight READ menuItemHeight CONSTANT FINAL)
Q_PROPERTY(int menuItemVerticalPadding READ menuItemVerticalPadding CONSTANT FINAL)
+ Q_PROPERTY(int switchIndicatorWidth READ switchIndicatorWidth CONSTANT FINAL)
+ Q_PROPERTY(int switchIndicatorHeight READ switchIndicatorHeight CONSTANT FINAL)
+ Q_PROPERTY(int switchNormalHandleHeight READ switchNormalHandleHeight CONSTANT FINAL)
+ Q_PROPERTY(int switchCheckedHandleHeight READ switchCheckedHandleHeight CONSTANT FINAL)
+ Q_PROPERTY(int switchLargestHandleHeight READ switchLargestHandleHeight CONSTANT FINAL)
Q_PROPERTY(int switchDelegateVerticalPadding READ switchDelegateVerticalPadding CONSTANT FINAL)
+ Q_PROPERTY(int textFieldHeight READ textFieldHeight CONSTANT FINAL)
+ Q_PROPERTY(int textFieldHorizontalPadding READ textFieldHorizontalPadding CONSTANT FINAL)
+ Q_PROPERTY(int textFieldVerticalPadding READ textFieldVerticalPadding CONSTANT FINAL)
Q_PROPERTY(int tooltipHeight READ tooltipHeight CONSTANT FINAL)
QML_NAMED_ELEMENT(Material)
@@ -254,18 +267,32 @@ public:
QColor toolTextColor() const;
QColor spinBoxDisabledIconColor() const;
QColor sliderDisabledColor() const;
+ QColor textFieldFilledContainerColor() const;
Q_INVOKABLE QColor color(Color color, Shade shade = Shade500) const;
Q_INVOKABLE QColor shade(const QColor &color, Shade shade) const;
int touchTarget() const;
+ int buttonVerticalPadding() const;
+ Q_INVOKABLE int buttonLeftPadding(bool flat, bool hasIcon) const;
+ Q_INVOKABLE int buttonRightPadding(bool flat, bool hasIcon, bool hasText) const;
int buttonHeight() const;
int delegateHeight() const;
int dialogButtonBoxHeight() const;
+ int dialogTitleFontPixelSize() const;
+ RoundedScale dialogRoundedScale() const;
int frameVerticalPadding() const;
int menuItemHeight() const;
int menuItemVerticalPadding() const;
+ int switchIndicatorWidth() const;
+ int switchIndicatorHeight() const;
+ int switchNormalHandleHeight() const;
+ int switchCheckedHandleHeight() const;
+ int switchLargestHandleHeight() const;
int switchDelegateVerticalPadding() const;
+ int textFieldHeight() const;
+ int textFieldHorizontalPadding() const;
+ int textFieldVerticalPadding() const;
int tooltipHeight() const;
static void initGlobals();
diff --git a/src/quickcontrols/material/qquickmaterialtheme.cpp b/src/quickcontrols/material/qquickmaterialtheme.cpp
index 629c389be5..d121a1a47e 100644
--- a/src/quickcontrols/material/qquickmaterialtheme.cpp
+++ b/src/quickcontrols/material/qquickmaterialtheme.cpp
@@ -6,7 +6,7 @@
#include <QtGui/qpa/qplatformdialoghelper.h>
#include <QtGui/qfont.h>
-#include <QtGui/qfontinfo.h>
+#include <QtGui/qfontdatabase.h>
#include <QtQuickTemplates2/private/qquicktheme_p.h>
QT_BEGIN_NAMESPACE
@@ -21,17 +21,15 @@ void QQuickMaterialTheme::initialize(QQuickTheme *theme)
QFont menuItemFont;
QFont editorFont;
- QFont font;
- font.setFamilies(QStringList{QLatin1String("Roboto")});
- QString family = QFontInfo(font).family();
-
- if (family != QLatin1String("Roboto")) {
- font.setFamilies(QStringList{QLatin1String("Noto")});
- family = QFontInfo(font).family();
+ auto defaultFontFamily = QLatin1String("Roboto");
+ if (!QFontDatabase::hasFamily(defaultFontFamily)) {
+ defaultFontFamily = QLatin1String("Noto"); // fallback
+ if (!QFontDatabase::hasFamily(defaultFontFamily))
+ defaultFontFamily = {};
}
- if (family == QLatin1String("Roboto") || family == QLatin1String("Noto")) {
- const QStringList families{family};
+ if (!defaultFontFamily.isEmpty()) {
+ const QStringList families{defaultFontFamily};
systemFont.setFamilies(families);
buttonFont.setFamilies(families);
toolTipFont.setFamilies(families);
@@ -47,7 +45,6 @@ void QQuickMaterialTheme::initialize(QQuickTheme *theme)
// https://material.io/guidelines/components/buttons.html#buttons-style
buttonFont.setPixelSize(dense ? 13 : 14);
- buttonFont.setCapitalization(QFont::AllUppercase);
buttonFont.setWeight(QFont::Medium);
theme->setFont(QQuickTheme::Button, buttonFont);
theme->setFont(QQuickTheme::TabBar, buttonFont);
diff --git a/src/quickcontrols/material/qquickmaterialtheme_p.h b/src/quickcontrols/material/qquickmaterialtheme_p.h
index 893f441c86..bdaecd1a87 100644
--- a/src/quickcontrols/material/qquickmaterialtheme_p.h
+++ b/src/quickcontrols/material/qquickmaterialtheme_p.h
@@ -15,13 +15,13 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
+#include <QtQuickControls2Material/qtquickcontrols2materialexports.h>
QT_BEGIN_NAMESPACE
class QQuickTheme;
-class QQuickMaterialTheme
+class Q_QUICKCONTROLS2MATERIAL_EXPORT QQuickMaterialTheme
{
public:
static void initialize(QQuickTheme *theme);
diff --git a/src/quickcontrols/material/qtquickcontrols2materialstyleplugin.cpp b/src/quickcontrols/material/qtquickcontrols2materialstyleplugin.cpp
index 10aa64b8cf..4911a3e0f2 100644
--- a/src/quickcontrols/material/qtquickcontrols2materialstyleplugin.cpp
+++ b/src/quickcontrols/material/qtquickcontrols2materialstyleplugin.cpp
@@ -5,8 +5,6 @@
#include "qquickmaterialtheme_p.h"
#include <QtQuickControls2/private/qquickstyleplugin_p.h>
-#include <QtQuickControls2Impl/private/qquickpaddedrectangle_p.h>
-#include <QtQuickTemplates2/private/qquicktheme_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quickcontrols/material/shaders/+glslcore/RectangularGlow.frag b/src/quickcontrols/material/shaders/+glslcore/RectangularGlow.frag
deleted file mode 100644
index 432d86b5d5..0000000000
--- a/src/quickcontrols/material/shaders/+glslcore/RectangularGlow.frag
+++ /dev/null
@@ -1,25 +0,0 @@
-#version 150
-
-uniform float qt_Opacity;
-uniform float relativeSizeX;
-uniform float relativeSizeY;
-uniform float spread;
-uniform vec4 color;
-
-in vec2 qt_TexCoord0;
-out vec4 fragColor;
-
-float linearstep(float e0, float e1, float x)
-{
- return clamp((x - e0) / (e1 - e0), 0.0, 1.0);
-}
-
-void main()
-{
- float alpha =
- smoothstep(0.0, relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
- smoothstep(0.0, relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
-
- float spreadMultiplier = linearstep(spread, 1.0 - spread, alpha);
- fragColor = color * qt_Opacity * spreadMultiplier * spreadMultiplier;
-}
diff --git a/src/quickcontrols/material/shaders/+hlsl/RectangularGlow.frag b/src/quickcontrols/material/shaders/+hlsl/RectangularGlow.frag
deleted file mode 100644
index 69d9f852fb..0000000000
--- a/src/quickcontrols/material/shaders/+hlsl/RectangularGlow.frag
+++ /dev/null
@@ -1,21 +0,0 @@
-cbuffer ConstantBuffer : register(b0)
-{
- float4x4 qt_Matrix;
- float qt_Opacity;
- float relativeSizeX;
- float relativeSizeY;
- float spread;
- float4 color;
-}
-
-float linearstep(float e0, float e1, float x) { return clamp((x - e0) / (e1 - e0), 0.0, 1.0); }
-
-float4 main(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET
-{
- float alpha =
- smoothstep(0.0, relativeSizeX, 0.5 - abs(0.5 - coord.x)) *
- smoothstep(0.0, relativeSizeY, 0.5 - abs(0.5 - coord.y));
-
- float spreadMultiplier = linearstep(spread, 1.0 - spread, alpha);
- return color * qt_Opacity * spreadMultiplier * spreadMultiplier;
-}
diff --git a/src/quickcontrols/material/shaders/+qsb/RectangularGlow.frag b/src/quickcontrols/material/shaders/+qsb/RectangularGlow.frag
deleted file mode 100644
index 5cfa2db6ed..0000000000
--- a/src/quickcontrols/material/shaders/+qsb/RectangularGlow.frag
+++ /dev/null
Binary files differ
diff --git a/src/quickcontrols/material/shaders/RectangularGlow.frag b/src/quickcontrols/material/shaders/RectangularGlow.frag
index 40bab5806c..50188d4516 100644
--- a/src/quickcontrols/material/shaders/RectangularGlow.frag
+++ b/src/quickcontrols/material/shaders/RectangularGlow.frag
@@ -1,19 +1,31 @@
-uniform highp float qt_Opacity;
-uniform mediump float relativeSizeX;
-uniform mediump float relativeSizeY;
-uniform mediump float spread;
-uniform lowp vec4 color;
-varying highp vec2 qt_TexCoord0;
+// Copyright (C) 2023 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
-highp float linearstep(highp float e0, highp float e1, highp float x) {
+#version 440
+
+layout(location = 0) in vec2 qt_TexCoord0;
+layout(location = 0) out vec4 fragColor;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 qt_Matrix;
+ float qt_Opacity;
+ float relativeSizeX;
+ float relativeSizeY;
+ float spread;
+ vec4 color;
+} ubuf;
+
+float linearstep(float e0, float e1, float x)
+{
return clamp((x - e0) / (e1 - e0), 0.0, 1.0);
}
-void main() {
- lowp float alpha =
- smoothstep(0.0, relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
- smoothstep(0.0, relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
+void main()
+{
+ float alpha =
+ smoothstep(0.0, ubuf.relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
+ smoothstep(0.0, ubuf.relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
- highp float spreadMultiplier = linearstep(spread, 1.0 - spread, alpha);
- gl_FragColor = color * qt_Opacity * spreadMultiplier * spreadMultiplier;
+ float spreadMultiplier = linearstep(ubuf.spread, 1.0 - ubuf.spread, alpha);
+ fragColor = ubuf.color * ubuf.qt_Opacity * spreadMultiplier * spreadMultiplier;
}
diff --git a/src/quickcontrols/material/shaders/RectangularGlow_rhi.frag b/src/quickcontrols/material/shaders/RectangularGlow_rhi.frag
deleted file mode 100644
index 3e7d2dfe6f..0000000000
--- a/src/quickcontrols/material/shaders/RectangularGlow_rhi.frag
+++ /dev/null
@@ -1,28 +0,0 @@
-#version 440
-
-layout(location = 0) in vec2 qt_TexCoord0;
-layout(location = 0) out vec4 fragColor;
-
-layout(std140, binding = 0) uniform buf {
- mat4 qt_Matrix;
- float qt_Opacity;
- float relativeSizeX;
- float relativeSizeY;
- float spread;
- vec4 color;
-} ubuf;
-
-float linearstep(float e0, float e1, float x)
-{
- return clamp((x - e0) / (e1 - e0), 0.0, 1.0);
-}
-
-void main()
-{
- float alpha =
- smoothstep(0.0, ubuf.relativeSizeX, 0.5 - abs(0.5 - qt_TexCoord0.x)) *
- smoothstep(0.0, ubuf.relativeSizeY, 0.5 - abs(0.5 - qt_TexCoord0.y));
-
- float spreadMultiplier = linearstep(ubuf.spread, 1.0 - ubuf.spread, alpha);
- fragColor = ubuf.color * ubuf.qt_Opacity * spreadMultiplier * spreadMultiplier;
-}
diff --git a/src/quickcontrols/material/shaders/compile.bat b/src/quickcontrols/material/shaders/compile.bat
deleted file mode 100644
index e0ccbb7ed5..0000000000
--- a/src/quickcontrols/material/shaders/compile.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-:: Copyright (C) 2019 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
-
-qsb --glsl "150,120,100 es" --hlsl 50 --msl 12 -o +qsb/RectangularGlow.frag RectangularGlow_rhi.frag