32e1311505f6f7b97a4a7daddd824f0e421f4960
[profile/ivi/qtbase.git] / tests / auto / widgets / dialogs / qfiledialog / tst_qfiledialog.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <qcoreapplication.h>
46 #include <qdebug.h>
47 #include <qfiledialog.h>
48 #include <qabstractitemdelegate.h>
49 #include <qdirmodel.h>
50 #include <qitemdelegate.h>
51 #include <qlistview.h>
52 #include <qcombobox.h>
53 #include <qpushbutton.h>
54 #include <qtoolbutton.h>
55 #include <qtreeview.h>
56 #include <qheaderview.h>
57 #include <qcompleter.h>
58 #include <qaction.h>
59 #include <qdialogbuttonbox.h>
60 #include <qsortfilterproxymodel.h>
61 #include <qlineedit.h>
62 #include <qlayout.h>
63 #if defined QT_BUILD_INTERNAL
64 #include <private/qsidebar_p.h>
65 #include <private/qfilesystemmodel_p.h>
66 #include <private/qfiledialog_p.h>
67 #endif
68 #include <QFileDialog>
69 #include <QFileSystemModel>
70
71 #if defined(Q_OS_UNIX)
72 #ifdef QT_BUILD_INTERNAL
73 QT_BEGIN_NAMESPACE
74 extern Q_GUI_EXPORT QString qt_tildeExpansion(const QString &path, bool *expanded = 0);
75 QT_END_NAMESPACE
76 #endif
77 #endif
78
79 class QNonNativeFileDialog : public QFileDialog
80 {
81     Q_OBJECT
82 public:
83     QNonNativeFileDialog(QWidget *parent = 0, const QString &caption = QString(), const QString &directory = QString(), const QString &filter = QString())
84         : QFileDialog(parent, caption, directory, filter)
85     {
86         setOption(QFileDialog::DontUseNativeDialog, true);
87     }
88 };
89
90 class tst_QFiledialog : public QObject
91 {
92 Q_OBJECT
93
94 public:
95     tst_QFiledialog();
96     virtual ~tst_QFiledialog();
97
98 public slots:
99     void init();
100     void cleanup();
101
102 private slots:
103     void currentChangedSignal();
104 #ifdef QT_BUILD_INTERNAL
105     void directoryEnteredSignal();
106 #endif
107     void filesSelectedSignal_data();
108     void filesSelectedSignal();
109     void filterSelectedSignal();
110
111     void args();
112     void directory();
113     void completer_data();
114     void completer();
115     void completer_up();
116     void acceptMode();
117     void confirmOverwrite();
118     void defaultSuffix();
119     void fileMode();
120     void filters();
121     void history();
122     void iconProvider();
123     void isReadOnly();
124     void itemDelegate();
125     void labelText();
126     void resolveSymlinks();
127     void selectFile_data();
128     void selectFile();
129     void selectFiles();
130     void selectFilter();
131     void viewMode();
132     void proxymodel();
133     void setNameFilter();
134     void focus();
135     void caption();
136     void historyBack();
137     void historyForward();
138     void disableSaveButton_data();
139     void disableSaveButton();
140     void saveButtonText_data();
141     void saveButtonText();
142     void clearLineEdit();
143     void enableChooseButton();
144     void hooks();
145 #ifdef Q_OS_UNIX
146 #ifdef QT_BUILD_INTERNAL
147     void tildeExpansion_data();
148     void tildeExpansion();
149 #endif // QT_BUILD_INTERNAL
150 #endif
151
152 private:
153     QByteArray userSettings;
154 };
155
156 tst_QFiledialog::tst_QFiledialog()
157 {
158 }
159
160 tst_QFiledialog::~tst_QFiledialog()
161 {
162 }
163
164 void tst_QFiledialog::init()
165 {
166     // Save the developers settings so they don't get mad when their sidebar folders are gone.
167     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
168     settings.beginGroup(QLatin1String("Qt"));
169     userSettings = settings.value(QLatin1String("filedialog")).toByteArray();
170     settings.remove(QLatin1String("filedialog"));
171
172     // populate it with some default settings
173     QNonNativeFileDialog fd;
174 #if defined(Q_OS_WINCE)
175     QTest::qWait(1000);
176 #endif
177 }
178
179 void tst_QFiledialog::cleanup()
180 {
181     QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
182     settings.beginGroup(QLatin1String("Qt"));
183     settings.setValue(QLatin1String("filedialog"), userSettings);
184 }
185
186 class MyAbstractItemDelegate : public QAbstractItemDelegate
187 {
188 public:
189     MyAbstractItemDelegate() : QAbstractItemDelegate() {};
190     void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const {}
191     QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return QSize(); }
192 };
193
194 // emitted any time the selection model emits current changed
195 void tst_QFiledialog::currentChangedSignal()
196 {
197     QNonNativeFileDialog fd;
198     fd.setViewMode(QFileDialog::List);
199     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
200
201     QListView* listView = qFindChild<QListView*>(&fd, "listView");
202     QVERIFY(listView);
203     fd.setDirectory(QDir::root());
204     QModelIndex root = listView->rootIndex();
205     QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
206
207     QModelIndex folder;
208     for (int i = 0; i < listView->model()->rowCount(root); ++i) {
209         folder = listView->model()->index(i, 0, root);
210         if (listView->model()->hasChildren(folder))
211             break;
212     }
213     QVERIFY(listView->model()->hasChildren(folder));
214     listView->setCurrentIndex(folder);
215
216     QCOMPARE(spyCurrentChanged.count(), 1);
217 }
218
219 // only emitted from the views, sidebar, or lookin combo
220 #if defined QT_BUILD_INTERNAL
221 void tst_QFiledialog::directoryEnteredSignal()
222 {
223     QNonNativeFileDialog fd(0, "", QDir::root().path());
224     fd.setOptions(QFileDialog::DontUseNativeDialog);
225     fd.show();
226     QTRY_COMPARE(fd.isVisible(), true);
227     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
228
229     // sidebar
230     QSidebar *sidebar = qFindChild<QSidebar*>(&fd, "sidebar");
231     sidebar->setCurrentIndex(sidebar->model()->index(1, 0));
232     QTest::keyPress(sidebar->viewport(), Qt::Key_Return);
233     QCOMPARE(spyDirectoryEntered.count(), 1);
234     spyDirectoryEntered.clear();
235
236     // lookInCombo
237     QComboBox *comboBox = qFindChild<QComboBox*>(&fd, "lookInCombo");
238     comboBox->showPopup();
239     QVERIFY(comboBox->view()->model()->index(1, 0).isValid());
240     comboBox->view()->setCurrentIndex(comboBox->view()->model()->index(1, 0));
241     QTest::keyPress(comboBox->view()->viewport(), Qt::Key_Return);
242     QCOMPARE(spyDirectoryEntered.count(), 1);
243     spyDirectoryEntered.clear();
244
245     // view
246     /*
247     // platform specific
248     fd.setViewMode(QFileDialog::ViewMode(QFileDialog::List));
249     QListView* listView = qFindChild<QListView*>(&fd, "listView");
250     QVERIFY(listView);
251     QModelIndex root = listView->rootIndex();
252     QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
253
254     QModelIndex folder;
255     for (int i = 0; i < listView->model()->rowCount(root); ++i) {
256         folder = listView->model()->index(i, 0, root);
257         if (listView->model()->hasChildren(folder))
258             break;
259     }
260     QVERIFY(listView->model()->hasChildren(folder));
261     listView->setCurrentIndex(folder);
262     QTRY_COMPARE((listView->indexAt(listView->visualRect(folder).center())), folder);
263     QTest::mouseDClick(listView->viewport(), Qt::LeftButton, 0, listView->visualRect(folder).center());
264     QTRY_COMPARE(spyDirectoryEntered.count(), 1);
265     */
266 }
267 #endif
268
269 Q_DECLARE_METATYPE(QFileDialog::FileMode)
270 void tst_QFiledialog::filesSelectedSignal_data()
271 {
272     QTest::addColumn<QFileDialog::FileMode>("fileMode");
273     QTest::newRow("any") << QFileDialog::AnyFile;
274     QTest::newRow("existing") << QFileDialog::ExistingFile;
275     QTest::newRow("directory") << QFileDialog::Directory;
276     QTest::newRow("directoryOnly") << QFileDialog::DirectoryOnly;
277     QTest::newRow("existingFiles") << QFileDialog::ExistingFiles;
278 }
279
280 // emitted when the dialog closes with the selected files
281 void tst_QFiledialog::filesSelectedSignal()
282 {
283     QNonNativeFileDialog fd;
284     fd.setViewMode(QFileDialog::List);
285     fd.setOptions(QFileDialog::DontUseNativeDialog);
286     QDir testDir(SRCDIR);
287     fd.setDirectory(testDir);
288     QFETCH(QFileDialog::FileMode, fileMode);
289     fd.setFileMode(fileMode);
290     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
291
292     fd.show();
293     QVERIFY(QTest::qWaitForWindowExposed(&fd));
294     QListView *listView = qFindChild<QListView*>(&fd, "listView");
295     QVERIFY(listView);
296
297     QModelIndex root = listView->rootIndex();
298     QTRY_COMPARE(listView->model()->rowCount(root) > 0, true);
299     QModelIndex file;
300     for (int i = 0; i < listView->model()->rowCount(root); ++i) {
301         file = listView->model()->index(i, 0, root);
302         if (fileMode == QFileDialog::Directory || fileMode == QFileDialog::DirectoryOnly) {
303             if (listView->model()->hasChildren(file))
304                 break;
305         } else {
306             if (!listView->model()->hasChildren(file))
307                 break;
308         }
309         file = QModelIndex();
310     }
311     QVERIFY(file.isValid());
312     listView->selectionModel()->select(file, QItemSelectionModel::Select | QItemSelectionModel::Rows);
313     listView->setCurrentIndex(file);
314
315     QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
316     QPushButton *button = buttonBox->button(QDialogButtonBox::Open);
317     QVERIFY(button);
318     QVERIFY(button->isEnabled());
319     button->animateClick();
320     QTRY_COMPARE(fd.isVisible(), false);
321     QCOMPARE(spyFilesSelected.count(), 1);
322 }
323
324 // only emitted when the combo box is activated
325 void tst_QFiledialog::filterSelectedSignal()
326 {
327     QNonNativeFileDialog fd;
328     fd.setAcceptMode(QFileDialog::AcceptSave);
329     fd.show();
330     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
331
332     QStringList filterChoices;
333     filterChoices << "Image files (*.png *.xpm *.jpg)"
334                   << "Text files (*.txt)"
335                   << "Any files (*.*)";
336     fd.setNameFilters(filterChoices);
337     QCOMPARE(fd.nameFilters(), filterChoices);
338
339     QComboBox *filters = qFindChild<QComboBox*>(&fd, "fileTypeCombo");
340     QVERIFY(filters);
341     QVERIFY(filters->view());
342     QCOMPARE(filters->isVisible(), true);
343
344     QTest::keyPress(filters, Qt::Key_Down);
345
346     QCOMPARE(spyFilterSelected.count(), 1);
347 }
348
349 void tst_QFiledialog::args()
350 {
351     QWidget *parent = 0;
352     QString caption = "caption";
353     QString directory = QDir::tempPath();
354     QString filter = "*.mp3";
355     QNonNativeFileDialog fd(parent, caption, directory, filter);
356     QCOMPARE(fd.parent(), (QObject *)parent);
357     QCOMPARE(fd.windowTitle(), caption);
358 #ifndef Q_OS_WIN
359     QCOMPARE(fd.directory(), QDir(directory));
360 #endif
361     QCOMPARE(fd.nameFilters(), QStringList(filter));
362 }
363
364 void tst_QFiledialog::directory()
365 {
366     QNonNativeFileDialog fd;
367     fd.setViewMode(QFileDialog::List);
368     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
369     QVERIFY(model);
370     fd.setDirectory(QDir::currentPath());
371     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
372     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
373     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
374     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
375
376     QCOMPARE(QDir::current().absolutePath(), fd.directory().absolutePath());
377     QDir temp = QDir::temp();
378     QString tempPath = temp.absolutePath();
379 #ifdef Q_OS_WIN
380     // since the user can have lowercase temp dir, check that we are actually case-insensitive.
381     tempPath = tempPath.toLower();
382 #endif
383     fd.setDirectory(tempPath);
384 #ifndef Q_OS_WIN
385     QCOMPARE(tempPath, fd.directory().absolutePath());
386 #endif
387     QCOMPARE(spyCurrentChanged.count(), 0);
388     QCOMPARE(spyDirectoryEntered.count(), 0);
389     QCOMPARE(spyFilesSelected.count(), 0);
390     QCOMPARE(spyFilterSelected.count(), 0);
391
392     // Check my way
393     QList<QListView*> list = qFindChildren<QListView*>(&fd, "listView");
394     QVERIFY(list.count() > 0);
395 #ifdef Q_OS_WIN
396     QCOMPARE(list.at(0)->rootIndex().data().toString().toLower(), temp.dirName().toLower());
397 #else
398     QCOMPARE(list.at(0)->rootIndex().data().toString(), temp.dirName());
399 #endif
400     QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", tempPath);
401     QCOMPARE(model->index(tempPath), model->index(dlg->directory().absolutePath()));
402     QCOMPARE(model->index(tempPath).data(QFileSystemModel::FileNameRole).toString(),
403              model->index(dlg->directory().absolutePath()).data(QFileSystemModel::FileNameRole).toString());
404     delete dlg;
405     dlg = new QNonNativeFileDialog();
406     QCOMPARE(model->index(tempPath), model->index(dlg->directory().absolutePath()));
407     delete dlg;
408 }
409
410 void tst_QFiledialog::completer_data()
411 {
412     QTest::addColumn<QString>("startPath");
413     QTest::addColumn<QString>("input");
414     QTest::addColumn<int>("expected");
415
416     QTest::newRow("r, 10")   << "" << "r"   << 10;
417     QTest::newRow("x, 0")    << "" << "x"   << 0;
418     QTest::newRow("../, -1") << "" << "../" << -1;
419
420     QTest::newRow("goto root")     << QString()        << QDir::rootPath() << -1;
421     QTest::newRow("start at root") << QDir::rootPath() << QString()        << -1;
422
423     QDir root = QDir::root();
424     QStringList list = root.entryList();
425     QString folder;
426     for (int i = 0; i < list.count(); ++i) {
427         if (list.at(0) == QChar('.'))
428             continue;
429         QFileInfo info(QDir::rootPath() + list[i]);
430         if (info.isDir()) {
431             folder = QDir::rootPath() + list[i];
432             break;
433         }
434     }
435
436     QTest::newRow("start at one below root r") << folder << "r" << -1;
437     QTest::newRow("start at one below root ../") << folder << "../" << -1;
438 }
439
440 void tst_QFiledialog::completer()
441 {
442     QFETCH(QString, input);
443     QFETCH(QString, startPath);
444     QFETCH(int, expected);
445
446     QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir";
447     if (startPath.isEmpty())
448         startPath = tempPath;
449
450     startPath = QDir::cleanPath(startPath);
451
452     // make temp dir and files
453     {
454         QDir cleanup(tempPath);
455         QStringList x = cleanup.entryList();
456         for (int i = 0; i < x.count(); ++i)
457             QFile::remove(tempPath + '/' + x[i]);
458         cleanup.rmdir(tempPath);
459     }
460     QDir tmp(QDir::tempPath());
461     if (!tmp.exists(tempPath))
462         QVERIFY(tmp.mkdir("QFileDialogTestDir"));
463     QList<QTemporaryFile*> files;
464     QT_TRY {
465     for (int i = 0; i < 10; ++i) {
466         QScopedPointer<QTemporaryFile> file(new QTemporaryFile(tempPath + "/rXXXXXX"));
467         file->open();
468         files.append(file.take());
469     }
470
471     // ### flesh this out more
472     QNonNativeFileDialog fd(0,QString("Test it"),startPath);
473     fd.setOptions(QFileDialog::DontUseNativeDialog);
474     fd.show();
475     QVERIFY(QTest::qWaitForWindowExposed(&fd));
476     QVERIFY(fd.isVisible());
477     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
478     QVERIFY(model);
479     QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
480     QVERIFY(lineEdit);
481     QCompleter *completer = lineEdit->completer();
482     QVERIFY(completer);
483     QAbstractItemModel *cModel = completer->completionModel();
484     QVERIFY(cModel);
485
486     //wait a bit
487     QTest::qWait(500);
488
489     // path C:\depot\qt\examples\dialogs\standarddialogs
490     // files
491     //       [debug] [release] [tmp] dialog dialog main makefile makefile.debug makefile.release standarddialgos
492     //
493     // d      -> D:\ debug dialog.cpp dialog.h
494     // ..\    -> ..\classwizard ..\configdialog ..\dialogs.pro
495     // c      -> C:\ control panel
496     // c:     -> C:\ (nothing more)
497     // C:\    -> C:\, C:\_viminfo, ...
498     // \      -> \_viminfo
499     // c:\depot  -> 'nothing'
500     // c:\depot\ -> C:\depot\devtools, C:\depot\dteske
501     QCOMPARE(model->index(fd.directory().path()), model->index(startPath));
502
503     if (input.isEmpty()) {
504         QModelIndex r = model->index(model->rootPath());
505         QVERIFY(model->rowCount(r) > 0);
506         QModelIndex idx = model->index(0, 0, r);
507         input = idx.data().toString().at(0);
508     }
509
510     // press 'keys' for the input
511     for (int i = 0; i < input.count(); ++i)
512         QTest::keyPress(lineEdit, input[i].toLatin1());
513
514     QStringList expectedFiles;
515     if (expected == -1) {
516         QString fullPath = startPath.isEmpty() ? tempPath : startPath;
517         if (!fullPath.endsWith(QLatin1Char('/')))
518             fullPath.append(QLatin1Char('/'));
519         fullPath.append(input);
520         if (input.startsWith(QDir::rootPath())) {
521             fullPath = input;
522             input.clear();
523         }
524
525         QFileInfo fi(fullPath);
526         QDir x(fi.absolutePath());
527         expectedFiles = x.entryList(model->filter());
528         expected = 0;
529         if (input.startsWith(".."))
530             input.clear();
531         for (int ii = 0; ii < expectedFiles.count(); ++ii) {
532 #if defined(Q_OS_WIN)
533             if (expectedFiles.at(ii).startsWith(input,Qt::CaseInsensitive))
534 #else
535             if (expectedFiles.at(ii).startsWith(input))
536 #endif
537                 ++expected;
538         }
539     }
540
541     QTest::qWait(1000);
542     if (cModel->rowCount() != expected) {
543         for (int i = 0; i < cModel->rowCount(); ++i) {
544             QString file = cModel->index(i, 0).data().toString();
545             expectedFiles.removeAll(file);
546         }
547         //qDebug() << expectedFiles;
548     }
549
550     QTRY_COMPARE(cModel->rowCount(), expected);
551     } QT_CATCH(...) {
552         qDeleteAll(files);
553         QT_RETHROW;
554     }
555     qDeleteAll(files);
556 }
557
558 void tst_QFiledialog::completer_up()
559 {
560     QNonNativeFileDialog fd;
561     fd.setOptions(QFileDialog::DontUseNativeDialog);
562     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
563     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
564     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
565     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
566
567     fd.show();
568     QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
569     QVERIFY(lineEdit);
570     QCOMPARE(spyFilesSelected.count(), 0);
571     int depth = QDir::currentPath().split('/').count();
572     for (int i = 0; i <= depth * 3 + 1; ++i) {
573         lineEdit->insert("../");
574         qApp->processEvents();
575     }
576     QCOMPARE(spyCurrentChanged.count(), 0);
577     QCOMPARE(spyDirectoryEntered.count(), 0);
578     QCOMPARE(spyFilesSelected.count(), 0);
579     QCOMPARE(spyFilterSelected.count(), 0);
580 }
581
582 void tst_QFiledialog::acceptMode()
583 {
584     QNonNativeFileDialog fd;
585     fd.show();
586
587     QToolButton* newButton = qFindChild<QToolButton*>(&fd, "newFolderButton");
588     QVERIFY(newButton);
589
590     // default
591     QCOMPARE(fd.acceptMode(), QFileDialog::AcceptOpen);
592     QCOMPARE(newButton && newButton->isVisible(), true);
593
594     //fd.setDetailsExpanded(true);
595     fd.setAcceptMode(QFileDialog::AcceptSave);
596     QCOMPARE(fd.acceptMode(), QFileDialog::AcceptSave);
597     QCOMPARE(newButton->isVisible(), true);
598
599     fd.setAcceptMode(QFileDialog::AcceptOpen);
600     QCOMPARE(fd.acceptMode(), QFileDialog::AcceptOpen);
601     QCOMPARE(newButton->isVisible(), true);
602 }
603
604 void tst_QFiledialog::confirmOverwrite()
605 {
606     QNonNativeFileDialog fd;
607     QCOMPARE(fd.confirmOverwrite(), true);
608     fd.setConfirmOverwrite(true);
609     QCOMPARE(fd.confirmOverwrite(), true);
610     fd.setConfirmOverwrite(false);
611     QCOMPARE(fd.confirmOverwrite(), false);
612     fd.setConfirmOverwrite(true);
613     QCOMPARE(fd.confirmOverwrite(), true);
614 }
615
616 void tst_QFiledialog::defaultSuffix()
617 {
618     QNonNativeFileDialog fd;
619     QCOMPARE(fd.defaultSuffix(), QString());
620     fd.setDefaultSuffix("txt");
621     QCOMPARE(fd.defaultSuffix(), QString("txt"));
622     fd.setDefaultSuffix(QString());
623     QCOMPARE(fd.defaultSuffix(), QString());
624 }
625
626 void tst_QFiledialog::fileMode()
627 {
628     QNonNativeFileDialog fd;
629     QCOMPARE(fd.fileMode(), QFileDialog::AnyFile);
630     fd.setFileMode(QFileDialog::ExistingFile);
631     QCOMPARE(fd.fileMode(), QFileDialog::ExistingFile);
632     fd.setFileMode(QFileDialog::Directory);
633     QCOMPARE(fd.fileMode(), QFileDialog::Directory);
634     fd.setFileMode(QFileDialog::DirectoryOnly);
635     QCOMPARE(fd.fileMode(), QFileDialog::DirectoryOnly);
636     fd.setFileMode(QFileDialog::ExistingFiles);
637     QCOMPARE(fd.fileMode(), QFileDialog::ExistingFiles);
638 }
639
640 void tst_QFiledialog::caption()
641 {
642     QNonNativeFileDialog fd;
643     fd.setWindowTitle("testing");
644     fd.setFileMode(QFileDialog::Directory);
645     QCOMPARE(fd.windowTitle(), QString("testing"));
646 }
647
648 void tst_QFiledialog::filters()
649 {
650     QNonNativeFileDialog fd;
651     fd.setOptions(QFileDialog::DontUseNativeDialog);
652     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
653     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
654     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
655     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
656     QCOMPARE(fd.nameFilters(), QStringList("All Files (*)"));
657
658     // effects
659     QList<QComboBox*> views = qFindChildren<QComboBox*>(&fd, "fileTypeCombo");
660     QVERIFY(views.count() == 1);
661     QCOMPARE(views.at(0)->isVisible(), false);
662
663     QStringList filters;
664     filters << "Image files (*.png *.xpm *.jpg)"
665          << "Text files (*.txt)"
666          << "Any files (*.*)";
667     fd.setNameFilters(filters);
668     QCOMPARE(views.at(0)->isVisible(), false);
669     fd.show();
670     fd.setAcceptMode(QFileDialog::AcceptSave);
671     QCOMPARE(views.at(0)->isVisible(), true);
672     QCOMPARE(fd.nameFilters(), filters);
673     fd.setNameFilter("Image files (*.png *.xpm *.jpg);;Text files (*.txt);;Any files (*.*)");
674     QCOMPARE(fd.nameFilters(), filters);
675     QCOMPARE(spyCurrentChanged.count(), 0);
676     QCOMPARE(spyDirectoryEntered.count(), 0);
677     QCOMPARE(spyFilesSelected.count(), 0);
678     QCOMPARE(spyFilterSelected.count(), 0);
679
680     // setting shouldn't emit any signals
681     for (int i = views.at(0)->currentIndex(); i < views.at(0)->count(); ++i)
682         views.at(0)->setCurrentIndex(i);
683     QCOMPARE(spyFilterSelected.count(), 0);
684
685     //Let check if filters with whitespaces
686     QNonNativeFileDialog fd2;
687     QStringList expected;
688     expected << "C++ Source Files(*.cpp)";
689     expected << "Any(*.*)";
690     fd2.setNameFilter("C++ Source Files(*.cpp);;Any(*.*)");
691     QCOMPARE(expected, fd2.nameFilters());
692     fd2.setNameFilter("C++ Source Files(*.cpp) ;;Any(*.*)");
693     QCOMPARE(expected, fd2.nameFilters());
694     fd2.setNameFilter("C++ Source Files(*.cpp);; Any(*.*)");
695     QCOMPARE(expected, fd2.nameFilters());
696     fd2.setNameFilter(" C++ Source Files(*.cpp);; Any(*.*)");
697     QCOMPARE(expected, fd2.nameFilters());
698     fd2.setNameFilter("C++ Source Files(*.cpp) ;; Any(*.*)");
699     QCOMPARE(expected, fd2.nameFilters());
700 }
701
702 void tst_QFiledialog::selectFilter()
703 {
704     QNonNativeFileDialog fd;
705     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
706     QCOMPARE(fd.selectedNameFilter(), QString("All Files (*)"));
707     QStringList filters;
708     filters << "Image files (*.png *.xpm *.jpg)"
709          << "Text files (*.txt)"
710          << "Any files (*.*)";
711     fd.setNameFilters(filters);
712     QCOMPARE(fd.selectedNameFilter(), filters.at(0));
713     fd.selectNameFilter(filters.at(1));
714     QCOMPARE(fd.selectedNameFilter(), filters.at(1));
715     fd.selectNameFilter(filters.at(2));
716     QCOMPARE(fd.selectedNameFilter(), filters.at(2));
717
718     fd.selectNameFilter("bob");
719     QCOMPARE(fd.selectedNameFilter(), filters.at(2));
720     fd.selectNameFilter("");
721     QCOMPARE(fd.selectedNameFilter(), filters.at(2));
722     QCOMPARE(spyFilterSelected.count(), 0);
723 }
724
725 void tst_QFiledialog::history()
726 {
727     QNonNativeFileDialog fd;
728     fd.setViewMode(QFileDialog::List);
729     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
730     QVERIFY(model);
731     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
732     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
733     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
734     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
735     QCOMPARE(model->index(fd.history().first()), model->index(QDir::toNativeSeparators(fd.directory().absolutePath())));
736     fd.setDirectory(QDir::current().absolutePath());
737     QStringList history;
738     history << QDir::toNativeSeparators(QDir::current().absolutePath())
739             << QDir::toNativeSeparators(QDir::home().absolutePath())
740             << QDir::toNativeSeparators(QDir::temp().absolutePath());
741     fd.setHistory(history);
742     if (fd.history() != history) {
743         qDebug() << fd.history() << history;
744         // quick and dirty output for windows failure.
745         QListView* list = qFindChild<QListView*>(&fd, "listView");
746         QVERIFY(list);
747         QModelIndex root = list->rootIndex();
748         while (root.isValid()) {
749             qDebug() << root.data();
750             root = root.parent();
751         }
752     }
753     QCOMPARE(fd.history(), history);
754
755     QStringList badHistory;
756     badHistory << "junk";
757     fd.setHistory(badHistory);
758     badHistory << QDir::toNativeSeparators(QDir::current().absolutePath());
759     QCOMPARE(fd.history(), badHistory);
760
761     QCOMPARE(spyCurrentChanged.count(), 0);
762     QCOMPARE(spyDirectoryEntered.count(), 0);
763     QCOMPARE(spyFilesSelected.count(), 0);
764     QCOMPARE(spyFilterSelected.count(), 0);
765 }
766
767 void tst_QFiledialog::iconProvider()
768 {
769     QNonNativeFileDialog *fd = new QNonNativeFileDialog();
770     QVERIFY(fd->iconProvider() != 0);
771     QFileIconProvider *ip = new QFileIconProvider();
772     fd->setIconProvider(ip);
773     QCOMPARE(fd->iconProvider(), ip);
774     delete fd;
775     delete ip;
776 }
777
778 void tst_QFiledialog::isReadOnly()
779 {
780     QNonNativeFileDialog fd;
781
782     QPushButton* newButton = qFindChild<QPushButton*>(&fd, "newFolderButton");
783     QAction* renameAction = qFindChild<QAction*>(&fd, "qt_rename_action");
784     QAction* deleteAction = qFindChild<QAction*>(&fd, "qt_delete_action");
785
786     QCOMPARE(fd.isReadOnly(), false);
787
788     // This is dependent upon the file/dir, find cross platform way to test
789     //fd.setDirectory(QDir::home());
790     //QCOMPARE(newButton && newButton->isEnabled(), true);
791     //QCOMPARE(renameAction && renameAction->isEnabled(), true);
792     //QCOMPARE(deleteAction && deleteAction->isEnabled(), true);
793
794     fd.setReadOnly(true);
795     QCOMPARE(fd.isReadOnly(), true);
796
797     QCOMPARE(newButton && newButton->isEnabled(), false);
798     QCOMPARE(renameAction && renameAction->isEnabled(), false);
799     QCOMPARE(deleteAction && deleteAction->isEnabled(), false);
800 }
801
802 void tst_QFiledialog::itemDelegate()
803 {
804     QNonNativeFileDialog fd;
805     QVERIFY(fd.itemDelegate() != 0);
806     QItemDelegate *id = new QItemDelegate(&fd);
807     fd.setItemDelegate(id);
808     QCOMPARE(fd.itemDelegate(), (QAbstractItemDelegate *)id);
809 }
810
811 void tst_QFiledialog::labelText()
812 {
813     QNonNativeFileDialog fd;
814     QDialogButtonBox buttonBox;
815     QPushButton *cancelButton = buttonBox.addButton(QDialogButtonBox::Cancel);
816     QCOMPARE(fd.labelText(QFileDialog::LookIn), QString("Look in:"));
817     QCOMPARE(fd.labelText(QFileDialog::FileName), QString("File &name:"));
818     QCOMPARE(fd.labelText(QFileDialog::FileType), QString("Files of type:"));
819     QCOMPARE(fd.labelText(QFileDialog::Accept), QString("&Open")); ///### see task 241462
820     QCOMPARE(fd.labelText(QFileDialog::Reject), cancelButton->text());
821
822     fd.setLabelText(QFileDialog::LookIn, "1");
823     QCOMPARE(fd.labelText(QFileDialog::LookIn), QString("1"));
824     fd.setLabelText(QFileDialog::FileName, "2");
825     QCOMPARE(fd.labelText(QFileDialog::FileName), QString("2"));
826     fd.setLabelText(QFileDialog::FileType, "3");
827     QCOMPARE(fd.labelText(QFileDialog::FileType), QString("3"));
828     fd.setLabelText(QFileDialog::Accept, "4");
829     QCOMPARE(fd.labelText(QFileDialog::Accept), QString("4"));
830     fd.setLabelText(QFileDialog::Reject, "5");
831     QCOMPARE(fd.labelText(QFileDialog::Reject), QString("5"));
832 }
833
834 void tst_QFiledialog::resolveSymlinks()
835 {
836     QNonNativeFileDialog fd;
837
838     // default
839     QCOMPARE(fd.resolveSymlinks(), true);
840     fd.setResolveSymlinks(false);
841     QCOMPARE(fd.resolveSymlinks(), false);
842     fd.setResolveSymlinks(true);
843     QCOMPARE(fd.resolveSymlinks(), true);
844
845     // the file dialog doesn't do anything based upon this, just passes it to the model
846     // the model should fully test it, don't test it here
847 }
848
849 void tst_QFiledialog::selectFile_data()
850 {
851     QTest::addColumn<QString>("file");
852     QTest::addColumn<int>("count");
853     QTest::newRow("null") << QString() << 1;
854     QTest::newRow("file") << "foo" << 1;
855     QTest::newRow("tmp") << "temp" << 1;
856 }
857
858 void tst_QFiledialog::selectFile()
859 {
860     QFETCH(QString, file);
861     QFETCH(int, count);
862     QNonNativeFileDialog fd;
863     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
864     QVERIFY(model);
865     fd.setDirectory(QDir::currentPath());
866     // default value
867     QCOMPARE(fd.selectedFiles().count(), 1);
868
869     QTemporaryFile tempFile(QDir::tempPath() + "/aXXXXXX");
870     bool inTemp = (file == "temp");
871     if (inTemp) {
872         tempFile.open();
873         file = tempFile.fileName();
874     }
875
876     fd.selectFile(file);
877     QCOMPARE(fd.selectedFiles().count(), count);
878     if (inTemp) {
879         QCOMPARE(model->index(fd.directory().path()), model->index(QDir::tempPath()));
880     } else {
881         QCOMPARE(model->index(fd.directory().path()), model->index(QDir::currentPath()));
882     }
883 }
884
885 void tst_QFiledialog::selectFiles()
886 {
887     QNonNativeFileDialog fd;
888     fd.setViewMode(QFileDialog::List);
889     QString tempPath = QDir::tempPath() + '/' + "QFileDialogTestDir4SelectFiles";
890     QDir dir;
891     QVERIFY(dir.mkpath(tempPath));
892     fd.setDirectory(tempPath);
893     QSignalSpy spyCurrentChanged(&fd, SIGNAL(currentChanged(const QString &)));
894     QSignalSpy spyDirectoryEntered(&fd, SIGNAL(directoryEntered(const QString &)));
895     QSignalSpy spyFilesSelected(&fd, SIGNAL(filesSelected(const QStringList &)));
896     QSignalSpy spyFilterSelected(&fd, SIGNAL(filterSelected(const QString &)));
897     fd.show();
898     fd.setFileMode(QFileDialog::ExistingFiles);
899
900     QString filesPath = fd.directory().absolutePath();
901     for (int i=0; i < 5; ++i) {
902         QFile file(filesPath + QString::fromLatin1("/qfiledialog_auto_test_not_pres_%1").arg(i));
903         file.open(QIODevice::WriteOnly);
904         file.resize(1024);
905         file.flush();
906         file.close();
907     }
908
909     // Get a list of files in the view and then get the corresponding index's
910     QStringList list = fd.directory().entryList(QDir::Files);
911     QModelIndexList toSelect;
912     QVERIFY(list.count() > 1);
913     QListView* listView = qFindChild<QListView*>(&fd, "listView");
914     QVERIFY(listView);
915     for (int i = 0; i < list.count(); ++i) {
916         fd.selectFile(fd.directory().path() + "/" + list.at(i));
917         QTRY_VERIFY(!listView->selectionModel()->selectedRows().isEmpty());
918         toSelect.append(listView->selectionModel()->selectedRows().last());
919     }
920     QCOMPARE(spyFilesSelected.count(), 0);
921
922     listView->selectionModel()->clear();
923     QCOMPARE(spyFilesSelected.count(), 0);
924
925     // select the indexes
926     for (int i = 0; i < toSelect.count(); ++i) {
927         listView->selectionModel()->select(toSelect.at(i),
928                 QItemSelectionModel::Select | QItemSelectionModel::Rows);
929     }
930     QCOMPARE(fd.selectedFiles().count(), toSelect.count());
931     QCOMPARE(spyCurrentChanged.count(), 0);
932     QCOMPARE(spyDirectoryEntered.count(), 0);
933     QCOMPARE(spyFilesSelected.count(), 0);
934     QCOMPARE(spyFilterSelected.count(), 0);
935     for (int i=0; i < 5; ++i)
936         QFile::remove(filesPath + QString::fromLatin1("/qfiledialog_auto_test_not_pres_%1").arg(i));
937
938     //If the selection is invalid then we fill the line edit but without the /
939     QNonNativeFileDialog * dialog = new QNonNativeFileDialog( 0, "Save" );
940     dialog->setFileMode( QFileDialog::AnyFile );
941     dialog->setAcceptMode( QFileDialog::AcceptSave );
942     QString temporary = QDir::tempPath() + QLatin1String("/blah");
943     dialog->selectFile(temporary);
944     dialog->show();
945     QVERIFY(QTest::qWaitForWindowExposed(dialog));
946     QLineEdit *lineEdit = qFindChild<QLineEdit*>(dialog, "fileNameEdit");
947     QVERIFY(lineEdit);
948     QCOMPARE(lineEdit->text(),QLatin1String("blah"));
949     delete dialog;
950 }
951
952 void tst_QFiledialog::viewMode()
953 {
954     QNonNativeFileDialog fd;
955     fd.setViewMode(QFileDialog::List);
956     fd.show();
957
958     // find widgets
959     QList<QTreeView*> treeView = qFindChildren<QTreeView*>(&fd, "treeView");
960     QCOMPARE(treeView.count(), 1);
961     QList<QListView*> listView = qFindChildren<QListView*>(&fd, "listView");
962     QCOMPARE(listView.count(), 1);
963     QList<QToolButton*> listButton = qFindChildren<QToolButton*>(&fd, "listModeButton");
964     QCOMPARE(listButton.count(), 1);
965     QList<QToolButton*> treeButton = qFindChildren<QToolButton*>(&fd, "detailModeButton");
966     QCOMPARE(treeButton.count(), 1);
967
968     // default value
969     QCOMPARE(fd.viewMode(), QFileDialog::List);
970
971     // detail
972     fd.setViewMode(QFileDialog::ViewMode(QFileDialog::Detail));
973
974     QCOMPARE(QFileDialog::ViewMode(QFileDialog::Detail), fd.viewMode());
975     QCOMPARE(listView.at(0)->isVisible(), false);
976     QCOMPARE(listButton.at(0)->isDown(), false);
977     QCOMPARE(treeView.at(0)->isVisible(), true);
978     QCOMPARE(treeButton.at(0)->isDown(), true);
979
980     // list
981     fd.setViewMode(QFileDialog::ViewMode(QFileDialog::List));
982
983     QCOMPARE(QFileDialog::ViewMode(QFileDialog::List), fd.viewMode());
984     QCOMPARE(treeView.at(0)->isVisible(), false);
985     QCOMPARE(treeButton.at(0)->isDown(), false);
986     QCOMPARE(listView.at(0)->isVisible(), true);
987     QCOMPARE(listButton.at(0)->isDown(), true);
988 }
989
990 void tst_QFiledialog::proxymodel()
991 {
992     QNonNativeFileDialog fd;
993     QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
994
995     fd.setProxyModel(0);
996     QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
997
998     QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(&fd);
999     fd.setProxyModel(proxyModel);
1000     QCOMPARE(fd.proxyModel(), (QAbstractProxyModel *)proxyModel);
1001
1002     fd.setProxyModel(0);
1003     QCOMPARE(fd.proxyModel(), (QAbstractProxyModel*)0);
1004 }
1005
1006 void tst_QFiledialog::setNameFilter()
1007 {
1008     QNonNativeFileDialog fd;
1009     fd.setNameFilter(QString());
1010     fd.setNameFilters(QStringList());
1011 }
1012
1013 void tst_QFiledialog::focus()
1014 {
1015     QNonNativeFileDialog fd;
1016     fd.setDirectory(QDir::currentPath());
1017     fd.show();
1018     QApplication::setActiveWindow(&fd);
1019     QVERIFY(QTest::qWaitForWindowActive(&fd));
1020     QCOMPARE(fd.isVisible(), true);
1021     QCOMPARE(QApplication::activeWindow(), static_cast<QWidget*>(&fd));
1022     qApp->processEvents();
1023
1024     // make sure the tests work with focus follows mouse
1025     QCursor::setPos(fd.geometry().center());
1026     QApplication::syncX();
1027
1028     QList<QWidget*> treeView = qFindChildren<QWidget*>(&fd, "fileNameEdit");
1029     QCOMPARE(treeView.count(), 1);
1030     QVERIFY(treeView.at(0));
1031     QTRY_COMPARE(treeView.at(0)->hasFocus(), true);
1032     QCOMPARE(treeView.at(0)->hasFocus(), true);
1033 }
1034
1035
1036 void tst_QFiledialog::historyBack()
1037 {
1038     QNonNativeFileDialog fd;
1039     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
1040     QVERIFY(model);
1041     QToolButton *backButton = qFindChild<QToolButton*>(&fd, "backButton");
1042     QVERIFY(backButton);
1043     QToolButton *forwardButton = qFindChild<QToolButton*>(&fd, "forwardButton");
1044     QVERIFY(forwardButton);
1045
1046     QSignalSpy spy(model, SIGNAL(rootPathChanged(const QString &)));
1047
1048     QString home = fd.directory().absolutePath();
1049     QString desktop = QDir::homePath();
1050     QString temp = QDir::tempPath();
1051
1052     QCOMPARE(backButton->isEnabled(), false);
1053     QCOMPARE(forwardButton->isEnabled(), false);
1054     fd.setDirectory(temp);
1055     qApp->processEvents();
1056     QCOMPARE(backButton->isEnabled(), true);
1057     QCOMPARE(forwardButton->isEnabled(), false);
1058     fd.setDirectory(desktop);
1059     QCOMPARE(spy.count(), 2);
1060
1061     backButton->click();
1062     qApp->processEvents();
1063     QCOMPARE(backButton->isEnabled(), true);
1064     QCOMPARE(forwardButton->isEnabled(), true);
1065     QCOMPARE(spy.count(), 3);
1066     QString currentPath = qvariant_cast<QString>(spy.last().first());
1067     QCOMPARE(model->index(currentPath), model->index(temp));
1068
1069     backButton->click();
1070     currentPath = qvariant_cast<QString>(spy.last().first());
1071     QCOMPARE(currentPath, home);
1072     QCOMPARE(backButton->isEnabled(), false);
1073     QCOMPARE(forwardButton->isEnabled(), true);
1074     QCOMPARE(spy.count(), 4);
1075
1076     // nothing should change at this point
1077     backButton->click();
1078     QCOMPARE(spy.count(), 4);
1079     QCOMPARE(backButton->isEnabled(), false);
1080     QCOMPARE(forwardButton->isEnabled(), true);
1081 }
1082
1083 void tst_QFiledialog::historyForward()
1084 {
1085     QNonNativeFileDialog fd;
1086     fd.setDirectory(QDir::currentPath());
1087     QToolButton *backButton = qFindChild<QToolButton*>(&fd, "backButton");
1088     QVERIFY(backButton);
1089     QToolButton *forwardButton = qFindChild<QToolButton*>(&fd, "forwardButton");
1090     QVERIFY(forwardButton);
1091
1092     QFileSystemModel *model = qFindChild<QFileSystemModel*>(&fd, "qt_filesystem_model");
1093     QVERIFY(model);
1094     QSignalSpy spy(model, SIGNAL(rootPathChanged(const QString &)));
1095
1096     QString home = fd.directory().absolutePath();
1097     QString desktop = QDir::homePath();
1098     QString temp = QDir::tempPath();
1099
1100     fd.setDirectory(home);
1101     fd.setDirectory(temp);
1102     fd.setDirectory(desktop);
1103
1104     backButton->click();
1105     QCOMPARE(forwardButton->isEnabled(), true);
1106     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp));
1107
1108     forwardButton->click();
1109     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(desktop));
1110     QCOMPARE(backButton->isEnabled(), true);
1111     QCOMPARE(forwardButton->isEnabled(), false);
1112     QCOMPARE(spy.count(), 4);
1113
1114     backButton->click();
1115     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp));
1116     QCOMPARE(backButton->isEnabled(), true);
1117
1118     backButton->click();
1119     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(home));
1120     QCOMPARE(backButton->isEnabled(), false);
1121     QCOMPARE(forwardButton->isEnabled(), true);
1122     QCOMPARE(spy.count(), 6);
1123
1124     forwardButton->click();
1125     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp));
1126     backButton->click();
1127     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(home));
1128     QCOMPARE(spy.count(), 8);
1129
1130     forwardButton->click();
1131     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp));
1132     forwardButton->click();
1133     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(desktop));
1134
1135     backButton->click();
1136     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(temp));
1137     backButton->click();
1138     QCOMPARE(model->index(qvariant_cast<QString>(spy.last().first())), model->index(home));
1139     fd.setDirectory(desktop);
1140     QCOMPARE(forwardButton->isEnabled(), false);
1141 }
1142
1143 void tst_QFiledialog::disableSaveButton_data()
1144 {
1145     QTest::addColumn<QString>("path");
1146     QTest::addColumn<bool>("isEnabled");
1147
1148     QTest::newRow("valid path") << QDir::temp().absolutePath() + QDir::separator() + "qfiledialog.new_file" << true;
1149     QTest::newRow("no path") << "" << false;
1150 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_OPENBSD)
1151     QTest::newRow("too long path") << "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii" << false;
1152 #endif
1153     QTest::newRow("file") << "foo.html" << true;
1154 }
1155
1156 void tst_QFiledialog::disableSaveButton()
1157 {
1158     QFETCH(QString, path);
1159     QFETCH(bool, isEnabled);
1160
1161     QNonNativeFileDialog fd(0, "caption", path);
1162     fd.setAcceptMode(QFileDialog::AcceptSave);
1163     QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
1164     QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
1165     QVERIFY(button);
1166     QCOMPARE(button->isEnabled(), isEnabled);
1167 }
1168
1169 void tst_QFiledialog::saveButtonText_data()
1170 {
1171     QTest::addColumn<QString>("path");
1172     QTest::addColumn<QString>("label");
1173     QTest::addColumn<QString>("caption");
1174
1175     QTest::newRow("empty path") << "" << QString() << QFileDialog::tr("&Save");
1176     QTest::newRow("file path") << "qfiledialog.new_file" << QString() << QFileDialog::tr("&Save");
1177     QTest::newRow("dir") << QDir::temp().absolutePath() << QString() << QFileDialog::tr("&Open");
1178     QTest::newRow("setTextLabel") << "qfiledialog.new_file" << "Mooo" << "Mooo";
1179     QTest::newRow("dir & label") << QDir::temp().absolutePath() << "Poo" << QFileDialog::tr("&Open");
1180 }
1181
1182 void tst_QFiledialog::saveButtonText()
1183 {
1184     QFETCH(QString, path);
1185     QFETCH(QString, label);
1186     QFETCH(QString, caption);
1187
1188     QNonNativeFileDialog fd(0, "auto test", QDir::temp().absolutePath());
1189     fd.setAcceptMode(QFileDialog::AcceptSave);
1190     if (!label.isNull())
1191         fd.setLabelText(QFileDialog::Accept, label);
1192     fd.setDirectory(QDir::temp());
1193     fd.selectFile(path);
1194     QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
1195     QVERIFY(buttonBox);
1196     QPushButton *button = buttonBox->button(QDialogButtonBox::Save);
1197     QVERIFY(button);
1198     QCOMPARE(button->text(), caption);
1199 }
1200
1201 void tst_QFiledialog::clearLineEdit()
1202 {
1203     QNonNativeFileDialog fd(0, "caption", "foo");
1204     fd.setViewMode(QFileDialog::List);
1205     fd.setFileMode(QFileDialog::AnyFile);
1206     fd.setOptions(QFileDialog::DontUseNativeDialog);
1207     fd.show();
1208
1209     //play it really safe by creating a directory
1210     QDir::home().mkdir("_____aaaaaaaaaaaaaaaaaaaaaa");
1211
1212     QLineEdit *lineEdit = qFindChild<QLineEdit*>(&fd, "fileNameEdit");
1213     QVERIFY(lineEdit);
1214     QVERIFY(lineEdit->text() == "foo");
1215     fd.setDirectory(QDir::home());
1216
1217     QListView* list = qFindChild<QListView*>(&fd, "listView");
1218     QVERIFY(list);
1219
1220     // saving a file the text shouldn't be cleared
1221     fd.setDirectory(QDir::home());
1222
1223     QTest::qWait(1000);
1224 #ifdef QT_KEYPAD_NAVIGATION
1225     list->setEditFocus(true);
1226 #endif
1227     QTest::keyClick(list, Qt::Key_Down);
1228 #ifndef Q_OS_MAC
1229     QTest::keyClick(list, Qt::Key_Return);
1230 #else
1231     QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
1232 #endif
1233
1234     QTest::qWait(2000);
1235 #ifdef Q_OS_MAC
1236     QEXPECT_FAIL("", "QTBUG-23703", Abort);
1237 #endif
1238     QVERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
1239     QVERIFY(!lineEdit->text().isEmpty());
1240
1241     // selecting a dir the text should be cleared so one can just hit ok
1242     // and it selects that directory
1243     fd.setFileMode(QNonNativeFileDialog::Directory);
1244     fd.setDirectory(QDir::home());
1245
1246     QTest::qWait(1000);
1247     QTest::keyClick(list, Qt::Key_Down);
1248 #ifndef Q_OS_MAC
1249     QTest::keyClick(list, Qt::Key_Return);
1250 #else
1251     QTest::keyClick(list, Qt::Key_O, Qt::ControlModifier);
1252 #endif
1253
1254     QTest::qWait(2000);
1255     QVERIFY(fd.directory().absolutePath() != QDir::home().absolutePath());
1256     QVERIFY(lineEdit->text().isEmpty());
1257
1258     //remove the dir
1259     QDir::home().rmdir("_____aaaaaaaaaaaaaaaaaaaaaa");
1260 }
1261
1262 void tst_QFiledialog::enableChooseButton()
1263 {
1264     QNonNativeFileDialog fd;
1265     fd.setFileMode(QFileDialog::Directory);
1266     fd.show();
1267     QDialogButtonBox *buttonBox = qFindChild<QDialogButtonBox*>(&fd, "buttonBox");
1268     QPushButton *button = buttonBox->button(QDialogButtonBox::Open);
1269     QVERIFY(button);
1270     QCOMPARE(button->isEnabled(), true);
1271 }
1272
1273 QT_BEGIN_NAMESPACE
1274 typedef QString (*_qt_filedialog_existing_directory_hook)(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options);
1275 extern Q_GUI_EXPORT _qt_filedialog_existing_directory_hook qt_filedialog_existing_directory_hook;
1276 QT_END_NAMESPACE
1277 QString existing(QWidget *, const QString &, const QString &, QFileDialog::Options) {
1278     return "dir";
1279 }
1280
1281 QT_BEGIN_NAMESPACE
1282 typedef QString (*_qt_filedialog_open_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
1283 extern Q_GUI_EXPORT _qt_filedialog_open_filename_hook qt_filedialog_open_filename_hook;
1284 QT_END_NAMESPACE
1285 QString openName(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
1286     return "openName";
1287 }
1288
1289 QT_BEGIN_NAMESPACE
1290 typedef QStringList (*_qt_filedialog_open_filenames_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
1291 extern Q_GUI_EXPORT _qt_filedialog_open_filenames_hook qt_filedialog_open_filenames_hook;
1292 QT_END_NAMESPACE
1293 QStringList openNames(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
1294     return QStringList("openNames");
1295 }
1296
1297 QT_BEGIN_NAMESPACE
1298 typedef QString (*_qt_filedialog_save_filename_hook)(QWidget * parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options);
1299 extern Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook;
1300 QT_END_NAMESPACE
1301 QString saveName(QWidget *, const QString &, const QString &, const QString &, QString *, QFileDialog::Options) {
1302     return "saveName";
1303 }
1304
1305
1306 void tst_QFiledialog::hooks()
1307 {
1308     qt_filedialog_existing_directory_hook = &existing;
1309     qt_filedialog_save_filename_hook = &saveName;
1310     qt_filedialog_open_filename_hook = &openName;
1311     qt_filedialog_open_filenames_hook = &openNames;
1312
1313     QCOMPARE(QFileDialog::getExistingDirectory(), QString("dir"));
1314     QCOMPARE(QFileDialog::getOpenFileName(), QString("openName"));
1315     QCOMPARE(QFileDialog::getOpenFileNames(), QStringList("openNames"));
1316     QCOMPARE(QFileDialog::getSaveFileName(), QString("saveName"));
1317 }
1318
1319 #ifdef Q_OS_UNIX
1320 #ifdef QT_BUILD_INTERNAL
1321 void tst_QFiledialog::tildeExpansion_data()
1322 {
1323     QTest::addColumn<QString>("tildePath");
1324     QTest::addColumn<QString>("expandedPath");
1325
1326     QTest::newRow("empty path") << QString() << QString();
1327     QTest::newRow("~") << QString::fromLatin1("~") << QDir::homePath();
1328     QTest::newRow("~/some/sub/dir/") << QString::fromLatin1("~/some/sub/dir") << QDir::homePath()
1329                                         + QString::fromLatin1("/some/sub/dir");
1330     QString userHome = QString(qgetenv("USER"));
1331     userHome.prepend('~');
1332     QTest::newRow("current user (~<user> syntax)") << userHome << QDir::homePath();
1333     QString invalid = QString::fromLatin1("~thisIsNotAValidUserName");
1334     QTest::newRow("invalid user name") << invalid << invalid;
1335 }
1336 #endif // QT_BUILD_INTERNAL
1337
1338 #ifdef QT_BUILD_INTERNAL
1339 void tst_QFiledialog::tildeExpansion()
1340 {
1341     QFETCH(QString, tildePath);
1342     QFETCH(QString, expandedPath);
1343
1344     QCOMPARE(qt_tildeExpansion(tildePath), expandedPath);
1345 }
1346 #endif // QT_BUILD_INTERNAL
1347 #endif
1348
1349 QTEST_MAIN(tst_QFiledialog)
1350 #include "tst_qfiledialog.moc"