diff options
Diffstat (limited to 'src/quickcontrols/universal')
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/[email protected]" + "images/[email protected]" + "images/[email protected]" + "images/downarrow.png" + "images/[email protected]" + "images/[email protected]" + "images/[email protected]" + "images/leftarrow.png" + "images/[email protected]" + "images/[email protected]" + "images/[email protected]" + "images/rightarrow.png" + "images/[email protected]" + "images/[email protected]" + "images/[email protected]" +) + +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 Binary files differnew file mode 100644 index 0000000000..e2aae6fe0f --- /dev/null +++ b/src/quickcontrols/universal/images/checkmark.png diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..0df4159a7c --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..43466cbcb6 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..7a47bd2159 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/downarrow.png b/src/quickcontrols/universal/images/downarrow.png Binary files differnew file mode 100644 index 0000000000..b66e2efc22 --- /dev/null +++ b/src/quickcontrols/universal/images/downarrow.png diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..a704376c8f --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..3b6d55ab4c --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..818c6b24ff --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/leftarrow.png b/src/quickcontrols/universal/images/leftarrow.png Binary files differnew file mode 100644 index 0000000000..0153ccd421 --- /dev/null +++ b/src/quickcontrols/universal/images/leftarrow.png diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..fa692d5b0f --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..06b0207a60 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..1049f616e4 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/rightarrow.png b/src/quickcontrols/universal/images/rightarrow.png Binary files differnew file mode 100644 index 0000000000..b24d117d79 --- /dev/null +++ b/src/quickcontrols/universal/images/rightarrow.png diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..80aca7c18f --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..ba01724065 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] diff --git a/src/quickcontrols/universal/images/[email protected] b/src/quickcontrols/universal/images/[email protected] Binary files differnew file mode 100644 index 0000000000..21f7ed4d15 --- /dev/null +++ b/src/quickcontrols/universal/images/[email protected] 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" |