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 | |
55 | QT_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 | |
120 | static const QQuickItemPrivate::ChangeTypes ItemChanges = QQuickItemPrivate::Visibility |
121 | | QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; |
122 | |
123 | class QQuickApplicationWindowPrivate : public QQuickItemChangeListener |
124 | { |
125 | Q_DECLARE_PUBLIC(QQuickApplicationWindow) |
126 | |
127 | public: |
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 * = nullptr; |
170 | QQuickItem * = nullptr; |
171 | QQuickItem * = 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 | |
181 | static 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 | |
194 | void 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 | |
227 | void 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 | |
235 | void QQuickApplicationWindowPrivate::itemVisibilityChanged(QQuickItem *item) |
236 | { |
237 | Q_UNUSED(item); |
238 | relayout(); |
239 | } |
240 | |
241 | void QQuickApplicationWindowPrivate::itemImplicitWidthChanged(QQuickItem *item) |
242 | { |
243 | Q_UNUSED(item); |
244 | relayout(); |
245 | } |
246 | |
247 | void QQuickApplicationWindowPrivate::itemImplicitHeightChanged(QQuickItem *item) |
248 | { |
249 | Q_UNUSED(item); |
250 | relayout(); |
251 | } |
252 | |
253 | void 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 *> = q->findChildren<QQuickPopup *>(); |
262 | for (QQuickPopup * : popups) |
263 | QQuickControlPrivate::get(control: static_cast<QQuickControl *>(popup->popupItem()))->inheritFont(font: f); |
264 | |
265 | if (changed) |
266 | emit q->fontChanged(); |
267 | } |
268 | |
269 | void QQuickApplicationWindowPrivate::resolveFont() |
270 | { |
271 | QFont resolvedFont = font.resolve(QQuickTheme::font(scope: QQuickTheme::System)); |
272 | setFont_helper(resolvedFont); |
273 | } |
274 | |
275 | void 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 *> = q->findChildren<QQuickPopup *>(); |
284 | for (QQuickPopup * : popups) |
285 | QQuickControlPrivate::get(control: static_cast<QQuickControl *>(popup->popupItem()))->inheritPalette(palette: p); |
286 | |
287 | if (changed) |
288 | emit q->paletteChanged(); |
289 | } |
290 | |
291 | void QQuickApplicationWindowPrivate::resolvePalette() |
292 | { |
293 | QPalette resolvedPalette = palette.resolve(QQuickTheme::palette(scope: QQuickTheme::System)); |
294 | setPalette_helper(resolvedPalette); |
295 | } |
296 | |
297 | static 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 | |
308 | void QQuickApplicationWindowPrivate::_q_updateActiveFocus() |
309 | { |
310 | Q_Q(QQuickApplicationWindow); |
311 | setActiveFocusControl(findActiveFocusControl(window: q)); |
312 | } |
313 | |
314 | void QQuickApplicationWindowPrivate::setActiveFocusControl(QQuickItem *control) |
315 | { |
316 | Q_Q(QQuickApplicationWindow); |
317 | if (activeFocusControl != control) { |
318 | activeFocusControl = control; |
319 | emit q->activeFocusControlChanged(); |
320 | } |
321 | } |
322 | |
323 | void 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 * = qobject_cast<QQuickPopup *>(object: obj)) |
329 | QQuickPopupPrivate::get(popup)->setWindow(static_cast<QQuickApplicationWindow *>(prop->data)); |
330 | } |
331 | |
332 | static inline QString backgroundName() { return QStringLiteral("background" ); } |
333 | |
334 | void QQuickApplicationWindowPrivate::cancelBackground() |
335 | { |
336 | Q_Q(QQuickApplicationWindow); |
337 | quickCancelDeferred(object: q, property: backgroundName()); |
338 | } |
339 | |
340 | void 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 | |
352 | QQuickApplicationWindow::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 | |
359 | QQuickApplicationWindow::~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 | |
373 | QQuickApplicationWindowAttached *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 | */ |
396 | QQuickItem *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 | |
404 | void 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 | */ |
447 | QQuickItem *QQuickApplicationWindow::() const |
448 | { |
449 | Q_D(const QQuickApplicationWindow); |
450 | return d->header; |
451 | } |
452 | |
453 | void QQuickApplicationWindow::(QQuickItem *) |
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 | */ |
502 | QQuickItem *QQuickApplicationWindow::() const |
503 | { |
504 | Q_D(const QQuickApplicationWindow); |
505 | return d->footer; |
506 | } |
507 | |
508 | void QQuickApplicationWindow::(QQuickItem *) |
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 | */ |
557 | QQmlListProperty<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 | */ |
578 | QQuickItem *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 | */ |
604 | QQuickItem *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 | */ |
648 | QQuickOverlay *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 | */ |
679 | QFont QQuickApplicationWindow::font() const |
680 | { |
681 | Q_D(const QQuickApplicationWindow); |
682 | return d->font; |
683 | } |
684 | |
685 | void 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 | |
698 | void 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 | */ |
717 | QLocale QQuickApplicationWindow::locale() const |
718 | { |
719 | Q_D(const QQuickApplicationWindow); |
720 | return d->locale; |
721 | } |
722 | |
723 | void 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 *> = QQuickWindow::contentItem()->findChildren<QQuickPopup *>(); |
734 | for (QQuickPopup * : popups) |
735 | QQuickControlPrivate::get(control: static_cast<QQuickControl *>(popup->popupItem()))->updateLocale(l: locale, e: false); // explicit=false |
736 | |
737 | emit localeChanged(); |
738 | } |
739 | |
740 | void 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 | */ |
761 | QPalette QQuickApplicationWindow::palette() const |
762 | { |
763 | Q_D(const QQuickApplicationWindow); |
764 | return d->palette; |
765 | } |
766 | |
767 | void 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 | |
777 | void 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 | */ |
800 | QQuickItem *QQuickApplicationWindow::() const |
801 | { |
802 | Q_D(const QQuickApplicationWindow); |
803 | return d->menuBar; |
804 | } |
805 | |
806 | void QQuickApplicationWindow::(QQuickItem *) |
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 | |
829 | bool QQuickApplicationWindow::isComponentComplete() const |
830 | { |
831 | Q_D(const QQuickApplicationWindow); |
832 | return d->complete; |
833 | } |
834 | |
835 | void QQuickApplicationWindow::classBegin() |
836 | { |
837 | Q_D(QQuickApplicationWindow); |
838 | d->complete = false; |
839 | QQuickWindowQmlImpl::classBegin(); |
840 | d->resolveFont(); |
841 | d->resolvePalette(); |
842 | } |
843 | |
844 | void QQuickApplicationWindow::componentComplete() |
845 | { |
846 | Q_D(QQuickApplicationWindow); |
847 | d->complete = true; |
848 | d->executeBackground(complete: true); |
849 | QQuickWindowQmlImpl::componentComplete(); |
850 | d->relayout(); |
851 | } |
852 | |
853 | void QQuickApplicationWindow::resizeEvent(QResizeEvent *event) |
854 | { |
855 | Q_D(QQuickApplicationWindow); |
856 | QQuickWindowQmlImpl::resizeEvent(event); |
857 | d->relayout(); |
858 | } |
859 | |
860 | class QQuickApplicationWindowAttachedPrivate : public QObjectPrivate |
861 | { |
862 | Q_DECLARE_PUBLIC(QQuickApplicationWindowAttached) |
863 | |
864 | public: |
865 | void windowChange(QQuickWindow *wnd); |
866 | void activeFocusChange(); |
867 | |
868 | QQuickWindow *window = nullptr; |
869 | QQuickItem *activeFocusControl = nullptr; |
870 | }; |
871 | |
872 | void 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 | |
925 | void 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 | |
940 | QQuickApplicationWindowAttached::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 * = 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 * = 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 | */ |
972 | QQuickApplicationWindow *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 | */ |
987 | QQuickItem *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 | */ |
1005 | QQuickItem *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 | */ |
1021 | QQuickItem *QQuickApplicationWindowAttached::() 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 | */ |
1039 | QQuickItem *QQuickApplicationWindowAttached::() 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 | */ |
1059 | QQuickOverlay *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 | */ |
1076 | QQuickItem *QQuickApplicationWindowAttached::() 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 | |
1084 | QT_END_NAMESPACE |
1085 | |
1086 | #include "moc_qquickapplicationwindow_p.cpp" |
1087 | |