aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/quickcontrols/windows')
-rw-r--r--src/quickcontrols/windows/ApplicationWindow.qml9
-rw-r--r--src/quickcontrols/windows/CMakeLists.txt24
-rw-r--r--src/quickcontrols/windows/CheckDelegate.qml75
-rw-r--r--src/quickcontrols/windows/ComboBox.qml7
-rw-r--r--src/quickcontrols/windows/DelayButton.qml82
-rw-r--r--src/quickcontrols/windows/ItemDelegate.qml10
-rw-r--r--src/quickcontrols/windows/Menu.qml74
-rw-r--r--src/quickcontrols/windows/MenuBar.qml35
-rw-r--r--src/quickcontrols/windows/MenuBarItem.qml47
-rw-r--r--src/quickcontrols/windows/MenuItem.qml74
-rw-r--r--src/quickcontrols/windows/MenuSeparator.qml23
-rw-r--r--src/quickcontrols/windows/RadioDelegate.qml12
-rw-r--r--src/quickcontrols/windows/RangeSlider.qml105
-rw-r--r--src/quickcontrols/windows/ScrollBar.qml15
-rw-r--r--src/quickcontrols/windows/ScrollIndicator.qml42
-rw-r--r--src/quickcontrols/windows/ScrollView.qml4
-rw-r--r--src/quickcontrols/windows/SpinBox.qml4
-rw-r--r--src/quickcontrols/windows/Switch.qml37
-rw-r--r--src/quickcontrols/windows/SwitchDelegate.qml45
-rw-r--r--src/quickcontrols/windows/images/checkmark.pngbin0 -> 200 bytes
-rw-r--r--src/quickcontrols/windows/images/checkmark@2x.pngbin0 -> 252 bytes
-rw-r--r--src/quickcontrols/windows/images/checkmark@3x.pngbin0 -> 321 bytes
-rw-r--r--src/quickcontrols/windows/images/menuarrow.pngbin0 -> 165 bytes
-rw-r--r--src/quickcontrols/windows/images/menuarrow@2x.pngbin0 -> 185 bytes
-rw-r--r--src/quickcontrols/windows/images/menuarrow@3x.pngbin0 -> 205 bytes
-rw-r--r--src/quickcontrols/windows/impl/CMakeLists.txt22
-rw-r--r--src/quickcontrols/windows/impl/CheckIndicator.qml21
-rw-r--r--src/quickcontrols/windows/impl/SwitchIndicator.qml59
28 files changed, 816 insertions, 10 deletions
diff --git a/src/quickcontrols/windows/ApplicationWindow.qml b/src/quickcontrols/windows/ApplicationWindow.qml
new file mode 100644
index 0000000000..dc3094c009
--- /dev/null
+++ b/src/quickcontrols/windows/ApplicationWindow.qml
@@ -0,0 +1,9 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick.NativeStyle
+import QtQuick.Templates as T
+
+T.ApplicationWindow {
+ color: palette.window
+}
diff --git a/src/quickcontrols/windows/CMakeLists.txt b/src/quickcontrols/windows/CMakeLists.txt
index b5319fef52..36e871abdb 100644
--- a/src/quickcontrols/windows/CMakeLists.txt
+++ b/src/quickcontrols/windows/CMakeLists.txt
@@ -6,16 +6,30 @@
#####################################################################
set(qml_files
+ "ApplicationWindow.qml"
"Button.qml"
"CheckBox.qml"
+ "CheckDelegate.qml"
"ComboBox.qml"
+ "DelayButton.qml"
"Frame.qml"
"GroupBox.qml"
+ "ItemDelegate.qml"
+ "Menu.qml"
+ "MenuBar.qml"
+ "MenuBarItem.qml"
+ "MenuItem.qml"
+ "MenuSeparator.qml"
"ProgressBar.qml"
"RadioButton.qml"
+ "RadioDelegate.qml"
+ "RangeSlider.qml"
+ "ScrollIndicator.qml"
"SelectionRectangle.qml"
"Slider.qml"
"SpinBox.qml"
+ "Switch.qml"
+ "SwitchDelegate.qml"
"TextArea.qml"
"TextField.qml"
"ScrollBar.qml"
@@ -36,6 +50,13 @@ qt_internal_add_qml_module(qtquickcontrols2windowsstyleplugin
qtquickcontrols2windowsstyleplugin.cpp
QML_FILES
${qml_files}
+ RESOURCES
+ images/checkmark.png
+ images/checkmark@2x.png
+ images/checkmark@3x.png
+ images/menuarrow.png
+ images/menuarrow@2x.png
+ images/menuarrow@3x.png
DEFINES
QT_NO_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
@@ -44,10 +65,13 @@ qt_internal_add_qml_module(qtquickcontrols2windowsstyleplugin
Qt::GuiPrivate
Qt::QmlPrivate
Qt::QuickControls2Private
+ Qt::QuickControls2WindowsStyleImpl
Qt::QuickPrivate
Qt::QuickTemplates2Private
)
+add_subdirectory(impl)
+
# Native style is a dependency of the Windows style.
_qt_internal_add_qml_static_plugin_dependency(qtquickcontrols2windowsstyleplugin
qtquickcontrols2nativestyleplugin)
diff --git a/src/quickcontrols/windows/CheckDelegate.qml b/src/quickcontrols/windows/CheckDelegate.qml
new file mode 100644
index 0000000000..ce020161c8
--- /dev/null
+++ b/src/quickcontrols/windows/CheckDelegate.qml
@@ -0,0 +1,75 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls
+import QtQuick.Controls.impl
+import QtQuick.NativeStyle as NativeStyle
+
+T.CheckDelegate {
+ id: control
+
+ readonly property bool __nativeIndicator: indicator instanceof NativeStyle.StyleItem
+ readonly property bool __notCustomizable: true
+ readonly property Item __focusFrameTarget: indicator
+ readonly property Item __focusFrameStyleItem: indicator
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding,
+ implicitIndicatorHeight + topPadding + bottomPadding)
+
+ spacing: 6
+ padding: 6
+
+ contentItem: NativeStyle.DefaultItemDelegateIconLabel {
+ color: control.highlighted ? control.palette.button : control.palette.windowText
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ indicator: NativeStyle.CheckDelegate {
+ x: control.text
+ ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding)
+ : control.leftPadding + (control.availableWidth - width) / 2
+ // The rendering gets messed up when rendering on sub-pixel positions.
+ y: control.topPadding + Math.round((control.availableHeight - height) / 2)
+ contentWidth: control.implicitContentWidth
+ contentHeight: control.implicitContentHeight
+ control: control
+ useNinePatchImage: false
+ overrideState: NativeStyle.StyleItem.NeverHovered
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ NativeStyle.CheckDelegate {
+ id: hoverCheckDelegate
+ control: control
+ x: control.indicator.x
+ y: control.indicator.y
+ z: control.indicator.z + 1
+ width: control.indicator.width
+ height: control.indicator.height
+ useNinePatchImage: false
+ overrideState: NativeStyle.StyleItem.AlwaysHovered
+ opacity: control.hovered ? 1 : 0
+ visible: opacity !== 0
+ Behavior on opacity {
+ NumberAnimation {
+ duration: hoverCheckDelegate.transitionDuration
+ }
+ }
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 20
+ color: Qt.darker(control.highlighted
+ ? control.palette.highlight : control.palette.button, control.down ? 1.05 : 1)
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+}
diff --git a/src/quickcontrols/windows/ComboBox.qml b/src/quickcontrols/windows/ComboBox.qml
index 66fffecb46..e8a0ed738d 100644
--- a/src/quickcontrols/windows/ComboBox.qml
+++ b/src/quickcontrols/windows/ComboBox.qml
@@ -1,6 +1,8 @@
// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+pragma ComponentBehavior: Bound
+
import QtQuick
import QtQuick.Window
import QtQuick.Controls
@@ -56,8 +58,11 @@ T.ComboBox {
}
delegate: ItemDelegate {
+ required property var model
+ required property int index
+
width: ListView.view.width
- text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
+ text: model[control.textRole]
palette.text: control.palette.text
palette.highlightedText: control.palette.highlightedText
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
diff --git a/src/quickcontrols/windows/DelayButton.qml b/src/quickcontrols/windows/DelayButton.qml
new file mode 100644
index 0000000000..935e5cc86a
--- /dev/null
+++ b/src/quickcontrols/windows/DelayButton.qml
@@ -0,0 +1,82 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Controls.impl
+import QtQuick.Templates as T
+import QtQuick.NativeStyle as NativeStyle
+
+T.DelayButton {
+ id: control
+
+ readonly property bool __nativeBackground: background instanceof NativeStyle.StyleItem
+ readonly property bool __notCustomizable: true
+ readonly property Item __focusFrameTarget: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ leftPadding: __nativeBackground ? background.contentPadding.left : 5
+ rightPadding: __nativeBackground ? background.contentPadding.right : 5
+ topPadding: __nativeBackground ? background.contentPadding.top : 5
+ bottomPadding: __nativeBackground ? background.contentPadding.bottom : 5
+
+ icon.width: 24
+ icon.height: 24
+ icon.color: control.palette.buttonText
+
+ transition: Transition {
+ NumberAnimation {
+ duration: control.delay * (control.pressed ? 1.0 - control.progress : 0.3 * control.progress)
+ }
+ }
+
+ background: NativeStyle.DelayButton {
+ control: control
+ contentWidth: contentItem.implicitWidth
+ contentHeight: contentItem.implicitHeight
+ useNinePatchImage: false
+ overrideState: NativeStyle.StyleItem.NeverHovered
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ NativeStyle.DelayButton {
+ id: hoverButton
+ control: control
+ x: background.x
+ y: background.y
+ width: background.width
+ height: background.height
+ useNinePatchImage: false
+ overrideState: NativeStyle.StyleItem.AlwaysHovered
+ opacity: control.hovered ? 1 : 0
+ visible: opacity !== 0
+ Behavior on opacity { NumberAnimation { duration: hoverButton.transitionDuration } }
+ }
+
+ contentItem: IconLabel {
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: control.palette.buttonText
+
+ readonly property bool __ignoreNotCustomizable: true
+
+ // Delay progress bar.
+ Rectangle {
+ x: (parent.width - parent.implicitWidth) / 2
+ y: parent.height + 1
+ width: control.progress * parent.implicitWidth
+ height: 1
+ color: control.palette.accent
+ scale: control.mirrored ? -1 : 1
+ }
+ }
+}
diff --git a/src/quickcontrols/windows/ItemDelegate.qml b/src/quickcontrols/windows/ItemDelegate.qml
new file mode 100644
index 0000000000..879c4532ec
--- /dev/null
+++ b/src/quickcontrols/windows/ItemDelegate.qml
@@ -0,0 +1,10 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick.NativeStyle as NativeStyle
+
+NativeStyle.DefaultItemDelegate {
+ contentItem: NativeStyle.DefaultItemDelegateIconLabel {
+ color: control.highlighted ? control.palette.button : control.palette.windowText
+ }
+}
diff --git a/src/quickcontrols/windows/Menu.qml b/src/quickcontrols/windows/Menu.qml
new file mode 100644
index 0000000000..0b110d7744
--- /dev/null
+++ b/src/quickcontrols/windows/Menu.qml
@@ -0,0 +1,74 @@
+// Copyright (C) 2024 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.Window
+import QtQuick.Effects
+
+T.Menu {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ // The insets are found by examining the MultiEffect.itemRect, which
+ // contains the drop shadow offsets. QQuickPopup will subract these insets when
+ // it opens up the menu so that the top left corner of the background ends up at
+ // the requested popup position.
+ // Note: the insets are hard-coded to avoid a binding loop to implicit size.
+ leftInset: 32
+ topInset: 32
+ rightInset: 32
+ bottomInset: 32
+ leftPadding: leftInset + 5
+ rightPadding: rightInset + 5
+ topPadding: topInset + 5
+ bottomPadding: bottomInset + 5
+ margins: 0
+ overlap: 4
+
+ delegate: MenuItem { }
+
+ contentItem: ListView {
+ implicitHeight: contentHeight
+ model: control.contentModel
+ interactive: Window.window
+ ? contentHeight + control.topPadding + control.bottomPadding > control.height
+ : false
+ currentIndex: control.currentIndex
+ spacing: 2
+
+ ScrollIndicator.vertical: ScrollIndicator {}
+ }
+
+ background: MultiEffect {
+ implicitWidth: 200
+ implicitHeight: 20
+ source: Rectangle {
+ width: control.background.width
+ height: control.background.height
+ radius: 8
+ color: Qt.lighter(control.palette.window, 1.15)
+ border.color: Qt.darker(control.palette.window, 1.12)
+ visible: false
+ }
+ shadowScale: 1.04
+ shadowOpacity: 0.1
+ shadowColor: 'black'
+ shadowEnabled: true
+ shadowHorizontalOffset: 0
+ shadowVerticalOffset: 10
+ }
+
+ T.Overlay.modal: Rectangle {
+ color: "transparent"
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: "transparent"
+ }
+}
diff --git a/src/quickcontrols/windows/MenuBar.qml b/src/quickcontrols/windows/MenuBar.qml
new file mode 100644
index 0000000000..ec998abde7
--- /dev/null
+++ b/src/quickcontrols/windows/MenuBar.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2024 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
+
+T.MenuBar {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ leftPadding: 3
+ rightPadding: 3
+ topPadding: 3
+ bottomPadding: 3
+ spacing: 10
+
+ delegate: MenuBarItem { }
+
+ contentItem: Row {
+ spacing: control.spacing
+ Repeater {
+ model: control.contentModel
+ }
+ }
+
+ background: Rectangle {
+ implicitHeight: 20
+ color: "white" // window title bar color
+ }
+}
diff --git a/src/quickcontrols/windows/MenuBarItem.qml b/src/quickcontrols/windows/MenuBarItem.qml
new file mode 100644
index 0000000000..fe71542153
--- /dev/null
+++ b/src/quickcontrols/windows/MenuBarItem.qml
@@ -0,0 +1,47 @@
+// Copyright (C) 2024 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
+
+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)
+
+ topPadding: 8
+ bottomPadding: 8
+ leftPadding: 10
+ rightPadding: 10
+ spacing: 6
+
+ icon.width: 16
+ icon.height: 16
+
+ 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.palette.text
+ }
+
+ background: Rectangle {
+ implicitWidth: 20
+ implicitHeight: 20
+
+ color: "black"
+ opacity: 0.05
+ radius: 4
+ visible: control.down || control.highlighted
+ }
+}
diff --git a/src/quickcontrols/windows/MenuItem.qml b/src/quickcontrols/windows/MenuItem.qml
new file mode 100644
index 0000000000..0d3c4f89f6
--- /dev/null
+++ b/src/quickcontrols/windows/MenuItem.qml
@@ -0,0 +1,74 @@
+// Copyright (C) 2024 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.Windows.impl
+
+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)
+
+ leftPadding: 10
+ rightPadding: 10
+ topPadding: 3
+ bottomPadding: 3
+ spacing: 6
+
+ icon.width: 16
+ icon.height: 16
+
+ implicitTextPadding: control.checkable && control.indicator ? control.indicator.width + control.spacing : 0
+
+ contentItem: IconLabel {
+ readonly property real arrowPadding: control.subMenu && control.arrow ? control.arrow.width + control.spacing : 0
+ leftPadding: !control.mirrored ? control.textPadding : arrowPadding
+ rightPadding: control.mirrored ? control.textPadding : arrowPadding
+
+ spacing: control.spacing
+ mirrored: control.mirrored
+ display: control.display
+ alignment: Qt.AlignLeft
+
+ icon: control.icon
+ text: control.text
+ font: control.font
+ color: control.palette.text
+ }
+
+ arrow: ColorImage {
+ x: control.mirrored ? control.padding : control.width - width - control.padding
+ y: control.topPadding + (control.availableHeight - height) / 2
+ width: 20
+
+ visible: control.subMenu
+ rotation: control.mirrored ? -180 : 0
+ color: control.palette.text
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Windows/images/menuarrow.png"
+ fillMode: Image.Pad
+ }
+
+ indicator: CheckIndicator {
+ x: control.mirrored ? control.width - width - control.rightPadding : control.leftPadding
+ y: control.topPadding + (control.availableHeight - height) / 2
+
+ control: control
+ visible: control.checkable
+ }
+
+ background: Rectangle {
+ implicitWidth: 200
+ implicitHeight: 30
+ radius: 4
+
+ color: control.palette.dark
+ opacity: 0.1
+ visible: control.down || control.highlighted
+ }
+}
diff --git a/src/quickcontrols/windows/MenuSeparator.qml b/src/quickcontrols/windows/MenuSeparator.qml
new file mode 100644
index 0000000000..6559be9958
--- /dev/null
+++ b/src/quickcontrols/windows/MenuSeparator.qml
@@ -0,0 +1,23 @@
+// Copyright (C) 2024 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
+
+T.MenuSeparator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ horizontalPadding: 0
+ verticalPadding: 2
+
+ contentItem: Rectangle {
+ implicitWidth: 188
+ implicitHeight: 1
+ color: control.palette.midlight
+ }
+}
diff --git a/src/quickcontrols/windows/RadioDelegate.qml b/src/quickcontrols/windows/RadioDelegate.qml
new file mode 100644
index 0000000000..e74e42350b
--- /dev/null
+++ b/src/quickcontrols/windows/RadioDelegate.qml
@@ -0,0 +1,12 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick.NativeStyle as NativeStyle
+
+NativeStyle.DefaultRadioDelegate {
+ contentItem: NativeStyle.DefaultItemDelegateIconLabel {
+ color: control.highlighted ? control.palette.button : control.palette.windowText
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+}
diff --git a/src/quickcontrols/windows/RangeSlider.qml b/src/quickcontrols/windows/RangeSlider.qml
new file mode 100644
index 0000000000..a124163e7b
--- /dev/null
+++ b/src/quickcontrols/windows/RangeSlider.qml
@@ -0,0 +1,105 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Templates as T
+
+T.RangeSlider {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ Math.max(first.implicitHandleWidth, second.implicitHandleWidth) + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ Math.max(first.implicitHandleHeight, second.implicitHandleHeight) + topPadding + bottomPadding)
+
+ readonly property bool __notCustomizable: true
+ readonly property Item __focusFrameTarget: control
+
+ component SliderHandle: Rectangle {
+ implicitWidth: control.horizontal ? 11 : 21
+ implicitHeight: control.horizontal ? 21 : 11
+ color: control.palette.highlight
+
+ required property bool pressed
+ }
+
+ first.handle: SliderHandle {
+ x: control.leftPadding + Math.round(control.horizontal
+ ? control.first.visualPosition * (control.availableWidth - width)
+ : (control.availableWidth - width) / 2)
+ y: control.topPadding + Math.round(control.horizontal
+ ? (control.availableHeight - height) / 2
+ : control.first.visualPosition * (control.availableHeight - height))
+ palette: control.palette
+ pressed: control.first.pressed
+
+ // We are the ones that get focus, but we want the control to
+ // be used for the visual focus frame.
+ readonly property Item __focusFrameControl: control
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ second.handle: SliderHandle {
+ x: control.leftPadding + Math.round(control.horizontal
+ ? control.second.visualPosition * (control.availableWidth - width)
+ : (control.availableWidth - width) / 2)
+ y: control.topPadding + Math.round(control.horizontal
+ ? (control.availableHeight - height) / 2
+ : control.second.visualPosition * (control.availableHeight - height))
+ palette: control.palette
+ pressed: control.second.pressed
+
+ readonly property Item __focusFrameControl: control
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ background: Item {
+ implicitWidth: control.horizontal ? 90 : 21
+ implicitHeight: control.horizontal ? 21 : 90
+
+ readonly property real __focusFrameRadius: 1
+ readonly property bool __ignoreNotCustomizable: true
+ readonly property int barThickness: 4
+
+ // Groove background.
+ Rectangle {
+ 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 : parent.barThickness
+ height: control.horizontal ? parent.barThickness : control.availableHeight
+ color: control.palette.window
+
+ Rectangle {
+ width: parent.width
+ height: parent.height
+ radius: parent.radius
+ // No border in dark mode, instead we fill.
+ color: Qt.styleHints.colorScheme === Qt.Light
+ ? "transparent" : Qt.lighter(control.palette.window, 1.6)
+ border.color: Qt.styleHints.colorScheme === Qt.Light
+ ? Qt.darker(control.palette.window, 1.1)
+ : "transparent"
+ }
+ }
+
+ // Progress bar.
+ Rectangle {
+ x: control.leftPadding + (control.horizontal
+ ? control.first.position * control.availableWidth
+ : (control.availableWidth - width) / 2)
+ y: control.topPadding + (control.horizontal
+ ? (control.availableHeight - height) / 2
+ : control.second.visualPosition * control.availableHeight)
+
+ width: control.horizontal
+ ? control.second.position * control.availableWidth - control.first.position * control.availableWidth
+ : parent.barThickness
+ height: control.horizontal
+ ? parent.barThickness
+ : control.second.position * control.availableHeight - control.first.position * control.availableHeight
+ color: Qt.rgba(control.palette.highlight.r, control.palette.highlight.g, control.palette.highlight.b, 0.3)
+ }
+ }
+}
diff --git a/src/quickcontrols/windows/ScrollBar.qml b/src/quickcontrols/windows/ScrollBar.qml
index 6906f7dfa2..80fbf74e75 100644
--- a/src/quickcontrols/windows/ScrollBar.qml
+++ b/src/quickcontrols/windows/ScrollBar.qml
@@ -7,6 +7,8 @@ import QtQuick.NativeStyle as NativeStyle
NativeStyle.DefaultScrollBar {
id: controlRoot
+ readonly property bool __notCustomizable: true
+
topPadding: orientation === Qt.Vertical ? controlRoot.__decreaseVisual.indicator.height : 0
bottomPadding: orientation === Qt.Vertical ? controlRoot.__increaseVisual.indicator.height : 0
leftPadding: orientation === Qt.Horizontal ? controlRoot.__decreaseVisual.indicator.width : 0
@@ -15,6 +17,8 @@ NativeStyle.DefaultScrollBar {
contentItem: NativeStyle.ScrollBar {
control: controlRoot
subControl: NativeStyle.ScrollBar.Handle
+
+ readonly property bool __ignoreNotCustomizable: true
}
NativeStyle.ScrollBar {
@@ -29,7 +33,6 @@ NativeStyle.DefaultScrollBar {
subControl: NativeStyle.ScrollBar.Handle
overrideState: NativeStyle.StyleItem.AlwaysHovered
opacity: controlRoot.hovered || control.pressed ? 1 : 0
- visible: contentItem instanceof NativeStyle.StyleItem
Behavior on opacity { NumberAnimation { duration: contentItem.transitionDuration } }
}
@@ -47,6 +50,8 @@ NativeStyle.DefaultScrollBar {
control: controlRoot
subControl: NativeStyle.ScrollBar.Groove
overrideState: NativeStyle.ScrollBar.NeverHovered
+
+ readonly property bool __ignoreNotCustomizable: true
}
__decreaseVisual.indicator: NativeStyle.ScrollBar {
@@ -54,9 +59,10 @@ NativeStyle.DefaultScrollBar {
subControl: NativeStyle.ScrollBar.SubLine
overrideState: NativeStyle.ScrollBar.AlwaysHovered
opacity: controlRoot.__decreaseVisual.hovered ? 1 : 0
- visible: contentItem instanceof NativeStyle.StyleItem
Behavior on opacity { NumberAnimation { duration: contentItem.transitionDuration } }
useNinePatchImage: false
+
+ readonly property bool __ignoreNotCustomizable: true
}
NativeStyle.ScrollBar {
@@ -64,7 +70,6 @@ NativeStyle.DefaultScrollBar {
subControl: NativeStyle.ScrollBar.SubLine
overrideState: NativeStyle.ScrollBar.AlwaysSunken
opacity: controlRoot.__decreaseVisual.pressed ? 1 : 0
- visible: contentItem instanceof NativeStyle.StyleItem
useNinePatchImage: false
z: 1
}
@@ -76,9 +81,10 @@ NativeStyle.DefaultScrollBar {
y: orientation === Qt.Vertical ? controlRoot.height - height : 0
overrideState: NativeStyle.ScrollBar.AlwaysHovered
opacity: controlRoot.__increaseVisual.hovered ? 1 : 0
- visible: contentItem instanceof NativeStyle.StyleItem
Behavior on opacity { NumberAnimation { duration: contentItem.transitionDuration } }
useNinePatchImage: false
+
+ readonly property bool __ignoreNotCustomizable: true
}
NativeStyle.ScrollBar {
@@ -89,7 +95,6 @@ NativeStyle.DefaultScrollBar {
z: 1
overrideState: NativeStyle.ScrollBar.AlwaysSunken
opacity: controlRoot.__increaseVisual.pressed ? 1 : 0
- visible: contentItem instanceof NativeStyle.StyleItem
useNinePatchImage: false
}
}
diff --git a/src/quickcontrols/windows/ScrollIndicator.qml b/src/quickcontrols/windows/ScrollIndicator.qml
new file mode 100644
index 0000000000..f8358eb1bf
--- /dev/null
+++ b/src/quickcontrols/windows/ScrollIndicator.qml
@@ -0,0 +1,42 @@
+// Copyright (C) 2024 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
+
+T.ScrollIndicator {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 2
+
+ contentItem: Rectangle {
+ implicitWidth: 2
+ implicitHeight: 2
+
+ color: control.palette.mid
+ visible: control.size < 1.0
+ opacity: 0.0
+
+ states: State {
+ name: "active"
+ when: control.active
+ PropertyChanges { control.contentItem.opacity: 0.75 }
+ }
+
+ transitions: [
+ Transition {
+ from: "active"
+ SequentialAnimation {
+ PauseAnimation { duration: 450 }
+ NumberAnimation { target: control.contentItem; duration: 200; property: "opacity"; to: 0.0 }
+ }
+ }
+ ]
+ }
+}
diff --git a/src/quickcontrols/windows/ScrollView.qml b/src/quickcontrols/windows/ScrollView.qml
index 28f2d8e0fc..65d65899ca 100644
--- a/src/quickcontrols/windows/ScrollView.qml
+++ b/src/quickcontrols/windows/ScrollView.qml
@@ -13,8 +13,8 @@ T.ScrollView {
implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
contentHeight + topPadding + bottomPadding)
- rightPadding: ScrollBar.vertical.visible ? ScrollBar.vertical.width : 0
- bottomPadding: ScrollBar.horizontal.visible ? ScrollBar.horizontal.height : 0
+ rightPadding: effectiveScrollBarWidth
+ bottomPadding: effectiveScrollBarHeight
// Don't set __notCustomizable here, because it would require special-casing
// setFlickable's call to setContentItem.
diff --git a/src/quickcontrols/windows/SpinBox.qml b/src/quickcontrols/windows/SpinBox.qml
index 982a5868a3..dcf75c0b0d 100644
--- a/src/quickcontrols/windows/SpinBox.qml
+++ b/src/quickcontrols/windows/SpinBox.qml
@@ -70,7 +70,7 @@ T.SpinBox {
}
up.indicator: Item {
- x: parent.width - width - 2
+ x: control.width - width - 2
y: 1
height: upAndDown.height >> 1
implicitWidth: upAndDown.implicitWidth
@@ -80,7 +80,7 @@ T.SpinBox {
}
down.indicator: Item {
- x: parent.width - width - 2
+ x: control.width - width - 2
y: up.indicator.y + (upAndDown.height >> 1)
height: upAndDown.height - up.indicator.height
implicitWidth: upAndDown.implicitWidth
diff --git a/src/quickcontrols/windows/Switch.qml b/src/quickcontrols/windows/Switch.qml
new file mode 100644
index 0000000000..4e8fc48396
--- /dev/null
+++ b/src/quickcontrols/windows/Switch.qml
@@ -0,0 +1,37 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Windows.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: 6
+ spacing: 6
+
+ readonly property bool __notCustomizable: true
+ readonly property Item __focusFrameTarget: indicator
+ readonly property Item __focusFrameStyleItem: indicator
+
+ indicator: SwitchIndicator {}
+
+ 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
+ color: control.palette.windowText
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+}
diff --git a/src/quickcontrols/windows/SwitchDelegate.qml b/src/quickcontrols/windows/SwitchDelegate.qml
new file mode 100644
index 0000000000..0130a9b372
--- /dev/null
+++ b/src/quickcontrols/windows/SwitchDelegate.qml
@@ -0,0 +1,45 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+import QtQuick.Controls.Windows.impl
+import QtQuick.NativeStyle as NativeStyle
+
+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)
+
+ padding: 6
+ spacing: 6
+
+ readonly property bool __notCustomizable: true
+ readonly property Item __focusFrameTarget: indicator
+ readonly property Item __focusFrameStyleItem: indicator
+
+ indicator: SwitchIndicator {
+ x: control.text
+ ? (control.mirrored ? control.leftPadding : control.width - width - control.rightPadding)
+ : control.leftPadding + (control.availableWidth - width) / 2
+ }
+
+ contentItem: NativeStyle.DefaultItemDelegateIconLabel {
+ color: control.highlighted ? control.palette.button : control.palette.windowText
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+
+ background: Rectangle {
+ implicitWidth: 100
+ implicitHeight: 20
+ color: Qt.darker(control.highlighted
+ ? control.palette.highlight : control.palette.button, control.down ? 1.05 : 1)
+
+ readonly property bool __ignoreNotCustomizable: true
+ }
+}
diff --git a/src/quickcontrols/windows/images/checkmark.png b/src/quickcontrols/windows/images/checkmark.png
new file mode 100644
index 0000000000..35fe52c8c0
--- /dev/null
+++ b/src/quickcontrols/windows/images/checkmark.png
Binary files differ
diff --git a/src/quickcontrols/windows/images/checkmark@2x.png b/src/quickcontrols/windows/images/checkmark@2x.png
new file mode 100644
index 0000000000..fb7096b4b5
--- /dev/null
+++ b/src/quickcontrols/windows/images/checkmark@2x.png
Binary files differ
diff --git a/src/quickcontrols/windows/images/checkmark@3x.png b/src/quickcontrols/windows/images/checkmark@3x.png
new file mode 100644
index 0000000000..e0c2790607
--- /dev/null
+++ b/src/quickcontrols/windows/images/checkmark@3x.png
Binary files differ
diff --git a/src/quickcontrols/windows/images/menuarrow.png b/src/quickcontrols/windows/images/menuarrow.png
new file mode 100644
index 0000000000..b504351fe1
--- /dev/null
+++ b/src/quickcontrols/windows/images/menuarrow.png
Binary files differ
diff --git a/src/quickcontrols/windows/images/menuarrow@2x.png b/src/quickcontrols/windows/images/menuarrow@2x.png
new file mode 100644
index 0000000000..fa9082d0c0
--- /dev/null
+++ b/src/quickcontrols/windows/images/menuarrow@2x.png
Binary files differ
diff --git a/src/quickcontrols/windows/images/menuarrow@3x.png b/src/quickcontrols/windows/images/menuarrow@3x.png
new file mode 100644
index 0000000000..acb626246d
--- /dev/null
+++ b/src/quickcontrols/windows/images/menuarrow@3x.png
Binary files differ
diff --git a/src/quickcontrols/windows/impl/CMakeLists.txt b/src/quickcontrols/windows/impl/CMakeLists.txt
new file mode 100644
index 0000000000..8b031b7a8d
--- /dev/null
+++ b/src/quickcontrols/windows/impl/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+set(qml_files
+ "CheckIndicator.qml"
+ "SwitchIndicator.qml"
+)
+
+qt_internal_add_qml_module(QuickControls2WindowsStyleImpl
+ URI "QtQuick.Controls.Windows.impl"
+ VERSION "${PROJECT_VERSION}"
+ PAST_MAJOR_VERSIONS 6
+ CLASS_NAME QtQuickControls2WindowsStyleImplPlugin
+ DEPENDENCIES
+ QtQuick/auto
+ PLUGIN_TARGET qtquickcontrols2windowsstyleimplplugin
+ QML_FILES
+ ${qml_files}
+ DEFINES
+ QT_NO_CAST_FROM_ASCII
+ QT_NO_CAST_TO_ASCII
+)
diff --git a/src/quickcontrols/windows/impl/CheckIndicator.qml b/src/quickcontrols/windows/impl/CheckIndicator.qml
new file mode 100644
index 0000000000..818336dfdf
--- /dev/null
+++ b/src/quickcontrols/windows/impl/CheckIndicator.qml
@@ -0,0 +1,21 @@
+// Copyright (C) 2024 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
+
+Item {
+ id: indicator
+ implicitWidth: 14
+ implicitHeight: 10
+
+ property Item control
+
+ ColorImage {
+ y: (parent.height - height) / 2
+ color: control.palette.text
+ source: "qrc:/qt-project.org/imports/QtQuick/Controls/Windows/images/checkmark.png"
+ visible: indicator.control.checkState === Qt.Checked
+ || (indicator.control.checked && indicator.control.checkState === undefined)
+ }
+}
diff --git a/src/quickcontrols/windows/impl/SwitchIndicator.qml b/src/quickcontrols/windows/impl/SwitchIndicator.qml
new file mode 100644
index 0000000000..0dd80dadf7
--- /dev/null
+++ b/src/quickcontrols/windows/impl/SwitchIndicator.qml
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+import QtQuick
+import QtQuick.Templates as T
+
+Rectangle {
+ id: root
+ 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
+ implicitWidth: 40
+ implicitHeight: 16
+ radius: 3
+ color: Qt.darker(control.palette.button, control.down ? 1.2 : 1.1)
+ border.color: Qt.darker(control.palette.window, 1.4)
+
+ readonly property bool __ignoreNotCustomizable: true
+ readonly property real __focusFrameRadius: 2
+ readonly property T.AbstractButton control: parent as T.AbstractButton
+
+ // Checked indicator.
+ Rectangle {
+ x: root.control.mirrored ? parent.children[1].x : 0
+ width: root.control.mirrored
+ ? parent.width - parent.children[1].x : parent.children[1].x + parent.children[1].width
+ height: parent.height
+ radius: 3
+ color: Qt.darker(root.control.palette.highlight, root.control.down ? 1.1 : 1)
+ border.color: Qt.darker(root.control.palette.highlight, 1.35)
+ border.width: root.control.enabled ? 1 : 0
+ opacity: root.control.checked ? 1 : 0
+
+ Behavior on opacity {
+ enabled: !root.control.down
+ NumberAnimation { duration: 80 }
+ }
+ }
+
+ // Handle.
+ Rectangle {
+ x: Math.max(0, Math.min(parent.width - width,
+ root.control.visualPosition * parent.width - (width / 2)))
+ y: (parent.height - height) / 2
+ width: 20
+ height: 16
+ radius: 3
+ color: Qt.lighter(root.control.palette.button, root.control.down
+ ? 1 : (root.control.hovered ? 1.07 : 1.045))
+ border.width: 1
+ border.color: Qt.darker(root.control.palette.window, 1.4)
+
+ Behavior on x {
+ enabled: !root.control.down
+ SmoothedAnimation { velocity: 200 }
+ }
+ }
+}