File indexing completed on 2024-04-28 15:31:53

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2009 Daniel Calviño Sánchez <danxuliu@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kselectaction_unittest.h"
0009 #include <QComboBox>
0010 #include <QMainWindow>
0011 #include <QStandardItemModel>
0012 #include <QTest>
0013 #include <kselectaction.h>
0014 #include <qtoolbar.h>
0015 
0016 QTEST_MAIN(KSelectAction_UnitTest)
0017 
0018 void KSelectAction_UnitTest::testSetToolTipBeforeRequestingComboBoxWidget()
0019 {
0020     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0021     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0022     selectAction.setToolTip(QStringLiteral("Test"));
0023     selectAction.setEnabled(false); // also test disabling the action
0024 
0025     QWidget parent;
0026     QWidget *widget = selectAction.requestWidget(&parent);
0027 
0028     QVERIFY(widget);
0029     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0030     QVERIFY(comboBox);
0031     QCOMPARE(comboBox->toolTip(), QStringLiteral("Test"));
0032     QCOMPARE(comboBox->isEnabled(), false);
0033 }
0034 
0035 void KSelectAction_UnitTest::testSetToolTipAfterRequestingComboBoxWidget()
0036 {
0037     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0038     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0039 
0040     QWidget parent;
0041     QWidget *widget = selectAction.requestWidget(&parent);
0042 
0043     selectAction.setToolTip(QStringLiteral("Test"));
0044     selectAction.setEnabled(false); // also test disabling the action
0045 
0046     QVERIFY(widget);
0047     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0048     QVERIFY(comboBox);
0049     QCOMPARE(comboBox->toolTip(), QStringLiteral("Test"));
0050     QCOMPARE(comboBox->isEnabled(), false);
0051 }
0052 
0053 void KSelectAction_UnitTest::testSetToolTipBeforeRequestingToolButtonWidget()
0054 {
0055     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0056     selectAction.setToolBarMode(KSelectAction::MenuMode);
0057     selectAction.setToolTip(QStringLiteral("Test"));
0058 
0059     QToolBar toolBar;
0060     // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
0061     //(in ComboBoxMode the widget is released automatically when it is
0062     // destroyed). When the action is added to the QToolBar, it requests and
0063     // releases the widget as needed.
0064     toolBar.addAction(&selectAction);
0065     QWidget *widget = toolBar.widgetForAction(&selectAction);
0066 
0067     QVERIFY(widget);
0068     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0069     QVERIFY(toolButton);
0070     QCOMPARE(toolButton->toolTip(), QStringLiteral("Test"));
0071 }
0072 
0073 void KSelectAction_UnitTest::testSetToolTipAfterRequestingToolButtonWidget()
0074 {
0075     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0076     selectAction.setToolBarMode(KSelectAction::MenuMode);
0077 
0078     QToolBar toolBar;
0079     // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
0080     //(in ComboBoxMode the widget is released automatically when it is
0081     // destroyed). When the action is added to the QToolBar, it requests and
0082     // releases the widget as needed.
0083     toolBar.addAction(&selectAction);
0084     QWidget *widget = toolBar.widgetForAction(&selectAction);
0085 
0086     selectAction.setToolTip(QStringLiteral("Test"));
0087 
0088     QVERIFY(widget);
0089     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0090     QVERIFY(toolButton);
0091     QCOMPARE(toolButton->toolTip(), QStringLiteral("Test"));
0092 }
0093 
0094 void KSelectAction_UnitTest::testSetWhatsThisBeforeRequestingComboBoxWidget()
0095 {
0096     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0097     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0098     selectAction.setWhatsThis(QStringLiteral("Test"));
0099 
0100     QWidget parent;
0101     QWidget *widget = selectAction.requestWidget(&parent);
0102 
0103     QVERIFY(widget);
0104     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0105     QVERIFY(comboBox);
0106     QCOMPARE(comboBox->whatsThis(), QStringLiteral("Test"));
0107 }
0108 
0109 void KSelectAction_UnitTest::testSetWhatsThisAfterRequestingComboBoxWidget()
0110 {
0111     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0112     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0113 
0114     QWidget parent;
0115     QWidget *widget = selectAction.requestWidget(&parent);
0116 
0117     selectAction.setWhatsThis(QStringLiteral("Test"));
0118 
0119     QVERIFY(widget);
0120     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0121     QVERIFY(comboBox);
0122     QCOMPARE(comboBox->whatsThis(), QStringLiteral("Test"));
0123 }
0124 
0125 void KSelectAction_UnitTest::testSetWhatsThisBeforeRequestingToolButtonWidget()
0126 {
0127     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0128     selectAction.setToolBarMode(KSelectAction::MenuMode);
0129     selectAction.setWhatsThis(QStringLiteral("Test"));
0130 
0131     QToolBar toolBar;
0132     // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
0133     //(in ComboBoxMode the widget is released automatically when it is
0134     // destroyed). When the action is added to the QToolBar, it requests and
0135     // releases the widget as needed.
0136     toolBar.addAction(&selectAction);
0137     QWidget *widget = toolBar.widgetForAction(&selectAction);
0138 
0139     QVERIFY(widget);
0140     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0141     QVERIFY(toolButton);
0142     QCOMPARE(toolButton->whatsThis(), QStringLiteral("Test"));
0143 }
0144 
0145 void KSelectAction_UnitTest::testSetWhatsThisAfterRequestingToolButtonWidget()
0146 {
0147     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0148     selectAction.setToolBarMode(KSelectAction::MenuMode);
0149 
0150     QToolBar toolBar;
0151     // Don't use requestWidget, as it needs a releaseWidget when used in MenuMode
0152     //(in ComboBoxMode the widget is released automatically when it is
0153     // destroyed). When the action is added to the QToolBar, it requests and
0154     // releases the widget as needed.
0155     toolBar.addAction(&selectAction);
0156     QWidget *widget = toolBar.widgetForAction(&selectAction);
0157 
0158     selectAction.setWhatsThis(QStringLiteral("Test"));
0159 
0160     QVERIFY(widget);
0161     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0162     QVERIFY(toolButton);
0163     QCOMPARE(toolButton->whatsThis(), QStringLiteral("Test"));
0164 }
0165 
0166 void KSelectAction_UnitTest::testChildActionStateChangeComboMode()
0167 {
0168     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0169     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0170     QWidget parent;
0171     QWidget *widget = selectAction.requestWidget(&parent);
0172     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0173     QVERIFY(comboBox);
0174     const QString itemText = QStringLiteral("foo");
0175     QAction *childAction = selectAction.addAction(itemText);
0176     QCOMPARE(comboBox->itemText(0), itemText);
0177     childAction->setEnabled(false);
0178     // There's no API for item-is-enabled, need to go via the internal model like kselectaction does...
0179     QStandardItemModel *model = qobject_cast<QStandardItemModel *>(comboBox->model());
0180     QVERIFY(model);
0181     QVERIFY(!model->item(0)->isEnabled());
0182 
0183     // Now remove the action
0184     selectAction.removeAction(childAction);
0185     QCOMPARE(comboBox->count(), 0);
0186     delete childAction;
0187 }
0188 
0189 // Bug 436808
0190 void KSelectAction_UnitTest::testCrashComboBoxDestruction()
0191 {
0192     QWidget parentWidget;
0193     QMainWindow mainWindow(&parentWidget);
0194 
0195     // Create a KSelectAction in a QWidget
0196     auto *comboSelect = new KSelectAction(QStringLiteral("selectAction"), &mainWindow);
0197 
0198     // Add some actions and create some connections to them
0199     for (int i = 0; i < 7; ++i) {
0200         QAction *action = comboSelect->addAction(QStringLiteral("Combo Action %1").arg(i));
0201         connect(action, &QAction::triggered, &mainWindow, []() {
0202             // Empty, just creating a connection to trigger a crash
0203         });
0204     }
0205 
0206     comboSelect->setToolBarMode(KSelectAction::ComboBoxMode);
0207     QToolBar *toolBar = mainWindow.addToolBar(QStringLiteral("Test"));
0208 
0209     // Add the KSelectAction to a toolbar
0210     toolBar->addAction(comboSelect);
0211     mainWindow.show();
0212     mainWindow.activateWindow();
0213     // Wait for window to show
0214     QVERIFY(QTest::qWaitForWindowActive(&mainWindow));
0215 
0216     // When this method finishes and the QWidget is destroyed, and there
0217     // should be no crash in KSelectActionPrivate::comboBoxDeleted()
0218 }
0219 
0220 void KSelectAction_UnitTest::testRequestWidgetComboBoxModeWidgetParent()
0221 {
0222     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0223     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0224 
0225     QToolBar toolBar;
0226     toolBar.addAction(&selectAction);
0227     QWidget *widget = toolBar.widgetForAction(&selectAction);
0228 
0229     QVERIFY(widget);
0230     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0231     QVERIFY(comboBox);
0232     QVERIFY(!comboBox->isEnabled());
0233 }
0234 
0235 void KSelectAction_UnitTest::testRequestWidgetComboBoxModeWidgetParentSeveralActions()
0236 {
0237     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0238     selectAction.setToolBarMode(KSelectAction::ComboBoxMode);
0239 
0240     selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
0241     selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
0242     selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
0243 
0244     QToolBar toolBar;
0245     toolBar.addAction(&selectAction);
0246     QWidget *widget = toolBar.widgetForAction(&selectAction);
0247 
0248     QVERIFY(widget);
0249     QComboBox *comboBox = qobject_cast<QComboBox *>(widget);
0250     QVERIFY(comboBox);
0251     QVERIFY(comboBox->isEnabled());
0252 }
0253 
0254 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParent()
0255 {
0256     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0257     selectAction.setToolBarMode(KSelectAction::MenuMode);
0258 
0259     QToolBar toolBar;
0260     toolBar.addAction(&selectAction);
0261     QWidget *widget = toolBar.widgetForAction(&selectAction);
0262 
0263     QVERIFY(widget);
0264     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0265     QVERIFY(toolButton);
0266     QVERIFY(!toolButton->isEnabled());
0267     QVERIFY(toolButton->autoRaise());
0268     QCOMPARE((int)toolButton->focusPolicy(), (int)Qt::NoFocus);
0269     QCOMPARE(toolButton->defaultAction(), (QAction *)&selectAction);
0270     QCOMPARE(toolButton->actions().count(), 1);
0271     QCOMPARE(toolButton->actions().at(0)->text(), QStringLiteral("selectAction"));
0272 }
0273 
0274 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentSeveralActions()
0275 {
0276     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0277     selectAction.setToolBarMode(KSelectAction::MenuMode);
0278 
0279     selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
0280     selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
0281     selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
0282 
0283     QToolBar toolBar;
0284     toolBar.addAction(&selectAction);
0285     QWidget *widget = toolBar.widgetForAction(&selectAction);
0286 
0287     QVERIFY(widget);
0288     QToolButton *toolButton = qobject_cast<QToolButton *>(widget);
0289     QVERIFY(toolButton);
0290     QVERIFY(toolButton->isEnabled());
0291     QVERIFY(toolButton->autoRaise());
0292     QCOMPARE((int)toolButton->focusPolicy(), (int)Qt::NoFocus);
0293     QCOMPARE(toolButton->defaultAction(), (QAction *)&selectAction);
0294     QCOMPARE(toolButton->actions().count(), 4);
0295     QCOMPARE(toolButton->actions().at(0)->text(), QStringLiteral("selectAction"));
0296     QCOMPARE(toolButton->actions().at(1)->text(), QStringLiteral("action1"));
0297     QCOMPARE(toolButton->actions().at(2)->text(), QStringLiteral("action2"));
0298     QCOMPARE(toolButton->actions().at(3)->text(), QStringLiteral("action3"));
0299 }
0300 
0301 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentAddActions()
0302 {
0303     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0304     selectAction.setToolBarMode(KSelectAction::MenuMode);
0305 
0306     QToolBar toolBar;
0307     toolBar.addAction(&selectAction);
0308     QWidget *widget = toolBar.widgetForAction(&selectAction);
0309 
0310     QVERIFY(widget);
0311     QVERIFY(!widget->isEnabled());
0312 
0313     selectAction.addAction(new QAction(QStringLiteral("action1"), &selectAction));
0314     selectAction.addAction(new QAction(QStringLiteral("action2"), &selectAction));
0315     selectAction.addAction(new QAction(QStringLiteral("action3"), &selectAction));
0316 
0317     QVERIFY(widget->isEnabled());
0318     QCOMPARE(widget->actions().count(), 4);
0319     QCOMPARE(widget->actions().at(0)->text(), QStringLiteral("selectAction"));
0320     QCOMPARE(widget->actions().at(1)->text(), QStringLiteral("action1"));
0321     QCOMPARE(widget->actions().at(2)->text(), QStringLiteral("action2"));
0322     QCOMPARE(widget->actions().at(3)->text(), QStringLiteral("action3"));
0323 }
0324 
0325 void KSelectAction_UnitTest::testRequestWidgetMenuModeWidgetParentRemoveActions()
0326 {
0327     KSelectAction selectAction(QStringLiteral("selectAction"), nullptr);
0328     selectAction.setToolBarMode(KSelectAction::MenuMode);
0329 
0330     QToolBar toolBar;
0331     toolBar.addAction(&selectAction);
0332     QWidget *widget = toolBar.widgetForAction(&selectAction);
0333 
0334     QVERIFY(widget);
0335 
0336     QAction *action1 = new QAction(QStringLiteral("action1"), &selectAction);
0337     selectAction.addAction(action1);
0338     QAction *action2 = new QAction(QStringLiteral("action2"), &selectAction);
0339     selectAction.addAction(action2);
0340     QAction *action3 = new QAction(QStringLiteral("action3"), &selectAction);
0341     selectAction.addAction(action3);
0342 
0343     delete selectAction.removeAction(action1);
0344     delete selectAction.removeAction(action2);
0345     delete selectAction.removeAction(action3);
0346 
0347     QVERIFY(!widget->isEnabled());
0348     QCOMPARE(widget->actions().count(), 1);
0349     QCOMPARE(widget->actions().at(0)->text(), QStringLiteral("selectAction"));
0350 }
0351 
0352 #include "moc_kselectaction_unittest.cpp"