1// Copyright (C) 2017 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
4#include "qquickgroupbox_p.h"
5#include "qquickframe_p_p.h"
6#include "qquickdeferredexecute_p_p.h"
7
8#include <QtGui/qpa/qplatformtheme.h>
9
10QT_BEGIN_NAMESPACE
11
12/*!
13 \qmltype GroupBox
14 \inherits Frame
15//! \instantiates QQuickGroupBox
16 \inqmlmodule QtQuick.Controls
17 \since 5.7
18 \ingroup qtquickcontrols-containers
19 \brief Visual frame and title for a logical group of controls.
20
21 GroupBox is used to layout a logical group of controls together, within
22 a \l {title}{titled} visual frame. GroupBox does not provide a layout of its own, but
23 requires you to position its contents, for instance by creating a \l RowLayout
24 or a \l ColumnLayout.
25
26 Items declared as children of a GroupBox are automatically parented to the
27 GroupBox's \l {Control::}{contentItem}. Items created dynamically need to be
28 explicitly parented to the contentItem.
29
30 If only a single item is used within a GroupBox, it will resize to fit the
31 implicit size of its contained item. This makes it particularly suitable
32 for use together with layouts.
33
34 \image qtquickcontrols-groupbox.png
35
36 \snippet qtquickcontrols-groupbox.qml 1
37
38 \section2 Checkable GroupBox
39
40 Even though GroupBox has no built-in check box, it is straightforward
41 to create a checkable GroupBox by pairing it with a CheckBox.
42
43 \image qtquickcontrols-groupbox-checkable.png
44
45 It is a common pattern to enable or disable the groupbox's children when
46 its checkbox is toggled on or off, but it is up to the application to decide
47 on the behavior of the checkbox.
48
49 \snippet qtquickcontrols-groupbox-checkable.qml 1
50
51 \sa CheckBox, {Customizing GroupBox}, {Container Controls}
52*/
53
54class QQuickGroupBoxPrivate : public QQuickFramePrivate
55{
56 Q_DECLARE_PUBLIC(QQuickGroupBox)
57
58public:
59 void cancelLabel();
60 void executeLabel(bool complete = false);
61
62 void itemImplicitWidthChanged(QQuickItem *item) override;
63 void itemImplicitHeightChanged(QQuickItem *item) override;
64
65 QPalette defaultPalette() const override { return QQuickTheme::palette(scope: QQuickTheme::GroupBox); }
66
67 QString title;
68 QQuickDeferredPointer<QQuickItem> label;
69};
70
71static inline QString labelName() { return QStringLiteral("label"); }
72
73void QQuickGroupBoxPrivate::cancelLabel()
74{
75 Q_Q(QQuickGroupBox);
76 quickCancelDeferred(object: q, property: labelName());
77}
78
79void QQuickGroupBoxPrivate::executeLabel(bool complete)
80{
81 Q_Q(QQuickGroupBox);
82 if (label.wasExecuted())
83 return;
84
85 if (!label || complete)
86 quickBeginDeferred(object: q, property: labelName(), delegate&: label);
87 if (complete)
88 quickCompleteDeferred(object: q, property: labelName(), delegate&: label);
89}
90
91void QQuickGroupBoxPrivate::itemImplicitWidthChanged(QQuickItem *item)
92{
93 Q_Q(QQuickGroupBox);
94 QQuickFramePrivate::itemImplicitWidthChanged(item);
95 if (item == label)
96 emit q->implicitLabelWidthChanged();
97}
98
99void QQuickGroupBoxPrivate::itemImplicitHeightChanged(QQuickItem *item)
100{
101 Q_Q(QQuickGroupBox);
102 QQuickFramePrivate::itemImplicitHeightChanged(item);
103 if (item == label)
104 emit q->implicitLabelHeightChanged();
105}
106
107QQuickGroupBox::QQuickGroupBox(QQuickItem *parent)
108 : QQuickFrame(*(new QQuickGroupBoxPrivate), parent)
109{
110}
111
112QQuickGroupBox::~QQuickGroupBox()
113{
114 Q_D(QQuickGroupBox);
115 d->removeImplicitSizeListener(item: d->label);
116}
117
118/*!
119 \qmlproperty string QtQuick.Controls::GroupBox::title
120
121 This property holds the title.
122
123 The title is typically displayed above the groupbox to
124 summarize its contents.
125*/
126QString QQuickGroupBox::title() const
127{
128 Q_D(const QQuickGroupBox);
129 return d->title;
130}
131
132void QQuickGroupBox::setTitle(const QString &title)
133{
134 Q_D(QQuickGroupBox);
135 if (d->title == title)
136 return;
137
138 d->title = title;
139 maybeSetAccessibleName(name: title);
140 emit titleChanged();
141}
142
143/*!
144 \qmlproperty Item QtQuick.Controls::GroupBox::label
145
146 This property holds the label item that visualizes \l title.
147
148 \sa {Customizing GroupBox}
149*/
150QQuickItem *QQuickGroupBox::label() const
151{
152 QQuickGroupBoxPrivate *d = const_cast<QQuickGroupBoxPrivate *>(d_func());
153 if (!d->label)
154 d->executeLabel();
155 return d->label;
156}
157
158void QQuickGroupBox::setLabel(QQuickItem *label)
159{
160 Q_D(QQuickGroupBox);
161 if (d->label == label)
162 return;
163
164 QQuickControlPrivate::warnIfCustomizationNotSupported(control: this, item: label, QStringLiteral("label"));
165
166 if (!d->label.isExecuting())
167 d->cancelLabel();
168
169 const qreal oldImplicitLabelWidth = implicitLabelWidth();
170 const qreal oldImplicitLabelHeight = implicitLabelHeight();
171
172 d->removeImplicitSizeListener(item: d->label);
173 QQuickControlPrivate::hideOldItem(item: d->label);
174 d->label = label;
175
176 if (label) {
177 if (!label->parentItem())
178 label->setParentItem(this);
179 d->addImplicitSizeListener(item: label);
180 }
181
182 if (!qFuzzyCompare(p1: oldImplicitLabelWidth, p2: implicitLabelWidth()))
183 emit implicitLabelWidthChanged();
184 if (!qFuzzyCompare(p1: oldImplicitLabelHeight, p2: implicitLabelHeight()))
185 emit implicitLabelHeightChanged();
186 if (!d->label.isExecuting())
187 emit labelChanged();
188}
189
190/*!
191 \since QtQuick.Controls 2.5 (Qt 5.12)
192 \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelWidth
193 \readonly
194
195 This property holds the implicit label width.
196
197 The value is equal to \c {label ? label.implicitWidth : 0}.
198
199 \sa implicitLabelHeight
200*/
201qreal QQuickGroupBox::implicitLabelWidth() const
202{
203 Q_D(const QQuickGroupBox);
204 if (!d->label)
205 return 0;
206 return d->label->implicitWidth();
207}
208
209/*!
210 \since QtQuick.Controls 2.5 (Qt 5.12)
211 \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelHeight
212 \readonly
213
214 This property holds the implicit label height.
215
216 The value is equal to \c {label ? label.implicitHeight : 0}.
217
218 \sa implicitLabelWidth
219*/
220qreal QQuickGroupBox::implicitLabelHeight() const
221{
222 Q_D(const QQuickGroupBox);
223 if (!d->label)
224 return 0;
225 return d->label->implicitHeight();
226}
227
228void QQuickGroupBox::componentComplete()
229{
230 Q_D(QQuickGroupBox);
231 d->executeLabel(complete: true);
232 QQuickFrame::componentComplete();
233}
234
235QFont QQuickGroupBox::defaultFont() const
236{
237 return QQuickTheme::font(scope: QQuickTheme::GroupBox);
238}
239
240#if QT_CONFIG(accessibility)
241QAccessible::Role QQuickGroupBox::accessibleRole() const
242{
243 return QAccessible::Grouping;
244}
245
246void QQuickGroupBox::accessibilityActiveChanged(bool active)
247{
248 Q_D(QQuickGroupBox);
249 QQuickFrame::accessibilityActiveChanged(active);
250
251 if (active)
252 maybeSetAccessibleName(name: d->title);
253}
254#endif
255
256QT_END_NAMESPACE
257
258#include "moc_qquickgroupbox_p.cpp"
259

source code of qtdeclarative/src/quicktemplates/qquickgroupbox.cpp