QtBase  v6.3.1
tst_qmenu.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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 https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include <QTest>
30 #include <QtTest/private/qtesthelpers_p.h>
31 #include <qapplication.h>
32 #include <private/qguiapplication_p.h>
33 #include <QPushButton>
34 #include <QMainWindow>
35 #include <QMenuBar>
36 #include <QToolBar>
37 #include <QToolButton>
38 #include <QStatusBar>
39 #include <QListWidget>
40 #include <QWidgetAction>
41 #include <QScreen>
42 #include <QSpinBox>
43 #include <QSignalSpy>
44 #include <qdialog.h>
45 
46 #include <qmenu.h>
47 #include <qstyle.h>
48 #include <QStyleHints>
49 #include <QTimer>
50 #include <qdebug.h>
51 #include <QToolTip>
52 #include <qpa/qplatformtheme.h>
53 #include <qpa/qplatformintegration.h>
54 
55 using namespace QTestPrivate;
56 
58 Q_DECLARE_METATYPE(Qt::KeyboardModifiers);
59 
60 struct MenuMetrics {
61  int fw;
62  int hmargin;
63  int vmargin;
65 
68  hmargin = menu->style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, menu);
69  vmargin = menu->style()->pixelMetric(QStyle::PM_MenuVMargin, nullptr, menu);
70  tearOffHeight = menu->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, nullptr, menu);
71  }
72 };
73 
74 class tst_QMenu : public QObject
75 {
76  Q_OBJECT
77 
78 public:
79  tst_QMenu();
80 
81 public slots:
82  void initTestCase();
83  void cleanupTestCase();
84  void init();
85 private slots:
86  void getSetCheck();
87  void addActionsAndClear();
88  void addActionsConnect();
89 
90  void keyboardNavigation_data();
91  void keyboardNavigation();
92  void focus();
93  void overrideMenuAction();
94  void statusTip();
95  void widgetActionFocus();
96  void mouseActivation();
97  void tearOff();
98  void submenuTearOffDontClose();
99  void layoutDirection();
100 
101  void task208001_stylesheet();
102  void activeSubMenuPosition();
103  void activeSubMenuPositionExec();
104  void task242454_sizeHint();
105  void task176201_clear();
106  void task250673_activeMultiColumnSubMenuPosition();
107  void task256918_setFont();
108  void menuSizeHint();
109  void task258920_mouseBorder();
110  void setFixedWidth();
111  void deleteActionInTriggered();
112  void pushButtonPopulateOnAboutToShow();
113  void QTBUG7907_submenus_autoselect();
114  void QTBUG7411_submenus_activate();
115  void QTBUG30595_rtl_submenu();
116  void QTBUG20403_nested_popup_on_shortcut_trigger();
117  void QTBUG47515_widgetActionEnterLeave();
118  void QTBUG_89082_actionTipsHide();
119  void QTBUG8122_widgetActionCrashOnClose();
120  void widgetActionTriggerClosesMenu();
121  void transientParent();
122 
123  void QTBUG_10735_crashWithDialog();
124 #ifdef Q_OS_MAC
125  void QTBUG_37933_ampersands_data();
126  void QTBUG_37933_ampersands();
127 #else
128  void click_while_dismissing_submenu();
129 #endif
130  void QTBUG_56917_wideMenuSize();
131  void QTBUG_56917_wideMenuScreenNumber();
132  void QTBUG_56917_wideSubmenuScreenNumber();
133  void menuSize_Scrolling_data();
134  void menuSize_Scrolling();
135  void tearOffMenuNotDisplayed();
136  void QTBUG_61039_menu_shortcuts();
137  void screenOrientationChangedCloseMenu();
138 
139 protected slots:
140  void onActivated(QAction*);
141  void onHighlighted(QAction*);
142  void onStatusMessageChanged(const QString &);
143  void onStatusTipTimer();
144  void deleteAction(QAction *a) { delete a; }
145 private:
146  void createActions();
147  QMenu *menus[2], *lastMenu;
148  enum { num_builtins = 10 };
149  QAction *activated, *highlighted, *builtins[num_builtins];
150  QString statustip;
151  bool m_onStatusTipTimerExecuted;
152 };
153 
154 // Testing get/set functions
155 void tst_QMenu::getSetCheck()
156 {
157  QMenu obj1;
158  // QAction * QMenu::defaultAction()
159  // void QMenu::setDefaultAction(QAction *)
160  QAction *var1 = new QAction(0);
161  obj1.setDefaultAction(var1);
162  QCOMPARE(var1, obj1.defaultAction());
163  obj1.setDefaultAction((QAction *)0);
164  QCOMPARE((QAction *)0, obj1.defaultAction());
165  delete var1;
166 
167  // QAction * QMenu::activeAction()
168  // void QMenu::setActiveAction(QAction *)
169  QAction *var2 = new QAction(0);
170  obj1.setActiveAction(var2);
171  QCOMPARE(var2, obj1.activeAction());
172  obj1.setActiveAction((QAction *)0);
173  QCOMPARE((QAction *)0, obj1.activeAction());
174  delete var2;
175 }
176 
178  : m_onStatusTipTimerExecuted(false)
179 {
183 }
184 
186 {
187  for (int i = 0; i < num_builtins; i++)
188  builtins[i] = 0;
189  for (int i = 0; i < 2; i++) {
190  menus[i] = new QMenu;
192  QObject::connect(menus[i], SIGNAL(hovered(QAction*)), this, SLOT(onHighlighted(QAction*)));
193  }
194 }
195 
197 {
198  for (int i = 0; i < 2; i++)
199  menus[i]->clear();
200  for (int i = 0; i < num_builtins; i++) {
201  bool menuAction = false;
202  for (int j = 0; j < 2; ++j)
203  if (menus[j]->menuAction() == builtins[i])
204  menuAction = true;
205  if (!menuAction)
206  delete builtins[i];
207  }
208  delete menus[0];
209  delete menus[1];
210 }
211 
213 {
214  activated = highlighted = 0;
215  lastMenu = 0;
216  m_onStatusTipTimerExecuted = false;
217 }
218 
219 void tst_QMenu::createActions()
220 {
221  if (!builtins[0])
222  builtins[0] = new QAction("New", 0);
223  menus[0]->addAction(builtins[0]);
224 
225  if (!builtins[1]) {
226  builtins[1] = new QAction(0);
227  builtins[1]->setSeparator(true);
228  }
229  menus[0]->addAction(builtins[1]);
230 
231  if (!builtins[2]) {
232  builtins[2] = menus[1]->menuAction();
233  builtins[2]->setText("&Open..");
234  builtins[8] = new QAction("Close", 0);
235  menus[1]->addAction(builtins[8]);
236  builtins[9] = new QAction("Quit", 0);
237  menus[1]->addAction(builtins[9]);
238  }
239  menus[0]->addAction(builtins[2]);
240 
241  if (!builtins[3])
242  builtins[3] = new QAction("Open &as..", 0);
243  menus[0]->addAction(builtins[3]);
244 
245  if (!builtins[4]) {
246  builtins[4] = new QAction("Save", 0);
247  builtins[4]->setEnabled(false);
248  }
249  menus[0]->addAction(builtins[4]);
250 
251  if (!builtins[5])
252  builtins[5] = new QAction("Sa&ve as..", 0);
253  menus[0]->addAction(builtins[5]);
254 
255  if (!builtins[6]) {
256  builtins[6] = new QAction(0);
257  builtins[6]->setSeparator(true);
258  }
259  menus[0]->addAction(builtins[6]);
260 
261  if (!builtins[7])
262  builtins[7] = new QAction("Prin&t", 0);
263  menus[0]->addAction(builtins[7]);
264 }
265 
267 {
268  highlighted = action;
269  lastMenu = qobject_cast<QMenu*>(sender());
270 }
271 
273 {
274  activated = action;
275  lastMenu = qobject_cast<QMenu*>(sender());
276 }
277 
279 {
280  statustip=s;
281 }
282 
283 void tst_QMenu::addActionsAndClear()
284 {
285  QCOMPARE(menus[0]->actions().count(), 0);
286  createActions();
287  QCOMPARE(menus[0]->actions().count(), 8);
288  menus[0]->clear();
289  QCOMPARE(menus[0]->actions().count(), 0);
290 }
291 
292 static void testFunction0() {}
293 static void testFunction1(bool) {}
294 
295 template <typename T>
297  T t;
298  operator const T() const { return t; }
299  operator T() { return t; }
300 };
301 
302 void tst_QMenu::addActionsConnect()
303 {
304  // almost exhaustive check of addAction() overloads:
305  // (text), (icon, text), (icon, text, shortcut), (text, shortcut)
306  // each with a good sample of ways to QObject::connect() to
307  // QAction::triggered(bool)
308  QMenu menu;
309 
310  // don't just pass QString etc - that'd be too easy (think QStringBuilder)
313 
314  const auto check = [&](auto &...args) { // don't need to perfectly-forward, only lvalues passed
315  menu.addAction(args...);
316 
317  menu.addAction(args..., &menu, SLOT(deleteLater()));
323  menu.addAction(args..., [&](bool b) { menu.setEnabled(b); });
324  menu.addAction(args..., &menu, [&](bool b) { menu.setEnabled(b); });
325 
326  menu.addAction(args..., &menu, SLOT(deleteLater()), Qt::QueuedConnection);
328  // doesn't exist: menu.addAction(args..., testFunction0, Qt::QueuedConnection);
330  // doesn't exist: menu.addAction(args..., testFunction1, Qt::QueuedConnection);
332  // doesn't exist: menu.addAction(args..., [&](bool b) { menu.setEnabled(b); }, Qt::QueuedConnection);
333  menu.addAction(args..., &menu, [&](bool b) { menu.setEnabled(b); }, Qt::QueuedConnection);
334  };
335  const auto check1 = [&](auto &arg, auto &...args) {
336  check(arg, args...);
337  check(std::as_const(arg), args...);
338  };
339  const auto check2 = [&](auto &arg1, auto &arg2, auto &...args) {
340  check1(arg1, arg2, args...);
341  check1(arg1, std::as_const(arg2), args...);
342  };
343  [[maybe_unused]]
344  const auto check3 = [&](auto &arg1, auto &arg2, auto &arg3) {
345  check2(arg1, arg2, arg3);
346  check2(arg1, arg2, std::as_const(arg3));
347  };
348 
349  check1(text);
350  check2(icon, text);
351 #ifndef QT_NO_SHORTCUT
353  check2(text, keySequence);
354  check3(icon, text, keySequence);
355 #if QT_DEPRECATED_SINCE(6, 4)
358  menu.addAction(text, &menu, SLOT(deleteLater()), keySequence);
359  menu.addAction(text, &menu, &QMenu::deleteLater, keySequence);
360  menu.addAction(text, testFunction0, keySequence);
361  menu.addAction(text, &menu, testFunction0, keySequence);
362  menu.addAction(text, testFunction1, keySequence);
363  menu.addAction(text, &menu, testFunction1, keySequence);
364  menu.addAction(icon, text, &menu, SLOT(deleteLater()), keySequence);
365  menu.addAction(icon, text, &menu, &QMenu::deleteLater, keySequence);
366  menu.addAction(icon, text, testFunction0, keySequence);
367  menu.addAction(icon, text, &menu, testFunction0, keySequence);
368  menu.addAction(icon, text, testFunction1, keySequence);
369  menu.addAction(icon, text, &menu, testFunction1, keySequence);
371 #endif
372 #endif // !QT_NO_SHORTCUT
373 }
374 
375 void tst_QMenu::mouseActivation()
376 {
377  QWidget topLevel;
378  topLevel.resize(300, 200);
379  centerOnScreen(&topLevel);
380  QMenu menu(&topLevel);
381  topLevel.show();
382  menu.addAction("Menu Action");
383  menu.move(topLevel.geometry().topRight() + QPoint(50, 0));
384  menu.show();
386  QVERIFY(!menu.isVisible());
387 
388  //context menus can always be accessed with right click except on windows
389  menu.show();
391  QVERIFY(!menu.isVisible());
392 
393 #ifdef Q_OS_WIN
394  //on windows normal mainwindow menus Can only be accessed with left mouse button
395  QMenuBar menubar;
396  QMenu submenu("Menu");
397  submenu.addAction("action");
398  QAction *action = menubar.addMenu(&submenu);
399  menubar.move(topLevel.geometry().topRight() + QPoint(300, 0));
400  menubar.show();
401 
402 
403  QTest::mouseClick(&menubar, Qt::LeftButton, {}, menubar.actionGeometry(action).center(), 300);
404  QVERIFY(submenu.isVisible());
405  QTest::mouseClick(&submenu, Qt::LeftButton, {}, QPoint(5, 5), 300);
406  QVERIFY(!submenu.isVisible());
407 
408  QTest::mouseClick(&menubar, Qt::LeftButton, {}, menubar.actionGeometry(action).center(), 300);
409  QVERIFY(submenu.isVisible());
410  QTest::mouseClick(&submenu, Qt::RightButton, {}, QPoint(5, 5), 300);
411  QVERIFY(submenu.isVisible());
412 #endif
413 }
414 
415 void tst_QMenu::keyboardNavigation_data()
416 {
417  QTest::addColumn<Qt::Key>("key");
418  QTest::addColumn<Qt::KeyboardModifiers>("modifiers");
419  QTest::addColumn<int>("expected_action");
420  QTest::addColumn<int>("expected_menu");
421  QTest::addColumn<bool>("init");
422  QTest::addColumn<bool>("expected_activated");
423  QTest::addColumn<bool>("expected_highlighted");
424 
425  //test up and down (order is important here)
426  QTest::newRow("data0") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 0 << 0 << true << false << true;
427  QTest::newRow("data1") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 2 << 0 << false << false << true; //skips the separator
428  QTest::newRow("data2") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 3 << 0 << false << false << true;
429 
431  QTest::newRow("data3_noMac") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 4 << 0 << false << false << true;
432  else
433  QTest::newRow("data3_Mac") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 5 << 0 << false << false << true;
434  QTest::newRow("data4") << Qt::Key(Qt::Key_Up) << Qt::KeyboardModifiers(Qt::NoModifier) << 3 << 0 << false << false << true;
435  QTest::newRow("data5") << Qt::Key(Qt::Key_Up) << Qt::KeyboardModifiers(Qt::NoModifier) << 2 << 0 << false << false << true;
436  QTest::newRow("data6") << Qt::Key(Qt::Key_Right) << Qt::KeyboardModifiers(Qt::NoModifier) << 8 << 1 << false << false << true;
437  QTest::newRow("data7") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 9 << 1 << false << false << true;
438  QTest::newRow("data8") << Qt::Key(Qt::Key_Escape) << Qt::KeyboardModifiers(Qt::NoModifier) << 2 << 0 << false << false << false;
439  QTest::newRow("data9") << Qt::Key(Qt::Key_Down) << Qt::KeyboardModifiers(Qt::NoModifier) << 3 << 0 << false << false<< true;
440  QTest::newRow("data10") << Qt::Key(Qt::Key_Return) << Qt::KeyboardModifiers(Qt::NoModifier) << 3 << 0 << false << true << false;
441 
443  // Test shortcuts.
444  QTest::newRow("shortcut0") << Qt::Key(Qt::Key_V) << Qt::KeyboardModifiers(Qt::AltModifier) << 5 << 0 << true << true << false;
445  }
446 }
447 
448 void tst_QMenu::keyboardNavigation()
449 {
450  QFETCH(Qt::Key, key);
451  QFETCH(Qt::KeyboardModifiers, modifiers);
452  QFETCH(int, expected_action);
453  QFETCH(int, expected_menu);
454  QFETCH(bool, init);
455  QFETCH(bool, expected_activated);
456  QFETCH(bool, expected_highlighted);
457 
458  if (init) {
459  lastMenu = menus[0];
460  lastMenu->clear();
461  createActions();
462  lastMenu->popup(QPoint(0, 0));
463  }
464 
465  QTest::keyClick(lastMenu, key, modifiers);
466  if (expected_activated) {
467 #ifdef Q_OS_MAC
468  QEXPECT_FAIL("shortcut0", "Shortcut navication fails, see QTBUG-23684", Continue);
469 #endif
470  QCOMPARE(activated, builtins[expected_action]);
471 #ifndef Q_OS_MAC
472  QEXPECT_FAIL("shortcut0", "QTBUG-22449: QMenu doesn't remove highlight if a menu item is activated by a shortcut", Abort);
473 #endif
474  QCOMPARE(menus[expected_menu]->activeAction(), nullptr);
475  } else {
476  QCOMPARE(menus[expected_menu]->activeAction(), builtins[expected_action]);
477  }
478 
479  if (expected_highlighted)
480  QCOMPARE(menus[expected_menu]->activeAction(), highlighted);
481  else
482  QCOMPARE(highlighted, nullptr);
483 }
484 
485 #ifdef Q_OS_MAC
487 extern bool qt_tab_all_widgets(); // from qapplication.cpp
489 #endif
490 
491 void tst_QMenu::focus()
492 {
493  QMenu menu;
494  menu.addAction("One");
495  menu.addAction("Two");
496  menu.addAction("Three");
497 
498 #ifdef Q_OS_MAC
499  if (!qt_tab_all_widgets())
500  QSKIP("Computer is currently set up to NOT tab to all widgets,"
501  " this test assumes you can tab to all widgets");
502 #endif
503 
504  QWidget window;
505  window.resize(300, 200);
506  QPushButton button("Push me", &window);
507  centerOnScreen(&window);
508  window.show();
509  qApp->setActiveWindow(&window);
510 
511  QVERIFY(button.hasFocus());
512  QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
514  menu.move(window.geometry().topRight() + QPoint(50, 0));
515  menu.show();
516  QVERIFY(button.hasFocus());
517  QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
519  menu.hide();
520  QVERIFY(button.hasFocus());
521  QCOMPARE(QApplication::focusWidget(), (QWidget *)&button);
523 }
524 
525 void tst_QMenu::overrideMenuAction()
526 {
528  QSKIP("Window activation is not supported");
529 
530  //test the override menu action by first creating an action to which we set its menu
531  QMainWindow w;
532  w.resize(300, 200);
533  w.menuBar()->setNativeMenuBar(false);
534  centerOnScreen(&w);
535 
536  QAction *aFileMenu = new QAction("&File", &w);
537  w.menuBar()->addAction(aFileMenu);
538 
539  QMenu *m = new QMenu(&w);
540  QAction *menuaction = m->menuAction();
542  aFileMenu->setMenu(m); //this sets the override menu action for the QMenu
543  QCOMPARE(m->menuAction(), aFileMenu);
544 
545  // On Mac and Windows CE, we need to create native key events to test menu
546  // action activation, so skip this part of the test.
547 #if QT_CONFIG(shortcut) && !defined(Q_OS_DARWIN)
548  QAction *aQuit = new QAction("Quit", &w);
549  aQuit->setShortcut(QKeySequence("Ctrl+X"));
550  m->addAction(aQuit);
551 
552  w.show();
554  w.setFocus();
556  QVERIFY(w.hasFocus());
557 
558  //test of the action inside the menu
559  QTest::keyClick(&w, Qt::Key_X, Qt::ControlModifier);
560  QTRY_COMPARE(activated, aQuit);
561 
562  //test if the menu still pops out
563  QTest::keyClick(&w, Qt::Key_F, Qt::AltModifier);
564  QTRY_VERIFY(m->isVisible());
565 #endif // QT_CONFIG(shortcut) && !Q_OS_DARWIN
566 
567  delete aFileMenu;
568 
569  //after the deletion of the override menu action,
570  //the menu should have its default menu action back
571  QCOMPARE(m->menuAction(), menuaction);
572 }
573 
574 void tst_QMenu::statusTip()
575 {
576  //check that the statustip of actions inserted into the menu are displayed
577  QMainWindow w;
578  w.resize(300, 200);
579  centerOnScreen(&w);
580  connect(w.statusBar(), SIGNAL(messageChanged(QString)), SLOT(onStatusMessageChanged(QString)));; //creates the status bar
581  QToolBar tb;
582  QAction a("main action", &tb);
583  a.setStatusTip("main action");
584  QMenu m(&tb);
585  QAction subact("sub action", &m);
586  subact.setStatusTip("sub action");
587  m.addAction(&subact);
588  a.setMenu(&m);
589  tb.addAction(&a);
590 
591  w.addToolBar(&tb);
592  w.show();
594 
595  QRect rect1 = tb.actionGeometry(&a);
596  QToolButton *btn = qobject_cast<QToolButton*>(tb.childAt(rect1.center()));
597 
598  QVERIFY(btn != nullptr);
599 
600  //because showMenu calls QMenu::exec, we need to use a singleshot
601  //to continue the test
602  QTimer timer;
603  timer.setSingleShot(true);
605  timer.setInterval(200);
606  timer.start();
607  btn->showMenu();
608  QVERIFY(m_onStatusTipTimerExecuted);
609  QVERIFY(statustip.isEmpty());
610 }
611 
612 //2nd part of the test
614 {
615  QMenu *menu = qobject_cast<QMenu*>(QApplication::activePopupWidget());
616  QVERIFY(menu != 0);
617  QVERIFY(menu->isVisible());
618  QTest::keyClick(menu, Qt::Key_Down);
619 
620  //we store the statustip to press escape in any case
621  //otherwise, if the test fails it blocks (never gets out of QMenu::exec
622  const QString st=statustip;
623 
624  menu->close(); //goes out of the menu
625 
626  QCOMPARE(st, QString("sub action"));
627  QVERIFY(!menu->isVisible());
628  m_onStatusTipTimerExecuted = true;
629 }
630 
631 void tst_QMenu::widgetActionFocus()
632 {
633  //test if the focus is correctly handled with a QWidgetAction
634  QMenu m;
635  QListWidget *l = new QListWidget(&m);
636  for (int i = 1; i<3 ; i++)
637  l->addItem(QStringLiteral("item" ) + QString::number(i));
638  QWidgetAction *wa = new QWidgetAction(&m);
639  wa->setDefaultWidget(l);
640  m.addAction(wa);
641  m.setActiveAction(wa);
642  l->setFocus(); //to ensure it has primarily the focus
643  QAction *menuitem1=m.addAction("menuitem1");
644  QAction *menuitem2=m.addAction("menuitem2");
645 
646  m.popup(QPoint());
647 
648  QVERIFY(m.isVisible());
649  QVERIFY(l->hasFocus());
650  QVERIFY(l->currentItem());
651  QCOMPARE(l->currentItem()->text(), QString("item1"));
652 
653  QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
654  QVERIFY(l->currentItem());
655  QCOMPARE(l->currentItem()->text(), QString("item2"));
656 
657  QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
658  QVERIFY(m.hasFocus());
659  QCOMPARE(m.activeAction(), menuitem1);
660 
661  QTest::keyClick(QApplication::focusWidget(), Qt::Key_Down);
662  QVERIFY(m.hasFocus());
663  QCOMPARE(m.activeAction(), menuitem2);
664 
665  QTest::keyClick(QApplication::focusWidget(), Qt::Key_Up);
666  QVERIFY(m.hasFocus());
667  QCOMPARE(m.activeAction(), menuitem1);
668 
669  QTest::keyClick(QApplication::focusWidget(), Qt::Key_Up);
670  QVERIFY(l->hasFocus());
671  QCOMPARE(m.activeAction(), (QAction *)wa);
672 }
673 
674 static QMenu *getTornOffMenu()
675 {
676  for (QWidget *w : QApplication::allWidgets()) {
677  if (w->isVisible() && w->inherits("QTornOffMenu"))
678  return static_cast<QMenu *>(w);
679  }
680  return nullptr;
681 }
682 
683 void tst_QMenu::tearOff()
684 {
686  QSKIP("Window activation is not supported");
687 
688  QWidget widget;
690  QVERIFY(!menu->isTearOffEnabled()); //default value
691  menu->setTearOffEnabled(true);
692  menu->setTitle(QLatin1String("Same &Menu"));
693  menu->addAction("aaa");
694  menu->addAction("bbb");
696 
697  widget.resize(300, 200);
698  centerOnScreen(&widget);
699  widget.show();
702  menu->popup(widget.geometry().topRight() + QPoint(50, 0));
705 
706  MenuMetrics mm(menu.data());
707  const int tearOffOffset = mm.fw + mm.vmargin + mm.tearOffHeight / 2;
708 
709  QTest::mouseClick(menu.data(), Qt::LeftButton, {}, QPoint(10, tearOffOffset), 10);
711  QPointer<QMenu> torn = getTornOffMenu();
712  QVERIFY(torn);
713  QVERIFY(torn->isVisible());
714 
715  // Check menu title
716  const QString cleanTitle = QPlatformTheme::removeMnemonics(menu->title()).trimmed();
717  QCOMPARE(torn->windowTitle(), cleanTitle);
718 
719  // Change menu title and check again
720  menu->setTitle(QLatin1String("Sample &Menu"));
721  const QString newCleanTitle = QPlatformTheme::removeMnemonics(menu->title()).trimmed();
722  QCOMPARE(torn->windowTitle(), newCleanTitle);
723 
724  // Clear menu title and check again
725  menu->setTitle(QString());
726  QCOMPARE(torn->windowTitle(), QString());
727 
730  QVERIFY(!torn->isVisible());
731 
732 #ifndef QT_NO_CURSOR
733  // Test under-mouse positioning
735  torn = getTornOffMenu();
736  QVERIFY(torn);
737  QVERIFY(torn->isVisible());
739  // Some platforms include the window title bar in its geometry.
740  QTRY_COMPARE(torn->windowHandle()->position(), QCursor::pos());
741 
744  QVERIFY(!torn->isVisible());
745 
746  // Test custom positioning
747  const QPoint &pos = QCursor::pos() / 2 + QPoint(10, 10);
749  torn = getTornOffMenu();
750  QVERIFY(torn);
751  QVERIFY(torn->isVisible());
753  // Some platforms include the window title bar in its geometry.
754  QTRY_COMPARE(torn->windowHandle()->position(), pos);
755 #endif // QT_NO_CURSOR
756 }
757 
758 void tst_QMenu::submenuTearOffDontClose()
759 {
761  QSKIP("Window activation is not supported");
762 
763  QWidget widget;
764  QMenu *menu = new QMenu(&widget);
765  QVERIFY(!menu->isTearOffEnabled()); //default value
766  menu->setTearOffEnabled(true);
768  QMenu *submenu = new QMenu(&widget);
769  submenu->addAction("aaa");
770  submenu->addAction("bbb");
771  QVERIFY(!submenu->isTearOffEnabled()); //default value
772  submenu->setTearOffEnabled(true);
773  QVERIFY(submenu->isTearOffEnabled());
774  menu->addMenu(submenu);
775 
776  widget.resize(300, 200);
777  centerOnScreen(&widget);
778  widget.show();
781  // Show parent menu
782  menu->popup(widget.geometry().topRight() + QPoint(50, 0));
784  // Then its submenu
785  const QRect submenuRect = menu->actionGeometry(menu->actions().at(0));
786  const QPoint submenuPos(submenuRect.topLeft() + QPoint(3, 3));
787  // Move then click to avoid the submenu moves from causing it to close
788  QTest::mouseMove(menu, submenuPos, 100);
789  QTest::mouseClick(menu, Qt::LeftButton, {}, submenuPos, 100);
790  QVERIFY(QTest::qWaitFor([&]() { return submenu->window()->windowHandle(); }));
792  // Make sure we enter the submenu frame directly on the tear-off area
793  QTest::mouseMove(submenu, QPoint(10, 3), 100);
795  qWarning("Sloppy menu timer disabled by the style: %s", qPrintable(QApplication::style()->objectName()));
796  // Submenu must get the enter event
797  QTRY_VERIFY(submenu->underMouse());
798  } else {
799  const int closeTimeout = submenu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppyCloseTimeout);
800  QTest::qWait(closeTimeout + 100);
801  // Menu must not disappear and it must get the enter event
802  QVERIFY(submenu->isVisible());
803  QVERIFY(submenu->underMouse());
804  }
805 }
806 
807 void tst_QMenu::layoutDirection()
808 {
810  win.setLayoutDirection(Qt::RightToLeft);
811  win.resize(300, 200);
812  centerOnScreen(&win);
813 
814  QMenu menu(&win);
815  menu.addAction("foo");
816  menu.move(win.geometry().topRight() + QPoint(50, 0));
817  menu.show();
820  menu.close();
821 
822  menu.setParent(0);
823  menu.move(win.geometry().topRight() + QPoint(50, 0));
824  menu.show();
827  menu.close();
828 
829  //now the menubar
830  QAction *action = win.menuBar()->addMenu(&menu);
831  win.menuBar()->setActiveAction(action);
834 }
835 
836 void tst_QMenu::task208001_stylesheet()
837 {
838  //test if it crash
840  main.setStyleSheet("QMenu [title =\"File\"] { color: red;}");
841  main.menuBar()->addMenu("File");
842 }
843 
844 void tst_QMenu::activeSubMenuPosition()
845 {
846  QPushButton lab("subMenuPosition test");
847 
848  QMenu *sub = new QMenu("Submenu", &lab);
849  sub->addAction("Sub-Item1");
850  QAction *subAction = sub->addAction("Sub-Item2");
851 
852  QMenu *main = new QMenu("Menu-Title", &lab);
853  (void)main->addAction("Item 1");
854  QAction *menuAction = main->addMenu(sub);
855  (void)main->addAction("Item 3");
856  (void)main->addAction("Item 4");
857 
858  main->setActiveAction(menuAction);
859  sub->setActiveAction(subAction);
860  main->popup(QPoint(200,200));
861 
862  QVERIFY(main->isVisible());
863  QCOMPARE(main->activeAction(), menuAction);
864  QVERIFY(sub->isVisible());
865  QVERIFY(sub->pos() != QPoint(0,0));
866  // well, it's enough to check the pos is not (0,0) but it's more safe
867  // to check that submenu is to the right of the main menu too.
868  QVERIFY(sub->pos().x() > main->pos().x());
869  QCOMPARE(sub->activeAction(), subAction);
870 }
871 
872 // QTBUG-49588, QTBUG-48396: activeSubMenuPositionExec() is the same as
873 // activeSubMenuPosition(), but uses QMenu::exec(), which produces a different
874 // sequence of events. Verify that the sub menu is positioned to the right of the
875 // main menu.
877 {
878  Q_OBJECT
879 public:
880  SubMenuPositionExecMenu() : QMenu("Menu-Title"), m_timerId(-1), m_timerTick(0)
881  {
882  addAction("Item 1");
883  m_subMenu = addMenu("Submenu");
884  m_subAction = m_subMenu->addAction("Sub-Item1");
885  setActiveAction(m_subMenu->menuAction());
886  }
887 
888 protected:
889  void showEvent(QShowEvent *e) override
890  {
891  QVERIFY(m_subMenu->isVisible());
892  QVERIFY2(m_subMenu->x() > x(),
893  (QByteArray::number(m_subMenu->x()) + ' ' + QByteArray::number(x())).constData());
894  m_timerId = startTimer(50);
896  }
897 
898  void timerEvent(QTimerEvent *e) override
899  {
900  if (e->timerId() == m_timerId) {
901  switch (m_timerTick++) {
902  case 0:
903  m_subMenu->close();
904  break;
905  case 1:
906  close();
907  break;
908  }
909  }
910  }
911 
912 private:
913  int m_timerId;
914  int m_timerTick;
915  QMenu *m_subMenu;
916  QAction *m_subAction;
917 };
918 
919 void tst_QMenu::activeSubMenuPositionExec()
920 {
921 #ifdef Q_OS_ANDROID
922  // QTBUG-87424
923  QSKIP("Android: This hangs. Figure out why.");
924 #endif
926  menu.exec(QGuiApplication::primaryScreen()->availableGeometry().center());
927 }
928 
929 void tst_QMenu::task242454_sizeHint()
930 {
931 #ifdef Q_OS_ANDROID
932  // QTBUG-87424
933  QSKIP("Android: This hangs. Figure out why.");
934 #endif
935  QMenu menu;
936  QString s = QLatin1String("foo\nfoo\nfoo\nfoo");
937  menu.addAction(s);
939 }
940 
941 class Menu : public QMenu
942 {
943  Q_OBJECT
944 public slots:
945  void clear()
946  {
947  QMenu::clear();
948  }
949 };
950 
951 void tst_QMenu::task176201_clear()
952 {
953  //this test used to crash
954  Menu menu;
955  QAction *action = menu.addAction("test");
957  menu.popup(QPoint());
959 }
960 
961 void tst_QMenu::task250673_activeMultiColumnSubMenuPosition()
962 {
963  class MyMenu : public QMenu
964  {
965  public:
966  int columnCount() const { return QMenu::columnCount(); }
967  };
968 
969  QMenu sub;
970 
971  if (sub.style()->styleHint(QStyle::SH_Menu_Scrollable, 0, &sub)) {
972  //the style prevents the menus from getting columns
973  QSKIP("the style doesn't support multiple columns, it makes the menu scrollable");
974  }
975 
976  sub.addAction("Sub-Item1");
977  QAction *subAction = sub.addAction("Sub-Item2");
978 
979  MyMenu main;
980  main.addAction("Item 1");
981  QAction *menuAction = main.addMenu(&sub);
982  main.popup(QPoint(200,200));
983 
984  uint i = 2;
985  while (main.columnCount() < 2) {
986  main.addAction(QLatin1String("Item ") + QString::number(i));
987  ++i;
988  QVERIFY(i<1000);
989  }
990  main.setActiveAction(menuAction);
991  sub.setActiveAction(subAction);
992 
993  QVERIFY(main.isVisible());
994  QCOMPARE(main.activeAction(), menuAction);
995  QVERIFY(sub.isVisible());
996  QVERIFY(sub.pos().x() > main.pos().x());
997 
998  const int subMenuOffset = main.style()->pixelMetric(QStyle::PM_SubMenuOverlap, 0, &main);
999  QVERIFY((sub.geometry().left() - subMenuOffset + 5) < main.geometry().right());
1000 }
1001 
1002 void tst_QMenu::task256918_setFont()
1003 {
1004  QMenu menu;
1005  QAction *action = menu.addAction("foo");
1006  QFont f;
1007  f.setPointSize(30);
1008  action->setFont(f);
1009  centerOnScreen(&menu, QSize(120, 40));
1010  menu.show(); //ensures that the actiongeometry are calculated
1011  QVERIFY(menu.actionGeometry(action).height() > f.pointSize());
1012 }
1013 
1014 void tst_QMenu::menuSizeHint()
1015 {
1016  QMenu menu;
1017  //this is a list of arbitrary strings so that we check the geometry
1018  for (auto str : {"trer", "ezrfgtgvqd", "sdgzgzerzerzer", "eerzertz", "er"})
1019  menu.addAction(str);
1020 
1021  const QMargins cm = menu.contentsMargins();
1022  const int panelWidth = menu.style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, &menu);
1023  const int hmargin = menu.style()->pixelMetric(QStyle::PM_MenuHMargin, 0, &menu),
1024  vmargin = menu.style()->pixelMetric(QStyle::PM_MenuVMargin, 0, &menu);
1025 
1026  int maxWidth =0;
1027  QRect result;
1028  for (QAction *action : menu.actions()) {
1029  maxWidth = qMax(maxWidth, menu.actionGeometry(action).width());
1031  QCOMPARE(result.x(), cm.left() + hmargin + panelWidth);
1032  QCOMPARE(result.y(), cm.top() + vmargin + panelWidth);
1033  }
1034 
1035  QStyleOption opt(0);
1036  opt.rect = menu.rect();
1038 
1039  QSize resSize = QSize(result.x(), result.y()) + result.size() + QSize(hmargin + cm.right() + panelWidth, vmargin + cm.top() + panelWidth);
1040 
1041  resSize = menu.style()->sizeFromContents(QStyle::CT_Menu, &opt, resSize, &menu);
1042 
1043  QCOMPARE(resSize, menu.sizeHint());
1044 }
1045 
1046 class Menu258920 : public QMenu
1047 {
1048  Q_OBJECT
1049 public slots:
1050  void paintEvent(QPaintEvent *e) override
1051  {
1053  painted = true;
1054  }
1055 
1056 public:
1057  bool painted;
1058 };
1059 
1060 // Mouse move related signals for Windows Mobile unavailable
1061 void tst_QMenu::task258920_mouseBorder()
1062 {
1063  const QRect screenGeometry = QGuiApplication::primaryScreen()->availableGeometry();
1064  Menu258920 menu;
1065  QCursor::setPos(screenGeometry.topLeft());
1066  if (!QTest::qWaitFor([screenGeometry]{ return QCursor::pos() == screenGeometry.topLeft(); }))
1067  QSKIP("Can't move cursor out of the way");
1068  // For styles which inherit from QWindowsStyle, styleHint(QStyle::SH_Menu_MouseTracking) is true.
1069  menu.setMouseTracking(true);
1070  QAction *action = menu.addAction("test");
1071 
1072  const QPoint center = screenGeometry.center();
1073  menu.popup(center);
1075  QRect actionRect = menu.actionGeometry(action);
1076  const QPoint actionCenter = actionRect.center();
1077  QTest::mouseMove(&menu, actionCenter - QPoint(-10, 0));
1078  QTest::mouseMove(&menu, actionCenter);
1079  QTest::mouseMove(&menu, actionCenter + QPoint(10, 0));
1081  menu.painted = false;
1082  QTest::mouseMove(&menu, QPoint(actionRect.center().x(), actionRect.bottom() + 1));
1083  QTRY_COMPARE(static_cast<QAction*>(0), menu.activeAction());
1084  QTRY_VERIFY(menu.painted);
1085 }
1086 
1087 void tst_QMenu::setFixedWidth()
1088 {
1089  QMenu menu;
1090  menu.addAction("action");
1091  menu.setFixedWidth(300);
1092  //the sizehint should reflect the minimumwidth because the action will try to
1093  //get as much space as possible
1094  QCOMPARE(menu.sizeHint().width(), menu.minimumWidth());
1095 }
1096 
1097 void tst_QMenu::deleteActionInTriggered()
1098 {
1099  // should not crash
1100  QMenu m;
1102  QPointer<QAction> a = m.addAction("action");
1103  a.data()->trigger();
1104  QVERIFY(!a);
1105 }
1106 
1108  Q_OBJECT
1109 public:
1110  explicit PopulateOnAboutToShowTestMenu(QWidget *parent = nullptr);
1111 
1112 public slots:
1113  void populateMenu();
1114 };
1115 
1117 {
1118  connect(this, SIGNAL(aboutToShow()), this, SLOT(populateMenu()));
1119 }
1120 
1122 {
1123  // just adds 3 dummy actions and a separator.
1124  addAction("Foo");
1125  addAction("Bar");
1126  addAction("FooBar");
1127  addSeparator();
1128 }
1129 
1130 static inline QByteArray msgGeometryIntersects(const QRect &r1, const QRect &r2)
1131 {
1132  QString result;
1133  QDebug(&result) << r1 << "intersects" << r2;
1134  return result.toLocal8Bit();
1135 }
1136 
1137 void tst_QMenu::pushButtonPopulateOnAboutToShow()
1138 {
1139 #ifdef Q_OS_MACOS
1140  QSKIP("Popup menus may partially overlap the button on macOS, and that's okey");
1141 #endif
1142 
1143  QPushButton b("Test PushButton");
1145 
1146  QMenu *buttonMenu= new PopulateOnAboutToShowTestMenu(&b);
1147  b.setMenu(buttonMenu);
1148  const QScreen *scr = QGuiApplication::screenAt(b.pos());
1149  b.show();
1150  const QRect screen = scr->geometry();
1151 
1152  QRect desiredGeometry = b.geometry();
1153  desiredGeometry.moveTopLeft(QPoint(screen.x() + 10, screen.bottom() - b.height() - 5));
1154 
1155  b.setGeometry(desiredGeometry);
1157 
1158  if (b.geometry() != desiredGeometry) {
1159  // We are trying to put the button very close to the edge of the screen,
1160  // explicitly to test behavior when the popup menu goes off the screen.
1161  // However a modern window manager is quite likely to reject this requested geometry
1162  // (kwin in kde4 does, for example, since the button would probably appear behind
1163  // or partially behind the taskbar).
1164  // Your best bet is to run this test _without_ a WM.
1165  QSKIP("Your window manager won't allow a window against the bottom of the screen");
1166  }
1167 
1168  QTimer::singleShot(300, buttonMenu, SLOT(hide()));
1169  QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center());
1170  QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry()));
1171 
1172  // note: we're assuming that, if we previously got the desired geometry, we'll get it here too
1173  b.move(10, screen.bottom()-buttonMenu->height()-5);
1174  QTimer::singleShot(300, buttonMenu, SLOT(hide()));
1175  QTest::mouseClick(&b, Qt::LeftButton, Qt::NoModifier, b.rect().center());
1176  QVERIFY2(!buttonMenu->geometry().intersects(b.geometry()), msgGeometryIntersects(buttonMenu->geometry(), b.geometry()));
1177 }
1178 
1179 void tst_QMenu::QTBUG7907_submenus_autoselect()
1180 {
1181  QMenu menu("Test Menu");
1182  QMenu set1("Setting1");
1183  QMenu set2("Setting2");
1184  QMenu subset("Subsetting");
1185  subset.addAction("Values");
1186  set1.addMenu(&subset);
1187  menu.addMenu(&set1);
1188  menu.addMenu(&set2);
1189  centerOnScreen(&menu, QSize(120, 100));
1190  menu.show();
1193  QVERIFY(!subset.isVisible());
1194 }
1195 
1196 void tst_QMenu::QTBUG7411_submenus_activate()
1197 {
1198  QMenu menu("Test Menu");
1199  QAction *act = menu.addAction("foo");
1200  QMenu sub1("&sub1");
1201  sub1.addAction("foo");
1202  sub1.setTitle("&sub1");
1203  QAction *act1 = menu.addMenu(&sub1);
1204  centerOnScreen(&menu, QSize(120, 100));
1205  menu.show();
1207  menu.setActiveAction(act);
1208  QTest::keyPress(&menu, Qt::Key_Down);
1209  QCOMPARE(menu.activeAction(), act1);
1210  QVERIFY(!sub1.isVisible());
1211  QTest::keyPress(&menu, Qt::Key_S);
1212  QTRY_VERIFY(sub1.isVisible());
1213 }
1214 
1215 static bool isPlatformWayland()
1216 {
1218 }
1219 
1220 void tst_QMenu::QTBUG30595_rtl_submenu()
1221 {
1222  if (isPlatformWayland())
1223  QSKIP("Creating xdg_popups on Wayland requires real input events. Positions would be off.");
1224 
1225  QMenu menu("Test Menu");
1227  QMenu sub("&sub");
1228  sub.addAction("bar");
1229  sub.setTitle("&sub");
1230  menu.addMenu(&sub);
1231  centerOnScreen(&menu, QSize(120, 40));
1232  menu.show();
1235  QTRY_VERIFY(sub.isVisible());
1236  QVERIFY2(sub.pos().x() < menu.pos().x(), QByteArray::number(sub.pos().x()) + QByteArrayLiteral(" not less than ") + QByteArray::number(menu.pos().x()));
1237 }
1238 
1239 void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger()
1240 {
1241  QMenu menu("Test Menu");
1242  QMenu sub1("&sub1");
1243  QMenu subsub1("&subsub1");
1244  subsub1.addAction("foo");
1245  sub1.addMenu(&subsub1);
1246  menu.addMenu(&sub1);
1247  centerOnScreen(&menu, QSize(120, 100));
1248  menu.show();
1250  QTest::keyPress(&menu, Qt::Key_S);
1251  QTest::qWait(100); // 20ms delay with previous behavior
1252  QTRY_VERIFY(sub1.isVisible());
1253  QVERIFY(!subsub1.isVisible());
1254 }
1255 
1256 #ifndef Q_OS_MACOS
1257 void tst_QMenu::click_while_dismissing_submenu()
1258 {
1259  if (isPlatformWayland())
1260  QSKIP("Wayland: Creating (grabbing) popups requires real mouse events.");
1261 
1262  QMenu menu("Test Menu");
1263  QAction *action = menu.addAction("action");
1264  QMenu sub("&sub");
1265  sub.addAction("subaction");
1266  menu.addMenu(&sub);
1267  centerOnScreen(&menu, QSize(120, 100));
1268  menu.show();
1270  QSignalSpy menuShownSpy(&sub, &QMenu::aboutToShow);
1271  QSignalSpy menuHiddenSpy(&sub, &QMenu::aboutToHide);
1273  QWindow *menuWindow = menu.windowHandle();
1274  QVERIFY(menuWindow);
1275  //go over the submenu, press, move and release over the top level action
1276  //this opens the submenu, move two times to emulate user interaction (d->motions > 0 in QMenu)
1277  QTest::mouseMove(menuWindow, menu.rect().center() + QPoint(0,2));
1278  QTest::mouseMove(menuWindow, menu.rect().center() + QPoint(1,3), 60);
1279  QVERIFY(menuShownSpy.wait());
1280  QVERIFY(sub.isVisible());
1282  //press over the submenu entry
1283  QTest::mousePress(menuWindow, Qt::LeftButton, {}, menu.rect().center() + QPoint(0, 2), 300);
1284  //move over the main action
1285  QTest::mouseMove(menuWindow, menu.rect().center() - QPoint(0,2));
1286  QVERIFY(menuHiddenSpy.wait());
1287  //the submenu must have been hidden for the bug to be triggered
1288  QVERIFY(!sub.isVisible());
1289  QTest::mouseRelease(menuWindow, Qt::LeftButton, {}, menu.rect().center() - QPoint(0, 2), 300);
1290  QCOMPARE(spy.count(), 1);
1291 }
1292 #endif
1293 
1294 class MyWidget : public QWidget
1295 {
1296 public:
1298  QWidget(parent),
1299  move(0), enter(0), leave(0)
1300  {
1301  setMinimumSize(100, 100);
1302  setMouseTracking(true);
1303  }
1304 
1305  bool event(QEvent *e) override
1306  {
1307  switch (e->type()) {
1308  case QEvent::MouseMove:
1309  ++move;
1310  break;
1311  case QEvent::Enter:
1312  ++enter;
1313  break;
1314  case QEvent::Leave:
1315  ++leave;
1316  break;
1317  default:
1318  break;
1319  }
1320  return QWidget::event(e);
1321  }
1322 
1324 };
1325 
1326 void tst_QMenu::QTBUG47515_widgetActionEnterLeave()
1327 {
1329  QSKIP("Window activation is not supported");
1330  if (QGuiApplication::platformName() == QLatin1String("cocoa"))
1331  QSKIP("This test is meaningless on macOS, for additional info see QTBUG-63031");
1332 
1333  const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
1334  QRect geometry(QPoint(), availableGeometry.size() / 3);
1335  geometry.moveCenter(availableGeometry.center());
1336  QPoint pointOutsideMenu = geometry.bottomRight() - QPoint(5, 5);
1337 
1338  QMainWindow topLevel;
1339  topLevel.setGeometry(geometry);
1340 
1341  QMenuBar *menuBar = topLevel.menuBar();
1342  menuBar->setNativeMenuBar(false);
1343  QMenu *menu = menuBar->addMenu("Menu1");
1344  QMenu *submenu = menu->addMenu("Menu2");
1345 
1346  QWidgetAction *menuAction = new QWidgetAction(menu);
1347  MyWidget *w1 = new MyWidget(menu);
1348  menuAction->setDefaultWidget(w1);
1349 
1350  QWidgetAction *submenuAction = new QWidgetAction(submenu);
1351  MyWidget *w2 = new MyWidget(submenu);
1352  submenuAction->setDefaultWidget(w2);
1353 
1354  QAction *nextMenuAct = menu->addMenu(submenu);
1355 
1356  menu->addAction(menuAction);
1357  submenu->addAction(submenuAction);
1358 
1359  topLevel.show();
1362  QWindow *topLevelWindow = topLevel.windowHandle();
1363  QVERIFY(topLevelWindow);
1364 
1365  // Root menu: Click on menu bar to open menu1
1366  {
1367  const QPoint menuActionPos = menuBar->mapTo(&topLevel, menuBar->actionGeometry(menu->menuAction()).center());
1368  QTest::mouseClick(topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), menuActionPos);
1370 
1371  w1->enter = 0;
1372  w1->leave = 0;
1373  QPoint w1Center = topLevel.mapFromGlobal(w1->mapToGlobal(w1->rect().center()));
1374  QTest::mouseMove(topLevelWindow, w1Center);
1375  QVERIFY(w1->isVisible());
1376  QTRY_COMPARE(w1->leave, 0);
1377  QTRY_COMPARE(w1->enter, 1);
1378 
1379  // Check whether leave event is not delivered on mouse move
1380  w1->move = 0;
1381  QTest::mouseMove(topLevelWindow, w1Center + QPoint(1, 1));
1382  QTRY_COMPARE(w1->move, 1);
1383  QTRY_COMPARE(w1->leave, 0);
1384  QTRY_COMPARE(w1->enter, 1);
1385 
1386  QTest::mouseMove(topLevelWindow, topLevel.mapFromGlobal(pointOutsideMenu));
1387  QTRY_COMPARE(w1->leave, 1);
1388  QTRY_COMPARE(w1->enter, 1);
1389  }
1390 
1391  // Submenu
1392  {
1393  menu->setActiveAction(nextMenuAct);
1395 
1396  QPoint w2Center = topLevel.mapFromGlobal(w2->mapToGlobal(w2->rect().center()));
1397  QTest::mouseMove(topLevelWindow, w2Center);
1398 
1399  QVERIFY(w2->isVisible());
1400  QTRY_COMPARE(w2->leave, 0);
1401  QTRY_COMPARE(w2->enter, 1);
1402 
1403  // Check whether leave event is not delivered on mouse move
1404  w2->move = 0;
1405  QTest::mouseMove(topLevelWindow, w2Center + QPoint(1, 1));
1406  QTRY_COMPARE(w2->move, 1);
1407  QTRY_COMPARE(w2->leave, 0);
1408  QTRY_COMPARE(w2->enter, 1);
1409 
1410  QTest::mouseMove(topLevelWindow, topLevel.mapFromGlobal(pointOutsideMenu));
1411  QTRY_COMPARE(w2->leave, 1);
1412  QTRY_COMPARE(w2->enter, 1);
1413  }
1414 }
1415 
1416 void tst_QMenu::QTBUG_89082_actionTipsHide()
1417 {
1419  QSKIP("Window activation is not supported");
1420 
1421  QWidget widget;
1422  QMenu *menu = new QMenu(&widget);
1423  menu->addAction("aaa");
1424  menu->addAction("bbb");
1425  menu->addAction("ccc");
1426  menu->addAction("ddd");
1427  menu->addAction("eee");
1428  menu->addAction("fff");
1429  menu->setToolTipsVisible(true);
1430 
1431  auto menuActTip = menu->actions().first();
1432  QString tipFullName = "actionTip-this-is-a-long-action-and-show-the-full-name-by-tip";
1433  QFontMetrics m_fm = QFontMetrics(QAction().font());
1434  const QString &&elidedName = m_fm.elidedText(tipFullName, Qt::ElideRight, 50);
1435  menuActTip->setText(elidedName);
1436  if (elidedName != tipFullName)
1437  menuActTip->setToolTip(tipFullName);
1438 
1439  widget.resize(300, 200);
1440  centerOnScreen(&widget);
1441  widget.show();
1442 #if QT_CONFIG(cursor)
1443  QCursor::setPos(widget.screen()->availableGeometry().topLeft() + QPoint(10, 10));
1444 #endif
1447  menu->popup(widget.geometry().topRight() + QPoint(50, 0));
1449  auto menuWindow = menu->windowHandle();
1450  QVERIFY(menuWindow != nullptr);
1451 
1452  auto actionZero = menu->actions().at(0);
1453  auto actionOne = menu->actions().at(1);
1454  auto actionFive = menu->actions().at(5);
1455  const QRect submenuRect0 = menu->actionGeometry(actionZero);
1456  const QPoint submenuPos0(submenuRect0.topLeft() + QPoint(3, 3));
1457 
1458  const QRect submenuRect1 = menu->actionGeometry(actionOne);
1459  const QPoint submenuPos1(submenuRect1.topLeft() + QPoint(3, 3));
1460 
1461  const QRect submenuRect5 = menu->actionGeometry(actionFive);
1462  const QPoint submenuPos5(submenuRect5.topLeft() + QPoint(10, 3));
1463 
1464  QTest::mouseMove(menuWindow, submenuPos1);
1465  QTest::mouseMove(menuWindow, submenuPos0); //show the tip
1466  QTRY_COMPARE_WITH_TIMEOUT(QToolTip::text(), tipFullName, 1000);
1467 
1468  //Move to the fifth action without prompting
1469  QTest::mouseMove(menuWindow, submenuPos5);
1470  //The previous tip was hidden, but now is a new tip to get text, So there should be no content
1472 }
1473 
1474 void tst_QMenu::QTBUG8122_widgetActionCrashOnClose()
1475 {
1477  QSKIP("Window activation is not supported");
1478  if (QGuiApplication::platformName() == QLatin1String("cocoa"))
1479  QSKIP("See QTBUG-63031");
1480 
1481  const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
1482  QRect geometry(QPoint(), availableGeometry.size() / 3);
1483  geometry.moveCenter(availableGeometry.center());
1484  QPoint pointOutsideMenu = geometry.bottomRight() - QPoint(5, 5);
1485 
1486  QMainWindow topLevel;
1487  topLevel.setGeometry(geometry);
1488 
1489  auto menuBar = topLevel.menuBar();
1490  auto menu = menuBar->addMenu("Menu");
1491  auto wAct = new QWidgetAction(menu);
1492  auto spinBox1 = new QSpinBox(menu);
1493  wAct->setDefaultWidget(spinBox1);
1494  menu->addAction(wAct);
1495  auto subMenu = menu->addMenu("Submenu");
1496  auto nextMenuAct = menu->addMenu(subMenu);
1497  auto wAct2 = new QWidgetAction(menu);
1498  auto spinBox2 = new QSpinBox(menu);
1499  wAct2->setDefaultWidget(spinBox2);
1500  subMenu->addAction(wAct2);
1502 
1503  topLevel.show();
1506  QWindow *topLevelWindow = topLevel.windowHandle();
1507  QVERIFY(topLevelWindow);
1508 
1509  const QPoint menuActionPos = menuBar->mapTo(&topLevel, menuBar->actionGeometry(menu->menuAction()).center());
1510  QTest::mouseClick(topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), menuActionPos);
1512 
1513  QPoint w1Center = topLevel.mapFromGlobal(spinBox1->mapToGlobal(spinBox1->rect().center()));
1514  QTest::mouseClick(topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), w1Center);
1515  menu->setActiveAction(nextMenuAct);
1517 
1518  QPoint w2Center = topLevel.mapFromGlobal(spinBox2->mapToGlobal(spinBox2->rect().center()));
1519  QTest::mouseClick(topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), w2Center);
1520  QTest::mouseMove(topLevelWindow, topLevel.mapFromGlobal(pointOutsideMenu));
1522 }
1523 
1527 void tst_QMenu::widgetActionTriggerClosesMenu()
1528 {
1529  class ButtonAction : public QWidgetAction
1530  {
1531  public:
1532  ButtonAction()
1534  {}
1535 
1536  void click()
1537  {
1538  if (pushButton)
1539  pushButton->click();
1540  }
1541 
1542  protected:
1543  QWidget *createWidget(QWidget *parent) override
1544  {
1545  QPushButton *button = new QPushButton(QLatin1String("Button"), parent);
1547 
1548  if (!pushButton)
1549  pushButton = button;
1550  return button;
1551  }
1552 
1553  private:
1555  };
1556 
1557  QMenu menu;
1558  QMenu submenu;
1559 
1560  int menuTriggeredCount = 0;
1561  int menuAboutToHideCount = 0;
1562  QAction *actionTriggered = nullptr;
1563 
1564  connect(&menu, &QMenu::triggered, this, [&](QAction *action){
1565  ++menuTriggeredCount;
1566  actionTriggered = action;
1567  });
1568  connect (&menu, &QMenu::aboutToHide, this, [&](){
1569  ++menuAboutToHideCount;
1570  });
1571 
1572  QAction regularAction(QLatin1String("Action"));
1573  ButtonAction widgetAction;
1574 
1575  submenu.addAction(&regularAction);
1576  submenu.addAction(&widgetAction);
1577 
1578  menu.addMenu(&submenu);
1579  menu.addAction(&regularAction);
1580  menu.addAction(&widgetAction);
1581 
1582  menu.popup(QPoint(200,200));
1583  submenu.popup(QPoint(250,250));
1585  QSKIP("Failed to show menus, aborting test");
1586 
1587  regularAction.trigger();
1588  QVERIFY(menu.isVisible());
1589  QVERIFY(submenu.isVisible());
1590  QCOMPARE(menuTriggeredCount, 1);
1591  QCOMPARE(actionTriggered, &regularAction);
1592  menuTriggeredCount = 0;
1593  actionTriggered = nullptr;
1594 
1595  widgetAction.click();
1596  QVERIFY(!menu.isVisible());
1597  QVERIFY(!submenu.isVisible());
1598  QCOMPARE(menuTriggeredCount, 1);
1599  QCOMPARE(menuAboutToHideCount, 1);
1600  QCOMPARE(actionTriggered, &widgetAction);
1601 }
1602 
1603 void tst_QMenu::transientParent()
1604 {
1606  window.resize(480, 320);
1607  window.menuBar()->setNativeMenuBar(false);
1608  centerOnScreen(&window);
1609 
1610  QMenu *fileMenu = new QMenu("&File");
1611  QAction *exitAct = new QAction("Exit");
1612  fileMenu->addAction(exitAct);
1613 
1614  QMenu *editMenu = new QMenu("&Edit");
1615  QAction *undoAct = new QAction("Undo");
1616  editMenu->addAction(undoAct);
1617 
1618  QMenuBar *menuBar = new QMenuBar;
1619  menuBar->addMenu(fileMenu);
1620  menuBar->addMenu(editMenu);
1621  window.setMenuBar(menuBar);
1622 
1623  // On Mac, we need to create native key events to test menu
1624  // action activation, so skip this part of the test.
1625 #if QT_CONFIG(shortcut) && !defined(Q_OS_DARWIN)
1626  window.show();
1628  QWindow *topLevel = window.windowHandle();
1629  QVERIFY(topLevel);
1630 
1632  window.setFocus();
1634  QVERIFY(window.hasFocus());
1635 
1636  QTest::keyPress(&window, Qt::Key_F, Qt::AltModifier);
1638  if (fileMenu->isWindow() && fileMenu->window() && fileMenu->window()->windowHandle())
1639  QVERIFY(fileMenu->window()->windowHandle()->transientParent());
1640  QTest::keyRelease(fileMenu, Qt::Key_F, Qt::AltModifier);
1641 
1642  QTest::keyPress(fileMenu, Qt::Key_E, Qt::AltModifier);
1644  if (editMenu->isWindow() && editMenu->window() && editMenu->window()->windowHandle())
1645  QVERIFY(editMenu->window()->windowHandle()->transientParent());
1646  QTest::keyRelease(editMenu, Qt::Key_E, Qt::AltModifier);
1647 #endif // QT_CONFIG(shortcut) && !Q_OS_DARWIN
1648 
1649 }
1650 
1651 class MyMenu : public QMenu
1652 {
1653  Q_OBJECT
1654 public:
1655  MyMenu() : m_currentIndex(0)
1656  {
1657  for (int i = 0; i < 2; ++i)
1658  dialogActions[i] = addAction(QLatin1String("dialog ") + QString::number(i), dialogs + i, SLOT(exec()));
1659  }
1660 
1662  {
1663  m_currentIndex = index;
1664  popup(QPoint());
1666  setActiveAction(dialogActions[index]);
1667  QTimer::singleShot(500, this, SLOT(checkVisibility()));
1668  QTest::keyClick(this, Qt::Key_Enter); //activation
1669  }
1670 
1671 public slots:
1673  {
1674  activateAction(1);
1675  }
1676 
1678  {
1679  QTRY_VERIFY(dialogs[m_currentIndex].isVisible());
1680  if (m_currentIndex == 1) {
1681  QApplication::closeAllWindows(); //this is the end of the test
1682  }
1683  }
1684 
1685 private:
1686  QAction *dialogActions[2];
1687  QDialog dialogs[2];
1688  int m_currentIndex;
1689 };
1690 
1691 void tst_QMenu::QTBUG_10735_crashWithDialog()
1692 {
1693  MyMenu menu;
1694 
1695  QTimer::singleShot(1000, &menu, SLOT(activateLastAction()));
1696  menu.activateAction(0);
1697 }
1698 
1699 #ifdef Q_OS_MAC
1700 void tst_QMenu::QTBUG_37933_ampersands_data()
1701 {
1702  QTest::addColumn<QString>("title");
1703  QTest::addColumn<QString>("visibleTitle");
1704  QTest::newRow("simple") << QString("Test") << QString("Test");
1705  QTest::newRow("ampersand") << QString("&Test") << QString("Test");
1706  QTest::newRow("double_ampersand") << QString("&Test && more") << QString("Test & more");
1707  QTest::newRow("ampersand_in_parentheses") << QString("Test(&T) (&&) more") << QString("Test (&) more");
1708  QTest::newRow("ampersand_in_parentheses_after_space") << QString("Test (&T)") << QString("Test");
1709  QTest::newRow("ampersand_in_parentheses_after_spaces") << QString("Test (&T)") << QString("Test");
1710  QTest::newRow("ampersand_in_parentheses_before_space") << QString("Test(&T) ") << QString("Test ");
1711  QTest::newRow("only_ampersand_in_parentheses") << QString("(&T)") << QString("");
1712  QTest::newRow("only_ampersand_in_parentheses_after_space") << QString(" (&T)") << QString("");
1713  QTest::newRow("parentheses_after_space") << QString(" (Dummy)") << QString(" (Dummy)");
1714  QTest::newRow("ampersand_after_space") << QString("About &Qt Project") << QString("About Qt Project");
1715 }
1716 
1718 
1719 void tst_QMenu::QTBUG_37933_ampersands()
1720 {
1721  // external in .mm file
1723 }
1724 #endif
1725 
1726 void tst_QMenu::QTBUG_56917_wideMenuSize()
1727 {
1728  // menu shouldn't to take on full screen height when menu width is larger than screen width
1729  QMenu menu;
1730  QString longString;
1731  longString.fill(QLatin1Char('Q'), 3000);
1732  menu.addAction(longString);
1733  QSize menuSizeHint = menu.sizeHint();
1734  menu.popup(QPoint());
1736  QVERIFY(menu.isVisible());
1737  QVERIFY(menu.height() <= menuSizeHint.height());
1738 }
1739 
1740 void tst_QMenu::QTBUG_56917_wideMenuScreenNumber()
1741 {
1742  if (QApplication::styleHints()->showIsFullScreen())
1743  QSKIP("The platform defaults to windows being fullscreen.");
1744  // menu must appear on the same screen where show action is triggered
1745  QString longString;
1746  longString.fill(QLatin1Char('Q'), 3000);
1747 
1748  const QList<QScreen *> screens = QGuiApplication::screens();
1749  for (QScreen *screen : screens) {
1750  QMenu menu;
1751  menu.addAction(longString);
1752  menu.popup(screen->geometry().center());
1754  QVERIFY(menu.isVisible());
1756  }
1757 }
1758 
1759 void tst_QMenu::QTBUG_56917_wideSubmenuScreenNumber()
1760 {
1761  if (QApplication::styleHints()->showIsFullScreen())
1762  QSKIP("The platform defaults to windows being fullscreen.");
1763  // submenu must appear on the same screen where its parent menu is shown
1764  QString longString;
1765  longString.fill(QLatin1Char('Q'), 3000);
1766 
1767  const QList<QScreen *> screens = QGuiApplication::screens();
1768  for (QScreen *screen : screens) {
1769  QMenu menu;
1770  QMenu submenu("Submenu");
1771  submenu.addAction(longString);
1772  QAction *action = menu.addMenu(&submenu);
1773  menu.popup(screen->geometry().center());
1775  QVERIFY(menu.isVisible());
1777  QTest::qWait(100);
1779  QVERIFY(submenu.isVisible());
1781  }
1782 }
1783 
1784 void tst_QMenu::menuSize_Scrolling_data()
1785 {
1786  QTest::addColumn<int>("numItems");
1787  QTest::addColumn<int>("topMargin");
1788  QTest::addColumn<int>("bottomMargin");
1789  QTest::addColumn<int>("leftMargin");
1790  QTest::addColumn<int>("rightMargin");
1791  QTest::addColumn<int>("topPadding");
1792  QTest::addColumn<int>("bottomPadding");
1793  QTest::addColumn<int>("leftPadding");
1794  QTest::addColumn<int>("rightPadding");
1795  QTest::addColumn<int>("border");
1796  QTest::addColumn<bool>("scrollable");
1797  QTest::addColumn<bool>("tearOff");
1798 
1799  // test data
1800  // a single column and non-scrollable menu with contents margins + border
1801  QTest::newRow("data0") << 5 << 2 << 2 << 2 << 2 << 0 << 0 << 0 << 0 << 2 << false << false;
1802  // a single column and non-scrollable menu with paddings + border
1803  QTest::newRow("data1") << 5 << 0 << 0 << 0 << 0 << 2 << 2 << 2 << 2 << 2 << false << false;
1804  // a single column and non-scrollable menu with contents margins + paddings + border
1805  QTest::newRow("data2") << 5 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << false << false;
1806  // a single column and non-scrollable menu with contents margins + paddings + border + tear-off
1807  QTest::newRow("data3") << 5 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << false << true;
1808  // a multi-column menu with contents margins + border
1809  QTest::newRow("data4") << 80 << 2 << 2 << 2 << 2 << 0 << 0 << 0 << 0 << 2 << false << false;
1810  // a multi-column menu with paddings + border
1811  QTest::newRow("data5") << 80 << 0 << 0 << 0 << 0 << 2 << 2 << 2 << 2 << 2 << false << false;
1812  // a multi-column menu with contents margins + paddings + border
1813  QTest::newRow("data6") << 80 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << false << false;
1814  // a multi-column menu with contents margins + paddings + border + tear-off
1815  QTest::newRow("data7") << 80 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << false << true;
1816  // a scrollable menu with contents margins + border
1817  QTest::newRow("data8") << 80 << 2 << 2 << 2 << 2 << 0 << 0 << 0 << 0 << 2 << true << false;
1818  // a scrollable menu with paddings + border
1819  QTest::newRow("data9") << 80 << 0 << 0 << 0 << 0 << 2 << 2 << 2 << 2 << 2 << true << false;
1820  // a scrollable menu with contents margins + paddings + border
1821  QTest::newRow("data10") << 80 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << true << false;
1822  // a scrollable menu with contents margins + paddings + border + tear-off
1823  QTest::newRow("data11") << 80 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << 2 << true << true;
1824 }
1825 
1826 void tst_QMenu::menuSize_Scrolling()
1827 {
1828  class TestMenu : public QMenu
1829  {
1830  public:
1831  struct ContentsMargins
1832  {
1833  ContentsMargins(int l, int t, int r, int b)
1834  : left(l), top(t), right(r), bottom(b) {}
1835  int left;
1836  int top;
1837  int right;
1838  int bottom;
1839  };
1840 
1841  struct MenuPaddings
1842  {
1843  MenuPaddings(int l, int t, int r, int b)
1844  : left(l), top(t), right(r), bottom(b) {}
1845  int left;
1846  int top;
1847  int right;
1848  int bottom;
1849  };
1850 
1851  TestMenu(int numItems, const ContentsMargins &margins, const MenuPaddings &paddings,
1852  int border, bool scrollable, bool tearOff)
1853  : QMenu("Test Menu"),
1854  m_numItems(numItems),
1855  m_scrollable(scrollable),
1856  m_tearOff(tearOff)
1857  {
1858  init(margins, paddings, border);
1859  }
1860 
1861  ~TestMenu() {}
1862 
1863  private:
1864  void showEvent(QShowEvent *e) override
1865  {
1866  QVERIFY(actions().length() == m_numItems);
1867 
1868  int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin, nullptr, this);
1869  int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, nullptr, this);
1870  const QMargins cm = contentsMargins();
1871  QRect lastItem = actionGeometry(actions().at(actions().length() - 1));
1872  QSize s = size();
1875  qWarning("Skipping test on minimal/offscreen platforms - QTBUG-73522");
1877  return;
1878  }
1879 
1880  QCOMPARE( s.width(), lastItem.right() + fw + hmargin + cm.right() + 1);
1882  }
1883 
1884  void init(const ContentsMargins &margins, const MenuPaddings &paddings, int border)
1885  {
1886  setLayoutDirection(Qt::LeftToRight);
1887 
1888  setTearOffEnabled(m_tearOff);
1889  setContentsMargins(margins.left, margins.top, margins.right, margins.bottom);
1890  QString cssStyle("QMenu {menu-scrollable: ");
1891  cssStyle += (m_scrollable ? QString::number(1) : QString::number(0));
1892  cssStyle += "; border: ";
1893  cssStyle += QString::number(border);
1894  cssStyle += "px solid black; padding: ";
1895  cssStyle += QString::number(paddings.top);
1896  cssStyle += "px ";
1897  cssStyle += QString::number(paddings.right);
1898  cssStyle += "px ";
1899  cssStyle += QString::number(paddings.bottom);
1900  cssStyle += "px ";
1901  cssStyle += QString::number(paddings.left);
1902  cssStyle += "px;}";
1903  setStyleSheet(cssStyle);
1904  for (int i = 1; i <= m_numItems; i++)
1905  addAction("MenuItem " + QString::number(i));
1906  }
1907 
1908  private:
1909  int m_numItems;
1910  bool m_scrollable;
1911  bool m_tearOff;
1912  };
1913 
1914  QFETCH(int, numItems);
1915  QFETCH(int, topMargin);
1916  QFETCH(int, bottomMargin);
1917  QFETCH(int, leftMargin);
1918  QFETCH(int, rightMargin);
1919  QFETCH(int, topPadding);
1920  QFETCH(int, bottomPadding);
1921  QFETCH(int, leftPadding);
1922  QFETCH(int, rightPadding);
1923  QFETCH(int, border);
1924  QFETCH(bool, scrollable);
1925  QFETCH(bool, tearOff);
1926 
1927  qApp->setAttribute(Qt::AA_DontUseNativeMenuBar);
1928 
1929  TestMenu::ContentsMargins margins(leftMargin, topMargin, rightMargin, bottomMargin);
1930  TestMenu::MenuPaddings paddings(leftPadding, topPadding, rightPadding, bottomPadding);
1931  TestMenu menu(numItems, margins, paddings, border, scrollable, tearOff);
1932  menu.popup(QPoint(0,0));
1933  centerOnScreen(&menu);
1935 
1936  QList<QAction *> actions = menu.actions();
1937  QCOMPARE(actions.length(), numItems);
1938 
1939  MenuMetrics mm(&menu);
1940  QTest::keyClick(&menu, Qt::Key_Home);
1941  QTRY_COMPARE(menu.actionGeometry(actions.first()).y(), mm.fw + mm.vmargin + topMargin + (tearOff ? mm.tearOffHeight : 0));
1942  QCOMPARE(menu.actionGeometry(actions.first()).x(), mm.fw + mm.hmargin + leftMargin);
1943 
1944  if (!scrollable)
1945  return;
1946 
1947  QTest::keyClick(&menu, Qt::Key_End);
1948  QTRY_COMPARE(menu.actionGeometry(actions.last()).right(),
1949  menu.width() - mm.fw - mm.hmargin - leftMargin - 1);
1950  QCOMPARE(menu.actionGeometry(actions.last()).bottom(),
1951  menu.height() - mm.fw - mm.vmargin - bottomMargin - 1);
1952 }
1953 
1954 void tst_QMenu::tearOffMenuNotDisplayed()
1955 {
1957  QSKIP("Window activation is not supported");
1958  QWidget widget;
1960  menu->setTearOffEnabled(true);
1962 
1963  menu->setStyleSheet("QMenu { menu-scrollable: 1 }");
1964  for (int i = 0; i < 80; i++)
1966 
1967  widget.resize(300, 200);
1968  centerOnScreen(&widget);
1969  widget.show();
1972  menu->popup(widget.geometry().topRight() + QPoint(50, 0));
1975 
1976  MenuMetrics mm(menu.data());
1977  const int tearOffOffset = mm.fw + mm.vmargin + mm.tearOffHeight / 2;
1978 
1979  QTest::mouseClick(menu.data(), Qt::LeftButton, {}, QPoint(10, tearOffOffset), 10);
1981  QPointer<QMenu> torn = getTornOffMenu();
1982  QVERIFY(torn);
1983  QVERIFY(torn->isVisible());
1984  QVERIFY(torn->minimumWidth() >=0 && torn->minimumWidth() < QWIDGETSIZE_MAX);
1985 
1986  menu->hideTearOffMenu();
1988  QVERIFY(!torn->isVisible());
1989 }
1990 
1991 void tst_QMenu::QTBUG_61039_menu_shortcuts()
1992 {
1994  QSKIP("Window activation is not supported");
1995 
1996  QAction *actionKamen = new QAction("Action Kamen");
1997 #if QT_CONFIG(shortcut)
1998  actionKamen->setShortcut(QKeySequence(QLatin1String("K")));
1999 #endif
2000  QAction *actionJoe = new QAction("Action Joe");
2001 #if QT_CONFIG(shortcut)
2002  actionJoe->setShortcut(QKeySequence(QLatin1String("Ctrl+J")));
2003 #endif
2004 
2005  QMenu menu;
2006  menu.addAction(actionKamen);
2007  menu.addAction(actionJoe);
2009 
2010  QWidget widget;
2012  widget.show();
2014 
2015  QSignalSpy actionKamenSpy(actionKamen, &QAction::triggered);
2016  QTest::keyClick(&widget, Qt::Key_K);
2017  QTRY_COMPARE(actionKamenSpy.count(), 1);
2018 
2019  QSignalSpy actionJoeSpy(actionJoe, &QAction::triggered);
2020  QTest::keyClick(&widget, Qt::Key_J, Qt::ControlModifier);
2021  QTRY_COMPARE(actionJoeSpy.count(), 1);
2022 }
2023 
2024 void tst_QMenu::screenOrientationChangedCloseMenu()
2025 {
2026  QMenu menu;
2027  menu.addAction("action1");
2028  menu.show();
2029 
2030  QTRY_COMPARE(menu.isVisible(),true);
2031 
2035 
2036  QTRY_COMPARE(menu.isVisible(),false);
2037 }
2038 
2040 #include "tst_qmenu.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
Arabic default style
Definition: afstyles.h:94
void testFunction1(bool)
void testFunction0()
void paintEvent(QPaintEvent *e) override
Definition: tst_qmenu.cpp:1050
void clear()
Definition: tst_qmenu.cpp:945
Menu(QGraphicsView *parent)
Definition: menu.cpp:42
void activateAction(int index)
Definition: tst_qmenu.cpp:1661
void activateLastAction()
Definition: tst_qmenu.cpp:1672
void checkVisibility()
Definition: tst_qmenu.cpp:1677
bool event(QEvent *e) override
Definition: tst_qmenu.cpp:1305
QWidget(QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags())
MyWidget(QWidget *parent)
Definition: tst_qmenu.cpp:1297
PopulateOnAboutToShowTestMenu(QWidget *parent=nullptr)
Definition: tst_qmenu.cpp:1116
void clicked(bool checked=false)
void editingFinished()
The QAction class provides an abstraction for user commands that can be added to different user inter...
Definition: qaction.h:65
void setSeparator(bool b)
Definition: qaction.cpp:607
void triggered(bool checked=false)
void setText(const QString &text)
Definition: qaction.cpp:641
void setEnabled(bool)
Definition: qaction.cpp:957
void trigger()
Definition: qaction.h:244
static QStyle * style()
static void closeAllWindows()
static QWidget * focusWidget()
static void setEffectEnabled(Qt::UIEffect, bool enable=true)
static QWidget * activePopupWidget()
static QWidget * activeWindow()
static void setActiveWindow(QWidget *act)
static QWidgetList allWidgets()
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
static QByteArray number(int, int base=10)
static QCoreApplication * instance()
static bool sendEvent(QObject *receiver, QEvent *event)
static void setPos(int x, int y)
Definition: qcursor.cpp:276
static QPoint pos()
Definition: qcursor.cpp:224
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:65
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ Enter
Definition: qcoreevent.h:82
@ Leave
Definition: qcoreevent.h:83
@ MouseMove
Definition: qcoreevent.h:76
The QFontMetrics class provides font metrics information.
Definition: qfontmetrics.h:56
QRect boundingRect(QChar) const
QString elidedText(const QString &text, Qt::TextElideMode mode, int width, int flags=0) const
QScreen * primaryScreen
the primary (or default) screen of the application.
static QStyleHints * styleHints()
QString platformName
The name of the underlying platform plugin.
Qt::LayoutDirection layoutDirection
the default layout direction for this application
static QScreen * screenAt(const QPoint &point)
static QList< QScreen * > screens()
static QPlatformIntegration * platformIntegration()
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
qsizetype length() const noexcept
Definition: qlist.h:416
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
T & last()
Definition: qlist.h:646
qsizetype count() const noexcept
Definition: qlist.h:415
T & first()
Definition: qlist.h:643
The QListWidget class provides an item-based list widget.
Definition: qlistwidget.h:188
The QMainWindow class provides a main application window.\inmodule QtWidgets.
Definition: qmainwindow.h:61
The QMargins class defines the four margins of a rectangle.
Definition: qmargins.h:52
The QMenuBar class provides a horizontal menu bar.
Definition: qmenubar.h:56
QAction * addMenu(QMenu *menu)
Definition: qmenubar.cpp:789
void setNativeMenuBar(bool nativeMenuBar)
Definition: qmenubar.cpp:1802
QRect actionGeometry(QAction *) const
Definition: qmenubar.cpp:1538
The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
Definition: qmenu.h:62
bool isTearOffEnabled() const
Definition: qmenu.cpp:2100
QString title
The title of the menu.
Definition: qmenu.h:68
QAction * exec()
Definition: qmenu.cpp:2602
QSize sizeHint() const override
Definition: qmenu.cpp:2263
void triggered(QAction *action)
QPlatformMenu * platformMenu()
Definition: qmenu.cpp:3698
void setTearOffEnabled(bool)
Definition: qmenu.cpp:2086
int columnCount() const
Definition: qmenu.cpp:2237
void setActiveAction(QAction *act)
Definition: qmenu.cpp:2174
void paintEvent(QPaintEvent *) override
Definition: qmenu.cpp:2730
void hideTearOffMenu()
Definition: qmenu.cpp:2157
void aboutToShow()
QRect actionGeometry(QAction *) const
Definition: qmenu.cpp:2255
void clear()
Definition: qmenu.cpp:2219
void popup(const QPoint &pos, QAction *at=nullptr)
Definition: qmenu.cpp:2304
bool isTearOffMenuVisible() const
Definition: qmenu.cpp:2112
void aboutToHide()
void showTearOffMenu()
Definition: qmenu.cpp:2146
QAction * defaultAction() const
Definition: qmenu.cpp:2068
QAction * addSeparator()
Definition: qmenu.cpp:1915
void setTitle(const QString &title)
Definition: qmenu.cpp:1101
QAction * addMenu(QMenu *menu)
Definition: qmenu.cpp:1871
QAction * activeAction() const
Definition: qmenu.cpp:2187
void setDefaultAction(QAction *)
Definition: qmenu.cpp:2058
void setToolTipsVisible(bool visible)
Definition: qmenu.cpp:3763
void addAction(QAction *action)
Definition: qwidget.cpp:3129
QAction * menuAction() const
Definition: qmenu.cpp:1073
int startTimer(int interval, Qt::TimerType timerType=Qt::CoarseTimer)
Definition: qobject.cpp:1765
QObject * parent() const
Definition: qobject.h:409
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
friend class QWidget
Definition: qobject.h:445
void deleteLater()
Definition: qobject.cpp:2319
The QPaintEvent class contains event parameters for paint events. \inmodule QtGui.
Definition: qevent.h:539
static QString removeMnemonics(const QString &original)
T * data() const
Definition: qpointer.h:76
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition: qscreen.h:68
QRect availableGeometry
the screen's available geometry in pixels
Definition: qscreen.h:82
QRect geometry
the screen's geometry in pixels
Definition: qscreen.h:81
Qt::ScreenOrientation orientation
the screen orientation
Definition: qscreen.h:98
The QShowEvent class provides an event that is sent when a widget is shown.
Definition: qevent.h:647
The QString class provides a Unicode character string.
Definition: qstring.h:388
QString & fill(QChar c, qsizetype size=-1)
Definition: qstring.cpp:5973
bool isEmpty() const
Definition: qstring.h:1216
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition: qstring.cpp:6263
static QString number(int, int base=10)
Definition: qstring.cpp:7538
QString trimmed() const &
Definition: qstring.h:623
@ State_None
Definition: qstyle.h:102
@ CT_Menu
Definition: qstyle.h:591
virtual QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w=nullptr) const =0
@ SH_Menu_Scrollable
Definition: qstyle.h:649
@ SH_Menu_AllowActiveAndDisabled
Definition: qstyle.h:633
@ SH_Menu_SubMenuDontStartSloppyOnLeave
Definition: qstyle.h:731
@ SH_Menu_SubMenuSloppyCloseTimeout
Definition: qstyle.h:729
virtual int styleHint(StyleHint stylehint, const QStyleOption *opt=nullptr, const QWidget *widget=nullptr, QStyleHintReturn *returnData=nullptr) const =0
@ PM_MenuVMargin
Definition: qstyle.h:488
@ PM_MenuPanelWidth
Definition: qstyle.h:489
@ PM_MenuTearoffHeight
Definition: qstyle.h:490
@ PM_MenuHMargin
Definition: qstyle.h:487
@ PM_SubMenuOverlap
Definition: qstyle.h:561
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option=nullptr, const QWidget *widget=nullptr) const =0
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:75
QStyle::State state
Definition: qstyleoption.h:95
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:367
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:58
void setSingleShot(bool singleShot)
Definition: qtimer.cpp:730
void start(int msec)
Definition: qtimer.cpp:259
void setInterval(int msec)
Definition: qtimer.cpp:757
bool singleShot
whether the timer is a single-shot timer
Definition: qtimer.h:60
void timeout(QPrivateSignal)
The QToolBar class provides a movable panel that contains a set of controls.
Definition: qtoolbar.h:59
QRect actionGeometry(QAction *action) const
Definition: qtoolbar.cpp:815
void addAction(QAction *action)
Definition: qwidget.cpp:3129
The QToolButton class provides a quick-access button to commands or options, usually used inside a QT...
Definition: qtoolbutton.h:56
static QString text()
Definition: qtooltip.cpp:539
The QWidgetAction class extends QAction by an interface for inserting custom widgets into action base...
Definition: qwidgetaction.h:53
void setDefaultWidget(QWidget *w)
QWidget * window() const
Definition: qwidget.cpp:4319
void setGeometry(int x, int y, int w, int h)
Definition: qwidget.h:919
Qt::LayoutDirection layoutDirection
the layout direction for this widget.
Definition: qwidget.h:204
void setParent(QWidget *parent)
Definition: qwidget.cpp:10512
void setMinimumSize(const QSize &)
Definition: qwidget.h:865
bool isHidden() const
Definition: qwidget.h:910
void setEnabled(bool)
Definition: qwidget.cpp:3368
QRect geometry
the geometry of the widget relative to its parent and excluding the window frame
Definition: qwidget.h:140
int width
the width of the widget excluding any window frame
Definition: qwidget.h:148
void setMouseTracking(bool enable)
Definition: qwidget.h:886
QWidget * childAt(int x, int y) const
Definition: qwidget.h:831
QPoint pos
the position of the widget within its parent widget
Definition: qwidget.h:145
bool close()
Definition: qwidget.cpp:8468
void move(int x, int y)
Definition: qwidget.h:913
QFontMetrics fontMetrics() const
Definition: qwidget.h:880
void hide()
Definition: qwidget.cpp:8078
int minimumWidth
the widget's minimum width in pixels
Definition: qwidget.h:157
int height
the height of the widget excluding any window frame
Definition: qwidget.h:149
QList< QAction * > actions() const
Definition: qwidget.cpp:3219
QRect rect
the internal geometry of the widget excluding any window frame
Definition: qwidget.h:150
void setLayoutDirection(Qt::LayoutDirection direction)
Definition: qwidget.cpp:4885
void show()
Definition: qwidget.cpp:7825
int x
the x coordinate of the widget relative to its parent including any window frame
Definition: qwidget.h:143
QWindow * windowHandle() const
Definition: qwidget.cpp:2495
void setFixedWidth(int w)
Definition: qwidget.cpp:4161
void setWindowTitle(const QString &)
Definition: qwidget.cpp:6119
bool event(QEvent *event) override
Definition: qwidget.cpp:8772
QStyle * style() const
Definition: qwidget.cpp:2612
void resize(int w, int h)
Definition: qwidget.h:916
QString windowTitle
the window title (caption)
Definition: qwidget.h:185
bool underMouse() const
Definition: qwidget.h:892
QPointF mapTo(const QWidget *, const QPointF &) const
bool isWindow() const
Definition: qwidget.h:844
QScreen * screen() const
Definition: qwidget.cpp:2508
void activateWindow()
Definition: qwidget.cpp:12708
void setStyleSheet(const QString &styleSheet)
Definition: qwidget.cpp:2567
QMargins contentsMargins() const
The contentsMargins function returns the widget's contents margins.
Definition: qwidget.cpp:7609
virtual void showEvent(QShowEvent *event)
Definition: qwidget.cpp:9982
bool isVisible() const
Definition: qwidget.h:907
QPointF mapFromGlobal(const QPointF &) const
void addAction(QAction *action)
Definition: qwidget.cpp:3129
The QWindow class represents a window in the underlying windowing system.
Definition: qwindow.h:99
void showEvent(QShowEvent *e) override
Definition: tst_qmenu.cpp:889
void timerEvent(QTimerEvent *e) override
Definition: tst_qmenu.cpp:898
void onStatusTipTimer()
Definition: tst_qmenu.cpp:613
void onActivated(QAction *)
Definition: tst_qmenu.cpp:272
void onStatusMessageChanged(const QString &)
Definition: tst_qmenu.cpp:278
void initTestCase()
Definition: tst_qmenu.cpp:185
void init()
Definition: tst_qmenu.cpp:212
void deleteAction(QAction *a)
Definition: tst_qmenu.cpp:144
void cleanupTestCase()
Definition: tst_qmenu.cpp:196
void onHighlighted(QAction *)
Definition: tst_qmenu.cpp:266
QPushButton
[1]
#define T(x)
Definition: main.cpp:42
QOpenGLWidget * widget
[1]
b clear()
QString str
[2]
QPushButton * button
[2]
bool focus
[0]
double e
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QCOMPARE(spy.count(), 1)
QStyleOptionButton opt
const QStyleOptionButton * btn
[3]
qApp setStyleSheet("QPushButton { color: white }")
[21]
Widget * createWidget(const char *name, QWidget *parent=nullptr)
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT const char * currentTestFunction()
Definition: qtestcase.cpp:2749
Q_GUI_EXPORT bool qWaitForWindowActive(QWindow *window, int timeout=5000)
Q_GUI_EXPORT bool qWaitForWindowExposed(QWindow *window, int timeout=5000)
void mouseMove(QWindow *window, QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:175
void mouseRelease(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:163
void mouseClick(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:167
void mousePress(QWindow *window, Qt::MouseButton button, Qt::KeyboardModifiers stateKey=Qt::KeyboardModifiers(), QPoint pos=QPoint(), int delay=-1)
Definition: qtestmouse.h:159
Q_CORE_EXPORT void qWait(int ms)
@ CTRL
Definition: qnamespace.h:1096
@ LeftButton
Definition: qnamespace.h:83
@ RightButton
Definition: qnamespace.h:84
@ LeftToRight
Definition: qnamespace.h:1463
@ RightToLeft
Definition: qnamespace.h:1464
@ TextSingleLine
Definition: qnamespace.h:195
ScreenOrientation
Definition: qnamespace.h:296
@ LandscapeOrientation
Definition: qnamespace.h:299
@ PortraitOrientation
Definition: qnamespace.h:298
@ UI_AnimateTooltip
Definition: qnamespace.h:1171
@ UI_AnimateMenu
Definition: qnamespace.h:1168
@ UI_FadeTooltip
Definition: qnamespace.h:1172
@ Key_Escape
Definition: qnamespace.h:684
@ Key_C
Definition: qnamespace.h:574
@ Key_Return
Definition: qnamespace.h:688
@ Key_Right
Definition: qnamespace.h:700
@ Key_Enter
Definition: qnamespace.h:689
@ Key_K
Definition: qnamespace.h:582
@ Key_X
Definition: qnamespace.h:595
@ Key_Up
Definition: qnamespace.h:699
@ Key_Down
Definition: qnamespace.h:701
@ Key_V
Definition: qnamespace.h:593
@ Key_J
Definition: qnamespace.h:581
@ Key_Home
Definition: qnamespace.h:696
@ Key_F
Definition: qnamespace.h:577
@ Key_S
Definition: qnamespace.h:590
@ Key_E
Definition: qnamespace.h:576
@ Key_End
Definition: qnamespace.h:697
@ ControlModifier
Definition: qnamespace.h:1076
@ NoModifier
Definition: qnamespace.h:1074
@ AltModifier
Definition: qnamespace.h:1077
@ AA_DontUseNativeMenuBar
Definition: qnamespace.h:456
@ CaseInsensitive
Definition: qnamespace.h:1283
@ QueuedConnection
Definition: qnamespace.h:1307
QTextStream & center(QTextStream &stream)
@ FramelessWindowHint
Definition: qnamespace.h:250
@ X11BypassWindowManagerHint
Definition: qnamespace.h:249
@ ElideRight
Definition: qnamespace.h:215
def cm(ctx, *output)
action
Definition: devices.py:78
#define QString()
Definition: parse-defines.h:51
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld init[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
void
Definition: png.h:1080
#define QByteArrayLiteral(str)
Definition: qbytearray.h:80
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_DEPRECATED
#define QT_WARNING_PUSH
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter * sub
unsigned int uint
Definition: qglobal.h:334
Q_WIDGETS_EXPORT bool qt_tab_all_widgets()
@ text
#define qWarning
Definition: qlogging.h:179
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
const GLfloat * m
GLuint64 key
GLboolean r
[2]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLdouble GLdouble GLdouble GLdouble top
GLenum GLenum GLsizei count
GLdouble GLdouble right
GLint GLenum GLsizei GLsizei GLsizei GLint border
GLfloat GLfloat f
GLint GLsizei width
GLint left
GLint GLint bottom
struct _cl_event * event
Definition: qopenglext.h:2998
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: qopenglext.h:12395
GLuint GLuint GLuint GLuint arg1
Definition: qopenglext.h:6221
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
Definition: qopenglext.h:6223
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: qopenglext.h:6222
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: qopenglext.h:12395
SSL_CTX int(*) void arg)
#define QStringLiteral(str)
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QTRY_COMPARE_WITH_TIMEOUT(expr, expected, timeout)
Definition: qtestcase.h:208
#define QEXPECT_FAIL(dataIndex, comment, mode)
Definition: qtestcase.h:224
#define QTRY_COMPARE(expr, expected)
Definition: qtestcase.h:214
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define QTRY_VERIFY(expr)
Definition: qtestcase.h:196
#define QVERIFY2(statement, description)
Definition: qtestcase.h:76
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define slots
Definition: qtmetamacros.h:76
#define QWIDGETSIZE_MAX
Definition: qwidget.h:951
QWidget * win
Definition: settings.cpp:53
QScreen * screen
[1]
Definition: main.cpp:76
QIcon icon
[15]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QPushButton * pushButton
QObject::connect nullptr
QTimer * timer
[3]
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
edit hide()
aWidget window() -> setWindowTitle("New Window Title")
[2]
QMenu menu
[5]
QAction * at
QMenuBar * menuBar
[0]
MenuMetrics(const QMenu *menu)
Definition: tst_qmenu.cpp:66
int tearOffHeight
Definition: tst_qmenu.cpp:64
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:53
Definition: main.cpp:38
const int columnCount
Definition: testtable2.cpp:31
#define main
[0]
void compare(Input input, FnUnderTest fn_under_test, const QByteArray &output)
Q_DECLARE_METATYPE(Qt::Key)
void tst_qmenu_QTBUG_37933_ampersands()
QAction * triggered
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent