diff -r 000000000000 -r 1918ee327afb tests/auto/qbuttongroup/tst_qbuttongroup.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/auto/qbuttongroup/tst_qbuttongroup.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,534 @@ +/**************************************************************************** +** +** Copyright (C) 2009 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 + + +#include "qbuttongroup.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef Q_WS_MAC +#include +#endif + +#include "../../shared/util.h" + +class SpecialRadioButton: public QRadioButton +{ +public: + SpecialRadioButton(QWidget *parent) : QRadioButton(parent) + { } + +protected: + void focusInEvent(QFocusEvent *) + { + QCoreApplication::postEvent(this, new QKeyEvent(QEvent::KeyPress, + Qt::Key_Down, Qt::NoModifier)); + } +}; + +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QButtonGroup : public QObject +{ +Q_OBJECT +public: + tst_QButtonGroup(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void arrowKeyNavigation(); + void exclusive(); + void exclusiveWithActions(); + void testSignals(); + void checkedButton(); + + void task106609(); + + // fixed for Qt 4.6.0 +#if QT_VERSION >= 0x040600 + void autoIncrementId(); +#endif + + void task209485_removeFromGroupInEventHandler_data(); + void task209485_removeFromGroupInEventHandler(); +}; + +tst_QButtonGroup::tst_QButtonGroup() +{ +} + + +void tst_QButtonGroup::initTestCase() +{ +} + +void tst_QButtonGroup::cleanupTestCase() +{ +} + +void tst_QButtonGroup::init() +{ +} + +void tst_QButtonGroup::cleanup() +{ +} + +QT_BEGIN_NAMESPACE +extern bool Q_GUI_EXPORT qt_tab_all_widgets; +QT_END_NAMESPACE + + +void tst_QButtonGroup::arrowKeyNavigation() +{ + if (!qt_tab_all_widgets) + QSKIP("This test requires full keyboard control to be enabled.", SkipAll); + + QDialog dlg(0); + QHBoxLayout layout(&dlg); + QGroupBox g1("1", &dlg); + QHBoxLayout g1layout(&g1); + QRadioButton bt1("Radio1", &g1); + QPushButton pb("PB", &g1); + QLineEdit le(&g1); + QRadioButton bt2("Radio2", &g1); + g1layout.addWidget(&bt1); + g1layout.addWidget(&pb); + g1layout.addWidget(&le); + g1layout.addWidget(&bt2); + + // create a mixed button group with radion buttons and push + // buttons. Not very useful, but it tests borderline cases wrt + // focus handling. + QButtonGroup bgrp1(&g1); + bgrp1.addButton(&bt1); + bgrp1.addButton(&pb); + bgrp1.addButton(&bt2); + + QGroupBox g2("2", &dlg); + QVBoxLayout g2layout(&g2); + // we don't need a button group here, because radio buttons are + // auto exclusive, i.e. they group themselves in he same parent + // widget. + QRadioButton bt3("Radio3", &g2); + QRadioButton bt4("Radio4", &g2); + g2layout.addWidget(&bt3); + g2layout.addWidget(&bt4); + + layout.addWidget(&g1); + layout.addWidget(&g2); + + dlg.show(); + qApp->setActiveWindow(&dlg); + QTest::qWaitForWindowShown(&dlg); + + bt1.setFocus(); + + QTRY_VERIFY(bt1.hasFocus()); + + QTest::keyClick(&bt1, Qt::Key_Right); + QVERIFY(pb.hasFocus()); + QTest::keyClick(&pb, Qt::Key_Right); + QVERIFY(bt2.hasFocus()); + QTest::keyClick(&bt2, Qt::Key_Right); + QVERIFY(bt2.hasFocus()); + QTest::keyClick(&bt2, Qt::Key_Left); + QVERIFY(pb.hasFocus()); + QTest::keyClick(&pb, Qt::Key_Left); + QVERIFY(bt1.hasFocus()); + + QTest::keyClick(&bt1, Qt::Key_Tab); + QVERIFY(pb.hasFocus()); + QTest::keyClick(&pb, Qt::Key_Tab); + + QVERIFY(le.hasFocus()); + QCOMPARE(le.selectedText(), le.text()); + QTest::keyClick(&le, Qt::Key_Tab); + + QVERIFY(bt2.hasFocus()); + QTest::keyClick(&bt2, Qt::Key_Tab); + QVERIFY(bt3.hasFocus()); + + QTest::keyClick(&bt3, Qt::Key_Down); + QVERIFY(bt4.hasFocus()); + QTest::keyClick(&bt4, Qt::Key_Down); + QVERIFY(bt4.hasFocus()); + + QTest::keyClick(&bt4, Qt::Key_Up); + QVERIFY(bt3.hasFocus()); + QTest::keyClick(&bt3, Qt::Key_Up); + QVERIFY(bt3.hasFocus()); +} + +void tst_QButtonGroup::exclusiveWithActions() +{ + QDialog dlg(0); + QHBoxLayout layout(&dlg); + QAction *action1 = new QAction("Action 1", &dlg); + action1->setCheckable(true); + QAction *action2 = new QAction("Action 2", &dlg); + action2->setCheckable(true); + QAction *action3 = new QAction("Action 3", &dlg); + action3->setCheckable(true); + QToolButton *toolButton1 = new QToolButton(&dlg); + QToolButton *toolButton2 = new QToolButton(&dlg); + QToolButton *toolButton3 = new QToolButton(&dlg); + toolButton1->setDefaultAction(action1); + toolButton2->setDefaultAction(action2); + toolButton3->setDefaultAction(action3); + layout.addWidget(toolButton1); + layout.addWidget(toolButton2); + layout.addWidget(toolButton3); + QButtonGroup *buttonGroup = new QButtonGroup( &dlg ); + buttonGroup->setExclusive(true); + buttonGroup->addButton(toolButton1, 1); + buttonGroup->addButton(toolButton2, 2); + buttonGroup->addButton(toolButton3, 3); + dlg.show(); + + QTest::mouseClick(toolButton1, Qt::LeftButton); + QVERIFY(toolButton1->isChecked()); + QVERIFY(action1->isChecked()); + QVERIFY(!toolButton2->isChecked()); + QVERIFY(!toolButton3->isChecked()); + QVERIFY(!action2->isChecked()); + QVERIFY(!action3->isChecked()); + + QTest::mouseClick(toolButton2, Qt::LeftButton); + QVERIFY(toolButton2->isChecked()); + QVERIFY(action2->isChecked()); + QVERIFY(!toolButton1->isChecked()); + QVERIFY(!toolButton3->isChecked()); + QVERIFY(!action1->isChecked()); + QVERIFY(!action3->isChecked()); + + QTest::mouseClick(toolButton3, Qt::LeftButton); + QVERIFY(toolButton3->isChecked()); + QVERIFY(action3->isChecked()); + QVERIFY(!toolButton1->isChecked()); + QVERIFY(!toolButton2->isChecked()); + QVERIFY(!action1->isChecked()); + QVERIFY(!action2->isChecked()); + + QTest::mouseClick(toolButton2, Qt::LeftButton); + QVERIFY(toolButton2->isChecked()); + QVERIFY(action2->isChecked()); + QVERIFY(!toolButton1->isChecked()); + QVERIFY(!toolButton3->isChecked()); + QVERIFY(!action1->isChecked()); + QVERIFY(!action3->isChecked()); +} + +void tst_QButtonGroup::exclusive() +{ + QDialog dlg(0); + QHBoxLayout layout(&dlg); + QPushButton *pushButton1 = new QPushButton(&dlg); + QPushButton *pushButton2 = new QPushButton(&dlg); + QPushButton *pushButton3 = new QPushButton(&dlg); + pushButton1->setCheckable(true); + pushButton2->setCheckable(true); + pushButton3->setCheckable(true); + layout.addWidget(pushButton1); + layout.addWidget(pushButton2); + layout.addWidget(pushButton3); + QButtonGroup *buttonGroup = new QButtonGroup( &dlg ); + buttonGroup->setExclusive(true); + buttonGroup->addButton(pushButton1, 1); + buttonGroup->addButton(pushButton2, 2); + buttonGroup->addButton(pushButton3, 3); + dlg.show(); + + QTest::mouseClick(pushButton1, Qt::LeftButton); + QVERIFY(pushButton1->isChecked()); + QVERIFY(!pushButton2->isChecked()); + QVERIFY(!pushButton3->isChecked()); + + QTest::mouseClick(pushButton2, Qt::LeftButton); + QVERIFY(pushButton2->isChecked()); + QVERIFY(!pushButton1->isChecked()); + QVERIFY(!pushButton3->isChecked()); + + QTest::mouseClick(pushButton3, Qt::LeftButton); + QVERIFY(pushButton3->isChecked()); + QVERIFY(!pushButton1->isChecked()); + QVERIFY(!pushButton2->isChecked()); + + QTest::mouseClick(pushButton2, Qt::LeftButton); + QVERIFY(pushButton2->isChecked()); + QVERIFY(!pushButton1->isChecked()); + QVERIFY(!pushButton3->isChecked()); +} + +void tst_QButtonGroup::testSignals() +{ + QButtonGroup buttons; + QPushButton pb1; + QPushButton pb2; + QPushButton pb3; + buttons.addButton(&pb1); + buttons.addButton(&pb2, 23); + buttons.addButton(&pb3); + + qRegisterMetaType("QAbstractButton *"); + QSignalSpy clickedSpy(&buttons, SIGNAL(buttonClicked(QAbstractButton *))); + QSignalSpy clickedIdSpy(&buttons, SIGNAL(buttonClicked(int))); + QSignalSpy pressedSpy(&buttons, SIGNAL(buttonPressed(QAbstractButton *))); + QSignalSpy pressedIdSpy(&buttons, SIGNAL(buttonPressed(int))); + QSignalSpy releasedSpy(&buttons, SIGNAL(buttonReleased(QAbstractButton *))); + QSignalSpy releasedIdSpy(&buttons, SIGNAL(buttonReleased(int))); + + pb1.animateClick(); + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedIdSpy.count(), 1); + + int expectedId = -1; +#if QT_VERSION >= 0x040600 + expectedId = -2; +#endif + + QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == expectedId); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(pressedIdSpy.count(), 1); + QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == expectedId); + QCOMPARE(releasedSpy.count(), 1); + QCOMPARE(releasedIdSpy.count(), 1); + QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == expectedId); + + clickedSpy.clear(); + clickedIdSpy.clear(); + pressedSpy.clear(); + pressedIdSpy.clear(); + releasedSpy.clear(); + releasedIdSpy.clear(); + + pb2.animateClick(); + QTestEventLoop::instance().enterLoop(1); + + QCOMPARE(clickedSpy.count(), 1); + QCOMPARE(clickedIdSpy.count(), 1); + QVERIFY(clickedIdSpy.takeFirst().at(0).toInt() == 23); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(pressedIdSpy.count(), 1); + QVERIFY(pressedIdSpy.takeFirst().at(0).toInt() == 23); + QCOMPARE(releasedSpy.count(), 1); + QCOMPARE(releasedIdSpy.count(), 1); + QVERIFY(releasedIdSpy.takeFirst().at(0).toInt() == 23); +} + +void tst_QButtonGroup::task106609() +{ + // task is: + // sometimes, only one of the two signals in QButtonGroup get emitted + // they get emitted when using the mouse, but when using the keyboard, only one is + // + + QDialog dlg(0); + QButtonGroup *buttons = new QButtonGroup(&dlg); + QVBoxLayout *vbox = new QVBoxLayout(&dlg); + + SpecialRadioButton *radio1 = new SpecialRadioButton(&dlg); + radio1->setText("radio1"); + SpecialRadioButton *radio2 = new SpecialRadioButton(&dlg); + radio2->setText("radio2"); + QRadioButton *radio3 = new QRadioButton(&dlg); + radio3->setText("radio3"); + + buttons->addButton(radio1, 1); + vbox->addWidget(radio1); + buttons->addButton(radio2, 2); + vbox->addWidget(radio2); + buttons->addButton(radio3, 3); + vbox->addWidget(radio3); + + radio1->setFocus(); + radio1->setChecked(true); + dlg.show(); + + qRegisterMetaType("QAbstractButton*"); + QSignalSpy spy1(buttons, SIGNAL(buttonClicked(QAbstractButton*))); + QSignalSpy spy2(buttons, SIGNAL(buttonClicked(int))); + + QTestEventLoop::instance().enterLoop(1); + QApplication::setActiveWindow(&dlg); + QTRY_COMPARE(QApplication::activeWindow(), static_cast(&dlg)); + + //qDebug() << "int:" << spy2.count() << "QAbstractButton*:" << spy1.count(); + QCOMPARE(spy2.count(), 2); + QCOMPARE(spy1.count(), 2); +} + +void tst_QButtonGroup::checkedButton() +{ + QButtonGroup buttons; + buttons.setExclusive(false); + QPushButton pb1; + pb1.setCheckable(true); + QPushButton pb2; + pb2.setCheckable(true); + buttons.addButton(&pb1); + buttons.addButton(&pb2, 23); + + QVERIFY(buttons.checkedButton() == 0); + pb1.setChecked(true); + QVERIFY(buttons.checkedButton() == &pb1); + pb2.setChecked(true); + QVERIFY(buttons.checkedButton() == &pb2); + pb2.setChecked(false); + QVERIFY(buttons.checkedButton() == &pb1); + pb1.setChecked(false); + QVERIFY(buttons.checkedButton() == 0); + + buttons.setExclusive(true); + QVERIFY(buttons.checkedButton() == 0); + pb1.setChecked(true); + QVERIFY(buttons.checkedButton() == &pb1); + pb2.setChecked(true); + QVERIFY(buttons.checkedButton() == &pb2); + // checked button cannot be unchecked + pb2.setChecked(false); + QVERIFY(buttons.checkedButton() == &pb2); +} + +class task209485_ButtonDeleter : public QObject +{ + Q_OBJECT + +public: + task209485_ButtonDeleter(QButtonGroup *group, bool deleteButton) + : group(group) + , deleteButton(deleteButton) + { + connect(group, SIGNAL(buttonClicked(int)), SLOT(buttonClicked(int))); + } + +private slots: + void buttonClicked(int) + { + if (deleteButton) + group->removeButton(group->buttons().first()); + } + +private: + QButtonGroup *group; + bool deleteButton; +}; + +void tst_QButtonGroup::task209485_removeFromGroupInEventHandler_data() +{ + QTest::addColumn("deleteButton"); + QTest::addColumn("signalCount"); + QTest::newRow("buttonPress 1") << true << 1; + QTest::newRow("buttonPress 2") << false << 2; +} + +void tst_QButtonGroup::task209485_removeFromGroupInEventHandler() +{ + QFETCH(bool, deleteButton); + QFETCH(int, signalCount); + qRegisterMetaType("QAbstractButton *"); + + QPushButton *button = new QPushButton; + QButtonGroup group; + group.addButton(button); + + task209485_ButtonDeleter buttonDeleter(&group, deleteButton); + + QSignalSpy spy1(&group, SIGNAL(buttonClicked(QAbstractButton *))); + QSignalSpy spy2(&group, SIGNAL(buttonClicked(int))); + + // NOTE: Reintroducing the bug of this task will cause the following line to crash: + QTest::mouseClick(button, Qt::LeftButton); + + QCOMPARE(spy1.count() + spy2.count(), signalCount); +} + +#if QT_VERSION >= 0x040600 +void tst_QButtonGroup::autoIncrementId() +{ + QDialog dlg(0); + QButtonGroup *buttons = new QButtonGroup(&dlg); + QVBoxLayout *vbox = new QVBoxLayout(&dlg); + + QRadioButton *radio1 = new QRadioButton(&dlg); + radio1->setText("radio1"); + QRadioButton *radio2 = new QRadioButton(&dlg); + radio2->setText("radio2"); + QRadioButton *radio3 = new QRadioButton(&dlg); + radio3->setText("radio3"); + + buttons->addButton(radio1); + vbox->addWidget(radio1); + buttons->addButton(radio2); + vbox->addWidget(radio2); + buttons->addButton(radio3); + vbox->addWidget(radio3); + + radio1->setChecked(true); + + QVERIFY(buttons->id(radio1) == -2); + QVERIFY(buttons->id(radio2) == -3); + QVERIFY(buttons->id(radio3) == -4); + + dlg.show(); +} +#endif + +QTEST_MAIN(tst_QButtonGroup) +#include "tst_qbuttongroup.moc"