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