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