aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2022-06-23 15:33:34 +0800
committerMitch Curtis <mitch.curtis@qt.io>2022-10-13 11:34:11 +0800
commit49b9f1f1e85ce9aee960b1384fb542daacd8b7a7 (patch)
tree575cebdd0dd014d6569bfec36f20dbe5f6cddf4b /examples
parent5eb52b725526c26d0efa3856b6aba1919010f8fd (diff)
Make QQuickAttachedPropertyPropagator public
This type has been used internally as QQuickAttachedObject by the Imagine, Material and Universal styles to enable propagation of colors, dark mode flags, etc. for a while now. Users would benefit from having access to it to create their own styles (although it's not just limited to that use case). This patch: - Makes the type public in quickcontrols2. - Adds documentation and an example. - Fixes the test_window test to ensure that propagation through child windows actually works. [ChangeLog][Controls] Added QQuickAttachedPropertyPropagator, which provides a way to propagate attached properties from parent objects to children. This is especially useful when creating your own style. Fixes: QTBUG-63267 Change-Id: I2f1794dc4a9f2be56fad2f5e5f39e2ab845157fa Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/quickcontrols2/CMakeLists.txt1
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/CMakeLists.txt52
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/ApplicationWindow.qml17
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/Button.qml33
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/CMakeLists.txt47
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/Label.qml11
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/Popup.qml48
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/Switch.qml58
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/ToolBar.qml24
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.cpp136
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.h76
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.cpp28
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.qml110
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/doc/images/qtquickcontrols2-attachedstyleproperties.pngbin0 -> 11703 bytes
-rw-r--r--examples/quickcontrols2/attachedstyleproperties/doc/src/qtquickcontrols2-attachedstyleproperties.qdoc18
15 files changed, 659 insertions, 0 deletions
diff --git a/examples/quickcontrols2/CMakeLists.txt b/examples/quickcontrols2/CMakeLists.txt
index 3473052f68..e4021bf430 100644
--- a/examples/quickcontrols2/CMakeLists.txt
+++ b/examples/quickcontrols2/CMakeLists.txt
@@ -1,6 +1,7 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+qt_internal_add_example(attachedstyleproperties)
qt_internal_add_example(gallery)
if (TARGET Qt::Sql)
add_subdirectory(chattutorial)
diff --git a/examples/quickcontrols2/attachedstyleproperties/CMakeLists.txt b/examples/quickcontrols2/attachedstyleproperties/CMakeLists.txt
new file mode 100644
index 0000000000..229129f5c6
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/CMakeLists.txt
@@ -0,0 +1,52 @@
+cmake_minimum_required(VERSION 3.16)
+project(attachedstyleproperties LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quickcontrols2/attachedstyleproperties")
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml QuickControls2)
+qt_standard_project_setup()
+
+add_subdirectory(MyStyle)
+
+qt_add_executable(attachedstylepropertiesexample
+ WIN32
+ MACOSX_BUNDLE
+ attachedstyleproperties.cpp
+)
+
+qt_add_qml_module(attachedstylepropertiesexample
+ URI App
+ VERSION 1.0
+ QML_FILES
+ attachedstyleproperties.qml
+ NO_RESOURCE_TARGET_PATH
+)
+
+target_link_libraries(attachedstylepropertiesexample PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::QuickControls2
+)
+
+add_dependencies(attachedstylepropertiesexample MyStyle)
+
+install(TARGETS attachedstylepropertiesexample
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
+
+include(../../quick/shared/QtBundleQmlModuleForMacOS.cmake)
+
+set(app_target "attachedstylepropertiesexample")
+set(qml_plugin_target "MyStyleplugin")
+set(qml_module_uri "MyStyle")
+add_qml_module_to_macos_app_bundle(
+ "${app_target}" "${qml_plugin_target}" "${qml_module_uri}")
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/ApplicationWindow.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/ApplicationWindow.qml
new file mode 100644
index 0000000000..8a7bbc7ed2
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/ApplicationWindow.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+
+import MyStyle
+
+T.ApplicationWindow {
+ color: MyStyle.windowColor
+
+ Behavior on color {
+ ColorAnimation {
+ duration: 150
+ }
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/Button.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Button.qml
new file mode 100644
index 0000000000..7eabcb0b35
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Button.qml
@@ -0,0 +1,33 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+
+import MyStyle
+
+T.Button {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 6
+ horizontalPadding: padding + 2
+ spacing: 6
+
+ contentItem: Text {
+ text: control.text
+ font: control.font
+ color: control.MyStyle.buttonTextColor
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ background: Rectangle {
+ implicitWidth: 60
+ implicitHeight: 40
+ color: control.down ? Qt.darker(control.MyStyle.buttonColor, 1.1) : control.MyStyle.buttonColor
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/CMakeLists.txt b/examples/quickcontrols2/attachedstyleproperties/MyStyle/CMakeLists.txt
new file mode 100644
index 0000000000..310670677e
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/CMakeLists.txt
@@ -0,0 +1,47 @@
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+ message(FATAL_ERROR "MyStyle should be built as part of the 'attachedstyleproperties' project, and not in isolation.")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quickcontrols2/attachedstyleproperties")
+
+qt_add_qml_module(MyStyle
+ URI MyStyle
+ VERSION 1.0
+ IMPORTS
+ QtQuick.Controls.Material
+ QML_FILES
+ ApplicationWindow.qml
+ Button.qml
+ Label.qml
+ Popup.qml
+ Switch.qml
+ ToolBar.qml
+ SOURCES
+ mystyle.cpp
+ mystyle.h
+)
+
+include(GenerateExportHeader)
+target_include_directories(MyStyle PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # find autogenerated header
+generate_export_header(MyStyle)
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml QuickControls2)
+
+target_link_libraries(MyStyle PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::QuickControls2
+)
+
+message(STATUS "@@@ INSTALL_EXAMPLEDIR ${INSTALL_EXAMPLEDIR}")
+
+install(TARGETS MyStyle
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qmldir
+ DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/Label.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Label.qml
new file mode 100644
index 0000000000..3d045aa70e
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Label.qml
@@ -0,0 +1,11 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+
+import MyStyle
+
+T.Label {
+ color: MyStyle.windowTextColor
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/Popup.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Popup.qml
new file mode 100644
index 0000000000..0f5e753f60
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Popup.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+import MyStyle
+
+T.Popup {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ contentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ contentHeight + topPadding + bottomPadding)
+
+ padding: 12
+
+ enter: Transition {
+ NumberAnimation {
+ property: "opacity"
+ from: 0.0
+ to: 1.0
+ easing.type: Easing.OutCubic
+ duration: 150
+ }
+ }
+
+ exit: Transition {
+ NumberAnimation {
+ property: "opacity"
+ from: 1.0
+ to: 0.0
+ easing.type: Easing.OutCubic
+ duration: 150
+ }
+ }
+
+ background: Rectangle {
+ radius: 2
+ color: control.MyStyle.popupColor
+ border.color: control.MyStyle.popupBorderColor
+ }
+
+ T.Overlay.modeless: Rectangle {
+ color: control.MyStyle.backgroundDimColor
+ Behavior on opacity { NumberAnimation { duration: 150 } }
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/Switch.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Switch.qml
new file mode 100644
index 0000000000..59bda147b7
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/Switch.qml
@@ -0,0 +1,58 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+
+import MyStyle
+
+T.Switch {
+ id: control
+
+ implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset,
+ implicitContentWidth + leftPadding + rightPadding)
+ implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset,
+ implicitContentHeight + topPadding + bottomPadding)
+
+ padding: 6
+ horizontalPadding: padding + 2
+ spacing: 6
+
+ indicator: Rectangle {
+ implicitWidth: 56
+ implicitHeight: 28
+
+ 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
+
+ radius: 8
+ color: control.down ? Qt.darker(control.MyStyle.buttonColor, 1.1) : control.MyStyle.buttonColor
+
+ Rectangle {
+ x: Math.max(0, Math.min(parent.width - width, control.visualPosition * parent.width - (width / 2)))
+ y: (parent.height - height) / 2
+ width: 28
+ height: 28
+ radius: 8
+ color: Qt.lighter(control.MyStyle.buttonColor)
+
+ Behavior on x {
+ enabled: !control.down
+ SmoothedAnimation { velocity: 200 }
+ }
+ }
+ }
+
+ contentItem: Text {
+ leftPadding: control.indicator && !control.mirrored ? control.indicator.width + control.spacing : 0
+ rightPadding: control.indicator && control.mirrored ? control.indicator.width + control.spacing : 0
+
+ text: control.text
+ font: control.font
+ color: control.MyStyle.windowTextColor
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/ToolBar.qml b/examples/quickcontrols2/attachedstyleproperties/MyStyle/ToolBar.qml
new file mode 100644
index 0000000000..b0cd597c87
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/ToolBar.qml
@@ -0,0 +1,24 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Templates as T
+
+import MyStyle
+
+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: 40
+ // Ensure that we use Control's attached MyStyle object by qualifying
+ // the binding with its id. If we don't do this, an extra, unnecessary
+ // attached MyStyle object will be created for the Rectangle.
+ color: control.MyStyle.toolBarColor
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.cpp b/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.cpp
new file mode 100644
index 0000000000..40f7af702e
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.cpp
@@ -0,0 +1,136 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "mystyle.h"
+
+// If no value was inherited from a parent or explicitly set, the "global" values are used.
+static MyStyle::Theme globalTheme = MyStyle::Light;
+
+MyStyle::MyStyle(QObject *parent)
+ : QQuickAttachedPropertyPropagator(parent)
+ , m_theme(globalTheme)
+{
+ // A static function could be called here that reads globalTheme from a
+ // settings file once at startup. That value would override the global
+ // value. This is similar to what the Imagine and Material styles do, for
+ // example.
+
+ initialize();
+}
+
+MyStyle *MyStyle::qmlAttachedProperties(QObject *object)
+{
+ return new MyStyle(object);
+}
+
+MyStyle::Theme MyStyle::theme() const
+{
+ return m_theme;
+}
+
+void MyStyle::setTheme(Theme theme)
+{
+ // When this function is called, we know that the user has explicitly
+ // set a theme on this attached object. We set this to true even if
+ // the effective theme didn't change, because it's important that
+ // the user's specified value is respected (and not inherited from
+ // from the parent).
+ m_explicitTheme = true;
+ if (m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ themeChange();
+
+}
+
+void MyStyle::inheritTheme(Theme theme)
+{
+ if (m_explicitTheme || m_theme == theme)
+ return;
+
+ m_theme = theme;
+ propagateTheme();
+ themeChange();
+}
+
+void MyStyle::propagateTheme()
+{
+ const auto styles = attachedChildren();
+ for (QQuickAttachedPropertyPropagator *child : styles) {
+ MyStyle *myStyle = qobject_cast<MyStyle *>(child);
+ if (myStyle)
+ myStyle->inheritTheme(m_theme);
+ }
+}
+
+void MyStyle::resetTheme()
+{
+ if (!m_explicitTheme)
+ return;
+
+ m_explicitTheme = false;
+ MyStyle *myStyle = qobject_cast<MyStyle *>(attachedParent());
+ inheritTheme(myStyle ? myStyle->theme() : globalTheme);
+}
+
+void MyStyle::themeChange()
+{
+ emit themeChanged();
+ // Emit any other change signals for properties that depend on the theme here...
+}
+
+QColor MyStyle::windowColor() const
+{
+ return m_theme == Light ? QColor::fromRgb(0xf0f0f0) : QColor::fromRgb(0x303030);
+}
+
+QColor MyStyle::windowTextColor() const
+{
+ return m_theme == Light ? QColor::fromRgb(0x5c5c5c) : QColor::fromRgb(0xe0e0e0);
+}
+
+QColor MyStyle::buttonColor() const
+{
+ return m_theme == Light ? QColor::fromRgb(0xc2e1ff) : QColor::fromRgb(0x74bbff);
+}
+
+QColor MyStyle::buttonTextColor() const
+{
+ return m_theme == Light ? QColor::fromRgb(0x5c5c5c) : QColor::fromRgb(0xffffff);
+}
+
+QColor MyStyle::toolBarColor() const
+{
+ return m_theme == Light ? QColor::fromRgb(0x4da6ff) : QColor::fromRgb(0x0066cc);
+}
+
+QColor MyStyle::popupColor() const
+{
+// const QColor winColor = windowColor();
+// return m_theme == Light ? winColor.darker(120) : winColor.lighter(120);
+ return windowColor().lighter(120);
+}
+
+QColor MyStyle::popupBorderColor() const
+{
+ const QColor winColor = windowColor();
+ return m_theme == Light ? winColor.darker(140) : winColor.lighter(140);
+}
+
+QColor MyStyle::backgroundDimColor() const
+{
+ const QColor winColor = windowColor().darker();
+ return QColor::fromRgb(winColor.red(), winColor.green(), winColor.blue(), 100);
+}
+
+void MyStyle::attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent)
+{
+ Q_UNUSED(oldParent);
+ MyStyle *attachedParentStyle = qobject_cast<MyStyle *>(newParent);
+ if (attachedParentStyle) {
+ inheritTheme(attachedParentStyle->theme());
+ // Do any other inheriting here...
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.h b/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.h
new file mode 100644
index 0000000000..da87ab4718
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/MyStyle/mystyle.h
@@ -0,0 +1,76 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#ifndef MYSTYLE_H
+#define MYSTYLE_H
+
+#include <QColor>
+#include <QQmlEngine>
+#include <QQuickAttachedPropertyPropagator>
+
+#include "mystyle_export.h"
+
+class MYSTYLE_EXPORT MyStyle : public QQuickAttachedPropertyPropagator
+{
+ Q_OBJECT
+ // Provide a RESET function in order to allow an item to set MyStyle.theme to undefined
+ // in order to use its parent's (or global) theme after one was explicitly set on it.
+ Q_PROPERTY(Theme theme READ theme WRITE setTheme RESET resetTheme NOTIFY themeChanged FINAL)
+ // As the values of these properties only depend on the theme, they can all use the theme
+ // property's change signal.
+ Q_PROPERTY(QColor windowColor READ windowColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor windowTextColor READ windowTextColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor buttonColor READ buttonColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor buttonTextColor READ buttonTextColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor toolBarColor READ toolBarColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor popupColor READ popupColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor popupBorderColor READ popupBorderColor NOTIFY themeChanged FINAL)
+ Q_PROPERTY(QColor backgroundDimColor READ backgroundDimColor NOTIFY themeChanged FINAL)
+
+ QML_ELEMENT
+ QML_ATTACHED(MyStyle)
+ QML_UNCREATABLE("")
+ QML_ADDED_IN_VERSION(1, 0)
+
+public:
+ enum Theme {
+ Light,
+ Dark
+ };
+
+ Q_ENUM(Theme)
+
+ explicit MyStyle(QObject *parent = nullptr);
+
+ static MyStyle *qmlAttachedProperties(QObject *object);
+
+ Theme theme() const;
+ void setTheme(Theme theme);
+ void inheritTheme(Theme theme);
+ void propagateTheme();
+ void resetTheme();
+ void themeChange();
+
+ QColor windowColor() const;
+ QColor windowTextColor() const;
+ QColor buttonColor() const;
+ QColor buttonTextColor() const;
+ QColor toolBarColor() const;
+ QColor popupColor() const;
+ QColor popupBorderColor() const;
+ QColor backgroundDimColor() const;
+
+Q_SIGNALS:
+ void themeChanged();
+
+protected:
+ void attachedParentChange(QQuickAttachedPropertyPropagator *newParent, QQuickAttachedPropertyPropagator *oldParent) override;
+
+private:
+ // Whether a color value was explicitly set on the specific object that this attached style object represents.
+ bool m_explicitTheme = false;
+ // The actual values for this item, whether explicit, inherited or globally set.
+ Theme m_theme = Light;
+};
+
+#endif // MYSTYLE_H
diff --git a/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.cpp b/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.cpp
new file mode 100644
index 0000000000..376e53c055
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.cpp
@@ -0,0 +1,28 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QDir>
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+ app.setOrganizationName("QtProject");
+ app.setOrganizationDomain("qt-project.org");
+ app.setApplicationName("Attached Objects");
+
+ QQmlApplicationEngine engine;
+#ifdef Q_OS_MACOS
+ engine.addImportPath(app.applicationDirPath() + "/../PlugIns");
+#endif
+ const QUrl url(QStringLiteral("qrc:/attachedstyleproperties.qml"));
+ QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
+ &app, [url](QObject *obj, const QUrl &objUrl) {
+ if (!obj && url == objUrl)
+ QCoreApplication::exit(-1);
+ }, Qt::QueuedConnection);
+ engine.load(url);
+
+ return app.exec();
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.qml b/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.qml
new file mode 100644
index 0000000000..e08e19801f
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/attachedstyleproperties.qml
@@ -0,0 +1,110 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Layouts
+
+import MyStyle
+
+ApplicationWindow {
+ width: 800
+ height: 600
+ title: qsTr("Attached Objects")
+ visible: true
+
+ MyStyle.theme: darkModeSwitch.checked ? MyStyle.Dark : MyStyle.Light
+
+ header: ToolBar {
+ MyStyle.theme: MyStyle.Dark
+
+ RowLayout {
+ anchors.fill: parent
+ anchors.leftMargin: 12
+
+ Label {
+ text: qsTr("This is a Label in a ToolBar")
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Switch {
+ id: darkModeSwitch
+ text: qsTr("Dark mode")
+ }
+ }
+ }
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Label {
+ text: qsTr("This is a Label in an ApplicationWindow")
+ Layout.alignment: Qt.AlignHCenter
+ }
+
+ RowLayout {
+ Button {
+ text: qsTr("Open Popup")
+ onClicked: popup.open()
+ }
+
+ Button {
+ text: qsTr("Open Window")
+ onClicked: {
+ if (!childWindow.active)
+ childWindow.show()
+ else
+ childWindow.raise()
+ }
+ }
+ }
+ }
+
+ Popup {
+ id: popup
+ dim: true
+ anchors.centerIn: parent
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Label {
+ text: qsTr("This is a Label in a Popup")
+ Layout.alignment: Qt.AlignHCenter
+ }
+
+ Button {
+ text: qsTr("Close Popup")
+ Layout.alignment: Qt.AlignHCenter
+ onClicked: popup.close()
+ }
+ }
+ }
+
+ ApplicationWindow {
+ id: childWindow
+ width: 600
+ height: 400
+ title: qsTr("Attached Objects - Child Window")
+
+ ColumnLayout {
+ anchors.centerIn: parent
+ spacing: 20
+
+ Label {
+ text: qsTr("This is a Label in a child ApplicationWindow")
+ Layout.alignment: Qt.AlignHCenter
+ }
+
+ Button {
+ text: qsTr("Close Window")
+ Layout.alignment: Qt.AlignHCenter
+ onClicked: childWindow.close()
+ }
+ }
+ }
+}
diff --git a/examples/quickcontrols2/attachedstyleproperties/doc/images/qtquickcontrols2-attachedstyleproperties.png b/examples/quickcontrols2/attachedstyleproperties/doc/images/qtquickcontrols2-attachedstyleproperties.png
new file mode 100644
index 0000000000..2cd5f214f7
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/doc/images/qtquickcontrols2-attachedstyleproperties.png
Binary files differ
diff --git a/examples/quickcontrols2/attachedstyleproperties/doc/src/qtquickcontrols2-attachedstyleproperties.qdoc b/examples/quickcontrols2/attachedstyleproperties/doc/src/qtquickcontrols2-attachedstyleproperties.qdoc
new file mode 100644
index 0000000000..de43fc80bd
--- /dev/null
+++ b/examples/quickcontrols2/attachedstyleproperties/doc/src/qtquickcontrols2-attachedstyleproperties.qdoc
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example attachedstyleproperties
+ \keyword Qt Quick Controls - Attached Style Properties Example
+ \title Qt Quick Controls - Attached Style Properties Example
+ \ingroup qtquickcontrols2-examples
+ \brief Demonstrates use of QQuickAttachedPropertyPropagator.
+
+ \image qtquickcontrols2-attachedstyleproperties.png
+
+ The Attached Style Properties example is a simple application that shows
+ how to use \l QQuickAttachedPropertyPropagator to propagate attached
+ property values to child objects.
+
+ \include examples-run.qdocinc
+*/