Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqstylekitdelegate.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <QtQuick/private/qquickrectangle_p.h>
8#include <QtQuick/private/qquickimplicitsizeitem_p_p.h>
9#include <QtQuickControls2Impl/private/qquickcolorimage_p.h>
10
12
14 : QQuickImplicitSizeItem(*new QQuickImplicitSizeItemPrivate, parent)
15{
16}
17
18QQStyleKitDelegateProperties *QQStyleKitDelegate::delegateProperties() const
19{
20 return m_delegateProperties;
21}
22
23void QQStyleKitDelegate::setDelegateProperties(QQStyleKitDelegateProperties *delegateProperties)
24{
25 if (m_delegateProperties == delegateProperties)
26 return;
27
28 if (m_delegateProperties)
29 disconnect(m_delegateProperties, nullptr, this, nullptr);
30
31 m_delegateProperties = delegateProperties;
32
33 if (!qmlEngine(this)) {
34 qmlWarning(this) << "Unable to draw delegate: no QQmlEngine found";
35 return;
36 }
37
38 maybeCreateColor();
39 maybeCreateGradient();
40 maybeCreateImage();
41 updateImplicitSize();
42
43 connect(m_delegateProperties, &QQStyleKitDelegateProperties::implicitWidthChanged, this, &QQStyleKitDelegate::updateImplicitSize);
44 connect(m_delegateProperties, &QQStyleKitDelegateProperties::implicitHeightChanged, this, &QQStyleKitDelegate::updateImplicitSize);
45
46 emit delegatePropertiesChanged();
47}
48
49void QQStyleKitDelegate::updateImplicitSize()
50{
51 if (!m_delegateProperties)
52 return;
53
54 /* The implicit size is determined by the following priority:
55 * 1. Explicit implicit size set on StyleKitDelegateProperties
56 * 2. Implicit size of the image (if present)
57 * 3. Zero
58 * The implicit size is read-only because it's calculated in C++ from internal
59 * child items that are intentionally not exposed to QML. */
60 const qreal impWidthInStyle = m_delegateProperties->implicitWidth();
61 const qreal impHeightInStyle = m_delegateProperties->implicitHeight();
62 setImplicitWidth(impWidthInStyle > 0 || !m_imageOverlay ? impWidthInStyle : m_imageOverlay->implicitWidth());
63 setImplicitHeight(impHeightInStyle > 0 || !m_imageOverlay ? impHeightInStyle : m_imageOverlay->implicitHeight());
64}
65
66void QQStyleKitDelegate::maybeCreateColor()
67{
68 if (m_colorOverlay)
69 return;
70 if (!m_delegateProperties)
71 return;
72 if (m_delegateProperties->color().alpha() == 0) {
73 connect(m_delegateProperties, &QQStyleKitDelegateProperties::colorChanged,
74 this, &QQStyleKitDelegate::maybeCreateColor, Qt::UniqueConnection);
75 return;
76 }
77
78 disconnect(m_delegateProperties, &QQStyleKitDelegateProperties::colorChanged,
79 this, &QQStyleKitDelegate::maybeCreateColor);
80
81 QQmlEngine *engine = qmlEngine(this);
82 Q_ASSERT(engine);
83 static QQmlComponent *component = nullptr;
84 if (!component || component->engine() != engine) {
85 delete component;
86 component = new QQmlComponent(engine);
87 const QString qmlCode = QString::fromUtf8(R"(
88 import QtQuick
89 Rectangle {
90 z: -3
91 width: parent.width
92 height: parent.height
93 visible: delegateProperties.visible
94 color: delegateProperties.color
95 topLeftRadius: delegateProperties.topLeftRadius
96 topRightRadius: delegateProperties.topRightRadius
97 bottomLeftRadius: delegateProperties.bottomLeftRadius
98 bottomRightRadius: delegateProperties.bottomRightRadius
99 border.width: delegateProperties.border.width
100 border.color: delegateProperties.border.color
101 }
102 )");
103 component->setData(qmlCode.toUtf8(), QUrl());
104 Q_ASSERT_X(!component->isError(), __FUNCTION__, component->errorString().toUtf8().constData());
105 }
106
107 QQmlContext *ctx = QQmlEngine::contextForObject(this);
108 m_colorOverlay = qobject_cast<QQuickItem*>(component->beginCreate(ctx));
109 Q_ASSERT(m_colorOverlay);
110 m_colorOverlay->setParent(this);
111 m_colorOverlay->setParentItem(this);
112 component->completeCreate();
113}
114
115void QQStyleKitDelegate::maybeCreateGradient()
116{
117 /* Unlike a Rectangle, a StyleKitDelegate draws both the color and the gradient at
118 * the same time. This allows a style to define them independently. That way you can
119 * define a common semi-transparent grayscale gradient once for a delegate in the style
120 * (e.g for control.background.gradient), and then tint it with different colors for
121 * different controls, states, or themes (e.g for button.hovered.background.color). */
122 if (m_gradientOverlay)
123 return;
124 if (!m_delegateProperties)
125 return;
126 if (!m_delegateProperties->gradient()) {
127 connect(m_delegateProperties, &QQStyleKitDelegateProperties::gradientChanged,
128 this, &QQStyleKitDelegate::maybeCreateGradient, Qt::UniqueConnection);
129 return;
130 }
131
132 disconnect(m_delegateProperties, &QQStyleKitDelegateProperties::gradientChanged,
133 this, &QQStyleKitDelegate::maybeCreateGradient);
134
135 QQmlEngine *engine = qmlEngine(this);
136 Q_ASSERT(engine);
137 static QQmlComponent *component = nullptr;
138 if (!component || component->engine() != engine) {
139 delete component;
140 component = new QQmlComponent(engine);
141 const QString qmlCode = QString::fromUtf8(R"(
142 import QtQuick
143 Rectangle {
144 z: -2
145 width: parent.width
146 height: parent.height
147 visible: delegateProperties.visible
148 color: "transparent"
149 gradient: delegateProperties.gradient
150 topLeftRadius: delegateProperties.topLeftRadius
151 topRightRadius: delegateProperties.topRightRadius
152 bottomLeftRadius: delegateProperties.bottomLeftRadius
153 bottomRightRadius: delegateProperties.bottomRightRadius
154 border.width: delegateProperties.border.width
155 border.color: delegateProperties.border.color
156 }
157 )");
158 component->setData(qmlCode.toUtf8(), QUrl());
159 Q_ASSERT_X(!component->isError(), __FUNCTION__, component->errorString().toUtf8().constData());
160 }
161
162 QQmlContext *ctx = QQmlEngine::contextForObject(this);
163 m_gradientOverlay = qobject_cast<QQuickItem*>(component->beginCreate(ctx));
164 Q_ASSERT(m_gradientOverlay);
165 m_gradientOverlay->setParent(this);
166 m_gradientOverlay->setParentItem(this);
167 component->completeCreate();
168}
169
170void QQStyleKitDelegate::maybeCreateImage()
171{
172 if (m_imageOverlay)
173 return;
174 if (!m_delegateProperties)
175 return;
176 if (m_delegateProperties->image()->source().isEmpty()
177 || m_delegateProperties->image()->color().alpha() == 0) {
178 connect(m_delegateProperties->image(), &QQStyleKitImageProperties::sourceChanged,
179 this, &QQStyleKitDelegate::maybeCreateImage, Qt::UniqueConnection);
180 connect(m_delegateProperties->image(), &QQStyleKitImageProperties::colorChanged,
181 this, &QQStyleKitDelegate::maybeCreateImage, Qt::UniqueConnection);
182 return;
183 }
184
185 disconnect(m_delegateProperties->image(), &QQStyleKitImageProperties::sourceChanged,
186 this, &QQStyleKitDelegate::maybeCreateImage);
187 disconnect(m_delegateProperties->image(), &QQStyleKitImageProperties::colorChanged,
188 this, &QQStyleKitDelegate::maybeCreateImage);
189
190 QQmlEngine *engine = qmlEngine(this);
191 Q_ASSERT(engine);
192 static QQmlComponent *component = nullptr;
193 if (!component || component->engine() != engine) {
194 delete component;
195 component = new QQmlComponent(engine);
196 const QString qmlCode = QString::fromUtf8(R"(
197 import QtQuick.Controls.impl
198 ColorImage {
199 z: -1
200 width: parent.width
201 height: parent.height
202 visible: delegateProperties.visible
203 color: delegateProperties.image.color
204 source: delegateProperties.image.source
205 fillMode: delegateProperties.image.fillMode
206 }
207 )");
208 component->setData(qmlCode.toUtf8(), QUrl());
209 Q_ASSERT_X(!component->isError(), __FUNCTION__, component->errorString().toUtf8().constData());
210 }
211
212 QQmlContext *ctx = QQmlEngine::contextForObject(this);
213 m_imageOverlay = qobject_cast<QQuickItem*>(component->beginCreate(ctx));
214 m_imageOverlay->setParent(this);
215 m_imageOverlay->setParentItem(this);
216 component->completeCreate();
217
218 updateImplicitSize();
219 connect(m_imageOverlay, &QQuickItem::implicitWidthChanged, this, &QQStyleKitDelegate::updateImplicitSize);
220 connect(m_imageOverlay, &QQuickItem::implicitHeightChanged, this, &QQStyleKitDelegate::updateImplicitSize);
221}
222
223QT_END_NAMESPACE
224
225#include "moc_qqstylekitdelegate_p.cpp"
QQStyleKitDelegateProperties * delegateProperties() const
void setDelegateProperties(QQStyleKitDelegateProperties *delegateProperties)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:64
Combined button and popup list for selecting options.