/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** 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, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include "qpushbutton.h" #include #include #include #include #include #include #include #include #include "../../shared/util.h" Q_DECLARE_METATYPE(QPushButton*) //TESTED_CLASS= //TESTED_FILES= class tst_QPushButton : public QObject { Q_OBJECT public: tst_QPushButton(); virtual ~tst_QPushButton(); public slots: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); private slots: void getSetCheck(); void setAutoRepeat(); void pressed(); void released(); void text(); void accel(); void setAccel(); void isCheckable(); void isDown(); void setDown(); void popupCrash(); void isChecked(); void autoRepeat(); void animateClick(); void toggle(); void clicked(); #ifdef Q_OS_MAC void macClicked(); #endif void toggled(); void isEnabled(); void defaultAndAutoDefault(); void sizeHint_data(); void sizeHint(); void taskQTBUG_20191_shortcutWithKeypadModifer(); /* void state(); void group(); void stateChanged(); */ protected slots: void resetCounters(); void onClicked(); void onToggled( bool on ); void onPressed(); void onReleased(); void helperSlotDelete(); private: uint click_count; uint toggle_count; uint press_count; uint release_count; QPushButton *testWidget; }; // Testing get/set functions void tst_QPushButton::getSetCheck() { QPushButton obj1; // QMenu* QPushButton::menu() // void QPushButton::setMenu(QMenu*) QMenu *var1 = new QMenu; obj1.setMenu(var1); QCOMPARE(var1, obj1.menu()); obj1.setMenu((QMenu *)0); QCOMPARE((QMenu *)0, obj1.menu()); delete var1; } tst_QPushButton::tst_QPushButton() { } tst_QPushButton::~tst_QPushButton() { } void tst_QPushButton::initTestCase() { // Create the test class testWidget = new QPushButton( "&Start", 0 ); testWidget->setObjectName("testWidget"); testWidget->resize( 200, 200 ); testWidget->show(); connect( testWidget, SIGNAL(clicked()), this, SLOT(onClicked()) ); connect( testWidget, SIGNAL(pressed()), this, SLOT(onPressed()) ); connect( testWidget, SIGNAL(released()), this, SLOT(onReleased()) ); connect( testWidget, SIGNAL(toggled(bool)), this, SLOT(onToggled(bool)) ); } void tst_QPushButton::cleanupTestCase() { delete testWidget; testWidget = 0; } void tst_QPushButton::init() { testWidget->setAutoRepeat( FALSE ); testWidget->setDown( FALSE ); testWidget->setText("Test"); testWidget->setEnabled( TRUE ); QKeySequence seq; testWidget->setShortcut( seq ); resetCounters(); } void tst_QPushButton::cleanup() { } void tst_QPushButton::resetCounters() { toggle_count = 0; press_count = 0; release_count = 0; click_count = 0; } void tst_QPushButton::onClicked() { click_count++; } void tst_QPushButton::onToggled( bool /*on*/ ) { toggle_count++; } void tst_QPushButton::onPressed() { press_count++; } void tst_QPushButton::onReleased() { release_count++; } void tst_QPushButton::setAutoRepeat() { // If this changes, this test must be completely revised. QVERIFY( !testWidget->isCheckable() ); // verify autorepeat is off by default. QPushButton tmp( 0 ); tmp.setObjectName("tmp"); QVERIFY( !tmp.autoRepeat() ); // check if we can toggle the mode testWidget->setAutoRepeat( TRUE ); QVERIFY( testWidget->autoRepeat() ); testWidget->setAutoRepeat( FALSE ); QVERIFY( !testWidget->autoRepeat() ); resetCounters(); // check that the button is down if we press space and not in autorepeat testWidget->setDown( FALSE ); testWidget->setAutoRepeat( FALSE ); QTest::keyPress( testWidget, Qt::Key_Space ); QTest::qWait( 300 ); QVERIFY( testWidget->isDown() ); QVERIFY( toggle_count == 0 ); QVERIFY( press_count == 1 ); QVERIFY( release_count == 0 ); QVERIFY( click_count == 0 ); QTest::keyRelease( testWidget, Qt::Key_Space ); resetCounters(); // check that the button is down if we press space while in autorepeat // we can't actually confirm how many times it is fired, more than 1 is enough. testWidget->setDown( FALSE ); testWidget->setAutoRepeat( TRUE ); QTest::keyPress( testWidget, Qt::Key_Space ); QTest::qWait(900); QVERIFY( testWidget->isDown() ); QVERIFY( toggle_count == 0 ); QTest::keyRelease( testWidget, Qt::Key_Space ); QVERIFY(press_count == release_count); QVERIFY(release_count == click_count); QVERIFY(press_count > 1); // #### shouldn't I check here to see if multiple signals have been fired??? // check that pressing ENTER has no effect resetCounters(); testWidget->setDown( FALSE ); testWidget->setAutoRepeat( FALSE ); QTest::keyPress( testWidget, Qt::Key_Enter ); QTest::qWait( 300 ); QVERIFY( !testWidget->isDown() ); QVERIFY( toggle_count == 0 ); QVERIFY( press_count == 0 ); QVERIFY( release_count == 0 ); QVERIFY( click_count == 0 ); QTest::keyRelease( testWidget, Qt::Key_Enter ); // check that pressing ENTER has no effect resetCounters(); testWidget->setDown( FALSE ); testWidget->setAutoRepeat( TRUE ); QTest::keyClick( testWidget, Qt::Key_Enter ); QTest::qWait( 300 ); QVERIFY( !testWidget->isDown() ); QVERIFY( toggle_count == 0 ); QVERIFY( press_count == 0 ); QVERIFY( release_count == 0 ); QVERIFY( click_count == 0 ); } void tst_QPushButton::autoRepeat() { DEPENDS_ON(" setAutoRepeat" ); } void tst_QPushButton::pressed() { QTest::keyPress( testWidget, ' ' ); // QTest::qWait( 300 ); QCOMPARE( press_count, (uint)1 ); QCOMPARE( release_count, (uint)0 ); QTest::keyRelease( testWidget, ' ' ); // QTest::qWait( 300 ); QCOMPARE( press_count, (uint)1 ); QCOMPARE( release_count, (uint)1 ); QTest::keyPress( testWidget,Qt::Key_Enter ); // QTest::qWait( 300 ); QCOMPARE( press_count, (uint)1 ); QCOMPARE( release_count, (uint)1 ); testWidget->setAutoDefault(true); QTest::keyPress( testWidget,Qt::Key_Enter ); // QTest::qWait( 300 ); QCOMPARE( press_count, (uint)2 ); QCOMPARE( release_count, (uint)2 ); testWidget->setAutoDefault(false); } void tst_QPushButton::released() { DEPENDS_ON( "pressed" ); } void tst_QPushButton::text() { DEPENDS_ON( "setText" ); } void tst_QPushButton::isEnabled() { DEPENDS_ON( "setEnabled" ); } void tst_QPushButton::isCheckable() { QVERIFY( !testWidget->isCheckable() ); } void tst_QPushButton::isDown() { DEPENDS_ON( "setDown" ); } void tst_QPushButton::setDown() { testWidget->setDown( FALSE ); QVERIFY( !testWidget->isDown() ); testWidget->setDown( TRUE ); QVERIFY( testWidget->isDown() ); testWidget->setDown( TRUE ); QTest::keyClick( testWidget, Qt::Key_Escape ); QVERIFY( !testWidget->isDown() ); } void tst_QPushButton::isChecked() { testWidget->setDown( FALSE ); QVERIFY( !testWidget->isChecked() ); testWidget->setDown( TRUE ); QVERIFY( !testWidget->isChecked() ); testWidget->setDown( FALSE ); testWidget->toggle(); QVERIFY( testWidget->isChecked() == testWidget->isCheckable() ); } void tst_QPushButton::toggle() { // the pushbutton shouldn't toggle the button. testWidget->toggle(); QVERIFY( testWidget->isChecked() == FALSE ); } void tst_QPushButton::toggled() { // the pushbutton shouldn't send a toggled signal when we call the toggle slot. QVERIFY( !testWidget->isCheckable() ); testWidget->toggle(); QVERIFY( toggle_count == 0 ); // do it again, just to be sure resetCounters(); testWidget->toggle(); QVERIFY( toggle_count == 0 ); // finally check that we can toggle using the mouse resetCounters(); QTest::mousePress( testWidget, Qt::LeftButton ); QVERIFY( toggle_count == 0 ); QVERIFY( click_count == 0 ); QTest::mouseRelease( testWidget, Qt::LeftButton ); QVERIFY( click_count == 1 ); } void tst_QPushButton::accel() { DEPENDS_ON( "setAccel" ); } /* If we press an accelerator key we ONLY get a pressed signal and NOT a released or clicked signal. */ void tst_QPushButton::setAccel() { testWidget->setText("&AccelTest"); QKeySequence seq( Qt::ALT + Qt::Key_A ); testWidget->setShortcut( seq ); // The shortcut will not be activated unless the button is in a active // window and has focus QApplication::setActiveWindow(testWidget); testWidget->setFocus(); for (int i = 0; !testWidget->isActiveWindow() && i < 1000; ++i) { testWidget->activateWindow(); QApplication::instance()->processEvents(); QTest::qWait(100); } QVERIFY(testWidget->isActiveWindow()); QTest::keyClick( testWidget, 'A', Qt::AltModifier ); QTest::qWait( 50 ); QTRY_VERIFY( click_count == 1 ); QVERIFY( press_count == 1 ); QVERIFY( release_count == 1 ); QVERIFY( toggle_count == 0 ); // wait 200 ms because setAccel uses animateClick. // if we don't wait this may screw up a next test. QTest::qWait(200); QTRY_VERIFY( !testWidget->isDown() ); } void tst_QPushButton::animateClick() { QVERIFY( !testWidget->isDown() ); testWidget->animateClick(); QVERIFY( testWidget->isDown() ); QTest::qWait( 200 ); QVERIFY( !testWidget->isDown() ); QVERIFY( click_count == 1 ); QVERIFY( press_count == 1 ); QVERIFY( release_count == 1 ); QVERIFY( toggle_count == 0 ); } void tst_QPushButton::clicked() { QTest::mousePress( testWidget, Qt::LeftButton ); QVERIFY( press_count == 1 ); QVERIFY( release_count == 0 ); QTest::mouseRelease( testWidget, Qt::LeftButton ); QCOMPARE( press_count, (uint)1 ); QCOMPARE( release_count, (uint)1 ); press_count = 0; release_count = 0; testWidget->setDown(FALSE); for (uint i=0; i<10; i++) QTest::mouseClick( testWidget, Qt::LeftButton ); QCOMPARE( press_count, (uint)10 ); QCOMPARE( release_count, (uint)10 ); } #ifdef Q_OS_MAC // test that the corners of a mac style button are not treated as clicks. // but that if a style is applied, they are. void tst_QPushButton::macClicked() { QPushButton *macTestWidget = new QPushButton( "Push button" ); macTestWidget->show(); connect( macTestWidget, SIGNAL(clicked()), this, SLOT(onClicked()) ); QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); QVERIFY( click_count == 0 ); QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); QVERIFY( click_count == 1 ); resetCounters(); macTestWidget->setStyleSheet("background: white;"); QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); QVERIFY( click_count == 1 ); QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); QVERIFY( click_count == 2 ); delete macTestWidget; } #endif /* void tst_QPushButton::group() { } void tst_QPushButton::state() { } void tst_QPushButton::stateChanged() { } */ QPushButton *pb = 0; void tst_QPushButton::helperSlotDelete() { delete pb; pb = 0; } void tst_QPushButton::popupCrash() { pb = new QPushButton("foo"); QMenu *menu = new QMenu("bar", pb); pb->setMenu(menu); QTimer::singleShot(1000, this, SLOT(helperSlotDelete())); pb->show(); pb->click(); } void tst_QPushButton::defaultAndAutoDefault() { { // Adding buttons directly to QDialog QDialog dialog; QPushButton button1(&dialog); QVERIFY(button1.autoDefault()); QVERIFY(!button1.isDefault()); QPushButton button2(&dialog); QVERIFY(button2.autoDefault()); QVERIFY(!button2.isDefault()); button1.setDefault(true); QVERIFY(button1.autoDefault()); QVERIFY(button1.isDefault()); QVERIFY(button2.autoDefault()); QVERIFY(!button2.isDefault()); dialog.show(); QVERIFY(dialog.isVisible()); QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide())); QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); QApplication::sendEvent(&dialog, &event); QVERIFY(!dialog.isVisible()); } { // Adding buttons to QDialog through a layout QDialog dialog; QPushButton button3; button3.setAutoDefault(false); QPushButton button1; QVERIFY(!button1.autoDefault()); QVERIFY(!button1.isDefault()); QPushButton button2; QVERIFY(!button2.autoDefault()); QVERIFY(!button2.isDefault()); button1.setDefault(true); QVERIFY(!button1.autoDefault()); QVERIFY(button1.isDefault()); QVERIFY(!button2.autoDefault()); QVERIFY(!button2.isDefault()); QGridLayout layout; layout.addWidget(&button3, 0, 3); layout.addWidget(&button2, 0, 2); layout.addWidget(&button1, 0, 1); dialog.setLayout(&layout); button3.setFocus(); QVERIFY(button1.autoDefault()); QVERIFY(button1.isDefault()); QVERIFY(button2.autoDefault()); QVERIFY(!button2.isDefault()); dialog.show(); QVERIFY(dialog.isVisible()); QObject::connect(&button1, SIGNAL(clicked()), &dialog, SLOT(hide())); QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); QApplication::sendEvent(&dialog, &event); QVERIFY(!dialog.isVisible()); } { // autoDefault behavior. QDialog dialog; QPushButton button2(&dialog); QPushButton button1(&dialog); dialog.show(); QVERIFY(dialog.isVisible()); // No default button is set, and button2 is the first autoDefault button // that is next in the tab order QObject::connect(&button2, SIGNAL(clicked()), &dialog, SLOT(hide())); QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); QApplication::sendEvent(&dialog, &event); QVERIFY(!dialog.isVisible()); // Reparenting QVERIFY(button2.autoDefault()); button2.setParent(0); QVERIFY(!button2.autoDefault()); button2.setAutoDefault(false); button2.setParent(&dialog); QVERIFY(!button2.autoDefault()); button1.setAutoDefault(true); button1.setParent(0); QVERIFY(button1.autoDefault()); } } void tst_QPushButton::sizeHint_data() { QTest::addColumn("stylename"); QTest::newRow("motif") << QString::fromAscii("motif"); QTest::newRow("cde") << QString::fromAscii("cde"); QTest::newRow("windows") << QString::fromAscii("windows"); QTest::newRow("cleanlooks") << QString::fromAscii("cleanlooks"); QTest::newRow("gtk") << QString::fromAscii("gtk"); QTest::newRow("mac") << QString::fromAscii("mac"); QTest::newRow("plastique") << QString::fromAscii("plastique"); QTest::newRow("windowsxp") << QString::fromAscii("windowsxp"); QTest::newRow("windowsvista") << QString::fromAscii("windowsvista"); } void tst_QPushButton::sizeHint() { QFETCH(QString, stylename); QStyle *style = QStyleFactory::create(stylename); if (!style) QSKIP(qPrintable(QString::fromLatin1("Qt has been compiled without style: %1") .arg(stylename)), SkipSingle); QApplication::setStyle(style); // Test 1 { QPushButton *button = new QPushButton("123"); QSize initSizeHint = button->sizeHint(); QDialog *dialog = new QDialog; QWidget *widget = new QWidget(dialog); button->setParent(widget); button->sizeHint(); widget->setParent(0); delete dialog; button->setDefault(false); QCOMPARE(button->sizeHint(), initSizeHint); delete button; } // Test 2 { QWidget *tab1 = new QWidget; QHBoxLayout *layout1 = new QHBoxLayout(tab1); QPushButton *button1_1 = new QPushButton("123"); QPushButton *button1_2 = new QPushButton("123"); layout1->addWidget(button1_1); layout1->addWidget(button1_2); QWidget *tab2 = new QWidget; QHBoxLayout *layout2 = new QHBoxLayout(tab2); QPushButton *button2_1 = new QPushButton("123"); QPushButton *button2_2 = new QPushButton("123"); layout2->addWidget(button2_1); layout2->addWidget(button2_2); QDialog *dialog = new QDialog; QTabWidget *tabWidget = new QTabWidget; tabWidget->addTab(tab1, "1"); tabWidget->addTab(tab2, "2"); QVBoxLayout *mainLayout = new QVBoxLayout(dialog); mainLayout->addWidget(tabWidget); dialog->show(); tabWidget->setCurrentWidget(tab2); tabWidget->setCurrentWidget(tab1); QTest::qWait(100); QApplication::processEvents(); QCOMPARE(button1_2->size(), button2_2->size()); } } void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() { // setup a dialog with two buttons QPushButton *button1 = new QPushButton("5"); QPushButton *button2 = new QPushButton("5 + KeypadModifier"); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(button1); layout->addWidget(button2); QDialog dialog; dialog.setLayout(layout); dialog.show(); QTest::qWaitForWindowShown(&dialog); QApplication::setActiveWindow(&dialog); // add shortcut '5' to button1 and test with keyboard and keypad '5' keys QSignalSpy spy1(button1, SIGNAL(clicked())); button1->setShortcut(Qt::Key_5); QTest::keyClick(&dialog, Qt::Key_5); QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); QCOMPARE(spy1.count(), 2); // add shortcut 'keypad 5' to button2 spy1.clear(); QSignalSpy spy2(button2, SIGNAL(clicked())); button2->setShortcut(Qt::Key_5 + Qt::KeypadModifier); QTest::keyClick(&dialog, Qt::Key_5); QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); QCOMPARE(spy1.count(), 1); QCOMPARE(spy2.count(), 1); // remove shortcut from button1 spy1.clear(); spy2.clear(); button1->setShortcut(QKeySequence()); QTest::keyClick(&dialog, Qt::Key_5); QTest::qWait(300); QTest::keyClick(&dialog, Qt::Key_5, Qt::KeypadModifier); QTest::qWait(300); QCOMPARE(spy1.count(), 0); QCOMPARE(spy2.count(), 1); } QTEST_MAIN(tst_QPushButton) #include "tst_qpushbutton.moc"