aboutsummaryrefslogtreecommitdiffstats
path: root/src/labs/stylekit/qqstylekit.cpp
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2025-11-19 15:49:47 +0100
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2025-11-27 12:22:49 +0100
commitc056aaa055187af7290d363d5ef02a4948cd8813 (patch)
treed5df750ffefe1d9dbb366177587a9b151d113c78 /src/labs/stylekit/qqstylekit.cpp
parent8890b4a2d56ebdd51bf550d307f48d60ccf9a632 (diff)
StyleKit: add StyleKit to labs
This patch introduces a new styling API for Controls called StyleKit. StyleKit provides a higher-level, key–value–based approach to styling applications, serving as an alternative to working directly with the lower-level Templates API. The primary goal of StyleKit is to offer a unified API for styling both Controls and Widgets. The current Templates-based approach relies heavily on JavaScript, which makes it unsuitable for use with Widgets. This initial version supports Controls only; support for Widgets will be added in a future update. StyleKit is designed to make it easier for designers and UI developers to: - Focus on visual styling rather than Template logic (such as geometry, delegate positioning, and handle placement). - Allow style properties to propagate, enabling you to factor out common styling into shared control types and override only what differs in the more specific control types. - Style controls independently in each of their states, without needing nested ternary expressions to check state. - Define and apply multiple themes with minimal effort. - Provide different style variations depending on context. For example, styling a Switch differently when it appears inside a ToolBar. [ChangeLog][Qt labs] Introduced new QML module 'StyleKit'. StyleKit provides a flexible styling framework for Qt Quick Controls, enabling developers to define reusable styles and themes using a simple key-value property format. Change-Id: Iae25324486aea7a7b9b2ce52135327ec7e9b6f59 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/labs/stylekit/qqstylekit.cpp')
-rw-r--r--src/labs/stylekit/qqstylekit.cpp131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/labs/stylekit/qqstylekit.cpp b/src/labs/stylekit/qqstylekit.cpp
new file mode 100644
index 0000000000..6f7ad2f2f3
--- /dev/null
+++ b/src/labs/stylekit/qqstylekit.cpp
@@ -0,0 +1,131 @@
+// Copyright (C) 2025 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 "qqstylekit_p.h"
+#include "qqstylekitstyle_p.h"
+#include "qqstylekittheme_p.h"
+#include "qqstylekitreader_p.h"
+
+#include <QtGui/QStyleHints>
+
+QT_BEGIN_NAMESPACE
+
+QPointer<QQStyleKitAttached> QQStyleKitAttached::s_instance;
+bool QQStyleKitAttached::s_transitionsEnabled = true;
+
+QQStyleKit::QQStyleKit(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QQStyleKitAttached *QQStyleKit::qmlAttachedProperties(QObject *obj)
+{
+ /* QQStyleKitAttached is a singleton. It doesn't matter where it's
+ * used from in the application, it will always represent the same
+ * application global style and theme. */
+ if (!QQStyleKitAttached::s_instance)
+ QQStyleKitAttached::s_instance = new QQStyleKitAttached(QGuiApplication::instance());
+ if (!QQStyleKitAttached::s_instance->m_engine && obj)
+ QQStyleKitAttached::s_instance->m_engine = qmlEngine(obj);
+ return QQStyleKitAttached::s_instance.get();
+}
+
+QQStyleKitAttached::QQStyleKitAttached(QObject *parent)
+ : QObject(parent)
+{
+ connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, [this](){
+ if (m_style)
+ m_style->recreateTheme();
+ });
+}
+
+QQStyleKitAttached::~QQStyleKitAttached()
+{
+ QQStyleKitAttached::s_instance = nullptr;
+ if (m_ownsStyle) {
+ delete m_style;
+ m_style = nullptr;
+ }
+}
+
+QQStyleKitStyle *QQStyleKitAttached::style() const
+{
+ return m_style;
+}
+
+void QQStyleKitAttached::setStyle(QQStyleKitStyle *style)
+{
+ if (m_style == style)
+ return;
+
+ if (m_ownsStyle)
+ m_style->deleteLater();
+
+ m_style = style;
+
+ if (m_style && m_style->m_theme)
+ m_style->m_theme->updateQuickTheme();
+ if (m_style->loaded())
+ QQStyleKitReader::resetAll();
+
+ emit styleChanged();
+}
+
+QString QQStyleKitAttached::styleUrl() const
+{
+ return m_styleUrl;
+}
+
+void QQStyleKitAttached::setStyleUrl(const QString &styleUrl)
+{
+ if (m_styleUrl == styleUrl)
+ return;
+
+ m_styleUrl = styleUrl;
+
+ Q_ASSERT(m_engine);
+ QQmlComponent comp(m_engine, QUrl(styleUrl), this);
+ if (!comp.errors().isEmpty()) {
+ qmlWarning(this) << "Could not create a StyleKit style: " << comp.errorString();
+ return;
+ }
+ auto *style = qobject_cast<QQStyleKitStyle *>(comp.create());
+ if (!style) {
+ qmlWarning(this) << "Could not create a StyleKit style from url: " << styleUrl;
+ return;
+ }
+
+ style->componentComplete();
+ setStyle(style);
+ m_ownsStyle = true;
+ emit styleUrlChanged();
+}
+
+bool QQStyleKitAttached::transitionsEnabled() const
+{
+ return s_transitionsEnabled;
+}
+
+void QQStyleKitAttached::setTransitionsEnabled(bool enabled)
+{
+ if (enabled == s_transitionsEnabled)
+ return;
+
+ s_transitionsEnabled = enabled;
+ emit transitionsEnabledChanged();
+}
+
+QQStyleKitDebug *QQStyleKitAttached::debug() const
+{
+ return &const_cast<QQStyleKitAttached *>(this)->m_debug;
+}
+
+bool QQStyleKitAttached::styleLoaded() const
+{
+ return m_style && m_style->loaded();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qqstylekit_p.cpp"
+