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

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