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 test suite 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 <qtest.h>
38#include <QtTest/QSignalSpy>
39#include <QtQml/qqmlengine.h>
40#include <QtQml/qqmlcomponent.h>
41#include <QtQml/qqmlcontext.h>
42#include <QtQuick/qquickview.h>
43#include <QtQuick/private/qquickitem_p.h>
44#include <QtGui/private/qguiapplication_p.h>
45#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
46#include <QtQuickTemplates2/private/qquickoverlay_p.h>
47#include <QtQuickTemplates2/private/qquickcontrol_p.h>
48#include <QtQuickTemplates2/private/qquicklabel_p.h>
49#include <QtQuickTemplates2/private/qquickmenu_p.h>
50#include <QtQuickTemplates2/private/qquickpopup_p.h>
51#include <QtQuickTemplates2/private/qquicktextarea_p.h>
52#include <QtQuickTemplates2/private/qquicktextfield_p.h>
53#include <QtQuickTemplates2/private/qquicktheme_p_p.h>
54#include "../shared/util.h"
55#include "../shared/visualtestutil.h"
56
57using namespace QQuickVisualTestUtil;
58
59class tst_QQuickApplicationWindow : public QQmlDataTest
60{
61 Q_OBJECT
62public:
63
64private slots:
65 void qmlCreation();
66 void activeFocusOnTab1();
67 void activeFocusOnTab2();
68 void defaultFocus();
69 void implicitFill();
70 void attachedProperties();
71 void font();
72 void defaultFont();
73 void locale();
74 void activeFocusControl_data();
75 void activeFocusControl();
76 void focusAfterPopupClosed();
77 void clearFocusOnDestruction();
78 void layout();
79 void layoutLayout();
80 void componentComplete();
81};
82
83void tst_QQuickApplicationWindow::qmlCreation()
84{
85 QQmlEngine engine;
86 QQmlComponent component(&engine);
87 component.loadUrl(url: testFileUrl(fileName: "basicapplicationwindow.qml"));
88 QObject* created = component.create();
89 QScopedPointer<QObject> cleanup(created);
90 QVERIFY(created);
91
92 QQuickWindow* window = qobject_cast<QQuickWindow*>(object: created);
93 QVERIFY(window);
94 QVERIFY(!window->isVisible());
95
96 QCOMPARE(created->property("title"), QVariant("Test Application Window"));
97
98 QQuickItem* statusBar = qvariant_cast<QQuickItem*>(v: created->property(name: "statusBar"));
99 QVERIFY(!statusBar);
100
101 QQuickItem* header = qvariant_cast<QQuickItem*>(v: created->property(name: "header"));
102 QVERIFY(!header);
103
104 QQuickItem* footer = qvariant_cast<QQuickItem*>(v: created->property(name: "footer"));
105 QVERIFY(!footer);
106}
107
108void tst_QQuickApplicationWindow::activeFocusOnTab1()
109{
110 QQmlEngine engine;
111 QQmlComponent component(&engine);
112 component.loadUrl(url: testFileUrl(fileName: "activefocusontab.qml"));
113 QObject* created = component.create();
114 QScopedPointer<QObject> cleanup(created);
115 QVERIFY(created);
116
117 QQuickWindow* window = qobject_cast<QQuickWindow*>(object: created);
118 QVERIFY(window);
119 window->show();
120 window->requestActivate();
121 QVERIFY(QTest::qWaitForWindowActive(window));
122 QVERIFY(QGuiApplication::focusWindow() == window);
123
124 QQuickItem* contentItem = window->contentItem();
125 QVERIFY(contentItem);
126 QVERIFY(contentItem->hasActiveFocus());
127
128 QQuickItem* item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub1");
129 QVERIFY(item);
130 QVERIFY(!item->hasActiveFocus());
131
132 // Tab: contentItem->sub1
133 QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
134 QGuiApplication::sendEvent(receiver: window, event: &key);
135 QVERIFY(key.isAccepted());
136
137 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub1");
138 QVERIFY(item);
139 QVERIFY(item->hasActiveFocus());
140
141 // Tab: sub1->sub2
142 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
143 QGuiApplication::sendEvent(receiver: window, event: &key);
144 QVERIFY(key.isAccepted());
145
146 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub2");
147 QVERIFY(item);
148 QVERIFY(item->hasActiveFocus());
149
150 // Tab: sub2->sub1
151 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
152 QGuiApplication::sendEvent(receiver: window, event: &key);
153 QVERIFY(key.isAccepted());
154
155 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub1");
156 QVERIFY(item);
157 QVERIFY(item->hasActiveFocus());
158}
159
160void tst_QQuickApplicationWindow::activeFocusOnTab2()
161{
162 QQmlEngine engine;
163 QQmlComponent component(&engine);
164 component.loadUrl(url: testFileUrl(fileName: "activefocusontab.qml"));
165 QObject* created = component.create();
166 QScopedPointer<QObject> cleanup(created);
167 QVERIFY(created);
168
169 QQuickWindow* window = qobject_cast<QQuickWindow*>(object: created);
170 QVERIFY(window);
171 window->show();
172 window->requestActivate();
173 QVERIFY(QTest::qWaitForWindowActive(window));
174 QVERIFY(QGuiApplication::focusWindow() == window);
175
176 QQuickItem* contentItem = window->contentItem();
177 QVERIFY(contentItem);
178 QVERIFY(contentItem->hasActiveFocus());
179
180 QQuickItem* item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub2");
181 QVERIFY(item);
182 QVERIFY(!item->hasActiveFocus());
183
184 // BackTab: contentItem->sub2
185 QKeyEvent key(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
186 QGuiApplication::sendEvent(receiver: window, event: &key);
187 QVERIFY(key.isAccepted());
188
189 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub2");
190 QVERIFY(item);
191 QVERIFY(item->hasActiveFocus());
192
193 // BackTab: sub2->sub1
194 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
195 QGuiApplication::sendEvent(receiver: window, event: &key);
196 QVERIFY(key.isAccepted());
197
198 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub1");
199 QVERIFY(item);
200 QVERIFY(item->hasActiveFocus());
201
202 // BackTab: sub1->sub2
203 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::ShiftModifier, "", false, 1);
204 QGuiApplication::sendEvent(receiver: window, event: &key);
205 QVERIFY(key.isAccepted());
206
207 item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "sub2");
208 QVERIFY(item);
209 QVERIFY(item->hasActiveFocus());
210}
211
212void tst_QQuickApplicationWindow::defaultFocus()
213{
214 QQmlEngine engine;
215 QQmlComponent component(&engine);
216 component.loadUrl(url: testFileUrl(fileName: "defaultFocus.qml"));
217 QObject* created = component.create();
218 QScopedPointer<QObject> cleanup(created);
219 Q_UNUSED(cleanup);
220 QVERIFY(created);
221
222 QQuickWindow* window = qobject_cast<QQuickWindow*>(object: created);
223 QVERIFY(window);
224 window->show();
225 window->requestActivate();
226 QVERIFY(QTest::qWaitForWindowActive(window));
227 QVERIFY(QGuiApplication::focusWindow() == window);
228
229 QQuickItem* contentItem = window->contentItem();
230 QVERIFY(contentItem);
231 QVERIFY(contentItem->hasActiveFocus());
232
233 // A single item in an ApplicationWindow with focus: true should receive focus.
234 QQuickItem* item = findItem<QQuickItem>(parent: window->contentItem(), objectName: "item");
235 QVERIFY(item);
236 QVERIFY(item->hasFocus());
237 QVERIFY(item->hasActiveFocus());
238}
239
240void tst_QQuickApplicationWindow::implicitFill()
241{
242 QQmlEngine engine;
243 QQmlComponent component(&engine);
244 component.loadUrl(url: testFileUrl(fileName: "fill.qml"));
245 QObject* created = component.create();
246 QScopedPointer<QObject> cleanup(created);
247 QVERIFY(created);
248
249 QQuickWindow* window = qobject_cast<QQuickWindow*>(object: created);
250 QVERIFY(window);
251 QVERIFY(!window->isVisible());
252 QCOMPARE(window->width(), 400);
253 QCOMPARE(window->height(), 400);
254
255 window->show();
256 QVERIFY(QTest::qWaitForWindowActive(window));
257
258 QQuickItem *stackView = window->property(name: "stackView").value<QQuickItem*>();
259 QVERIFY(stackView);
260 QCOMPARE(stackView->width(), 400.0);
261 QCOMPARE(stackView->height(), 400.0);
262
263 QQuickItem *nextItem = window->property(name: "nextItem").value<QQuickItem*>();
264 QVERIFY(nextItem);
265
266 QVERIFY(QMetaObject::invokeMethod(window, "pushNextItem"));
267 QCOMPARE(nextItem->width(), 400.0);
268 QCOMPARE(nextItem->height(), 400.0);
269}
270
271void tst_QQuickApplicationWindow::attachedProperties()
272{
273 QQmlEngine engine;
274 QQmlComponent component(&engine);
275 component.loadUrl(url: testFileUrl(fileName: "attachedProperties.qml"));
276
277 QScopedPointer<QObject> object(component.create());
278 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
279
280 QQuickApplicationWindow *window = qobject_cast<QQuickApplicationWindow *>(object: object.data());
281 QVERIFY(window);
282
283 QQuickItem *childControl = object->property(name: "childControl").value<QQuickItem *>();
284 QVERIFY(childControl);
285 QCOMPARE(childControl->property("attached_window").value<QQuickApplicationWindow *>(), window);
286 QCOMPARE(childControl->property("attached_contentItem").value<QQuickItem *>(), window->contentItem());
287 QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), window->activeFocusControl());
288 QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), window->header());
289 QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), window->footer());
290 QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), window->overlay());
291
292 QQuickItem *childItem = object->property(name: "childItem").value<QQuickItem *>();
293 QVERIFY(childItem);
294 QCOMPARE(childItem->property("attached_window").value<QQuickApplicationWindow *>(), window);
295 QCOMPARE(childItem->property("attached_contentItem").value<QQuickItem *>(), window->contentItem());
296 QCOMPARE(childItem->property("attached_activeFocusControl").value<QQuickItem *>(), window->activeFocusControl());
297 QCOMPARE(childItem->property("attached_header").value<QQuickItem *>(), window->header());
298 QCOMPARE(childItem->property("attached_footer").value<QQuickItem *>(), window->footer());
299 QCOMPARE(childItem->property("attached_overlay").value<QQuickItem *>(), window->overlay());
300
301 QObject *childObject = object->property(name: "childObject").value<QObject *>();
302 QVERIFY(childObject);
303 QVERIFY(!childObject->property("attached_window").value<QQuickApplicationWindow *>());
304 QVERIFY(!childObject->property("attached_contentItem").value<QQuickItem *>());
305 QVERIFY(!childObject->property("attached_activeFocusControl").value<QQuickItem *>());
306 QVERIFY(!childObject->property("attached_header").value<QQuickItem *>());
307 QVERIFY(!childObject->property("attached_footer").value<QQuickItem *>());
308 QVERIFY(!childObject->property("attached_overlay").value<QQuickItem *>());
309
310 QQuickWindow *childWindow = object->property(name: "childWindow").value<QQuickWindow *>();
311 QVERIFY(childWindow);
312 QVERIFY(!childWindow->property("attached_window").value<QQuickApplicationWindow *>());
313 QVERIFY(!childWindow->property("attached_contentItem").value<QQuickItem *>());
314 QVERIFY(!childWindow->property("attached_activeFocusControl").value<QQuickItem *>());
315 QVERIFY(!childWindow->property("attached_header").value<QQuickItem *>());
316 QVERIFY(!childWindow->property("attached_footer").value<QQuickItem *>());
317 QVERIFY(!childWindow->property("attached_overlay").value<QQuickItem *>());
318
319 QQuickItem *childWindowControl = object->property(name: "childWindowControl").value<QQuickItem *>();
320 QVERIFY(childWindowControl);
321 QVERIFY(!childWindowControl->property("attached_window").value<QQuickApplicationWindow *>());
322 QVERIFY(!childWindowControl->property("attached_contentItem").value<QQuickItem *>());
323 QVERIFY(!childWindowControl->property("attached_activeFocusControl").value<QQuickItem *>());
324 QVERIFY(!childWindowControl->property("attached_header").value<QQuickItem *>());
325 QVERIFY(!childWindowControl->property("attached_footer").value<QQuickItem *>());
326 QCOMPARE(childWindowControl->property("attached_overlay").value<QQuickItem *>(), QQuickOverlay::overlay(childWindow));
327
328 QQuickItem *childWindowItem = object->property(name: "childWindowItem").value<QQuickItem *>();
329 QVERIFY(childWindowItem);
330 QVERIFY(!childWindowItem->property("attached_window").value<QQuickApplicationWindow *>());
331 QVERIFY(!childWindowItem->property("attached_contentItem").value<QQuickItem *>());
332 QVERIFY(!childWindowItem->property("attached_activeFocusControl").value<QQuickItem *>());
333 QVERIFY(!childWindowItem->property("attached_header").value<QQuickItem *>());
334 QVERIFY(!childWindowItem->property("attached_footer").value<QQuickItem *>());
335 QCOMPARE(childWindowItem->property("attached_overlay").value<QQuickItem *>(), QQuickOverlay::overlay(childWindow));
336
337 QObject *childWindowObject = object->property(name: "childWindowObject").value<QObject *>();
338 QVERIFY(childWindowObject);
339 QVERIFY(!childWindowObject->property("attached_window").value<QQuickApplicationWindow *>());
340 QVERIFY(!childWindowObject->property("attached_contentItem").value<QQuickItem *>());
341 QVERIFY(!childWindowObject->property("attached_activeFocusControl").value<QQuickItem *>());
342 QVERIFY(!childWindowObject->property("attached_header").value<QQuickItem *>());
343 QVERIFY(!childWindowObject->property("attached_footer").value<QQuickItem *>());
344 QVERIFY(!childWindowObject->property("attached_overlay").value<QQuickItem *>());
345
346 QQuickApplicationWindow *childAppWindow = object->property(name: "childAppWindow").value<QQuickApplicationWindow *>();
347 QVERIFY(childAppWindow);
348 QVERIFY(!childAppWindow->property("attached_window").value<QQuickApplicationWindow *>());
349 QVERIFY(!childAppWindow->property("attached_contentItem").value<QQuickItem *>());
350 QVERIFY(!childAppWindow->property("attached_activeFocusControl").value<QQuickItem *>());
351 QVERIFY(!childAppWindow->property("attached_header").value<QQuickItem *>());
352 QVERIFY(!childAppWindow->property("attached_footer").value<QQuickItem *>());
353 QVERIFY(!childAppWindow->property("attached_overlay").value<QQuickItem *>());
354
355 QQuickItem *childAppWindowControl = object->property(name: "childAppWindowControl").value<QQuickItem *>();
356 QVERIFY(childAppWindowControl);
357 QCOMPARE(childAppWindowControl->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow);
358 QCOMPARE(childAppWindowControl->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem());
359 QCOMPARE(childAppWindowControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl());
360 QCOMPARE(childAppWindowControl->property("attached_header").value<QQuickItem *>(), childAppWindow->header());
361 QCOMPARE(childAppWindowControl->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer());
362 QCOMPARE(childAppWindowControl->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay());
363
364 QQuickItem *childAppWindowItem = object->property(name: "childAppWindowItem").value<QQuickItem *>();
365 QVERIFY(childAppWindowItem);
366 QCOMPARE(childAppWindowItem->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow);
367 QCOMPARE(childAppWindowItem->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem());
368 QCOMPARE(childAppWindowItem->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindow->activeFocusControl());
369 QCOMPARE(childAppWindowItem->property("attached_header").value<QQuickItem *>(), childAppWindow->header());
370 QCOMPARE(childAppWindowItem->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer());
371 QCOMPARE(childAppWindowItem->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay());
372
373 QObject *childAppWindowObject = object->property(name: "childAppWindowObject").value<QObject *>();
374 QVERIFY(childAppWindowObject);
375 QVERIFY(!childAppWindowObject->property("attached_window").value<QQuickApplicationWindow *>());
376 QVERIFY(!childAppWindowObject->property("attached_contentItem").value<QQuickItem *>());
377 QVERIFY(!childAppWindowObject->property("attached_activeFocusControl").value<QQuickItem *>());
378 QVERIFY(!childAppWindowObject->property("attached_header").value<QQuickItem *>());
379 QVERIFY(!childAppWindowObject->property("attached_footer").value<QQuickItem *>());
380 QVERIFY(!childAppWindowObject->property("attached_overlay").value<QQuickItem *>());
381
382 window->show();
383 window->requestActivate();
384 QVERIFY(QTest::qWaitForWindowActive(window));
385
386 QVERIFY(!childControl->hasActiveFocus());
387 childControl->forceActiveFocus();
388 QTRY_VERIFY(childControl->hasActiveFocus());
389 QCOMPARE(window->activeFocusItem(), childControl);
390 QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childControl);
391
392 QQuickItem *header = new QQuickItem;
393 window->setHeader(header);
394 QCOMPARE(window->header(), header);
395 QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), header);
396
397 QQuickItem *footer = new QQuickItem;
398 window->setFooter(footer);
399 QCOMPARE(window->footer(), footer);
400 QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), footer);
401
402 childAppWindow->show();
403 childAppWindow->requestActivate();
404 QVERIFY(QTest::qWaitForWindowActive(childAppWindow));
405
406 QVERIFY(!childAppWindowControl->hasActiveFocus());
407 childAppWindowControl->forceActiveFocus();
408 QTRY_VERIFY(childAppWindowControl->hasActiveFocus());
409 QCOMPARE(childAppWindow->activeFocusItem(), childAppWindowControl);
410 QCOMPARE(childAppWindowControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindowControl);
411
412 childControl->setParentItem(childAppWindow->contentItem());
413 QCOMPARE(childControl->window(), childAppWindow);
414 QCOMPARE(childControl->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow);
415 QCOMPARE(childControl->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem());
416 QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindowControl);
417 QCOMPARE(childControl->property("attached_header").value<QQuickItem *>(), childAppWindow->header());
418 QCOMPARE(childControl->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer());
419 QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay());
420
421 childItem->setParentItem(childAppWindow->contentItem());
422 QCOMPARE(childItem->window(), childAppWindow);
423 QCOMPARE(childItem->property("attached_window").value<QQuickApplicationWindow *>(), childAppWindow);
424 QCOMPARE(childItem->property("attached_contentItem").value<QQuickItem *>(), childAppWindow->contentItem());
425 QCOMPARE(childItem->property("attached_activeFocusControl").value<QQuickItem *>(), childAppWindowControl);
426 QCOMPARE(childItem->property("attached_header").value<QQuickItem *>(), childAppWindow->header());
427 QCOMPARE(childItem->property("attached_footer").value<QQuickItem *>(), childAppWindow->footer());
428 QCOMPARE(childItem->property("attached_overlay").value<QQuickItem *>(), childAppWindow->overlay());
429
430 childControl->setParentItem(nullptr);
431 QVERIFY(!childControl->window());
432 QVERIFY(!childControl->property("attached_window").value<QQuickApplicationWindow *>());
433 QVERIFY(!childControl->property("attached_contentItem").value<QQuickItem *>());
434 QVERIFY(!childControl->property("attached_activeFocusControl").value<QQuickItem *>());
435 QVERIFY(!childControl->property("attached_header").value<QQuickItem *>());
436 QVERIFY(!childControl->property("attached_footer").value<QQuickItem *>());
437 QVERIFY(!childControl->property("attached_overlay").value<QQuickItem *>());
438
439 childItem->setParentItem(nullptr);
440 QVERIFY(!childItem->window());
441 QVERIFY(!childItem->property("attached_window").value<QQuickApplicationWindow *>());
442 QVERIFY(!childItem->property("attached_contentItem").value<QQuickItem *>());
443 QVERIFY(!childItem->property("attached_activeFocusControl").value<QQuickItem *>());
444 QVERIFY(!childItem->property("attached_header").value<QQuickItem *>());
445 QVERIFY(!childItem->property("attached_footer").value<QQuickItem *>());
446 QVERIFY(!childItem->property("attached_overlay").value<QQuickItem *>());
447 childAppWindow->close();
448 qApp->processEvents();
449
450 childWindow->show();
451 childWindow->requestActivate();
452 QVERIFY(QTest::qWaitForWindowActive(childWindow));
453
454 QVERIFY(!childWindowControl->hasActiveFocus());
455 childWindowControl->forceActiveFocus();
456 QTRY_VERIFY(childWindowControl->hasActiveFocus());
457 QCOMPARE(childWindow->activeFocusItem(), childWindowControl);
458 QCOMPARE(childWindowControl->property("attached_activeFocusControl").value<QQuickItem *>(), childWindowControl);
459
460 childControl->setParentItem(childWindow->contentItem());
461 QCOMPARE(childControl->window(), childWindow);
462 QVERIFY(!childControl->property("attached_window").value<QQuickWindow *>());
463 QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childWindowControl);
464 QVERIFY(!childControl->property("attached_contentItem").value<QQuickItem *>());
465 QVERIFY(!childControl->property("attached_header").value<QQuickItem *>());
466 QVERIFY(!childControl->property("attached_footer").value<QQuickItem *>());
467 QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), QQuickOverlay::overlay(childWindow));
468
469 childItem->setParentItem(childWindow->contentItem());
470 QCOMPARE(childItem->window(), childWindow);
471 QVERIFY(!childControl->property("attached_window").value<QQuickWindow *>());
472 QCOMPARE(childControl->property("attached_activeFocusControl").value<QQuickItem *>(), childWindowControl);
473 QVERIFY(!childControl->property("attached_contentItem").value<QQuickItem *>());
474 QVERIFY(!childControl->property("attached_header").value<QQuickItem *>());
475 QVERIFY(!childControl->property("attached_footer").value<QQuickItem *>());
476 QCOMPARE(childControl->property("attached_overlay").value<QQuickItem *>(), QQuickOverlay::overlay(childWindow));
477
478 childControl->setParentItem(nullptr);
479 QVERIFY(!childControl->window());
480 QVERIFY(!childControl->property("attached_window").value<QQuickWindow *>());
481 QVERIFY(!childControl->property("attached_contentItem").value<QQuickItem *>());
482 QVERIFY(!childControl->property("attached_activeFocusControl").value<QQuickItem *>());
483 QVERIFY(!childControl->property("attached_header").value<QQuickItem *>());
484 QVERIFY(!childControl->property("attached_footer").value<QQuickItem *>());
485 QVERIFY(!childControl->property("attached_overlay").value<QQuickItem *>());
486
487 childItem->setParentItem(nullptr);
488 QVERIFY(!childItem->window());
489 QVERIFY(!childItem->property("attached_window").value<QQuickWindow *>());
490 QVERIFY(!childItem->property("attached_contentItem").value<QQuickItem *>());
491 QVERIFY(!childItem->property("attached_activeFocusControl").value<QQuickItem *>());
492 QVERIFY(!childItem->property("attached_header").value<QQuickItem *>());
493 QVERIFY(!childItem->property("attached_footer").value<QQuickItem *>());
494 QVERIFY(!childItem->property("attached_overlay").value<QQuickItem *>());
495 childWindow->close();
496}
497
498void tst_QQuickApplicationWindow::font()
499{
500 QQmlEngine engine;
501 QQmlComponent component(&engine);
502 component.loadUrl(url: testFileUrl(fileName: "font.qml"));
503 QObject* created = component.create();
504 QScopedPointer<QObject> cleanup(created);
505 QVERIFY(created);
506
507 QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object: created);
508 QVERIFY(window);
509 QVERIFY(!window->isVisible());
510 QCOMPARE(window->width(), 400);
511 QCOMPARE(window->height(), 400);
512
513 window->show();
514 QVERIFY(QTest::qWaitForWindowActive(window));
515
516 QFont font = window->font();
517
518 QQuickControl *mainItem = window->property(name: "mainItem").value<QQuickControl*>();
519 QVERIFY(mainItem);
520 QCOMPARE(mainItem->width(), 400.0);
521 QCOMPARE(mainItem->height(), 400.0);
522 QCOMPARE(mainItem->font(), font);
523
524 QQuickControl *item2 = mainItem->property(name: "item_2").value<QQuickControl*>();
525 QVERIFY(item2);
526 QQuickControl *item3 = mainItem->property(name: "item_3").value<QQuickControl*>();
527 QVERIFY(item3);
528 QQuickTextArea *item4 = mainItem->property(name: "item_4").value<QQuickTextArea*>();
529 QVERIFY(item4);
530 QQuickTextField *item5 = mainItem->property(name: "item_5").value<QQuickTextField*>();
531 QVERIFY(item5);
532 QQuickLabel *item6 = mainItem->property(name: "item_6").value<QQuickLabel*>();
533 QVERIFY(item6);
534
535 QCOMPARE(item2->font(), font);
536 QCOMPARE(item3->font(), font);
537 QCOMPARE(item4->font(), font);
538 QCOMPARE(item5->font(), font);
539 QCOMPARE(item6->font(), font);
540
541 int pointSize = font.pointSize();
542 font.setPixelSize(pointSize + 5);
543 window->setFont(font);
544
545 QCOMPARE(window->font(), font);
546 QCOMPARE(mainItem->font(), font);
547 QCOMPARE(item2->font(), font);
548 QCOMPARE(item3->font(), font);
549 QCOMPARE(item4->font(), font);
550 QCOMPARE(item5->font(), font);
551 QCOMPARE(item6->font(), font);
552}
553
554class TestTheme : public QQuickTheme
555{
556public:
557 TestTheme()
558 {
559 setFont(scope: System, font: QFont("Courier"));
560 }
561};
562
563void tst_QQuickApplicationWindow::defaultFont()
564{
565 QQuickThemePrivate::instance.reset(other: new TestTheme);
566
567 QQmlEngine engine;
568 QQmlComponent component(&engine);
569 component.setData("import QtQuick.Controls 2.1; ApplicationWindow { }", baseUrl: QUrl());
570
571 QScopedPointer<QQuickApplicationWindow> window;
572 window.reset(other: static_cast<QQuickApplicationWindow *>(component.create()));
573 QVERIFY(!window.isNull());
574 QCOMPARE(window->font(), QQuickTheme::font(QQuickTheme::System));
575}
576
577void tst_QQuickApplicationWindow::locale()
578{
579 QQmlEngine engine;
580 QQmlComponent component(&engine);
581 component.loadUrl(url: testFileUrl(fileName: "locale.qml"));
582 QObject* created = component.create();
583 QScopedPointer<QObject> cleanup(created);
584 QVERIFY(created);
585
586 QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object: created);
587 QVERIFY(window);
588 QVERIFY(!window->isVisible());
589 QCOMPARE(window->width(), 400);
590 QCOMPARE(window->height(), 400);
591
592 window->show();
593 QVERIFY(QTest::qWaitForWindowActive(window));
594
595 QLocale l = window->locale();
596
597 QQuickControl *mainItem = window->property(name: "mainItem").value<QQuickControl*>();
598 QVERIFY(mainItem);
599 QCOMPARE(mainItem->width(), 400.0);
600 QCOMPARE(mainItem->height(), 400.0);
601 QCOMPARE(mainItem->locale(), l);
602
603 QQuickControl *item2 = mainItem->property(name: "item_2").value<QQuickControl*>();
604 QVERIFY(item2);
605 QQuickControl *item3 = mainItem->property(name: "item_3").value<QQuickControl*>();
606 QVERIFY(item3);
607
608 QCOMPARE(item2->locale(), l);
609 QCOMPARE(item3->locale(), l);
610
611 l = QLocale("en_US");
612 window->setLocale(l);
613
614 QCOMPARE(window->locale(), l);
615 QCOMPARE(mainItem->locale(), l);
616 QCOMPARE(item2->locale(), l);
617 QCOMPARE(item3->locale(), l);
618
619 l = QLocale("ar_EG");
620 window->setLocale(l);
621
622 QCOMPARE(window->locale(), l);
623 QCOMPARE(mainItem->locale(), l);
624 QCOMPARE(item2->locale(), l);
625 QCOMPARE(item3->locale(), l);
626}
627
628void tst_QQuickApplicationWindow::activeFocusControl_data()
629{
630 QTest::addColumn<QByteArray>(name: "containerName");
631 QTest::addColumn<QByteArray>(name: "activeFocusItemName");
632 QTest::addColumn<QByteArray>(name: "activeFocusControlName");
633
634 QTest::newRow(dataTag: "Column:TextInput") << QByteArray("container_column") << QByteArray("textInput_column") << QByteArray();
635 QTest::newRow(dataTag: "Column:TextEdit") << QByteArray("container_column") << QByteArray("textEdit_column") << QByteArray();
636 QTest::newRow(dataTag: "Column:TextField") << QByteArray("container_column") << QByteArray("textField_column") << QByteArray("textField_column");
637 QTest::newRow(dataTag: "Column:TextArea") << QByteArray("container_column") << QByteArray("textArea_column") << QByteArray("textArea_column");
638 QTest::newRow(dataTag: "Column:SpinBox") << QByteArray("container_column") << QByteArray("spinContent_column") << QByteArray("spinBox_column");
639
640 QTest::newRow(dataTag: "Frame:TextInput") << QByteArray("container_frame") << QByteArray("textInput_frame") << QByteArray("container_frame");
641 QTest::newRow(dataTag: "Frame:TextEdit") << QByteArray("container_frame") << QByteArray("textEdit_frame") << QByteArray("container_frame");
642 QTest::newRow(dataTag: "Frame:TextField") << QByteArray("container_frame") << QByteArray("textField_frame") << QByteArray("textField_frame");
643 QTest::newRow(dataTag: "Frame:TextArea") << QByteArray("container_frame") << QByteArray("textArea_frame") << QByteArray("textArea_frame");
644 QTest::newRow(dataTag: "Frame:SpinBox") << QByteArray("container_frame") << QByteArray("spinContent_frame") << QByteArray("spinBox_frame");
645}
646
647void tst_QQuickApplicationWindow::activeFocusControl()
648{
649 QFETCH(QByteArray, containerName);
650 QFETCH(QByteArray, activeFocusItemName);
651 QFETCH(QByteArray, activeFocusControlName);
652
653 QQmlEngine engine;
654 QQmlComponent component(&engine);
655 component.loadUrl(url: testFileUrl(fileName: "activeFocusControl.qml"));
656 QScopedPointer<QObject> object(component.create());
657 QVERIFY(!object.isNull());
658
659 QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object: object.data());
660 QVERIFY(window);
661 QVERIFY(!window->isVisible());
662 QCOMPARE(window->width(), 400);
663 QCOMPARE(window->height(), 400);
664
665 window->show();
666 QVERIFY(QTest::qWaitForWindowActive(window));
667
668 QQuickItem *container = window->property(name: containerName).value<QQuickItem*>();
669 QVERIFY(container);
670
671 QQuickItem *activeFocusItem = window->property(name: activeFocusItemName).value<QQuickItem*>();
672 QVERIFY(activeFocusItem);
673 activeFocusItem->forceActiveFocus();
674 QVERIFY(activeFocusItem->hasActiveFocus());
675 QCOMPARE(window->activeFocusItem(), activeFocusItem);
676
677 QQuickItem *activeFocusControl = window->property(name: activeFocusControlName).value<QQuickItem*>();
678 if (activeFocusControlName.isEmpty()) {
679 QVERIFY(!activeFocusControl);
680 } else {
681 QVERIFY(activeFocusControl);
682 QVERIFY(activeFocusControl->hasActiveFocus());
683 }
684 QCOMPARE(window->activeFocusControl(), activeFocusControl);
685}
686
687void tst_QQuickApplicationWindow::focusAfterPopupClosed()
688{
689 QQmlEngine engine;
690 QQmlComponent component(&engine);
691 component.loadUrl(url: testFileUrl(fileName: "focusAfterPopupClosed.qml"));
692 QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow*>(object: component.create()));
693 QVERIFY(window);
694
695 window->show();
696 window->requestActivate();
697 QVERIFY(QTest::qWaitForWindowActive(window.data()));
698 QVERIFY(QGuiApplication::focusWindow() == window.data());
699
700 QQuickItem* contentItem = window->contentItem();
701 QVERIFY(contentItem);
702 QVERIFY(contentItem->hasActiveFocus());
703
704 QQuickItem* focusScope = window->property(name: "focusScope").value<QQuickItem*>();
705 QVERIFY(focusScope);
706 QVERIFY(focusScope->hasActiveFocus());
707
708 QSignalSpy focusScopeSpy(window.data(), SIGNAL(focusScopeKeyPressed()));
709 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
710 QCOMPARE(focusScopeSpy.count(), 1);
711
712 // Open the menu.
713 QQuickItem* toolButton = window->property(name: "toolButton").value<QQuickItem*>();
714 QVERIFY(toolButton);
715 QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier,
716 pos: toolButton->mapFromScene(point: QPointF(toolButton->width() / 2, toolButton->height() / 2)).toPoint());
717 QVERIFY(!focusScope->hasActiveFocus());
718
719 // The FocusScope shouldn't receive any key events while the menu is open.
720 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
721 QCOMPARE(focusScopeSpy.count(), 1);
722
723 // Close the menu. The FocusScope should regain focus.
724 QTest::keyClick(window: window.data(), key: Qt::Key_Escape);
725 QVERIFY(focusScope->hasActiveFocus());
726
727 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
728 QCOMPARE(focusScopeSpy.count(), 2);
729
730 QQuickPopup *focusPopup = window->property(name: "focusPopup").value<QQuickPopup*>();
731 QVERIFY(focusPopup);
732 QVERIFY(!focusPopup->hasActiveFocus());
733
734 focusPopup->open();
735 QVERIFY(focusPopup->isVisible());
736
737 QSignalSpy focusPopupSpy(window.data(), SIGNAL(focusPopupKeyPressed()));
738 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
739 QCOMPARE(focusPopupSpy.count(), 1);
740
741 QQuickMenu *fileMenu = window->property(name: "fileMenu").value<QQuickMenu*>();
742 QVERIFY(fileMenu);
743 fileMenu->open();
744 QVERIFY(fileMenu->isVisible());
745
746 // The Popup shouldn't receive any key events while the menu is open.
747 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
748 QCOMPARE(focusPopupSpy.count(), 1);
749
750 // Close the menu. The Popup should regain focus.
751 QTest::keyClick(window: window.data(), key: Qt::Key_Escape);
752 QVERIFY(focusPopup->hasActiveFocus());
753
754 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
755 QCOMPARE(focusPopupSpy.count(), 2);
756
757 // Close the popup. The FocusScope should regain focus.
758 QTest::keyClick(window: window.data(), key: Qt::Key_Escape);
759 QVERIFY(focusScope->hasActiveFocus());
760
761 QTest::keyClick(window: window.data(), key: Qt::Key_Space);
762 QCOMPARE(focusScopeSpy.count(), 3);
763}
764
765void tst_QQuickApplicationWindow::clearFocusOnDestruction()
766{
767 QQmlEngine engine;
768 QQmlComponent component(&engine);
769 component.loadUrl(url: testFileUrl(fileName: "clearfocusondestruction.qml"));
770 QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow*>(object: component.create()));
771 QVERIFY(window);
772
773 window->show();
774 window->requestActivate();
775 QVERIFY(QTest::qWaitForWindowActive(window.data()));
776 QVERIFY(QGuiApplication::focusWindow() == window.data());
777
778 QQuickItem* contentItem = window->contentItem();
779 QVERIFY(contentItem);
780 QVERIFY(contentItem->hasActiveFocus());
781
782 QQuickItem* focusScope = window->property(name: "textfield").value<QQuickItem*>();
783 QVERIFY(focusScope);
784 QVERIFY(focusScope->hasActiveFocus());
785
786 QSignalSpy spy(window.data(), SIGNAL(activeFocusControlChanged()));
787 // destroy the window, do not crash
788 window.reset();
789
790 /*
791 QQuickWindow::activeFocusItemChanged() is emitted inconsistently and
792 only for certain use cases. Ideally it should be emitted whenever a
793 QQuickWindow with a focus item is destroyed, but it doesn't... It might
794 also be favorable to not emit it for performance reason.
795
796 However, activeFocusControlChanged() is emitted more consistently, which
797 of course makes it inconsistent with the emission of
798 activeFocusItemChanged()....
799
800 Therefore, if you have good reasons to change the behavior (and not emit
801 it) take the test below with a grain of salt.
802 */
803 QCOMPARE(spy.count(), 1);
804}
805
806void tst_QQuickApplicationWindow::layout()
807{
808 QQmlEngine engine;
809 QQmlComponent component(&engine);
810 component.loadUrl(url: testFileUrl(fileName: "layout.qml"));
811 QScopedPointer<QObject> object(component.create());
812 QVERIFY(!object.isNull());
813
814 QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object: object.data());
815 QVERIFY(window);
816 QVERIFY(QTest::qWaitForWindowExposed(window));
817
818 QQuickItem *content = window->contentItem();
819 QVERIFY(content);
820 QQuickItem *menuBar = window->menuBar();
821 QVERIFY(menuBar);
822 QQuickItem *header = window->header();
823 QVERIFY(header);
824 QQuickItem *footer = window->footer();
825 QVERIFY(footer);
826
827 QCOMPARE(menuBar->x(), 0.0);
828 QCOMPARE(menuBar->y(), -menuBar->height() - header->height());
829 QCOMPARE(header->width(), qreal(window->width()));
830 QVERIFY(menuBar->height() > 0);
831
832 QCOMPARE(header->x(), 0.0);
833 QCOMPARE(header->y(), -header->height());
834 QCOMPARE(header->width(), qreal(window->width()));
835 QVERIFY(header->height() > 0);
836
837 QCOMPARE(footer->x(), 0.0);
838 QCOMPARE(footer->y(), content->height());
839 QCOMPARE(footer->width(), qreal(window->width()));
840 QVERIFY(footer->height() > 0.0);
841
842 QCOMPARE(content->x(), 0.0);
843 QCOMPARE(content->y(), menuBar->height() + header->height());
844 QCOMPARE(content->width(), qreal(window->width()));
845 QCOMPARE(content->height(), window->height() - menuBar->height() - header->height() - footer->height());
846
847 menuBar->setVisible(false);
848 QCOMPARE(content->x(), 0.0);
849 QCOMPARE(content->y(), header->height());
850 QCOMPARE(content->width(), qreal(window->width()));
851 QCOMPARE(content->height(), window->height() - header->height() - footer->height());
852
853 header->setVisible(false);
854 QCOMPARE(content->x(), 0.0);
855 QCOMPARE(content->y(), 0.0);
856 QCOMPARE(content->width(), qreal(window->width()));
857 QCOMPARE(content->height(), window->height() - footer->height());
858
859 footer->setVisible(false);
860 QCOMPARE(content->x(), 0.0);
861 QCOMPARE(content->y(), 0.0);
862 QCOMPARE(content->width(), qreal(window->width()));
863 QCOMPARE(content->height(), qreal(window->height()));
864}
865
866void tst_QQuickApplicationWindow::layoutLayout()
867{
868 QQmlEngine engine;
869 QQmlComponent component(&engine);
870 component.loadUrl(url: testFileUrl(fileName: "layoutLayout.qml"));
871 QScopedPointer<QObject> object(component.create());
872 QVERIFY2(!object.isNull(), qPrintable(component.errorString()));
873
874 QQuickApplicationWindow* window = qobject_cast<QQuickApplicationWindow*>(object: object.data());
875 QVERIFY(window);
876 QVERIFY(QTest::qWaitForWindowExposed(window));
877
878 QQuickItem *content = window->contentItem();
879 QVERIFY(content);
880 QQuickItem *header = window->header();
881 QVERIFY(header);
882 QQuickItem *footer = window->footer();
883 QVERIFY(footer);
884
885 QQuickItem *headerChild = header->findChild<QQuickItem*>();
886 QVERIFY(headerChild);
887 QCOMPARE(header->x(), 0.0);
888 QCOMPARE(header->y(), -header->height());
889 QCOMPARE(header->width(), qreal(window->width()));
890 QCOMPARE(headerChild->width(), qreal(window->width()));
891 QVERIFY(header->height() > 0);
892
893 QQuickItem *footerChild = header->findChild<QQuickItem*>();
894 QVERIFY(footerChild);
895 QCOMPARE(footer->x(), 0.0);
896 QCOMPARE(footer->y(), content->height());
897 QCOMPARE(footer->width(), qreal(window->width()));
898 QCOMPARE(footerChild->width(), qreal(window->width()));
899 QVERIFY(footer->height() > 0.0);
900}
901
902class FriendlyApplicationWindow : public QQuickApplicationWindow
903{
904 friend class tst_QQuickApplicationWindow;
905};
906
907void tst_QQuickApplicationWindow::componentComplete()
908{
909 FriendlyApplicationWindow cppWindow;
910 QVERIFY(cppWindow.isComponentComplete());
911
912 QQmlEngine engine;
913 QQmlComponent component(&engine);
914 component.setData("import QtQuick.Controls 2.2; ApplicationWindow { }", baseUrl: QUrl());
915
916 FriendlyApplicationWindow *qmlWindow = static_cast<FriendlyApplicationWindow *>(component.beginCreate(engine.rootContext()));
917 QVERIFY(qmlWindow);
918 QVERIFY(!qmlWindow->isComponentComplete());
919
920 component.completeCreate();
921 QVERIFY(qmlWindow->isComponentComplete());
922}
923
924QTEST_MAIN(tst_QQuickApplicationWindow)
925
926#include "tst_qquickapplicationwindow.moc"
927

source code of qtquickcontrols2/tests/auto/qquickapplicationwindow/tst_qquickapplicationwindow.cpp