diff --git a/autotests/kdiroperatortest.cpp b/autotests/kdiroperatortest.cpp --- a/autotests/kdiroperatortest.cpp +++ b/autotests/kdiroperatortest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include /** * Unit test for KDirOperator @@ -116,6 +117,21 @@ dirOp.setUrl(url, true); QCOMPARE(spy.takeFirst().at(0).toUrl(), expectedUrl); } + + void testSupportedSchemes() + { + KDirOperator dirOp; + QSignalSpy spy(&dirOp, &KDirOperator::urlEntered); + QCOMPARE(dirOp.supportedSchemes(), QStringList()); + dirOp.setSupportedSchemes({"file"}); + QCOMPARE(dirOp.supportedSchemes(), QStringList("file")); + dirOp.setUrl(QUrl("smb://foo/bar"), true); + QCOMPARE(spy.count(), 0); + const auto fileUrl = QUrl::fromLocalFile(QDir::homePath() + QLatin1Char('/')); + dirOp.setUrl(fileUrl, true); + QCOMPARE(spy.count(), 1); + QCOMPARE(spy.first().at(0).toUrl(), fileUrl); + } }; QTEST_MAIN(KDirOperatorTest) diff --git a/autotests/kfileplacesmodeltest.cpp b/autotests/kfileplacesmodeltest.cpp --- a/autotests/kfileplacesmodeltest.cpp +++ b/autotests/kfileplacesmodeltest.cpp @@ -88,6 +88,7 @@ void testPlaceGroupHiddenSignal(); void testPlaceGroupHiddenRole(); void testFilterWithAlternativeApplicationName(); + void testSupportedSchemes(); private: QStringList placesUrls(KFilePlacesModel *model = nullptr) const; @@ -1288,6 +1289,20 @@ delete newModel; } +void KFilePlacesModelTest::testSupportedSchemes() +{ + QCoreApplication::processEvents(); // support running this test on its own + + QCOMPARE(m_places->supportedSchemes(), QStringList()); + QCOMPARE(placesUrls(), initialListOfUrls()); + m_places->setSupportedSchemes({"trash"}); + QCOMPARE(m_places->supportedSchemes(), QStringList("trash")); + QCOMPARE(placesUrls(), QStringList("trash:/")); + m_places->setSupportedSchemes({}); + QCOMPARE(m_places->supportedSchemes(), QStringList()); + QCOMPARE(placesUrls(), initialListOfUrls()); +} + QTEST_MAIN(KFilePlacesModelTest) #include "kfileplacesmodeltest.moc" diff --git a/src/filewidgets/kdiroperator.h b/src/filewidgets/kdiroperator.h --- a/src/filewidgets/kdiroperator.h +++ b/src/filewidgets/kdiroperator.h @@ -627,6 +627,16 @@ */ bool isSaving() const; + /** + * Returns the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::supportedSchemes + * @since 5.43 + */ + QStringList supportedSchemes() const; + protected: /** * A view factory for creating predefined fileviews. Called internally by setView, @@ -774,6 +784,16 @@ */ void setIconsZoom(int value); + /** + * Set the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::setSupportedSchemes + * @since 5.43 + */ + void setSupportedSchemes(const QStringList &schemes); + protected Q_SLOTS: /** * Restores the normal cursor after showing the busy-cursor. Also hides diff --git a/src/filewidgets/kdiroperator.cpp b/src/filewidgets/kdiroperator.cpp --- a/src/filewidgets/kdiroperator.cpp +++ b/src/filewidgets/kdiroperator.cpp @@ -187,6 +187,7 @@ void updateSorting(QDir::SortFlags sort); static bool isReadable(const QUrl &url); + bool isSchemeSupported(const QString &scheme) const; KFile::FileView allViews(); @@ -289,6 +290,7 @@ QList itemsToBeSetAsCurrent; bool shouldFetchForItems; InlinePreviewState inlinePreviewState; + QStringList supportedSchemes; }; KDirOperator::Private::Private(KDirOperator *_parent) : @@ -998,6 +1000,9 @@ return; } + if (!d->isSchemeSupported(newurl.scheme())) + return; + if (!Private::isReadable(newurl)) { // maybe newurl is a file? check its parent directory newurl = newurl.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash); @@ -1060,9 +1065,16 @@ d->openUrl(d->currUrl, KDirLister::Reload); } +bool KDirOperator::Private::isSchemeSupported(const QString &scheme) const +{ + return supportedSchemes.isEmpty() || supportedSchemes.contains(scheme); +} + bool KDirOperator::Private::openUrl(const QUrl &url, KDirLister::OpenUrlFlags flags) { - const bool result = KProtocolManager::supportsListing(url) && dirLister->openUrl(url, flags); + const bool result = KProtocolManager::supportsListing(url) + && isSchemeSupported(url.scheme()) + && dirLister->openUrl(url, flags); if (!result) { // in that case, neither completed() nor canceled() will be emitted by KDL _k_slotCanceled(); } @@ -2634,5 +2646,16 @@ parent->setUrl(url, true); } +void KDirOperator::setSupportedSchemes(const QStringList &schemes) +{ + d->supportedSchemes = schemes; + rereadDir(); +} + +QStringList KDirOperator::supportedSchemes() const +{ + return d->supportedSchemes; +} + #include "moc_kdiroperator.cpp" #include "kdiroperator.moc" diff --git a/src/filewidgets/kfileplacesmodel.h b/src/filewidgets/kfileplacesmodel.h --- a/src/filewidgets/kfileplacesmodel.h +++ b/src/filewidgets/kfileplacesmodel.h @@ -186,6 +186,26 @@ */ static QUrl convertedUrl(const QUrl &url); + /** + * Set the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::setSupportedSchemes + * @since 5.43 + */ + void setSupportedSchemes(const QStringList &schemes); + + /** + * Returns the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::supportedSchemes + * @since 5.43 + */ + QStringList supportedSchemes() const; + Q_SIGNALS: void errorMessage(const QString &message); void setupDone(const QModelIndex &index, bool success); diff --git a/src/filewidgets/kfileplacesmodel.cpp b/src/filewidgets/kfileplacesmodel.cpp --- a/src/filewidgets/kfileplacesmodel.cpp +++ b/src/filewidgets/kfileplacesmodel.cpp @@ -187,6 +187,7 @@ QList items; QVector availableDevices; QMap setupInProgress; + QStringList supportedSchemes; Solid::Predicate predicate; KBookmarkManager *bookmarkManager; @@ -672,8 +673,9 @@ ((appName == QCoreApplication::instance()->applicationName()) || (appName == alternativeApplicationName)); bool isSupportedUrl = isBalooUrl(url) ? fileIndexingEnabled : true; + bool isSupportedScheme = supportedSchemes.isEmpty() || supportedSchemes.contains(url.scheme()); - if ((isSupportedUrl && udi.isEmpty() && allowedHere) || deviceAvailable) { + if (isSupportedScheme && ((isSupportedUrl && udi.isEmpty() && allowedHere) || deviceAvailable)) { KFilePlacesItem *item; if (deviceAvailable) { @@ -1264,4 +1266,15 @@ } } +void KFilePlacesModel::setSupportedSchemes(const QStringList &schemes) +{ + d->supportedSchemes = schemes; + d->_k_reloadBookmarks(); +} + +QStringList KFilePlacesModel::supportedSchemes() const +{ + return d->supportedSchemes; +} + #include "moc_kfileplacesmodel.cpp" diff --git a/src/filewidgets/kfilewidget.h b/src/filewidgets/kfilewidget.h --- a/src/filewidgets/kfilewidget.h +++ b/src/filewidgets/kfilewidget.h @@ -494,6 +494,26 @@ */ QSize sizeHint() const Q_DECL_OVERRIDE; + /** + * Set the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::setSupportedSchemes + * @since 5.43 + */ + void setSupportedSchemes(const QStringList &schemes); + + /** + * Returns the URL schemes that the file widget should allow navigating to. + * + * If the returned list is empty, all schemes are supported. + * + * @sa QFileDialog::supportedSchemes + * @since 5.43 + */ + QStringList supportedSchemes() const; + public Q_SLOTS: /** * Called when clicking ok (when this widget is used in KFileDialog) diff --git a/src/filewidgets/kfilewidget.cpp b/src/filewidgets/kfilewidget.cpp --- a/src/filewidgets/kfilewidget.cpp +++ b/src/filewidgets/kfilewidget.cpp @@ -1008,6 +1008,19 @@ return; } + const auto &supportedSchemes = d->model->supportedSchemes(); + if (!supportedSchemes.isEmpty() && !supportedSchemes.contains(d->url.scheme())) { + KMessageBox::sorry(this, + i18np("The selected URL uses an unsupported scheme. " + "Please use the following scheme: %2", + "The selected URL uses an unsupported scheme. " + "Please use one of the following schemes: %2", + supportedSchemes.size(), + supportedSchemes.join(QLatin1String(", "))), + i18n("Unsupported URL scheme")); + return; + } + // if we are given a folder when not on directory mode, let's get into it if (res && !directoryMode && statJob->statResult().isDir()) { // check if we were given more than one folder, in that case we don't know to which one @@ -2836,4 +2849,15 @@ d->hasView = true; } +void KFileWidget::setSupportedSchemes(const QStringList &schemes) +{ + d->model->setSupportedSchemes(schemes); + d->ops->setSupportedSchemes(schemes); +} + +QStringList KFileWidget::supportedSchemes() const +{ + return d->model->supportedSchemes(); +} + #include "moc_kfilewidget.cpp"