Index: src/kitemviews/kfileitemmodel.h =================================================================== --- src/kitemviews/kfileitemmodel.h +++ src/kitemviews/kfileitemmodel.h @@ -73,7 +73,7 @@ * the root-parent of all items. * @see rootItem() */ - QUrl directory() const; + QUrl directory() const Q_DECL_OVERRIDE; /** * Cancels the loading of a directory which has been started by either Index: src/kitemviews/kitemlistcontroller.cpp =================================================================== --- src/kitemviews/kitemlistcontroller.cpp +++ src/kitemviews/kitemlistcontroller.cpp @@ -39,6 +39,7 @@ #include #include #include +#include KItemListController::KItemListController(KItemModelBase* model, KItemListView* view, QObject* parent) : QObject(parent), @@ -842,6 +843,7 @@ Q_UNUSED(event); Q_UNUSED(transform); + m_autoActivationTimer->stop(); m_view->setAutoScroll(false); m_view->hideDropIndicator(); @@ -859,8 +861,8 @@ return false; } - event->acceptProposedAction(); + QUrl hoveredDir = m_model->directory(); KItemListWidget* oldHoveredWidget = hoveredWidget(); const QPointF pos = transform.map(event->pos()); @@ -883,6 +885,11 @@ } const int index = newHoveredWidget->index(); + + if (m_model->isDir(index)) { + hoveredDir = m_model->url(index); + } + if (!droppingBetweenItems) { if (m_model->supportsDropping(index)) { // Something has been dragged on an item. @@ -908,6 +915,8 @@ m_view->hideDropIndicator(); } + event->setAccepted(!DragAndDropHelper::urlListMatchesUrl(event->mimeData()->urls(), hoveredDir)); + return false; } Index: src/kitemviews/kitemmodelbase.h =================================================================== --- src/kitemviews/kitemmodelbase.h +++ src/kitemviews/kitemmodelbase.h @@ -182,6 +182,20 @@ */ QString blacklistItemDropEventMimeType() const; + /** + * @return URL of the item at the specified index + */ + virtual QUrl url(int index) const; + + /** + * @return True, if item at specified index is a directory + */ + virtual bool isDir(int index) const; + + /** + * @return Parent directory of the items that are shown + */ + virtual QUrl directory() const; signals: /** * Is emitted if one or more items have been inserted. Each item-range consists Index: src/kitemviews/kitemmodelbase.cpp =================================================================== --- src/kitemviews/kitemmodelbase.cpp +++ src/kitemviews/kitemmodelbase.cpp @@ -164,3 +164,17 @@ Q_UNUSED(previous); } +QUrl KItemModelBase::url(int index) const +{ + return data(index).value("url").toUrl(); +} + +bool KItemModelBase::isDir(int index) const +{ + return data(index).value("isDir").toBool(); +} + +QUrl KItemModelBase::directory() const +{ + return QUrl(); +} \ No newline at end of file Index: src/panels/places/placesitemmodel.h =================================================================== --- src/panels/places/placesitemmodel.h +++ src/panels/places/placesitemmodel.h @@ -132,6 +132,7 @@ */ void saveBookmarks(); + bool isDir(int index) const Q_DECL_OVERRIDE; signals: void errorMessage(const QString& message); void storageSetupDone(int index, bool success); Index: src/panels/places/placesitemmodel.cpp =================================================================== --- src/panels/places/placesitemmodel.cpp +++ src/panels/places/placesitemmodel.cpp @@ -1159,6 +1159,12 @@ return date; } +bool PlacesItemModel::isDir(int index) const +{ + Q_UNUSED(index); + return true; +} + QUrl PlacesItemModel::createSearchUrl(const QUrl& url) { QUrl searchUrl; Index: src/views/draganddrophelper.h =================================================================== --- src/views/draganddrophelper.h +++ src/views/draganddrophelper.h @@ -22,9 +22,10 @@ #define DRAGANDDROPHELPER_H #include "dolphin_export.h" +#include +#include -class QUrl; class QDropEvent; class QWidget; namespace KIO { class DropJob; } @@ -42,11 +43,17 @@ * is true. * @param event Drop event. * @param window Widget where the drop happened, will be used as parent of the drop menu. - * @return KIO::DropJob pointer + * @return KIO::DropJob pointer or null in case the destUrl is contained + * in the mimeData url list. */ static KIO::DropJob* dropUrls(const QUrl& destUrl, QDropEvent* event, QWidget *window); + + /** + * @return True if destUrl is contained in the urls parameter. + */ + static bool urlListMatchesUrl(const QList& urls, const QUrl& destUrl); }; #endif Index: src/views/draganddrophelper.cpp =================================================================== --- src/views/draganddrophelper.cpp +++ src/views/draganddrophelper.cpp @@ -29,6 +29,14 @@ #include #include + +bool DragAndDropHelper::urlListMatchesUrl(const QList& urls, const QUrl& destUrl) +{ + return std::find_if(urls.constBegin(), urls.constEnd(), [destUrl](const QUrl& url) { + return url.matches(destUrl, QUrl::StripTrailingSlash); + }) != urls.constEnd(); +} + KIO::DropJob* DragAndDropHelper::dropUrls(const QUrl& destUrl, QDropEvent* event, QWidget* window) { const QMimeData* mimeData = event->mimeData(); @@ -42,6 +50,10 @@ message.setArguments({destUrl.toDisplayString(QUrl::PreferLocalFile)}); QDBusConnection::sessionBus().call(message); } else { + if (urlListMatchesUrl(event->mimeData()->urls(), destUrl)) { + return nullptr; + } + // Drop into a directory or a desktop-file KIO::DropJob *job = KIO::drop(event, destUrl); KJobWidgets::setWindow(job, window);