1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#include <qcoreapplication.h>
33#include <qdebug.h>
34#include <qfiledialog.h>
35#include <qabstractitemdelegate.h>
36#include <qdirmodel.h>
37#include <qitemdelegate.h>
38#include <qlistview.h>
39#include <qcombobox.h>
40#include <qpushbutton.h>
41#include <qtoolbutton.h>
42#include <qtreeview.h>
43#include <qheaderview.h>
44#include <qcompleter.h>
45#include <qaction.h>
46#include <qdialogbuttonbox.h>
47#include <qsortfilterproxymodel.h>
48#include <qlineedit.h>
49#include <qlayout.h>
50#include <qmenu.h>
51#include <qrandom.h>
52#include "../../../../../src/widgets/dialogs/qsidebar_p.h"
53#include "../../../../../src/widgets/dialogs/qfilesystemmodel_p.h"
54#include "../../../../../src/widgets/dialogs/qfiledialog_p.h"
55
56#include <private/qguiapplication_p.h>
57
58#include <qpa/qplatformdialoghelper.h>
59#include <qpa/qplatformintegration.h>
60
61#if defined(Q_OS_WIN)
62#include "../../../network-settings.h"
63#endif
64
65#if defined QT_BUILD_INTERNAL
66QT_BEGIN_NAMESPACE
67Q_GUI_EXPORT bool qt_test_isFetchedRoot();
68Q_GUI_EXPORT void qt_test_resetFetchedRoot();
69QT_END_NAMESPACE
70#endif
71
72static QByteArray msgDoesNotExist(const QString &name)
73{
74 return (QLatin1Char('"') + QDir::toNativeSeparators(pathName: name)
75 + QLatin1String("\" does not exist.")).toLocal8Bit();
76}
77
78class tst_QFileDialog2 : public QObject
79{
80Q_OBJECT
81
82public:
83 tst_QFileDialog2();
84
85private slots:
86 void initTestCase();
87 void init();
88 void cleanup();
89
90#ifdef QT_BUILD_INTERNAL
91 void deleteDirAndFiles();
92 void listRoot();
93 void task227304_proxyOnFileDialog();
94 void task236402_dontWatchDeletedDir();
95 void task251321_sideBarHiddenEntries();
96 void task251341_sideBarRemoveEntries();
97 void task257579_sideBarWithNonCleanUrls();
98#endif
99 void heapCorruption();
100 void filter();
101 void showNameFilterDetails();
102 void unc();
103 void emptyUncPath();
104
105#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_MENU)
106 void task143519_deleteAndRenameActionBehavior();
107#endif
108 void task178897_minimumSize();
109 void task180459_lastDirectory_data();
110 void task180459_lastDirectory();
111#ifndef Q_OS_MAC
112 void task227930_correctNavigationKeyboardBehavior();
113#endif
114#if defined(Q_OS_WIN)
115 void task226366_lowerCaseHardDriveWindows();
116#endif
117 void completionOnLevelAfterRoot();
118 void task233037_selectingDirectory();
119 void task235069_hideOnEscape_data();
120 void task235069_hideOnEscape();
121 void task203703_returnProperSeparator();
122 void task228844_ensurePreviousSorting();
123 void task239706_editableFilterCombo();
124 void task218353_relativePaths();
125 void task254490_selectFileMultipleTimes();
126 void task259105_filtersCornerCases();
127
128 void QTBUG4419_lineEditSelectAll();
129 void QTBUG6558_showDirsOnly();
130 void QTBUG4842_selectFilterWithHideNameFilterDetails();
131 void dontShowCompleterOnRoot();
132 void nameFilterParsing_data();
133 void nameFilterParsing();
134
135private:
136 void cleanupSettingsFile();
137
138 QTemporaryDir tempDir;
139};
140
141tst_QFileDialog2::tst_QFileDialog2()
142 : tempDir(QDir::tempPath() + "/tst_qfiledialog2.XXXXXX")
143{
144 QCoreApplication::setAttribute(attribute: Qt::AA_DontUseNativeDialogs);
145}
146
147void tst_QFileDialog2::cleanupSettingsFile()
148{
149 // clean up the sidebar between each test
150 QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
151 settings.beginGroup(prefix: QLatin1String("FileDialog"));
152 settings.remove(key: QString());
153 settings.endGroup();
154 settings.beginGroup(prefix: QLatin1String("Qt")); // Compatibility settings
155 settings.remove(key: QLatin1String("filedialog"));
156 settings.endGroup();
157}
158
159void tst_QFileDialog2::initTestCase()
160{
161 QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString()));
162 QStandardPaths::setTestModeEnabled(true);
163 cleanupSettingsFile();
164}
165
166void tst_QFileDialog2::init()
167{
168 QFileDialogPrivate::setLastVisitedDirectory(QUrl());
169 // populate the sidebar with some default settings
170 QFileDialog fd;
171}
172
173void tst_QFileDialog2::cleanup()
174{
175 cleanupSettingsFile();
176}
177
178#ifdef QT_BUILD_INTERNAL
179void tst_QFileDialog2::listRoot()
180{
181 QFileInfoGatherer fileInfoGatherer;
182 fileInfoGatherer.start();
183 QTest::qWait(ms: 1500);
184 qt_test_resetFetchedRoot();
185 QString dir(QDir::currentPath());
186 QFileDialog fd(0, QString(), dir);
187 fd.show();
188 QCOMPARE(qt_test_isFetchedRoot(),false);
189 fd.setDirectory("");
190 QTRY_COMPARE(qt_test_isFetchedRoot(),true);
191}
192#endif
193
194void tst_QFileDialog2::heapCorruption()
195{
196 QVector<QFileDialog*> dialogs;
197 for (int i=0; i < 10; i++) {
198 QFileDialog *f = new QFileDialog(NULL);
199 dialogs << f;
200 }
201 qDeleteAll(c: dialogs);
202}
203
204struct FriendlyQFileDialog : public QFileDialog
205{
206 friend class tst_QFileDialog2;
207 Q_DECLARE_PRIVATE(QFileDialog)
208};
209
210
211#ifdef QT_BUILD_INTERNAL
212void tst_QFileDialog2::deleteDirAndFiles()
213{
214 QString tempPath = tempDir.path() + "/QFileDialogTestDir4FullDelete";
215 QDir dir;
216 QVERIFY(dir.mkpath(tempPath + "/foo"));
217 QVERIFY(dir.mkpath(tempPath + "/foo/B"));
218 QVERIFY(dir.mkpath(tempPath + "/foo/B"));
219 QVERIFY(dir.mkpath(tempPath + "/foo/c"));
220 QVERIFY(dir.mkpath(tempPath + "/bar"));
221 QFile(tempPath + "/foo/a");
222 QTemporaryFile *t;
223 t = new QTemporaryFile(tempPath + "/foo/aXXXXXX");
224 t->setAutoRemove(false);
225 QVERIFY2(t->open(), qPrintable(t->errorString()));
226 t->close();
227 delete t;
228
229 t = new QTemporaryFile(tempPath + "/foo/B/yXXXXXX");
230 t->setAutoRemove(false);
231 QVERIFY2(t->open(), qPrintable(t->errorString()));
232 t->close();
233 delete t;
234 FriendlyQFileDialog fd;
235 fd.d_func()->removeDirectory(path: tempPath);
236 QTRY_VERIFY(!QFileInfo::exists(tempPath));
237}
238#endif
239
240void tst_QFileDialog2::filter()
241{
242 QFileDialog fd;
243 QAction *hiddenAction = fd.findChild<QAction*>(aName: "qt_show_hidden_action");
244 QVERIFY(hiddenAction);
245 QVERIFY(hiddenAction->isEnabled());
246 QVERIFY(!hiddenAction->isChecked());
247 QDir::Filters filter = fd.filter();
248 filter |= QDir::Hidden;
249 fd.setFilter(filter);
250 QVERIFY(hiddenAction->isChecked());
251}
252
253void tst_QFileDialog2::showNameFilterDetails()
254{
255 QFileDialog fd;
256 QComboBox *filters = fd.findChild<QComboBox*>(aName: "fileTypeCombo");
257 QVERIFY(filters);
258 QVERIFY(!fd.testOption(QFileDialog::HideNameFilterDetails));
259
260
261 QStringList filterChoices;
262 filterChoices << "Image files (*.png *.xpm *.jpg)"
263 << "Text files (*.txt)"
264 << "Any files (*.*)";
265 fd.setNameFilters(filterChoices);
266
267 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: true);
268 QCOMPARE(filters->itemText(0), QString("Image files"));
269 QCOMPARE(filters->itemText(1), QString("Text files"));
270 QCOMPARE(filters->itemText(2), QString("Any files"));
271
272 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: false);
273 QCOMPARE(filters->itemText(0), filterChoices.at(0));
274 QCOMPARE(filters->itemText(1), filterChoices.at(1));
275 QCOMPARE(filters->itemText(2), filterChoices.at(2));
276}
277
278void tst_QFileDialog2::unc()
279{
280#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
281 // Only test UNC on Windows./
282 QString dir("\\\\" + QtNetworkSettings::winServerName() + "\\testsharewritable");
283#else
284 QString dir(QDir::currentPath());
285#endif
286 QVERIFY2(QFile::exists(dir), msgDoesNotExist(dir).constData());
287 QFileDialog fd(0, QString(), dir);
288 QFileSystemModel *model = fd.findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
289 QVERIFY(model);
290 QCOMPARE(model->index(fd.directory().absolutePath()), model->index(dir));
291}
292
293void tst_QFileDialog2::emptyUncPath()
294{
295 QFileDialog fd;
296 fd.show();
297 QLineEdit *lineEdit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
298 QVERIFY(lineEdit);
299 // press 'keys' for the input
300 for (int i = 0; i < 3 ; ++i)
301 QTest::keyPress(widget: lineEdit, key: Qt::Key_Backslash);
302 QFileSystemModel *model = fd.findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
303 QVERIFY(model);
304}
305
306#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_MENU)
307struct MenuCloser : public QObject {
308 QWidget *w;
309 explicit MenuCloser(QWidget *w) : w(w) {}
310
311 void close()
312 {
313 QMenu *menu = w->findChild<QMenu*>();
314 if (!menu) {
315 qDebug(msg: "%s: cannot find file dialog child of type QMenu", Q_FUNC_INFO);
316 w->close();
317 }
318 QTest::keyClick(widget: menu, key: Qt::Key_Escape);
319 }
320};
321static bool openContextMenu(QFileDialog &fd)
322{
323 QListView *list = fd.findChild<QListView*>(aName: "listView");
324 if (!list) {
325 qDebug(msg: "%s: didn't find file dialog child \"listView\"", Q_FUNC_INFO);
326 return false;
327 }
328 QTimer timer;
329 timer.setInterval(300);
330 timer.setSingleShot(true);
331 MenuCloser closer(&fd);
332 QObject::connect(sender: &timer, signal: &QTimer::timeout, receiver: &closer, slot: &MenuCloser::close);
333 timer.start();
334 QContextMenuEvent cme(QContextMenuEvent::Mouse, QPoint(10, 10));
335 qApp->sendEvent(receiver: list->viewport(), event: &cme); // blocks until menu is closed again.
336 return true;
337}
338
339void tst_QFileDialog2::task143519_deleteAndRenameActionBehavior()
340{
341 // test based on task233037_selectingDirectory
342
343 struct TestContext {
344 explicit TestContext(const QString &path) : current(path) {}
345 ~TestContext() {
346 file.remove();
347 current.rmdir(dirName: test.dirName());
348 }
349 QDir current;
350 QDir test;
351 QFile file;
352 };
353
354 TestContext ctx(tempDir.path());
355
356 // setup testbed
357 QVERIFY(ctx.current.mkdir("task143519_deleteAndRenameActionBehavior_test")); // ensure at least one item
358 ctx.test = ctx.current;
359 QVERIFY(ctx.test.cd("task143519_deleteAndRenameActionBehavior_test"));
360 ctx.file.setFileName(ctx.test.absoluteFilePath(fileName: "hello"));
361 QVERIFY(ctx.file.open(QIODevice::WriteOnly));
362 QVERIFY(ctx.file.permissions() & QFile::WriteUser);
363 ctx.file.close();
364
365 QFileDialog fd;
366 fd.setViewMode(QFileDialog::List);
367 fd.setDirectory(ctx.test.absolutePath());
368 fd.selectFile(filename: ctx.file.fileName());
369 fd.show();
370
371 QVERIFY(QTest::qWaitForWindowExposed(&fd));
372
373 // grab some internals:
374 QAction *rm = fd.findChild<QAction*>(aName: "qt_delete_action");
375 QVERIFY(rm);
376 QAction *mv = fd.findChild<QAction*>(aName: "qt_rename_action");
377 QVERIFY(mv);
378
379 // these are the real test cases:
380
381 // defaults
382 QVERIFY(openContextMenu(fd));
383 QCOMPARE(fd.selectedFiles(), QStringList(ctx.file.fileName()));
384 QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
385 QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
386
387 // change to non-defaults:
388 fd.setOption(option: QFileDialog::ReadOnly, on: !fd.testOption(option: QFileDialog::ReadOnly));
389
390 QVERIFY(openContextMenu(fd));
391 QCOMPARE(fd.selectedFiles().size(), 1);
392 QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
393 QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
394
395 // and changed back to defaults:
396 fd.setOption(option: QFileDialog::ReadOnly, on: !fd.testOption(option: QFileDialog::ReadOnly));
397
398 QVERIFY(openContextMenu(fd));
399 QCOMPARE(fd.selectedFiles().size(), 1);
400 QCOMPARE(rm->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
401 QCOMPARE(mv->isEnabled(), !fd.testOption(QFileDialog::ReadOnly));
402}
403#endif // !QT_NO_CONTEXTMENU && !QT_NO_MENU
404
405void tst_QFileDialog2::task178897_minimumSize()
406{
407 QFileDialog fd;
408 QSize oldMs = fd.layout()->minimumSize();
409 QStringList history = fd.history();
410 history << QDir::toNativeSeparators(pathName: "/verylongdirectory/"
411 "aaaaaaaaaabbbbbbbbcccccccccccddddddddddddddeeeeeeeeeeeeffffffffffgggtggggggggghhhhhhhhiiiiiijjjk");
412 fd.setHistory(history);
413 fd.show();
414
415 QSize ms = fd.layout()->minimumSize();
416 QVERIFY(ms.width() <= oldMs.width());
417}
418
419void tst_QFileDialog2::task180459_lastDirectory_data()
420{
421 QTest::addColumn<QString>(name: "path");
422 QTest::addColumn<QString>(name: "directory");
423 QTest::addColumn<bool>(name: "isEnabled");
424 QTest::addColumn<QString>(name: "result");
425
426 QTest::newRow(dataTag: "path+file") << QDir::homePath() + QDir::separator() + "foo"
427 << QDir::homePath() << true
428 << QDir::homePath() + QDir::separator() + "foo" ;
429 QTest::newRow(dataTag: "no path") << ""
430 << tempDir.path() << false << QString();
431 QTest::newRow(dataTag: "file") << "foo"
432 << QDir::currentPath() << true
433 << QDir::currentPath() + QDir::separator() + "foo" ;
434 QTest::newRow(dataTag: "path") << QDir::homePath()
435 << QDir::homePath() << false << QString();
436 QTest::newRow(dataTag: "path not existing") << "/usr/bin/foo/bar/foo/foo.txt"
437 << tempDir.path() << true
438 << tempDir.path() + QDir::separator() + "foo.txt";
439
440}
441
442void tst_QFileDialog2::task180459_lastDirectory()
443{
444 if (!QGuiApplication::platformName().compare(other: QLatin1String("cocoa"), cs: Qt::CaseInsensitive))
445 QSKIP("Insignificant on OSX"); //QTBUG-39183
446 //first visit the temp directory and close the dialog
447 QFileDialog *dlg = new QFileDialog(0, "", tempDir.path());
448 QFileSystemModel *model = dlg->findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
449 QVERIFY(model);
450 QCOMPARE(model->index(tempDir.path()), model->index(dlg->directory().absolutePath()));
451 delete dlg;
452
453 QFETCH(QString, path);
454 QFETCH(QString, directory);
455 QFETCH(bool, isEnabled);
456 QFETCH(QString, result);
457
458 dlg = new QFileDialog(0, "", path);
459 model = dlg->findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
460 QVERIFY(model);
461 dlg->setAcceptMode(QFileDialog::AcceptSave);
462 QCOMPARE(model->index(dlg->directory().absolutePath()), model->index(directory));
463
464 QDialogButtonBox *buttonBox = dlg->findChild<QDialogButtonBox*>(aName: "buttonBox");
465 QPushButton *button = buttonBox->button(which: QDialogButtonBox::Save);
466 QVERIFY(button);
467 QCOMPARE(button->isEnabled(), isEnabled);
468 if (isEnabled)
469 QCOMPARE(model->index(result), model->index(dlg->selectedFiles().first()));
470
471 delete dlg;
472}
473
474
475
476class FilterDirModel : public QSortFilterProxyModel
477{
478
479public:
480 FilterDirModel(QString root, QObject* parent=0):QSortFilterProxyModel(parent), m_root(root)
481 {}
482 ~FilterDirModel()
483 {};
484
485protected:
486 bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
487 {
488 QModelIndex parentIndex;
489 parentIndex = source_parent;
490
491 QString path;
492 path = sourceModel()->index(row: source_row, column: 0, parent: parentIndex).data(arole: Qt::DisplayRole).toString();
493
494 do {
495 path = parentIndex.data(arole: Qt::DisplayRole).toString() + QLatin1Char('/') + path;
496 parentIndex = parentIndex.parent();
497 } while(parentIndex.isValid());
498
499 QFileInfo info(path);
500 if (info.isDir() && (QDir(path) != m_root))
501 return false;
502 return true;
503 }
504
505
506private:
507 QDir m_root;
508
509
510};
511
512class sortProxy : public QSortFilterProxyModel
513{
514public:
515 sortProxy(QObject *parent) : QSortFilterProxyModel(parent)
516 {
517 }
518protected:
519 virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const
520 {
521 QFileSystemModel * const model = qobject_cast<QFileSystemModel *>(object: sourceModel());
522 const QFileInfo leftInfo(model->fileInfo(index: left));
523 const QFileInfo rightInfo(model->fileInfo(index: right));
524
525 if (leftInfo.isDir() == rightInfo.isDir())
526 return(leftInfo.filePath().compare(s: rightInfo.filePath(),cs: Qt::CaseInsensitive) < 0);
527 else if (leftInfo.isDir())
528 return(false);
529 else
530 return(true);
531 }
532};
533
534class CrashDialog : public QFileDialog
535{
536 Q_OBJECT
537
538public:
539 CrashDialog(QWidget *parent, const QString &caption, const
540QString &dir, const QString &filter)
541 : QFileDialog(parent, caption, dir, filter)
542 {
543 sortProxy *proxyModel = new sortProxy(this);
544 setProxyModel(proxyModel);
545 }
546};
547
548#ifdef QT_BUILD_INTERNAL
549void tst_QFileDialog2::task227304_proxyOnFileDialog()
550{
551 QFileDialog fd(0, "", QDir::currentPath(), 0);
552 fd.setProxyModel(new FilterDirModel(QDir::currentPath()));
553 fd.show();
554 QVERIFY(QTest::qWaitForWindowExposed(&fd));
555 QLineEdit *edit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
556 QVERIFY(edit);
557 QTest::keyClick(widget: edit, key: Qt::Key_T);
558 QTest::keyClick(widget: edit, key: Qt::Key_S);
559 QTest::keyClick(widget: edit->completer()->popup(), key: Qt::Key_Down);
560
561 CrashDialog *dialog = new CrashDialog(0, QString("crash dialog test"), QDir::homePath(), QString("*") );
562 dialog->setFileMode(QFileDialog::ExistingFile);
563 dialog->show();
564 QVERIFY(QTest::qWaitForWindowExposed(dialog));
565
566 QListView *list = dialog->findChild<QListView*>(aName: "listView");
567 QVERIFY(list);
568 QTest::keyClick(widget: list, key: Qt::Key_Down);
569 QTest::keyClick(widget: list, key: Qt::Key_Return);
570
571 dialog->close();
572 fd.close();
573
574 QFileDialog fd2(0, "I should not crash with a proxy", tempDir.path(), {});
575 QSortFilterProxyModel *pm = new QSortFilterProxyModel;
576 fd2.setProxyModel(pm);
577 fd2.show();
578 QSidebar *sidebar = fd2.findChild<QSidebar*>(aName: "sidebar");
579 sidebar->setFocus();
580 sidebar->selectUrl(url: QUrl::fromLocalFile(localfile: QDir::homePath()));
581 QTest::mouseClick(widget: sidebar->viewport(), button: Qt::LeftButton, stateKey: {},
582 pos: sidebar->visualRect(index: sidebar->model()->index(row: 1, column: 0)).center());
583 QTest::qWait(ms: 250);
584 //We shouldn't crash
585}
586#endif
587
588#ifndef Q_OS_MAC
589// The following test implies the folder created will appear first in
590// the list. On Mac files sorting depends on the locale and the order
591// displayed cannot be known for sure.
592void tst_QFileDialog2::task227930_correctNavigationKeyboardBehavior()
593{
594 QDir current = QDir::currentPath();
595 current.mkdir(dirName: "test");
596 current.cd(dirName: "test");
597 QFile file("test/out.txt");
598 QFile file2("test/out2.txt");
599 QVERIFY(file.open(QIODevice::WriteOnly | QIODevice::Text));
600 QVERIFY(file2.open(QIODevice::WriteOnly | QIODevice::Text));
601 current.cdUp();
602 current.mkdir(dirName: "test2");
603 QFileDialog fd;
604 fd.setViewMode(QFileDialog::List);
605 fd.setDirectory(current.absolutePath());
606 fd.show();
607 QVERIFY(QTest::qWaitForWindowExposed(&fd));
608
609 // Ensure LayoutRequest event is processed so that the list view
610 // is sorted correctly to have the directory entires at the top.
611 QCoreApplication::processEvents();
612
613 QListView *list = fd.findChild<QListView*>(aName: "listView");
614 QVERIFY(list);
615 QTest::keyClick(widget: list, key: Qt::Key_Down);
616 QTest::keyClick(widget: list, key: Qt::Key_Return);
617 QTest::mouseClick(widget: list->viewport(), button: Qt::LeftButton, stateKey: {});
618 QTest::keyClick(widget: list, key: Qt::Key_Down);
619 QTest::keyClick(widget: list, key: Qt::Key_Backspace);
620 QTest::keyClick(widget: list, key: Qt::Key_Down);
621 QTest::keyClick(widget: list, key: Qt::Key_Down);
622 QTest::keyClick(widget: list, key: Qt::Key_Return);
623 QCOMPARE(fd.isVisible(), true);
624 file.close();
625 file2.close();
626 file.remove();
627 file2.remove();
628 current.rmdir(dirName: "test");
629 current.rmdir(dirName: "test2");
630}
631#endif
632
633#if defined(Q_OS_WIN)
634void tst_QFileDialog2::task226366_lowerCaseHardDriveWindows()
635{
636 QFileDialog fd;
637 fd.setDirectory(QDir::root().path());
638 fd.show();
639 QLineEdit *edit = fd.findChild<QLineEdit*>("fileNameEdit");
640 QToolButton *buttonParent = fd.findChild<QToolButton*>("toParentButton");
641 QTest::qWait(200);
642 QTest::mouseClick(buttonParent, Qt::LeftButton,0,QPoint(0,0));
643 QTest::qWait(2000);
644 QTest::keyClick(edit, Qt::Key_C);
645 QTest::qWait(200);
646 QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
647 QTest::qWait(200);
648 QCOMPARE(edit->text(), QString("C:/"));
649 QTest::qWait(2000);
650 //i clear my previous selection in the completer
651 QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
652 edit->clear();
653 QTest::keyClick(edit, (char)(Qt::Key_C | Qt::SHIFT));
654 QTest::qWait(200);
655 QTest::keyClick(edit->completer()->popup(), Qt::Key_Down);
656 QCOMPARE(edit->text(), QString("C:/"));
657}
658#endif
659
660void tst_QFileDialog2::completionOnLevelAfterRoot()
661{
662 QFileDialog fd;
663#if defined(Q_OS_WIN)
664 fd.setDirectory("C:/");
665 QDir current = fd.directory();
666 QStringList entryList = current.entryList(QStringList(), QDir::Dirs);
667 // Find a suitable test dir under c:-root:
668 // - At least 6 characters long
669 // - Ascii, letters only
670 // - No another dir with same start
671 QString testDir;
672 foreach (const QString &entry, entryList) {
673 if (entry.size() > 5 && QString(entry.toLatin1()).compare(entry) == 0) {
674 bool invalid = false;
675 for (int i = 0; i < 5; i++) {
676 if (!entry.at(i).isLetter()) {
677 invalid = true;
678 break;
679 }
680 }
681 if (!invalid) {
682 foreach (const QString &check, entryList) {
683 if (check.startsWith(entry.left(5), Qt::CaseInsensitive) && check != entry) {
684 invalid = true;
685 break;
686 }
687 }
688 }
689 if (!invalid) {
690 testDir = entry;
691 break;
692 }
693 }
694 }
695 if (testDir.isEmpty())
696 QSKIP("This test requires to have a unique directory of at least six ascii characters under c:/");
697#else
698 fd.setFilter(QDir::Hidden | QDir::AllDirs | QDir::Files | QDir::System);
699 fd.setDirectory("/");
700 QDir etc("/etc");
701 if (!etc.exists())
702 QSKIP("This test requires to have an etc directory under /");
703#endif
704 fd.show();
705 QLineEdit *edit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
706 QTest::qWait(ms: 2000);
707#if defined(Q_OS_WIN)
708 //I love testlib :D
709 for (int i = 0; i < 5; i++)
710 QTest::keyClick(edit, testDir.at(i).toLower().toLatin1() - 'a' + Qt::Key_A);
711#else
712 QTest::keyClick(widget: edit, key: Qt::Key_E);
713 QTest::keyClick(widget: edit, key: Qt::Key_T);
714#endif
715 QTest::qWait(ms: 200);
716 QTest::keyClick(widget: edit->completer()->popup(), key: Qt::Key_Down);
717 QTest::qWait(ms: 200);
718#if defined(Q_OS_WIN)
719 QCOMPARE(edit->text(), testDir);
720#else
721 QTRY_COMPARE(edit->text(), QString("etc"));
722#endif
723}
724
725void tst_QFileDialog2::task233037_selectingDirectory()
726{
727 QDir current = QDir::currentPath();
728 current.mkdir(dirName: "test");
729 QFileDialog fd;
730 fd.setViewMode(QFileDialog::List);
731 fd.setDirectory(current.absolutePath());
732 fd.setAcceptMode( QFileDialog::AcceptSave);
733 fd.show();
734 QListView *list = fd.findChild<QListView*>(aName: "listView");
735 QTest::qWait(ms: 3000); // Wait for sort to settle (I need a signal).
736#ifdef QT_KEYPAD_NAVIGATION
737 list->setEditFocus(true);
738#endif
739 QTest::keyClick(widget: list, key: Qt::Key_Down);
740 QDialogButtonBox *buttonBox = fd.findChild<QDialogButtonBox*>(aName: "buttonBox");
741 QVERIFY(buttonBox);
742 QPushButton *button = buttonBox->button(which: QDialogButtonBox::Save);
743 QVERIFY(button);
744 QVERIFY(button->isEnabled());
745 current.rmdir(dirName: "test");
746}
747
748void tst_QFileDialog2::task235069_hideOnEscape_data()
749{
750 QTest::addColumn<QString>(name: "childName");
751 QTest::addColumn<QFileDialog::ViewMode>(name: "viewMode");
752 QTest::newRow(dataTag: "listView") << QStringLiteral("listView") << QFileDialog::List;
753 QTest::newRow(dataTag: "fileNameEdit") << QStringLiteral("fileNameEdit") << QFileDialog::List;
754 QTest::newRow(dataTag: "treeView") << QStringLiteral("treeView") << QFileDialog::Detail;
755}
756
757void tst_QFileDialog2::task235069_hideOnEscape()
758{
759 QFETCH(QString, childName);
760 QFETCH(QFileDialog::ViewMode, viewMode);
761 QDir current = QDir::currentPath();
762
763 QFileDialog fd;
764 QSignalSpy spyFinished(&fd, &QDialog::finished);
765 QVERIFY(spyFinished.isValid());
766 QSignalSpy spyRejected(&fd, &QDialog::rejected);
767 QVERIFY(spyRejected.isValid());
768 fd.setViewMode(viewMode);
769 fd.setDirectory(current.absolutePath());
770 fd.setAcceptMode(QFileDialog::AcceptSave);
771 fd.show();
772 QVERIFY(QTest::qWaitForWindowExposed(&fd));
773 QWidget *child = fd.findChild<QWidget *>(aName: childName);
774 QVERIFY(child);
775 child->setFocus();
776 QTest::keyClick(widget: child, key: Qt::Key_Escape);
777 QCOMPARE(fd.isVisible(), false);
778 QCOMPARE(spyFinished.count(), 1); // QTBUG-7690
779 QCOMPARE(spyRejected.count(), 1); // reject(), don't hide()
780}
781
782#ifdef QT_BUILD_INTERNAL
783void tst_QFileDialog2::task236402_dontWatchDeletedDir()
784{
785 //THIS TEST SHOULD NOT DISPLAY WARNINGS
786 QDir current = QDir::currentPath();
787 //make sure it is the first on the list
788 current.mkdir(dirName: "aaaaaaaaaa");
789 FriendlyQFileDialog fd;
790 fd.setViewMode(QFileDialog::List);
791 fd.setDirectory(current.absolutePath());
792 fd.setAcceptMode( QFileDialog::AcceptSave);
793 fd.show();
794 QVERIFY(QTest::qWaitForWindowExposed(&fd));
795 QListView *list = fd.findChild<QListView*>(aName: "listView");
796 QVERIFY(list);
797 list->setFocus();
798 QTest::keyClick(widget: list, key: Qt::Key_Return);
799 QTest::keyClick(widget: list, key: Qt::Key_Backspace);
800 QTest::keyClick(widget: list, key: Qt::Key_Down);
801 fd.d_func()->removeDirectory(path: current.absolutePath() + "/aaaaaaaaaa/");
802 QTest::qWait(ms: 1000);
803}
804#endif
805
806void tst_QFileDialog2::task203703_returnProperSeparator()
807{
808 QDir current = QDir::currentPath();
809 current.mkdir(dirName: "aaaaaaaaaaaaaaaaaa");
810 QFileDialog fd;
811 fd.setDirectory(current.absolutePath());
812 fd.setViewMode(QFileDialog::List);
813 fd.setFileMode(QFileDialog::Directory);
814 fd.show();
815 QVERIFY(QTest::qWaitForWindowExposed(&fd));
816 QListView *list = fd.findChild<QListView*>(aName: "listView");
817 QVERIFY(list);
818 list->setFocus();
819 QTest::keyClick(widget: list, key: Qt::Key_Return);
820 QDialogButtonBox *buttonBox = fd.findChild<QDialogButtonBox*>(aName: "buttonBox");
821 QVERIFY(buttonBox);
822 QPushButton *button = buttonBox->button(which: QDialogButtonBox::Cancel);
823 QVERIFY(button);
824 QTest::keyClick(widget: button, key: Qt::Key_Return);
825 QString result = fd.selectedFiles().first();
826 QVERIFY(result.at(result.count() - 1) != '/');
827 QVERIFY(!result.contains('\\'));
828 current.rmdir(dirName: "aaaaaaaaaaaaaaaaaa");
829}
830
831void tst_QFileDialog2::task228844_ensurePreviousSorting()
832{
833 QDir current = QDir::currentPath();
834 current.mkdir(dirName: "aaaaaaaaaaaaaaaaaa");
835 current.cd(dirName: "aaaaaaaaaaaaaaaaaa");
836 current.mkdir(dirName: "a");
837 current.mkdir(dirName: "b");
838 current.mkdir(dirName: "c");
839 current.mkdir(dirName: "d");
840 current.mkdir(dirName: "e");
841 current.mkdir(dirName: "f");
842 current.mkdir(dirName: "g");
843 QTemporaryFile *tempFile = new QTemporaryFile(current.absolutePath() + "/rXXXXXX");
844 QVERIFY2(tempFile->open(), qPrintable(tempFile->errorString()));
845 current.cdUp();
846
847 QFileDialog fd;
848 fd.setDirectory(current.absolutePath());
849 fd.setViewMode(QFileDialog::Detail);
850 fd.show();
851 QVERIFY(QTest::qWaitForWindowExposed(&fd));
852 QTreeView *tree = fd.findChild<QTreeView*>(aName: "treeView");
853 QVERIFY(tree);
854 tree->header()->setSortIndicator(logicalIndex: 3,order: Qt::DescendingOrder);
855 QDialogButtonBox *buttonBox = fd.findChild<QDialogButtonBox*>(aName: "buttonBox");
856 QVERIFY(buttonBox);
857 QPushButton *button = buttonBox->button(which: QDialogButtonBox::Open);
858 QVERIFY(button);
859 QTest::mouseClick(widget: button, button: Qt::LeftButton);
860 QFileDialog fd2;
861 fd2.setFileMode(QFileDialog::Directory);
862 fd2.restoreState(state: fd.saveState());
863 current.cd(dirName: "aaaaaaaaaaaaaaaaaa");
864 fd2.setDirectory(current.absolutePath());
865 fd2.show();
866 QVERIFY(QTest::qWaitForWindowExposed(&fd2));
867 QTreeView *tree2 = fd2.findChild<QTreeView*>(aName: "treeView");
868 QVERIFY(tree2);
869 tree2->setFocus();
870
871 QCOMPARE(tree2->rootIndex().data(QFileSystemModel::FilePathRole).toString(),current.absolutePath());
872
873 QDialogButtonBox *buttonBox2 = fd2.findChild<QDialogButtonBox*>(aName: "buttonBox");
874 QVERIFY(buttonBox2);
875 QPushButton *button2 = buttonBox2->button(which: QDialogButtonBox::Open);
876 QVERIFY(button2);
877 fd2.selectFile(filename: "g");
878 QTest::mouseClick(widget: button2, button: Qt::LeftButton);
879 QCOMPARE(fd2.selectedFiles().first(), current.absolutePath() + QLatin1String("/g"));
880
881 QFileDialog fd3(0, "This is a third file dialog", tempFile->fileName());
882 fd3.restoreState(state: fd.saveState());
883 fd3.setFileMode(QFileDialog::Directory);
884 fd3.show();
885 QVERIFY(QTest::qWaitForWindowExposed(&fd3));
886 QTreeView *tree3 = fd3.findChild<QTreeView*>(aName: "treeView");
887 QVERIFY(tree3);
888 tree3->setFocus();
889
890 QCOMPARE(tree3->rootIndex().data(QFileSystemModel::FilePathRole).toString(), current.absolutePath());
891
892 QDialogButtonBox *buttonBox3 = fd3.findChild<QDialogButtonBox*>(aName: "buttonBox");
893 QVERIFY(buttonBox3);
894 QPushButton *button3 = buttonBox3->button(which: QDialogButtonBox::Open);
895 QVERIFY(button3);
896 QTest::mouseClick(widget: button3, button: Qt::LeftButton);
897 QCOMPARE(fd3.selectedFiles().first(), tempFile->fileName());
898
899 current.cd(dirName: "aaaaaaaaaaaaaaaaaa");
900 current.rmdir(dirName: "a");
901 current.rmdir(dirName: "b");
902 current.rmdir(dirName: "c");
903 current.rmdir(dirName: "d");
904 current.rmdir(dirName: "e");
905 current.rmdir(dirName: "f");
906 current.rmdir(dirName: "g");
907 tempFile->close();
908 delete tempFile;
909 current.cdUp();
910 current.rmdir(dirName: "aaaaaaaaaaaaaaaaaa");
911}
912
913
914void tst_QFileDialog2::task239706_editableFilterCombo()
915{
916 QFileDialog d;
917 d.setNameFilter("*.cpp *.h");
918 d.show();
919 QVERIFY(QTest::qWaitForWindowExposed(&d));
920
921 QList<QComboBox *> comboList = d.findChildren<QComboBox *>();
922 QComboBox *filterCombo = 0;
923 foreach (QComboBox *combo, comboList) {
924 if (combo->objectName() == QString("fileTypeCombo")) {
925 filterCombo = combo;
926 break;
927 }
928 }
929 QVERIFY(filterCombo);
930 filterCombo->setEditable(true);
931 QTest::mouseClick(widget: filterCombo, button: Qt::LeftButton);
932 QTest::keyPress(widget: filterCombo, key: Qt::Key_X);
933 QTest::keyPress(widget: filterCombo, key: Qt::Key_Enter); // should not trigger assertion failure
934}
935
936void tst_QFileDialog2::task218353_relativePaths()
937{
938 QDir appDir = QDir::current();
939 QVERIFY(appDir.cdUp() != false);
940 QFileDialog d(0, "TestDialog", "..");
941 QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
942
943 d.setDirectory(appDir.absolutePath() + QLatin1String("/non-existing-directory/../another-non-existing-dir/../"));
944 QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
945
946 QDir::current().mkdir(dirName: "test");
947 appDir = QDir::current();
948 d.setDirectory(appDir.absolutePath() + QLatin1String("/test/../test/../"));
949 QCOMPARE(d.directory().absolutePath(), appDir.absolutePath());
950 appDir.rmdir(dirName: "test");
951}
952
953#ifdef QT_BUILD_INTERNAL
954void tst_QFileDialog2::task251321_sideBarHiddenEntries()
955{
956 QFileDialog fd;
957
958 QDir current = QDir::currentPath();
959 current.mkdir(dirName: ".hidden");
960 QDir hiddenDir = QDir(".hidden");
961 hiddenDir.mkdir(dirName: "subdir");
962 QDir hiddenSubDir = QDir(".hidden/subdir");
963 hiddenSubDir.mkdir(dirName: "happy");
964 hiddenSubDir.mkdir(dirName: "happy2");
965
966 QList<QUrl> urls;
967 urls << QUrl::fromLocalFile(localfile: hiddenSubDir.absolutePath());
968 fd.setSidebarUrls(urls);
969 fd.show();
970 QVERIFY(QTest::qWaitForWindowExposed(&fd));
971
972 QSidebar *sidebar = fd.findChild<QSidebar*>(aName: "sidebar");
973 QVERIFY(sidebar);
974 sidebar->setFocus();
975 sidebar->selectUrl(url: QUrl::fromLocalFile(localfile: hiddenSubDir.absolutePath()));
976 QTest::mouseClick(widget: sidebar->viewport(), button: Qt::LeftButton, stateKey: {},
977 pos: sidebar->visualRect(index: sidebar->model()->index(row: 0, column: 0)).center());
978 // give the background processes more time on windows mobile
979 QTest::qWait(ms: 250);
980
981 QFileSystemModel *model = fd.findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
982 QCOMPARE(model->rowCount(model->index(hiddenSubDir.absolutePath())), 2);
983
984 hiddenSubDir.rmdir(dirName: "happy2");
985 hiddenSubDir.rmdir(dirName: "happy");
986 hiddenDir.rmdir(dirName: "subdir");
987 current.rmdir(dirName: ".hidden");
988}
989#endif
990
991#if defined QT_BUILD_INTERNAL
992class MyQSideBar : public QSidebar
993{
994public :
995 MyQSideBar(QWidget *parent = 0) : QSidebar(parent)
996 {}
997
998 void removeSelection() {
999 QList<QModelIndex> idxs = selectionModel()->selectedIndexes();
1000 QList<QPersistentModelIndex> indexes;
1001 for (int i = 0; i < idxs.count(); i++)
1002 indexes.append(t: idxs.at(i));
1003
1004 for (int i = 0; i < indexes.count(); ++i)
1005 if (!indexes.at(i).data(role: Qt::UserRole + 1).toUrl().path().isEmpty())
1006 model()->removeRow(arow: indexes.at(i).row());
1007 }
1008};
1009#endif
1010
1011#ifdef QT_BUILD_INTERNAL
1012void tst_QFileDialog2::task251341_sideBarRemoveEntries()
1013{
1014 QFileDialog fd;
1015
1016 QDir current = QDir::currentPath();
1017 current.mkdir(dirName: "testDir");
1018 QDir testSubDir = QDir("testDir");
1019
1020 QList<QUrl> urls;
1021 urls << QUrl::fromLocalFile(localfile: testSubDir.absolutePath());
1022 urls << QUrl::fromLocalFile(localfile: "NotFound");
1023 fd.setSidebarUrls(urls);
1024 fd.show();
1025 QVERIFY(QTest::qWaitForWindowExposed(&fd));
1026
1027 QSidebar *sidebar = fd.findChild<QSidebar*>(aName: "sidebar");
1028 QVERIFY(sidebar);
1029 sidebar->setFocus();
1030 //We enter in the first bookmark
1031 sidebar->selectUrl(url: QUrl::fromLocalFile(localfile: testSubDir.absolutePath()));
1032 QTest::mouseClick(widget: sidebar->viewport(), button: Qt::LeftButton, stateKey: {},
1033 pos: sidebar->visualRect(index: sidebar->model()->index(row: 0, column: 0)).center());
1034
1035 QFileSystemModel *model = fd.findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
1036 QVERIFY(model);
1037 //There is no file
1038 QCOMPARE(model->rowCount(model->index(testSubDir.absolutePath())), 0);
1039 //Icon is not enabled QUrlModel::EnabledRole
1040 QVariant value = sidebar->model()->index(row: 0, column: 0).data(arole: Qt::UserRole + 2);
1041 QCOMPARE(qvariant_cast<bool>(value), true);
1042
1043 sidebar->setFocus();
1044 //We enter in the second bookmark which is invalid
1045 sidebar->selectUrl(url: QUrl::fromLocalFile(localfile: "NotFound"));
1046 QTest::mouseClick(widget: sidebar->viewport(), button: Qt::LeftButton, stateKey: {},
1047 pos: sidebar->visualRect(index: sidebar->model()->index(row: 1, column: 0)).center());
1048
1049 //We fallback to root because the entry in the bookmark is invalid
1050 QCOMPARE(model->rowCount(model->index("NotFound")), model->rowCount(model->index(model->rootPath())));
1051 //Icon is not enabled QUrlModel::EnabledRole
1052 value = sidebar->model()->index(row: 1, column: 0).data(arole: Qt::UserRole + 2);
1053 QCOMPARE(qvariant_cast<bool>(value), false);
1054
1055 MyQSideBar mySideBar;
1056 mySideBar.setModelAndUrls(model, newUrls: urls);
1057 mySideBar.show();
1058 mySideBar.selectUrl(url: QUrl::fromLocalFile(localfile: testSubDir.absolutePath()));
1059 QTest::qWait(ms: 1000);
1060 mySideBar.removeSelection();
1061
1062 //We remove the first entry
1063 QList<QUrl> expected;
1064 expected << QUrl::fromLocalFile(localfile: "NotFound");
1065 QCOMPARE(mySideBar.urls(), expected);
1066
1067 mySideBar.selectUrl(url: QUrl::fromLocalFile(localfile: "NotFound"));
1068 mySideBar.removeSelection();
1069
1070 //We remove the second entry
1071 expected.clear();
1072 QCOMPARE(mySideBar.urls(), expected);
1073
1074 current.rmdir(dirName: "testDir");
1075}
1076#endif
1077
1078void tst_QFileDialog2::task254490_selectFileMultipleTimes()
1079{
1080 QString tempPath = tempDir.path();
1081 QTemporaryFile *t;
1082 t = new QTemporaryFile;
1083 QVERIFY2(t->open(), qPrintable(t->errorString()));
1084 t->open();
1085 QFileDialog fd(0, "TestFileDialog");
1086
1087 fd.setDirectory(tempPath);
1088 fd.setViewMode(QFileDialog::List);
1089 fd.setAcceptMode(QFileDialog::AcceptSave);
1090 fd.setFileMode(QFileDialog::AnyFile);
1091
1092 //This should select the file in the QFileDialog
1093 fd.selectFile(filename: t->fileName());
1094
1095 //This should clear the selection and write it into the filename line edit
1096 fd.selectFile(filename: "new_file.txt");
1097
1098 fd.show();
1099 QVERIFY(QTest::qWaitForWindowExposed(&fd));
1100
1101 QLineEdit *lineEdit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
1102 QVERIFY(lineEdit);
1103 QCOMPARE(lineEdit->text(),QLatin1String("new_file.txt"));
1104 QListView *list = fd.findChild<QListView*>(aName: "listView");
1105 QVERIFY(list);
1106 QCOMPARE(list->selectionModel()->selectedRows(0).count(), 0);
1107
1108 t->deleteLater();
1109}
1110
1111#ifdef QT_BUILD_INTERNAL
1112void tst_QFileDialog2::task257579_sideBarWithNonCleanUrls()
1113{
1114 QDir dir(tempDir.path());
1115 QLatin1String dirname("autotest_task257579");
1116 dir.rmdir(dirName: dirname); //makes sure it doesn't exist any more
1117 QVERIFY(dir.mkdir(dirname));
1118 QString url = dir.absolutePath() + QLatin1Char('/') + dirname + QLatin1String("/..");
1119 QFileDialog fd;
1120 fd.setSidebarUrls(QList<QUrl>() << QUrl::fromLocalFile(localfile: url));
1121 QSidebar *sidebar = fd.findChild<QSidebar*>(aName: "sidebar");
1122 QCOMPARE(sidebar->urls().count(), 1);
1123 QVERIFY(sidebar->urls().first().toLocalFile() != url);
1124 QCOMPARE(sidebar->urls().first().toLocalFile(), QDir::cleanPath(url));
1125
1126#ifdef Q_OS_WIN
1127 QCOMPARE(sidebar->model()->index(0,0).data().toString().toLower(), dir.dirName().toLower());
1128#else
1129 QCOMPARE(sidebar->model()->index(0,0).data().toString(), dir.dirName());
1130#endif
1131
1132 //all tests are finished, we can remove the temporary dir
1133 QVERIFY(dir.rmdir(dirname));
1134}
1135#endif
1136
1137void tst_QFileDialog2::task259105_filtersCornerCases()
1138{
1139 QFileDialog fd(0, "TestFileDialog");
1140 fd.setNameFilter(QLatin1String("All Files! (*);;Text Files (*.txt)"));
1141 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: true);
1142 fd.show();
1143 QVERIFY(QTest::qWaitForWindowExposed(&fd));
1144
1145 //Extensions are hidden
1146 QComboBox *filters = fd.findChild<QComboBox*>(aName: "fileTypeCombo");
1147 QVERIFY(filters);
1148 QCOMPARE(filters->currentText(), QLatin1String("All Files!"));
1149 filters->setCurrentIndex(1);
1150 QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
1151
1152 //We should have the full names
1153 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: false);
1154 filters->setCurrentIndex(0);
1155 QCOMPARE(filters->currentText(), QLatin1String("All Files! (*)"));
1156 filters->setCurrentIndex(1);
1157 QCOMPARE(filters->currentText(), QLatin1String("Text Files (*.txt)"));
1158
1159 //Corner case undocumented of the task
1160 fd.setNameFilter(QLatin1String("\352 (I like cheese) All Files! (*);;Text Files (*.txt)"));
1161 QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files! (*)"));
1162 filters->setCurrentIndex(1);
1163 QCOMPARE(filters->currentText(), QLatin1String("Text Files (*.txt)"));
1164
1165 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: true);
1166 filters->setCurrentIndex(0);
1167 QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files!"));
1168 filters->setCurrentIndex(1);
1169 QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
1170
1171 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: true);
1172 filters->setCurrentIndex(0);
1173 QCOMPARE(filters->currentText(), QLatin1String("\352 (I like cheese) All Files!"));
1174 filters->setCurrentIndex(1);
1175 QCOMPARE(filters->currentText(), QLatin1String("Text Files"));
1176}
1177
1178void tst_QFileDialog2::QTBUG4419_lineEditSelectAll()
1179{
1180 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
1181 QSKIP("Window activation is not supported");
1182
1183 QString tempPath = tempDir.path();
1184 QTemporaryFile temporaryFile(tempPath + "/tst_qfiledialog2_lineEditSelectAll.XXXXXX");
1185 QVERIFY2(temporaryFile.open(), qPrintable(temporaryFile.errorString()));
1186 QFileDialog fd(0, "TestFileDialog", temporaryFile.fileName());
1187
1188 fd.setDirectory(tempPath);
1189 fd.setViewMode(QFileDialog::List);
1190 fd.setAcceptMode(QFileDialog::AcceptSave);
1191 fd.setFileMode(QFileDialog::AnyFile);
1192
1193 fd.show();
1194 fd.activateWindow();
1195 QVERIFY(QTest::qWaitForWindowActive(&fd));
1196 QCOMPARE(fd.isVisible(), true);
1197 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
1198
1199 QLineEdit *lineEdit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
1200 QVERIFY(lineEdit);
1201
1202 QTRY_COMPARE(tempPath + QChar('/') + lineEdit->text(), temporaryFile.fileName());
1203 QCOMPARE(tempPath + QChar('/') + lineEdit->selectedText(), temporaryFile.fileName());
1204}
1205
1206void tst_QFileDialog2::QTBUG6558_showDirsOnly()
1207{
1208 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
1209 QSKIP("Window activation is not supported");
1210
1211 const QString tempPath = tempDir.path();
1212 QDir dirTemp(tempPath);
1213 const QString tempName = QLatin1String("showDirsOnly.") + QString::number(QRandomGenerator::global()->generate());
1214 dirTemp.mkdir(dirName: tempName);
1215 dirTemp.cd(dirName: tempName);
1216 QTRY_VERIFY(dirTemp.exists());
1217
1218 const QString dirPath = dirTemp.absolutePath();
1219 QDir dir(dirPath);
1220
1221 //We create two dirs
1222 dir.mkdir(dirName: "a");
1223 dir.mkdir(dirName: "b");
1224
1225 //Create a file
1226 QFile tempFile(dirPath + "/plop.txt");
1227 tempFile.open(flags: QIODevice::WriteOnly | QIODevice::Text);
1228 QTextStream out(&tempFile);
1229 out << "The magic number is: " << 49 << "\n";
1230 tempFile.close();
1231
1232 QFileDialog fd(0, "TestFileDialog");
1233
1234 fd.setDirectory(dir.absolutePath());
1235 fd.setViewMode(QFileDialog::List);
1236 fd.setAcceptMode(QFileDialog::AcceptSave);
1237 fd.setOption(option: QFileDialog::ShowDirsOnly, on: true);
1238 fd.show();
1239
1240 QApplication::setActiveWindow(&fd);
1241 QVERIFY(QTest::qWaitForWindowActive(&fd));
1242 QCOMPARE(fd.isVisible(), true);
1243 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
1244
1245 QFileSystemModel *model = fd.findChild<QFileSystemModel*>(aName: "qt_filesystem_model");
1246 QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
1247
1248 fd.setOption(option: QFileDialog::ShowDirsOnly, on: false);
1249 QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 3);
1250
1251 fd.setOption(option: QFileDialog::ShowDirsOnly, on: true);
1252 QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
1253
1254 fd.setFileMode(QFileDialog::DirectoryOnly);
1255 QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 2);
1256 QTRY_COMPARE(bool(fd.options() & QFileDialog::ShowDirsOnly), true);
1257
1258 fd.setFileMode(QFileDialog::AnyFile);
1259 QTRY_COMPARE(model->rowCount(model->index(dir.absolutePath())), 3);
1260 QTRY_COMPARE(bool(fd.options() & QFileDialog::ShowDirsOnly), false);
1261
1262 fd.setDirectory(QDir::homePath());
1263
1264 //We remove the dirs
1265 dir.rmdir(dirName: "a");
1266 dir.rmdir(dirName: "b");
1267
1268 //we delete the file
1269 tempFile.remove();
1270
1271 dirTemp.cdUp();
1272 dirTemp.rmdir(dirName: tempName);
1273}
1274
1275void tst_QFileDialog2::QTBUG4842_selectFilterWithHideNameFilterDetails()
1276{
1277 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
1278 QSKIP("Window activation is not supported");
1279
1280 QStringList filtersStr;
1281 filtersStr << "Images (*.png *.xpm *.jpg)" << "Text files (*.txt)" << "XML files (*.xml)";
1282 QString chosenFilterString("Text files (*.txt)");
1283
1284 QFileDialog fd(0, "TestFileDialog");
1285 fd.setAcceptMode(QFileDialog::AcceptSave);
1286 fd.setOption(option: QFileDialog::HideNameFilterDetails, on: true);
1287 fd.setNameFilters(filtersStr);
1288 fd.selectNameFilter(filter: chosenFilterString);
1289 fd.show();
1290
1291 QApplication::setActiveWindow(&fd);
1292 QVERIFY(QTest::qWaitForWindowActive(&fd));
1293 QCOMPARE(fd.isVisible(), true);
1294 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
1295
1296 QComboBox *filters = fd.findChild<QComboBox*>(aName: "fileTypeCombo");
1297 //We compare the current combobox text with the stripped version
1298 QCOMPARE(filters->currentText(), QString("Text files"));
1299
1300 QFileDialog fd2(0, "TestFileDialog");
1301 fd2.setAcceptMode(QFileDialog::AcceptSave);
1302 fd2.setOption(option: QFileDialog::HideNameFilterDetails, on: false);
1303 fd2.setNameFilters(filtersStr);
1304 fd2.selectNameFilter(filter: chosenFilterString);
1305 fd2.show();
1306
1307 QApplication::setActiveWindow(&fd2);
1308 QVERIFY(QTest::qWaitForWindowActive(&fd2));
1309 QCOMPARE(fd2.isVisible(), true);
1310 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd2));
1311
1312 QComboBox *filters2 = fd2.findChild<QComboBox*>(aName: "fileTypeCombo");
1313 //We compare the current combobox text with the non stripped version
1314 QCOMPARE(filters2->currentText(), chosenFilterString);
1315
1316}
1317
1318void tst_QFileDialog2::dontShowCompleterOnRoot()
1319{
1320 if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation))
1321 QSKIP("Window activation is not supported");
1322
1323 QFileDialog fd(0, "TestFileDialog");
1324 fd.setAcceptMode(QFileDialog::AcceptSave);
1325 fd.show();
1326
1327 QApplication::setActiveWindow(&fd);
1328 QVERIFY(QTest::qWaitForWindowActive(&fd));
1329 QCOMPARE(fd.isVisible(), true);
1330 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
1331
1332 fd.setDirectory("");
1333 QLineEdit *lineEdit = fd.findChild<QLineEdit*>(aName: "fileNameEdit");
1334 QTRY_VERIFY(lineEdit->text().isEmpty());
1335
1336 //The gatherer thread will then return the result
1337 QApplication::processEvents();
1338
1339 QTRY_VERIFY(lineEdit->completer()->popup()->isHidden());
1340}
1341
1342void tst_QFileDialog2::nameFilterParsing_data()
1343{
1344 QTest::addColumn<QString>(name: "filterString");
1345 QTest::addColumn<QStringList>(name: "filters");
1346
1347 // QTBUG-47923: Do not trip over "*,v".
1348 QTest::newRow(dataTag: "text") << "plain text document (*.txt *.asc *,v *.doc)"
1349 << (QStringList() << "*.txt" << "*.asc" << "*,v" << "*.doc");
1350 QTest::newRow(dataTag: "html") << "HTML document (*.html *.htm)"
1351 << (QStringList() << "*.html" << "*.htm");
1352}
1353
1354void tst_QFileDialog2::nameFilterParsing()
1355{
1356 QFETCH(QString, filterString);
1357 QFETCH(QStringList, filters);
1358 QCOMPARE(QPlatformFileDialogHelper::cleanFilterList(filterString), filters);
1359}
1360
1361QTEST_MAIN(tst_QFileDialog2)
1362#include "tst_qfiledialog2.moc"
1363

source code of qtbase/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp