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 <QtTest> |
38 | #include <QtQml> |
39 | #include "../shared/util.h" |
40 | #include "../shared/visualtestutil.h" |
41 | #include "../shared/qtest_quickcontrols.h" |
42 | |
43 | #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> |
44 | #include <QtQuickTemplates2/private/qquickmenu_p.h> |
45 | #include <QtQuickTemplates2/private/qquickmenubar_p.h> |
46 | #include <QtQuickTemplates2/private/qquickmenubaritem_p.h> |
47 | #include <QtQuickTemplates2/private/qquickmenuitem_p.h> |
48 | |
49 | using namespace QQuickVisualTestUtil; |
50 | |
51 | class : public QQmlDataTest |
52 | { |
53 | Q_OBJECT |
54 | |
55 | public: |
56 | |
57 | private slots: |
58 | void delegate(); |
59 | void mouse(); |
60 | void keys(); |
61 | void mnemonics(); |
62 | void addRemove(); |
63 | void checkHighlightWhenMenuDismissed(); |
64 | }; |
65 | |
66 | void tst_qquickmenubar::() |
67 | { |
68 | QQmlApplicationEngine engine(testFileUrl(fileName: "empty.qml" )); |
69 | QScopedPointer<QQuickMenuBar> (qobject_cast<QQuickMenuBar *>(object: engine.rootObjects().value(i: 0))); |
70 | QVERIFY(menuBar); |
71 | |
72 | QQmlComponent *delegate = menuBar->delegate(); |
73 | QVERIFY(delegate); |
74 | |
75 | QScopedPointer<QQuickMenuBarItem> item(qobject_cast<QQuickMenuBarItem *>(object: delegate->create())); |
76 | QVERIFY(item); |
77 | } |
78 | |
79 | void tst_qquickmenubar::() |
80 | { |
81 | if ((QGuiApplication::platformName() == QLatin1String("offscreen" )) |
82 | || (QGuiApplication::platformName() == QLatin1String("minimal" ))) |
83 | QSKIP("Mouse highlight not functional on offscreen/minimal platforms" ); |
84 | |
85 | QQmlApplicationEngine engine(testFileUrl(fileName: "menubar.qml" )); |
86 | |
87 | QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: engine.rootObjects().value(i: 0))); |
88 | QVERIFY(window); |
89 | |
90 | centerOnScreen(window: window.data()); |
91 | moveMouseAway(window: window.data()); |
92 | QVERIFY(QTest::qWaitForWindowActive(window.data())); |
93 | |
94 | QQuickMenuBar * = window->property(name: "header" ).value<QQuickMenuBar *>(); |
95 | QVERIFY(menuBar); |
96 | |
97 | QQuickMenu * = menuBar->menuAt(index: 0); |
98 | QQuickMenu * = menuBar->menuAt(index: 1); |
99 | QQuickMenu * = menuBar->menuAt(index: 2); |
100 | QQuickMenu * = menuBar->menuAt(index: 3); |
101 | QVERIFY(fileMenuBarMenu && editMenuBarMenu && viewMenuBarMenu && helpMenuBarMenu); |
102 | |
103 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: fileMenuBarMenu->parentItem()); |
104 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: editMenuBarMenu->parentItem()); |
105 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: viewMenuBarMenu->parentItem()); |
106 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: helpMenuBarMenu->parentItem()); |
107 | QVERIFY(fileMenuBarItem && editMenuBarItem && viewMenuBarItem && helpMenuBarItem); |
108 | |
109 | // highlight a menubar item |
110 | QTest::mouseMove(window: window.data(), pos: fileMenuBarItem->mapToScene(point: QPointF(fileMenuBarItem->width() / 2, fileMenuBarItem->height() / 2)).toPoint()); |
111 | QVERIFY(fileMenuBarItem->isHighlighted()); |
112 | QVERIFY(!fileMenuBarMenu->isVisible()); |
113 | |
114 | // highlight another menubar item |
115 | QTest::mouseMove(window: window.data(), pos: editMenuBarItem->mapToScene(point: QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint()); |
116 | QVERIFY(!fileMenuBarItem->isHighlighted()); |
117 | QVERIFY(editMenuBarItem->isHighlighted()); |
118 | QVERIFY(!fileMenuBarMenu->isVisible()); |
119 | QVERIFY(!editMenuBarMenu->isVisible()); |
120 | |
121 | // trigger a menubar item to open a menu |
122 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: editMenuBarItem->mapToScene(point: QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint()); |
123 | QVERIFY(editMenuBarItem->isHighlighted()); |
124 | QVERIFY(editMenuBarMenu->isVisible()); |
125 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
126 | |
127 | // re-trigger a menubar item to hide the menu |
128 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: editMenuBarItem->mapToScene(point: QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint()); |
129 | QVERIFY(editMenuBarItem->isHighlighted()); |
130 | QVERIFY(editMenuBarItem->hasActiveFocus()); |
131 | QTRY_VERIFY(!editMenuBarMenu->isVisible()); |
132 | |
133 | // re-trigger a menubar item to show the menu again |
134 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: editMenuBarItem->mapToScene(point: QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint()); |
135 | QVERIFY(editMenuBarItem->isHighlighted()); |
136 | QVERIFY(editMenuBarMenu->isVisible()); |
137 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
138 | |
139 | // highlight another menubar item to open another menu |
140 | QTest::mouseMove(window: window.data(), pos: helpMenuBarItem->mapToScene(point: QPointF(helpMenuBarItem->width() / 2, helpMenuBarItem->height() / 2)).toPoint()); |
141 | QVERIFY(!fileMenuBarItem->isHighlighted()); |
142 | QVERIFY(!editMenuBarItem->isHighlighted()); |
143 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
144 | QVERIFY(helpMenuBarItem->isHighlighted()); |
145 | QVERIFY(!fileMenuBarMenu->isVisible()); |
146 | QVERIFY(!viewMenuBarMenu->isVisible()); |
147 | QVERIFY(helpMenuBarMenu->isVisible()); |
148 | QTRY_VERIFY(!editMenuBarMenu->isVisible()); |
149 | QTRY_VERIFY(helpMenuBarMenu->isOpened()); |
150 | |
151 | // trigger a menu item to close the menu |
152 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: helpMenuBarMenu->itemAt(index: 0)); |
153 | QVERIFY(aboutMenuItem); |
154 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: aboutMenuItem->mapToScene(point: QPointF(aboutMenuItem->width() / 2, aboutMenuItem->height() / 2)).toPoint()); |
155 | QVERIFY(!helpMenuBarItem->isHighlighted()); |
156 | QTRY_VERIFY(!helpMenuBarMenu->isVisible()); |
157 | |
158 | // highlight a menubar item |
159 | QTest::mouseMove(window: window.data(), pos: editMenuBarItem->mapToScene(point: QPointF(editMenuBarItem->width() / 2, editMenuBarItem->height() / 2)).toPoint()); |
160 | QVERIFY(editMenuBarItem->isHighlighted()); |
161 | QVERIFY(!helpMenuBarItem->isHighlighted()); |
162 | QVERIFY(!editMenuBarMenu->isVisible()); |
163 | QVERIFY(!helpMenuBarMenu->isVisible()); |
164 | |
165 | // trigger a menubar item to open a menu |
166 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: viewMenuBarItem->mapToScene(point: QPointF(viewMenuBarItem->width() / 2, viewMenuBarItem->height() / 2)).toPoint()); |
167 | QVERIFY(!editMenuBarItem->isHighlighted()); |
168 | QVERIFY(viewMenuBarItem->isHighlighted()); |
169 | QVERIFY(viewMenuBarMenu->isVisible()); |
170 | QTRY_VERIFY(viewMenuBarMenu->isOpened()); |
171 | |
172 | // trigger a menu item to open a sub-menu |
173 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: viewMenuBarMenu->itemAt(index: 0)); |
174 | QVERIFY(alignmentSubMenuItem); |
175 | QQuickMenu * = alignmentSubMenuItem->subMenu(); |
176 | QVERIFY(alignmentSubMenu); |
177 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: alignmentSubMenuItem->mapToScene(point: QPointF(alignmentSubMenuItem->width() / 2, alignmentSubMenuItem->height() / 2)).toPoint()); |
178 | QVERIFY(viewMenuBarMenu->isVisible()); |
179 | QVERIFY(alignmentSubMenu->isVisible()); |
180 | QTRY_VERIFY(alignmentSubMenu->isOpened()); |
181 | |
182 | // trigger a menu item to open a sub-sub-menu |
183 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: alignmentSubMenu->itemAt(index: 1)); |
184 | QVERIFY(verticalSubMenuItem); |
185 | QQuickMenu * = verticalSubMenuItem->subMenu(); |
186 | QVERIFY(verticalSubMenu); |
187 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: verticalSubMenuItem->mapToScene(point: QPointF(verticalSubMenuItem->width() / 2, verticalSubMenuItem->height() / 2)).toPoint()); |
188 | QVERIFY(viewMenuBarMenu->isVisible()); |
189 | QVERIFY(alignmentSubMenu->isVisible()); |
190 | QVERIFY(verticalSubMenu->isVisible()); |
191 | QTRY_VERIFY(verticalSubMenu->isOpened()); |
192 | |
193 | // trigger a menu item to close the whole chain of menus |
194 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: verticalSubMenu->itemAt(index: 1)); |
195 | QVERIFY(centerMenuItem); |
196 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: centerMenuItem->mapToScene(point: QPointF(centerMenuItem->width() / 2, centerMenuItem->height() / 2)).toPoint()); |
197 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
198 | QTRY_VERIFY(!viewMenuBarMenu->isVisible()); |
199 | QTRY_VERIFY(!alignmentSubMenu->isVisible()); |
200 | QTRY_VERIFY(!verticalSubMenu->isVisible()); |
201 | |
202 | // re-highlight the same menubar item |
203 | QTest::mouseMove(window: window.data(), pos: viewMenuBarItem->mapToScene(point: QPointF(viewMenuBarItem->width() / 2, viewMenuBarItem->height() / 2)).toPoint()); |
204 | QVERIFY(viewMenuBarItem->isHighlighted()); |
205 | |
206 | // re-open the chain of menus |
207 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: viewMenuBarItem->mapToScene(point: QPointF(viewMenuBarItem->width() / 2, viewMenuBarItem->height() / 2)).toPoint()); |
208 | QTRY_VERIFY(viewMenuBarMenu->isOpened()); |
209 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: alignmentSubMenuItem->mapToScene(point: QPointF(alignmentSubMenuItem->width() / 2, alignmentSubMenuItem->height() / 2)).toPoint()); |
210 | QTRY_VERIFY(alignmentSubMenu->isOpened()); |
211 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: verticalSubMenuItem->mapToScene(point: QPointF(verticalSubMenuItem->width() / 2, verticalSubMenuItem->height() / 2)).toPoint()); |
212 | QTRY_VERIFY(verticalSubMenu->isOpened()); |
213 | |
214 | // click outside to close the whole chain of menus |
215 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(window->width() - 1, window->height() - 1)); |
216 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
217 | QTRY_VERIFY(!viewMenuBarMenu->isVisible()); |
218 | QTRY_VERIFY(!alignmentSubMenu->isVisible()); |
219 | QTRY_VERIFY(!verticalSubMenu->isVisible()); |
220 | } |
221 | |
222 | void tst_qquickmenubar::() |
223 | { |
224 | QQmlApplicationEngine engine(testFileUrl(fileName: "menubar.qml" )); |
225 | |
226 | QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: engine.rootObjects().value(i: 0))); |
227 | QVERIFY(window); |
228 | |
229 | centerOnScreen(window: window.data()); |
230 | moveMouseAway(window: window.data()); |
231 | QVERIFY(QTest::qWaitForWindowActive(window.data())); |
232 | |
233 | QQuickMenuBar * = window->property(name: "header" ).value<QQuickMenuBar *>(); |
234 | QVERIFY(menuBar); |
235 | |
236 | QQuickMenu * = menuBar->menuAt(index: 0); |
237 | QQuickMenu * = menuBar->menuAt(index: 1); |
238 | QQuickMenu * = menuBar->menuAt(index: 2); |
239 | QQuickMenu * = menuBar->menuAt(index: 3); |
240 | QVERIFY(fileMenuBarMenu && editMenuBarMenu && viewMenuBarMenu && helpMenuBarMenu); |
241 | |
242 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: fileMenuBarMenu->parentItem()); |
243 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: editMenuBarMenu->parentItem()); |
244 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: viewMenuBarMenu->parentItem()); |
245 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: helpMenuBarMenu->parentItem()); |
246 | QVERIFY(fileMenuBarItem && editMenuBarItem && viewMenuBarItem && helpMenuBarItem); |
247 | |
248 | // trigger a menubar item to open a menu |
249 | editMenuBarItem->forceActiveFocus(); |
250 | QTest::keyClick(window: window.data(), key: Qt::Key_Space); |
251 | QVERIFY(editMenuBarItem->isHighlighted()); |
252 | QVERIFY(editMenuBarMenu->isVisible()); |
253 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
254 | QVERIFY(editMenuBarMenu->hasActiveFocus()); |
255 | |
256 | // navigate down to the menu |
257 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: editMenuBarMenu->itemAt(index: 0)); |
258 | QVERIFY(cutMenuItem); |
259 | QVERIFY(!cutMenuItem->isHighlighted()); |
260 | QVERIFY(!cutMenuItem->hasActiveFocus()); |
261 | QTest::keyClick(window: window.data(), key: Qt::Key_Down); |
262 | QVERIFY(cutMenuItem->isHighlighted()); |
263 | QVERIFY(cutMenuItem->hasActiveFocus()); |
264 | |
265 | // navigate up, back to the menubar |
266 | QTest::keyClick(window: window.data(), key: Qt::Key_Up); |
267 | QVERIFY(editMenuBarItem->isHighlighted()); |
268 | QVERIFY(editMenuBarItem->hasActiveFocus()); |
269 | QTRY_VERIFY(!editMenuBarMenu->isVisible()); |
270 | QVERIFY(!cutMenuItem->isHighlighted()); |
271 | QVERIFY(!cutMenuItem->hasActiveFocus()); |
272 | |
273 | // navigate down to re-open the menu |
274 | QTest::keyClick(window: window.data(), key: Qt::Key_Down); |
275 | QVERIFY(editMenuBarItem->isHighlighted()); |
276 | QVERIFY(!editMenuBarItem->hasActiveFocus()); |
277 | QVERIFY(editMenuBarMenu->isVisible()); |
278 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
279 | QVERIFY(editMenuBarMenu->hasActiveFocus()); |
280 | QVERIFY(cutMenuItem->isHighlighted()); |
281 | QVERIFY(cutMenuItem->hasActiveFocus()); |
282 | |
283 | // navigate left in popup mode (menu open) |
284 | QTest::keyClick(window: window.data(), key: Qt::Key_Left); |
285 | QVERIFY(fileMenuBarItem->isHighlighted()); |
286 | QVERIFY(!editMenuBarItem->isHighlighted()); |
287 | QVERIFY(fileMenuBarMenu->isVisible()); |
288 | QTRY_VERIFY(fileMenuBarMenu->isOpened()); |
289 | QTRY_VERIFY(!editMenuBarMenu->isVisible()); |
290 | |
291 | // navigate left in popup mode (wrap) |
292 | QTest::keyClick(window: window.data(), key: Qt::Key_Left); |
293 | QVERIFY(helpMenuBarItem->isHighlighted()); |
294 | QVERIFY(!fileMenuBarItem->isHighlighted()); |
295 | QVERIFY(helpMenuBarMenu->isVisible()); |
296 | QTRY_VERIFY(helpMenuBarMenu->isOpened()); |
297 | QTRY_VERIFY(!fileMenuBarMenu->isVisible()); |
298 | |
299 | // navigate up to close the menu |
300 | QTest::keyClick(window: window.data(), key: Qt::Key_Up); |
301 | QVERIFY(helpMenuBarItem->isHighlighted()); |
302 | QTRY_VERIFY(!helpMenuBarMenu->isVisible()); |
303 | |
304 | // navigate right in non-popup mode (wrap) |
305 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
306 | QVERIFY(fileMenuBarItem->isHighlighted()); |
307 | QVERIFY(!helpMenuBarItem->isHighlighted()); |
308 | QVERIFY(!fileMenuBarMenu->isVisible()); |
309 | QVERIFY(!helpMenuBarMenu->isVisible()); |
310 | |
311 | // navigate right in non-popup mode (menu closed) |
312 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
313 | QVERIFY(!fileMenuBarItem->isHighlighted()); |
314 | QVERIFY(editMenuBarItem->isHighlighted()); |
315 | QVERIFY(!fileMenuBarMenu->isVisible()); |
316 | QVERIFY(!editMenuBarMenu->isVisible()); |
317 | |
318 | // open a menu |
319 | viewMenuBarItem->forceActiveFocus(); |
320 | QTest::keyClick(window: window.data(), key: Qt::Key_Space); |
321 | QVERIFY(viewMenuBarItem->isHighlighted()); |
322 | QVERIFY(viewMenuBarMenu->isVisible()); |
323 | QTRY_VERIFY(viewMenuBarMenu->isOpened()); |
324 | QVERIFY(!viewMenuBarItem->hasActiveFocus()); |
325 | QVERIFY(viewMenuBarMenu->hasActiveFocus()); |
326 | |
327 | // open a sub-menu |
328 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: viewMenuBarMenu->itemAt(index: 0)); |
329 | QVERIFY(alignmentSubMenuItem); |
330 | QQuickMenu * = alignmentSubMenuItem->subMenu(); |
331 | QVERIFY(alignmentSubMenu); |
332 | QTest::keyClick(window: window.data(), key: Qt::Key_Down); |
333 | QVERIFY(alignmentSubMenuItem->isHighlighted()); |
334 | QVERIFY(!alignmentSubMenu->isVisible()); |
335 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
336 | QVERIFY(alignmentSubMenu->isVisible()); |
337 | QTRY_VERIFY(alignmentSubMenu->isOpened()); |
338 | |
339 | // open a sub-sub-menu |
340 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: alignmentSubMenu->itemAt(index: 0)); |
341 | QVERIFY(horizontalSubMenuItem); |
342 | QVERIFY(horizontalSubMenuItem->isHighlighted()); |
343 | QQuickMenu * = horizontalSubMenuItem->subMenu(); |
344 | QVERIFY(horizontalSubMenu); |
345 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
346 | QVERIFY(viewMenuBarMenu->isVisible()); |
347 | QVERIFY(alignmentSubMenu->isVisible()); |
348 | QVERIFY(horizontalSubMenu->isVisible()); |
349 | QTRY_VERIFY(horizontalSubMenu->isOpened()); |
350 | |
351 | // navigate left to close a sub-menu |
352 | QTest::keyClick(window: window.data(), key: Qt::Key_Left); |
353 | QTRY_VERIFY(!horizontalSubMenu->isVisible()); |
354 | QVERIFY(viewMenuBarMenu->isVisible()); |
355 | QVERIFY(alignmentSubMenu->isVisible()); |
356 | |
357 | // navigate right to re-open the sub-menu |
358 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
359 | QVERIFY(horizontalSubMenuItem->isHighlighted()); |
360 | QVERIFY(horizontalSubMenu->isVisible()); |
361 | QTRY_VERIFY(horizontalSubMenu->isOpened()); |
362 | |
363 | // navigate right to the next menubar menu |
364 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
365 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
366 | QVERIFY(helpMenuBarItem->isHighlighted()); |
367 | QVERIFY(helpMenuBarMenu->isVisible()); |
368 | QTRY_VERIFY(!viewMenuBarMenu->isVisible()); |
369 | QTRY_VERIFY(!alignmentSubMenu->isVisible()); |
370 | QTRY_VERIFY(!horizontalSubMenu->isVisible()); |
371 | QTRY_VERIFY(helpMenuBarMenu->isOpened()); |
372 | |
373 | // navigate back |
374 | QTest::keyClick(window: window.data(), key: Qt::Key_Left); |
375 | QVERIFY(!helpMenuBarItem->isHighlighted()); |
376 | QVERIFY(viewMenuBarItem->isHighlighted()); |
377 | QVERIFY(viewMenuBarMenu->isVisible()); |
378 | QTRY_VERIFY(!helpMenuBarMenu->isVisible()); |
379 | QTRY_VERIFY(viewMenuBarMenu->isOpened()); |
380 | |
381 | // re-open the chain of menus |
382 | QTest::keyClick(window: window.data(), key: Qt::Key_Down); |
383 | QVERIFY(alignmentSubMenuItem->isHighlighted()); |
384 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
385 | QTRY_VERIFY(alignmentSubMenu->isOpened()); |
386 | QTest::keyClick(window: window.data(), key: Qt::Key_Right); |
387 | QTRY_VERIFY(horizontalSubMenu->isOpened()); |
388 | |
389 | // repeat escape to close the whole chain of menus one by one |
390 | QTest::keyClick(window: window.data(), key: Qt::Key_Escape); |
391 | QTRY_VERIFY(!horizontalSubMenu->isVisible()); |
392 | QVERIFY(viewMenuBarItem->isHighlighted()); |
393 | QVERIFY(viewMenuBarMenu->isVisible()); |
394 | QVERIFY(alignmentSubMenu->isVisible()); |
395 | |
396 | QTest::keyClick(window: window.data(), key: Qt::Key_Escape); |
397 | QTRY_VERIFY(!alignmentSubMenu->isVisible()); |
398 | QVERIFY(viewMenuBarItem->isHighlighted()); |
399 | QVERIFY(viewMenuBarMenu->isVisible()); |
400 | |
401 | QTest::keyClick(window: window.data(), key: Qt::Key_Escape); |
402 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
403 | QTRY_VERIFY(!viewMenuBarMenu->isVisible()); |
404 | } |
405 | |
406 | void tst_qquickmenubar::() |
407 | { |
408 | #ifdef Q_OS_MACOS |
409 | QSKIP("Mnemonics are not used on macOS" ); |
410 | #endif |
411 | |
412 | QQmlApplicationEngine engine(testFileUrl(fileName: "menubar.qml" )); |
413 | |
414 | QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: engine.rootObjects().value(i: 0))); |
415 | QVERIFY(window); |
416 | |
417 | centerOnScreen(window: window.data()); |
418 | moveMouseAway(window: window.data()); |
419 | QVERIFY(QTest::qWaitForWindowActive(window.data())); |
420 | |
421 | QQuickMenuBar * = window->property(name: "header" ).value<QQuickMenuBar *>(); |
422 | QVERIFY(menuBar); |
423 | |
424 | QQuickMenu * = menuBar->menuAt(index: 0); |
425 | QQuickMenu * = menuBar->menuAt(index: 1); |
426 | QQuickMenu * = menuBar->menuAt(index: 2); |
427 | QQuickMenu * = menuBar->menuAt(index: 3); |
428 | QVERIFY(fileMenuBarMenu && editMenuBarMenu && viewMenuBarMenu && helpMenuBarMenu); |
429 | |
430 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: fileMenuBarMenu->parentItem()); |
431 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: editMenuBarMenu->parentItem()); |
432 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: viewMenuBarMenu->parentItem()); |
433 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: helpMenuBarMenu->parentItem()); |
434 | QVERIFY(fileMenuBarItem && editMenuBarItem && viewMenuBarItem && helpMenuBarItem); |
435 | |
436 | // trigger a menubar item to open a menu |
437 | QTest::keyClick(window: window.data(), key: Qt::Key_E, modifier: Qt::AltModifier); // "&Edit" |
438 | QVERIFY(editMenuBarItem->isHighlighted()); |
439 | QVERIFY(!editMenuBarItem->hasActiveFocus()); |
440 | QVERIFY(editMenuBarMenu->isVisible()); |
441 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
442 | QVERIFY(editMenuBarMenu->hasActiveFocus()); |
443 | |
444 | // re-trigger a menubar item to hide the menu |
445 | QTest::keyClick(window: window.data(), key: Qt::Key_E, modifier: Qt::AltModifier); // "&Edit" |
446 | QVERIFY(editMenuBarItem->isHighlighted()); |
447 | QVERIFY(editMenuBarItem->hasActiveFocus()); |
448 | QVERIFY(!editMenuBarMenu->hasActiveFocus()); |
449 | QTRY_VERIFY(!editMenuBarMenu->isVisible()); |
450 | |
451 | // re-trigger a menubar item to show the menu again |
452 | QTest::keyClick(window: window.data(), key: Qt::Key_E, modifier: Qt::AltModifier); // "&Edit" |
453 | QVERIFY(editMenuBarItem->isHighlighted()); |
454 | QVERIFY(editMenuBarMenu->isVisible()); |
455 | QTRY_VERIFY(editMenuBarMenu->isOpened()); |
456 | QVERIFY(editMenuBarMenu->hasActiveFocus()); |
457 | QVERIFY(!editMenuBarItem->hasActiveFocus()); |
458 | |
459 | // trigger another menubar item to open another menu |
460 | QTest::keyClick(window: window.data(), key: Qt::Key_H, modifier: Qt::AltModifier); // "&Help" |
461 | QVERIFY(!editMenuBarItem->isHighlighted()); |
462 | QVERIFY(helpMenuBarItem->isHighlighted()); |
463 | QVERIFY(!viewMenuBarMenu->isVisible()); |
464 | QVERIFY(helpMenuBarMenu->isVisible()); |
465 | QTRY_VERIFY(helpMenuBarMenu->isOpened()); |
466 | |
467 | // trigger a menu item to close the menu |
468 | QTest::keyClick(window: window.data(), key: Qt::Key_A, modifier: Qt::AltModifier); // "&About" |
469 | QVERIFY(!helpMenuBarItem->isHighlighted()); |
470 | QTRY_VERIFY(!helpMenuBarMenu->isVisible()); |
471 | |
472 | // trigger a menubar item to open a menu |
473 | QTest::keyClick(window: window.data(), key: Qt::Key_V, modifier: Qt::AltModifier); // "&View" |
474 | QVERIFY(!editMenuBarItem->isHighlighted()); |
475 | QVERIFY(viewMenuBarItem->isHighlighted()); |
476 | QVERIFY(viewMenuBarMenu->isVisible()); |
477 | QTRY_VERIFY(viewMenuBarMenu->isOpened()); |
478 | |
479 | // trigger a menu item to open a sub-menu |
480 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: viewMenuBarMenu->itemAt(index: 0)); |
481 | QVERIFY(alignmentSubMenuItem); |
482 | QQuickMenu * = alignmentSubMenuItem->subMenu(); |
483 | QVERIFY(alignmentSubMenu); |
484 | QTest::keyClick(window: window.data(), key: Qt::Key_A, modifier: Qt::AltModifier); // "&Alignment" |
485 | QVERIFY(viewMenuBarMenu->isVisible()); |
486 | QVERIFY(alignmentSubMenu->isVisible()); |
487 | QTRY_VERIFY(alignmentSubMenu->isOpened()); |
488 | |
489 | // trigger a menu item to open a sub-sub-menu |
490 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: alignmentSubMenu->itemAt(index: 1)); |
491 | QVERIFY(verticalSubMenuItem); |
492 | QQuickMenu * = verticalSubMenuItem->subMenu(); |
493 | QVERIFY(verticalSubMenu); |
494 | QTest::keyClick(window: window.data(), key: Qt::Key_V, modifier: Qt::AltModifier); // "&Vertical" |
495 | QVERIFY(viewMenuBarMenu->isVisible()); |
496 | QVERIFY(alignmentSubMenu->isVisible()); |
497 | QVERIFY(verticalSubMenu->isVisible()); |
498 | QTRY_VERIFY(verticalSubMenu->isOpened()); |
499 | |
500 | // trigger a menu item to close the whole chain of menus |
501 | QTest::keyClick(window: window.data(), key: Qt::Key_C, modifier: Qt::AltModifier); // "&Center" |
502 | QVERIFY(!viewMenuBarItem->isHighlighted()); |
503 | QTRY_VERIFY(!viewMenuBarMenu->isVisible()); |
504 | QTRY_VERIFY(!alignmentSubMenu->isVisible()); |
505 | QTRY_VERIFY(!verticalSubMenu->isVisible()); |
506 | } |
507 | |
508 | void tst_qquickmenubar::() |
509 | { |
510 | QQmlApplicationEngine engine(testFileUrl(fileName: "empty.qml" )); |
511 | |
512 | QScopedPointer<QQuickMenuBar> (qobject_cast<QQuickMenuBar *>(object: engine.rootObjects().value(i: 0))); |
513 | QVERIFY(menuBar); |
514 | |
515 | QQmlComponent component(&engine); |
516 | component.setData("import QtQuick.Controls 2.0; Menu { }" , baseUrl: QUrl()); |
517 | |
518 | QPointer<QQuickMenu> (qobject_cast<QQuickMenu *>(object: component.create())); |
519 | QVERIFY(!menu1.isNull()); |
520 | menuBar->addMenu(menu: menu1.data()); |
521 | QCOMPARE(menuBar->count(), 1); |
522 | QCOMPARE(menuBar->menuAt(0), menu1.data()); |
523 | |
524 | QPointer<QQuickMenuBarItem> (qobject_cast<QQuickMenuBarItem *>(object: menuBar->itemAt(index: 0))); |
525 | QVERIFY(menuBarItem1); |
526 | QCOMPARE(menuBarItem1->menu(), menu1.data()); |
527 | QCOMPARE(menuBar->itemAt(0), menuBarItem1.data()); |
528 | |
529 | QScopedPointer<QQuickMenu> (qobject_cast<QQuickMenu *>(object: component.create())); |
530 | QVERIFY(!menu2.isNull()); |
531 | menuBar->insertMenu(index: 0, menu: menu2.data()); |
532 | QCOMPARE(menuBar->count(), 2); |
533 | QCOMPARE(menuBar->menuAt(0), menu2.data()); |
534 | QCOMPARE(menuBar->menuAt(1), menu1.data()); |
535 | |
536 | QPointer<QQuickMenuBarItem> (qobject_cast<QQuickMenuBarItem *>(object: menuBar->itemAt(index: 0))); |
537 | QVERIFY(menuBarItem2); |
538 | QCOMPARE(menuBarItem2->menu(), menu2.data()); |
539 | QCOMPARE(menuBar->itemAt(0), menuBarItem2.data()); |
540 | QCOMPARE(menuBar->itemAt(1), menuBarItem1.data()); |
541 | |
542 | // takeMenu(int) does not destroy the menu, but does destroy the respective item in the menubar |
543 | QCOMPARE(menuBar->takeMenu(1), menu1.data()); |
544 | QCOMPARE(menuBar->count(), 1); |
545 | QVERIFY(!menuBar->menuAt(1)); |
546 | QVERIFY(!menuBar->itemAt(1)); |
547 | QCoreApplication::sendPostedEvents(receiver: menu1.data(), event_type: QEvent::DeferredDelete); |
548 | QVERIFY(!menu1.isNull()); |
549 | QCoreApplication::sendPostedEvents(receiver: menuBarItem1, event_type: QEvent::DeferredDelete); |
550 | QVERIFY(menuBarItem1.isNull()); |
551 | |
552 | // addMenu(Menu) re-creates the respective item in the menubar |
553 | menuBar->addMenu(menu: menu1.data()); |
554 | QCOMPARE(menuBar->count(), 2); |
555 | menuBarItem1 = qobject_cast<QQuickMenuBarItem *>(object: menuBar->itemAt(index: 1)); |
556 | QVERIFY(!menuBarItem1.isNull()); |
557 | |
558 | // removeMenu(Menu) destroys both the menu and the respective item in the menubar |
559 | menuBar->removeMenu(menu: menu1.data()); |
560 | QCOMPARE(menuBar->count(), 1); |
561 | QVERIFY(!menuBar->itemAt(1)); |
562 | QCoreApplication::sendPostedEvents(receiver: menu1.data(), event_type: QEvent::DeferredDelete); |
563 | QVERIFY(menu1.isNull()); |
564 | QCoreApplication::sendPostedEvents(receiver: menuBarItem1, event_type: QEvent::DeferredDelete); |
565 | QVERIFY(menuBarItem1.isNull()); |
566 | } |
567 | |
568 | void tst_qquickmenubar::() |
569 | { |
570 | if ((QGuiApplication::platformName() == QLatin1String("offscreen" )) |
571 | || (QGuiApplication::platformName() == QLatin1String("minimal" ))) |
572 | QSKIP("Mouse highlight not functional on offscreen/minimal platforms" ); |
573 | |
574 | QQmlApplicationEngine engine(testFileUrl(fileName: "checkHighlightWhenDismissed.qml" )); |
575 | QScopedPointer<QQuickApplicationWindow> window(qobject_cast<QQuickApplicationWindow *>(object: engine.rootObjects().value(i: 0))); |
576 | QVERIFY(window); |
577 | |
578 | centerOnScreen(window: window.data()); |
579 | moveMouseAway(window: window.data()); |
580 | QVERIFY(QTest::qWaitForWindowActive(window.data())); |
581 | |
582 | QQuickMenuBar * = window->findChild<QQuickMenuBar *>(aName: "menuBar" ); |
583 | QVERIFY(menuBar); |
584 | |
585 | QQuickMenu * = menuBar->menuAt(index: 0); |
586 | QQuickMenu * = menuBar->menuAt(index: 1); |
587 | QVERIFY(staticMenu && dynamicMenu); |
588 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: staticMenu->parentItem()); |
589 | QQuickMenuBarItem * = qobject_cast<QQuickMenuBarItem *>(object: dynamicMenu->parentItem()); |
590 | QVERIFY(staticMenuBarItem && dynamicMenuBarItem); |
591 | |
592 | // highlight the static MenuBarItem and open the menu |
593 | QTest::mouseMove(window: window.data(), pos: staticMenuBarItem->mapToScene( |
594 | point: QPointF(staticMenuBarItem->width() / 2, staticMenuBarItem->height() / 2)).toPoint()); |
595 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
596 | pos: staticMenuBarItem->mapToScene(point: QPointF(staticMenuBarItem->width() / 2, staticMenuBarItem->height() / 2)).toPoint()); |
597 | QCOMPARE(staticMenuBarItem->isHighlighted(), true); |
598 | QCOMPARE(staticMenu->isVisible(), true); |
599 | QTRY_COMPARE(staticMenu->isOpened(), true); |
600 | |
601 | // click a menu item to dismiss the menu and unhighlight the static MenuBarItem |
602 | QQuickMenuItem * = qobject_cast<QQuickMenuItem *>(object: staticMenu->itemAt(index: 0)); |
603 | QVERIFY(menuItem); |
604 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
605 | pos: menuItem->mapToScene(point: QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); |
606 | QCOMPARE(staticMenuBarItem->isHighlighted(), false); |
607 | |
608 | // highlight the dynamic MenuBarItem and open the menu |
609 | QTest::mouseMove(window: window.data(), pos: dynamicMenuBarItem->mapToScene( |
610 | point: QPointF(dynamicMenuBarItem->width() / 2, dynamicMenuBarItem->height() / 2)).toPoint()); |
611 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
612 | pos: dynamicMenuBarItem->mapToScene(point: QPointF(dynamicMenuBarItem->width() / 2, dynamicMenuBarItem->height() / 2)).toPoint()); |
613 | QCOMPARE(dynamicMenuBarItem->isHighlighted(), true); |
614 | QCOMPARE(dynamicMenu->isVisible(), true); |
615 | QTRY_COMPARE(dynamicMenu->isOpened(), true); |
616 | |
617 | // click a menu item to dismiss the menu and unhighlight the dynamic MenuBarItem |
618 | menuItem = qobject_cast<QQuickMenuItem *>(object: dynamicMenu->itemAt(index: 0)); |
619 | QVERIFY(menuItem); |
620 | QTest::mouseClick(window: window.data(), button: Qt::LeftButton, stateKey: Qt::NoModifier, |
621 | pos: menuItem->mapToScene(point: QPointF(menuItem->width() / 2, menuItem->height() / 2)).toPoint()); |
622 | QCOMPARE(dynamicMenuBarItem->isHighlighted(), false); |
623 | } |
624 | |
625 | QTEST_QUICKCONTROLS_MAIN(tst_qquickmenubar) |
626 | |
627 | #include "tst_qquickmenubar.moc" |
628 | |