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 "qquickapplicationwindow_p.h"
5#include "qquickcontentitem_p.h"
6#include "qquickpopup_p_p.h"
7#include "qquickcontrol_p_p.h"
8#include "qquicktextarea_p.h"
9#include "qquicktextfield_p.h"
10#include "qquicktoolbar_p.h"
11#include "qquicktabbar_p.h"
12#include "qquickdialogbuttonbox_p.h"
13#include "qquickdeferredexecute_p_p.h"
14#include "qquickdeferredpointer_p_p.h"
15
16#include <QtCore/private/qobject_p.h>
17#include <QtCore/qscopedvaluerollback.h>
18#include <QtQuick/private/qquickitem_p.h>
19#include <QtQuick/private/qquickitemchangelistener_p.h>
20#include <QtQuick/private/qquickwindowmodule_p_p.h>
21
22QT_BEGIN_NAMESPACE
23
24/*!
25 \qmltype ApplicationWindow
26 \inherits Window
27//! \instantiates QQuickApplicationWindow
28 \inqmlmodule QtQuick.Controls
29 \since 5.7
30 \ingroup qtquickcontrols-containers
31 \ingroup qtquickcontrols-focusscopes
32 \brief Styled top-level window with support for a header and footer.
33
34 ApplicationWindow is a \l Window which makes it convenient to add
35 a \l {menuBar}{menu bar}, \l header and \l footer item to the window.
36
37 You can declare ApplicationWindow as the root item of your application,
38 and run it by using \l QQmlApplicationEngine. In this way you can control
39 the window's properties, appearance and layout from QML.
40
41 \image qtquickcontrols-applicationwindow-wireframe.png
42
43 \qml
44 import QtQuick.Controls 2.12
45
46 ApplicationWindow {
47 visible: true
48
49 menuBar: MenuBar {
50 // ...
51 }
52
53 header: ToolBar {
54 // ...
55 }
56
57 footer: TabBar {
58 // ...
59 }
60
61 StackView {
62 anchors.fill: parent
63 }
64 }
65 \endqml
66
67 \note By default, an ApplicationWindow is not visible.
68
69 \section2 Attached ApplicationWindow Properties
70
71 Due to how \l {Scope and Naming Resolution} works in QML, it is possible
72 to reference the \c id of the application root element anywhere in its
73 child QML objects. Even though this approach is fine for many applications
74 and use cases, for a generic QML component it may not be acceptable as it
75 creates a dependency to the surrounding environment.
76
77 ApplicationWindow provides a set of attached properties that can be used
78 to access the window and its building blocks from places where no direct
79 access to the window is available, without creating a dependency to a
80 certain window \c id. A QML component that uses the ApplicationWindow
81 attached properties works in any window regardless of its \c id.
82
83 \sa {Customizing ApplicationWindow}, Overlay, Page, {Container Controls},
84 {Focus Management in Qt Quick Controls}
85*/
86
87static const QQuickItemPrivate::ChangeTypes ItemChanges = QQuickItemPrivate::Visibility
88 | QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight;
89
90class Q_QUICKTEMPLATES2_PRIVATE_EXPORT QQuickApplicationWindowPrivate
91 : public QQuickWindowQmlImplPrivate
92 , public QQuickItemChangeListener
93{
94 Q_DECLARE_PUBLIC(QQuickApplicationWindow)
95
96public:
97 static QQuickApplicationWindowPrivate *get(QQuickApplicationWindow *window)
98 {
99 return window->d_func();
100 }
101
102 QQmlListProperty<QObject> contentData();
103
104 void relayout();
105
106 void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override;
107 void itemVisibilityChanged(QQuickItem *item) override;
108 void itemImplicitWidthChanged(QQuickItem *item) override;
109 void itemImplicitHeightChanged(QQuickItem *item) override;
110 QPalette windowPalette() const override { return defaultPalette(); }
111
112 void updateFont(const QFont &f);
113 inline void setFont_helper(const QFont &f) {
114 if (font.resolveMask() == f.resolveMask() && font == f)
115 return;
116 updateFont(f);
117 }
118 void resolveFont();
119
120 void _q_updateActiveFocus();
121 void setActiveFocusControl(QQuickItem *item);
122
123 static void contentData_append(QQmlListProperty<QObject> *prop, QObject *obj);
124
125 void cancelBackground();
126 void executeBackground(bool complete = false);
127
128 QPalette defaultPalette() const override { return QQuickTheme::palette(scope: QQuickTheme::System); }
129 void updateChildrenPalettes(const QPalette &parentPalette) override
130 {
131 // Update regular children
132 QQuickWindowPrivate::updateChildrenPalettes(parentPalette);
133
134 // And cover one special case
135 for (auto &&popup : q_func()->findChildren<QQuickPopup *>())
136 QQuickPopupPrivate::get(popup)->updateContentPalettes(parentPalette);
137 }
138
139 QQuickDeferredPointer<QQuickItem> background;
140 QQuickItem *appWindowContentItem = nullptr;
141 QQuickItem *menuBar = nullptr;
142 QQuickItem *header = nullptr;
143 QQuickItem *footer = nullptr;
144 QFont font;
145 QLocale locale;
146 QQuickItem *activeFocusControl = nullptr;
147 bool insideRelayout = false;
148};
149
150static void layoutItem(QQuickItem *item, qreal y, qreal width)
151{
152 if (!item)
153 return;
154
155 item->setY(y);
156 QQuickItemPrivate *p = QQuickItemPrivate::get(item);
157 if (!p->widthValid()) {
158 item->setWidth(width);
159 p->widthValidFlag = false;
160 }
161}
162
163void QQuickApplicationWindowPrivate::relayout()
164{
165 Q_Q(QQuickApplicationWindow);
166 if (!componentComplete || insideRelayout)
167 return;
168
169 QScopedValueRollback<bool> guard(insideRelayout, true);
170 QQuickItem *content = q->contentItem();
171 qreal hh = header && header->isVisible() ? header->height() : 0;
172 qreal fh = footer && footer->isVisible() ? footer->height() : 0;
173 qreal mbh = menuBar && menuBar->isVisible() ? menuBar->height() : 0;
174
175 content->setY(mbh + hh);
176 content->setWidth(q->width());
177 content->setHeight(q->height() - mbh - hh - fh);
178
179 layoutItem(item: menuBar, y: -mbh - hh, width: q->width());
180 layoutItem(item: header, y: -hh, width: q->width());
181 layoutItem(item: footer, y: content->height(), width: q->width());
182
183 if (background) {
184 QQuickItemPrivate *p = QQuickItemPrivate::get(item: background);
185 if (!p->widthValid() && qFuzzyIsNull(d: background->x())) {
186 background->setWidth(q->width());
187 p->widthValidFlag = false;
188 }
189 if (!p->heightValid() && qFuzzyIsNull(d: background->y())) {
190 background->setHeight(q->height());
191 p->heightValidFlag = false;
192 }
193 }
194}
195
196void QQuickApplicationWindowPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff)
197{
198 Q_UNUSED(item);
199 Q_UNUSED(change);
200 Q_UNUSED(diff);
201 relayout();
202}
203
204void QQuickApplicationWindowPrivate::itemVisibilityChanged(QQuickItem *item)
205{
206 Q_UNUSED(item);
207 relayout();
208}
209
210void QQuickApplicationWindowPrivate::itemImplicitWidthChanged(QQuickItem *item)
211{
212 Q_UNUSED(item);
213 relayout();
214}
215
216void QQuickApplicationWindowPrivate::itemImplicitHeightChanged(QQuickItem *item)
217{
218 Q_UNUSED(item);
219 relayout();
220}
221
222void QQuickApplicationWindowPrivate::updateFont(const QFont &f)
223{
224 Q_Q(QQuickApplicationWindow);
225 const bool changed = font != f;
226 font = f;
227
228 QQuickControlPrivate::updateFontRecur(item: q->QQuickWindow::contentItem(), font: f);
229
230 const QList<QQuickPopup *> popups = q->findChildren<QQuickPopup *>();
231 for (QQuickPopup *popup : popups)
232 QQuickControlPrivate::get(control: static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(font: f);
233
234 if (changed)
235 emit q->fontChanged();
236}
237
238void QQuickApplicationWindowPrivate::resolveFont()
239{
240 QFont resolvedFont = font.resolve(QQuickTheme::font(scope: QQuickTheme::System));
241 setFont_helper(resolvedFont);
242}
243
244static QQuickItem *findActiveFocusControl(QQuickWindow *window)
245{
246 QQuickItem *item = window->activeFocusItem();
247 while (item) {
248 if (qobject_cast<QQuickControl *>(object: item) || qobject_cast<QQuickTextField *>(object: item) || qobject_cast<QQuickTextArea *>(object: item))
249 return item;
250 item = item->parentItem();
251 }
252 return item;
253}
254
255void QQuickApplicationWindowPrivate::_q_updateActiveFocus()
256{
257 Q_Q(QQuickApplicationWindow);
258 setActiveFocusControl(findActiveFocusControl(window: q));
259}
260
261void QQuickApplicationWindowPrivate::setActiveFocusControl(QQuickItem *control)
262{
263 Q_Q(QQuickApplicationWindow);
264 if (activeFocusControl != control) {
265 activeFocusControl = control;
266 emit q->activeFocusControlChanged();
267 }
268}
269
270void QQuickApplicationWindowPrivate::contentData_append(QQmlListProperty<QObject> *prop, QObject *obj)
271{
272 QQuickItemPrivate::data_append(prop, obj);
273
274 // associate "top-level" popups with the window as soon as they are added to the default property
275 if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(object: obj))
276 QQuickPopupPrivate::get(popup)->setWindow(static_cast<QQuickApplicationWindow *>(prop->data));
277}
278
279void QQuickApplicationWindowPrivate::cancelBackground()
280{
281 Q_Q(QQuickApplicationWindow);
282 quickCancelDeferred(object: q, property: backgroundName());
283}
284
285void QQuickApplicationWindowPrivate::executeBackground(bool complete)
286{
287 Q_Q(QQuickApplicationWindow);
288 if (background.wasExecuted())
289 return;
290
291 if (!background || complete)
292 quickBeginDeferred(object: q, property: backgroundName(), delegate&: background);
293 if (complete)
294 quickCompleteDeferred(object: q, property: backgroundName(), delegate&: background);
295}
296
297QQuickApplicationWindow::QQuickApplicationWindow(QWindow *parent)
298 : QQuickWindowQmlImpl(*(new QQuickApplicationWindowPrivate), parent)
299{
300 connect(sender: this, SIGNAL(activeFocusItemChanged()), receiver: this, SLOT(_q_updateActiveFocus()));
301}
302
303QQuickApplicationWindow::~QQuickApplicationWindow()
304{
305 Q_D(QQuickApplicationWindow);
306 d->setActiveFocusControl(nullptr);
307 disconnect(sender: this, SIGNAL(activeFocusItemChanged()), receiver: this, SLOT(_q_updateActiveFocus()));
308 if (d->menuBar)
309 QQuickItemPrivate::get(item: d->menuBar)->removeItemChangeListener(d, types: ItemChanges);
310 if (d->header)
311 QQuickItemPrivate::get(item: d->header)->removeItemChangeListener(d, types: ItemChanges);
312 if (d->footer)
313 QQuickItemPrivate::get(item: d->footer)->removeItemChangeListener(d, types: ItemChanges);
314}
315
316QQuickApplicationWindowAttached *QQuickApplicationWindow::qmlAttachedProperties(QObject *object)
317{
318 return new QQuickApplicationWindowAttached(object);
319}
320
321/*!
322 \qmlproperty Item QtQuick.Controls::ApplicationWindow::background
323
324 This property holds the background item.
325
326 The background item is stacked under the \l {contentItem}{content item},
327 but above the \l {Window::color}{background color} of the window.
328
329 The background item is useful for images and gradients, for example,
330 but the \l {Window::}{color} property is preferable for solid colors,
331 as it doesn't need to create an item.
332
333 \note If the background item has no explicit size specified, it automatically
334 follows the control's size. In most cases, there is no need to specify
335 width or height for a background item.
336
337 \sa {Customizing ApplicationWindow}, contentItem, header, footer
338*/
339QQuickItem *QQuickApplicationWindow::background() const
340{
341 QQuickApplicationWindowPrivate *d = const_cast<QQuickApplicationWindowPrivate *>(d_func());
342 if (!d->background)
343 d->executeBackground();
344 return d->background;
345}
346
347void QQuickApplicationWindow::setBackground(QQuickItem *background)
348{
349 Q_D(QQuickApplicationWindow);
350 if (d->background == background)
351 return;
352
353 if (!d->background.isExecuting())
354 d->cancelBackground();
355
356 QQuickControlPrivate::hideOldItem(item: d->background);
357 d->background = background;
358 if (background) {
359 background->setParentItem(QQuickWindow::contentItem());
360 if (qFuzzyIsNull(d: background->z()))
361 background->setZ(-1);
362 if (isComponentComplete())
363 d->relayout();
364 }
365 if (!d->background.isExecuting())
366 emit backgroundChanged();
367}
368
369/*!
370 \qmlproperty Item QtQuick.Controls::ApplicationWindow::header
371
372 This property holds the window header item. The header item is positioned at the
373 top of the window, below the menu bar, and resized to the width of the window.
374 The default value is \c null.
375
376 \code
377 ApplicationWindow {
378 header: TabBar {
379 // ...
380 }
381 }
382 \endcode
383
384 \note Assigning a ToolBar, TabBar, or DialogButtonBox as a window header
385 automatically sets the respective \l ToolBar::position, \l TabBar::position,
386 or \l DialogButtonBox::position property to \c Header.
387
388 \sa menuBar, footer, Page::header
389*/
390QQuickItem *QQuickApplicationWindow::header() const
391{
392 Q_D(const QQuickApplicationWindow);
393 return d->header;
394}
395
396void QQuickApplicationWindow::setHeader(QQuickItem *header)
397{
398 Q_D(QQuickApplicationWindow);
399 if (d->header == header)
400 return;
401
402 if (d->header) {
403 QQuickItemPrivate::get(item: d->header)->removeItemChangeListener(d, types: ItemChanges);
404 d->header->setParentItem(nullptr);
405 }
406 d->header = header;
407 if (header) {
408 header->setParentItem(contentItem());
409 QQuickItemPrivate *p = QQuickItemPrivate::get(item: header);
410 p->addItemChangeListener(listener: d, types: ItemChanges);
411 if (qFuzzyIsNull(d: header->z()))
412 header->setZ(1);
413 if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(object: header))
414 toolBar->setPosition(QQuickToolBar::Header);
415 else if (QQuickTabBar *tabBar = qobject_cast<QQuickTabBar *>(object: header))
416 tabBar->setPosition(QQuickTabBar::Header);
417 else if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(object: header))
418 buttonBox->setPosition(QQuickDialogButtonBox::Header);
419 }
420 if (isComponentComplete())
421 d->relayout();
422 emit headerChanged();
423}
424
425/*!
426 \qmlproperty Item QtQuick.Controls::ApplicationWindow::footer
427
428 This property holds the window footer item. The footer item is positioned to
429 the bottom, and resized to the width of the window. The default value is \c null.
430
431 \code
432 ApplicationWindow {
433 footer: ToolBar {
434 // ...
435 }
436 }
437 \endcode
438
439 \note Assigning a ToolBar, TabBar, or DialogButtonBox as a window footer
440 automatically sets the respective \l ToolBar::position, \l TabBar::position,
441 or \l DialogButtonBox::position property to \c Footer.
442
443 \sa menuBar, header, Page::footer
444*/
445QQuickItem *QQuickApplicationWindow::footer() const
446{
447 Q_D(const QQuickApplicationWindow);
448 return d->footer;
449}
450
451void QQuickApplicationWindow::setFooter(QQuickItem *footer)
452{
453 Q_D(QQuickApplicationWindow);
454 if (d->footer == footer)
455 return;
456
457 if (d->footer) {
458 QQuickItemPrivate::get(item: d->footer)->removeItemChangeListener(d, types: ItemChanges);
459 d->footer->setParentItem(nullptr);
460 }
461 d->footer = footer;
462 if (footer) {
463 footer->setParentItem(contentItem());
464 QQuickItemPrivate *p = QQuickItemPrivate::get(item: footer);
465 p->addItemChangeListener(listener: d, types: ItemChanges);
466 if (qFuzzyIsNull(d: footer->z()))
467 footer->setZ(1);
468 if (QQuickToolBar *toolBar = qobject_cast<QQuickToolBar *>(object: footer))
469 toolBar->setPosition(QQuickToolBar::Footer);
470 else if (QQuickTabBar *tabBar = qobject_cast<QQuickTabBar *>(object: footer))
471 tabBar->setPosition(QQuickTabBar::Footer);
472 else if (QQuickDialogButtonBox *buttonBox = qobject_cast<QQuickDialogButtonBox *>(object: footer))
473 buttonBox->setPosition(QQuickDialogButtonBox::Footer);
474 }
475 if (isComponentComplete())
476 d->relayout();
477 emit footerChanged();
478}
479
480/*!
481 \qmlproperty list<QtObject> QtQuick.Controls::ApplicationWindow::contentData
482 \qmldefault
483
484 This default property holds the list of all objects declared as children of
485 the window.
486
487 The data property allows you to freely mix visual children, resources and
488 other windows in an ApplicationWindow.
489
490 If you assign an Item to the contentData list, it becomes a child of the
491 window's contentItem, so that it appears inside the window. The item's
492 parent will be the window's \l contentItem.
493
494 It should not generally be necessary to refer to the contentData property,
495 as it is the default property for ApplicationWindow and thus all child
496 items are automatically assigned to this property.
497
498 \sa contentItem
499*/
500QQmlListProperty<QObject> QQuickApplicationWindowPrivate::contentData()
501{
502 Q_Q(QQuickApplicationWindow);
503 return QQmlListProperty<QObject>(q->contentItem(), q,
504 QQuickApplicationWindowPrivate::contentData_append,
505 QQuickItemPrivate::data_count,
506 QQuickItemPrivate::data_at,
507 QQuickItemPrivate::data_clear);
508}
509
510/*!
511 \qmlproperty Item QtQuick.Controls::ApplicationWindow::contentItem
512 \readonly
513
514 This property holds the window content item.
515
516 The content item is stacked above the \l background item, and under the
517 \l menuBar, \l header, and \l footer items.
518
519 \sa background, menuBar, header, footer
520*/
521QQuickItem *QQuickApplicationWindow::contentItem() const
522{
523 QQuickApplicationWindowPrivate *d = const_cast<QQuickApplicationWindowPrivate *>(d_func());
524 if (!d->appWindowContentItem) {
525 d->appWindowContentItem = new QQuickContentItem(this, QQuickWindow::contentItem());
526 d->appWindowContentItem->setFlag(flag: QQuickItem::ItemIsFocusScope);
527 d->appWindowContentItem->setFocus(true);
528 d->relayout();
529 }
530 return d->appWindowContentItem;
531}
532
533/*!
534 \qmlproperty Control QtQuick.Controls::ApplicationWindow::activeFocusControl
535 \readonly
536
537 This property holds the control that currently has active focus, or \c null if there is
538 no control with active focus.
539
540 The difference between \l Window::activeFocusItem and ApplicationWindow::activeFocusControl
541 is that the former may point to a building block of a control, whereas the latter points
542 to the enclosing control. For example, when SpinBox has focus, activeFocusItem points to
543 the editor and activeFocusControl to the SpinBox itself.
544
545 \sa Window::activeFocusItem
546*/
547QQuickItem *QQuickApplicationWindow::activeFocusControl() const
548{
549 Q_D(const QQuickApplicationWindow);
550 return d->activeFocusControl;
551}
552
553/*!
554 \qmlproperty font QtQuick.Controls::ApplicationWindow::font
555
556 This property holds the font currently set for the window.
557
558 The default font depends on the system environment. QGuiApplication maintains a system/theme
559 font which serves as a default for all application windows. You can also set the default font
560 for windows by passing a custom font to QGuiApplication::setFont(), before loading any QML.
561 Finally, the font is matched against Qt's font database to find the best match.
562
563 ApplicationWindow propagates explicit font properties to child controls. If you change a specific
564 property on the window's font, that property propagates to all child controls in the window,
565 overriding any system defaults for that property.
566
567 \sa Control::font
568*/
569QFont QQuickApplicationWindow::font() const
570{
571 Q_D(const QQuickApplicationWindow);
572 return d->font;
573}
574
575void QQuickApplicationWindow::setFont(const QFont &font)
576{
577 Q_D(QQuickApplicationWindow);
578 if (d->font.resolveMask() == font.resolveMask() && d->font == font)
579 return;
580
581 QFont resolvedFont = font.resolve(QQuickTheme::font(scope: QQuickTheme::System));
582 d->setFont_helper(resolvedFont);
583}
584
585void QQuickApplicationWindow::resetFont()
586{
587 setFont(QFont());
588}
589
590/*!
591 \qmlproperty Locale QtQuick.Controls::ApplicationWindow::locale
592
593 This property holds the locale of the window.
594
595 The default locale depends on the system environment. You can set the
596 default locale by calling QLocale::setDefault(), before loading any QML.
597
598 ApplicationWindow propagates the locale to child controls. If you change
599 the window's locale, that locale propagates to all child controls in the
600 window, overriding the system default locale.
601
602 \sa Control::locale
603*/
604QLocale QQuickApplicationWindow::locale() const
605{
606 Q_D(const QQuickApplicationWindow);
607 return d->locale;
608}
609
610void QQuickApplicationWindow::setLocale(const QLocale &locale)
611{
612 Q_D(QQuickApplicationWindow);
613 if (d->locale == locale)
614 return;
615
616 d->locale = locale;
617 QQuickControlPrivate::updateLocaleRecur(item: QQuickWindow::contentItem(), l: locale);
618
619 // TODO: internal QQuickPopupManager that provides reliable access to all QQuickPopup instances
620 const QList<QQuickPopup *> popups = QQuickWindow::contentItem()->findChildren<QQuickPopup *>();
621 for (QQuickPopup *popup : popups)
622 QQuickControlPrivate::get(control: static_cast<QQuickControl *>(popup->popupItem()))->updateLocale(l: locale, e: false); // explicit=false
623
624 emit localeChanged();
625}
626
627void QQuickApplicationWindow::resetLocale()
628{
629 setLocale(QLocale());
630}
631
632/*!
633 \since QtQuick.Controls 2.3 (Qt 5.10)
634 \qmlproperty Item QtQuick.Controls::ApplicationWindow::menuBar
635
636 This property holds the window menu bar. The menu bar is positioned at the
637 top of the window, above the header, and resized to the width of the window.
638 The default value is \c null.
639
640 \code
641 ApplicationWindow {
642 menuBar: MenuBar {
643 // ...
644 }
645 }
646 \endcode
647
648 \sa header, footer, MenuBar
649*/
650QQuickItem *QQuickApplicationWindow::menuBar() const
651{
652 Q_D(const QQuickApplicationWindow);
653 return d->menuBar;
654}
655
656void QQuickApplicationWindow::setMenuBar(QQuickItem *menuBar)
657{
658 Q_D(QQuickApplicationWindow);
659 if (d->menuBar == menuBar)
660 return;
661
662 if (d->menuBar) {
663 QQuickItemPrivate::get(item: d->menuBar)->removeItemChangeListener(d, types: ItemChanges);
664 d->menuBar->setParentItem(nullptr);
665 }
666 d->menuBar = menuBar;
667 if (menuBar) {
668 menuBar->setParentItem(contentItem());
669 QQuickItemPrivate *p = QQuickItemPrivate::get(item: menuBar);
670 p->addItemChangeListener(listener: d, types: ItemChanges);
671 if (qFuzzyIsNull(d: menuBar->z()))
672 menuBar->setZ(2);
673 }
674 if (isComponentComplete())
675 d->relayout();
676 emit menuBarChanged();
677}
678
679bool QQuickApplicationWindow::isComponentComplete() const
680{
681 Q_D(const QQuickApplicationWindow);
682 return d->componentComplete;
683}
684
685void QQuickApplicationWindow::classBegin()
686{
687 Q_D(QQuickApplicationWindow);
688 d->componentComplete = false;
689 QQuickWindowQmlImpl::classBegin();
690 d->resolveFont();
691}
692
693void QQuickApplicationWindow::componentComplete()
694{
695 Q_D(QQuickApplicationWindow);
696 d->componentComplete = true;
697 d->executeBackground(complete: true);
698 QQuickWindowQmlImpl::componentComplete();
699 d->relayout();
700}
701
702void QQuickApplicationWindow::resizeEvent(QResizeEvent *event)
703{
704 Q_D(QQuickApplicationWindow);
705 QQuickWindowQmlImpl::resizeEvent(event);
706 d->relayout();
707}
708
709class QQuickApplicationWindowAttachedPrivate : public QObjectPrivate
710{
711public:
712 Q_DECLARE_PUBLIC(QQuickApplicationWindowAttached)
713
714 void windowChange(QQuickWindow *wnd);
715 void activeFocusChange();
716
717 QQuickWindow *window = nullptr;
718 QQuickItem *activeFocusControl = nullptr;
719};
720
721void QQuickApplicationWindowAttachedPrivate::windowChange(QQuickWindow *wnd)
722{
723 Q_Q(QQuickApplicationWindowAttached);
724 if (window == wnd)
725 return;
726
727 QQuickApplicationWindow *oldWindow = qobject_cast<QQuickApplicationWindow *>(object: window);
728 if (oldWindow && !QQuickApplicationWindowPrivate::get(window: oldWindow))
729 oldWindow = nullptr; // being deleted (QTBUG-52731)
730
731 if (oldWindow) {
732 disconnect(sender: oldWindow, signal: &QQuickApplicationWindow::activeFocusControlChanged,
733 receiverPrivate: this, slot: &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
734 QObject::disconnect(sender: oldWindow, signal: &QQuickApplicationWindow::menuBarChanged,
735 receiver: q, slot: &QQuickApplicationWindowAttached::menuBarChanged);
736 QObject::disconnect(sender: oldWindow, signal: &QQuickApplicationWindow::headerChanged,
737 receiver: q, slot: &QQuickApplicationWindowAttached::headerChanged);
738 QObject::disconnect(sender: oldWindow, signal: &QQuickApplicationWindow::footerChanged,
739 receiver: q, slot: &QQuickApplicationWindowAttached::footerChanged);
740 } else if (window) {
741 disconnect(sender: window, signal: &QQuickWindow::activeFocusItemChanged,
742 receiverPrivate: this, slot: &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
743 }
744
745 QQuickApplicationWindow *newWindow = qobject_cast<QQuickApplicationWindow *>(object: wnd);
746 if (newWindow) {
747 connect(sender: newWindow, signal: &QQuickApplicationWindow::activeFocusControlChanged,
748 receiverPrivate: this, slot: &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
749 QObject::connect(sender: newWindow, signal: &QQuickApplicationWindow::menuBarChanged,
750 context: q, slot: &QQuickApplicationWindowAttached::menuBarChanged);
751 QObject::connect(sender: newWindow, signal: &QQuickApplicationWindow::headerChanged,
752 context: q, slot: &QQuickApplicationWindowAttached::headerChanged);
753 QObject::connect(sender: newWindow, signal: &QQuickApplicationWindow::footerChanged,
754 context: q, slot: &QQuickApplicationWindowAttached::footerChanged);
755 } else if (wnd) {
756 connect(sender: wnd, signal: &QQuickWindow::activeFocusItemChanged,
757 receiverPrivate: this, slot: &QQuickApplicationWindowAttachedPrivate::activeFocusChange);
758 }
759
760 window = wnd;
761 emit q->windowChanged();
762 emit q->contentItemChanged();
763
764 activeFocusChange();
765 if ((oldWindow && oldWindow->menuBar()) || (newWindow && newWindow->menuBar()))
766 emit q->menuBarChanged();
767 if ((oldWindow && oldWindow->header()) || (newWindow && newWindow->header()))
768 emit q->headerChanged();
769 if ((oldWindow && oldWindow->footer()) || (newWindow && newWindow->footer()))
770 emit q->footerChanged();
771}
772
773void QQuickApplicationWindowAttachedPrivate::activeFocusChange()
774{
775 Q_Q(QQuickApplicationWindowAttached);
776 QQuickItem *control = nullptr;
777 if (QQuickApplicationWindow *appWindow = qobject_cast<QQuickApplicationWindow *>(object: window))
778 control = appWindow->activeFocusControl();
779 else if (window)
780 control = findActiveFocusControl(window);
781 if (activeFocusControl == control)
782 return;
783
784 activeFocusControl = control;
785 emit q->activeFocusControlChanged();
786}
787
788QQuickApplicationWindowAttached::QQuickApplicationWindowAttached(QObject *parent)
789 : QObject(*(new QQuickApplicationWindowAttachedPrivate), parent)
790{
791 Q_D(QQuickApplicationWindowAttached);
792 if (QQuickItem *item = qobject_cast<QQuickItem *>(o: parent)) {
793 d->windowChange(wnd: item->window());
794 QObjectPrivate::connect(sender: item, signal: &QQuickItem::windowChanged, receiverPrivate: d, slot: &QQuickApplicationWindowAttachedPrivate::windowChange);
795 if (!d->window) {
796 QQuickItem *p = item;
797 while (p) {
798 if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(object: p->parent())) {
799 d->windowChange(wnd: popup->window());
800 QObjectPrivate::connect(sender: popup, signal: &QQuickPopup::windowChanged, receiverPrivate: d, slot: &QQuickApplicationWindowAttachedPrivate::windowChange);
801 }
802 p = p->parentItem();
803 }
804 }
805 } else if (QQuickPopup *popup = qobject_cast<QQuickPopup *>(object: parent)) {
806 d->windowChange(wnd: popup->window());
807 QObjectPrivate::connect(sender: popup, signal: &QQuickPopup::windowChanged, receiverPrivate: d, slot: &QQuickApplicationWindowAttachedPrivate::windowChange);
808 }
809}
810
811/*!
812 \qmlattachedproperty ApplicationWindow QtQuick.Controls::ApplicationWindow::window
813 \readonly
814
815 This attached property holds the application window. The property can be attached
816 to any item. The value is \c null if the item is not in an ApplicationWindow.
817
818 \sa {Attached ApplicationWindow Properties}
819*/
820QQuickApplicationWindow *QQuickApplicationWindowAttached::window() const
821{
822 Q_D(const QQuickApplicationWindowAttached);
823 return qobject_cast<QQuickApplicationWindow *>(object: d->window);
824}
825
826/*!
827 \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::contentItem
828 \readonly
829
830 This attached property holds the window content item. The property can be attached
831 to any item. The value is \c null if the item is not in an ApplicationWindow.
832
833 \sa {Attached ApplicationWindow Properties}
834*/
835QQuickItem *QQuickApplicationWindowAttached::contentItem() const
836{
837 Q_D(const QQuickApplicationWindowAttached);
838 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: d->window))
839 return window->contentItem();
840 return nullptr;
841}
842
843/*!
844 \qmlattachedproperty Control QtQuick.Controls::ApplicationWindow::activeFocusControl
845 \readonly
846
847 This attached property holds the control that currently has active focus, or \c null
848 if there is no control with active focus. The property can be attached to any item.
849 The value is \c null if the item is not in a window, or the window has no active focus.
850
851 \sa Window::activeFocusItem, {Attached ApplicationWindow Properties}
852*/
853QQuickItem *QQuickApplicationWindowAttached::activeFocusControl() const
854{
855 Q_D(const QQuickApplicationWindowAttached);
856 return d->activeFocusControl;
857}
858
859/*!
860 \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::header
861 \readonly
862
863 This attached property holds the window header item. The property can be attached
864 to any item. The value is \c null if the item is not in an ApplicationWindow, or
865 the window has no header item.
866
867 \sa {Attached ApplicationWindow Properties}
868*/
869QQuickItem *QQuickApplicationWindowAttached::header() const
870{
871 Q_D(const QQuickApplicationWindowAttached);
872 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: d->window))
873 return window->header();
874 return nullptr;
875}
876
877/*!
878 \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::footer
879 \readonly
880
881 This attached property holds the window footer item. The property can be attached
882 to any item. The value is \c null if the item is not in an ApplicationWindow, or
883 the window has no footer item.
884
885 \sa {Attached ApplicationWindow Properties}
886*/
887QQuickItem *QQuickApplicationWindowAttached::footer() const
888{
889 Q_D(const QQuickApplicationWindowAttached);
890 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: d->window))
891 return window->footer();
892 return nullptr;
893}
894
895/*!
896 \since QtQuick.Controls 2.3 (Qt 5.10)
897 \qmlattachedproperty Item QtQuick.Controls::ApplicationWindow::menuBar
898 \readonly
899
900 This attached property holds the window menu bar. The property can be attached
901 to any item. The value is \c null if the item is not in an ApplicationWindow, or
902 the window has no menu bar.
903
904 \sa {Attached ApplicationWindow Properties}
905*/
906QQuickItem *QQuickApplicationWindowAttached::menuBar() const
907{
908 Q_D(const QQuickApplicationWindowAttached);
909 if (QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: d->window))
910 return window->menuBar();
911 return nullptr;
912}
913
914QT_END_NAMESPACE
915
916#include "moc_qquickapplicationwindow_p.cpp"
917

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