aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp')
-rw-r--r--tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp879
1 files changed, 879 insertions, 0 deletions
diff --git a/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
new file mode 100644
index 0000000000..9bc6a7d8f9
--- /dev/null
+++ b/tests/auto/quickdialogs/qquickfolderdialogimpl/tst_qquickfolderdialogimpl.cpp
@@ -0,0 +1,879 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/qtest.h>
+#include <QtTest/qsignalspy.h>
+#include <QtQml/qqmlfile.h>
+#include <QtQuick/private/qquicklistview_p.h>
+#include <QtQuickTest/quicktest.h>
+#include <QtQuickControlsTestUtils/private/controlstestutils_p.h>
+#include <QtQuickControlsTestUtils/private/dialogstestutils_p.h>
+#include <QtQuickDialogs2/private/qquickfolderdialog_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickplatformfolderdialog_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickfiledialogdelegate_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickfolderbreadcrumbbar_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickfolderbreadcrumbbar_p_p.h>
+#include <QtQuickDialogs2QuickImpl/private/qquickfolderdialogimpl_p.h>
+#include <QtQuickTemplates2/private/qquickapplicationwindow_p.h>
+#include <QtQuickTemplates2/private/qquickcombobox_p.h>
+#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h>
+#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
+#include <QtQuickTemplates2/private/qquicklabel_p.h>
+#include <QtQuickTemplates2/private/qquickoverlay_p.h>
+#include <QtQuickControls2/qquickstyle.h>
+
+using namespace QQuickVisualTestUtils;
+using namespace QQuickDialogTestUtils;
+using namespace QQuickControlsTestUtils;
+
+class tst_QQuickFolderDialogImpl : public QQmlDataTest
+{
+ Q_OBJECT
+
+public:
+ tst_QQuickFolderDialogImpl();
+ static void initMain()
+ {
+ // We need to set this attribute.
+ QCoreApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
+ // We also don't want to run this for every style, as each one will have
+ // different ways of implementing the dialogs.
+ // For now we only test one style.
+ QQuickStyle::setStyle("Basic");
+ }
+
+private slots:
+ void initTestCase() override;
+ void cleanupTestCase();
+
+ void defaults();
+ void chooseFolderViaStandardButtons();
+ void bindCurrentFolder_data();
+ void bindCurrentFolder();
+ void changeFolderViaDoubleClick();
+ void changeFolderViaTextEdit();
+ void changeFolderViaEnter();
+ void cancelDialogWhileTextEditHasFocus();
+ void goUp();
+ void goUpWhileTextEditHasFocus();
+ void goIntoLargeFolder();
+ void clickOnBreadcrumb();
+ void keyAndShortcutHandling();
+ void tabFocusNavigation();
+ void acceptRejectLabel();
+ void bindTitle();
+ void itemsDisabledWhenNecessary();
+ void done_data();
+ void done();
+
+private:
+ QTemporaryDir tempDir;
+ QScopedPointer<QFile> tempFile1;
+ QScopedPointer<QFile> tempFile2;
+ QDir tempSubDir1;
+ QDir tempSubSubDir;
+ QScopedPointer<QFile> tempSubFile1;
+ QScopedPointer<QFile> tempSubFile2;
+ QDir tempSubDir2;
+ QDir oldCurrentDir;
+};
+
+tst_QQuickFolderDialogImpl::tst_QQuickFolderDialogImpl()
+ : QQmlDataTest(QT_QMLTEST_DATADIR)
+{
+}
+
+void tst_QQuickFolderDialogImpl::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+
+ QVERIFY(tempDir.isValid());
+ // QTEST_QUICKCONTROLS_MAIN constructs the test case object once,
+ // and then calls qRun() for each style, and qRun() calls initTestCase().
+ // So, we need to check if we've already made the temporary directory.
+ // Note that this is only necessary if the test is run with more than one style.
+ if (!QDir(tempDir.path()).isEmpty())
+ return;
+
+ /*
+ Create a couple of files within the temporary directory. The structure is:
+
+ [temp directory]
+ ├── sub-dir-1
+ │ ├── sub-sub-dir
+ │ ├── sub-file1.txt
+ │ └── sub-file2.txt
+ ├── sub-dir-2
+ ├── file1.txt
+ └── file2.txt
+ */
+ tempSubDir1 = QDir(tempDir.path());
+ QVERIFY2(tempSubDir1.mkdir("sub-dir-1"), qPrintable(QString::fromLatin1(
+ "Failed to make sub-directory \"sub-dir-1\" in %1. Permissions are: %2")
+ .arg(tempDir.path(), QDebug::toString(QFileInfo(tempDir.path()).permissions()))));
+ QVERIFY(tempSubDir1.cd("sub-dir-1"));
+
+ tempSubSubDir = QDir(tempSubDir1.path());
+ QVERIFY2(tempSubSubDir.mkdir("sub-sub-dir"), qPrintable(QString::fromLatin1(
+ "Failed to make sub-directory \"sub-sub-dir\" in %1. Permissions are: %2")
+ .arg(tempSubDir1.path(), QDebug::toString(QFileInfo(tempSubDir1.path()).permissions()))));
+ QVERIFY(tempSubSubDir.cd("sub-sub-dir"));
+
+ tempSubFile1.reset(new QFile(tempSubDir1.path() + "/sub-file1.txt"));
+ QVERIFY(tempSubFile1->open(QIODevice::ReadWrite));
+
+ tempSubFile2.reset(new QFile(tempSubDir1.path() + "/sub-file2.txt"));
+ QVERIFY(tempSubFile2->open(QIODevice::ReadWrite));
+
+ tempSubDir2 = QDir(tempDir.path());
+ QVERIFY2(tempSubDir2.mkdir("sub-dir-2"), qPrintable(QString::fromLatin1(
+ "Failed to make sub-directory \"sub-dir-2\" in %1. Permissions are: %2")
+ .arg(tempDir.path(), QDebug::toString(QFileInfo(tempDir.path()).permissions()))));
+ QVERIFY(tempSubDir2.cd("sub-dir-2"));
+
+ tempFile1.reset(new QFile(tempDir.path() + "/file1.txt"));
+ QVERIFY(tempFile1->open(QIODevice::ReadWrite));
+
+ tempFile2.reset(new QFile(tempDir.path() + "/file2.txt"));
+ QVERIFY(tempFile2->open(QIODevice::ReadWrite));
+
+ // Ensure that each test starts off in the temporary directory.
+ oldCurrentDir = QDir::current();
+ QDir::setCurrent(tempDir.path());
+}
+
+void tst_QQuickFolderDialogImpl::cleanupTestCase()
+{
+ // Just in case...
+ QDir::setCurrent(oldCurrentDir.path());
+}
+
+void tst_QQuickFolderDialogImpl::defaults()
+{
+ QQuickApplicationHelper helper(this, "folderDialog.qml");
+ QVERIFY2(helper.ready, helper.failureMessage());
+
+ QQuickWindow *window = helper.window;
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickFolderDialog *dialog = window->property("dialog").value<QQuickFolderDialog*>();
+ QVERIFY(dialog);
+ COMPARE_URL(dialog->currentFolder(), QUrl::fromLocalFile(QDir().absolutePath()));
+ // The first file in the directory should be selected, but not until the dialog is actually open,
+ // as QQuickFileDialogImpl hasn't been created yet.
+ COMPARE_URL(dialog->selectedFolder(), QUrl());
+ QCOMPARE(dialog->title(), QString());
+
+ dialog->open();
+ QQuickFolderDialogImpl *quickDialog = window->findChild<QQuickFolderDialogImpl*>();
+ QVERIFY(quickDialog);
+ QTRY_VERIFY(quickDialog->isOpened());
+ QVERIFY(quickDialog);
+ COMPARE_URL(quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+ COMPARE_URL(quickDialog->currentFolder(), QUrl::fromLocalFile(QDir().absolutePath()));
+ COMPARE_URL(dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+ COMPARE_URL(dialog->currentFolder(), QUrl::fromLocalFile(QDir().absolutePath()));
+ QCOMPARE(quickDialog->title(), QString());
+}
+
+typedef DialogTestHelper<QQuickFolderDialog, QQuickFolderDialogImpl> FolderDialogTestHelper;
+
+class FolderDialogSignalHelper
+{
+public:
+ FolderDialogSignalHelper(const FolderDialogTestHelper &dialogTestHelper) :
+ dialogSelectedFolderChangedSpy(dialogTestHelper.dialog, SIGNAL(selectedFolderChanged())),
+ quickDialogSelectedFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(selectedFolderChanged(const QUrl &))),
+ dialogCurrentFolderChangedSpy(dialogTestHelper.dialog, SIGNAL(currentFolderChanged())),
+ quickDialogCurrentFolderChangedSpy(dialogTestHelper.quickDialog, SIGNAL(currentFolderChanged(const QUrl &)))
+ {
+ if (!dialogSelectedFolderChangedSpy.isValid())
+ errorMessage = "selectedFolderChanged signal of dialog is not valid";
+ if (!quickDialogSelectedFolderChangedSpy.isValid())
+ errorMessage = "selectedFolderChanged signal of quickDialog is not valid";
+ if (!dialogCurrentFolderChangedSpy.isValid())
+ errorMessage = "currentFolderChanged signal of dialog is not valid";
+ if (!quickDialogCurrentFolderChangedSpy.isValid())
+ errorMessage = "currentFolderChanged signal of quickDialog is not valid";
+ }
+
+ QSignalSpy dialogSelectedFolderChangedSpy;
+ QSignalSpy quickDialogSelectedFolderChangedSpy;
+ QSignalSpy dialogCurrentFolderChangedSpy;
+ QSignalSpy quickDialogCurrentFolderChangedSpy;
+
+ QByteArray errorMessage;
+};
+
+void tst_QQuickFolderDialogImpl::chooseFolderViaStandardButtons()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Select the delegate by clicking once.
+ const FolderDialogSignalHelper signalHelper(dialogHelper);
+ QVERIFY2(signalHelper.errorMessage.isEmpty(), signalHelper.errorMessage);
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *delegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 1, delegate));
+ COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2.path()));
+ QVERIFY(clickButton(delegate));
+ // currentFolder shouldn't change just from a single click.
+ COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ // Only selectedFile-related signals should be emitted.
+ QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.dialogCurrentFolderChangedSpy.count(), 0);
+ QCOMPARE(signalHelper.quickDialogCurrentFolderChangedSpy.count(), 0);
+
+ // Click the "Open" button.
+ QVERIFY(dialogHelper.quickDialog->footer());
+ auto dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialogHelper.quickDialog->footer());
+ QVERIFY(dialogButtonBox);
+ QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Open");
+ QVERIFY(openButton);
+ QVERIFY(clickButton(openButton));
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.dialogCurrentFolderChangedSpy.count(), 0);
+ QCOMPARE(signalHelper.quickDialogCurrentFolderChangedSpy.count(), 0);
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+ QVERIFY(!dialogHelper.dialog->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::bindCurrentFolder_data()
+{
+ QTest::addColumn<QUrl>("initialFolder");
+ QTest::addColumn<QUrl>("expectedFolder");
+ QTest::addColumn<QStringList>("expectedVisibleFiles");
+
+ const auto currentDirUrl = QUrl::fromLocalFile(QDir::current().path());
+ const auto tempSubDirUrl = QUrl::fromLocalFile(tempSubDir1.path());
+ const auto tempSubFile1Url = QUrl::fromLocalFile(tempSubFile1->fileName());
+
+ const QStringList currentDirFiles = { tempSubDir1.path(), tempSubDir2.path() };
+ const QStringList tempSubDirFiles = { tempSubSubDir.path() };
+
+ // Setting the folder to "sub-dir-1" should result in "sub-sub-dir" being visible.
+ QTest::addRow("sub-dir-1") << tempSubDirUrl << tempSubDirUrl << tempSubDirFiles;
+ // Setting a file as the folder shouldn't work, and the dialog shouldn't change its folder.
+ QTest::addRow("sub-dir/sub-file1.txt") << tempSubFile1Url << currentDirUrl << currentDirFiles;
+}
+
+void tst_QQuickFolderDialogImpl::bindCurrentFolder()
+{
+ QFETCH(QUrl, initialFolder);
+ QFETCH(QUrl, expectedFolder);
+ QFETCH(QStringList, expectedVisibleFiles);
+
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", initialFolder }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), expectedFolder);
+
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QString failureMessage;
+ // Even waiting for ListView polish and that the FolderListModel's status is ready aren't enough
+ // on Windows, apparently, as sometimes there just aren't any delegates by the time we do the check.
+ // So, we use QTRY_VERIFY2 each time we call this function just to be safe.
+ QTRY_VERIFY2(verifyFileDialogDelegates(folderDialogListView, expectedVisibleFiles, failureMessage), qPrintable(failureMessage));
+
+ // Check that the breadcrumb bar is correct by constructing the expected files from the expectedFolder.
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ QVERIFY2(verifyBreadcrumbDelegates(breadcrumbBar, expectedFolder, failureMessage), qPrintable(failureMessage));
+}
+
+void tst_QQuickFolderDialogImpl::changeFolderViaDoubleClick()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Double-click on the "sub-dir-2" delegate.
+ const FolderDialogSignalHelper signalHelper(dialogHelper);
+ QVERIFY2(signalHelper.errorMessage.isEmpty(), signalHelper.errorMessage);
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *delegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 1, delegate));
+ COMPARE_URL(delegate->file(), QUrl::fromLocalFile(tempSubDir2.path()))
+ QVERIFY(doubleClickButton(delegate));
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path()))
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl());
+ // selectedFolder is set to the folder when clicked and then set to an empty URL after
+ // the double click.
+ QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.count(), 2);
+ QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.count(), 2);
+ QCOMPARE(signalHelper.dialogCurrentFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.quickDialogCurrentFolderChangedSpy.count(), 1);
+ // Since we only changed the current folder, the dialog should still be open.
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ dialogHelper.dialog->close();
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::changeFolderViaTextEdit()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Get the text edit visible with Ctrl+L.
+ const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+ QCOMPARE(breadcrumbBar->textField()->text(), dialogHelper.dialog->currentFolder().toLocalFile());
+ QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text());
+
+ // Enter the path to the folder in the text edit.
+ enterText(dialogHelper.window(), tempSubDir2.path());
+ QCOMPARE(breadcrumbBar->textField()->text(), tempSubDir2.path());
+
+ // Hit enter to accept.
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ // We changed into a directory with no folders, so the selected folder should be invalid.
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl());
+ COMPARE_URL(dialogHelper.quickDialog->selectedFolder(), QUrl());
+ QTRY_VERIFY(dialogHelper.dialog->isVisible());
+
+ // Close the dialog.
+ dialogHelper.dialog->close();
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::changeFolderViaEnter()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // The first delegate in the view should be selected and have focus.
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *subDir1Delegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, subDir1Delegate));
+ COMPARE_URL(subDir1Delegate->file(), QUrl::fromLocalFile(tempSubDir1.path()));
+ QVERIFY(subDir1Delegate->hasActiveFocus());
+
+ // Select the delegate by pressing enter.
+ const FolderDialogSignalHelper signalHelper(dialogHelper);
+ QVERIFY2(signalHelper.errorMessage.isEmpty(), signalHelper.errorMessage);
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Return);
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubSubDir.path()));
+ QCOMPARE(signalHelper.dialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.quickDialogSelectedFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.dialogCurrentFolderChangedSpy.count(), 1);
+ QCOMPARE(signalHelper.quickDialogCurrentFolderChangedSpy.count(), 1);
+ // Since we only changed the current folder, the dialog should still be open.
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ dialogHelper.dialog->close();
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::cancelDialogWhileTextEditHasFocus()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Get the text edit visible with Ctrl+L.
+ const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+ QCOMPARE(breadcrumbBar->textField()->text(), dialogHelper.dialog->currentFolder().toLocalFile());
+ QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text());
+
+ // Close it via the cancel button.
+ auto dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialogHelper.quickDialog->footer());
+ QVERIFY(dialogButtonBox);
+ const QString cancelText = QQuickDialogButtonBoxPrivate::buttonText(QPlatformDialogHelper::Cancel);
+ auto cancelButton = findDialogButton(dialogButtonBox, cancelText);
+ QVERIFY(cancelButton);
+ QVERIFY(clickButton(cancelButton));
+
+ // Open it again. The text field should not be visible, but the breadcrumb bar itself should be.
+ dialogHelper.dialog->open();
+ QVERIFY(dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(dialogHelper.quickDialog->isOpened());
+ QVERIFY(breadcrumbBar->isVisible());
+ // The ListView that contains the breadcrumb delegates should be visible.
+ QVERIFY(breadcrumbBar->contentItem()->isVisible());
+ QVERIFY(!breadcrumbBar->textField()->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::goUp()
+{
+ // Open the dialog, starting off in "sub-dir-1".
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Go up a directory via the button next to the breadcrumb bar.
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ auto barListView = qobject_cast<QQuickListView*>(breadcrumbBar->contentItem());
+ QVERIFY(barListView);
+ if (QQuickTest::qIsPolishScheduled(barListView))
+ QVERIFY(QQuickTest::qWaitForItemPolished(barListView));
+ QVERIFY(clickButton(breadcrumbBar->upButton()));
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ // The previous directory that we were in should now be selected (matches e.g. Windows and Ubuntu).
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *subDirDelegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, subDirDelegate));
+ QCOMPARE(subDirDelegate->isHighlighted(), true);
+
+ // Go up a directory via the keyboard shortcut next to the breadcrumb bar.
+ const auto goUpKeySequence = QKeySequence(Qt::ALT | Qt::Key_Up);
+ QTest::keySequence(dialogHelper.window(), goUpKeySequence);
+ QDir tempParentDir(tempDir.path());
+ QVERIFY(tempParentDir.cdUp());
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempParentDir.path()));
+ COMPARE_URL(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempDir.path()));
+}
+
+void tst_QQuickFolderDialogImpl::goUpWhileTextEditHasFocus()
+{
+ // Open the dialog, starting off in "sub-dir-1".
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Go up a directory via the button next to the breadcrumb bar.
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ auto barListView = qobject_cast<QQuickListView*>(breadcrumbBar->contentItem());
+ QVERIFY(barListView);
+ if (QQuickTest::qIsPolishScheduled(barListView))
+ QVERIFY(QQuickTest::qWaitForItemPolished(barListView));
+ QVERIFY(clickButton(breadcrumbBar->upButton()));
+ // The path should have changed to the parent directory.
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ // The text edit should be hidden when it loses focus.
+ QVERIFY(!breadcrumbBar->textField()->hasActiveFocus());
+ QVERIFY(!breadcrumbBar->textField()->isVisible());
+ // The focus should be given to the first delegate.
+ QVERIFY(dialogHelper.window()->activeFocusItem());
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *firstDelegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, firstDelegate));
+ QCOMPARE(dialogHelper.window()->activeFocusItem(), firstDelegate);
+}
+
+void tst_QQuickFolderDialogImpl::goIntoLargeFolder()
+{
+ // Create a throwaway directory with a lot of folders within it...
+ QTemporaryDir anotherTempDir;
+ QVERIFY(anotherTempDir.isValid());
+ for (int i = 0; i < 30; ++i) {
+ QDir newDir(anotherTempDir.path());
+ QVERIFY(newDir.exists());
+ // Pad with zeroes so that the directories are ordered as we expect.
+ QVERIFY(newDir.mkdir(QString::fromLatin1("dir%1").arg(i, 2, 10, QLatin1Char('0'))));
+ }
+
+ // ... and within one of those folders, more folders.
+ QDir dir20(anotherTempDir.path() + "/dir20");
+ QVERIFY(dir20.exists());
+ for (int i = 0; i < 30; ++i) {
+ QDir newDir(dir20.path());
+ QVERIFY(newDir.exists());
+ QVERIFY(newDir.mkdir(QString::fromLatin1("subdir%1").arg(i, 2, 10, QLatin1Char('0'))));
+ }
+
+ // Open the dialog. Start off in the throwaway directory.
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", QUrl::fromLocalFile(anotherTempDir.path()) }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // If the screen is so tall that the contentItem is not vertically larger than the view,
+ // then the test makes no sense.
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ if (QQuickTest::qIsPolishScheduled(folderDialogListView))
+ QVERIFY(QQuickTest::qWaitForItemPolished(folderDialogListView));
+ // Just to be safe, make sure it's at least twice as big.
+ if (folderDialogListView->contentItem()->height() < folderDialogListView->height() * 2) {
+ QSKIP(qPrintable(QString::fromLatin1("Expected height of folderDialogListView's contentItem (%1)" \
+ " to be at least twice as big as the ListView's height (%2)")
+ .arg(folderDialogListView->contentItem()->height()).arg(folderDialogListView->height())));
+ }
+
+ // Scroll down to dir20. The view should be somewhere past the middle.
+ QVERIFY(QMetaObject::invokeMethod(folderDialogListView, "positionViewAtIndex", Qt::DirectConnection,
+ Q_ARG(int, 20), Q_ARG(int, QQuickItemView::PositionMode::Center)));
+ QVERIFY(folderDialogListView->contentY() > 0);
+
+ // Go into it. The view should start at the top of the directory, not at the same contentY
+ // that it had in the previous directory.
+ QQuickFileDialogDelegate *dir20Delegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 20, dir20Delegate));
+ COMPARE_URL(dir20Delegate->file(), QUrl::fromLocalFile(dir20.path()));
+ QVERIFY(doubleClickButton(dir20Delegate));
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(dir20.path()));
+ COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(dir20.path()));
+ QCOMPARE(folderDialogListView->contentY(), 0);
+}
+
+void tst_QQuickFolderDialogImpl::clickOnBreadcrumb()
+{
+ // Open the dialog, starting off in "sub-dir-1".
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", QUrl::fromLocalFile(tempSubDir1.path()) }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Find the breadcrumb bar delegate for the temp directory (parent of "sub-dir-1").
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ auto breadcrumbBarListView = qobject_cast<QQuickListView*>(breadcrumbBar->contentItem());
+ QVERIFY(breadcrumbBarListView);
+ QQuickAbstractButton *breadcrumbDelegate = nullptr;
+ // The following breadcrumb bar has 5 delegates:
+ // [ / > tmp > deadbeef ]
+ // We can assume that, regardless of which system we're running on, we'll have
+ // at least 3: one for the temp directory, and one for the > separator, and one for "sub-dir-1".
+ QVERIFY(breadcrumbBarListView->count() >= 3);
+ // - 1 to make it zero-based, and another 2 to get to the second-last directory, which is the parent of "sub-dir-1".
+ QTRY_VERIFY(findViewDelegateItem(breadcrumbBarListView, breadcrumbBarListView->count() - 3, breadcrumbDelegate));
+
+ QVERIFY(clickButton(breadcrumbDelegate));
+ QCOMPARE(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ QCOMPARE(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ QCOMPARE(dialogHelper.quickDialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+ QCOMPARE(dialogHelper.dialog->selectedFolder(), QUrl::fromLocalFile(tempSubDir1.path()));
+}
+
+void tst_QQuickFolderDialogImpl::keyAndShortcutHandling()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Get the text edit visible with Ctrl+L.
+ const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+ QCOMPARE(breadcrumbBar->textField()->text(), dialogHelper.dialog->currentFolder().toLocalFile());
+ QCOMPARE(breadcrumbBar->textField()->selectedText(), breadcrumbBar->textField()->text());
+
+ // Ctrl+L shouldn't hide it.
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+
+ // Cancel it with the escape key.
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
+ QVERIFY(!breadcrumbBar->textField()->isVisible());
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ // Make it visible.
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+
+ // Cancel it with the escape key again.
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
+ QVERIFY(!breadcrumbBar->textField()->isVisible());
+ QVERIFY(dialogHelper.dialog->isVisible());
+
+ // Pressing escape now should close the dialog.
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+}
+
+void tst_QQuickFolderDialogImpl::tabFocusNavigation()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ QList<QQuickItem*> expectedFocusItems;
+
+ // The initial focus should be on the first delegate.
+ auto folderDialogListView = dialogHelper.quickDialog->findChild<QQuickListView*>("folderDialogListView");
+ QVERIFY(folderDialogListView);
+ QQuickFileDialogDelegate *firstDelegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, 0, firstDelegate));
+ expectedFocusItems << firstDelegate;
+
+ // Next, the left-most dialog button.
+ auto dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialogHelper.quickDialog->footer());
+ QVERIFY(dialogButtonBox);
+ QCOMPARE(dialogButtonBox->count(), 2);
+ auto leftMostButton = qobject_cast<QQuickAbstractButton*>(dialogButtonBox->itemAt(0));
+ QVERIFY(leftMostButton);
+ expectedFocusItems << leftMostButton;
+
+ // Then, the right-most dialog button.
+ auto rightMostButton = qobject_cast<QQuickAbstractButton*>(dialogButtonBox->itemAt(1));
+ QVERIFY(rightMostButton);
+ expectedFocusItems << rightMostButton;
+
+ // Then, the up button.
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ expectedFocusItems << breadcrumbBar->upButton();
+
+ // Finally, add each bread crumb delegate.
+ for (int i = 0; i < folderDialogListView->count(); ++i) {
+ QQuickFileDialogDelegate *delegate = nullptr;
+ QTRY_VERIFY(findViewDelegateItem(folderDialogListView, i, delegate));
+ expectedFocusItems << delegate;
+ }
+
+ // Tab through each item, checking the focus after each.
+ for (auto expectedFocusItem : qAsConst(expectedFocusItems)) {
+ // Check the focus item first so that we account for the first item.
+ // Print detailed failure message as workaround for QTBUG-92102.
+ QVERIFY2(dialogHelper.window()->activeFocusItem() == expectedFocusItem, qPrintable(QString::fromLatin1(
+ "\n Actual: %1\n Expected: %2").arg(QDebug::toString(dialogHelper.window()->activeFocusItem()))
+ .arg(QDebug::toString(expectedFocusItem))));
+
+ if (expectedFocusItem != expectedFocusItems.last())
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Tab);
+ }
+
+ // Ensure the order is reversed when shift-tabbing.
+ std::reverse(expectedFocusItems.begin(), expectedFocusItems.end());
+ // We know the first (last) item has focus already, so skip it.
+ expectedFocusItems.removeFirst();
+ for (auto expectedFocusItem : qAsConst(expectedFocusItems)) {
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Tab, Qt::ShiftModifier);
+
+ QCOMPARE(dialogHelper.window()->activeFocusItem(), expectedFocusItem);
+ }
+}
+
+void tst_QQuickFolderDialogImpl::acceptRejectLabel()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "acceptRejectLabel.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Check that the accept and reject buttons' labels have changed.
+ auto dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialogHelper.quickDialog->footer());
+ QVERIFY(dialogButtonBox);
+ QVERIFY(findDialogButton(dialogButtonBox, "AcceptTest"));
+ QVERIFY(findDialogButton(dialogButtonBox, "RejectTest"));
+
+ // Close the dialog.
+ dialogHelper.dialog->close();
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+
+ // Reset back to the default text.
+ dialogHelper.dialog->resetAcceptLabel();
+ dialogHelper.dialog->resetRejectLabel();
+
+ // Re-open the dialog.
+ dialogHelper.dialog->open();
+ QVERIFY(dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(dialogHelper.quickDialog->isOpened());
+
+ // Check that the defaults are back.
+ const QString openText = QQuickDialogButtonBoxPrivate::buttonText(QPlatformDialogHelper::Open);
+ QVERIFY2(findDialogButton(dialogButtonBox, openText), qPrintable(QString::fromLatin1(
+ "Failed to find dialog button with text \"%1\"").arg(openText)));
+ const QString cancelText = QQuickDialogButtonBoxPrivate::buttonText(QPlatformDialogHelper::Cancel);
+ QVERIFY2(findDialogButton(dialogButtonBox, cancelText), qPrintable(QString::fromLatin1(
+ "Failed to find dialog button with text \"%1\"").arg(cancelText)));
+}
+
+void tst_QQuickFolderDialogImpl::bindTitle()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "bindTitle.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Open the dialog and check that the correct title is displayed.
+ const QString expectedTitle = QLatin1String("Test Title");
+ QCOMPARE(dialogHelper.dialog->title(), expectedTitle);
+ QCOMPARE(dialogHelper.quickDialog->title(), expectedTitle);
+ auto header = dialogHelper.quickDialog->header();
+ QVERIFY(header);
+ auto dialogTitleBarLabel = dialogHelper.quickDialog->header()->findChild<QQuickLabel*>("dialogTitleBarLabel");
+ QVERIFY(dialogTitleBarLabel);
+ QCOMPARE(dialogTitleBarLabel->text(), expectedTitle);
+}
+
+void tst_QQuickFolderDialogImpl::itemsDisabledWhenNecessary()
+{
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "bindCurrentFolder.qml", {},
+ {{ "initialFolder", QUrl::fromLocalFile(tempSubDir2.path()) }});
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+ COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempSubDir2.path()));
+
+ // We opened it in a folder that has no files, so the Open button should be disabled.
+ QVERIFY(dialogHelper.quickDialog->footer());
+ auto dialogButtonBox = qobject_cast<QQuickDialogButtonBox*>(dialogHelper.quickDialog->footer());
+ QVERIFY(dialogButtonBox);
+ QQuickAbstractButton* openButton = findDialogButton(dialogButtonBox, "Open");
+ QVERIFY(openButton);
+ QCOMPARE(openButton->isEnabled(), false);
+
+ // Now go up. The Open button should now be enabled.
+ auto breadcrumbBar = dialogHelper.quickDialog->findChild<QQuickFolderBreadcrumbBar*>();
+ QVERIFY(breadcrumbBar);
+ QVERIFY(clickButton(breadcrumbBar->upButton()));
+ QCOMPARE(openButton->isEnabled(), true);
+ COMPARE_URL(dialogHelper.dialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+ COMPARE_URL(dialogHelper.quickDialog->currentFolder(), QUrl::fromLocalFile(tempDir.path()));
+
+ // Get the text edit visible with Ctrl+L. The Open button should now be disabled.
+ const auto editPathKeySequence = QKeySequence(Qt::CTRL | Qt::Key_L);
+ QTest::keySequence(dialogHelper.window(), editPathKeySequence);
+ QVERIFY(breadcrumbBar->textField()->isVisible());
+ QCOMPARE(openButton->isEnabled(), false);
+
+ // Hide it with the escape key. The Open button should now be enabled.
+ QTest::keyClick(dialogHelper.window(), Qt::Key_Escape);
+ QVERIFY(!breadcrumbBar->textField()->isVisible());
+ QCOMPARE(openButton->isEnabled(), true);
+}
+
+void tst_QQuickFolderDialogImpl::done_data()
+{
+ QTest::addColumn<QQuickAbstractDialog::StandardCode>("result");
+
+ QTest::newRow("Accepted") << QQuickAbstractDialog::Accepted;
+ QTest::newRow("Rejected") << QQuickAbstractDialog::Rejected;
+}
+
+void tst_QQuickFolderDialogImpl::done()
+{
+ QFETCH(QQuickAbstractDialog::StandardCode, result);
+
+ // Open the dialog.
+ FolderDialogTestHelper dialogHelper(this, "folderDialog.qml");
+ QVERIFY2(dialogHelper.isWindowInitialized(), dialogHelper.failureMessage());
+ QVERIFY(dialogHelper.waitForWindowActive());
+ QVERIFY(dialogHelper.openDialog());
+ QTRY_VERIFY(dialogHelper.isQuickDialogOpen());
+
+ // Call the "done" slot manually.
+ switch (result) {
+ case QQuickAbstractDialog::Accepted:
+ QVERIFY(QMetaObject::invokeMethod(dialogHelper.window(), "doneAccepted"));
+ break;
+ case QQuickAbstractDialog::Rejected:
+ QVERIFY(QMetaObject::invokeMethod(dialogHelper.window(), "doneRejected"));
+ break;
+ }
+
+ QVERIFY(!dialogHelper.dialog->isVisible());
+ QTRY_VERIFY(!dialogHelper.quickDialog->isVisible());
+ QCOMPARE(dialogHelper.dialog->result(), result);
+}
+
+QTEST_MAIN(tst_QQuickFolderDialogImpl)
+
+#include "tst_qquickfolderdialogimpl.moc"