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
qquickpage.cpp
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
5#include "qquickpage_p.h"
8#if QT_CONFIG(quicktemplates2_container)
9#include "qquicktabbar_p.h"
10#include "qquickdialogbuttonbox_p.h"
11#endif
12
14
15/*!
16 \qmltype Page
17 \inherits Pane
18//! \nativetype QQuickPage
19 \inqmlmodule QtQuick.Controls
20 \since 5.7
21 \ingroup qtquickcontrols-containers
22 \ingroup qtquickcontrols-focusscopes
23 \brief Styled page control with support for a header and footer.
24
25 Page is a container control which makes it convenient to add
26 a \l header and \l footer item to a page.
27
28 \image qtquickcontrols-page-wireframe.webp
29
30 Items declared as children of a Page are:
31 \list
32 \li automatically parented to the Page's contentItem. Items created
33 dynamically need to be explicitly parented to the contentItem.
34 \li not automatically positioned or resized.
35 \endlist
36
37 The following example snippet illustrates how to use a page-specific
38 toolbar header and an application-wide tabbar footer.
39
40 \qml
41 import QtQuick.Controls
42 import QtQuick.Layouts
43
44 ApplicationWindow {
45 visible: true
46
47 StackView {
48 anchors.fill: parent
49
50 initialItem: Page {
51 header: ToolBar {
52 // ...
53 }
54
55 ColumnLayout {
56 anchors.fill: parent
57 // ...
58 }
59 }
60 }
61
62 footer: TabBar {
63 // ...
64 }
65 }
66 \endqml
67
68 \sa ApplicationWindow, {Container Controls},
69 {Focus Management in Qt Quick Controls}
70*/
71
72static const QQuickItemPrivate::ChangeTypes LayoutChanges = QQuickItemPrivate::Geometry | QQuickItemPrivate::Visibility | QQuickItemPrivate::Destroyed
73 | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
74
75namespace {
76 enum Position {
77 Header,
78 Footer
79 };
80
81Q_STATIC_ASSERT(int(Header) == int(QQuickToolBar::Header));
82Q_STATIC_ASSERT(int(Footer) == int(QQuickToolBar::Footer));
83
84#if QT_CONFIG(quicktemplates2_container)
85 Q_STATIC_ASSERT(int(Header) == int(QQuickTabBar::Header));
86 Q_STATIC_ASSERT(int(Footer) == int(QQuickTabBar::Footer));
87
88 Q_STATIC_ASSERT(int(Header) == int(QQuickDialogButtonBox::Header));
89 Q_STATIC_ASSERT(int(Footer) == int(QQuickDialogButtonBox::Footer));
90#endif
91
92 static void setPos(QQuickItem *item, Position position)
93 {
94 if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(item))
95 toolBar->setPosition(static_cast<QQuickToolBar::Position>(position));
96#if QT_CONFIG(quicktemplates2_container)
97 else if (QQuickTabBar *tabBar = qobject_cast<QQuickTabBar *>(item))
98 tabBar->setPosition(static_cast<QQuickTabBar::Position>(position));
99 else if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(item))
100 buttonBox->setPosition(static_cast<QQuickDialogButtonBox::Position>(position));
101#endif
102 }
103}
104
105void QQuickPagePrivate::relayout()
106{
107 Q_Q(QQuickPage);
108 const qreal hh = header && header->isVisible() ? header->height() : 0;
109 const qreal fh = footer && footer->isVisible() ? footer->height() : 0;
110 const qreal hsp = hh > 0 ? spacing : 0;
111 const qreal fsp = fh > 0 ? spacing : 0;
112
113 if (contentItem) {
114 contentItem->setY(q->topPadding() + hh + hsp);
115 contentItem->setX(q->leftPadding());
116 contentItem->setWidth(q->availableWidth());
117 contentItem->setHeight(q->availableHeight() - hh - fh - hsp - fsp);
118 }
119
120 if (header) {
121 header->setY(0);
122 header->setWidth(q->width());
123 }
124
125 if (footer) {
126 footer->setY(q->height() - footer->height());
127 footer->setWidth(q->width());
128 }
129}
130
132{
133 relayout();
134}
135
137{
138 Q_Q(QQuickPage);
139 QQuickPanePrivate::itemVisibilityChanged(item);
140 QScopedValueRollback signalGuard(emittingImplicitSizeChangedSignals, true);
141 if (item == header) {
142 emit q->implicitHeaderWidthChanged();
143 emit q->implicitHeaderHeightChanged();
144 relayout();
145 } else if (item == footer) {
146 emit q->implicitFooterWidthChanged();
147 emit q->implicitFooterHeightChanged();
148 relayout();
149 }
150}
151
153{
154 Q_Q(QQuickPage);
155 QQuickPanePrivate::itemImplicitWidthChanged(item);
156
157 // Avoid binding loops by skipping signal emission if we're already doing it.
159 return;
160
161 if (item == header)
162 emit q->implicitHeaderWidthChanged();
163 else if (item == footer)
164 emit q->implicitFooterWidthChanged();
165}
166
168{
169 Q_Q(QQuickPage);
170 QQuickPanePrivate::itemImplicitHeightChanged(item);
171
172 // Avoid binding loops by skipping signal emission if we're already doing it.
174 return;
175
176 if (item == header)
177 emit q->implicitHeaderHeightChanged();
178 else if (item == footer)
179 emit q->implicitFooterHeightChanged();
180}
181
182void QQuickPagePrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF & diff)
183{
184 QQuickPanePrivate::itemGeometryChanged(item, change, diff);
185 if (item == header || item == footer)
186 relayout();
187}
188
189void QQuickPagePrivate::itemDestroyed(QQuickItem *item)
190{
191 Q_Q(QQuickPage);
192 QQuickPanePrivate::itemDestroyed(item);
193 if (item == header) {
194 header = nullptr;
195 relayout();
196 emit q->implicitHeaderWidthChanged();
197 emit q->implicitHeaderHeightChanged();
198 emit q->headerChanged();
199 } else if (item == footer) {
200 footer = nullptr;
201 relayout();
202 emit q->implicitFooterWidthChanged();
203 emit q->implicitFooterHeightChanged();
204 emit q->footerChanged();
205 }
206}
207
208QQuickPage::QQuickPage(QQuickItem *parent)
209 : QQuickPane(*(new QQuickPagePrivate), parent)
210{
211}
212
213QQuickPage::QQuickPage(QQuickPagePrivate &dd, QQuickItem *parent)
214 : QQuickPane(dd, parent)
215{
216}
217
218QQuickPage::~QQuickPage()
219{
220 Q_D(QQuickPage);
221 if (d->header)
222 QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, LayoutChanges);
223 if (d->footer)
224 QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, LayoutChanges);
225}
226
227/*!
228 \qmlproperty string QtQuick.Controls::Page::title
229
230 This property holds the page title.
231
232 The title is often displayed at the top of a page to give
233 the user context about the page they are viewing.
234
235 Page does not render the title itself, but instead relies
236 on the application to do so. For example:
237
238 \code
239 ApplicationWindow {
240 visible: true
241 width: 400
242 height: 400
243
244 header: Label {
245 text: view.currentItem.title
246 horizontalAlignment: Text.AlignHCenter
247 }
248
249 SwipeView {
250 id: view
251 anchors.fill: parent
252
253 Page {
254 title: qsTr("Home")
255 }
256 Page {
257 title: qsTr("Discover")
258 }
259 Page {
260 title: qsTr("Activity")
261 }
262 }
263 }
264 \endcode
265*/
266
267QString QQuickPage::title() const
268{
269 return d_func()->title;
270}
271
272void QQuickPage::setTitle(const QString &title)
273{
274 Q_D(QQuickPage);
275 if (d->title == title)
276 return;
277
278 d->title = title;
279 maybeSetAccessibleName(title);
280 emit titleChanged();
281}
282
283void QQuickPage::resetTitle()
284{
285 setTitle(QString());
286}
287
288/*!
289 \qmlproperty Item QtQuick.Controls::Page::header
290
291 This property holds the page header item. The header item is positioned to
292 the top, and resized to the width of the page. The default value is \c null.
293
294 \note Assigning a ToolBar, TabBar, or DialogButtonBox as a page header
295 automatically sets the respective \l ToolBar::position, \l TabBar::position,
296 or \l DialogButtonBox::position property to \c Header.
297
298 \sa footer, ApplicationWindow::header
299*/
300QQuickItem *QQuickPage::header() const
301{
302 Q_D(const QQuickPage);
303 return d->header;
304}
305
306void QQuickPage::setHeader(QQuickItem *header)
307{
308 Q_D(QQuickPage);
309 if (d->header == header)
310 return;
311
312 if (d->header) {
313 QQuickItemPrivate::get(d->header)->removeItemChangeListener(d, LayoutChanges);
314 d->header->setParentItem(nullptr);
315 }
316 d->header = header;
317 if (header) {
318 header->setParentItem(this);
319 QQuickItemPrivate::get(header)->addItemChangeListener(d, LayoutChanges);
320 if (qFuzzyIsNull(header->z()))
321 header->setZ(1);
322 setPos(header, Header);
323 }
324 if (isComponentComplete())
325 d->relayout();
326 emit headerChanged();
327}
328
329/*!
330 \qmlproperty Item QtQuick.Controls::Page::footer
331
332 This property holds the page footer item. The footer item is positioned to
333 the bottom, and resized to the width of the page. The default value is \c null.
334
335 \note Assigning a ToolBar, TabBar, or DialogButtonBox as a page footer
336 automatically sets the respective \l ToolBar::position, \l TabBar::position,
337 or \l DialogButtonBox::position property to \c Footer.
338
339 \sa header, ApplicationWindow::footer
340*/
341QQuickItem *QQuickPage::footer() const
342{
343 Q_D(const QQuickPage);
344 return d->footer;
345}
346
347void QQuickPage::setFooter(QQuickItem *footer)
348{
349 Q_D(QQuickPage);
350 if (d->footer == footer)
351 return;
352
353 if (d->footer) {
354 QQuickItemPrivate::get(d->footer)->removeItemChangeListener(d, LayoutChanges);
355 d->footer->setParentItem(nullptr);
356 }
357 d->footer = footer;
358 if (footer) {
359 footer->setParentItem(this);
360 QQuickItemPrivate::get(footer)->addItemChangeListener(d, LayoutChanges);
361 if (qFuzzyIsNull(footer->z()))
362 footer->setZ(1);
363 setPos(footer, Footer);
364 }
365 if (isComponentComplete())
366 d->relayout();
367 emit footerChanged();
368}
369
370/*!
371 \since QtQuick.Controls 2.5 (Qt 5.12)
372 \qmlproperty real QtQuick.Controls::Page::implicitHeaderWidth
373 \readonly
374
375 This property holds the implicit header width.
376
377 The value is equal to \c {header && header.visible ? header.implicitWidth : 0}.
378
379 \sa implicitHeaderHeight, implicitFooterWidth
380*/
381qreal QQuickPage::implicitHeaderWidth() const
382{
383 Q_D(const QQuickPage);
384 if (!d->header || !d->header->isVisible())
385 return 0;
386 return d->header->implicitWidth();
387}
388
389/*!
390 \since QtQuick.Controls 2.5 (Qt 5.12)
391 \qmlproperty real QtQuick.Controls::Page::implicitHeaderHeight
392 \readonly
393
394 This property holds the implicit header height.
395
396 The value is equal to \c {header && header.visible ? header.implicitHeight : 0}.
397
398 \sa implicitHeaderWidth, implicitFooterHeight
399*/
400qreal QQuickPage::implicitHeaderHeight() const
401{
402 Q_D(const QQuickPage);
403 if (!d->header || !d->header->isVisible())
404 return 0;
405 return d->header->implicitHeight();
406}
407
408/*!
409 \since QtQuick.Controls 2.5 (Qt 5.12)
410 \qmlproperty real QtQuick.Controls::Page::implicitFooterWidth
411 \readonly
412
413 This property holds the implicit footer width.
414
415 The value is equal to \c {footer && footer.visible ? footer.implicitWidth : 0}.
416
417 \sa implicitFooterHeight, implicitHeaderWidth
418*/
419qreal QQuickPage::implicitFooterWidth() const
420{
421 Q_D(const QQuickPage);
422 if (!d->footer || !d->footer->isVisible())
423 return 0;
424 return d->footer->implicitWidth();
425}
426
427/*!
428 \since QtQuick.Controls 2.5 (Qt 5.12)
429 \qmlproperty real QtQuick.Controls::Page::implicitFooterHeight
430 \readonly
431
432 This property holds the implicit footer height.
433
434 The value is equal to \c {footer && footer.visible ? footer.implicitHeight : 0}.
435
436 \sa implicitFooterWidth, implicitHeaderHeight
437*/
438qreal QQuickPage::implicitFooterHeight() const
439{
440 Q_D(const QQuickPage);
441 if (!d->footer || !d->footer->isVisible())
442 return 0;
443 return d->footer->implicitHeight();
444}
445
446void QQuickPage::componentComplete()
447{
448 Q_D(QQuickPage);
449 QQuickPane::componentComplete();
450 d->relayout();
451}
452
453void QQuickPage::spacingChange(qreal newSpacing, qreal oldSpacing)
454{
455 Q_D(QQuickPage);
456 QQuickPane::spacingChange(newSpacing, oldSpacing);
457 d->relayout();
458}
459
460#if QT_CONFIG(accessibility)
461QAccessible::Role QQuickPage::accessibleRole() const
462{
463 return QAccessible::PageTab;
464}
465
466void QQuickPage::accessibilityActiveChanged(bool active)
467{
468 Q_D(QQuickPage);
469 QQuickPane::accessibilityActiveChanged(active);
470
471 if (active)
472 maybeSetAccessibleName(d->title);
473}
474#endif
475
476QT_END_NAMESPACE
477
478#include "moc_qquickpage_p.cpp"
void itemDestroyed(QQuickItem *item) override
void itemVisibilityChanged(QQuickItem *item) override
bool emittingImplicitSizeChangedSignals
void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override
void itemImplicitWidthChanged(QQuickItem *item) override
void itemImplicitHeightChanged(QQuickItem *item) override
void resizeContent() override
static QT_BEGIN_NAMESPACE const QQuickItemPrivate::ChangeTypes LayoutChanges
Styled page control with support for a header and footer.