Warning, file /frameworks/kcompletion/autotests/kcombobox_unittest.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include <QSignalSpy> 0009 #include <QTest> 0010 #include <khistorycombobox.h> 0011 #include <klineedit.h> 0012 0013 class KTestComboBox : public KComboBox 0014 { 0015 public: 0016 KTestComboBox(bool rw, QWidget *parent = nullptr) 0017 : KComboBox(rw, parent) 0018 { 0019 } 0020 KCompletionBase *delegate() const 0021 { 0022 return KCompletionBase::delegate(); 0023 } 0024 }; 0025 0026 class KComboBox_UnitTest : public QObject 0027 { 0028 Q_OBJECT 0029 0030 private: 0031 void testComboReturnPressed(bool ctorArg) 0032 { 0033 KComboBox w(ctorArg /*initial value for editable*/); 0034 w.setEditable(true); 0035 w.setCompletionMode(KCompletion::CompletionPopup); 0036 w.addItem(QStringLiteral("Hello world")); 0037 QVERIFY(w.lineEdit()); 0038 auto lineEdit = qobject_cast<KLineEdit *>(w.lineEdit()); 0039 QVERIFY(lineEdit); 0040 0041 // set editable again, don't recreate the line edit 0042 w.setEditable(true); 0043 QCOMPARE(w.lineEdit(), lineEdit); 0044 // KLineEdit signals 0045 QSignalSpy qReturnPressedSpy(w.lineEdit(), &QLineEdit::returnPressed); 0046 0047 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0048 QSignalSpy kEditReturnPressedSpy(lineEdit, qOverload<const QString &>(&KLineEdit::returnPressed)); 0049 #endif 0050 QSignalSpy kEditReturnKeyPressedSpy(lineEdit, &KLineEdit::returnKeyPressed); 0051 0052 // KComboBox signals 0053 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0054 QSignalSpy comboReturnPressedSpy(&w, qOverload<>(&KComboBox::returnPressed)); 0055 #endif 0056 QSignalSpy comboReturnPressedStringSpy(&w, qOverload<const QString &>(&KComboBox::returnPressed)); 0057 0058 QSignalSpy comboActivatedSpy(&w, &QComboBox::textActivated); 0059 QTest::keyClick(&w, Qt::Key_Return); 0060 QCOMPARE(qReturnPressedSpy.count(), 1); 0061 0062 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0063 QCOMPARE(kEditReturnPressedSpy.count(), 1); 0064 QCOMPARE(kEditReturnPressedSpy[0][0].toString(), QString("Hello world")); 0065 #endif 0066 QCOMPARE(kEditReturnKeyPressedSpy.count(), 1); 0067 QCOMPARE(kEditReturnKeyPressedSpy.at(0).at(0).toString(), QStringLiteral("Hello world")); 0068 0069 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0070 QCOMPARE(comboReturnPressedSpy.count(), 1); 0071 #endif 0072 QCOMPARE(comboReturnPressedStringSpy.count(), 1); 0073 QCOMPARE(comboReturnPressedStringSpy[0][0].toString(), QString("Hello world")); 0074 0075 QCOMPARE(comboActivatedSpy.count(), 1); 0076 QCOMPARE(comboActivatedSpy[0][0].toString(), QString("Hello world")); 0077 } 0078 0079 private Q_SLOTS: 0080 void testComboReturnPressed() 0081 { 0082 testComboReturnPressed(false); 0083 testComboReturnPressed(true); 0084 } 0085 0086 void testHistoryComboReturnPressed() 0087 { 0088 KHistoryComboBox w; 0089 QVERIFY(qobject_cast<KLineEdit *>(w.lineEdit())); 0090 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0091 QSignalSpy comboReturnPressedSpy(&w, qOverload<>(&KComboBox::returnPressed)); 0092 #endif 0093 QSignalSpy comboReturnPressedStringSpy(&w, qOverload<const QString &>(&KComboBox::returnPressed)); 0094 connect(&w, &KHistoryComboBox::textActivated, &w, &KHistoryComboBox::addToHistory); 0095 QSignalSpy comboActivatedSpy(&w, &QComboBox::textActivated); 0096 QTest::keyClicks(&w, QStringLiteral("Hello world")); 0097 QTest::keyClick(&w, Qt::Key_Return); 0098 qApp->processEvents(); // QueuedConnection in KHistoryComboBox 0099 #if KCOMPLETION_BUILD_DEPRECATED_SINCE(5, 81) 0100 QCOMPARE(comboReturnPressedSpy.count(), 1); 0101 #endif 0102 QCOMPARE(comboReturnPressedStringSpy.count(), 1); 0103 QCOMPARE(comboReturnPressedStringSpy[0][0].toString(), QString("Hello world")); 0104 0105 QCOMPARE(comboActivatedSpy.count(), 1); 0106 QCOMPARE(comboActivatedSpy[0][0].toString(), QString("Hello world")); 0107 } 0108 0109 void testHistoryComboKeyUp() 0110 { 0111 KHistoryComboBox w; 0112 QStringList items; 0113 items << QStringLiteral("One") << QStringLiteral("Two") << QStringLiteral("Three") << QStringLiteral("Four"); 0114 w.addItems(items); 0115 QSignalSpy currentIndexChangedSpy(&w, &QComboBox::currentIndexChanged); 0116 w.completionObject()->setItems(items); 0117 QCOMPARE(w.currentIndex(), 0); 0118 QTest::keyClick(&w, Qt::Key_Up); 0119 QCOMPARE(w.currentIndex(), 1); 0120 QCOMPARE(currentIndexChangedSpy.count(), 1); 0121 QCOMPARE(currentIndexChangedSpy[0][0].toInt(), 1); 0122 } 0123 0124 void testHistoryComboInsertItems() 0125 { 0126 KHistoryComboBox combo; 0127 // uic generates code like this, let's make sure it compiles 0128 combo.insertItems(0, QStringList() << QStringLiteral("foo")); 0129 } 0130 0131 void testHistoryComboReset() 0132 { 0133 // It only tests that it doesn't crash 0134 // TODO: Finish 0135 KHistoryComboBox combo; 0136 QStringList items; 0137 items << QStringLiteral("One") << QStringLiteral("Two"); 0138 combo.addItems(items); 0139 combo.reset(); 0140 } 0141 0142 void testDeleteLineEdit() 0143 { 0144 // Test for KCombo's KLineEdit destruction 0145 KTestComboBox *testCombo = new KTestComboBox(true, nullptr); // rw, with KLineEdit 0146 testCombo->setEditable(false); // destroys our KLineEdit, with deleteLater 0147 qApp->sendPostedEvents(nullptr, QEvent::DeferredDelete); 0148 QVERIFY(testCombo->KTestComboBox::delegate() == nullptr); 0149 delete testCombo; // not needed anymore 0150 } 0151 0152 void testLineEditCompletion() 0153 { 0154 QFETCH(bool, editable); 0155 QPointer<KCompletion> completion; 0156 QPointer<KLineEdit> lineEdit; 0157 QPointer<KLineEdit> lineEdit2; 0158 0159 { 0160 // Test for KCombo's KLineEdit inheriting the completion object of the parent 0161 KTestComboBox testCombo(editable, nullptr); 0162 0163 // we only have a line edit when we are editable already 0164 QCOMPARE(static_cast<bool>(testCombo.lineEdit()), editable); 0165 0166 // we can always get a completion object 0167 // NOTE: for an editable combo, this refers to the completion object of 0168 // the internal line edit 0169 // NOTE: for a not-yet-editable combo, this refers to the completion object 0170 // that belongs to the combo directly 0171 completion = testCombo.completionObject(); 0172 QVERIFY(completion); 0173 0174 // make editable 0175 testCombo.setEditable(true); 0176 QVERIFY(completion); // completion is still alive 0177 0178 // verify that the completion object was set on the line edit 0179 lineEdit = qobject_cast<KLineEdit *>(testCombo.lineEdit()); 0180 QVERIFY(lineEdit); 0181 QVERIFY(lineEdit->compObj()); 0182 QCOMPARE(lineEdit->compObj(), completion.data()); 0183 QCOMPARE(testCombo.completionObject(), completion.data()); 0184 0185 // don't lose the completion and don't crash when we set a new line edit 0186 // NOTE: only reuse the completion when it belongs to the combo box 0187 lineEdit2 = new KLineEdit(&testCombo); 0188 QVERIFY(!lineEdit2->compObj()); 0189 testCombo.setLineEdit(lineEdit2); 0190 QVERIFY(!lineEdit); // first line edit got deleted now 0191 if (editable) { 0192 QVERIFY(!completion); // got deleted with the line edit 0193 // but we get a new one from the second line edit 0194 completion = testCombo.completionObject(); 0195 } 0196 QVERIFY(completion); 0197 QCOMPARE(lineEdit2->compObj(), completion.data()); 0198 QCOMPARE(testCombo.completionObject(), completion.data()); 0199 } 0200 0201 // ensure nothing gets leaked 0202 QVERIFY(!completion); 0203 QVERIFY(!lineEdit2); 0204 } 0205 0206 void testLineEditCompletion_data() 0207 { 0208 QTest::addColumn<bool>("editable"); 0209 QTest::newRow("deferred-editable") << false; 0210 QTest::newRow("editable") << true; 0211 } 0212 0213 void testSelectionResetOnReturn() 0214 { 0215 // void QComboBoxPrivate::_q_returnPressed() calls lineEdit->deselect() 0216 KHistoryComboBox *testCombo = new KHistoryComboBox(true, nullptr); 0217 QCOMPARE(testCombo->insertPolicy(), QComboBox::NoInsert); // not the Qt default; KHistoryComboBox changes that 0218 QTest::keyClicks(testCombo, QStringLiteral("Hello world")); 0219 testCombo->lineEdit()->setSelection(5, 3); 0220 QVERIFY(testCombo->lineEdit()->hasSelectedText()); 0221 QTest::keyClick(testCombo, Qt::Key_Return); 0222 // Changed in Qt5: it only does that if insertionPolicy isn't NoInsert. 0223 // Should we add a lineEdit()->deselect() in KHistoryComboBox? Why does this matter? 0224 QEXPECT_FAIL("", "Qt5: QComboBox doesn't deselect text anymore on returnPressed", Continue); 0225 QVERIFY(!testCombo->lineEdit()->hasSelectedText()); 0226 } 0227 }; 0228 0229 QTEST_MAIN(KComboBox_UnitTest) 0230 0231 #include "kcombobox_unittest.moc"