File indexing completed on 2024-04-21 14:55:14

0001 /* This file is part of the KDE libraries
0002 
0003     Copyright (c) 2010 Romain Perier <mrpouet@gentoo.org>
0004 
0005     This library is free software; you can redistribute it and/or
0006     modify it under the terms of the GNU Library General Public
0007     License as published by the Free Software Foundation; either
0008     version 2 of the License, or (at your option) any later version.
0009 
0010     This library is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013     Library General Public License for more details.
0014 
0015     You should have received a copy of the GNU Library General Public License
0016     along with this library; see the file COPYING.LIB.  If not, write to
0017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018     Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include <QApplication>
0022 #include <QCheckBox>
0023 #include <QSignalSpy>
0024 #include <kdialog.h>
0025 #include <QPushButton>
0026 #include <QPointer>
0027 #include <QTest>
0028 
0029 Q_DECLARE_METATYPE(KDialog::ButtonCode)
0030 
0031 class KDialog_UnitTest : public QObject
0032 {
0033     Q_OBJECT
0034 public:
0035     KDialog_UnitTest()
0036     {
0037         qRegisterMetaType<KDialog::ButtonCode>("KDialog::ButtonCode");
0038     }
0039 
0040 private: // helper methods
0041     void checkOtherButtonsAreNotDefault(KDialog &dialog, KDialog::ButtonCode id)
0042     {
0043         KDialog::ButtonCode codes[] = { KDialog::Ok, KDialog::Apply, KDialog::Cancel,
0044                                         KDialog::No, KDialog::Yes
0045                                       };
0046         for (int i = 0; i < 5; i++) {
0047             if (codes[i] == id) {
0048                 continue;
0049             }
0050             QVERIFY(!dialog.button(codes[i])->isDefault());
0051         }
0052     }
0053 
0054     void checkSetDefaultButton(KDialog &dialog, KDialog::ButtonCode id)
0055     {
0056         dialog.setDefaultButton(id);
0057         QCOMPARE(dialog.defaultButton(), id);
0058         QVERIFY(dialog.button(id)->isDefault());
0059         checkOtherButtonsAreNotDefault(dialog, id);
0060     }
0061 
0062 private Q_SLOTS:
0063     // Test if buttons are correctly stored
0064     // in the KDialog, then try to get back them.
0065     // (only common buttons are tested)
0066     void testDefaultButton()
0067     {
0068         KDialog dialog;
0069         dialog.setButtons(KDialog::Ok | KDialog::Apply
0070                           | KDialog::Cancel | KDialog::No | KDialog::Yes);
0071         checkSetDefaultButton(dialog, KDialog::Ok);
0072         checkSetDefaultButton(dialog, KDialog::Apply);
0073         checkSetDefaultButton(dialog, KDialog::Cancel);
0074         checkSetDefaultButton(dialog, KDialog::No);
0075         dialog.setDefaultButton(KDialog::NoDefault);
0076         checkOtherButtonsAreNotDefault(dialog, KDialog::NoDefault);
0077         checkSetDefaultButton(dialog, KDialog::Yes);
0078         dialog.setDefaultButton(KDialog::None); // #148969
0079         checkOtherButtonsAreNotDefault(dialog, KDialog::None);
0080     }
0081 
0082     void testFutureDefaultButton()
0083     {
0084         // Test setting a default button that doesn't exist yet
0085         KDialog dialog;
0086         KDialog::ButtonCode id = KDialog::Apply;
0087         dialog.setDefaultButton(id);
0088         QCOMPARE(dialog.defaultButton(), id);
0089         QCOMPARE(dialog.button(id), static_cast<QPushButton *>(nullptr));
0090 
0091         dialog.setButtons(KDialog::Ok | KDialog::Apply
0092                           | KDialog::Cancel | KDialog::No | KDialog::Yes);
0093         QCOMPARE(dialog.defaultButton(), KDialog::Apply);
0094         QVERIFY(dialog.button(id)->isDefault());
0095         QVERIFY(!dialog.button(KDialog::Ok)->isDefault());
0096     }
0097 
0098     // Test what happens with giving focus to widgets before the window is shown
0099     // This is mostly Qt experimentation, unrelated to KDialog's own code
0100     void testFocus()
0101     {
0102         KDialog dialog;
0103         dialog.setButtons(KDialog::Ok | KDialog::Cancel);
0104         QCheckBox *checkBox = new QCheckBox("Hello world !", &dialog);
0105         QPushButton *okButton = dialog.button(KDialog::Ok);
0106         okButton->setFocus();
0107         QVERIFY(!okButton->hasFocus()); // confusing, heh?
0108         QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(okButton));
0109         checkBox->setFocus();
0110         QVERIFY(!checkBox->hasFocus()); // confusing, heh?
0111         QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(checkBox));
0112     }
0113 
0114     // Ensure that only the defaultButton() receives the keyEvent
0115     // (it should get the focus)
0116     void testKeyPressEvents()
0117     {
0118         KDialog dialog;
0119         QSignalSpy qCancelClickedSpy(&dialog, SIGNAL(cancelClicked()));
0120         QSignalSpy qOkClickedSpy(&dialog, SIGNAL(okClicked()));
0121         dialog.setButtons(KDialog::Ok | KDialog::Cancel);
0122         dialog.setDefaultButton(KDialog::Cancel);
0123         dialog.show();
0124         // Necessary after show(), otherwise dialog.focusWidget() returns NULL
0125         QApplication::setActiveWindow(&dialog);
0126         QVERIFY(dialog.focusWidget());
0127         // Graphically always the focused widget receives the keyEvent
0128         // (otherwises it does not make sense)
0129         QTest::keyClick(dialog.focusWidget(), Qt::Key_Return);
0130         QCOMPARE(qCancelClickedSpy.count(), 1);
0131         QCOMPARE(qOkClickedSpy.count(), 0);
0132     }
0133 
0134     void testCheckBoxKeepsFocus()
0135     {
0136         KDialog dialog;
0137         QCheckBox checkBox("Hello world !", &dialog);
0138         QSignalSpy qCancelClickedSpy(&dialog, SIGNAL(cancelClicked()));
0139         dialog.setButtons(KDialog::Ok | KDialog::Cancel);
0140         checkBox.setFocus();
0141         dialog.setMainWidget(&checkBox);
0142         dialog.setDefaultButton(KDialog::Cancel);
0143         dialog.show();
0144         QApplication::setActiveWindow(&dialog);
0145         QVERIFY(checkBox.hasFocus());
0146         QVERIFY(!dialog.button(KDialog::Cancel)->hasFocus());
0147         QCOMPARE(dialog.focusWidget(), static_cast<QWidget *>(&checkBox));
0148         QTest::keyClick(dialog.focusWidget(), Qt::Key_Return);
0149         QCOMPARE(qCancelClickedSpy.count(), 1);
0150     }
0151 
0152     // Test if buttons labels are correctly handled
0153     // assuming that testButtonDefault() passed
0154     void testButtonText()
0155     {
0156         KDialog dialog;
0157         KDialog::ButtonCode id = KDialog::Ok;
0158         QString text = "it's okay !";
0159         dialog.setButtons(id);
0160         dialog.setButtonText(id, text);
0161         QCOMPARE(dialog.buttonText(id), text);
0162         QCOMPARE(dialog.button(id)->text(), text);
0163     }
0164 
0165     void testButtonToolTip()
0166     {
0167         KDialog dialog;
0168         KDialog::ButtonCode id = KDialog::Ok;
0169         QString tooltip = "This is okay button";
0170         dialog.setButtons(id);
0171         dialog.setButtonToolTip(id, tooltip);
0172         QCOMPARE(dialog.buttonToolTip(id), tooltip);
0173         QCOMPARE(dialog.button(id)->toolTip(), tooltip);
0174     }
0175 
0176     void testButtonWhatsThis()
0177     {
0178         KDialog dialog;
0179         KDialog::ButtonCode id = KDialog::Ok;
0180         QString whatsthis = "A simple button to press okay";
0181         dialog.setButtons(id);
0182         dialog.setButtonWhatsThis(id, whatsthis);
0183         QCOMPARE(dialog.buttonWhatsThis(id), whatsthis);
0184         QCOMPARE(dialog.button(id)->whatsThis(), whatsthis);
0185     }
0186 
0187     void testDeleteOnClose_data()
0188     {
0189         QTest::addColumn<KDialog::ButtonCode>("button");
0190         QTest::addColumn<int>("emitAccepted");
0191         QTest::addColumn<int>("emitRejected");
0192 
0193         QTest::newRow("Ok") << KDialog::Ok << 1 << 0;
0194         QTest::newRow("Cancel") << KDialog::Cancel << 0 << 1;
0195         QTest::newRow("Close") << KDialog::Close << 0 << 0;
0196     }
0197 
0198     void testDeleteOnClose()
0199     {
0200         QFETCH(KDialog::ButtonCode, button);
0201         QFETCH(int, emitAccepted);
0202         QFETCH(int, emitRejected);
0203 
0204         KDialog *dialog = new KDialog;
0205         QPointer<KDialog> dialogPointer(dialog);
0206         dialog->setAttribute(Qt::WA_DeleteOnClose);
0207         dialog->setButtons(KDialog::Ok | button);
0208         QSignalSpy qAcceptedSpy(dialog, SIGNAL(accepted()));
0209         QSignalSpy qRejectedSpy(dialog, SIGNAL(rejected()));
0210         dialog->show(); // KDialog::closeEvent tests for isHidden
0211         dialog->button(button)->click();
0212         QCOMPARE(qAcceptedSpy.count(), emitAccepted);
0213         QCOMPARE(qRejectedSpy.count(), emitRejected);
0214         QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
0215         QVERIFY(dialogPointer.isNull()); // deletion happened
0216     }
0217 
0218     // Closing the dialog using the window manager button
0219     void testCloseDialogWithDeleteOnClose_data()
0220     {
0221         QTest::addColumn<KDialog::ButtonCode>("button");
0222         QTest::addColumn<int>("emitRejected");
0223         QTest::addColumn<QString>("signal");
0224 
0225         QTest::newRow("Cancel") << KDialog::Cancel << 1 << SIGNAL(cancelClicked());
0226         QTest::newRow("Close") << KDialog::Close << 0 << SIGNAL(closeClicked());
0227     }
0228 
0229     void testCloseDialogWithDeleteOnClose()
0230     {
0231         QFETCH(KDialog::ButtonCode, button);
0232         QFETCH(int, emitRejected);
0233         QFETCH(QString, signal);
0234 
0235         KDialog *dialog = new KDialog;
0236         QPointer<KDialog> dialogPointer(dialog);
0237         dialog->setAttribute(Qt::WA_DeleteOnClose);
0238         dialog->setButtons(KDialog::Ok | button);
0239         QSignalSpy qCancelOrCloseClickedSpy(dialog, signal.toLatin1().constData());
0240         QSignalSpy qRejectedSpy(dialog, SIGNAL(rejected()));
0241         dialog->show(); // KDialog::closeEvent tests for isHidden
0242         dialog->close();
0243         if (qRejectedSpy.isEmpty() && emitRejected) {
0244             QVERIFY(qRejectedSpy.wait(5000));
0245         }
0246         if (qCancelOrCloseClickedSpy.isEmpty()) {
0247             QVERIFY(qCancelOrCloseClickedSpy.wait(5000));
0248         }
0249         QCOMPARE(qRejectedSpy.count(), emitRejected); // and then rejected is emitted as well
0250         QCOMPARE(qCancelOrCloseClickedSpy.count(), 1); // KDialog emulated cancel or close being clicked
0251         qApp->sendPostedEvents(); // DeferredDelete
0252         QVERIFY(dialogPointer.isNull()); // deletion happened
0253     }
0254 };
0255 
0256 QTEST_MAIN(KDialog_UnitTest)
0257 #include "kdialog_unittest.moc"