aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/universal
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols/universal')
-rw-r--r--src/quickcontrols/universal/ApplicationWindow.qml21
-rw-r--r--src/quickcontrols/universal/BusyIndicator.qml27
-rw-r--r--src/quickcontrols/universal/Button.qml56
-rw-r--r--src/quickcontrols/universal/CMakeLists.txt156
-rw-r--r--src/quickcontrols/universal/CheckBox.qml41
-rw-r--r--src/quickcontrols/universal/CheckDelegate.qml63
-rw-r--r--src/quickcontrols/universal/ComboBox.qml124
-rw-r--r--src/quickcontrols/universal/DelayButton.qml61
-rw-r--r--src/quickcontrols/universal/Dial.qml53
-rw-r--r--src/quickcontrols/universal/Dialog.qml57
-rw-r--r--src/quickcontrols/universal/DialogButtonBox.qml43
-rw-r--r--src/quickcontrols/universal/Drawer.qml45
-rw-r--r--src/quickcontrols/universal/Frame.qml22
-rw-r--r--src/quickcontrols/universal/GroupBox.qml42
-rw-r--r--src/quickcontrols/universal/HorizontalHeaderView.qml36
-rw-r--r--src/quickcontrols/universal/ItemDelegate.qml53
-rw-r--r--src/quickcontrols/universal/Label.qml14
-rw-r--r--src/quickcontrols/universal/Menu.qml49
-rw-r--r--src/quickcontrols/universal/MenuBar.qml30
-rw-r--r--src/quickcontrols/universal/MenuBarItem.qml57
-rw-r--r--src/quickcontrols/universal/MenuItem.qml81
-rw-r--r--src/quickcontrols/universal/MenuSeparator.qml29
-rw-r--r--src/quickcontrols/universal/Page.qml23
-rw-r--r--src/quickcontrols/universal/PageIndicator.qml38
-rw-r--r--src/quickcontrols/universal/Pane.qml21
-rw-r--r--src/quickcontrols/universal/Popup.qml31
-rw-r--r--src/quickcontrols/universal/ProgressBar.qml35
-rw-r--r--src/quickcontrols/universal/README.md9
-rw-r--r--src/quickcontrols/universal/RadioButton.qml41
-rw-r--r--src/quickcontrols/universal/RadioDelegate.qml63
-rw-r--r--src/quickcontrols/universal/RangeSlider.qml76
-rw-r--r--src/quickcontrols/universal/RoundButton.qml57
-rw-r--r--src/quickcontrols/universal/ScrollBar.qml61
-rw-r--r--src/quickcontrols/universal/ScrollIndicator.qml45
-rw-r--r--src/quickcontrols/universal/ScrollView.qml31
-rw-r--r--src/quickcontrols/universal/SelectionRectangle.qml37
-rw-r--r--src/quickcontrols/universal/Slider.qml63
-rw-r--r--src/quickcontrols/universal/SpinBox.qml114
-rw-r--r--src/quickcontrols/universal/SplitView.qml22
-rw-r--r--src/quickcontrols/universal/StackView.qml43
-rw-r--r--src/quickcontrols/universal/SwipeDelegate.qml59
-rw-r--r--src/quickcontrols/universal/Switch.qml41
-rw-r--r--src/quickcontrols/universal/SwitchDelegate.qml63
-rw-r--r--src/quickcontrols/universal/TabBar.qml37
-rw-r--r--src/quickcontrols/universal/TabButton.qml36
-rw-r--r--src/quickcontrols/universal/TextArea.qml60
-rw-r--r--src/quickcontrols/universal/TextField.qml60
-rw-r--r--src/quickcontrols/universal/ToolBar.qml20
-rw-r--r--src/quickcontrols/universal/ToolButton.qml50
-rw-r--r--src/quickcontrols/universal/ToolSeparator.qml26
-rw-r--r--src/quickcontrols/universal/ToolTip.qml39
-rw-r--r--src/quickcontrols/universal/Tumbler.qml45
-rw-r--r--src/quickcontrols/universal/VerticalHeaderView.qml36
-rw-r--r--src/quickcontrols/universal/images/checkmark.pngbin0 -> 222 bytes
-rw-r--r--src/quickcontrols/universal/images/checkmark@2x.pngbin0 -> 346 bytes
-rw-r--r--src/quickcontrols/universal/images/checkmark@3x.pngbin0 -> 796 bytes
-rw-r--r--src/quickcontrols/universal/images/checkmark@4x.pngbin0 -> 613 bytes
-rw-r--r--src/quickcontrols/universal/images/downarrow.pngbin0 -> 175 bytes
-rw-r--r--src/quickcontrols/universal/images/downarrow@2x.pngbin0 -> 267 bytes
-rw-r--r--src/quickcontrols/universal/images/downarrow@3x.pngbin0 -> 329 bytes
-rw-r--r--src/quickcontrols/universal/images/downarrow@4x.pngbin0 -> 365 bytes
-rw-r--r--src/quickcontrols/universal/images/leftarrow.pngbin0 -> 158 bytes
-rw-r--r--src/quickcontrols/universal/images/leftarrow@2x.pngbin0 -> 222 bytes
-rw-r--r--src/quickcontrols/universal/images/leftarrow@3x.pngbin0 -> 283 bytes
-rw-r--r--src/quickcontrols/universal/images/leftarrow@4x.pngbin0 -> 315 bytes
-rw-r--r--src/quickcontrols/universal/images/rightarrow.pngbin0 -> 152 bytes
-rw-r--r--src/quickcontrols/universal/images/rightarrow@2x.pngbin0 -> 226 bytes
-rw-r--r--src/quickcontrols/universal/images/rightarrow@3x.pngbin0 -> 258 bytes
-rw-r--r--src/quickcontrols/universal/images/rightarrow@4x.pngbin0 -> 338 bytes
-rw-r--r--src/quickcontrols/universal/impl/CMakeLists.txt39
-rw-r--r--src/quickcontrols/universal/impl/CheckIndicator.qml48
-rw-r--r--src/quickcontrols/universal/impl/RadioIndicator.qml47
-rw-r--r--src/quickcontrols/universal/impl/SwitchIndicator.qml48
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalbusyindicator.cpp220
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalbusyindicator_p.h57
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalfocusrectangle.cpp53
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalfocusrectangle_p.h37
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalprogressbar.cpp307
-rw-r--r--src/quickcontrols/universal/impl/qquickuniversalprogressbar_p.h59
-rw-r--r--src/quickcontrols/universal/qquickuniversalstyle.cpp587
-rw-r--r--src/quickcontrols/universal/qquickuniversalstyle_p.h212
-rw-r--r--src/quickcontrols/universal/qquickuniversaltheme.cpp37
-rw-r--r--src/quickcontrols/universal/qquickuniversaltheme_p.h32
-rw-r--r--src/quickcontrols/universal/qtquickcontrols2universalstyleplugin.cpp48
84 files changed, 4373 insertions, 0 deletions
diff --git a/src/quickcontrols/universal/ApplicationWindow.qml b/src/quickcontrols/universal/ApplicationWindow.qml
new file mode 100644
index 0000000000..7828d20480
--- /dev/null
+++ b/src/quickcontrols/universal/ApplicationWindow.qml
@@ -0,0 +1,21 @@
+// 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
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.ApplicationWindow {
+ id: window
+
+ color: Universal.background
+
+ FocusRectangle {
+ parent: window.activeFocusControl
+ width: parent ? parent.width : 0
+ height: parent ? parent.height : 0
+ visible: parent && !!parent.useSystemFocusVisuals && !!parent.visualFocus
+ }
+}
diff --git a/src/quickcontrols/universal/BusyIndicator.qml b/src/quickcontrols/universal/BusyIndicator.qml
new file mode 100644
index 0000000000..64dfdd251a
--- /dev/null
+++ b/src/quickcontrols/universal/BusyIndicator.qml
@@ -0,0 +1,27 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.BusyIndicator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ contentItem: BusyIndicatorImpl {
+ implicitWidth: 20
+ implicitHeight: 20
+
+ readonly property real size: Math.min(control.availableWidth, control.availableHeight)
+
+ count: size < 60 ? 5 : 6 // "Small" vs. "Large"
+ color: control.Universal.accent
+ visible: control.running
+ }
+}
diff --git a/src/quickcontrols/universal/Button.qml b/src/quickcontrols/universal/Button.qml
new file mode 100644
index 0000000000..bdf10e3c8c
--- /dev/null
+++ b/src/quickcontrols/universal/Button.qml
@@ -0,0 +1,56 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.Button {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 8
+ verticalPadding: padding - 4
+ spacing: 8
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ property bool useSystemFocusVisuals: true
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ visible: !control.flat || control.down || control.checked || control.highlighted
+ color: control.down ? control.Universal.baseMediumLowColor :
+ control.enabled && (control.highlighted || control.checked) ? control.Universal.accent :
+ control.Universal.baseLowColor
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "transparent"
+ visible: enabled && control.hovered
+ border.width: 2 // ButtonBorderThemeThickness
+ border.color: control.Universal.baseMediumLowColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/CMakeLists.txt b/src/quickcontrols/universal/CMakeLists.txt
new file mode 100644
index 0000000000..6f5dc1bb25
--- /dev/null
+++ b/src/quickcontrols/universal/CMakeLists.txt
@@ -0,0 +1,156 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## qtquickcontrols2universalstyleplugin Plugin:
+#####################################################################
+
+set(qml_files
+ "ApplicationWindow.qml"
+ "BusyIndicator.qml"
+ "Button.qml"
+ "CheckBox.qml"
+ "CheckDelegate.qml"
+ "ComboBox.qml"
+ "DelayButton.qml"
+ "Dial.qml"
+ "Dialog.qml"
+ "DialogButtonBox.qml"
+ "Drawer.qml"
+ "Frame.qml"
+ "GroupBox.qml"
+ "HorizontalHeaderView.qml"
+ "ItemDelegate.qml"
+ "Label.qml"
+ "Menu.qml"
+ "MenuBar.qml"
+ "MenuBarItem.qml"
+ "MenuItem.qml"
+ "MenuSeparator.qml"
+ "Page.qml"
+ "PageIndicator.qml"
+ "Pane.qml"
+ "Popup.qml"
+ "ProgressBar.qml"
+ "RadioButton.qml"
+ "RadioDelegate.qml"
+ "RangeSlider.qml"
+ "RoundButton.qml"
+ "ScrollView.qml"
+ "ScrollBar.qml"
+ "ScrollIndicator.qml"
+ "SelectionRectangle.qml"
+ "Slider.qml"
+ "SpinBox.qml"
+ "SplitView.qml"
+ "StackView.qml"
+ "SwipeDelegate.qml"
+ "SwitchDelegate.qml"
+ "Switch.qml"
+ "TabBar.qml"
+ "TabButton.qml"
+ "TextArea.qml"
+ "TextField.qml"
+ "ToolBar.qml"
+ "ToolButton.qml"
+ "ToolSeparator.qml"
+ "ToolTip.qml"
+ "Tumbler.qml"
+ "VerticalHeaderView.qml"
+)
+set_source_files_properties(DelayButton.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.2;6.0"
+)
+set_source_files_properties(Dialog.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.1;6.0"
+)
+set_source_files_properties(DialogButtonBox.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.1;6.0"
+)
+set_source_files_properties(HorizontalHeaderView.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.15;6.0"
+)
+set_source_files_properties(MenuBar.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.3;6.0"
+)
+set_source_files_properties(MenuBarItem.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.3;6.0"
+)
+set_source_files_properties(MenuSeparator.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.1;6.0"
+)
+set_source_files_properties(RoundButton.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.1;6.0"
+)
+set_source_files_properties(SplitView.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.13;6.0"
+)
+set_source_files_properties(ToolSeparator.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.1;6.0"
+)
+set_source_files_properties(VerticalHeaderView.qml PROPERTIES
+ QT_QML_SOURCE_VERSIONS "2.15;6.0"
+)
+
+qt_internal_add_qml_module(qtquickcontrols2universalstyleplugin
+ URI "QtQuick.Controls.Universal"
+ VERSION "${PROJECT_VERSION}"
+ PAST_MAJOR_VERSIONS 2
+ CLASS_NAME QtQuickControls2UniversalStylePlugin
+ DEPENDENCIES
+ QtQuick/auto
+ IMPORTS
+ QtQuick.Controls.Basic/auto
+ PLUGIN_TARGET qtquickcontrols2universalstyleplugin
+ NO_PLUGIN_OPTIONAL
+ NO_GENERATE_PLUGIN_SOURCE
+ SOURCES
+ qquickuniversalstyle.cpp qquickuniversalstyle_p.h
+ qquickuniversaltheme.cpp qquickuniversaltheme_p.h
+ qtquickcontrols2universalstyleplugin.cpp
+ QML_FILES
+ ${qml_files}
+ DEFINES
+ QT_NO_CAST_FROM_ASCII
+ QT_NO_CAST_TO_ASCII
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::GuiPrivate
+ Qt::QmlPrivate
+ Qt::QuickControls2ImplPrivate
+ Qt::QuickControls2Private
+ Qt::QuickPrivate
+ Qt::QuickTemplates2Private
+)
+
+qt_internal_add_resource(qtquickcontrols2universalstyleplugin "qtquickcontrols2universalstyleplugin"
+ PREFIX
+ "/qt-project.org/imports/QtQuick/Controls/Universal"
+ FILES
+ "images/checkmark.png"
+ "images/checkmark@2x.png"
+ "images/checkmark@3x.png"
+ "images/checkmark@4x.png"
+ "images/downarrow.png"
+ "images/downarrow@2x.png"
+ "images/downarrow@3x.png"
+ "images/downarrow@4x.png"
+ "images/leftarrow.png"
+ "images/leftarrow@2x.png"
+ "images/leftarrow@3x.png"
+ "images/leftarrow@4x.png"
+ "images/rightarrow.png"
+ "images/rightarrow@2x.png"
+ "images/rightarrow@3x.png"
+ "images/rightarrow@4x.png"
+)
+
+add_subdirectory(impl)
+
+_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2universalstyleplugin quickwindow)
+_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2universalstyleplugin
+ qtquickcontrols2universalstyleimplplugin)
+
+# Basic style is the required fallback style.
+_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2universalstyleplugin
+ qtquickcontrols2basicstyleplugin)
diff --git a/src/quickcontrols/universal/CheckBox.qml b/src/quickcontrols/universal/CheckBox.qml
new file mode 100644
index 0000000000..c7f99b3b2b
--- /dev/null
+++ b/src/quickcontrols/universal/CheckBox.qml
@@ -0,0 +1,41 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.CheckBox {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 6
+ spacing: 8
+
+ property bool useSystemFocusVisuals: true
+
+ indicator: CheckIndicator {
+ x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: Text {
+ leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
+ rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
+
+ text: control.text
+ font: control.font
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+}
diff --git a/src/quickcontrols/universal/CheckDelegate.qml b/src/quickcontrols/universal/CheckDelegate.qml
new file mode 100644
index 0000000000..f11f0ac888
--- /dev/null
+++ b/src/quickcontrols/universal/CheckDelegate.qml
@@ -0,0 +1,63 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.CheckDelegate {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 12
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ indicator: CheckIndicator {
+ x: control.text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: IconLabel {
+ leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing
+ rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing
+
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ visible: enabled && (control.down || control.highlighted || control.visualFocus || control.hovered)
+ color: control.down ? control.Universal.listMediumColor :
+ control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: control.visualFocus || control.highlighted
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+
+ }
+}
diff --git a/src/quickcontrols/universal/ComboBox.qml b/src/quickcontrols/universal/ComboBox.qml
new file mode 100644
index 0000000000..9a812388aa
--- /dev/null
+++ b/src/quickcontrols/universal/ComboBox.qml
@@ -0,0 +1,124 @@
+// 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
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls.impl
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ComboBox {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+ rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing)
+
+ Universal.theme: editable && activeFocus ? Universal.Light : undefined
+
+ delegate: ItemDelegate {
+ width: ListView.view.width
+ text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
+ font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
+ highlighted: control.highlightedIndex === index
+ hoverEnabled: control.hoverEnabled
+ }
+
+ indicator: ColorImage {
+ x: control.mirrored ? control.padding : control.width - width - control.padding
+ y: control.topPadding + (control.availableHeight - height) / 2
+ color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumHighColor
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/downarrow.png"
+
+ Rectangle {
+ z: -1
+ width: parent.width
+ height: parent.height
+ color: control.activeFocus ? control.Universal.accent :
+ control.pressed ? control.Universal.baseMediumLowColor :
+ control.hovered ? control.Universal.baseLowColor : "transparent"
+ visible: control.editable && !control.contentItem.hovered && (control.pressed || control.hovered)
+ opacity: control.activeFocus && !control.pressed ? 0.4 : 1.0
+ }
+ }
+
+ contentItem: T.TextField {
+ leftPadding: control.mirrored ? 1 : 12
+ rightPadding: control.mirrored ? 10 : 1
+ topPadding: 5 - control.topPadding
+ bottomPadding: 7 - control.bottomPadding
+
+ text: control.editable ? control.editText : control.displayText
+
+ enabled: control.editable
+ autoScroll: control.editable
+ readOnly: control.down
+ inputMethodHints: control.inputMethodHints
+ validator: control.validator
+ selectByMouse: control.selectTextByMouse
+
+ color: !control.enabled ? control.Universal.chromeDisabledLowColor :
+ control.editable && control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.foreground
+ selectionColor: control.Universal.accent
+ selectedTextColor: control.Universal.chromeWhiteColor
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ background: Rectangle {
+ implicitWidth: 120
+ implicitHeight: 32
+
+ border.width: control.flat ? 0 : 2 // ComboBoxBorderThemeThickness
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.editable && control.activeFocus ? control.Universal.accent :
+ control.down ? control.Universal.baseMediumLowColor :
+ control.hovered ? control.Universal.baseMediumColor : control.Universal.baseMediumLowColor
+ color: !control.enabled ? control.Universal.baseLowColor :
+ control.down ? control.Universal.listMediumColor :
+ control.flat && control.hovered ? control.Universal.listLowColor :
+ control.editable && control.activeFocus ? control.Universal.background : control.Universal.altMediumLowColor
+ visible: !control.flat || control.pressed || control.hovered || control.visualFocus
+
+ Rectangle {
+ x: 2
+ y: 2
+ width: parent.width - 4
+ height: parent.height - 4
+
+ visible: control.visualFocus && !control.editable
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+ }
+
+ popup: T.Popup {
+ width: control.width
+ height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
+ topMargin: 8
+ bottomMargin: 8
+
+ Universal.theme: control.Universal.theme
+ Universal.accent: control.Universal.accent
+
+ contentItem: ListView {
+ clip: true
+ implicitHeight: contentHeight
+ model: control.delegateModel
+ currentIndex: control.highlightedIndex
+ highlightMoveDuration: 0
+
+ T.ScrollIndicator.vertical: ScrollIndicator { }
+ }
+
+ background: Rectangle {
+ color: control.Universal.chromeMediumLowColor
+ border.color: control.Universal.chromeHighColor
+ border.width: 1 // FlyoutBorderThemeThickness
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/DelayButton.qml b/src/quickcontrols/universal/DelayButton.qml
new file mode 100644
index 0000000000..2b2cc83580
--- /dev/null
+++ b/src/quickcontrols/universal/DelayButton.qml
@@ -0,0 +1,61 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.DelayButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 8
+ verticalPadding: padding - 4
+
+ property bool useSystemFocusVisuals: true
+
+ transition: Transition {
+ NumberAnimation {
+ duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress)
+ }
+ }
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ elide: Text.ElideRight
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ color: control.down ? control.Universal.baseMediumLowColor :
+ control.enabled && control.checked ? control.Universal.accent : control.Universal.baseLowColor
+
+ Rectangle {
+ visible: !control.checked
+ width: parent.width * control.progress
+ height: parent.height
+ color: control.Universal.accent
+ }
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: "transparent"
+ visible: enabled && control.hovered
+ border.width: 2 // ButtonBorderThemeThickness
+ border.color: control.Universal.baseMediumLowColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/Dial.qml b/src/quickcontrols/universal/Dial.qml
new file mode 100644
index 0000000000..6f86b00722
--- /dev/null
+++ b/src/quickcontrols/universal/Dial.qml
@@ -0,0 +1,53 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Dial {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 100
+
+ x: control.width / 2 - width / 2
+ y: control.height / 2 - height / 2
+ width: Math.max(64, Math.min(control.width, control.height))
+ height: width
+ radius: width / 2
+ color: "transparent"
+ border.color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseMediumColor
+ border.width: 2
+ }
+
+ handle: Rectangle {
+ implicitWidth: 14
+ implicitHeight: 14
+
+ x: control.background.x + control.background.width / 2 - width / 2
+ y: control.background.y + control.background.height / 2 - height / 2
+
+ radius: width / 2
+ color: !control.enabled ? control.Universal.baseLowColor :
+ control.pressed ? control.Universal.baseMediumColor :
+ control.hovered ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor
+
+ transform: [
+ Translate {
+ y: -control.background.height * 0.4 + control.handle.height / 2
+ },
+ Rotation {
+ angle: control.angle
+ origin.x: control.handle.width / 2
+ origin.y: control.handle.height / 2
+ }
+ ]
+ }
+}
diff --git a/src/quickcontrols/universal/Dialog.qml b/src/quickcontrols/universal/Dialog.qml
new file mode 100644
index 0000000000..0ed4e673c7
--- /dev/null
+++ b/src/quickcontrols/universal/Dialog.qml
@@ -0,0 +1,57 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Dialog {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding,
+ implicitHeaderWidth,
+ implicitFooterWidth)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding
+ + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0)
+ + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0))
+
+ padding: 24
+ verticalPadding: 18
+
+ background: Rectangle {
+ color: control.Universal.chromeMediumLowColor
+ border.color: control.Universal.chromeHighColor
+ border.width: 1 // FlyoutBorderThemeThickness
+ }
+
+ header: Label {
+ text: control.title
+ visible: control.title
+ elide: Label.ElideRight
+ topPadding: 18
+ leftPadding: 24
+ rightPadding: 24
+ // TODO: QPlatformTheme::TitleBarFont
+ font.pixelSize: 20
+ background: Rectangle {
+ x: 1; y: 1 // // FlyoutBorderThemeThickness
+ color: control.Universal.chromeMediumLowColor
+ width: parent.width - 2
+ height: parent.height - 1
+ }
+ }
+
+ footer: DialogButtonBox {
+ visible: count > 0
+ }
+
+ T.Overlay.modal: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/DialogButtonBox.qml b/src/quickcontrols/universal/DialogButtonBox.qml
new file mode 100644
index 0000000000..826a13efd3
--- /dev/null
+++ b/src/quickcontrols/universal/DialogButtonBox.qml
@@ -0,0 +1,43 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.DialogButtonBox {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ (control.count === 1 ? implicitContentWidth * 2 : implicitContentWidth) + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+ contentWidth: contentItem.contentWidth
+
+ spacing: 4
+ padding: 24
+ topPadding: position === T.DialogButtonBox.Footer ? 6 : 24
+ bottomPadding: position === T.DialogButtonBox.Header ? 6 : 24
+ alignment: count === 1 ? Qt.AlignRight : undefined
+
+ delegate: Button {
+ width: control.count === 1 ? control.availableWidth / 2 : undefined
+ }
+
+ contentItem: ListView {
+ implicitWidth: contentWidth
+ model: control.contentModel
+ spacing: control.spacing
+ orientation: ListView.Horizontal
+ boundsBehavior: Flickable.StopAtBounds
+ snapMode: ListView.SnapToItem
+ }
+
+ background: Rectangle {
+ implicitHeight: 32
+ color: control.Universal.chromeMediumLowColor
+ x: 1; y: 1
+ width: parent.width - 2
+ height: parent.height - 2
+ }
+}
diff --git a/src/quickcontrols/universal/Drawer.qml b/src/quickcontrols/universal/Drawer.qml
new file mode 100644
index 0000000000..4c4ff5d443
--- /dev/null
+++ b/src/quickcontrols/universal/Drawer.qml
@@ -0,0 +1,45 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Drawer {
+ id: control
+
+ parent: T.Overlay.overlay
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ topPadding: control.edge === Qt.BottomEdge
+ leftPadding: control.edge === Qt.RightEdge
+ rightPadding: control.edge === Qt.LeftEdge
+ bottomPadding: control.edge === Qt.TopEdge
+
+ enter: Transition { SmoothedAnimation { velocity: 5 } }
+ exit: Transition { SmoothedAnimation { velocity: 5 } }
+
+ background: Rectangle {
+ color: control.Universal.chromeMediumLowColor
+ 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.Universal.chromeHighColor
+ x: control.edge === Qt.LeftEdge ? parent.width - 1 : 0
+ y: control.edge === Qt.TopEdge ? parent.height - 1 : 0
+ }
+ }
+
+ T.Overlay.modal: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/Frame.qml b/src/quickcontrols/universal/Frame.qml
new file mode 100644
index 0000000000..2e650d7913
--- /dev/null
+++ b/src/quickcontrols/universal/Frame.qml
@@ -0,0 +1,22 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Frame {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ padding: 12
+
+ background: Rectangle {
+ color: "transparent"
+ border.color: control.Universal.chromeDisabledLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/GroupBox.qml b/src/quickcontrols/universal/GroupBox.qml
new file mode 100644
index 0000000000..b0b211bd95
--- /dev/null
+++ b/src/quickcontrols/universal/GroupBox.qml
@@ -0,0 +1,42 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.GroupBox {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding,
+ implicitLabelWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ spacing: 12
+ padding: 12
+ topPadding: padding + (implicitLabelWidth > 0 ? implicitLabelHeight + spacing : 0)
+
+ label: Text {
+ x: control.leftPadding
+ width: control.availableWidth
+
+ text: control.title
+ font: control.font
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+
+ background: Rectangle {
+ y: control.topPadding - control.bottomPadding
+ width: parent.width
+ height: parent.height - control.topPadding + control.bottomPadding
+
+ color: "transparent"
+ border.color: control.Universal.chromeDisabledLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/HorizontalHeaderView.qml b/src/quickcontrols/universal/HorizontalHeaderView.qml
new file mode 100644
index 0000000000..878fb1e10e
--- /dev/null
+++ b/src/quickcontrols/universal/HorizontalHeaderView.qml
@@ -0,0 +1,36 @@
+// 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
+
+import QtQuick
+import QtQuick.Controls.impl
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.HorizontalHeaderView {
+ id: control
+
+ implicitWidth: syncView ? syncView.width : 0
+ implicitHeight: contentHeight
+
+ delegate: Rectangle {
+ // Qt6: add cellPadding (and font etc) as public API in headerview
+ readonly property real cellPadding: 8
+
+ implicitWidth: text.implicitWidth + (cellPadding * 2)
+ implicitHeight: Math.max(control.height, text.implicitHeight + (cellPadding * 2))
+ color: control.Universal.background
+
+ Text {
+ id: text
+ text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole]
+ : model[control.textRole])
+ : modelData
+ width: parent.width
+ height: parent.height
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/ItemDelegate.qml b/src/quickcontrols/universal/ItemDelegate.qml
new file mode 100644
index 0000000000..ab999d6094
--- /dev/null
+++ b/src/quickcontrols/universal/ItemDelegate.qml
@@ -0,0 +1,53 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.ItemDelegate {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 12
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ visible: enabled && (control.down || control.highlighted || control.visualFocus || control.hovered)
+ color: control.down ? control.Universal.listMediumColor :
+ control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: control.visualFocus || control.highlighted
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+
+ }
+}
diff --git a/src/quickcontrols/universal/Label.qml b/src/quickcontrols/universal/Label.qml
new file mode 100644
index 0000000000..e77f48d185
--- /dev/null
+++ b/src/quickcontrols/universal/Label.qml
@@ -0,0 +1,14 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Label {
+ id: control
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ linkColor: Universal.accent
+}
diff --git a/src/quickcontrols/universal/Menu.qml b/src/quickcontrols/universal/Menu.qml
new file mode 100644
index 0000000000..64dac0c4b8
--- /dev/null
+++ b/src/quickcontrols/universal/Menu.qml
@@ -0,0 +1,49 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Window
+
+T.Menu {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ margins: 0
+ overlap: 1
+
+ delegate: MenuItem { }
+
+ contentItem: ListView {
+ implicitHeight: contentHeight
+ model: control.contentModel
+ interactive: Window.window
+ ? contentHeight + control.topPadding + control.bottomPadding > Window.window.height
+ : false
+ clip: true
+ currentIndex: control.currentIndex
+
+ ScrollIndicator.vertical: ScrollIndicator {}
+ }
+
+ background: Rectangle {
+ implicitWidth: 200
+ implicitHeight: 40
+ color: control.Universal.chromeMediumLowColor
+ border.color: control.Universal.chromeHighColor
+ border.width: 1 // FlyoutBorderThemeThickness
+ }
+
+ T.Overlay.modal: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/MenuBar.qml b/src/quickcontrols/universal/MenuBar.qml
new file mode 100644
index 0000000000..1c0f4c6b2d
--- /dev/null
+++ b/src/quickcontrols/universal/MenuBar.qml
@@ -0,0 +1,30 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.MenuBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ delegate: MenuBarItem { }
+
+ contentItem: Row {
+ spacing: control.spacing
+ Repeater {
+ model: control.contentModel
+ }
+ }
+
+ background: Rectangle {
+ implicitHeight: 40
+ color: control.Universal.chromeMediumColor
+ }
+}
diff --git a/src/quickcontrols/universal/MenuBarItem.qml b/src/quickcontrols/universal/MenuBarItem.qml
new file mode 100644
index 0000000000..84dfb22fad
--- /dev/null
+++ b/src/quickcontrols/universal/MenuBarItem.qml
@@ -0,0 +1,57 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.MenuBarItem {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+ spacing: 12
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: !enabled ? Universal.baseLowColor : Universal.baseHighColor
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseHighColor
+ }
+
+ background: Rectangle {
+ implicitWidth: 40
+ implicitHeight: 40
+
+ color: !control.enabled ? control.Universal.baseLowColor :
+ control.down ? control.Universal.listMediumColor :
+ control.highlighted ? control.Universal.listLowColor : "transparent"
+
+ Rectangle {
+ x: 1; y: 1
+ width: parent.width - 2
+ height: parent.height - 2
+
+ visible: control.visualFocus
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/MenuItem.qml b/src/quickcontrols/universal/MenuItem.qml
new file mode 100644
index 0000000000..00b9d16228
--- /dev/null
+++ b/src/quickcontrols/universal/MenuItem.qml
@@ -0,0 +1,81 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.MenuItem {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+ spacing: 12
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: !enabled ? Universal.baseLowColor : Universal.baseHighColor
+
+ contentItem: IconLabel {
+ readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
+ readonly property real indicatorPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
+ leftPadding: !control.mirrored ? indicatorPadding : arrowPadding
+ rightPadding: control.mirrored ? indicatorPadding : arrowPadding
+
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: !control.enabled ? control.Universal.baseLowColor : control.Universal.baseHighColor
+ }
+
+ arrow: ColorImage {
+ x: control.mirrored ? control.leftPadding : control.width - width - control.rightPadding
+ y: control.topPadding + (control.availableHeight - height) / 2
+
+ visible: control.subMenu
+ mirror: control.mirrored
+ color: !enabled ? control.Universal.baseLowColor : control.Universal.baseHighColor
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/rightarrow.png"
+ }
+
+ indicator: ColorImage {
+ x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+
+ visible: control.checked
+ color: !control.enabled ? control.Universal.baseLowColor : control.down ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor
+ source: !control.checkable ? "" : "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/checkmark.png"
+ }
+
+ background: Rectangle {
+ implicitWidth: 200
+ implicitHeight: 40
+
+ color: !control.enabled ? control.Universal.baseLowColor :
+ control.down ? control.Universal.listMediumColor :
+ control.highlighted ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+
+ Rectangle {
+ x: 1; y: 1
+ width: parent.width - 2
+ height: parent.height - 2
+
+ visible: control.visualFocus
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/MenuSeparator.qml b/src/quickcontrols/universal/MenuSeparator.qml
new file mode 100644
index 0000000000..dc814ef2fe
--- /dev/null
+++ b/src/quickcontrols/universal/MenuSeparator.qml
@@ -0,0 +1,29 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.MenuSeparator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 12
+ topPadding: 9
+ bottomPadding: 10
+
+ contentItem: Rectangle {
+ implicitWidth: 188
+ implicitHeight: 1
+ color: control.Universal.baseMediumLowColor
+ }
+
+ background: Rectangle {
+ color: control.Universal.altMediumLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/Page.qml b/src/quickcontrols/universal/Page.qml
new file mode 100644
index 0000000000..7e2c69aa5b
--- /dev/null
+++ b/src/quickcontrols/universal/Page.qml
@@ -0,0 +1,23 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Page {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding,
+ implicitHeaderWidth,
+ implicitFooterWidth)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding
+ + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0)
+ + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0))
+
+ background: Rectangle {
+ color: control.Universal.background
+ }
+}
diff --git a/src/quickcontrols/universal/PageIndicator.qml b/src/quickcontrols/universal/PageIndicator.qml
new file mode 100644
index 0000000000..68147f6996
--- /dev/null
+++ b/src/quickcontrols/universal/PageIndicator.qml
@@ -0,0 +1,38 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.PageIndicator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 6
+ spacing: 7
+
+ delegate: Rectangle {
+ implicitWidth: 5
+ implicitHeight: 5
+
+ radius: width / 2
+ color: index === control.currentIndex ? control.Universal.baseMediumHighColor :
+ pressed ? control.Universal.baseMediumLowColor : control.Universal.baseLowColor
+
+ required property int index
+ }
+
+ contentItem: Row {
+ spacing: control.spacing
+
+ Repeater {
+ model: control.count
+ delegate: control.delegate
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/Pane.qml b/src/quickcontrols/universal/Pane.qml
new file mode 100644
index 0000000000..2f27979c4b
--- /dev/null
+++ b/src/quickcontrols/universal/Pane.qml
@@ -0,0 +1,21 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Pane {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ padding: 12
+
+ background: Rectangle {
+ color: control.Universal.background
+ }
+}
diff --git a/src/quickcontrols/universal/Popup.qml b/src/quickcontrols/universal/Popup.qml
new file mode 100644
index 0000000000..5899919791
--- /dev/null
+++ b/src/quickcontrols/universal/Popup.qml
@@ -0,0 +1,31 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Popup {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ padding: 12
+
+ background: Rectangle {
+ color: control.Universal.chromeMediumLowColor
+ border.color: control.Universal.chromeHighColor
+ border.width: 1 // FlyoutBorderThemeThickness
+ }
+
+ T.Overlay.modal: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/ProgressBar.qml b/src/quickcontrols/universal/ProgressBar.qml
new file mode 100644
index 0000000000..803941f865
--- /dev/null
+++ b/src/quickcontrols/universal/ProgressBar.qml
@@ -0,0 +1,35 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.ProgressBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ contentItem: ProgressBarImpl {
+ implicitHeight: 10
+
+ scale: control.mirrored ? -1 : 1
+ color: control.Universal.accent
+ progress: control.position
+ indeterminate: control.visible && control.indeterminate
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 10
+ y: (control.height - height) / 2
+ height: 10
+
+ visible: !control.indeterminate
+ color: control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/README.md b/src/quickcontrols/universal/README.md
new file mode 100644
index 0000000000..8d02d18ba3
--- /dev/null
+++ b/src/quickcontrols/universal/README.md
@@ -0,0 +1,9 @@
+# Universal Style
+
+This style is based on the [Microsoft Universal Design Guidelines](https://dev.windows.com/design).
+
+The colors and metrics used all around the QML and C++ files originate from the Windows 10 SDK. The files are called **generic.xaml** and **themeresources.xml**, and they are located in the following folder:
+
+ \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic
+
+See also [XAML theme resources](https://msdn.microsoft.com/en-us/library/windows/apps/mt187274.aspx).
diff --git a/src/quickcontrols/universal/RadioButton.qml b/src/quickcontrols/universal/RadioButton.qml
new file mode 100644
index 0000000000..b7e594308b
--- /dev/null
+++ b/src/quickcontrols/universal/RadioButton.qml
@@ -0,0 +1,41 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.RadioButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 6
+ spacing: 8
+
+ property bool useSystemFocusVisuals: true
+
+ indicator: RadioIndicator {
+ x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: Text {
+ leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
+ rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
+
+ text: control.text
+ font: control.font
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+}
diff --git a/src/quickcontrols/universal/RadioDelegate.qml b/src/quickcontrols/universal/RadioDelegate.qml
new file mode 100644
index 0000000000..9e9899d15a
--- /dev/null
+++ b/src/quickcontrols/universal/RadioDelegate.qml
@@ -0,0 +1,63 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.RadioDelegate {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 12
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ indicator: RadioIndicator {
+ x: control.text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: IconLabel {
+ leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing
+ rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing
+
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ visible: enabled && (control.down || control.highlighted || control.visualFocus || control.hovered)
+ color: control.down ? control.Universal.listMediumColor :
+ control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: control.visualFocus || control.highlighted
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+
+ }
+}
diff --git a/src/quickcontrols/universal/RangeSlider.qml b/src/quickcontrols/universal/RangeSlider.qml
new file mode 100644
index 0000000000..cd85d930bb
--- /dev/null
+++ b/src/quickcontrols/universal/RangeSlider.qml
@@ -0,0 +1,76 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.RangeSlider {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ first.implicitHandleWidth + leftPadding + rightPadding,
+ second.implicitHandleWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ first.implicitHandleHeight + topPadding + bottomPadding,
+ second.implicitHandleHeight + topPadding + bottomPadding)
+
+ padding: 6
+
+ first.handle: Rectangle {
+ implicitWidth: control.horizontal ? 8 : 24
+ implicitHeight: control.horizontal ? 24 : 8
+
+ 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))
+
+ radius: 4
+ color: control.first.pressed ? control.Universal.chromeHighColor :
+ control.first.hovered ? control.Universal.chromeAltLowColor :
+ control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor
+ }
+
+ second.handle: Rectangle {
+ implicitWidth: control.horizontal ? 8 : 24
+ implicitHeight: control.horizontal ? 24 : 8
+
+ x: control.leftPadding + (control.horizontal ? control.second.visualPosition * (control.availableWidth - width) : (control.availableWidth - width) / 2)
+ y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : control.second.visualPosition * (control.availableHeight - height))
+
+ radius: 4
+ color: control.second.pressed ? control.Universal.chromeHighColor :
+ control.second.hovered ? control.Universal.chromeAltLowColor :
+ control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor
+ }
+
+ background: Item {
+ implicitWidth: control.horizontal ? 200 : 18
+ implicitHeight: control.horizontal ? 18 : 200
+
+ x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2)
+ y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0)
+ width: control.horizontal ? control.availableWidth : implicitWidth
+ height: control.horizontal ? implicitHeight : control.availableHeight
+
+ scale: control.horizontal && control.mirrored ? -1 : 1
+
+ Rectangle {
+ x: control.horizontal ? 0 : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : 0
+ width: control.horizontal ? parent.width : 2 // SliderBackgroundThemeHeight
+ height: control.vertical ? parent.height : 2 // SliderBackgroundThemeHeight
+
+ color: enabled && control.hovered && !control.pressed ? control.Universal.baseMediumColor :
+ control.enabled ? control.Universal.baseMediumLowColor : control.Universal.chromeDisabledHighColor
+ }
+
+ Rectangle {
+ x: control.horizontal ? control.first.position * parent.width : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : control.second.visualPosition * parent.height
+ width: control.horizontal ? control.second.position * parent.width - control.first.position * parent.width : 2 // SliderBackgroundThemeHeight
+ height: control.vertical ? control.second.position * parent.height - control.first.position * parent.height : 2 // SliderBackgroundThemeHeight
+
+ color: control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/RoundButton.qml b/src/quickcontrols/universal/RoundButton.qml
new file mode 100644
index 0000000000..c2d0f9e823
--- /dev/null
+++ b/src/quickcontrols/universal/RoundButton.qml
@@ -0,0 +1,57 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.RoundButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 8
+ spacing: 8
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ property bool useSystemFocusVisuals: true
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ implicitWidth: 32
+ implicitHeight: 32
+
+ radius: control.radius
+ visible: !control.flat || control.down || control.checked || control.highlighted
+ color: control.down ? control.Universal.baseMediumLowColor :
+ control.enabled && (control.highlighted || control.checked) ? control.Universal.accent :
+ control.Universal.baseLowColor
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ radius: control.radius
+ color: "transparent"
+ visible: enabled && control.hovered
+ border.width: 2 // ButtonBorderThemeThickness
+ border.color: control.Universal.baseMediumLowColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/ScrollBar.qml b/src/quickcontrols/universal/ScrollBar.qml
new file mode 100644
index 0000000000..a5ab5fc762
--- /dev/null
+++ b/src/quickcontrols/universal/ScrollBar.qml
@@ -0,0 +1,61 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ScrollBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ visible: control.policy !== T.ScrollBar.AlwaysOff
+ minimumSize: orientation === Qt.Horizontal ? height / width : width / height
+
+ // TODO: arrows
+
+ contentItem: Rectangle {
+ implicitWidth: control.interactive ? 12 : 6
+ implicitHeight: control.interactive ? 12: 6
+
+ color: control.pressed ? control.Universal.baseMediumColor :
+ enabled && control.interactive && control.hovered ? control.Universal.baseMediumLowColor :
+ control.Universal.chromeHighColor
+ opacity: 0.0
+ }
+
+ background: Rectangle {
+ implicitWidth: control.interactive ? 12 : 6
+ implicitHeight: control.interactive ? 12: 6
+
+ color: control.Universal.chromeLowColor
+ visible: control.size < 1.0
+ opacity: 0.0
+ }
+
+ states: [
+ State {
+ name: "active"
+ when: control.policy === T.ScrollBar.AlwaysOn || (control.active && control.size < 1.0)
+ }
+ ]
+
+ transitions: [
+ Transition {
+ to: "active"
+ NumberAnimation { targets: [control.contentItem, control.background]; property: "opacity"; to: 1.0 }
+ },
+ Transition {
+ from: "active"
+ SequentialAnimation {
+ PropertyAction{ targets: [control.contentItem, control.background]; property: "opacity"; value: 1.0 }
+ PauseAnimation { duration: 3000 }
+ NumberAnimation { targets: [control.contentItem, control.background]; property: "opacity"; to: 0.0 }
+ }
+ }
+ ]
+}
diff --git a/src/quickcontrols/universal/ScrollIndicator.qml b/src/quickcontrols/universal/ScrollIndicator.qml
new file mode 100644
index 0000000000..1df2163498
--- /dev/null
+++ b/src/quickcontrols/universal/ScrollIndicator.qml
@@ -0,0 +1,45 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ScrollIndicator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ contentItem: Rectangle {
+ implicitWidth: 6
+ implicitHeight: 6
+
+ color: control.Universal.baseMediumLowColor
+ visible: control.size < 1.0
+ opacity: 0.0
+
+ states: [
+ State {
+ name: "active"
+ when: control.active
+ }
+ ]
+
+ transitions: [
+ Transition {
+ to: "active"
+ NumberAnimation { target: control.contentItem; property: "opacity"; to: 1.0 }
+ },
+ Transition {
+ from: "active"
+ SequentialAnimation {
+ PauseAnimation { duration: 5000 }
+ NumberAnimation { target: control.contentItem; property: "opacity"; to: 0.0 }
+ }
+ }
+ ]
+ }
+}
diff --git a/src/quickcontrols/universal/ScrollView.qml b/src/quickcontrols/universal/ScrollView.qml
new file mode 100644
index 0000000000..60789313c9
--- /dev/null
+++ b/src/quickcontrols/universal/ScrollView.qml
@@ -0,0 +1,31 @@
+// 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
+
+import QtQuick
+import QtQuick.Controls.impl
+import QtQuick.Templates as T
+
+T.ScrollView {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ ScrollBar.vertical: ScrollBar {
+ parent: control
+ x: control.mirrored ? 0 : control.width - width
+ y: control.topPadding
+ height: control.availableHeight
+ active: control.ScrollBar.horizontal.active
+ }
+
+ ScrollBar.horizontal: ScrollBar {
+ parent: control
+ x: control.leftPadding
+ y: control.height - height
+ width: control.availableWidth
+ active: control.ScrollBar.vertical.active
+ }
+}
diff --git a/src/quickcontrols/universal/SelectionRectangle.qml b/src/quickcontrols/universal/SelectionRectangle.qml
new file mode 100644
index 0000000000..e7b99852da
--- /dev/null
+++ b/src/quickcontrols/universal/SelectionRectangle.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2021 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
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.SelectionRectangle {
+ id: control
+
+ topLeftHandle: handle
+ bottomRightHandle: handle
+
+ Component {
+ id: handle
+ Rectangle {
+ implicitWidth: 8
+ implicitHeight: 24
+ radius: 4
+ color: tapHandler.pressed || SelectionRectangle.dragging ? control.Universal.chromeHighColor :
+ hoverHandler.hovered ? control.Universal.chromeAltLowColor :
+ control.Universal.accent
+ visible: control.active
+
+ property Item control: SelectionRectangle.control
+
+ HoverHandler {
+ id: hoverHandler
+ }
+
+ TapHandler {
+ id: tapHandler
+ }
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/Slider.qml b/src/quickcontrols/universal/Slider.qml
new file mode 100644
index 0000000000..305c5c321f
--- /dev/null
+++ b/src/quickcontrols/universal/Slider.qml
@@ -0,0 +1,63 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.Slider {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitHandleWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitHandleHeight + topPadding + bottomPadding)
+
+ padding: 6
+
+ property bool useSystemFocusVisuals: true
+
+ handle: Rectangle {
+ implicitWidth: control.horizontal ? 8 : 24
+ implicitHeight: control.horizontal ? 24 : 8
+
+ 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))
+
+ radius: 4
+ color: control.pressed ? control.Universal.chromeHighColor :
+ control.enabled ? control.hovered ? control.Universal.chromeAltLowColor :
+ control.Universal.accent : control.Universal.chromeDisabledHighColor
+ }
+
+ background: Item {
+ implicitWidth: control.horizontal ? 200 : 18
+ implicitHeight: control.horizontal ? 18 : 200
+
+ x: control.leftPadding + (control.horizontal ? 0 : (control.availableWidth - width) / 2)
+ y: control.topPadding + (control.horizontal ? (control.availableHeight - height) / 2 : 0)
+ width: control.horizontal ? control.availableWidth : implicitWidth
+ height: control.horizontal ? implicitHeight : control.availableHeight
+
+ scale: control.horizontal && control.mirrored ? -1 : 1
+
+ Rectangle {
+ x: control.horizontal ? 0 : (parent.width - width) / 2
+ y: control.horizontal ? (parent.height - height) / 2 : 0
+ width: control.horizontal ? parent.width : 2 // SliderTrackThemeHeight
+ height: !control.horizontal ? parent.height : 2 // SliderTrackThemeHeight
+
+ color: enabled && control.hovered && !control.pressed ? control.Universal.baseMediumColor :
+ control.enabled ? control.Universal.baseMediumLowColor : control.Universal.chromeDisabledHighColor
+ }
+
+ 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 : 2 // SliderTrackThemeHeight
+ height: !control.horizontal ? control.position * parent.height : 2 // SliderTrackThemeHeight
+
+ color: control.enabled ? control.Universal.accent : control.Universal.chromeDisabledHighColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/SpinBox.qml b/src/quickcontrols/universal/SpinBox.qml
new file mode 100644
index 0000000000..07721c8712
--- /dev/null
+++ b/src/quickcontrols/universal/SpinBox.qml
@@ -0,0 +1,114 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.SpinBox {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentItem.implicitWidth + 16 +
+ up.implicitIndicatorWidth +
+ down.implicitIndicatorWidth)
+ implicitHeight: Math.max(implicitContentHeight + topPadding + bottomPadding,
+ implicitBackgroundHeight,
+ up.implicitIndicatorHeight,
+ down.implicitIndicatorHeight)
+
+ // TextControlThemePadding + 2 (border)
+ padding: 12
+ topPadding: padding - 7
+ leftPadding: padding + (control.mirrored ? (up.indicator ? up.indicator.width : 0) : (down.indicator ? down.indicator.width : 0))
+ rightPadding: padding - 4 + (control.mirrored ? (down.indicator ? down.indicator.width : 0) : (up.indicator ? up.indicator.width : 0))
+ bottomPadding: padding - 5
+
+ Universal.theme: activeFocus ? Universal.Light : undefined
+
+ validator: IntValidator {
+ locale: control.locale.name
+ bottom: Math.min(control.from, control.to)
+ top: Math.max(control.from, control.to)
+ }
+
+ contentItem: TextInput {
+ text: control.displayText
+
+ font: control.font
+ color: !enabled ? control.Universal.chromeDisabledLowColor :
+ activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.foreground
+ selectionColor: control.Universal.accent
+ selectedTextColor: control.Universal.chromeWhiteColor
+ horizontalAlignment: Qt.AlignHCenter
+ verticalAlignment: TextInput.AlignVCenter
+
+ readOnly: !control.editable
+ validator: control.validator
+ inputMethodHints: control.inputMethodHints
+ }
+
+ up.indicator: Item {
+ implicitWidth: 28
+ height: control.height + 4
+ y: -2
+ x: control.mirrored ? 0 : control.width - width
+
+ Rectangle {
+ x: 2; y: 4
+ width: parent.width - 4
+ height: parent.height - 8
+ color: control.activeFocus ? control.Universal.accent :
+ control.up.pressed ? control.Universal.baseMediumLowColor :
+ control.up.hovered ? control.Universal.baseLowColor : "transparent"
+ visible: control.up.pressed || control.up.hovered
+ opacity: control.activeFocus && !control.up.pressed ? 0.4 : 1.0
+ }
+
+ ColorImage {
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ color: !enabled ? control.Universal.chromeDisabledLowColor :
+ control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/" + (control.mirrored ? "left" : "right") + "arrow.png"
+ }
+ }
+
+ down.indicator: Item {
+ implicitWidth: 28
+ height: control.height + 4
+ y: -2
+ x: control.mirrored ? control.width - width : 0
+
+ Rectangle {
+ x: 2; y: 4
+ width: parent.width - 4
+ height: parent.height - 8
+ color: control.activeFocus ? control.Universal.accent :
+ control.down.pressed ? control.Universal.baseMediumLowColor :
+ control.down.hovered ? control.Universal.baseLowColor : "transparent"
+ visible: control.down.pressed || control.down.hovered
+ opacity: control.activeFocus && !control.down.pressed ? 0.4 : 1.0
+ }
+
+ ColorImage {
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ color: !enabled ? control.Universal.chromeDisabledLowColor :
+ control.activeFocus ? control.Universal.chromeBlackHighColor : control.Universal.baseHighColor
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/" + (control.mirrored ? "right" : "left") + "arrow.png"
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: 60 + 28 // TextControlThemeMinWidth - 4 (border)
+ implicitHeight: 28 // TextControlThemeMinHeight - 4 (border)
+
+ border.width: 2 // TextControlBorderThemeThickness
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.activeFocus ? control.Universal.accent :
+ control.hovered ? control.Universal.baseMediumColor : control.Universal.chromeDisabledLowColor
+ color: control.enabled ? control.Universal.background : control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/SplitView.qml b/src/quickcontrols/universal/SplitView.qml
new file mode 100644
index 0000000000..e18169db6a
--- /dev/null
+++ b/src/quickcontrols/universal/SplitView.qml
@@ -0,0 +1,22 @@
+// Copyright (C) 2018 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
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.SplitView {
+ id: control
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ handle: Rectangle {
+ implicitWidth: control.orientation === Qt.Horizontal ? 6 : control.width
+ implicitHeight: control.orientation === Qt.Horizontal ? control.height : 6
+ color: T.SplitHandle.pressed ? control.Universal.baseMediumColor
+ : (enabled && T.SplitHandle.hovered ? control.Universal.baseMediumLowColor : control.Universal.chromeHighColor)
+ }
+}
diff --git a/src/quickcontrols/universal/StackView.qml b/src/quickcontrols/universal/StackView.qml
new file mode 100644
index 0000000000..b5d568f98d
--- /dev/null
+++ b/src/quickcontrols/universal/StackView.qml
@@ -0,0 +1,43 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.StackView {
+ id: control
+
+ popEnter: Transition {
+ ParallelAnimation {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint }
+ NumberAnimation { property: "x"; from: (control.mirrored ? -0.3 : 0.3) * -control.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
+ }
+ }
+
+ popExit: Transition {
+ NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 200; easing.type: Easing.OutQuint }
+ }
+
+ pushEnter: Transition {
+ ParallelAnimation {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint }
+ NumberAnimation { property: "x"; from: (control.mirrored ? -0.3 : 0.3) * control.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
+ }
+ }
+
+ pushExit: Transition {
+ NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 200; easing.type: Easing.OutQuint }
+ }
+
+ replaceEnter: Transition {
+ ParallelAnimation {
+ NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 200; easing.type: Easing.InQuint }
+ NumberAnimation { property: "x"; from: (control.mirrored ? -0.3 : 0.3) * control.width; to: 0; duration: 400; easing.type: Easing.OutCubic }
+ }
+ }
+
+ replaceExit: Transition {
+ NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 200; easing.type: Easing.OutQuint }
+ }
+}
diff --git a/src/quickcontrols/universal/SwipeDelegate.qml b/src/quickcontrols/universal/SwipeDelegate.qml
new file mode 100644
index 0000000000..0bb2367ca7
--- /dev/null
+++ b/src/quickcontrols/universal/SwipeDelegate.qml
@@ -0,0 +1,59 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.SwipeDelegate {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 12
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ swipe.transition: Transition { SmoothedAnimation { velocity: 3; easing.type: Easing.InOutCubic } }
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ color: control.Universal.background
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ color: control.down ? control.Universal.listMediumColor :
+ enabled && control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: control.visualFocus || control.highlighted
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/Switch.qml b/src/quickcontrols/universal/Switch.qml
new file mode 100644
index 0000000000..70de360bde
--- /dev/null
+++ b/src/quickcontrols/universal/Switch.qml
@@ -0,0 +1,41 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.Switch {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ padding: 5
+ spacing: 8
+
+ property bool useSystemFocusVisuals: true
+
+ indicator: SwitchIndicator {
+ x: control.text ? (control.mirrored ? control.width - width - control.rightPadding : control.leftPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: Text {
+ leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
+ rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
+
+ text: control.text
+ font: control.font
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+}
diff --git a/src/quickcontrols/universal/SwitchDelegate.qml b/src/quickcontrols/universal/SwitchDelegate.qml
new file mode 100644
index 0000000000..18a55e9cd9
--- /dev/null
+++ b/src/quickcontrols/universal/SwitchDelegate.qml
@@ -0,0 +1,63 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.SwitchDelegate {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 12
+
+ padding: 12
+ topPadding: padding - 1
+ bottomPadding: padding + 1
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ indicator: SwitchIndicator {
+ x: control.text ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding) : control.leftPadding + (control.availableWidth - width) / 2
+ y: control.topPadding + (control.availableHeight - height) / 2
+ control: control
+ }
+
+ contentItem: IconLabel {
+ leftPadding: !control.mirrored ? 0 : control.indicator.width + control.spacing
+ rightPadding: control.mirrored ? 0 : control.indicator.width + control.spacing
+
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: control.display === IconLabel.IconOnly || control.display === IconLabel.TextUnderIcon ? Qt.AlignCenter : Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ visible: enabled && (control.down || control.highlighted || control.visualFocus || control.hovered)
+ color: control.down ? control.Universal.listMediumColor :
+ control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: control.visualFocus || control.highlighted
+ color: control.Universal.accent
+ opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6
+ }
+
+ }
+}
diff --git a/src/quickcontrols/universal/TabBar.qml b/src/quickcontrols/universal/TabBar.qml
new file mode 100644
index 0000000000..c06aaaf541
--- /dev/null
+++ b/src/quickcontrols/universal/TabBar.qml
@@ -0,0 +1,37 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.TabBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ contentItem: ListView {
+ model: control.contentModel
+ currentIndex: control.currentIndex
+
+ spacing: control.spacing
+ orientation: ListView.Horizontal
+ boundsBehavior: Flickable.StopAtBounds
+ flickableDirection: Flickable.AutoFlickIfNeeded
+ snapMode: ListView.SnapToItem
+
+ highlightMoveDuration: 100
+ highlightRangeMode: ListView.ApplyRange
+ preferredHighlightBegin: 48
+ preferredHighlightEnd: width - 48
+ }
+
+ background: Rectangle {
+ implicitWidth: 200
+ implicitHeight: 48
+ color: control.Universal.background
+ }
+}
diff --git a/src/quickcontrols/universal/TabButton.qml b/src/quickcontrols/universal/TabButton.qml
new file mode 100644
index 0000000000..7c8080301e
--- /dev/null
+++ b/src/quickcontrols/universal/TabButton.qml
@@ -0,0 +1,36 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.TabButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 12 // PivotItemMargin
+ spacing: 8
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(control.hovered ? control.Universal.baseMediumHighColor : control.Universal.foreground,
+ control.checked || control.down || control.hovered ? 1.0 : 0.2)
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(enabled && control.hovered ? control.Universal.baseMediumHighColor : control.Universal.foreground,
+ control.checked || control.down || (enabled && control.hovered) ? 1.0 : 0.2)
+ }
+}
diff --git a/src/quickcontrols/universal/TextArea.qml b/src/quickcontrols/universal/TextArea.qml
new file mode 100644
index 0000000000..8a3cdd1119
--- /dev/null
+++ b/src/quickcontrols/universal/TextArea.qml
@@ -0,0 +1,60 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.TextArea {
+ id: control
+
+ implicitWidth: Math.max(contentWidth + leftPadding + rightPadding,
+ implicitBackgroundWidth + leftInset + rightInset,
+ placeholder.implicitWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(contentHeight + topPadding + bottomPadding,
+ implicitBackgroundHeight + topInset + bottomInset,
+ placeholder.implicitHeight + topPadding + bottomPadding)
+
+ // TextControlThemePadding + 2 (border)
+ padding: 12
+ topPadding: padding - 7
+ rightPadding: padding - 4
+ bottomPadding: padding - 5
+
+ Universal.theme: activeFocus ? Universal.Light : undefined
+
+ color: !enabled ? Universal.chromeDisabledLowColor : Universal.foreground
+ selectionColor: Universal.accent
+ selectedTextColor: Universal.chromeWhiteColor
+ placeholderTextColor: !enabled ? Universal.chromeDisabledLowColor :
+ activeFocus ? Universal.chromeBlackMediumLowColor :
+ Universal.baseMediumColor
+
+ PlaceholderText {
+ id: placeholder
+ x: control.leftPadding
+ y: control.topPadding
+ width: control.width - (control.leftPadding + control.rightPadding)
+ height: control.height - (control.topPadding + control.bottomPadding)
+
+ text: control.placeholderText
+ font: control.font
+ color: control.placeholderTextColor
+ visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
+ verticalAlignment: control.verticalAlignment
+ elide: Text.ElideRight
+ renderType: control.renderType
+ }
+
+ background: Rectangle {
+ implicitWidth: 60 // TextControlThemeMinWidth - 4 (border)
+ implicitHeight: 28 // TextControlThemeMinHeight - 4 (border)
+
+ border.width: 2 // TextControlBorderThemeThickness
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.activeFocus ? control.Universal.accent :
+ control.hovered ? control.Universal.baseMediumColor : control.Universal.chromeDisabledLowColor
+ color: control.enabled ? control.Universal.background : control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/TextField.qml b/src/quickcontrols/universal/TextField.qml
new file mode 100644
index 0000000000..fb20779156
--- /dev/null
+++ b/src/quickcontrols/universal/TextField.qml
@@ -0,0 +1,60 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.TextField {
+ id: control
+
+ implicitWidth: implicitBackgroundWidth + leftInset + rightInset
+ || Math.max(contentWidth, placeholder.implicitWidth) + leftPadding + rightPadding
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding,
+ placeholder.implicitHeight + topPadding + bottomPadding)
+
+ // TextControlThemePadding + 2 (border)
+ padding: 12
+ topPadding: padding - 7
+ rightPadding: padding - 4
+ bottomPadding: padding - 5
+
+ Universal.theme: activeFocus ? Universal.Light : undefined
+
+ color: !enabled ? Universal.chromeDisabledLowColor : Universal.foreground
+ selectionColor: Universal.accent
+ selectedTextColor: Universal.chromeWhiteColor
+ placeholderTextColor: !enabled ? Universal.chromeDisabledLowColor :
+ activeFocus ? Universal.chromeBlackMediumLowColor :
+ Universal.baseMediumColor
+ verticalAlignment: TextInput.AlignVCenter
+
+ PlaceholderText {
+ id: placeholder
+ x: control.leftPadding
+ y: control.topPadding
+ width: control.width - (control.leftPadding + control.rightPadding)
+ height: control.height - (control.topPadding + control.bottomPadding)
+
+ text: control.placeholderText
+ font: control.font
+ color: control.placeholderTextColor
+ visible: !control.length && !control.preeditText && (!control.activeFocus || control.horizontalAlignment !== Qt.AlignHCenter)
+ verticalAlignment: control.verticalAlignment
+ elide: Text.ElideRight
+ renderType: control.renderType
+ }
+
+ background: Rectangle {
+ implicitWidth: 60 // TextControlThemeMinWidth - 4 (border)
+ implicitHeight: 28 // TextControlThemeMinHeight - 4 (border)
+
+ border.width: 2 // TextControlBorderThemeThickness
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.activeFocus ? control.Universal.accent :
+ control.hovered ? control.Universal.baseMediumColor : control.Universal.chromeDisabledLowColor
+ color: control.enabled ? control.Universal.background : control.Universal.baseLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/ToolBar.qml b/src/quickcontrols/universal/ToolBar.qml
new file mode 100644
index 0000000000..33aa490c08
--- /dev/null
+++ b/src/quickcontrols/universal/ToolBar.qml
@@ -0,0 +1,20 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ToolBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ background: Rectangle {
+ implicitHeight: 48 // AppBarThemeCompactHeight
+ color: control.Universal.chromeMediumColor
+ }
+}
diff --git a/src/quickcontrols/universal/ToolButton.qml b/src/quickcontrols/universal/ToolButton.qml
new file mode 100644
index 0000000000..08c346b99e
--- /dev/null
+++ b/src/quickcontrols/universal/ToolButton.qml
@@ -0,0 +1,50 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+T.ToolButton {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 6
+ spacing: 8
+
+ icon.width: 20
+ icon.height: 20
+ icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2)
+
+ property bool useSystemFocusVisuals: true
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+
+ background: Rectangle {
+ implicitWidth: 68
+ implicitHeight: 48 // AppBarThemeCompactHeight
+
+ color: control.enabled && (control.highlighted || control.checked) ? control.Universal.accent : "transparent"
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ visible: enabled && (control.down || control.hovered)
+ color: control.down ? control.Universal.listMediumColor : control.Universal.listLowColor
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/ToolSeparator.qml b/src/quickcontrols/universal/ToolSeparator.qml
new file mode 100644
index 0000000000..2d6cc9a3cc
--- /dev/null
+++ b/src/quickcontrols/universal/ToolSeparator.qml
@@ -0,0 +1,26 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ToolSeparator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ leftPadding: vertical ? 16 : 12
+ rightPadding: vertical ? 15 : 12
+ topPadding: vertical ? 12 : 16
+ bottomPadding: vertical ? 12 : 15
+
+ contentItem: Rectangle {
+ implicitWidth: control.vertical ? 1 : 20
+ implicitHeight: control.vertical ? 20 : 1
+ color: control.Universal.baseMediumLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/ToolTip.qml b/src/quickcontrols/universal/ToolTip.qml
new file mode 100644
index 0000000000..af1d49586e
--- /dev/null
+++ b/src/quickcontrols/universal/ToolTip.qml
@@ -0,0 +1,39 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+T.ToolTip {
+ id: control
+
+ x: parent ? (parent.width - implicitWidth) / 2 : 0
+ y: -implicitHeight - 16
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ margins: 8
+ padding: 8
+ topPadding: padding - 3
+ bottomPadding: padding - 1
+
+ closePolicy: T.Popup.CloseOnEscape | T.Popup.CloseOnPressOutsideParent | T.Popup.CloseOnReleaseOutsideParent
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ wrapMode: Text.Wrap
+ opacity: enabled ? 1.0 : 0.2
+ color: control.Universal.foreground
+ }
+
+ background: Rectangle {
+ color: control.Universal.chromeMediumLowColor
+ border.color: control.Universal.chromeHighColor
+ border.width: 1 // ToolTipBorderThemeThickness
+ }
+}
diff --git a/src/quickcontrols/universal/Tumbler.qml b/src/quickcontrols/universal/Tumbler.qml
new file mode 100644
index 0000000000..03b5fcca63
--- /dev/null
+++ b/src/quickcontrols/universal/Tumbler.qml
@@ -0,0 +1,45 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.impl
+
+T.Tumbler {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ delegate: Text {
+ text: modelData
+ font: control.font
+ color: control.Universal.foreground
+ opacity: (1.0 - Math.abs(Tumbler.displacement) / (control.visibleItemCount / 2)) * (control.enabled ? 1 : 0.6)
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ required property var modelData
+ required property int index
+ }
+
+ contentItem: TumblerView {
+ implicitWidth: 60
+ implicitHeight: 200
+ model: control.model
+ delegate: control.delegate
+ path: Path {
+ startX: control.contentItem.width / 2
+ startY: -control.contentItem.delegateHeight / 2
+ PathLine {
+ x: control.contentItem.width / 2
+ y: (control.visibleItemCount + 1) * control.contentItem.delegateHeight - control.contentItem.delegateHeight / 2
+ }
+ }
+
+ property real delegateHeight: control.availableHeight / control.visibleItemCount
+ }
+}
diff --git a/src/quickcontrols/universal/VerticalHeaderView.qml b/src/quickcontrols/universal/VerticalHeaderView.qml
new file mode 100644
index 0000000000..189bed0906
--- /dev/null
+++ b/src/quickcontrols/universal/VerticalHeaderView.qml
@@ -0,0 +1,36 @@
+// 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
+
+import QtQuick
+import QtQuick.Controls.impl
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+import QtQuick.Controls.Universal.impl
+
+T.VerticalHeaderView {
+ id: control
+
+ implicitWidth: contentWidth
+ implicitHeight: syncView ? syncView.height : 0
+
+ delegate: Rectangle {
+ // Qt6: add cellPadding (and font etc) as public API in headerview
+ readonly property real cellPadding: 8
+
+ implicitWidth: Math.max(control.width, text.implicitWidth + (cellPadding * 2))
+ implicitHeight: text.implicitHeight + (cellPadding * 2)
+ color: control.Universal.background
+
+ Text {
+ id: text
+ text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole]
+ : model[control.textRole])
+ : modelData
+ width: parent.width
+ height: parent.height
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2)
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/images/checkmark.png b/src/quickcontrols/universal/images/checkmark.png
new file mode 100644
index 0000000000..e2aae6fe0f
--- /dev/null
+++ b/src/quickcontrols/universal/images/checkmark.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/checkmark@2x.png b/src/quickcontrols/universal/images/checkmark@2x.png
new file mode 100644
index 0000000000..0df4159a7c
--- /dev/null
+++ b/src/quickcontrols/universal/images/checkmark@2x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/checkmark@3x.png b/src/quickcontrols/universal/images/checkmark@3x.png
new file mode 100644
index 0000000000..43466cbcb6
--- /dev/null
+++ b/src/quickcontrols/universal/images/checkmark@3x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/checkmark@4x.png b/src/quickcontrols/universal/images/checkmark@4x.png
new file mode 100644
index 0000000000..7a47bd2159
--- /dev/null
+++ b/src/quickcontrols/universal/images/checkmark@4x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/downarrow.png b/src/quickcontrols/universal/images/downarrow.png
new file mode 100644
index 0000000000..b66e2efc22
--- /dev/null
+++ b/src/quickcontrols/universal/images/downarrow.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/downarrow@2x.png b/src/quickcontrols/universal/images/downarrow@2x.png
new file mode 100644
index 0000000000..a704376c8f
--- /dev/null
+++ b/src/quickcontrols/universal/images/downarrow@2x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/downarrow@3x.png b/src/quickcontrols/universal/images/downarrow@3x.png
new file mode 100644
index 0000000000..3b6d55ab4c
--- /dev/null
+++ b/src/quickcontrols/universal/images/downarrow@3x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/downarrow@4x.png b/src/quickcontrols/universal/images/downarrow@4x.png
new file mode 100644
index 0000000000..818c6b24ff
--- /dev/null
+++ b/src/quickcontrols/universal/images/downarrow@4x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/leftarrow.png b/src/quickcontrols/universal/images/leftarrow.png
new file mode 100644
index 0000000000..0153ccd421
--- /dev/null
+++ b/src/quickcontrols/universal/images/leftarrow.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/leftarrow@2x.png b/src/quickcontrols/universal/images/leftarrow@2x.png
new file mode 100644
index 0000000000..fa692d5b0f
--- /dev/null
+++ b/src/quickcontrols/universal/images/leftarrow@2x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/leftarrow@3x.png b/src/quickcontrols/universal/images/leftarrow@3x.png
new file mode 100644
index 0000000000..06b0207a60
--- /dev/null
+++ b/src/quickcontrols/universal/images/leftarrow@3x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/leftarrow@4x.png b/src/quickcontrols/universal/images/leftarrow@4x.png
new file mode 100644
index 0000000000..1049f616e4
--- /dev/null
+++ b/src/quickcontrols/universal/images/leftarrow@4x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/rightarrow.png b/src/quickcontrols/universal/images/rightarrow.png
new file mode 100644
index 0000000000..b24d117d79
--- /dev/null
+++ b/src/quickcontrols/universal/images/rightarrow.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/rightarrow@2x.png b/src/quickcontrols/universal/images/rightarrow@2x.png
new file mode 100644
index 0000000000..80aca7c18f
--- /dev/null
+++ b/src/quickcontrols/universal/images/rightarrow@2x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/rightarrow@3x.png b/src/quickcontrols/universal/images/rightarrow@3x.png
new file mode 100644
index 0000000000..ba01724065
--- /dev/null
+++ b/src/quickcontrols/universal/images/rightarrow@3x.png
Binary files differ
diff --git a/src/quickcontrols/universal/images/rightarrow@4x.png b/src/quickcontrols/universal/images/rightarrow@4x.png
new file mode 100644
index 0000000000..21f7ed4d15
--- /dev/null
+++ b/src/quickcontrols/universal/images/rightarrow@4x.png
Binary files differ
diff --git a/src/quickcontrols/universal/impl/CMakeLists.txt b/src/quickcontrols/universal/impl/CMakeLists.txt
new file mode 100644
index 0000000000..078e42e217
--- /dev/null
+++ b/src/quickcontrols/universal/impl/CMakeLists.txt
@@ -0,0 +1,39 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+#####################################################################
+## qtquickcontrols2universalstyleimplplugin Plugin:
+#####################################################################
+
+set(qml_files
+ "CheckIndicator.qml"
+ "RadioIndicator.qml"
+ "SwitchIndicator.qml"
+)
+
+qt_internal_add_qml_module(qtquickcontrols2universalstyleimplplugin
+ URI "QtQuick.Controls.Universal.impl"
+ VERSION "${PROJECT_VERSION}"
+ PAST_MAJOR_VERSIONS 2
+ CLASS_NAME QtQuickControls2UniversalStyleImplPlugin
+ DEPENDENCIES
+ QtQuick/auto
+ PLUGIN_TARGET qtquickcontrols2universalstyleimplplugin
+ NO_PLUGIN_OPTIONAL
+ SOURCES
+ qquickuniversalbusyindicator.cpp qquickuniversalbusyindicator_p.h
+ qquickuniversalfocusrectangle.cpp qquickuniversalfocusrectangle_p.h
+ qquickuniversalprogressbar.cpp qquickuniversalprogressbar_p.h
+ QML_FILES
+ ${qml_files}
+ DEFINES
+ QT_NO_CAST_FROM_ASCII
+ QT_NO_CAST_TO_ASCII
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::Gui
+ Qt::QmlPrivate
+ Qt::QuickControls2ImplPrivate
+ Qt::QuickPrivate
+ Qt::QuickTemplates2Private
+)
diff --git a/src/quickcontrols/universal/impl/CheckIndicator.qml b/src/quickcontrols/universal/impl/CheckIndicator.qml
new file mode 100644
index 0000000000..b78e57570d
--- /dev/null
+++ b/src/quickcontrols/universal/impl/CheckIndicator.qml
@@ -0,0 +1,48 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.impl
+import QtQuick.Controls.Universal
+
+Rectangle {
+ id: indicator
+ implicitWidth: 20
+ implicitHeight: 20
+
+ color: !control.enabled ? "transparent" :
+ control.down && !partiallyChecked ? control.Universal.baseMediumColor :
+ control.checkState === Qt.Checked ? control.Universal.accent : "transparent"
+ border.color: !control.enabled ? control.Universal.baseLowColor :
+ control.down ? control.Universal.baseMediumColor :
+ control.checked ? control.Universal.accent : control.Universal.baseMediumHighColor
+ border.width: 2 // CheckBoxBorderThemeThickness
+
+ property Item control
+ readonly property bool partiallyChecked: control.checkState === Qt.PartiallyChecked
+
+ ColorImage {
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+
+ visible: indicator.control.checkState === Qt.Checked
+ color: !indicator.control.enabled ? indicator.control.Universal.baseLowColor : indicator.control.Universal.chromeWhiteColor
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Universal/images/checkmark.png"
+ }
+
+ Rectangle {
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: indicator.partiallyChecked ? parent.width / 2 : parent.width
+ height: indicator.partiallyChecked ? parent.height / 2 : parent.height
+
+ visible: !indicator.control.pressed && enabled && indicator.control.hovered || indicator.partiallyChecked
+ color: !indicator.partiallyChecked ? "transparent" :
+ !indicator.control.enabled ? indicator.control.Universal.baseLowColor :
+ indicator.control.down ? indicator.control.Universal.baseMediumColor :
+ indicator.control.hovered ? indicator.control.Universal.baseHighColor : indicator.control.Universal.baseMediumHighColor
+ border.width: indicator.partiallyChecked ? 0 : 2 // CheckBoxBorderThemeThickness
+ border.color: indicator.control.Universal.baseMediumLowColor
+ }
+}
diff --git a/src/quickcontrols/universal/impl/RadioIndicator.qml b/src/quickcontrols/universal/impl/RadioIndicator.qml
new file mode 100644
index 0000000000..73fc2e964f
--- /dev/null
+++ b/src/quickcontrols/universal/impl/RadioIndicator.qml
@@ -0,0 +1,47 @@
+// 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
+
+import QtQuick
+import QtQuick.Controls.Universal
+
+Rectangle {
+ id: indicator
+ implicitWidth: 20
+ implicitHeight: 20
+ radius: width / 2
+ color: "transparent"
+ border.width: 2 // RadioButtonBorderThemeThickness
+ border.color: control.checked ? "transparent" :
+ !control.enabled ? control.Universal.baseLowColor :
+ control.down ? control.Universal.baseMediumColor :
+ control.hovered ? control.Universal.baseHighColor : control.Universal.baseMediumHighColor
+
+ property var control
+
+ Rectangle {
+ id: checkOuterEllipse
+ width: parent.width
+ height: parent.height
+
+ radius: width / 2
+ opacity: indicator.control.checked ? 1 : 0
+ color: "transparent"
+ border.width: 2 // RadioButtonBorderThemeThickness
+ border.color: !indicator.control.enabled ? indicator.control.Universal.baseLowColor :
+ indicator.control.down ? indicator.control.Universal.baseMediumColor : indicator.control.Universal.accent
+ }
+
+ Rectangle {
+ id: checkGlyph
+ x: (parent.width - width) / 2
+ y: (parent.height - height) / 2
+ width: parent.width / 2
+ height: parent.height / 2
+
+ radius: width / 2
+ opacity: indicator.control.checked ? 1 : 0
+ color: !indicator.control.enabled ? indicator.control.Universal.baseLowColor :
+ indicator.control.down ? indicator.control.Universal.baseMediumColor :
+ indicator.control.hovered ? indicator.control.Universal.baseHighColor : indicator.control.Universal.baseMediumHighColor
+ }
+}
diff --git a/src/quickcontrols/universal/impl/SwitchIndicator.qml b/src/quickcontrols/universal/impl/SwitchIndicator.qml
new file mode 100644
index 0000000000..f88094becc
--- /dev/null
+++ b/src/quickcontrols/universal/impl/SwitchIndicator.qml
@@ -0,0 +1,48 @@
+// 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
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Universal
+
+Item {
+ id: indicator
+ implicitWidth: 44
+ implicitHeight: 20
+
+ property T.AbstractButton control
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+
+ radius: 10
+ color: !indicator.control.enabled ? "transparent" :
+ indicator.control.pressed ? indicator.control.Universal.baseMediumColor :
+ indicator.control.checked ? indicator.control.Universal.accent : "transparent"
+ border.color: !indicator.control.enabled ? indicator.control.Universal.baseLowColor :
+ indicator.control.checked && !indicator.control.pressed ? indicator.control.Universal.accent :
+ indicator.control.hovered && !indicator.control.checked && !indicator.control.pressed ? indicator.control.Universal.baseHighColor : indicator.control.Universal.baseMediumColor
+ opacity: enabled && indicator.control.hovered && indicator.control.checked && !indicator.control.pressed ? (indicator.control.Universal.theme === Universal.Light ? 0.7 : 0.9) : 1.0
+ border.width: 2
+ }
+
+ Rectangle {
+ width: 10
+ height: 10
+ radius: 5
+
+ color: !indicator.control.enabled ? indicator.control.Universal.baseLowColor :
+ indicator.control.pressed || indicator.control.checked ? indicator.control.Universal.chromeWhiteColor :
+ indicator.control.hovered && !indicator.control.checked ? indicator.control.Universal.baseHighColor : indicator.control.Universal.baseMediumHighColor
+
+ x: Math.max(5, Math.min(parent.width - width - 5,
+ indicator.control.visualPosition * parent.width - (width / 2)))
+ y: (parent.height - height) / 2
+
+ Behavior on x {
+ enabled: !indicator.control.pressed
+ SmoothedAnimation { velocity: 200 }
+ }
+ }
+}
diff --git a/src/quickcontrols/universal/impl/qquickuniversalbusyindicator.cpp b/src/quickcontrols/universal/impl/qquickuniversalbusyindicator.cpp
new file mode 100644
index 0000000000..d0fdd925cd
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalbusyindicator.cpp
@@ -0,0 +1,220 @@
+// 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
+
+#include "qquickuniversalbusyindicator_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qeasingcurve.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int PhaseCount = 6;
+static const int Interval = 167;
+static const int TotalDuration = 4052;
+
+class QQuickUniversalBusyIndicatorNode : public QQuickAnimatedNode
+{
+public:
+ QQuickUniversalBusyIndicatorNode(QQuickUniversalBusyIndicator *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+
+private:
+ struct Phase {
+ Phase() = default;
+ Phase(int d, qreal f, qreal t, QEasingCurve::Type c) : duration(d), from(f), to(t), curve(c) { }
+ int duration = 0;
+ qreal from = 0;
+ qreal to = 0;
+ QEasingCurve curve = QEasingCurve::Linear;
+ };
+
+ Phase m_phases[PhaseCount];
+};
+
+QQuickUniversalBusyIndicatorNode::QQuickUniversalBusyIndicatorNode(QQuickUniversalBusyIndicator *item)
+ : QQuickAnimatedNode(item)
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+ setCurrentTime(item->elapsed());
+
+ m_phases[0] = Phase(433, -110, 10, QEasingCurve::BezierSpline);
+ m_phases[1] = Phase(767, 10, 93, QEasingCurve::Linear );
+ m_phases[2] = Phase(417, 93, 205, QEasingCurve::BezierSpline);
+ m_phases[3] = Phase(400, 205, 357, QEasingCurve::BezierSpline);
+ m_phases[4] = Phase(766, 357, 439, QEasingCurve::Linear );
+ m_phases[5] = Phase(434, 439, 585, QEasingCurve::BezierSpline);
+
+ m_phases[0].curve.addCubicBezierSegment(QPointF(0.02, 0.33), QPointF(0.38, 0.77), QPointF(1.00, 1.00));
+ m_phases[2].curve.addCubicBezierSegment(QPointF(0.57, 0.17), QPointF(0.95, 0.75), QPointF(1.00, 1.00));
+ m_phases[3].curve.addCubicBezierSegment(QPointF(0.00, 0.19), QPointF(0.07, 0.72), QPointF(1.00, 1.00));
+ m_phases[5].curve.addCubicBezierSegment(QPointF(0.00, 0.00), QPointF(0.95, 0.37), QPointF(1.00, 1.00));
+}
+
+void QQuickUniversalBusyIndicatorNode::updateCurrentTime(int time)
+{
+ int nodeIndex = 0;
+ int count = childCount();
+ QSGTransformNode *transformNode = static_cast<QSGTransformNode *>(firstChild());
+ while (transformNode) {
+ Q_ASSERT(transformNode->type() == QSGNode::TransformNodeType);
+
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(transformNode->firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ int begin = nodeIndex * Interval;
+ int end = TotalDuration - (PhaseCount - nodeIndex - 1) * Interval;
+
+ bool visible = time >= begin && time <= end;
+ opacityNode->setOpacity(visible ? 1.0 : 0.0);
+
+ if (visible) {
+ int phaseIndex, remain = time, elapsed = 0;
+ for (phaseIndex = 0; phaseIndex < PhaseCount - 1; ++phaseIndex) {
+ if (remain <= m_phases[phaseIndex].duration + begin)
+ break;
+ remain -= m_phases[phaseIndex].duration;
+ elapsed += m_phases[phaseIndex].duration;
+ }
+
+ const Phase &phase = m_phases[phaseIndex];
+
+ qreal from = phase.from - nodeIndex * count;
+ qreal to = phase.to - nodeIndex * count;
+ qreal pos = time - elapsed - begin;
+
+ qreal value = phase.curve.valueForProgress(pos / phase.duration);
+ qreal rotation = from + (to - from) * value;
+
+ QMatrix4x4 matrix;
+ matrix.rotate(rotation, 0, 0, 1);
+ transformNode->setMatrix(matrix);
+ }
+
+ transformNode = static_cast<QSGTransformNode *>(transformNode->nextSibling());
+ ++nodeIndex;
+ }
+}
+
+void QQuickUniversalBusyIndicatorNode::sync(QQuickItem *item)
+{
+ QQuickUniversalBusyIndicator *indicator = static_cast<QQuickUniversalBusyIndicator *>(item);
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+
+ QMatrix4x4 matrix;
+ matrix.translate(item->width() / 2, item->height() / 2);
+ setMatrix(matrix);
+
+ qreal size = qMin(item->width(), item->height());
+ qreal diameter = size / 10.0;
+ qreal radius = diameter / 2;
+ qreal offset = (size - diameter * 2) / M_PI;
+ const QRectF rect(offset, offset, diameter, diameter);
+
+ int count = indicator->count();
+ QSGNode *transformNode = firstChild();
+ for (int i = 0; i < count; ++i) {
+ if (!transformNode) {
+ transformNode = new QSGTransformNode;
+ appendChildNode(transformNode);
+
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ transformNode->appendChildNode(opacityNode);
+
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ opacityNode->appendChildNode(rectNode);
+ }
+
+ QSGNode *opacityNode = transformNode->firstChild();
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ rectNode->setRect(rect);
+ rectNode->setColor(indicator->color());
+ rectNode->setRadius(radius);
+ rectNode->update();
+
+ transformNode = transformNode->nextSibling();
+ }
+
+ while (transformNode) {
+ QSGNode *nextSibling = transformNode->nextSibling();
+ delete transformNode;
+ transformNode = nextSibling;
+ }
+}
+
+QQuickUniversalBusyIndicator::QQuickUniversalBusyIndicator(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+int QQuickUniversalBusyIndicator::count() const
+{
+ return m_count;
+}
+
+void QQuickUniversalBusyIndicator::setCount(int count)
+{
+ if (m_count == count)
+ return;
+
+ m_count = count;
+ update();
+}
+
+QColor QQuickUniversalBusyIndicator::color() const
+{
+ return m_color;
+}
+
+void QQuickUniversalBusyIndicator::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+int QQuickUniversalBusyIndicator::elapsed() const
+{
+ return m_elapsed;
+}
+
+void QQuickUniversalBusyIndicator::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickUniversalBusyIndicator::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
+{
+ QQuickUniversalBusyIndicatorNode *node = static_cast<QQuickUniversalBusyIndicatorNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node) {
+ node = new QQuickUniversalBusyIndicatorNode(this);
+ node->start();
+ }
+ node->sync(this);
+ } else {
+ m_elapsed = node ? node->currentTime() : 0;
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickuniversalbusyindicator_p.cpp"
diff --git a/src/quickcontrols/universal/impl/qquickuniversalbusyindicator_p.h b/src/quickcontrols/universal/impl/qquickuniversalbusyindicator_p.h
new file mode 100644
index 0000000000..1000bbab09
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalbusyindicator_p.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2021 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 QQUICKUNIVERSALBUSYINDICATOR_P_H
+#define QQUICKUNIVERSALBUSYINDICATOR_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 <QtGui/qcolor.h>
+#include <QtQuick/qquickitem.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickUniversalBusyIndicator : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(int count READ count WRITE setCount FINAL)
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
+ QML_NAMED_ELEMENT(BusyIndicatorImpl)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickUniversalBusyIndicator(QQuickItem *parent = nullptr);
+
+ int count() const;
+ void setCount(int count);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ int elapsed() const;
+
+protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
+
+private:
+ int m_count = 5;
+ int m_elapsed = 0;
+ QColor m_color = Qt::black;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickUniversalBusyIndicator)
+
+#endif // QQUICKUNIVERSALBUSYINDICATOR_P_H
diff --git a/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle.cpp b/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle.cpp
new file mode 100644
index 0000000000..9b815b9147
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle.cpp
@@ -0,0 +1,53 @@
+// 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
+
+#include "qquickuniversalfocusrectangle_p.h"
+
+#include <QtGui/qpixmap.h>
+#include <QtGui/qpainter.h>
+#include <QtGui/qpixmapcache.h>
+#include <QtQuick/private/qquickitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQuickUniversalFocusRectangle::QQuickUniversalFocusRectangle(QQuickItem *parent)
+ : QQuickPaintedItem(parent)
+{
+ QQuickItemPrivate::get(this)->setTransparentForPositioner(true);
+}
+
+void QQuickUniversalFocusRectangle::paint(QPainter *painter)
+{
+ if (!isVisible() || width() <= 0 || height() <= 0)
+ return;
+
+ QRect bounds = boundingRect().toAlignedRect();
+ const int boundsWidth = bounds.width();
+ const int boundsHeight = bounds.width();
+ const QString key = QStringLiteral("qquickuniversalfocusrectangle_%1_%2").arg(QString::number(boundsWidth), QString::number(boundsHeight));
+
+ QPixmap pixmap(boundsWidth, boundsHeight);
+ if (!QPixmapCache::find(key, &pixmap)) {
+ bounds.adjust(0, 0, -1, -1);
+ pixmap.fill(Qt::transparent);
+ QPainter p(&pixmap);
+
+ QPen pen;
+ pen.setWidth(1);
+ pen.setColor(Qt::white);
+ p.setPen(pen);
+ p.drawRect(bounds);
+
+ pen.setColor(Qt::black);
+ pen.setDashPattern(QList<qreal>(2, 1));
+ p.setPen(pen);
+ p.drawRect(bounds);
+
+ QPixmapCache::insert(key, pixmap);
+ }
+ painter->drawPixmap(0, 0, pixmap);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickuniversalfocusrectangle_p.cpp"
diff --git a/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle_p.h b/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle_p.h
new file mode 100644
index 0000000000..909c566722
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalfocusrectangle_p.h
@@ -0,0 +1,37 @@
+// Copyright (C) 2021 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 QQUICKUNIVERSALFOCUSRECTANGLE_P_H
+#define QQUICKUNIVERSALFOCUSRECTANGLE_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 <QtQuick/qquickpainteditem.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickUniversalFocusRectangle : public QQuickPaintedItem
+{
+ Q_OBJECT
+ QML_NAMED_ELEMENT(FocusRectangle)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ QQuickUniversalFocusRectangle(QQuickItem *parent = nullptr);
+
+ void paint(QPainter *painter) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKUNIVERSALFOCUSRECTANGLE_P_H
diff --git a/src/quickcontrols/universal/impl/qquickuniversalprogressbar.cpp b/src/quickcontrols/universal/impl/qquickuniversalprogressbar.cpp
new file mode 100644
index 0000000000..0ab47e8804
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalprogressbar.cpp
@@ -0,0 +1,307 @@
+// 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
+
+#include "qquickuniversalprogressbar_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qeasingcurve.h>
+#include <QtQuick/private/qquickitem_p.h>
+#include <QtQuick/private/qsgadaptationlayer_p.h>
+#include <QtQuick/qsgrectanglenode.h>
+#include <QtQuickControls2Impl/private/qquickanimatednode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int PhaseCount = 4;
+static const int EllipseCount = 5;
+static const int Interval = 167;
+static const int TotalDuration = 3917;
+static const int VisibleDuration = 3000;
+static const qreal EllipseDiameter = 4;
+static const qreal EllipseOffset = 4;
+static const qreal ContainerAnimationStartPosition = -34; // absolute
+static const qreal ContainerAnimationEndPosition = 0.435222; // relative
+static const qreal EllipseAnimationWellPosition = 0.333333333333333; // relative
+static const qreal EllipseAnimationEndPosition = 0.666666666666667; // relative
+
+class QQuickUniversalProgressBarNode : public QQuickAnimatedNode
+{
+public:
+ QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item);
+
+ void updateCurrentTime(int time) override;
+ void sync(QQuickItem *item) override;
+
+private:
+ struct Phase {
+ Phase() = default;
+ Phase(int d, qreal f, qreal t) : duration(d), from(f), to(t) { }
+ int duration = 0;
+ qreal from = 0;
+ qreal to = 0;
+ };
+
+ bool m_indeterminate = false;
+ Phase m_borderPhases[PhaseCount];
+ Phase m_ellipsePhases[PhaseCount];
+};
+
+QQuickUniversalProgressBarNode::QQuickUniversalProgressBarNode(QQuickUniversalProgressBar *item)
+ : QQuickAnimatedNode(item)
+{
+ setLoopCount(Infinite);
+ setDuration(TotalDuration);
+
+ m_borderPhases[0] = Phase( 500, -50, 0);
+ m_borderPhases[1] = Phase(1500, 0, 0);
+ m_borderPhases[2] = Phase(1000, 0, 100);
+ m_borderPhases[3] = Phase( 917, 100, 100);
+
+ m_ellipsePhases[0] = Phase(1000, 0, EllipseAnimationWellPosition);
+ m_ellipsePhases[1] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationWellPosition);
+ m_ellipsePhases[2] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationEndPosition);
+ m_ellipsePhases[3] = Phase(1000, EllipseAnimationWellPosition, EllipseAnimationEndPosition);
+}
+
+void QQuickUniversalProgressBarNode::updateCurrentTime(int time)
+{
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
+ Q_ASSERT(!geometryNode || geometryNode->type() == QSGNode::GeometryNodeType);
+ if (!geometryNode)
+ return;
+
+ QSGTransformNode *gridNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
+ Q_ASSERT(!gridNode || gridNode->type() == QSGNode::TransformNodeType);
+ if (!gridNode)
+ return;
+
+ qreal width = geometryNode->rect().width();
+ {
+ qreal from = ContainerAnimationStartPosition;
+ qreal to = from + ContainerAnimationEndPosition * width;
+ qreal progress = static_cast<qreal>(time) / TotalDuration;
+ qreal dx = from + (to - from) * progress;
+
+ QMatrix4x4 matrix;
+ matrix.translate(dx, 0);
+ gridNode->setMatrix(matrix);
+ }
+
+ int nodeIndex = 0;
+ QSGTransformNode *borderNode = static_cast<QSGTransformNode *>(gridNode->firstChild());
+ while (borderNode) {
+ Q_ASSERT(borderNode->type() == QSGNode::TransformNodeType);
+
+ QSGTransformNode *ellipseNode = static_cast<QSGTransformNode *>(borderNode->firstChild());
+ Q_ASSERT(ellipseNode->type() == QSGNode::TransformNodeType);
+
+ QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(ellipseNode->firstChild());
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ int begin = nodeIndex * Interval;
+ int end = VisibleDuration + nodeIndex * Interval;
+
+ bool visible = time >= begin && time <= end;
+ opacityNode->setOpacity(visible ? 1.0 : 0.0);
+
+ if (visible) {
+ {
+ int phaseIndex, remain = time, elapsed = 0;
+ for (phaseIndex = 0; phaseIndex < PhaseCount - 1; ++phaseIndex) {
+ if (remain <= m_borderPhases[phaseIndex].duration + begin)
+ break;
+ remain -= m_borderPhases[phaseIndex].duration;
+ elapsed += m_borderPhases[phaseIndex].duration;
+ }
+
+ const Phase &phase = m_borderPhases[phaseIndex];
+
+ qreal pos = time - elapsed - begin;
+ qreal progress = pos / phase.duration;
+ qreal dx = phase.from + (phase.to - phase.from) * progress;
+
+ QMatrix4x4 matrix;
+ matrix.translate(dx, 0);
+ borderNode->setMatrix(matrix);
+ }
+
+ {
+ QEasingCurve curve(QEasingCurve::BezierSpline);
+ curve.addCubicBezierSegment(QPointF(0.4, 0.0), QPointF(0.6, 1.0), QPointF(1.0, 1.0));
+
+ int phaseIndex, remain = time, elapsed = 0;
+ for (phaseIndex = 0; phaseIndex < PhaseCount - 1; ++phaseIndex) {
+ if (remain <= m_ellipsePhases[phaseIndex].duration + begin)
+ break;
+ remain -= m_ellipsePhases[phaseIndex].duration;
+ elapsed += m_ellipsePhases[phaseIndex].duration;
+ }
+
+ const Phase &phase = m_ellipsePhases[phaseIndex];
+
+ qreal from = phase.from * width;
+ qreal to = phase.to * width;
+ qreal pos = time - elapsed - begin;
+ qreal progress = curve.valueForProgress(pos / phase.duration);
+ qreal dx = from + (to - from) * progress;
+
+ QMatrix4x4 matrix;
+ matrix.translate(dx, 0);
+ ellipseNode->setMatrix(matrix);
+ }
+ }
+
+ borderNode = static_cast<QSGTransformNode *>(borderNode->nextSibling());
+ ++nodeIndex;
+ }
+}
+
+void QQuickUniversalProgressBarNode::sync(QQuickItem *item)
+{
+ QQuickUniversalProgressBar *bar = static_cast<QQuickUniversalProgressBar *>(item);
+ if (m_indeterminate != bar->isIndeterminate()) {
+ m_indeterminate = bar->isIndeterminate();
+ if (m_indeterminate)
+ start();
+ else
+ stop();
+ }
+
+ QQuickItemPrivate *d = QQuickItemPrivate::get(item);
+
+ QRectF bounds = item->boundingRect();
+ bounds.setHeight(item->implicitHeight());
+ bounds.moveTop((item->height() - bounds.height()) / 2.0);
+ if (!m_indeterminate)
+ bounds.setWidth(bar->progress() * bounds.width());
+
+ QSGRectangleNode *geometryNode = static_cast<QSGRectangleNode *>(firstChild());
+ if (!geometryNode) {
+ geometryNode = item->window()->createRectangleNode();
+ appendChildNode(geometryNode);
+ }
+ geometryNode->setRect(bounds);
+ geometryNode->setColor(m_indeterminate ? Qt::transparent : bar->color());
+
+ if (!m_indeterminate) {
+ while (QSGNode *node = geometryNode->firstChild())
+ delete node;
+ return;
+ }
+
+ QSGTransformNode *gridNode = static_cast<QSGTransformNode *>(geometryNode->firstChild());
+ if (!gridNode) {
+ gridNode = new QSGTransformNode;
+ geometryNode->appendChildNode(gridNode);
+ }
+ Q_ASSERT(gridNode->type() == QSGNode::TransformNodeType);
+
+ QSGNode *borderNode = gridNode->firstChild();
+ for (int i = 0; i < EllipseCount; ++i) {
+ if (!borderNode) {
+ borderNode = new QSGTransformNode;
+ gridNode->appendChildNode(borderNode);
+
+ QSGTransformNode *ellipseNode = new QSGTransformNode;
+ borderNode->appendChildNode(ellipseNode);
+
+ QSGOpacityNode *opacityNode = new QSGOpacityNode;
+ ellipseNode->appendChildNode(opacityNode);
+
+ QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode();
+ rectNode->setAntialiasing(true);
+ rectNode->setRadius(EllipseDiameter / 2);
+ opacityNode->appendChildNode(rectNode);
+ }
+ Q_ASSERT(borderNode->type() == QSGNode::TransformNodeType);
+
+ QSGNode *ellipseNode = borderNode->firstChild();
+ Q_ASSERT(ellipseNode->type() == QSGNode::TransformNodeType);
+
+ QSGNode *opacityNode = ellipseNode->firstChild();
+ Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType);
+
+ QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild());
+ Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType);
+
+ rectNode->setRect(QRectF((EllipseCount - i - 1) * (EllipseDiameter + EllipseOffset), (item->height() - EllipseDiameter) / 2, EllipseDiameter, EllipseDiameter));
+ rectNode->setColor(bar->color());
+ rectNode->update();
+
+ borderNode = borderNode->nextSibling();
+ }
+}
+
+QQuickUniversalProgressBar::QQuickUniversalProgressBar(QQuickItem *parent)
+ : QQuickItem(parent)
+{
+ setFlag(ItemHasContents);
+}
+
+QColor QQuickUniversalProgressBar::color() const
+{
+ return m_color;
+}
+
+void QQuickUniversalProgressBar::setColor(const QColor &color)
+{
+ if (m_color == color)
+ return;
+
+ m_color = color;
+ update();
+}
+
+qreal QQuickUniversalProgressBar::progress() const
+{
+ return m_progress;
+}
+
+void QQuickUniversalProgressBar::setProgress(qreal progress)
+{
+ if (progress == m_progress)
+ return;
+
+ m_progress = progress;
+ update();
+}
+
+bool QQuickUniversalProgressBar::isIndeterminate() const
+{
+ return m_indeterminate;
+}
+
+void QQuickUniversalProgressBar::setIndeterminate(bool indeterminate)
+{
+ if (indeterminate == m_indeterminate)
+ return;
+
+ m_indeterminate = indeterminate;
+ setClip(m_indeterminate);
+ update();
+}
+
+void QQuickUniversalProgressBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
+{
+ QQuickItem::itemChange(change, data);
+ if (change == ItemVisibleHasChanged)
+ update();
+}
+
+QSGNode *QQuickUniversalProgressBar::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
+{
+ QQuickUniversalProgressBarNode *node = static_cast<QQuickUniversalProgressBarNode *>(oldNode);
+ if (isVisible() && width() > 0 && height() > 0) {
+ if (!node)
+ node = new QQuickUniversalProgressBarNode(this);
+ node->sync(this);
+ } else {
+ delete node;
+ node = nullptr;
+ }
+ return node;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickuniversalprogressbar_p.cpp"
diff --git a/src/quickcontrols/universal/impl/qquickuniversalprogressbar_p.h b/src/quickcontrols/universal/impl/qquickuniversalprogressbar_p.h
new file mode 100644
index 0000000000..a4bbae8cb5
--- /dev/null
+++ b/src/quickcontrols/universal/impl/qquickuniversalprogressbar_p.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2021 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 QQUICKUNIVERSALPROGRESSBAR_P_H
+#define QQUICKUNIVERSALPROGRESSBAR_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 <QtGui/qcolor.h>
+#include <QtQuick/qquickitem.h>
+#include <QtCore/private/qglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickUniversalProgressBar : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QColor color READ color WRITE setColor FINAL)
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress FINAL)
+ Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate FINAL)
+ QML_NAMED_ELEMENT(ProgressBarImpl)
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickUniversalProgressBar(QQuickItem *parent = nullptr);
+
+ QColor color() const;
+ void setColor(const QColor &color);
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ bool isIndeterminate() const;
+ void setIndeterminate(bool indeterminate);
+
+protected:
+ void itemChange(ItemChange change, const ItemChangeData &data) override;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override;
+
+private:
+ QColor m_color = Qt::black;
+ qreal m_progress = 0.0;
+ bool m_indeterminate = false;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QQuickUniversalProgressBar)
+
+#endif // QQUICKUNIVERSALPROGRESSBAR_P_H
diff --git a/src/quickcontrols/universal/qquickuniversalstyle.cpp b/src/quickcontrols/universal/qquickuniversalstyle.cpp
new file mode 100644
index 0000000000..cacf20a75f
--- /dev/null
+++ b/src/quickcontrols/universal/qquickuniversalstyle.cpp
@@ -0,0 +1,587 @@
+// 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
+
+#include "qquickuniversalstyle_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtQml/qqmlinfo.h>
+#include <QtQuickControls2/private/qquickstyle_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QRgb qquickuniversal_light_color(QQuickUniversalStyle::SystemColor role)
+{
+ static const QRgb colors[] = {
+ 0xFFFFFFFF, // SystemAltHighColor
+ 0x33FFFFFF, // SystemAltLowColor
+ 0x99FFFFFF, // SystemAltMediumColor
+ 0xCCFFFFFF, // SystemAltMediumHighColor
+ 0x66FFFFFF, // SystemAltMediumLowColor
+ 0xFF000000, // SystemBaseHighColor
+ 0x33000000, // SystemBaseLowColor
+ 0x99000000, // SystemBaseMediumColor
+ 0xCC000000, // SystemBaseMediumHighColor
+ 0x66000000, // SystemBaseMediumLowColor
+ 0xFF171717, // SystemChromeAltLowColor
+ 0xFF000000, // SystemChromeBlackHighColor
+ 0x33000000, // SystemChromeBlackLowColor
+ 0x66000000, // SystemChromeBlackMediumLowColor
+ 0xCC000000, // SystemChromeBlackMediumColor
+ 0xFFCCCCCC, // SystemChromeDisabledHighColor
+ 0xFF7A7A7A, // SystemChromeDisabledLowColor
+ 0xFFCCCCCC, // SystemChromeHighColor
+ 0xFFF2F2F2, // SystemChromeLowColor
+ 0xFFE6E6E6, // SystemChromeMediumColor
+ 0xFFF2F2F2, // SystemChromeMediumLowColor
+ 0xFFFFFFFF, // SystemChromeWhiteColor
+ 0x19000000, // SystemListLowColor
+ 0x33000000 // SystemListMediumColor
+ };
+ return colors[role];
+}
+
+static QRgb qquickuniversal_dark_color(QQuickUniversalStyle::SystemColor role)
+{
+ static const QRgb colors[] = {
+ 0xFF000000, // SystemAltHighColor
+ 0x33000000, // SystemAltLowColor
+ 0x99000000, // SystemAltMediumColor
+ 0xCC000000, // SystemAltMediumHighColor
+ 0x66000000, // SystemAltMediumLowColor
+ 0xFFFFFFFF, // SystemBaseHighColor
+ 0x33FFFFFF, // SystemBaseLowColor
+ 0x99FFFFFF, // SystemBaseMediumColor
+ 0xCCFFFFFF, // SystemBaseMediumHighColor
+ 0x66FFFFFF, // SystemBaseMediumLowColor
+ 0xFFF2F2F2, // SystemChromeAltLowColor
+ 0xFF000000, // SystemChromeBlackHighColor
+ 0x33000000, // SystemChromeBlackLowColor
+ 0x66000000, // SystemChromeBlackMediumLowColor
+ 0xCC000000, // SystemChromeBlackMediumColor
+ 0xFF333333, // SystemChromeDisabledHighColor
+ 0xFF858585, // SystemChromeDisabledLowColor
+ 0xFF767676, // SystemChromeHighColor
+ 0xFF171717, // SystemChromeLowColor
+ 0xFF1F1F1F, // SystemChromeMediumColor
+ 0xFF2B2B2B, // SystemChromeMediumLowColor
+ 0xFFFFFFFF, // SystemChromeWhiteColor
+ 0x19FFFFFF, // SystemListLowColor
+ 0x33FFFFFF // SystemListMediumColor
+ };
+ return colors[role];
+}
+
+static QRgb qquickuniversal_accent_color(QQuickUniversalStyle::Color accent)
+{
+ static const QRgb colors[] = {
+ 0xFFA4C400, // Lime
+ 0xFF60A917, // Green
+ 0xFF008A00, // Emerald
+ 0xFF00ABA9, // Teal
+ 0xFF1BA1E2, // Cyan
+ 0xFF3E65FF, // Cobalt
+ 0xFF6A00FF, // Indigo
+ 0xFFAA00FF, // Violet
+ 0xFFF472D0, // Pink
+ 0xFFD80073, // Magenta
+ 0xFFA20025, // Crimson
+ 0xFFE51400, // Red
+ 0xFFFA6800, // Orange
+ 0xFFF0A30A, // Amber
+ 0xFFE3C800, // Yellow
+ 0xFF825A2C, // Brown
+ 0xFF6D8764, // Olive
+ 0xFF647687, // Steel
+ 0xFF76608A, // Mauve
+ 0xFF87794E // Taupe
+ };
+ return colors[accent];
+}
+
+static QQuickUniversalStyle::Theme qquickuniversal_effective_theme(QQuickUniversalStyle::Theme theme)
+{
+ if (theme == QQuickUniversalStyle::System)
+ theme = QQuickStylePrivate::isDarkSystemTheme() ? QQuickUniversalStyle::Dark : QQuickUniversalStyle::Light;
+ return theme;
+}
+
+// If no value was inherited from a parent or explicitly set, the "global" values are used.
+// The initial, default values of the globals are hard-coded here, but the environment
+// variables and .conf file override them if specified.
+static QQuickUniversalStyle::Theme GlobalTheme = QQuickUniversalStyle::Light;
+static QRgb GlobalAccent = qquickuniversal_accent_color(QQuickUniversalStyle::Cobalt);
+static QRgb GlobalForeground = qquickuniversal_light_color(QQuickUniversalStyle::BaseHigh);
+static QRgb GlobalBackground = qquickuniversal_light_color(QQuickUniversalStyle::AltHigh);
+// These represent whether a global foreground/background was set.
+// Each style's m_hasForeground/m_hasBackground are initialized to these values.
+static bool HasGlobalForeground = false;
+static bool HasGlobalBackground = false;
+
+QQuickUniversalStyle::QQuickUniversalStyle(QObject *parent) : QQuickAttachedPropertyPropagator(parent),
+ m_hasForeground(HasGlobalForeground), m_hasBackground(HasGlobalBackground), m_theme(GlobalTheme),
+ m_accent(GlobalAccent), m_foreground(GlobalForeground), m_background(GlobalBackground)
+{
+ initialize();
+}
+
+QQuickUniversalStyle *QQuickUniversalStyle::qmlAttachedProperties(QObject *object)
+{
+ return new QQuickUniversalStyle(object);
+}
+
+QQuickUniversalStyle::Theme QQuickUniversalStyle::theme() const
+{
+ return m_theme;
+}
+
+void QQuickUniversalStyle::setTheme(Theme theme)
+{
+ theme = qquickuniversal_effective_theme(theme);
+ m_explicitTheme = true;
+ if (m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ emit themeChanged();
+ emit paletteChanged();
+ emit foregroundChanged();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::inheritTheme(Theme theme)
+{
+ if (m_explicitTheme || m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ emit themeChanged();
+ emit paletteChanged();
+ emit foregroundChanged();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::propagateTheme()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritTheme(m_theme);
+ }
+}
+
+void QQuickUniversalStyle::resetTheme()
+{
+ if (!m_explicitTheme)
+ return;
+
+ m_explicitTheme = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritTheme(universal ? universal->theme() : GlobalTheme);
+}
+
+QVariant QQuickUniversalStyle::accent() const
+{
+ return QColor::fromRgba(m_accent);
+}
+
+void QQuickUniversalStyle::setAccent(const QVariant &var)
+{
+ QRgb accent = 0;
+ if (!variantToRgba(var, "accent", &accent))
+ return;
+
+ m_explicitAccent = true;
+ if (m_accent == accent)
+ return;
+
+ m_accent = accent;
+ propagateAccent();
+ emit accentChanged();
+}
+
+void QQuickUniversalStyle::inheritAccent(QRgb accent)
+{
+ if (m_explicitAccent || m_accent == accent)
+ return;
+
+ m_accent = accent;
+ propagateAccent();
+ emit accentChanged();
+}
+
+void QQuickUniversalStyle::propagateAccent()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritAccent(m_accent);
+ }
+}
+
+void QQuickUniversalStyle::resetAccent()
+{
+ if (!m_explicitAccent)
+ return;
+
+ m_explicitAccent = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritAccent(universal ? universal->m_accent : GlobalAccent);
+}
+
+QVariant QQuickUniversalStyle::foreground() const
+{
+ if (m_hasForeground)
+ return QColor::fromRgba(m_foreground);
+ return baseHighColor();
+}
+
+void QQuickUniversalStyle::setForeground(const QVariant &var)
+{
+ QRgb foreground = 0;
+ if (!variantToRgba(var, "foreground", &foreground))
+ return;
+
+ m_hasForeground = true;
+ m_explicitForeground = true;
+ if (m_foreground == foreground)
+ return;
+
+ m_foreground = foreground;
+ propagateForeground();
+ emit foregroundChanged();
+}
+
+void QQuickUniversalStyle::inheritForeground(QRgb foreground, bool has)
+{
+ if (m_explicitForeground || m_foreground == foreground)
+ return;
+
+ m_hasForeground = has;
+ m_foreground = foreground;
+ propagateForeground();
+ emit foregroundChanged();
+}
+
+void QQuickUniversalStyle::propagateForeground()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritForeground(m_foreground, m_hasForeground);
+ }
+}
+
+void QQuickUniversalStyle::resetForeground()
+{
+ if (!m_explicitForeground)
+ return;
+
+ m_hasForeground = false;
+ m_explicitForeground = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritForeground(universal ? universal->m_foreground : GlobalForeground, universal ? universal->m_hasForeground : false);
+}
+
+QVariant QQuickUniversalStyle::background() const
+{
+ if (m_hasBackground)
+ return QColor::fromRgba(m_background);
+ return altHighColor();
+}
+
+void QQuickUniversalStyle::setBackground(const QVariant &var)
+{
+ QRgb background = 0;
+ if (!variantToRgba(var, "background", &background))
+ return;
+
+ m_hasBackground = true;
+ m_explicitBackground = true;
+ if (m_background == background)
+ return;
+
+ m_background = background;
+ propagateBackground();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::inheritBackground(QRgb background, bool has)
+{
+ if (m_explicitBackground || m_background == background)
+ return;
+
+ m_hasBackground = has;
+ m_background = background;
+ propagateBackground();
+ emit backgroundChanged();
+}
+
+void QQuickUniversalStyle::propagateBackground()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(child);
+ if (universal)
+ universal->inheritBackground(m_background, m_hasBackground);
+ }
+}
+
+void QQuickUniversalStyle::resetBackground()
+{
+ if (!m_explicitBackground)
+ return;
+
+ m_hasBackground = false;
+ m_explicitBackground = false;
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(attachedParent());
+ inheritBackground(universal ? universal->m_background : GlobalBackground, universal ? universal->m_hasBackground : false);
+}
+
+QColor QQuickUniversalStyle::color(Color color) const
+{
+ return qquickuniversal_accent_color(color);
+}
+
+QColor QQuickUniversalStyle::altHighColor() const
+{
+ return systemColor(AltHigh);
+}
+
+QColor QQuickUniversalStyle::altLowColor() const
+{
+ return systemColor(AltLow);
+}
+
+QColor QQuickUniversalStyle::altMediumColor() const
+{
+ return systemColor(AltMedium);
+}
+
+QColor QQuickUniversalStyle::altMediumHighColor() const
+{
+ return systemColor(AltMediumHigh);
+}
+
+QColor QQuickUniversalStyle::altMediumLowColor() const
+{
+ return systemColor(AltMediumLow);
+}
+
+QColor QQuickUniversalStyle::baseHighColor() const
+{
+ return systemColor(BaseHigh);
+}
+
+QColor QQuickUniversalStyle::baseLowColor() const
+{
+ return systemColor(BaseLow);
+}
+
+QColor QQuickUniversalStyle::baseMediumColor() const
+{
+ return systemColor(BaseMedium);
+}
+
+QColor QQuickUniversalStyle::baseMediumHighColor() const
+{
+ return systemColor(BaseMediumHigh);
+}
+
+QColor QQuickUniversalStyle::baseMediumLowColor() const
+{
+ return systemColor(BaseMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeAltLowColor() const
+{
+ return systemColor(ChromeAltLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackHighColor() const
+{
+ return systemColor(ChromeBlackHigh);
+}
+
+QColor QQuickUniversalStyle::chromeBlackLowColor() const
+{
+ return systemColor(ChromeBlackLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackMediumLowColor() const
+{
+ return systemColor(ChromeBlackMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeBlackMediumColor() const
+{
+ return systemColor(ChromeBlackMedium);
+}
+
+QColor QQuickUniversalStyle::chromeDisabledHighColor() const
+{
+ return systemColor(ChromeDisabledHigh);
+}
+
+QColor QQuickUniversalStyle::chromeDisabledLowColor() const
+{
+ return systemColor(ChromeDisabledLow);
+}
+
+QColor QQuickUniversalStyle::chromeHighColor() const
+{
+ return systemColor(ChromeHigh);
+}
+
+QColor QQuickUniversalStyle::chromeLowColor() const
+{
+ return systemColor(ChromeLow);
+}
+
+QColor QQuickUniversalStyle::chromeMediumColor() const
+{
+ return systemColor(ChromeMedium);
+}
+
+QColor QQuickUniversalStyle::chromeMediumLowColor() const
+{
+ return systemColor(ChromeMediumLow);
+}
+
+QColor QQuickUniversalStyle::chromeWhiteColor() const
+{
+ return systemColor(ChromeWhite);
+}
+
+QColor QQuickUniversalStyle::listLowColor() const
+{
+ return systemColor(ListLow);
+}
+
+QColor QQuickUniversalStyle::listMediumColor() const
+{
+ return systemColor(ListMedium);
+}
+
+QColor QQuickUniversalStyle::systemColor(SystemColor role) const
+{
+ return QColor::fromRgba(m_theme == QQuickUniversalStyle::Dark ? qquickuniversal_dark_color(role) : qquickuniversal_light_color(role));
+}
+
+void QQuickUniversalStyle::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent)
+{
+ Q_UNUSED(oldParent);
+ QQuickUniversalStyle *universal = qobject_cast<QQuickUniversalStyle *>(newParent);
+ if (universal) {
+ inheritTheme(universal->theme());
+ inheritAccent(universal->m_accent);
+ inheritForeground(universal->m_foreground, universal->m_hasForeground);
+ inheritBackground(universal->m_background, universal->m_hasBackground);
+ }
+}
+
+template <typename Enum>
+static Enum toEnumValue(const QByteArray &value, bool *ok)
+{
+ QMetaEnum enumeration = QMetaEnum::fromType<Enum>();
+ return static_cast<Enum>(enumeration.keyToValue(value, ok));
+}
+
+static QByteArray resolveSetting(const QByteArray &env, const QSharedPointer<QSettings> &settings, const QString &name)
+{
+ QByteArray value = qgetenv(env);
+#if QT_CONFIG(settings)
+ if (value.isNull() && !settings.isNull())
+ value = settings->value(name).toByteArray();
+#endif
+ return value;
+}
+
+void QQuickUniversalStyle::initGlobals()
+{
+ QSharedPointer<QSettings> settings = QQuickStylePrivate::settings(QStringLiteral("Universal"));
+
+ bool ok = false;
+ QByteArray themeValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_THEME", settings, QStringLiteral("Theme"));
+ Theme themeEnum = toEnumValue<Theme>(themeValue, &ok);
+ if (ok)
+ GlobalTheme = qquickuniversal_effective_theme(themeEnum);
+ else if (!themeValue.isEmpty())
+ qWarning().nospace().noquote() << "Universal: unknown theme value: " << themeValue;
+
+ QByteArray accentValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_ACCENT", settings, QStringLiteral("Accent"));
+ Color accentEnum = toEnumValue<Color>(accentValue, &ok);
+ if (ok) {
+ GlobalAccent = qquickuniversal_accent_color(accentEnum);
+ } else if (!accentValue.isEmpty()) {
+ QColor color = QColor::fromString(accentValue);
+ if (color.isValid())
+ GlobalAccent = color.rgba();
+ else
+ qWarning().nospace().noquote() << "Universal: unknown accent value: " << accentValue;
+ }
+
+ QByteArray foregroundValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_FOREGROUND", settings, QStringLiteral("Foreground"));
+ Color foregroundEnum = toEnumValue<Color>(foregroundValue, &ok);
+ if (ok) {
+ GlobalForeground = qquickuniversal_accent_color(foregroundEnum);
+ HasGlobalForeground = true;
+ } else if (!foregroundValue.isEmpty()) {
+ QColor color = QColor::fromString(foregroundValue);
+ if (color.isValid()) {
+ GlobalForeground = color.rgba();
+ HasGlobalForeground = true;
+ } else {
+ qWarning().nospace().noquote() << "Universal: unknown foreground value: " << foregroundValue;
+ }
+ }
+
+ QByteArray backgroundValue = resolveSetting("QT_QUICK_CONTROLS_UNIVERSAL_BACKGROUND", settings, QStringLiteral("Background"));
+ Color backgroundEnum = toEnumValue<Color>(backgroundValue, &ok);
+ if (ok) {
+ GlobalBackground = qquickuniversal_accent_color(backgroundEnum);
+ HasGlobalBackground = true;
+ } else if (!backgroundValue.isEmpty()) {
+ QColor color = QColor::fromString(backgroundValue);
+ if (color.isValid()) {
+ GlobalBackground = color.rgba();
+ HasGlobalBackground = true;
+ } else {
+ qWarning().nospace().noquote() << "Universal: unknown background value: " << backgroundValue;
+ }
+ }
+}
+
+bool QQuickUniversalStyle::variantToRgba(const QVariant &var, const char *name, QRgb *rgba) const
+{
+ if (var.metaType().id() == QMetaType::Int) {
+ int val = var.toInt();
+ if (val < Lime || val > Taupe) {
+ qmlWarning(parent()) << "unknown Universal." << name << " value: " << val;
+ return false;
+ }
+ *rgba = qquickuniversal_accent_color(static_cast<Color>(val));
+ } else {
+ int val = QMetaEnum::fromType<Color>().keyToValue(var.toByteArray());
+ if (val != -1) {
+ *rgba = qquickuniversal_accent_color(static_cast<Color>(val));
+ } else {
+ QColor color = QColor::fromString(var.toString());
+ if (!color.isValid()) {
+ qmlWarning(parent()) << "unknown Universal." << name << " value: " << var.toString();
+ return false;
+ }
+ *rgba = color.rgba();
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qquickuniversalstyle_p.cpp"
diff --git a/src/quickcontrols/universal/qquickuniversalstyle_p.h b/src/quickcontrols/universal/qquickuniversalstyle_p.h
new file mode 100644
index 0000000000..024fde2192
--- /dev/null
+++ b/src/quickcontrols/universal/qquickuniversalstyle_p.h
@@ -0,0 +1,212 @@
+// 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
+
+#ifndef QQUICKUNIVERSALSTYLE_P_H
+#define QQUICKUNIVERSALSTYLE_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 <QtGui/qcolor.h>
+#include <QtQml/qqml.h>
+#include <QtQuickControls2/qquickattachedpropertypropagator.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickUniversalStylePrivate;
+
+class QQuickUniversalStyle : public QQuickAttachedPropertyPropagator
+{
+ Q_OBJECT
+ Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QVariant accent READ accent WRITE setAccent RESET resetAccent NOTIFY accentChanged FINAL)
+ Q_PROPERTY(QVariant foreground READ foreground WRITE setForeground RESET resetForeground NOTIFY foregroundChanged FINAL)
+ Q_PROPERTY(QVariant background READ background WRITE setBackground RESET resetBackground NOTIFY backgroundChanged FINAL)
+
+ Q_PROPERTY(QColor altHighColor READ altHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor altLowColor READ altLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor altMediumColor READ altMediumColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor altMediumHighColor READ altMediumHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor altMediumLowColor READ altMediumLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor baseHighColor READ baseHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor baseLowColor READ baseLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor baseMediumColor READ baseMediumColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor baseMediumHighColor READ baseMediumHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor baseMediumLowColor READ baseMediumLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeAltLowColor READ chromeAltLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeBlackHighColor READ chromeBlackHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeBlackLowColor READ chromeBlackLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeBlackMediumLowColor READ chromeBlackMediumLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeBlackMediumColor READ chromeBlackMediumColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeDisabledHighColor READ chromeDisabledHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeDisabledLowColor READ chromeDisabledLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeHighColor READ chromeHighColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeLowColor READ chromeLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeMediumColor READ chromeMediumColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeMediumLowColor READ chromeMediumLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor chromeWhiteColor READ chromeWhiteColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor listLowColor READ listLowColor NOTIFY paletteChanged FINAL)
+ Q_PROPERTY(QColor listMediumColor READ listMediumColor NOTIFY paletteChanged FINAL)
+
+ QML_NAMED_ELEMENT(Universal)
+ QML_ATTACHED(QQuickUniversalStyle)
+ QML_UNCREATABLE("")
+ QML_ADDED_IN_VERSION(2, 0)
+
+public:
+ explicit QQuickUniversalStyle(QObject *parent = nullptr);
+
+ static QQuickUniversalStyle *qmlAttachedProperties(QObject *object);
+
+ enum Theme { Light, Dark, System };
+ Q_ENUM(Theme)
+
+ Theme theme() const;
+ void setTheme(Theme theme);
+ void inheritTheme(Theme theme);
+ void propagateTheme();
+ void resetTheme();
+
+ enum Color {
+ Lime,
+ Green,
+ Emerald,
+ Teal,
+ Cyan,
+ Cobalt,
+ Indigo,
+ Violet,
+ Pink,
+ Magenta,
+ Crimson,
+ Red,
+ Orange,
+ Amber,
+ Yellow,
+ Brown,
+ Olive,
+ Steel,
+ Mauve,
+ Taupe
+ };
+ Q_ENUM(Color)
+
+ QVariant accent() const;
+ void setAccent(const QVariant &accent);
+ void inheritAccent(QRgb accent);
+ void propagateAccent();
+ void resetAccent();
+
+ QVariant foreground() const;
+ void setForeground(const QVariant &foreground);
+ void inheritForeground(QRgb foreground, bool has);
+ void propagateForeground();
+ void resetForeground();
+
+ QVariant background() const;
+ void setBackground(const QVariant &background);
+ void inheritBackground(QRgb background, bool has);
+ void propagateBackground();
+ void resetBackground();
+
+ Q_INVOKABLE QColor color(Color color) const;
+
+ QColor altHighColor() const;
+ QColor altLowColor() const;
+ QColor altMediumColor() const;
+ QColor altMediumHighColor() const;
+ QColor altMediumLowColor() const;
+ QColor baseHighColor() const;
+ QColor baseLowColor() const;
+ QColor baseMediumColor() const;
+ QColor baseMediumHighColor() const;
+ QColor baseMediumLowColor() const;
+ QColor chromeAltLowColor() const;
+ QColor chromeBlackHighColor() const;
+ QColor chromeBlackLowColor() const;
+ QColor chromeBlackMediumLowColor() const;
+ QColor chromeBlackMediumColor() const;
+ QColor chromeDisabledHighColor() const;
+ QColor chromeDisabledLowColor() const;
+ QColor chromeHighColor() const;
+ QColor chromeLowColor() const;
+ QColor chromeMediumColor() const;
+ QColor chromeMediumLowColor() const;
+ QColor chromeWhiteColor() const;
+ QColor listLowColor() const;
+ QColor listMediumColor() const;
+
+ enum SystemColor {
+ AltHigh,
+ AltLow,
+ AltMedium,
+ AltMediumHigh,
+ AltMediumLow,
+ BaseHigh,
+ BaseLow,
+ BaseMedium,
+ BaseMediumHigh,
+ BaseMediumLow,
+ ChromeAltLow,
+ ChromeBlackHigh,
+ ChromeBlackLow,
+ ChromeBlackMediumLow,
+ ChromeBlackMedium,
+ ChromeDisabledHigh,
+ ChromeDisabledLow,
+ ChromeHigh,
+ ChromeLow,
+ ChromeMedium,
+ ChromeMediumLow,
+ ChromeWhite,
+ ListLow,
+ ListMedium
+ };
+
+ QColor systemColor(SystemColor role) const;
+
+ static void initGlobals();
+
+Q_SIGNALS:
+ void themeChanged();
+ void accentChanged();
+ void foregroundChanged();
+ void backgroundChanged();
+ void paletteChanged();
+
+protected:
+ void attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent) override;
+
+private:
+ bool variantToRgba(const QVariant &var, const char *name, QRgb *rgba) const;
+
+ // These reflect whether a color value was explicitly set on the specific
+ // item that this attached style object represents.
+ bool m_explicitTheme = false;
+ bool m_explicitAccent = false;
+ bool m_explicitForeground = false;
+ bool m_explicitBackground = false;
+ // These will be true when this item has an explicit or inherited foreground/background
+ // color, or these colors were declared globally via settings (e.g. conf or env vars).
+ // Some color properties of the style will return different values depending on whether
+ // or not these are set.
+ bool m_hasForeground = false;
+ bool m_hasBackground = false;
+ // The actual values for this item, whether explicit, inherited or globally set.
+ Theme m_theme = Light;
+ QRgb m_accent = Qt::blue;
+ QRgb m_foreground = Qt::black;
+ QRgb m_background = Qt::white;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKUNIVERSALSTYLE_P_H
diff --git a/src/quickcontrols/universal/qquickuniversaltheme.cpp b/src/quickcontrols/universal/qquickuniversaltheme.cpp
new file mode 100644
index 0000000000..fff5400986
--- /dev/null
+++ b/src/quickcontrols/universal/qquickuniversaltheme.cpp
@@ -0,0 +1,37 @@
+// 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
+
+#include "qquickuniversaltheme_p.h"
+
+#include <QtGui/qfontinfo.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QQuickUniversalTheme::initialize(QQuickTheme *theme)
+{
+ QFont systemFont;
+ QFont groupBoxTitleFont;
+ QFont tabButtonFont;
+
+ const QFont font(QLatin1String("Segoe UI"));
+ if (QFontInfo(font).family() == QLatin1String("Segoe UI")) {
+ const QStringList families{font.family()};
+ systemFont.setFamilies(families);
+ groupBoxTitleFont.setFamilies(families);
+ tabButtonFont.setFamilies(families);
+ }
+
+ systemFont.setPixelSize(15);
+ theme->setFont(QQuickTheme::System, systemFont);
+
+ groupBoxTitleFont.setPixelSize(15);
+ groupBoxTitleFont.setWeight(QFont::DemiBold);
+ theme->setFont(QQuickTheme::GroupBox, groupBoxTitleFont);
+
+ tabButtonFont.setPixelSize(24);
+ tabButtonFont.setWeight(QFont::Light);
+ theme->setFont(QQuickTheme::TabBar, tabButtonFont);
+}
+
+QT_END_NAMESPACE
diff --git a/src/quickcontrols/universal/qquickuniversaltheme_p.h b/src/quickcontrols/universal/qquickuniversaltheme_p.h
new file mode 100644
index 0000000000..84789c5da1
--- /dev/null
+++ b/src/quickcontrols/universal/qquickuniversaltheme_p.h
@@ -0,0 +1,32 @@
+// Copyright (C) 2021 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 QQUICKUNIVERSALTHEME_P_H
+#define QQUICKUNIVERSALTHEME_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>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickTheme;
+
+class QQuickUniversalTheme
+{
+public:
+ static void initialize(QQuickTheme *theme);
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKUNIVERSALTHEME_P_H
diff --git a/src/quickcontrols/universal/qtquickcontrols2universalstyleplugin.cpp b/src/quickcontrols/universal/qtquickcontrols2universalstyleplugin.cpp
new file mode 100644
index 0000000000..683c966833
--- /dev/null
+++ b/src/quickcontrols/universal/qtquickcontrols2universalstyleplugin.cpp
@@ -0,0 +1,48 @@
+// 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
+
+#include "qquickuniversalstyle_p.h"
+#include "qquickuniversaltheme_p.h"
+
+#include <QtQuickControls2/private/qquickstyleplugin_p.h>
+#include <QtQuickTemplates2/private/qquicktheme_p.h>
+
+QT_BEGIN_NAMESPACE
+
+extern void qml_register_types_QtQuick_Controls_Universal();
+Q_GHS_KEEP_REFERENCE(qml_register_types_QtQuick_Controls_Universal);
+
+class QtQuickControls2UniversalStylePlugin : public QQuickStylePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ QtQuickControls2UniversalStylePlugin(QObject *parent = nullptr);
+
+ QString name() const override;
+ void initializeTheme(QQuickTheme *theme) override;
+
+ QQuickUniversalTheme theme;
+};
+
+QtQuickControls2UniversalStylePlugin::QtQuickControls2UniversalStylePlugin(QObject *parent) : QQuickStylePlugin(parent)
+{
+ volatile auto registration = &qml_register_types_QtQuick_Controls_Universal;
+ Q_UNUSED(registration);
+}
+
+QString QtQuickControls2UniversalStylePlugin::name() const
+{
+ return QStringLiteral("Universal");
+}
+
+void QtQuickControls2UniversalStylePlugin::initializeTheme(QQuickTheme *theme)
+{
+ QQuickUniversalStyle::initGlobals();
+ this->theme.initialize(theme);
+}
+
+QT_END_NAMESPACE
+
+#include "qtquickcontrols2universalstyleplugin.moc"