diff options
| author | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2025-11-19 15:49:47 +0100 |
|---|---|---|
| committer | Richard Moe Gustavsen <richard.gustavsen@qt.io> | 2025-11-27 12:22:49 +0100 |
| commit | c056aaa055187af7290d363d5ef02a4948cd8813 (patch) | |
| tree | d5df750ffefe1d9dbb366177587a9b151d113c78 /src/labs/stylekit/qqstylekit.cpp | |
| parent | 8890b4a2d56ebdd51bf550d307f48d60ccf9a632 (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.cpp | 131 |
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" + |
