summaryrefslogtreecommitdiffstats
path: root/tests/auto/qmenubar/tst_qmenubar.cpp
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /tests/auto/qmenubar/tst_qmenubar.cpp
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tests/auto/qmenubar/tst_qmenubar.cpp')
-rw-r--r--tests/auto/qmenubar/tst_qmenubar.cpp1766
1 files changed, 1766 insertions, 0 deletions
diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp
new file mode 100644
index 0000000000..6e12d7b7dc
--- /dev/null
+++ b/tests/auto/qmenubar/tst_qmenubar.cpp
@@ -0,0 +1,1766 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qapplication.h>
+#include <qmainwindow.h>
+#include <qmenubar.h>
+#ifdef QT3_SUPPORT
+#include <q3popupmenu.h>
+#endif
+#include <qstyle.h>
+#include <qwindowsstyle.h>
+#include <qdesktopwidget.h>
+#include <qaction.h>
+#include <qstyleoption.h>
+
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+
+#include <qobject.h>
+
+#include "../../shared/util.h"
+
+QT_FORWARD_DECLARE_CLASS(QMainWindow)
+
+#include <qmenubar.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class QtTestSlot : public QObject
+{
+ Q_OBJECT
+
+public:
+ QtTestSlot( QObject* parent = 0 ): QObject( parent ) { clear(); };
+ virtual ~QtTestSlot() {};
+
+ void clear() { sel_count = 0; };
+ uint selCount() { return sel_count; };
+
+public slots:
+ void selected() { sel_count++; };
+
+private:
+ uint sel_count;
+};
+
+class Menu : public QMenu
+{
+ Q_OBJECT
+ public slots:
+ void addActions()
+ {
+ //this will change the geometry of the menu
+ addAction("action1");
+ addAction("action2");
+ }
+};
+
+class tst_QMenuBar : public QObject
+{
+ Q_OBJECT
+public:
+ tst_QMenuBar();
+ virtual ~tst_QMenuBar();
+
+#ifdef QT3_SUPPORT
+ void initSimpleMenubar();
+#endif
+ void initSimpleMenubar_noQt3();
+
+#ifdef QT3_SUPPORT
+ void initComplexMenubar();
+#endif
+ void initComplexMenubar_noQt3();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+private slots:
+ void getSetCheck();
+
+ void clear_noQt3();
+ void removeItemAt_noQt3();
+ void removeItemAt_noQt3_data();
+ void removeItem_noQt3_data();
+ void removeItem_noQt3();
+ void count_noQt3();
+ void insertItem_QString_QObject_noQt3();
+ void accel_noQt3();
+ void activatedCount_noQt3();
+ void allowActiveAndDisabled();
+#ifdef QT3_SUPPORT
+ void clear();
+ void removeItemAt_data();
+ void removeItemAt();
+ void removeItem_data();
+ void removeItem();
+ void count();
+ void insertItem_QString_QObject();
+ void accel();
+ void activatedCount();
+#endif
+
+ void check_accelKeys();
+ void check_cursorKeys1();
+ void check_cursorKeys2();
+ void check_cursorKeys3();
+
+ void check_homeKey();
+ void check_endKey();
+#ifdef QT3_SUPPORT
+ void check_escKey();
+#endif
+ void check_escKey_noQt3();
+
+// void check_mouse1_data();
+// void check_mouse1();
+// void check_mouse2_data();
+// void check_mouse2();
+
+ void check_altPress();
+ void check_shortcutPress();
+ void check_menuPosition();
+ void task223138_triggered();
+ void task256322_highlight();
+ void menubarSizeHint();
+ void taskQTBUG4965_escapeEaten();
+ void taskQTBUG11823_crashwithInvisibleActions();
+
+#if defined(QT3_SUPPORT)
+ void indexBasedInsertion_data();
+ void indexBasedInsertion();
+#endif
+
+protected slots:
+#ifdef QT3_SUPPORT
+ void onActivated( int );
+#endif
+ void onActivated_noQt3( QAction*);
+
+private:
+
+ void initTestCase_noQt3();
+
+ QtTestSlot *menu1;
+ QtTestSlot *menu2;
+ QtTestSlot *menu3;
+ QtTestSlot *menu4;
+
+ QtTestSlot *item1_A;
+ QtTestSlot *item1_B;
+ QtTestSlot *item2_C;
+ QtTestSlot *item2_D;
+ QtTestSlot *item2_E;
+ QtTestSlot *item2_F;
+ QtTestSlot *item2_G;
+ QtTestSlot *item2_H;
+
+ void resetSlots();
+ void resetCount();
+
+ void reset() { resetSlots(); resetCount(); };
+
+#ifdef QT3_SUPPORT
+ int last_accel_id;
+#endif
+ QAction* last_accel_id_Qt4;
+ int activated_count;
+
+#ifdef QT3_SUPPORT
+ int idAccel;
+ int idAccel1;
+#endif
+ QAction *action;
+ QAction *action1;
+ QMainWindow *mw;
+ QMenuBar *mb;
+#ifdef QT3_SUPPORT
+ Q3PopupMenu *pm1;
+ Q3PopupMenu *pm2;
+#endif
+ QMenu *pm1_Qt4;
+ QMenu *pm2_Qt4;
+};
+
+// Testing get/set functions
+void tst_QMenuBar::getSetCheck()
+{
+ QMenuBar obj1;
+ // QAction * QMenuBar::activeAction()
+ // void QMenuBar::setActiveAction(QAction *)
+ QAction *var1 = new QAction(0);
+ obj1.setActiveAction(var1);
+ QCOMPARE(var1, obj1.activeAction());
+ obj1.setActiveAction((QAction *)0);
+ QCOMPARE((QAction *)0, obj1.activeAction());
+ delete var1;
+}
+
+////
+
+
+
+#include <qcursor.h>
+
+const int RESET = 0;
+
+/*!
+ Test plan:
+ insertItem (all flavours and combinations)
+ removing menu items
+ clearing the menu
+
+ check the common behaviour + emitted signals for:
+ accelerator keys
+ navigating tru the menu and then pressing ENTER
+ mouse clicks
+ mouse drags
+ combinations of key + mouse (if possible)
+ checked / unckecked state of menu options
+ active / inactive state
+
+ Can't test these without pixmap comparison...
+ show and hide
+ icons in a menu
+ pixmaps in a menu
+
+*/
+
+tst_QMenuBar::tst_QMenuBar()
+
+{
+ QApplication::setEffectEnabled(Qt::UI_AnimateMenu, false);
+
+
+ activated_count = 0;
+ mb = 0;
+#ifdef QT3_SUPPORT
+ pm1 = 0;
+ pm2 = 0;
+ last_accel_id = RESET;
+#endif
+ pm1_Qt4 = 0;
+ pm2_Qt4 = 0;
+ last_accel_id_Qt4 = 0;
+}
+
+tst_QMenuBar::~tst_QMenuBar()
+{
+ //delete mw; //#### cannot do that AFTER qapplication was destroyed!
+ mw = 0;
+}
+
+void tst_QMenuBar::initTestCase()
+{
+#ifdef QT3_SUPPORT
+ // create a default mainwindow
+ // If you run a widget test, this will be replaced in the testcase by the
+ // widget under test
+ mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint);
+ mb = new QMenuBar( mw, "menubar" );
+ connect( mb, SIGNAL(activated(int)), this, SLOT(onActivated(int)) );
+
+ initSimpleMenubar();
+
+ qApp->setMainWidget( mw );
+ mw->show();
+ qApp->setActiveWindow(mw);
+
+ menu1 = new QtTestSlot( mw );
+ menu2 = new QtTestSlot( mw );
+ menu3 = new QtTestSlot( mw );
+ menu4 = new QtTestSlot( mw );
+ item1_A = new QtTestSlot( mw );
+ item1_B = new QtTestSlot( mw );
+ item2_C = new QtTestSlot( mw );
+ item2_D = new QtTestSlot( mw );
+ item2_E = new QtTestSlot( mw );
+ item2_F = new QtTestSlot( mw );
+ item2_G = new QtTestSlot( mw );
+ item2_H = new QtTestSlot( mw );
+#else
+ initTestCase_noQt3();
+#endif
+}
+
+void tst_QMenuBar::initTestCase_noQt3()
+{
+ // create a default mainwindow
+ // If you run a widget test, this will be replaced in the testcase by the
+ // widget under test
+ mw = new QMainWindow(0, Qt::X11BypassWindowManagerHint);
+ mb = new QMenuBar( mw );
+ connect( mb, SIGNAL(triggered(QAction *)), this, SLOT(onActivated_noQt3(QAction *)) );
+
+ initSimpleMenubar_noQt3();
+ mw->show();
+ QTest::qWaitForWindowShown(mw);
+ mw->activateWindow();
+
+ menu1 = new QtTestSlot( mw );
+ menu2 = new QtTestSlot( mw );
+ menu3 = new QtTestSlot( mw );
+ menu4 = new QtTestSlot( mw );
+ item1_A = new QtTestSlot( mw );
+ item1_B = new QtTestSlot( mw );
+ item2_C = new QtTestSlot( mw );
+ item2_D = new QtTestSlot( mw );
+ item2_E = new QtTestSlot( mw );
+ item2_F = new QtTestSlot( mw );
+ item2_G = new QtTestSlot( mw );
+ item2_H = new QtTestSlot( mw );
+}
+
+
+void tst_QMenuBar::cleanupTestCase()
+{
+ delete mw;
+}
+
+#if defined(QT3_SUPPORT)
+void tst_QMenuBar::initSimpleMenubar()
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1;
+ pm1 = new Q3PopupMenu( mb );
+ idAccel = pm1->insertItem( "menu1", 123 );
+// pm->setAccel( ALT + Key_A, idAccel );
+ pm1->setAccel( Qt::CTRL + Qt::Key_A, idAccel );
+ mb->insertItem( "&accel", pm1 );
+ connect( pm1, SIGNAL(activated(int)), this, SLOT(onActivated(int)));
+
+ delete pm2;
+ pm2 = new Q3PopupMenu( mb );
+// idAccel1 = pm2->insertItem( "&Open...", this, SLOT(onActivated(int)), Qt::Key_O, 456 );
+ idAccel1 = pm2->insertItem( "&Open...", 0, 0, Qt::Key_O, 456 );
+ connect(pm2, SIGNAL(activated(int)), this, SLOT(onActivated(int)));
+ mb->insertItem( "accel1", pm2 );
+
+ mb->show();
+ qApp->syncX();
+ qApp->processEvents();
+}
+#endif
+
+void tst_QMenuBar::initSimpleMenubar_noQt3()
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1_Qt4;
+ pm1_Qt4 = mb->addMenu("&accel");
+ action = pm1_Qt4->addAction( "menu1" );
+ action->setShortcut(QKeySequence("ALT+A"));
+ action->setShortcut(QKeySequence("CTRL+A"));
+
+
+ connect( pm1_Qt4, SIGNAL(triggered(QAction*)), this, SLOT(onActivated_noQt3(QAction*)));
+
+ delete pm2_Qt4;
+ pm2_Qt4 = mb->addMenu("accel1");
+
+ action1 = pm2_Qt4->addAction( "&Open..." );
+ action1->setShortcut(Qt::Key_O);
+ connect(pm2_Qt4, SIGNAL(triggered(QAction*)), this, SLOT(onActivated_noQt3(QAction*)));
+
+ mb->show();
+ qApp->syncX();
+ qApp->processEvents();
+}
+
+void tst_QMenuBar::init()
+{
+ resetSlots();
+ resetCount();
+}
+
+void tst_QMenuBar::resetSlots()
+{
+ menu1->clear();
+ menu2->clear();
+ menu3->clear();
+ menu4->clear();
+ item1_A->clear();
+ item1_B->clear();
+ item2_C->clear();
+ item2_D->clear();
+ item2_E->clear();
+ item2_F->clear();
+ item2_G->clear();
+ item2_H->clear();
+}
+
+void tst_QMenuBar::resetCount()
+{
+#ifdef QT3_SUPPORT
+ last_accel_id = RESET;
+#endif
+ last_accel_id_Qt4 = 0;
+ activated_count = 0;
+}
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::onActivated( int i )
+{
+ last_accel_id = i;
+ activated_count++;
+// printf( QString("acceleratorId: %1, count: %1\n").arg( i ).arg(activated_count) );
+}
+#endif
+
+void tst_QMenuBar::onActivated_noQt3( QAction* action )
+{
+ last_accel_id_Qt4 = action;
+ activated_count++;
+// printf( QString("acceleratorId: %1, count: %1\n").arg( i ).arg(activated_count) );
+}
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::accel()
+{
+#ifdef Q_WS_MAC
+ QSKIP("On Mac, native key events are needed to test menu action activation", SkipAll);
+#endif
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar();
+// QTest::keyClick( 0, Qt::Key_A, AltKey );
+ QTest::keyClick( 0, Qt::Key_A, Qt::ControlModifier );
+ QTest::qWait(300);
+
+ QCOMPARE( last_accel_id, idAccel );
+}
+#endif //QT3_SUPPORT
+
+void tst_QMenuBar::accel_noQt3()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("On Mac/WinCE, native key events are needed to test menu action activation", SkipAll);
+#endif
+#ifdef Q_OS_SYMBIAN
+ QSKIP("On Symbian OS, native key events are needed to test menu action activation", SkipAll);
+#endif
+
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar_noQt3();
+// QTest::keyClick( 0, Qt::Key_A, AltKey );
+ QTest::keyClick( 0, Qt::Key_A, Qt::ControlModifier );
+ QTest::qWait(300);
+
+ QCOMPARE( last_accel_id_Qt4, action );
+}
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::activatedCount()
+{
+#ifdef Q_WS_MAC
+ QSKIP("On Mac, native key events are needed to test menu action activation", SkipAll);
+#endif
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar();
+
+ QTest::keyClick( 0, Qt::Key_A, Qt::ControlModifier );
+//wait(5000);
+ QCOMPARE( activated_count, 2 ); //1 from the popupmenu and 1 from the menubar
+}
+#endif //QT3_SUPPORT
+
+void tst_QMenuBar::activatedCount_noQt3()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("On Mac/WinCE, native key events are needed to test menu action activation", SkipAll);
+#endif
+ // create a popup menu with menu items set the accelerators later...
+ initSimpleMenubar_noQt3();
+
+ QTest::keyClick( 0, Qt::Key_A, Qt::ControlModifier );
+//wait(5000);
+ QCOMPARE( activated_count, 2 ); //1 from the popupmenu and 1 from the menubar
+}
+
+void tst_QMenuBar::clear_noQt3()
+{
+ mb->clear();
+ QVERIFY( (uint) mb->actions().size() == 0 );
+
+ mb->clear();
+ for (uint i=0; i<10; i++) {
+ QMenu *menu = mb->addMenu( QString("Menu %1"));
+ for (uint k=0; k<i; k++)
+ menu->addAction( QString("Item %1"));
+ QCOMPARE( (uint) mb->actions().size(), (uint)i+1 );
+ }
+ QCOMPARE( (uint) mb->actions().size(), 10u );
+
+ mb->clear();
+ QVERIFY( (uint) mb->actions().size() == 0 );
+}
+
+void tst_QMenuBar::count_noQt3()
+{
+ mb->clear();
+ QVERIFY( mb->actions().size() == 0 );
+
+ for (uint i=0; i<10; i++) {
+ mb->addAction( QString("Menu %1"));
+ QCOMPARE( (uint) mb->actions().size(), (uint) i+1 );
+ }
+}
+
+void tst_QMenuBar::removeItem_noQt3_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+// Basically the same test as removeItemAt, except that we remember and remove id's.
+void tst_QMenuBar::removeItem_noQt3()
+{
+ mb->clear();
+
+ QMenu *pm;
+ pm = new QMenu( "stuff", mb );
+ pm->setTitle("Menu 1");
+ pm->addAction( QString("Item 10") );
+ QAction* action1 = mb->addMenu( pm );
+
+ pm = new QMenu( mb );
+ pm->setTitle("Menu 2");
+ pm->addAction( QString("Item 20") );
+ pm->addAction( QString("Item 21") );
+ QAction *action2 = mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 3", mb );
+ pm->addAction( QString("Item 30") );
+ pm->addAction( QString("Item 31") );
+ pm->addAction( QString("Item 32") );
+ QAction *action3 = mb->addMenu( pm );
+
+ QList<QAction *> menuBarActions = mb->actions();
+
+ QCOMPARE( action1->text(), QString("Menu 1") );
+ QCOMPARE( action2->text(), QString("Menu 2") );
+ QCOMPARE( action3->text(), QString("Menu 3") );
+
+ QVERIFY( menuBarActions.at(0) == action1 );
+ QVERIFY( menuBarActions.at(1) == action2 );
+ QVERIFY( menuBarActions.at(2) == action3 );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ switch (removeIndex )
+ {
+ case 0: {
+ mb->removeAction(action1);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ }
+ break;
+ case 1: {
+ mb->removeAction(action2);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ }
+ break;
+ case 2: {
+ mb->removeAction(action3);
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") );
+ }
+ break;
+ }
+ QList<QAction *> menuBarActions2 = mb->actions();
+ QVERIFY( menuBarActions2.size() == 2 );
+}
+
+void tst_QMenuBar::removeItemAt_noQt3_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+void tst_QMenuBar::removeItemAt_noQt3()
+{
+ mb->clear();
+
+ QMenu *pm;
+ pm = new QMenu("Menu 1", mb);
+ pm->addAction( QString("Item 10") );
+ mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 2", mb );
+ pm->addAction( QString("Item 20") );
+ pm->addAction( QString("Item 21") );
+ mb->addMenu( pm );
+
+ pm = new QMenu( "Menu 3", mb );
+ pm->addAction( QString("Item 30") );
+ pm->addAction( QString("Item 31") );
+ pm->addAction( QString("Item 32") );
+ mb->addMenu( pm );
+
+ QList<QAction *> menuBarActions = mb->actions();
+
+ QCOMPARE( menuBarActions.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions.at(1)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions.at(2)->text(), QString("Menu 3") );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ mb->removeAction(menuBarActions.at(removeIndex));
+ QList<QAction *> menuBarActions2 = mb->actions();
+ switch (removeIndex )
+ {
+ case 0:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 2") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ break;
+ case 1:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 3") );
+ break;
+ case 2:
+ QCOMPARE( menuBarActions2.at(0)->text(), QString("Menu 1") );
+ QCOMPARE( menuBarActions2.at(1)->text(), QString("Menu 2") );
+ break;
+ }
+
+ QVERIFY( menuBarActions2.size() == 2 );
+}
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::clear()
+{
+ mb->clear();
+ QVERIFY( mb->count() == 0 );
+
+ mb->clear();
+ for (uint i=0; i<10; i++) {
+ Q3PopupMenu *pm = new Q3PopupMenu( mb );
+ for (uint k=0; k<i; k++)
+ pm->insertItem( QString("Item %1").arg(i*10 + k) );
+ mb->insertItem( QString("Menu %1").arg(i), pm );
+ QCOMPARE( mb->count(), (uint)i+1 );
+ }
+ QCOMPARE( mb->count(), 10u );
+
+ mb->clear();
+ QVERIFY( mb->count() == 0 );
+}
+
+void tst_QMenuBar::count()
+{
+ mb->clear();
+ QVERIFY( mb->count() == 0 );
+
+ for (uint i=0; i<10; i++) {
+ Q3PopupMenu *pm = new Q3PopupMenu( mb );
+ mb->insertItem( QString("Menu %1").arg(i), pm );
+ QCOMPARE( mb->count(), i+1 );
+ }
+}
+
+void tst_QMenuBar::removeItemAt_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+void tst_QMenuBar::removeItemAt()
+{
+ mb->clear();
+
+ Q3PopupMenu *pm;
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 10") );
+ mb->insertItem( QString("Menu 1"), pm );
+
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 20") );
+ pm->insertItem( QString("Item 21") );
+ mb->insertItem( QString("Menu 2"), pm );
+
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 30") );
+ pm->insertItem( QString("Item 31") );
+ pm->insertItem( QString("Item 32") );
+ mb->insertItem( QString("Menu 3"), pm );
+
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 1") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 2") );
+ QCOMPARE( mb->text( mb->idAt(2) ), QString("Menu 3") );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ mb->removeItemAt( removeIndex );
+ switch (removeIndex )
+ {
+ case 0:
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 2") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 3") );
+ break;
+ case 1:
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 1") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 3") );
+ break;
+ case 2:
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 1") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 2") );
+ break;
+ }
+
+ QVERIFY( mb->count() == 2 );
+}
+
+void tst_QMenuBar::removeItem_data()
+{
+ QTest::addColumn<int>("removeIndex");
+ QTest::newRow( "first" ) << 0;
+ QTest::newRow( "middle" ) << 1;
+ QTest::newRow( "last" ) << 2;
+}
+
+// Basically the same test as removeItemAt, except that we remember and remove id's.
+void tst_QMenuBar::removeItem()
+{
+ mb->clear();
+
+ Q3PopupMenu *pm;
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 10") );
+ int id1 = mb->insertItem( QString("Menu 1"), pm );
+
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 20") );
+ pm->insertItem( QString("Item 21") );
+ int id2 = mb->insertItem( QString("Menu 2"), pm );
+
+ pm = new Q3PopupMenu( mb );
+ pm->insertItem( QString("Item 30") );
+ pm->insertItem( QString("Item 31") );
+ pm->insertItem( QString("Item 32") );
+ int id3 = mb->insertItem( QString("Menu 3"), pm );
+
+ QCOMPARE( mb->text( id1 ), QString("Menu 1") );
+ QCOMPARE( mb->text( id2 ), QString("Menu 2") );
+ QCOMPARE( mb->text( id3 ), QString("Menu 3") );
+
+ QVERIFY( mb->idAt(0) == id1 );
+ QVERIFY( mb->idAt(1) == id2 );
+ QVERIFY( mb->idAt(2) == id3 );
+
+ // Ok, now that we know we have created the menu we expect, lets remove an item...
+ QFETCH( int, removeIndex );
+ switch (removeIndex )
+ {
+ case 0:
+ mb->removeItem( id1 );
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 2") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 3") );
+ break;
+ case 1:
+ mb->removeItem( id2 );
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 1") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 3") );
+ break;
+ case 2:
+ mb->removeItem( id3 );
+ QCOMPARE( mb->text( mb->idAt(0) ), QString("Menu 1") );
+ QCOMPARE( mb->text( mb->idAt(1) ), QString("Menu 2") );
+ break;
+ }
+
+ QVERIFY( mb->count() == 2 );
+}
+
+void tst_QMenuBar::initComplexMenubar() // well, complex....
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1;
+ pm1 = new Q3PopupMenu( mb, "popup1" );
+ pm1->insertItem( QString("Item A"), item1_A, SLOT(selected()), Qt::CTRL+Qt::Key_A );
+ pm1->insertItem( QString("Item B"), item1_B, SLOT(selected()), Qt::CTRL+Qt::Key_B );
+ // use the form insertItem( QString, Q3PopupMenu )
+ mb->insertItem( "Menu &1", pm1 );
+
+ delete pm2;
+ pm2 = new Q3PopupMenu( mb, "popup2" );
+ pm2->insertItem( QString("Item C"), item2_C, SLOT(selected()), Qt::CTRL+Qt::Key_C );
+ pm2->insertItem( QString("Item D"), item2_D, SLOT(selected()), Qt::CTRL+Qt::Key_D );
+ pm2->insertItem( QString("Item E"), item2_E, SLOT(selected()), Qt::CTRL+Qt::Key_E );
+ pm2->insertItem( QString("Item F"), item2_F, SLOT(selected()), Qt::CTRL+Qt::Key_F );
+ pm2->insertSeparator();
+ pm2->insertItem( QString("Item G"), item2_G, SLOT(selected()), Qt::CTRL+Qt::Key_G );
+ pm2->insertItem( QString("Item H"), item2_H, SLOT(selected()), Qt::CTRL+Qt::Key_H );
+ // use the form insertItem( QString, Q3PopupMenu )
+ mb->insertItem( "Menu &2", pm2 );
+
+ // use the form insertItem( QString, QObject, slot, keysequence )
+ mb->insertItem( QString("M&enu 3"), menu3, SLOT(selected()), Qt::ALT+Qt::Key_J );
+ mb->show();
+}
+#endif
+
+void tst_QMenuBar::initComplexMenubar_noQt3() // well, complex....
+{
+ mb->hide();
+ mb->clear();
+
+ delete pm1_Qt4;
+ pm1_Qt4 = mb->addMenu("Menu &1");
+ pm1_Qt4->addAction( QString("Item A"), item1_A, SLOT(selected()), Qt::CTRL+Qt::Key_A );
+ pm1_Qt4->addAction( QString("Item B"), item1_B, SLOT(selected()), Qt::CTRL+Qt::Key_B );
+
+ delete pm2_Qt4;
+ pm2_Qt4 = mb->addMenu("Menu &2");
+ pm2_Qt4->addAction( QString("Item C"), item2_C, SLOT(selected()), Qt::CTRL+Qt::Key_C );
+ pm2_Qt4->addAction( QString("Item D"), item2_D, SLOT(selected()), Qt::CTRL+Qt::Key_D );
+ pm2_Qt4->addAction( QString("Item E"), item2_E, SLOT(selected()), Qt::CTRL+Qt::Key_E );
+ pm2_Qt4->addAction( QString("Item F"), item2_F, SLOT(selected()), Qt::CTRL+Qt::Key_F );
+ pm2_Qt4->addSeparator();
+ pm2_Qt4->addAction( QString("Item G"), item2_G, SLOT(selected()), Qt::CTRL+Qt::Key_G );
+ pm2_Qt4->addAction( QString("Item H"), item2_H, SLOT(selected()), Qt::CTRL+Qt::Key_H );
+
+ QAction *ac = mb->addAction( QString("M&enu 3"), menu3, SLOT(selected()));
+ ac->setShortcut(Qt::ALT+Qt::Key_J);
+ mb->show();
+}
+
+
+/*
+ Check the insert functions that create menu items.
+ For the moment i only check the strings and pixmaps. The rest are special cases which are
+ used less frequently.
+*/
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::insertItem_QString_QObject()
+{
+ initComplexMenubar();
+ QCOMPARE( mb->text( mb->idAt( 0 ) ), QString("Menu &1") );
+ QCOMPARE( mb->text( mb->idAt( 1 ) ), QString("Menu &2") );
+ QCOMPARE( mb->text( mb->idAt( 2 ) ), QString("M&enu 3") );
+ QCOMPARE( mb->text( mb->idAt( 3 ) ), QString() ); // there is no menu 4!
+}
+#endif
+
+void tst_QMenuBar::insertItem_QString_QObject_noQt3()
+{
+ initComplexMenubar_noQt3();
+
+ QList<QAction *> actions = mb->actions();
+
+ QCOMPARE(actions.at(0)->text(), QString("Menu &1") );
+ QCOMPARE(actions.at(1)->text(), QString("Menu &2") );
+ QCOMPARE(actions.at(2)->text(), QString("M&enu 3") );
+ QVERIFY(actions.size() < 4); // there is no menu 4!
+}
+
+void tst_QMenuBar::check_accelKeys()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("On Mac/WinCE, native key events are needed to test menu action activation", SkipAll);
+#endif
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // start with a bogus key that shouldn't trigger anything
+ QTest::keyClick(0, Qt::Key_I, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(0, Qt::Key_A, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(0, Qt::Key_C, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(0, Qt::Key_B, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ QTest::keyClick(0, Qt::Key_D, Qt::ControlModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 1u);
+
+ QTest::keyClick(0, Qt::Key_J, Qt::AltModifier);
+ QCOMPARE(menu1->selCount(), 0u);
+ QCOMPARE(menu2->selCount(), 0u);
+ QCOMPARE(menu3->selCount(), 1u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 1u);
+ QCOMPARE(item1_B->selCount(), 1u);
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(item2_D->selCount(), 1u);
+}
+
+void tst_QMenuBar::check_cursorKeys1()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("Qt/Mac,WinCE does not use the native popups/menubar", SkipAll);
+#endif
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // start with a ALT + 1 that activates the first popupmenu
+ QTest::keyClick( 0, Qt::Key_1, Qt::AltModifier );
+ // the Popupmenu should be visible now
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+
+ // Simulate a cursor key down click
+ QTest::keyClick( 0, Qt::Key_Down );
+ // and an Enter key
+ QTest::keyClick( 0, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called
+ QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+}
+
+void tst_QMenuBar::check_cursorKeys2()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("Qt/Mac,WinCE does not use the native popups/menubar", SkipAll);
+#endif
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // select popupmenu2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some cursor keys
+ QTest::keyClick( 0, Qt::Key_Left );
+ QTest::keyClick( 0, Qt::Key_Down );
+ QTest::keyClick( 0, Qt::Key_Right );
+ QTest::keyClick( 0, Qt::Key_Down );
+ // and an Enter key
+ QTest::keyClick( 0, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been caled
+ QCOMPARE(item1_B->selCount(), 0u); // and this should have been called by a signal ow
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 1u);
+}
+
+/*!
+ If a popupmenu is active you can use Left to move to the menu to the left of it.
+*/
+void tst_QMenuBar::check_cursorKeys3()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("Qt/Mac,WinCE does not use the native popups/menubar", SkipAll);
+#endif
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // select Popupmenu 2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick( 0, Qt::Key_Left );
+ QTest::keyClick( 0, Qt::Key_Down );
+ // and press ENTER
+ QTest::keyClick( 0, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u); // this shouldn't have been called
+ QCOMPARE(item1_B->selCount(), 1u); // and this should have been called by a signal now
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+}
+
+/*!
+ If a popupmenu is active you can use home to go quickly to the first item in the menu.
+*/
+void tst_QMenuBar::check_homeKey()
+{
+ // I'm temporarily shutting up this testcase.
+ // Seems like the behaviour i'm expecting isn't ok.
+ QVERIFY( TRUE );
+ return;
+
+ QEXPECT_FAIL( "0", "Popupmenu should respond to a Home key", Abort );
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // select Popupmenu 2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick( 0, Qt::Key_Down );
+ QTest::keyClick( 0, Qt::Key_Down );
+ QTest::keyClick( 0, Qt::Key_Down );
+ QTest::keyClick( 0, Qt::Key_Home );
+ // and press ENTER
+ QTest::keyClick( 0, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+// QVERIFY2( item2_C->selCount() == 1, "Popupmenu should respond to a Home key" );
+ QCOMPARE(item2_C->selCount(), 1u);
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+ QCOMPARE(item2_E->selCount(), 0u);
+ QCOMPARE(item2_F->selCount(), 0u);
+ QCOMPARE(item2_G->selCount(), 0u);
+ QCOMPARE(item2_H->selCount(), 0u);
+}
+
+/*!
+ If a popupmenu is active you can use end to go quickly to the last item in the menu.
+*/
+void tst_QMenuBar::check_endKey()
+{
+ // I'm temporarily silenting this testcase.
+ // Seems like the behaviour i'm expecting isn't ok.
+ QVERIFY( TRUE );
+ return;
+
+ QEXPECT_FAIL( "0", "Popupmenu should respond to an End key", Abort );
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ // select Popupmenu 2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+
+ // Simulate some keys
+ QTest::keyClick( 0, Qt::Key_End );
+ // and press ENTER
+ QTest::keyClick( 0, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+// QVERIFY2( item2_H->selCount() == 1, "Popupmenu should respond to an End key" );
+ QCOMPARE(item2_H->selCount(), 1u);//, "Popupmenu should respond to an End key");
+ QCOMPARE(menu3->selCount(), 0u);
+ QCOMPARE(menu4->selCount(), 0u);
+ QCOMPARE(item1_A->selCount(), 0u);
+ QCOMPARE(item1_B->selCount(), 0u);
+ QCOMPARE(item2_C->selCount(), 0u);
+ QCOMPARE(item2_D->selCount(), 0u);
+ QCOMPARE(item2_E->selCount(), 0u);
+ QCOMPARE(item2_F->selCount(), 0u);
+ QCOMPARE(item2_G->selCount(), 0u);
+}
+
+/*!
+ If a popupmenu is active you can use esc to hide the menu and then the
+ menubar should become active.
+ If Down is pressed next the popup is activated again.
+*/
+
+#ifdef QT3_SUPPORT
+void tst_QMenuBar::check_escKey()
+{
+#ifdef Q_WS_MAC
+ QSKIP("Qt/Mac does not use the native popups/menubar", SkipAll);
+#endif
+
+ initComplexMenubar();
+
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( !pm2->isActiveWindow() );
+
+ // select Popupmenu 2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( pm2->isActiveWindow() );
+
+ // If we press ESC, the popup should disappear
+ QTest::keyClick( 0, Qt::Key_Escape );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( !pm2->isActiveWindow() );
+
+ if (!QApplication::style()->inherits("QWindowsStyle"))
+ return;
+
+ // but the menubar item should stay selected
+ QVERIFY( mb->isItemActive(mb->idAt(1)) );
+
+ // If we press Down the popupmenu should be active again
+ QTest::keyClick( 0, Qt::Key_Down );
+ QVERIFY( !pm1->isActiveWindow() );
+ QVERIFY( pm2->isActiveWindow() );
+
+ // and press ENTER
+ QTest::keyClick( pm2, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QVERIFY2( item2_C->selCount() == 1, "Expected item 2C to be selected" );
+}
+#endif
+
+void tst_QMenuBar::check_escKey_noQt3()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("Qt/Mac,WinCE does not use the native popups/menubar", SkipAll);
+#endif
+
+ initComplexMenubar_noQt3();
+
+ QVERIFY( !pm1_Qt4->isActiveWindow() );
+ QVERIFY( !pm2_Qt4->isActiveWindow() );
+
+ // select Popupmenu 2
+ QTest::keyClick( 0, Qt::Key_2, Qt::AltModifier );
+ QVERIFY( !pm1_Qt4->isActiveWindow() );
+ QVERIFY( pm2_Qt4->isActiveWindow() );
+
+ // If we press ESC, the popup should disappear
+ QTest::keyClick( 0, Qt::Key_Escape );
+ QVERIFY( !pm1_Qt4->isActiveWindow() );
+ QVERIFY( !pm2_Qt4->isActiveWindow() );
+
+ if (!QApplication::style()->inherits("QWindowsStyle"))
+ return;
+
+ // If we press Down the popupmenu should be active again
+ QTest::keyClick( 0, Qt::Key_Down );
+ QVERIFY( !pm1_Qt4->isActiveWindow() );
+ QVERIFY( pm2_Qt4->isActiveWindow() );
+
+ // and press ENTER
+ QTest::keyClick( pm2_Qt4, Qt::Key_Enter );
+ // Let's see if the correct slot is called...
+ QVERIFY2( item2_C->selCount() == 1, "Expected item 2C to be selected" );
+}
+
+
+// void tst_QMenuBar::check_mouse1_data()
+// {
+// QTest::addColumn<QString>("popup_item");
+// QTest::addColumn<int>("itemA_count");
+// QTest::addColumn<int>("itemB_count");
+
+// QTest::newRow( "A" ) << QString( "Item A Ctrl+A" ) << 1 << 0;
+// QTest::newRow( "B" ) << QString( "Item B Ctrl+B" ) << 0 << 1;
+// }
+
+// /*!
+// Check if the correct signals are emitted if we select a popupmenu.
+// */
+// void tst_QMenuBar::check_mouse1()
+// {
+// if (QSystem::curStyle() == "Motif")
+// QSKIP("This fails in Motif due to a bug in the testing framework", SkipAll);
+// QFETCH( QString, popup_item );
+// QFETCH( int, itemA_count );
+// QFETCH( int, itemB_count );
+
+// initComplexMenubar();
+// QVERIFY( !pm1->isActiveWindow() );
+// QVERIFY( !pm2->isActiveWindow() );
+
+// QTest::qWait(1000);
+// QtTestMouse mouse;
+// mouse.mouseEvent( QtTestMouse::MouseClick, mb, "Menu &1", Qt::LeftButton );
+
+// QVERIFY( pm1->isActiveWindow() );
+// QVERIFY( !pm2->isActiveWindow() );
+
+// QTest::qWait(1000);
+// mouse.mouseEvent( QtTestMouse::MouseClick, pm1, popup_item, Qt::LeftButton );
+
+// QCOMPARE(menu3->selCount(), 0u);
+// QCOMPARE(menu4->selCount(), 0u);
+// QCOMPARE(item1_A->selCount(), (uint)itemA_count); // this option should have fired
+// QCOMPARE(item1_B->selCount(), (uint)itemB_count);
+// QCOMPARE(item2_C->selCount(), 0u);
+// QCOMPARE(item2_D->selCount(), 0u);
+// QCOMPARE(item2_E->selCount(), 0u);
+// QCOMPARE(item2_F->selCount(), 0u);
+// QCOMPARE(item2_G->selCount(), 0u);
+// }
+
+// void tst_QMenuBar::check_mouse2_data()
+// {
+// QTest::addColumn<QString>("label");
+// QTest::addColumn<int>("itemA_count");
+// QTest::addColumn<int>("itemB_count");
+// QTest::addColumn<int>("itemC_count");
+// QTest::addColumn<int>("itemD_count");
+// QTest::addColumn<int>("itemE_count");
+// QTest::addColumn<int>("itemF_count");
+// QTest::addColumn<int>("itemG_count");
+// QTest::addColumn<int>("itemH_count");
+// QTest::addColumn<int>("menu3_count");
+
+// QTest::newRow( "A" ) << QString( "Menu &1/Item A Ctrl+A" ) << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "B" ) << QString( "Menu &1/Item B Ctrl+B" ) << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "C" ) << QString( "Menu &2/Item C Ctrl+C" ) << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "D" ) << QString( "Menu &2/Item D Ctrl+D" ) << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 0;
+// QTest::newRow( "E" ) << QString( "Menu &2/Item E Ctrl+E" ) << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0;
+// QTest::newRow( "F" ) << QString( "Menu &2/Item F Ctrl+F" ) << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0 << 0;
+// QTest::newRow( "G" ) << QString( "Menu &2/Item G Ctrl+G" ) << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 0;
+// QTest::newRow( "H" ) << QString( "Menu &2/Item H Ctrl+H" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0;
+// QTest::newRow( "menu 3" ) << QString( "M&enu 3" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1;
+// }
+
+// /*!
+// Check if the correct signals are emitted if we select a popupmenu.
+// This time, we use a little bit more magic from the testframework.
+// */
+// void tst_QMenuBar::check_mouse2()
+// {
+// if (QSystem::curStyle() == "Motif")
+// QSKIP("This fails in Motif due to a bug in the testing framework", SkipAll);
+// QFETCH( QString, label );
+// QFETCH( int, itemA_count );
+// QFETCH( int, itemB_count );
+// QFETCH( int, itemC_count );
+// QFETCH( int, itemD_count );
+// QFETCH( int, itemE_count );
+// QFETCH( int, itemF_count );
+// QFETCH( int, itemG_count );
+// QFETCH( int, itemH_count );
+// QFETCH( int, menu3_count );
+
+// initComplexMenubar();
+// QtTestMouse mouse;
+// mouse.click( QtTestMouse::Menu, label, Qt::LeftButton );
+
+// // check if the correct signals have fired
+// QCOMPARE(menu3->selCount(), (uint)menu3_count);
+// QCOMPARE(menu4->selCount(), 0u);
+// QCOMPARE(item1_A->selCount(), (uint)itemA_count);
+// QCOMPARE(item1_B->selCount(), (uint)itemB_count);
+// QCOMPARE(item2_C->selCount(), (uint)itemC_count);
+// QCOMPARE(item2_D->selCount(), (uint)itemD_count);
+// QCOMPARE(item2_E->selCount(), (uint)itemE_count);
+// QCOMPARE(item2_F->selCount(), (uint)itemF_count);
+// QCOMPARE(item2_G->selCount(), (uint)itemG_count);
+// QCOMPARE(item2_H->selCount(), (uint)itemH_count);
+// }
+
+void
+tst_QMenuBar::allowActiveAndDisabled()
+{
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE_WM)
+ mb->hide();
+ mb->clear();
+
+ // Task 241043 : check that second menu is activated if only
+ // disabled menu items are added
+
+ QMenu fileMenu("&File");
+ // Task 241043 : check that second menu is activated
+ // if all items are disabled
+ QAction *act = fileMenu.addAction("Disabled");
+ act->setEnabled(false);
+
+ mb->addMenu(&fileMenu);
+ QMenu disabledMenu("Disabled");
+ disabledMenu.setEnabled(false);
+ QMenu activeMenu("Active");
+ mb->addMenu(&disabledMenu);
+ mb->addMenu(&activeMenu);
+ mb->show();
+
+
+ // Here we verify that AllowActiveAndDisabled correctly skips
+ // the disabled menu entry
+ QTest::keyClick(mb, Qt::Key_F, Qt::AltModifier );
+ QTest::keyClick(&fileMenu, (Qt::Key_Right));
+ if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled))
+ QCOMPARE(mb->activeAction()->text(), disabledMenu.title());
+ else
+ QCOMPARE(mb->activeAction()->text(), activeMenu.title());
+
+ QTest::keyClick(mb, (Qt::Key_Left));
+ if (qApp->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled))
+ QCOMPARE(mb->activeAction()->text(), fileMenu.title());
+ else
+ QCOMPARE(mb->activeAction()->text(), fileMenu.title());
+
+ mb->hide();
+#endif //Q_WS_MAC
+}
+
+void tst_QMenuBar::check_altPress()
+{
+ if ( !qApp->style()->styleHint(QStyle::SH_MenuBar_AltKeyNavigation) ) {
+ QSKIP( QString( "this is not supposed to work in the %1 style. Skipping." ).
+ arg( qApp->style()->objectName() ).toAscii(), SkipAll );
+ }
+
+#ifdef QT3_SUPPORT
+ initSimpleMenubar();
+#else
+ initSimpleMenubar_noQt3();
+#endif
+
+ qApp->setActiveWindow(mw);
+ mw->setFocus();
+
+ QTest::keyClick( mw, Qt::Key_Alt );
+
+ QVERIFY( ::qobject_cast<QMenuBar *>(qApp->focusWidget()) );
+}
+
+void tst_QMenuBar::check_shortcutPress()
+{
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE_WM)
+ QSKIP("Qt/Mac,WinCE does not use the native popups/menubar", SkipAll);
+#endif
+
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+
+ qApp->setActiveWindow(mw);
+ QCOMPARE(menu3->selCount(), 0u);
+ QTest::keyClick(mw, Qt::Key_E, Qt::AltModifier);
+ QTest::qWait(200);
+ QCOMPARE(menu3->selCount(), 1u);
+ QVERIFY(!mb->activeAction());
+
+ QTest::keyClick(mw, Qt::Key_1, Qt::AltModifier );
+#ifdef QT3_SUPPORT
+ QVERIFY(pm1->isActiveWindow());
+#else
+ QVERIFY(pm1_Qt4->isActiveWindow());
+#endif
+ QTest::keyClick(mb, Qt::Key_2);
+#ifdef QT3_SUPPORT
+ QVERIFY(pm1->isActiveWindow()); // Should still be the active window
+#else
+ QVERIFY(pm1_Qt4->isActiveWindow());
+#endif
+}
+
+void tst_QMenuBar::check_menuPosition()
+{
+#ifdef Q_WS_MAC
+ QSKIP("Qt/Mac does not use the native popups/menubar", SkipAll);
+#endif
+#ifdef Q_OS_WINCE_WM
+ QSKIP("Qt/CE uses native menubar", SkipAll);
+#endif
+ Menu menu;
+#ifdef QT3_SUPPORT
+ initComplexMenubar();
+#else
+ initComplexMenubar_noQt3();
+#endif
+ menu.setTitle("&menu");
+ QRect availRect = QApplication::desktop()->availableGeometry(mw);
+ QRect screenRect = QApplication::desktop()->screenGeometry(mw);
+
+ while(menu.sizeHint().height() < (screenRect.height()*2/3)) {
+ menu.addAction("item");
+ }
+
+ QAction *menu_action = mw->menuBar()->addMenu(&menu);
+
+ qApp->setActiveWindow(mw);
+ qApp->processEvents();
+
+ //the menu should be below the menubar item
+ {
+ mw->move(availRect.topLeft());
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.bottom() + 1));
+ menu.close();
+ }
+
+ //the menu should be above the menubar item
+ {
+ mw->move(0,screenRect.bottom() - screenRect.height()/4); //just leave some place for the menubar
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.pos(), QPoint(mbItemRect.x(), mbItemRect.top() - menu.height()));
+ menu.close();
+ }
+
+ //the menu should be on the side of the menubar item and should be "stuck" to the bottom of the screen
+ {
+ mw->move(0,screenRect.y() + screenRect.height()/2); //put it in the middle
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QPoint firstPoint = QPoint(mbItemRect.right()+1, screenRect.bottom() - menu.height() + 1);
+ QPoint secondPoint = QPoint(mbItemRect.right()+1, availRect.bottom() - menu.height() + 1);
+ QVERIFY(menu.pos() == firstPoint || menu.pos() == secondPoint);
+ menu.close();
+ }
+
+ //in RTL, the menu should be stuck at the right of the action geometry
+ {
+ Qt::LayoutDirection dir = qApp->layoutDirection();
+ qApp->setLayoutDirection(Qt::RightToLeft);
+ menu.clear();
+ QObject::connect(&menu, SIGNAL(aboutToShow()), &menu, SLOT(addActions()));
+ QRect mbItemRect = mw->menuBar()->actionGeometry(menu_action);
+ mbItemRect.moveTo(mw->menuBar()->mapToGlobal(mbItemRect.topLeft()));
+ QTest::keyClick(mw, Qt::Key_M, Qt::AltModifier );
+ QVERIFY(menu.isActiveWindow());
+ QCOMPARE(menu.geometry().right(), mbItemRect.right());
+ menu.close();
+ qApp->setLayoutDirection(dir);
+ }
+
+}
+
+void tst_QMenuBar::task223138_triggered()
+{
+ qRegisterMetaType<QAction *>("QAction *");
+ //we create a window with submenus and we check that both menubar and menus get the triggered signal
+ QMainWindow win;
+ QMenu *menu = win.menuBar()->addMenu("test");
+ QAction *top = menu->addAction("toplevelaction");
+ QMenu *submenu = menu->addMenu("nested menu");
+ QAction *action = submenu->addAction("nested action");
+
+ QSignalSpy menubarSpy(win.menuBar(), SIGNAL(triggered(QAction*)));
+ QSignalSpy menuSpy(menu, SIGNAL(triggered(QAction*)));
+ QSignalSpy submenuSpy(submenu, SIGNAL(triggered(QAction*)));
+
+ //let's trigger the first action
+ top->trigger();
+
+ QCOMPARE(menubarSpy.count(), 1);
+ QCOMPARE(menuSpy.count(), 1);
+ QCOMPARE(submenuSpy.count(), 0);
+
+ menubarSpy.clear();
+ menuSpy.clear();
+ submenuSpy.clear();
+
+ //let's trigger the sub action
+ action->trigger();
+ QCOMPARE(menubarSpy.count(), 1);
+ QCOMPARE(menuSpy.count(), 1);
+ QCOMPARE(submenuSpy.count(), 1);
+}
+
+void tst_QMenuBar::task256322_highlight()
+{
+ QMainWindow win;
+ win.menuBar()->setNativeMenuBar(false); //we can't check the geometry of native menubars
+ QMenu menu;
+ QAction *file = win.menuBar()->addMenu(&menu);
+ file->setText("file");
+ QMenu menu2;
+ QAction *file2 = win.menuBar()->addMenu(&menu2);
+ file2->setText("file2");
+ QAction *nothing = win.menuBar()->addAction("nothing");
+
+ win.show();
+ QTest::qWait(200);
+
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center());
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file).center());
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center());
+ QTRY_VERIFY(menu.isVisible());
+ QVERIFY(!menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file);
+
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file2).center());
+ QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file2).center());
+ QTRY_VERIFY(!menu.isVisible());
+ QVERIFY(menu2.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), file2);
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file2).center());
+
+ QPoint nothingCenter = win.menuBar()->actionGeometry(nothing).center();
+ QTest::mousePress(win.menuBar(), Qt::LeftButton, 0, nothingCenter);
+ QTest::mouseMove(win.menuBar(), nothingCenter);
+ QTRY_VERIFY(!menu2.isVisible());
+ QVERIFY(!menu.isVisible());
+ QCOMPARE(win.menuBar()->activeAction(), nothing);
+ QTest::mouseRelease(win.menuBar(), Qt::LeftButton, 0, nothingCenter);
+}
+
+void tst_QMenuBar::menubarSizeHint()
+{
+ struct MyStyle : public QWindowsStyle
+ {
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0, const QWidget * widget = 0 ) const
+ {
+ // I chose strange values (prime numbers to be more sure that the size of the menubar is correct)
+ switch (metric)
+ {
+ case QStyle::PM_MenuBarItemSpacing:
+ return 7;
+ case PM_MenuBarHMargin:
+ return 13;
+ case PM_MenuBarVMargin:
+ return 11;
+ case PM_MenuBarPanelWidth:
+ return 1;
+ default:
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+ }
+ }
+ } style;
+
+ QMenuBar mb;
+ mb.setNativeMenuBar(false); //we can't check the geometry of native menubars
+
+ mb.setStyle(&style);
+ //this is a list of arbitrary strings so that we check the geometry
+ QStringList list = QStringList() << "trer" << "ezrfgtgvqd" << "sdgzgzerzerzer" << "eerzertz" << "er";
+ foreach(QString str, list)
+ mb.addAction(str);
+
+ const int panelWidth = style.pixelMetric(QStyle::PM_MenuBarPanelWidth);
+ const int hmargin = style.pixelMetric(QStyle::PM_MenuBarHMargin);
+ const int vmargin = style.pixelMetric(QStyle::PM_MenuBarVMargin);
+ const int spacing = style.pixelMetric(QStyle::PM_MenuBarItemSpacing);
+
+ mb.show();
+ QRect result;
+ foreach(QAction *action, mb.actions()) {
+ const QRect actionRect = mb.actionGeometry(action);
+ if (!result.isNull()) //this is the first item
+ QCOMPARE(actionRect.left() - result.right() - 1, spacing);
+ result |= actionRect;
+ QCOMPARE(result.x(), panelWidth + hmargin + spacing);
+ QCOMPARE(result.y(), panelWidth + vmargin);
+ }
+
+ //this code is copied from QMenuBar
+ //there is no public member that allows to initialize a styleoption instance
+ QStyleOptionMenuItem opt;
+ opt.rect = mb.rect();
+ opt.menuRect = mb.rect();
+ opt.state = QStyle::State_None;
+ opt.menuItemType = QStyleOptionMenuItem::Normal;
+ opt.checkType = QStyleOptionMenuItem::NotCheckable;
+ opt.palette = mb.palette();
+
+ QSize resSize = QSize(result.x(), result.y()) + result.size()
+ + QSize(panelWidth + hmargin, panelWidth + vmargin);
+
+
+ resSize = style.sizeFromContents(QStyle::CT_MenuBar, &opt,
+ resSize.expandedTo(QApplication::globalStrut()),
+ &mb);
+
+ QCOMPARE(resSize, mb.sizeHint());
+}
+
+void tst_QMenuBar::taskQTBUG4965_escapeEaten()
+{
+#ifdef Q_WS_MAC
+ QSKIP("On Mac, do not test the menubar with escape key", SkipAll);
+#endif
+ QMenuBar menubar;
+ QMenu menu("menu1");
+ QAction *first = menubar.addMenu(&menu);
+ menu.addAction("quit", &menubar, SLOT(close()), QKeySequence("ESC"));
+ menubar.show();
+ QApplication::setActiveWindow(&menubar);
+ QTest::qWaitForWindowShown(&menubar);
+ menubar.setActiveAction(first);
+ QTRY_VERIFY(menu.isVisible());
+ QCOMPARE(menubar.activeAction(), first);
+ QTest::keyClick(0, Qt::Key_Escape);
+ QVERIFY(!menu.isVisible());
+ QTRY_VERIFY(menubar.hasFocus());
+ QCOMPARE(menubar.activeAction(), first);
+ QTest::keyClick(0, Qt::Key_Escape);
+ QVERIFY(!menubar.activeAction());
+ QTest::keyClick(0, Qt::Key_Escape); //now the action should be triggered
+ QTRY_VERIFY(!menubar.isVisible());
+}
+
+void tst_QMenuBar::taskQTBUG11823_crashwithInvisibleActions()
+{
+ QMenuBar menubar;
+ menubar.setNativeMenuBar(false); //we can't check the geometry of native menubars
+
+ QAction * m = menubar.addAction( "&m" );
+ QAction * a = menubar.addAction( "&a" );
+
+ menubar.show();
+ QTest::qWaitForWindowShown(&menubar);
+ QApplication::setActiveWindow(&menubar);
+ menubar.setActiveAction(m);
+ QCOMPARE(menubar.activeAction(), m);
+ QTest::keyClick(0, Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), a);
+ QTest::keyClick(0, Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), m);
+ a->setVisible(false);
+
+ menubar.setActiveAction(m);
+ QCOMPARE(menubar.activeAction(), m); //the active action shouldn't have changed
+
+ //it used to crash here because the action is invisible
+ QTest::keyClick(0, Qt::Key_Right);
+ QCOMPARE(menubar.activeAction(), m); //the active action shouldn't have changed
+}
+
+
+#if defined(QT3_SUPPORT)
+void tst_QMenuBar::indexBasedInsertion_data()
+{
+ QTest::addColumn<int>("indexForInsertion");
+ QTest::addColumn<int>("expectedIndex");
+
+ QTest::newRow("negative-index-appends") << -1 << 1;
+ QTest::newRow("prepend") << 0 << 0;
+ QTest::newRow("append") << 1 << 1;
+}
+
+void tst_QMenuBar::indexBasedInsertion()
+{
+ // test the compat'ed index based insertion
+
+ QFETCH(int, indexForInsertion);
+ QFETCH(int, expectedIndex);
+
+ {
+ QMenuBar menu;
+ menu.addAction("Regular Item");
+
+ menu.insertItem("New Item", -1 /*id*/, indexForInsertion);
+
+ QAction *act = menu.actions().value(expectedIndex);
+ QVERIFY(act);
+ QCOMPARE(act->text(), QString("New Item"));
+ }
+ {
+ QMenuBar menu;
+ menu.addAction("Regular Item");
+
+ menu.insertSeparator(indexForInsertion);
+
+ QAction *act = menu.actions().value(expectedIndex);
+ QVERIFY(act);
+ QVERIFY(act->isSeparator());
+ }
+}
+#endif
+
+QTEST_MAIN(tst_QMenuBar)
+#include "tst_qmenubar.moc"