diff --git a/autotests/kfilewidgettest.cpp b/autotests/kfilewidgettest.cpp --- a/autotests/kfilewidgettest.cpp +++ b/autotests/kfilewidgettest.cpp @@ -19,15 +19,16 @@ Boston, MA 02110-1301, USA. */ -#include - #include "kfilewidget.h" #include +#include +#include #include #include #include +#include /** * Unit test for KFileWidget @@ -123,14 +124,92 @@ QCOMPARE(outFileName, QStringLiteral("foo.txt")); } - void testBug369216() + void testSetSelection_data() + { + QTest::addColumn("baseDir"); + QTest::addColumn("selection"); + QTest::addColumn("expectedBaseDir"); + QTest::addColumn("expectedCurrentText"); + + const QString baseDir = QDir::homePath(); + // A nice filename to detect URL encoding issues + const QString fileName = QStringLiteral("some:fi#le"); + + // Bug 369216, kdialog calls setSelection(path) + QTest::newRow("path") << baseDir << baseDir + QLatin1Char('/') + fileName << baseDir << fileName; + QTest::newRow("differentPath") << QDir::rootPath() << baseDir + QLatin1Char('/') + fileName << baseDir << fileName; + // kdeplatformfiledialoghelper.cpp calls setSelection(URL as string) + QTest::newRow("url") << baseDir << QUrl::fromLocalFile(baseDir + QLatin1Char('/') + fileName).toString() << baseDir << fileName; + // What if someone calls setSelection(fileName)? That breaks, hence e70f8134a2b in plasma-integration.git + QTest::newRow("filename") << baseDir << fileName << baseDir << fileName; + } + + void testSetSelection() { - KFileWidget fw(QUrl::fromLocalFile(QStringLiteral("/"))); + // GIVEN + QFETCH(QString, baseDir); + QFETCH(QString, selection); + QFETCH(QString, expectedBaseDir); + QFETCH(QString, expectedCurrentText); + const QUrl baseUrl = QUrl::fromLocalFile(baseDir).adjusted(QUrl::StripTrailingSlash); + const QUrl expectedBaseUrl = QUrl::fromLocalFile(expectedBaseDir); + + KFileWidget fw(baseUrl); fw.show(); QTest::qWaitForWindowActive(&fw); - fw.setSelection(QDir::homePath() + QLatin1String("/somefile")); - QCOMPARE(fw.baseUrl().adjusted(QUrl::StripTrailingSlash), QUrl::fromLocalFile(QDir::homePath())); + // WHEN + fw.setSelection(selection); // now deprecated, this test shows why ;) + + // THEN + QCOMPARE(fw.baseUrl().adjusted(QUrl::StripTrailingSlash), expectedBaseUrl); + //if (QByteArray(QTest::currentDataTag()) == "filename") { + QEXPECT_FAIL("filename", "setSelection cannot work with filenames, bad API", Continue); + //} + QCOMPARE(fw.locationEdit()->currentText(), expectedCurrentText); + } + + void testSetSelectedUrl_data() + { + QTest::addColumn("baseDir"); + QTest::addColumn("selectionUrl"); + QTest::addColumn("expectedBaseDir"); + QTest::addColumn("expectedCurrentText"); + + const QString baseDir = QDir::homePath(); + // A nice filename to detect URL encoding issues + const QString fileName = QStringLiteral("some:fi#le"); + const QUrl fileUrl = QUrl::fromLocalFile(baseDir + QLatin1Char('/') + fileName); + + QTest::newRow("path") << baseDir << fileUrl << baseDir << fileName; + QTest::newRow("differentPath") << QDir::rootPath() << fileUrl << baseDir << fileName; + QTest::newRow("url") << baseDir << QUrl::fromLocalFile(baseDir + QLatin1Char('/') + fileName) << baseDir << fileName; + + QUrl relativeUrl; + relativeUrl.setPath(fileName); + QTest::newRow("filename") << baseDir << relativeUrl << baseDir << fileName; + } + + void testSetSelectedUrl() + { + // GIVEN + QFETCH(QString, baseDir); + QFETCH(QUrl, selectionUrl); + QFETCH(QString, expectedBaseDir); + QFETCH(QString, expectedCurrentText); + + const QUrl baseUrl = QUrl::fromLocalFile(baseDir).adjusted(QUrl::StripTrailingSlash); + const QUrl expectedBaseUrl = QUrl::fromLocalFile(expectedBaseDir); + KFileWidget fw(baseUrl); + fw.show(); + QTest::qWaitForWindowActive(&fw); + + // WHEN + fw.setSelectedUrl(selectionUrl); + + // THEN + QCOMPARE(fw.baseUrl().adjusted(QUrl::StripTrailingSlash), expectedBaseUrl); + QCOMPARE(fw.locationEdit()->currentText(), expectedCurrentText); } }; diff --git a/src/filewidgets/kfilewidget.h b/src/filewidgets/kfilewidget.h --- a/src/filewidgets/kfilewidget.h +++ b/src/filewidgets/kfilewidget.h @@ -141,12 +141,32 @@ */ void setUrl(const QUrl &url, bool clearforward = true); +#if !defined(KIOFILEWIDGETS_NO_DEPRECATED) && !defined(DOXYGEN_SHOULD_SKIP_THIS) /** - * Sets the file name to preselect to @p name + * Sets the file to preselect to @p pathOrUrl * - * This takes absolute URLs and relative file names. + * This method handles absolute paths (on Unix, but probably not correctly on Windows) + * and absolute URLs as strings (but for those you should use setSelectedUrl instead). + * + * This method does not work with relative paths (filenames) + * (it would misinterpret a ':' or a '#' in the filename). + * + * @deprecated since 5.33, use setSelectedUrl instead, after ensuring that + * construct the QUrl correctly (e.g. use fromLocalFile for local paths). + */ + KIOFILEWIDGETS_DEPRECATED void setSelection(const QString &pathOrUrl); +#endif + + /** + * Sets the URL to preselect to @p url + * + * This method handles absolute URLs (remember to use fromLocalFile for local paths). + * It also handles relative URLs, which you should construct like this: + * QUrl relativeUrl; relativeUrl.setPath(fileName); + * + * @since 5.33 */ - void setSelection(const QString &name); + void setSelectedUrl(const QUrl &url); /** * Sets the operational mode of the filedialog to @p Saving, @p Opening diff --git a/src/filewidgets/kfilewidget.cpp b/src/filewidgets/kfilewidget.cpp --- a/src/filewidgets/kfilewidget.cpp +++ b/src/filewidgets/kfilewidget.cpp @@ -1557,6 +1557,7 @@ return true; } +#ifndef KIOFILEWIDGETS_NO_DEPRECATED void KFileWidget::setSelection(const QString &url) { // qDebug() << "setSelection " << url; @@ -1571,12 +1572,17 @@ return; } + setSelectedUrl(urlFromString(url)); +} +#endif + +void KFileWidget::setSelectedUrl(const QUrl &url) +{ // Honor protocols that do not support directory listing - if (!u.isRelative() && !KProtocolManager::supportsListing(u)) { + if (!url.isRelative() && !KProtocolManager::supportsListing(url)) { return; } - - d->setLocationText(urlFromString(url)); + d->setLocationText(url); } void KFileWidgetPrivate::_k_slotLoadingFinished()