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 "qquickpane_p.h"
38#include "qquickpane_p_p.h"
39#include "qquickcontentitem_p.h"
40
41QT_BEGIN_NAMESPACE
42
43/*!
44 \qmltype Pane
45 \inherits Control
46//! \instantiates QQuickPane
47 \inqmlmodule QtQuick.Controls
48 \since 5.7
49 \ingroup qtquickcontrols2-containers
50 \ingroup qtquickcontrols2-focusscopes
51 \brief Provides a background matching with the application style and theme.
52
53 Pane provides a background color that matches with the application style
54 and theme. Pane does not provide a layout of its own, but requires you to
55 position its contents, for instance by creating a \l RowLayout or a
56 \l ColumnLayout.
57
58 Items declared as children of a Pane are automatically parented to the
59 Pane's \l[QtQuickControls2]{Control::}{contentItem}. Items created
60 dynamically need to be explicitly parented to the contentItem.
61
62 \section1 Content Sizing
63
64 If only a single item is used within a Pane, it will resize to fit the
65 implicit size of its contained item. This makes it particularly suitable
66 for use together with layouts.
67
68 \image qtquickcontrols2-pane.png
69
70 \snippet qtquickcontrols2-pane.qml 1
71
72 Sometimes there might be two items within the pane:
73
74 \code
75 Pane {
76 SwipeView {
77 // ...
78 }
79 PageIndicator {
80 anchors.horizontalCenter: parent.horizontalCenter
81 anchors.bottom: parent.bottom
82 }
83 }
84 \endcode
85
86 In this case, Pane cannot calculate a sensible implicit size. Since we're
87 anchoring the \l PageIndicator over the \l SwipeView, we can simply set the
88 content size to the view's implicit size:
89
90 \code
91 Pane {
92 contentWidth: view.implicitWidth
93 contentHeight: view.implicitHeight
94
95 SwipeView {
96 id: view
97 // ...
98 }
99 PageIndicator {
100 anchors.horizontalCenter: parent.horizontalCenter
101 anchors.bottom: parent.bottom
102 }
103 }
104 \endcode
105
106 If the \l contentItem has no implicit size and only one child, Pane will
107 use the implicit size of that child. For example, in the following code,
108 the Pane will assume the size of the Rectangle:
109
110 \code
111 Pane {
112 Item {
113 Rectangle {
114 implicitWidth: 200
115 implicitHeight: 200
116 color: "salmon"
117 }
118 }
119 }
120 \endcode
121
122 \sa {Customizing Pane}, {Container Controls},
123 {Focus Management in Qt Quick Controls}, {Event Handling}
124*/
125
126void QQuickPanePrivate::init()
127{
128 Q_Q(QQuickPane);
129 q->setFlag(flag: QQuickItem::ItemIsFocusScope);
130 q->setAcceptedMouseButtons(Qt::AllButtons);
131#if QT_CONFIG(cursor)
132 q->setCursor(Qt::ArrowCursor);
133#endif
134 connect(sender: q, signal: &QQuickControl::implicitContentWidthChanged, receiverPrivate: this, slot: &QQuickPanePrivate::updateContentWidth);
135 connect(sender: q, signal: &QQuickControl::implicitContentHeightChanged, receiverPrivate: this, slot: &QQuickPanePrivate::updateContentHeight);
136}
137
138QList<QQuickItem *> QQuickPanePrivate::contentChildItems() const
139{
140 if (!contentItem)
141 return QList<QQuickItem *>();
142
143 return contentItem->childItems();
144}
145
146QQuickItem *QQuickPanePrivate::getContentItem()
147{
148 Q_Q(QQuickPane);
149 if (QQuickItem *item = QQuickControlPrivate::getContentItem())
150 return item;
151
152 return new QQuickContentItem(q);
153}
154
155void QQuickPanePrivate::itemImplicitWidthChanged(QQuickItem *item)
156{
157 QQuickControlPrivate::itemImplicitWidthChanged(item);
158
159 if (item == firstChild)
160 updateImplicitContentWidth();
161}
162
163void QQuickPanePrivate::itemImplicitHeightChanged(QQuickItem *item)
164{
165 QQuickControlPrivate::itemImplicitHeightChanged(item);
166
167 if (item == firstChild)
168 updateImplicitContentHeight();
169}
170
171void QQuickPanePrivate::contentChildrenChange()
172{
173 Q_Q(QQuickPane);
174 QQuickItem *newFirstChild = contentChildItems().value(i: 0);
175 if (newFirstChild != firstChild) {
176 if (firstChild)
177 removeImplicitSizeListener(item: firstChild);
178 if (newFirstChild)
179 addImplicitSizeListener(item: newFirstChild);
180 firstChild = newFirstChild;
181 }
182
183 updateImplicitContentSize();
184 emit q->contentChildrenChanged();
185}
186
187qreal QQuickPanePrivate::getContentWidth() const
188{
189 if (!contentItem)
190 return 0;
191
192 const qreal cw = contentItem->implicitWidth();
193 if (!qFuzzyIsNull(d: cw))
194 return cw;
195
196 const auto contentChildren = contentChildItems();
197 if (contentChildren.count() == 1)
198 return contentChildren.first()->implicitWidth();
199
200 return 0;
201}
202
203qreal QQuickPanePrivate::getContentHeight() const
204{
205 if (!contentItem)
206 return 0;
207
208 const qreal ch = contentItem->implicitHeight();
209 if (!qFuzzyIsNull(d: ch))
210 return ch;
211
212 const auto contentChildren = contentChildItems();
213 if (contentChildren.count() == 1)
214 return contentChildren.first()->implicitHeight();
215
216 return 0;
217}
218
219void QQuickPanePrivate::updateContentWidth()
220{
221 Q_Q(QQuickPane);
222 if (hasContentWidth || qFuzzyCompare(p1: contentWidth, p2: implicitContentWidth))
223 return;
224
225 const qreal oldContentWidth = contentWidth;
226 contentWidth = implicitContentWidth;
227 q->contentSizeChange(newSize: QSizeF(contentWidth, contentHeight), oldSize: QSizeF(oldContentWidth, contentHeight));
228 emit q->contentWidthChanged();
229}
230
231void QQuickPanePrivate::updateContentHeight()
232{
233 Q_Q(QQuickPane);
234 if (hasContentHeight || qFuzzyCompare(p1: contentHeight, p2: implicitContentHeight))
235 return;
236
237 const qreal oldContentHeight = contentHeight;
238 contentHeight = implicitContentHeight;
239 q->contentSizeChange(newSize: QSizeF(contentWidth, contentHeight), oldSize: QSizeF(contentWidth, oldContentHeight));
240 emit q->contentHeightChanged();
241}
242
243QQuickPane::QQuickPane(QQuickItem *parent)
244 : QQuickControl(*(new QQuickPanePrivate), parent)
245{
246 Q_D(QQuickPane);
247 d->init();
248}
249
250QQuickPane::~QQuickPane()
251{
252 Q_D(QQuickPane);
253 d->removeImplicitSizeListener(item: d->contentItem);
254 d->removeImplicitSizeListener(item: d->firstChild);
255}
256
257QQuickPane::QQuickPane(QQuickPanePrivate &dd, QQuickItem *parent)
258 : QQuickControl(dd, parent)
259{
260 Q_D(QQuickPane);
261 d->init();
262}
263
264/*!
265 \qmlproperty real QtQuick.Controls::Pane::contentWidth
266
267 This property holds the content width. It is used for calculating the total
268 implicit width of the pane.
269
270 For more information, see \l {Content Sizing}.
271
272 \sa contentHeight
273*/
274qreal QQuickPane::contentWidth() const
275{
276 Q_D(const QQuickPane);
277 return d->contentWidth;
278}
279
280void QQuickPane::setContentWidth(qreal width)
281{
282 Q_D(QQuickPane);
283 d->hasContentWidth = true;
284 if (qFuzzyCompare(p1: d->contentWidth, p2: width))
285 return;
286
287 const qreal oldWidth = d->contentWidth;
288 d->contentWidth = width;
289 contentSizeChange(newSize: QSizeF(width, d->contentHeight), oldSize: QSizeF(oldWidth, d->contentHeight));
290 emit contentWidthChanged();
291}
292
293void QQuickPane::resetContentWidth()
294{
295 Q_D(QQuickPane);
296 if (!d->hasContentWidth)
297 return;
298
299 d->hasContentHeight = false;
300 d->updateContentWidth();
301}
302
303/*!
304 \qmlproperty real QtQuick.Controls::Pane::contentHeight
305
306 This property holds the content height. It is used for calculating the total
307 implicit height of the pane.
308
309 For more information, see \l {Content Sizing}.
310
311 \sa contentWidth
312*/
313qreal QQuickPane::contentHeight() const
314{
315 Q_D(const QQuickPane);
316 return d->contentHeight;
317}
318
319void QQuickPane::setContentHeight(qreal height)
320{
321 Q_D(QQuickPane);
322 d->hasContentHeight = true;
323 if (qFuzzyCompare(p1: d->contentHeight, p2: height))
324 return;
325
326 const qreal oldHeight = d->contentHeight;
327 d->contentHeight = height;
328 contentSizeChange(newSize: QSizeF(d->contentWidth, height), oldSize: QSizeF(d->contentWidth, oldHeight));
329 emit contentHeightChanged();
330}
331
332void QQuickPane::resetContentHeight()
333{
334 Q_D(QQuickPane);
335 if (!d->hasContentHeight)
336 return;
337
338 d->hasContentHeight = false;
339 d->updateContentHeight();
340}
341
342/*!
343 \qmlproperty list<Object> QtQuick.Controls::Pane::contentData
344 \default
345
346 This property holds the list of content data.
347
348 The list contains all objects that have been declared in QML as children
349 of the pane.
350
351 \note Unlike \c contentChildren, \c contentData does include non-visual QML
352 objects.
353
354 \sa Item::data, contentChildren
355*/
356QQmlListProperty<QObject> QQuickPanePrivate::contentData()
357{
358 Q_Q(QQuickPane);
359 return QQmlListProperty<QObject>(q->contentItem(), nullptr,
360 QQuickItemPrivate::data_append,
361 QQuickItemPrivate::data_count,
362 QQuickItemPrivate::data_at,
363 QQuickItemPrivate::data_clear);
364}
365
366/*!
367 \qmlproperty list<Item> QtQuick.Controls::Pane::contentChildren
368
369 This property holds the list of content children.
370
371 The list contains all items that have been declared in QML as children
372 of the pane.
373
374 \note Unlike \c contentData, \c contentChildren does not include non-visual
375 QML objects.
376
377 \sa Item::children, contentData
378*/
379QQmlListProperty<QQuickItem> QQuickPanePrivate::contentChildren()
380{
381 Q_Q(QQuickPane);
382 return QQmlListProperty<QQuickItem>(q->contentItem(), nullptr,
383 QQuickItemPrivate::children_append,
384 QQuickItemPrivate::children_count,
385 QQuickItemPrivate::children_at,
386 QQuickItemPrivate::children_clear);
387}
388
389void QQuickPane::componentComplete()
390{
391 Q_D(QQuickPane);
392 QQuickControl::componentComplete();
393 d->updateImplicitContentSize();
394}
395
396void QQuickPane::contentItemChange(QQuickItem *newItem, QQuickItem *oldItem)
397{
398 Q_D(QQuickPane);
399 QQuickControl::contentItemChange(newItem, oldItem);
400 if (oldItem) {
401 d->removeImplicitSizeListener(item: oldItem);
402 QObjectPrivate::disconnect(sender: oldItem, signal: &QQuickItem::childrenChanged, receiverPrivate: d, slot: &QQuickPanePrivate::contentChildrenChange);
403 }
404 if (newItem) {
405 d->addImplicitSizeListener(item: newItem);
406 QObjectPrivate::connect(sender: newItem, signal: &QQuickItem::childrenChanged, receiverPrivate: d, slot: &QQuickPanePrivate::contentChildrenChange);
407 }
408 d->contentChildrenChange();
409}
410
411void QQuickPane::contentSizeChange(const QSizeF &newSize, const QSizeF &oldSize)
412{
413 Q_UNUSED(newSize)
414 Q_UNUSED(oldSize)
415}
416
417#if QT_CONFIG(accessibility)
418QAccessible::Role QQuickPane::accessibleRole() const
419{
420 return QAccessible::Pane;
421}
422#endif
423
424QT_END_NAMESPACE
425
426#include "moc_qquickpane_p.cpp"
427

source code of qtquickcontrols2/src/quicktemplates2/qquickpane.cpp