1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Quick Templates 2 module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #include "qquickgroupbox_p.h"
38 #include "qquickframe_p_p.h"
39 #include "qquickdeferredexecute_p_p.h"
40 
41 #include <QtGui/qpa/qplatformtheme.h>
42 
43 QT_BEGIN_NAMESPACE
44 
45 /*!
46     \qmltype GroupBox
47     \inherits Frame
48 //!     \instantiates QQuickGroupBox
49     \inqmlmodule QtQuick.Controls
50     \since 5.7
51     \ingroup qtquickcontrols2-containers
52     \brief Visual frame and title for a logical group of controls.
53 
54     GroupBox is used to layout a logical group of controls together, within
55     a \l {title}{titled} visual frame. GroupBox does not provide a layout of its own, but
56     requires you to position its contents, for instance by creating a \l RowLayout
57     or a \l ColumnLayout.
58 
59     Items declared as children of a GroupBox are automatically parented to the
60     GroupBox's \l {Control::}{contentItem}. Items created dynamically need to be
61     explicitly parented to the contentItem.
62 
63     If only a single item is used within a GroupBox, it will resize to fit the
64     implicit size of its contained item. This makes it particularly suitable
65     for use together with layouts.
66 
67     \image qtquickcontrols2-groupbox.png
68 
69     \snippet qtquickcontrols2-groupbox.qml 1
70 
71     \section2 Checkable GroupBox
72 
73     Even though GroupBox has no built-in check box, it is straightforward
74     to create a checkable GroupBox by pairing it with a CheckBox.
75 
76     \image qtquickcontrols2-groupbox-checkable.png
77 
78     It is a common pattern to enable or disable the groupbox's children when
79     its checkbox is toggled on or off, but it is up to the application to decide
80     on the behavior of the checkbox.
81 
82     \snippet qtquickcontrols2-groupbox-checkable.qml 1
83 
84     \sa CheckBox, {Customizing GroupBox}, {Container Controls}
85 */
86 
87 class QQuickGroupBoxPrivate : public QQuickFramePrivate
88 {
89     Q_DECLARE_PUBLIC(QQuickGroupBox)
90 
91 public:
92     void cancelLabel();
93     void executeLabel(bool complete = false);
94 
95     void itemImplicitWidthChanged(QQuickItem *item) override;
96     void itemImplicitHeightChanged(QQuickItem *item) override;
97 
98     QString title;
99     QQuickDeferredPointer<QQuickItem> label;
100 };
101 
labelName()102 static inline QString labelName() { return QStringLiteral("label"); }
103 
cancelLabel()104 void QQuickGroupBoxPrivate::cancelLabel()
105 {
106     Q_Q(QQuickGroupBox);
107     quickCancelDeferred(q, labelName());
108 }
109 
executeLabel(bool complete)110 void QQuickGroupBoxPrivate::executeLabel(bool complete)
111 {
112     Q_Q(QQuickGroupBox);
113     if (label.wasExecuted())
114         return;
115 
116     if (!label || complete)
117         quickBeginDeferred(q, labelName(), label);
118     if (complete)
119         quickCompleteDeferred(q, labelName(), label);
120 }
121 
itemImplicitWidthChanged(QQuickItem * item)122 void QQuickGroupBoxPrivate::itemImplicitWidthChanged(QQuickItem *item)
123 {
124     Q_Q(QQuickGroupBox);
125     QQuickFramePrivate::itemImplicitWidthChanged(item);
126     if (item == label)
127         emit q->implicitLabelWidthChanged();
128 }
129 
itemImplicitHeightChanged(QQuickItem * item)130 void QQuickGroupBoxPrivate::itemImplicitHeightChanged(QQuickItem *item)
131 {
132     Q_Q(QQuickGroupBox);
133     QQuickFramePrivate::itemImplicitHeightChanged(item);
134     if (item == label)
135         emit q->implicitLabelHeightChanged();
136 }
137 
QQuickGroupBox(QQuickItem * parent)138 QQuickGroupBox::QQuickGroupBox(QQuickItem *parent)
139     : QQuickFrame(*(new QQuickGroupBoxPrivate), parent)
140 {
141 }
142 
~QQuickGroupBox()143 QQuickGroupBox::~QQuickGroupBox()
144 {
145     Q_D(QQuickGroupBox);
146     d->removeImplicitSizeListener(d->label);
147 }
148 
149 /*!
150     \qmlproperty string QtQuick.Controls::GroupBox::title
151 
152     This property holds the title.
153 
154     The title is typically displayed above the groupbox to
155     summarize its contents.
156 */
title() const157 QString QQuickGroupBox::title() const
158 {
159     Q_D(const QQuickGroupBox);
160     return d->title;
161 }
162 
setTitle(const QString & title)163 void QQuickGroupBox::setTitle(const QString &title)
164 {
165     Q_D(QQuickGroupBox);
166     if (d->title == title)
167         return;
168 
169     d->title = title;
170     maybeSetAccessibleName(title);
171     emit titleChanged();
172 }
173 
174 /*!
175     \qmlproperty Item QtQuick.Controls::GroupBox::label
176 
177     This property holds the label item that visualizes \l title.
178 
179     \sa {Customizing GroupBox}
180 */
label() const181 QQuickItem *QQuickGroupBox::label() const
182 {
183     QQuickGroupBoxPrivate *d = const_cast<QQuickGroupBoxPrivate *>(d_func());
184     if (!d->label)
185         d->executeLabel();
186     return d->label;
187 }
188 
setLabel(QQuickItem * label)189 void QQuickGroupBox::setLabel(QQuickItem *label)
190 {
191     Q_D(QQuickGroupBox);
192     if (d->label == label)
193         return;
194 
195     if (!d->label.isExecuting())
196         d->cancelLabel();
197 
198     const qreal oldImplicitLabelWidth = implicitLabelWidth();
199     const qreal oldImplicitLabelHeight = implicitLabelHeight();
200 
201     d->removeImplicitSizeListener(d->label);
202     QQuickControlPrivate::hideOldItem(d->label);
203     d->label = label;
204 
205     if (label) {
206         if (!label->parentItem())
207             label->setParentItem(this);
208         d->addImplicitSizeListener(label);
209     }
210 
211     if (!qFuzzyCompare(oldImplicitLabelWidth, implicitLabelWidth()))
212         emit implicitLabelWidthChanged();
213     if (!qFuzzyCompare(oldImplicitLabelHeight, implicitLabelHeight()))
214         emit implicitLabelHeightChanged();
215     if (!d->label.isExecuting())
216         emit labelChanged();
217 }
218 
219 /*!
220     \since QtQuick.Controls 2.5 (Qt 5.12)
221     \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelWidth
222     \readonly
223 
224     This property holds the implicit label width.
225 
226     The value is equal to \c {label ? label.implicitWidth : 0}.
227 
228     \sa implicitLabelHeight
229 */
implicitLabelWidth() const230 qreal QQuickGroupBox::implicitLabelWidth() const
231 {
232     Q_D(const QQuickGroupBox);
233     if (!d->label)
234         return 0;
235     return d->label->implicitWidth();
236 }
237 
238 /*!
239     \since QtQuick.Controls 2.5 (Qt 5.12)
240     \qmlproperty real QtQuick.Controls::GroupBox::implicitLabelHeight
241     \readonly
242 
243     This property holds the implicit label height.
244 
245     The value is equal to \c {label ? label.implicitHeight : 0}.
246 
247     \sa implicitLabelWidth
248 */
implicitLabelHeight() const249 qreal QQuickGroupBox::implicitLabelHeight() const
250 {
251     Q_D(const QQuickGroupBox);
252     if (!d->label)
253         return 0;
254     return d->label->implicitHeight();
255 }
256 
componentComplete()257 void QQuickGroupBox::componentComplete()
258 {
259     Q_D(QQuickGroupBox);
260     d->executeLabel(true);
261     QQuickFrame::componentComplete();
262 }
263 
defaultFont() const264 QFont QQuickGroupBox::defaultFont() const
265 {
266     return QQuickTheme::font(QQuickTheme::GroupBox);
267 }
268 
defaultPalette() const269 QPalette QQuickGroupBox::defaultPalette() const
270 {
271     return QQuickTheme::palette(QQuickTheme::GroupBox);
272 }
273 
274 #if QT_CONFIG(accessibility)
accessibleRole() const275 QAccessible::Role QQuickGroupBox::accessibleRole() const
276 {
277     return QAccessible::Grouping;
278 }
279 
accessibilityActiveChanged(bool active)280 void QQuickGroupBox::accessibilityActiveChanged(bool active)
281 {
282     Q_D(QQuickGroupBox);
283     QQuickFrame::accessibilityActiveChanged(active);
284 
285     if (active)
286         maybeSetAccessibleName(d->title);
287 }
288 #endif
289 
290 QT_END_NAMESPACE
291