/**************************************************************************** ** ** 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$ ** GNU Lesser General Public License Usage ** 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. ** ** 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. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include //TESTED_CLASS= //TESTED_FILES= class tst_QWidgetAction : public QObject { Q_OBJECT private slots: void defaultWidget(); void visibilityUpdate(); void customWidget(); void keepOwnership(); void visibility(); void setEnabled(); void popup(); void releaseWidgetCrash(); }; void tst_QWidgetAction::defaultWidget() { { QToolBar tb1; QPointer combo = new QComboBox(&tb1); QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); QVERIFY(!combo->isVisible()); QVERIFY(!combo->parent()); QVERIFY(action->isVisible()); delete action; QVERIFY(!combo); } { QToolBar tb1; QPointer combo = new QComboBox(&tb1); combo->hide(); QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); // explicitly hidden widgets should also set the action invisible QVERIFY(!action->isVisible()); delete action; } { QPointer combo = new QComboBox(0); combo->show(); QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); QVERIFY(action->isVisible()); QVERIFY(!combo->isVisible()); delete action; } { QToolBar tb1; tb1.show(); QToolBar tb2; tb2.show(); QPointer combo = new QComboBox(0); QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); tb1.addAction(action); QVERIFY(combo->parent() == &tb1); qApp->processEvents(); qApp->processEvents(); QVERIFY(combo->isVisible()); // not supported, not supposed to work, hence the parent() check tb2.addAction(action); QVERIFY(combo->parent() == &tb1); tb2.removeAction(action); tb1.removeAction(action); qApp->processEvents(); //the call to hide is delayd by the toolbar layout QVERIFY(!combo->isVisible()); tb2.addAction(action); qApp->processEvents(); //the call to hide is delayd by the toolbar layout qApp->processEvents(); QVERIFY(combo->parent() == &tb2); QVERIFY(combo->isVisible()); tb1.addAction(action); QVERIFY(combo->parent() == &tb2); delete action; QVERIFY(!combo); } { QWidgetAction *a = new QWidgetAction(0); QVERIFY(!a->defaultWidget()); QPointer combo1 = new QComboBox; a->setDefaultWidget(combo1); QVERIFY(a->defaultWidget() == combo1); a->setDefaultWidget(combo1); QVERIFY(combo1); QVERIFY(a->defaultWidget() == combo1); QPointer combo2 = new QComboBox; QVERIFY(combo1 != combo2); a->setDefaultWidget(combo2); QVERIFY(!combo1); QVERIFY(a->defaultWidget() == combo2); delete a; QVERIFY(!combo2); } } void tst_QWidgetAction::visibilityUpdate() { // actually keeping the widget's state in sync with the // action in terms of visibility is QToolBar's responsibility. QToolBar tb; tb.show(); QComboBox *combo = new QComboBox(0); QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); tb.addAction(action); //the call to show is delayed by the toolbar layout QTRY_VERIFY(combo->isVisible()); QVERIFY(action->isVisible()); action->setVisible(false); //the call to hide is delayed by the toolbar layout QTRY_VERIFY(!combo->isVisible()); delete action; // action also deletes combo } class ComboAction : public QWidgetAction { public: inline ComboAction(QObject *parent) : QWidgetAction(parent) {} QList createdWidgets() const { return QWidgetAction::createdWidgets(); } protected: virtual QWidget *createWidget(QWidget *parent); }; QWidget *ComboAction::createWidget(QWidget *parent) { return new QComboBox(parent); } void tst_QWidgetAction::customWidget() { QToolBar tb1; tb1.show(); QToolBar tb2; tb2.show(); ComboAction *action = new ComboAction(0); tb1.addAction(action); QList combos = action->createdWidgets(); QCOMPARE(combos.count(), 1); QPointer combo1 = qobject_cast(combos.at(0)); QVERIFY(combo1); tb2.addAction(action); combos = action->createdWidgets(); QCOMPARE(combos.count(), 2); QVERIFY(combos.at(0) == combo1); QPointer combo2 = qobject_cast(combos.at(1)); QVERIFY(combo2); tb2.removeAction(action); QVERIFY(combo2); // widget is deleted using deleteLater(), so process that posted event QCoreApplication::sendPostedEvents(combo2, QEvent::DeferredDelete); QVERIFY(!combo2); delete action; QVERIFY(!combo1); QVERIFY(!combo2); } void tst_QWidgetAction::keepOwnership() { QPointer combo = new QComboBox; QWidgetAction *action = new QWidgetAction(0); action->setDefaultWidget(combo); { QToolBar *tb = new QToolBar; tb->addAction(action); QVERIFY(combo->parent() == tb); delete tb; } QVERIFY(combo); delete action; QVERIFY(!combo); } void tst_QWidgetAction::visibility() { { QWidgetAction *a = new QWidgetAction(0); QComboBox *combo = new QComboBox; a->setDefaultWidget(combo); QToolBar *tb = new QToolBar; tb->addAction(a); QVERIFY(!combo->isVisible()); tb->show(); QVERIFY(combo->isVisible()); delete tb; delete a; } { QWidgetAction *a = new QWidgetAction(0); QComboBox *combo = new QComboBox; a->setDefaultWidget(combo); QToolBar *tb = new QToolBar; tb->addAction(a); QVERIFY(!combo->isVisible()); QToolBar *tb2 = new QToolBar; tb->removeAction(a); tb2->addAction(a); QVERIFY(!combo->isVisible()); tb2->show(); QVERIFY(combo->isVisible()); delete tb; delete tb2; delete a; } } void tst_QWidgetAction::setEnabled() { QToolBar toolbar; QComboBox *combobox = new QComboBox; QAction *action = toolbar.addWidget(combobox); toolbar.show(); QVERIFY(action->isEnabled()); QVERIFY(combobox->isEnabled()); action->setEnabled(false); QVERIFY(!action->isEnabled()); QVERIFY(!combobox->isEnabled()); action->setEnabled(true); QVERIFY(action->isEnabled()); QVERIFY(combobox->isEnabled()); combobox->setEnabled(false); QVERIFY(!combobox->isEnabled()); combobox->setEnabled(true); QVERIFY(action->isEnabled()); QVERIFY(combobox->isEnabled()); QWidgetAction aw(0); aw.setEnabled(false); QVERIFY(!aw.isEnabled()); combobox = new QComboBox; aw.setDefaultWidget(combobox); QVERIFY(!aw.isEnabled()); QVERIFY(!combobox->isEnabled()); // Make sure we don't change the default widget's Qt::WA_ForceDisabled attribute // during a normal disable/enable operation (task 207433). { QToolBar toolBar; QWidget widget; toolBar.addWidget(&widget); // creates a QWidgetAction and sets 'widget' as the default widget. QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled)); toolBar.setEnabled(false); QVERIFY(toolBar.testAttribute(Qt::WA_ForceDisabled)); QVERIFY(!widget.isEnabled()); QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled)); toolBar.setEnabled(true); QVERIFY(widget.isEnabled()); QVERIFY(!widget.testAttribute(Qt::WA_ForceDisabled)); } } void tst_QWidgetAction::popup() { QPointer l = new QLabel("test"); QWidgetAction action(0); action.setDefaultWidget(l); { QMenu menu; menu.addAction(&action); QTimer::singleShot(0, &menu, SLOT(close())); menu.exec(); } QVERIFY(!l.isNull()); delete l; } class CrashedAction : public QWidgetAction { public: inline CrashedAction(QObject *parent) : QWidgetAction(parent) { } virtual QWidget *createWidget(QWidget *parent) { return new QWidget(parent); } }; void tst_QWidgetAction::releaseWidgetCrash() { // this should not crash! QMainWindow *w = new QMainWindow; QAction *a = new CrashedAction(w); QMenu *menu = w->menuBar()->addMenu("Test"); menu->addAction("foo"); menu->addAction(a); menu->addAction("bar"); delete w; } QTEST_MAIN(tst_QWidgetAction) #include "tst_qwidgetaction.moc"