File indexing completed on 2024-11-17 05:01:36
0001 /* This file is part of the KDE libraries 0002 SPDX-FileCopyrightText: 2014 Dominik Haumann <dhaumann@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include <KDirOperator> 0008 #include <KFileWidget> 0009 #include <QDir> 0010 #include <QFileDialog> 0011 #include <QTemporaryDir> 0012 #include <QTemporaryFile> 0013 #include <QTest> 0014 #include <QTimer> 0015 0016 Q_DECLARE_METATYPE(QFileDialog::ViewMode) 0017 Q_DECLARE_METATYPE(QFileDialog::FileMode) 0018 Q_DECLARE_METATYPE(KFile::FileView) 0019 Q_DECLARE_METATYPE(KFile::Modes) 0020 0021 class KFileDialog_UnitTest : public QObject 0022 { 0023 Q_OBJECT 0024 private Q_SLOTS: 0025 void initTestCase() 0026 { 0027 } 0028 0029 void init() 0030 { 0031 } 0032 0033 void cleanupTestCase() 0034 { 0035 } 0036 0037 void testSetNameFilters() 0038 { 0039 QFileDialog dialog; 0040 0041 QStringList nameFilterList = QStringList() << QStringLiteral("c (*.cpp)") << QStringLiteral("h (*.h)"); 0042 dialog.setNameFilters(nameFilterList); 0043 QCOMPARE(dialog.nameFilters(), nameFilterList); 0044 } 0045 0046 void testSelectNameFilter() 0047 { 0048 QFileDialog dialog; 0049 0050 QStringList nameFilterList = QStringList() << QStringLiteral("c (*.cpp)") << QStringLiteral("h (*.h)"); 0051 dialog.setNameFilters(nameFilterList); 0052 QCOMPARE(dialog.nameFilters(), nameFilterList); 0053 0054 QString selectNameFilter(QStringLiteral("h (*.h)")); 0055 dialog.selectNameFilter(selectNameFilter); 0056 QEXPECT_FAIL("", "Does currently not work. Works, once the dialog gets shown, though.", Continue); 0057 QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); 0058 0059 dialog.show(); 0060 QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); 0061 } 0062 0063 void testSelectNameFilterMultipleMatching() 0064 { 0065 QFileDialog dialog; 0066 0067 QStringList nameFilterList = QStringList() << QStringLiteral("c (*.cpp)") << QStringLiteral("h1 (*.h)") << QStringLiteral("h2 (*.h)"); 0068 dialog.setNameFilters(nameFilterList); 0069 QCOMPARE(dialog.nameFilters(), nameFilterList); 0070 0071 QString selectNameFilter(QStringLiteral("h2 (*.h)")); 0072 dialog.selectNameFilter(selectNameFilter); 0073 QEXPECT_FAIL("", "Does currently not work. Works, once the dialog gets shown, though.", Continue); 0074 QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); 0075 0076 dialog.show(); 0077 QCOMPARE(dialog.selectedNameFilter(), selectNameFilter); 0078 } 0079 0080 void testSelectedMimeTypeFilter_data() 0081 { 0082 QTest::addColumn<QStringList>("mimeTypeFilters"); 0083 QTest::addColumn<QString>("targetMimeTypeFilter"); 0084 0085 const auto headerMime = QStringLiteral("text/x-chdr"); 0086 const auto jsonMime = QStringLiteral("application/json"); 0087 const auto zipMime = QStringLiteral("application/zip"); 0088 0089 QTest::newRow("single mime filter (C header file)") << QStringList{headerMime} << headerMime; 0090 0091 QTest::newRow("single mime filter (JSON file)") << QStringList{jsonMime} << jsonMime; 0092 0093 QTest::newRow("multiple mime filters") << QStringList{jsonMime, zipMime} << jsonMime; 0094 } 0095 0096 void testSelectedMimeTypeFilter() 0097 { 0098 QFileDialog dialog; 0099 0100 QFETCH(QStringList, mimeTypeFilters); 0101 dialog.setMimeTypeFilters(mimeTypeFilters); 0102 0103 QFETCH(QString, targetMimeTypeFilter); 0104 dialog.selectMimeTypeFilter(targetMimeTypeFilter); 0105 0106 dialog.show(); 0107 QCOMPARE(dialog.selectedMimeTypeFilter(), targetMimeTypeFilter); 0108 } 0109 0110 void testFallbackOnFirstFilterInSaveMode() 0111 { 0112 QFileDialog dialog; 0113 dialog.setAcceptMode(QFileDialog::AcceptSave); 0114 dialog.setMimeTypeFilters({QStringLiteral("application/json"), QStringLiteral("application/zip")}); 0115 dialog.show(); 0116 QCOMPARE(dialog.selectedMimeTypeFilter(), QStringLiteral("application/json")); 0117 } 0118 0119 void testSetDirectory() 0120 { 0121 QFileDialog dialog; 0122 dialog.setDirectory(QDir::rootPath()); 0123 QCOMPARE(dialog.directory().absolutePath(), QDir::rootPath()); 0124 } 0125 0126 void testSelectUrl() 0127 { 0128 QTemporaryFile tempFile(m_tempDir.path() + "/kfiledialogtest_XXXXXX"); 0129 tempFile.setAutoRemove(true); 0130 tempFile.open(); 0131 QString tempName = tempFile.fileName(); 0132 QUrl url = QUrl::fromLocalFile(tempName); 0133 int idx = tempName.lastIndexOf('/'); 0134 QUrl directoryUrl = QUrl::fromLocalFile(tempName.left(idx + 1)); 0135 0136 QFileDialog dialog; 0137 dialog.selectUrl(url); 0138 dialog.show(); 0139 0140 // check if dialog was set to base directory url of the passed file url 0141 QCOMPARE(dialog.directoryUrl(), directoryUrl); 0142 } 0143 0144 void testGetSaveFileUrl() 0145 { 0146 QObject lambdaGuard; 0147 QTemporaryFile tempFile(m_tempDir.path() + "/kfiledialogtest_XXXXXX"); 0148 tempFile.open(); 0149 const QString tempName = tempFile.fileName(); 0150 const QUrl url = QUrl::fromLocalFile(tempName); 0151 0152 // Need to use a lambda and not just QTest::qWaitForWindowExposed(); 0153 // because with the static getSaveFileUrl we do not have access 0154 // to the QFileDialog object, so instead we hook to a signal 0155 KFileWidget::OperationMode saveFileOperationMode = KFileWidget::Other; 0156 connect(qApp, &QGuiApplication::focusWindowChanged, &lambdaGuard, [&saveFileOperationMode] { 0157 KFileWidget *fileWidget = findFileWidget(); 0158 saveFileOperationMode = fileWidget->operationMode(); 0159 qApp->activeWindow()->close(); 0160 }); 0161 0162 QFileDialog::getSaveFileUrl(nullptr, QString(), url); 0163 0164 QCOMPARE(saveFileOperationMode, KFileWidget::Saving); 0165 } 0166 0167 void testViewMode() 0168 { 0169 // Open a file dialog, and change view mode to tree 0170 { 0171 QFileDialog dialog; 0172 dialog.show(); 0173 0174 KFileWidget *fw = findFileWidget(); 0175 QVERIFY(fw); 0176 fw->setViewMode(KFile::Tree); 0177 fw->slotCancel(); // the saving happens there 0178 } 0179 // Open another one, and check that the view mode is now tree, change it to simple 0180 { 0181 QFileDialog dialog; 0182 dialog.show(); 0183 0184 KFileWidget *fw = findFileWidget(); 0185 QVERIFY(fw); 0186 KDirOperator *op = fw->dirOperator(); 0187 QCOMPARE(fileViewToString(op->viewMode()), fileViewToString(KFile::Tree)); 0188 fw->setViewMode(KFile::Simple); 0189 fw->slotCancel(); 0190 } 0191 // Open another one, and check that the view mode is now simple 0192 { 0193 QFileDialog dialog; 0194 dialog.show(); 0195 0196 KFileWidget *fw = findFileWidget(); 0197 QVERIFY(fw); 0198 KDirOperator *op = fw->dirOperator(); 0199 QCOMPARE(fileViewToString(op->viewMode()), fileViewToString(KFile::Simple)); 0200 fw->setViewMode(KFile::Detail); 0201 fw->slotCancel(); 0202 } 0203 } 0204 0205 void testOpenDialog() 0206 { 0207 // Open parentless 0208 { 0209 QFileDialog dialog; 0210 dialog.open(); 0211 0212 KFileWidget *fw = findFileWidget(); 0213 QVERIFY(fw); 0214 QCOMPARE(fw->isVisible(), true); 0215 fw->slotCancel(); 0216 } 0217 // Open with parent 0218 { 0219 QWidget w; 0220 w.show(); 0221 0222 QFileDialog dialog(&w); 0223 dialog.open(); 0224 0225 KFileWidget *fw = findFileWidget(); 0226 QVERIFY(fw); 0227 QCOMPARE(fw->isVisible(), true); 0228 fw->slotCancel(); 0229 } 0230 } 0231 0232 void testShowDialog() 0233 { 0234 // Show parentless 0235 { 0236 QFileDialog dialog; 0237 dialog.show(); 0238 0239 KFileWidget *fw = findFileWidget(); 0240 QVERIFY(fw); 0241 QCOMPARE(fw->isVisible(), true); 0242 fw->slotCancel(); 0243 } 0244 // Show with parent 0245 { 0246 QWidget w; 0247 w.show(); 0248 0249 QFileDialog dialog(&w); 0250 dialog.show(); 0251 0252 KFileWidget *fw = findFileWidget(); 0253 QVERIFY(fw); 0254 QCOMPARE(fw->isVisible(), true); 0255 fw->slotCancel(); 0256 } 0257 } 0258 0259 void testSetFileMode_data() 0260 { 0261 QTest::addColumn<QFileDialog::FileMode>("qtFileMode"); 0262 QTest::addColumn<KFile::Modes>("kdeFileMode"); 0263 QTest::newRow("anyfile") << QFileDialog::AnyFile << KFile::Modes(KFile::File); 0264 QTest::newRow("existingfile") << QFileDialog::ExistingFile << KFile::Modes(KFile::File | KFile::ExistingOnly); 0265 QTest::newRow("directory") << QFileDialog::Directory << KFile::Modes(KFile::Directory | KFile::ExistingOnly); 0266 QTest::newRow("existingfiles") << QFileDialog::ExistingFiles << KFile::Modes(KFile::Files | KFile::ExistingOnly); 0267 } 0268 0269 void testSetFileMode() 0270 { 0271 QFETCH(QFileDialog::FileMode, qtFileMode); 0272 QFETCH(KFile::Modes, kdeFileMode); 0273 QFileDialog dialog; 0274 dialog.setFileMode(qtFileMode); 0275 dialog.show(); 0276 0277 KFileWidget *fw = findFileWidget(); 0278 QVERIFY(fw); 0279 QCOMPARE(fw->mode(), kdeFileMode); 0280 0281 QCOMPARE(dialog.fileMode(), qtFileMode); 0282 } 0283 0284 void testSaveOverwrite_data() 0285 { 0286 QTest::addColumn<bool>("qtOverwriteOption"); 0287 QTest::addColumn<bool>("messageBoxExpected"); 0288 QTest::newRow("checkoverwrite") << false << true; 0289 QTest::newRow("allowoverwrite") << true << false; 0290 } 0291 0292 void testSaveOverwrite() 0293 { 0294 QFETCH(bool, qtOverwriteOption); 0295 QFETCH(bool, messageBoxExpected); 0296 0297 QTemporaryFile tempFile(m_tempDir.path() + "/kfiledialogtest_XXXXXX"); 0298 tempFile.setAutoRemove(true); 0299 tempFile.open(); 0300 QString tempName = tempFile.fileName(); 0301 tempFile.close(); 0302 int idx = tempName.lastIndexOf('/'); 0303 0304 QFileDialog dialog; 0305 dialog.setAcceptMode(QFileDialog::AcceptSave); 0306 if (qtOverwriteOption) 0307 dialog.setOption(QFileDialog::DontConfirmOverwrite); 0308 dialog.setDirectory(tempName.left(idx + 1)); 0309 dialog.selectFile(tempName.mid(idx + 1)); 0310 dialog.open(); 0311 0312 KFileWidget *fw = findFileWidget(); 0313 QVERIFY(fw); 0314 QVERIFY(QTest::qWaitForWindowExposed(fw->window())); 0315 QCOMPARE(fw->isVisible(), true); 0316 0317 bool timerRun = false; 0318 0319 QTimer::singleShot(3500, this, [&] { 0320 timerRun = true; 0321 QDialog *msgbox = findMessageBox(); 0322 if (msgbox) { 0323 QVERIFY(QTest::qWaitForWindowExposed(msgbox)); 0324 QCOMPARE(msgbox->isVisible(), true); 0325 msgbox->close(); 0326 QVERIFY(messageBoxExpected); 0327 } else { 0328 QVERIFY(!messageBoxExpected); 0329 } 0330 }); 0331 fw->slotOk(); 0332 0333 QTRY_VERIFY(timerRun); 0334 } 0335 0336 void testRememberLastDirectory() 0337 { 0338 const QUrl dir = QUrl::fromLocalFile(QDir::tempPath()).adjusted(QUrl::StripTrailingSlash); 0339 // Open and navigate 0340 { 0341 QFileDialog dialog; 0342 dialog.open(); 0343 0344 KFileWidget *fw = findFileWidget(); 0345 QVERIFY(fw); 0346 QCOMPARE(fw->isVisible(), true); 0347 fw->setUrl(dir); 0348 fw->slotCancel(); 0349 } 0350 // Open another filedialog, check that the default directory is the one from above 0351 { 0352 QFileDialog dialog; 0353 dialog.open(); 0354 0355 KFileWidget *fw = findFileWidget(); 0356 QVERIFY(fw); 0357 QCOMPARE(fw->isVisible(), true); 0358 QCOMPARE(dialog.directoryUrl().adjusted(QUrl::StripTrailingSlash), dir); 0359 fw->slotCancel(); 0360 } 0361 } 0362 0363 private: 0364 QTemporaryDir m_tempDir; 0365 0366 static QString fileViewToString(KFile::FileView fv) 0367 { 0368 switch (fv) { 0369 case KFile::Detail: 0370 return QStringLiteral("Detail"); 0371 case KFile::Simple: 0372 return QStringLiteral("Simple"); 0373 case KFile::Tree: 0374 return QStringLiteral("Tree"); 0375 case KFile::DetailTree: 0376 return QStringLiteral("DetailTree"); 0377 default: 0378 break; 0379 } 0380 return QStringLiteral("ERROR"); 0381 } 0382 0383 static KFileWidget *findFileWidget() 0384 { 0385 QList<KFileWidget *> widgets; 0386 foreach (QWidget *widget, QApplication::topLevelWidgets()) { 0387 KFileWidget *fw = widget->findChild<KFileWidget *>(); 0388 if (fw) { 0389 widgets.append(fw); 0390 } 0391 } 0392 Q_ASSERT(widgets.count() == 1); 0393 return (widgets.count() == 1) ? widgets.first() : nullptr; 0394 } 0395 0396 static QDialog *findMessageBox() 0397 { 0398 QList<QDialog *> widgets; 0399 foreach (QWidget *widget, QApplication::topLevelWidgets()) { 0400 QDialog *dlg = widget->findChild<QDialog *>(); 0401 if (dlg) { 0402 widgets.append(dlg); 0403 } 0404 } 0405 return (widgets.count() == 1) ? widgets.first() : nullptr; 0406 } 0407 }; 0408 0409 QTEST_MAIN(KFileDialog_UnitTest) 0410 0411 #include "kfiledialog_unittest.moc"