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 @@ -145,6 +145,9 @@ */ KFileItem rootItem() const; + QUrl indexGetUrl(int index) const Q_DECL_OVERRIDE; + bool indexIsDir(int index) Q_DECL_OVERRIDE; + /** * Clears all items of the model. */ Index: src/kitemviews/kfileitemmodel.cpp =================================================================== --- src/kitemviews/kfileitemmodel.cpp +++ src/kitemviews/kfileitemmodel.cpp @@ -2413,3 +2413,13 @@ return true; } + +QUrl KFileItemModel::indexGetUrl(int index) const +{ + return fileItem(index).url(); +} + +bool KFileItemModel::indexIsDir(int index) +{ + return fileItem(index).isDir(); +} Index: src/kitemviews/kitemlistcontroller.h =================================================================== --- src/kitemviews/kitemlistcontroller.h +++ src/kitemviews/kitemlistcontroller.h @@ -256,6 +256,11 @@ */ void startDragging(); + /** + * @return True, if destUrl is contained in the url list. + */ + bool urlListMatchesUrl(const QList& urls, const QUrl& destUrl); + /** * @return Widget that is currently in the hovered state. 0 is returned * if no widget is marked as hovered. Index: src/kitemviews/kitemlistcontroller.cpp =================================================================== --- src/kitemviews/kitemlistcontroller.cpp +++ src/kitemviews/kitemlistcontroller.cpp @@ -838,6 +838,7 @@ Q_UNUSED(event); Q_UNUSED(transform); + m_autoActivationTimer->stop(); m_view->setAutoScroll(false); m_view->hideDropIndicator(); @@ -855,8 +856,8 @@ return false; } - event->acceptProposedAction(); + QUrl hoveredDir = m_model->directory(); KItemListWidget* oldHoveredWidget = hoveredWidget(); const QPointF pos = transform.map(event->pos()); @@ -879,6 +880,11 @@ } const int index = newHoveredWidget->index(); + + if (m_model->indexIsDir(index)) { + hoveredDir = m_model->indexGetUrl(index); + } + if (!droppingBetweenItems) { if (m_model->supportsDropping(index)) { // Something has been dragged on an item. @@ -904,6 +910,8 @@ m_view->hideDropIndicator(); } + event->setAccepted(!urlListMatchesUrl(event->mimeData()->urls(), hoveredDir)); + return false; } @@ -1326,3 +1334,13 @@ } } +bool KItemListController::urlListMatchesUrl(const QList& urls, const QUrl& destUrl) +{ + foreach(const QUrl& url, urls) { + if (url.matches(destUrl, QUrl::StripTrailingSlash)) { + return true; + } + } + + return false; +} Index: src/kitemviews/kitemmodelbase.h =================================================================== --- src/kitemviews/kitemmodelbase.h +++ src/kitemviews/kitemmodelbase.h @@ -182,6 +182,21 @@ */ QString blacklistItemDropEventMimeType() const; + /** + * @return URL of the item at the specified index + */ + virtual QUrl indexGetUrl(int index) const; + + /** + * @return True, if item at specified index is a directory + */ + virtual bool indexIsDir(int index) = 0; + + /** + * @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,14 @@ Q_UNUSED(previous); } + +QUrl KItemModelBase::indexGetUrl(int index) const +{ + Q_UNUSED(index); + return QUrl(); +} + +QUrl KItemModelBase::directory() const +{ + return QUrl(); +} Index: src/kitemviews/kstandarditemmodel.h =================================================================== --- src/kitemviews/kstandarditemmodel.h +++ src/kitemviews/kstandarditemmodel.h @@ -63,6 +63,7 @@ void removeItem(int index); KStandardItem* item(int index) const; int index(const KStandardItem* item) const; + bool indexIsDir(int index) Q_DECL_OVERRIDE; /** * Convenience method for insertItem(count(), item). Index: src/kitemviews/kstandarditemmodel.cpp =================================================================== --- src/kitemviews/kstandarditemmodel.cpp +++ src/kitemviews/kstandarditemmodel.cpp @@ -237,3 +237,8 @@ Q_UNUSED(removedItem); } +bool KStandardItemModel::indexIsDir(int index) { + Q_UNUSED(index); + return true; +} + Index: src/panels/places/placesitemmodel.h =================================================================== --- src/panels/places/placesitemmodel.h +++ src/panels/places/placesitemmodel.h @@ -132,6 +132,9 @@ */ void saveBookmarks(); + QUrl indexGetUrl(int index) const Q_DECL_OVERRIDE; + bool indexIsDir(int index) 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,23 @@ return date; } +QUrl PlacesItemModel::indexGetUrl(int index) const +{ + const PlacesItem* item = placesItem(index); + + if (item) { + return item->url(); + } + + return KItemModelBase::indexGetUrl(index); +} + +bool PlacesItemModel::indexIsDir(int index) +{ + Q_UNUSED(index); + return true; +} + QUrl PlacesItemModel::createSearchUrl(const QUrl& url) { QUrl searchUrl; Index: src/tests/kitemlistselectionmanagertest.cpp =================================================================== --- src/tests/kitemlistselectionmanagertest.cpp +++ src/tests/kitemlistselectionmanagertest.cpp @@ -29,6 +29,8 @@ Q_OBJECT public: DummyModel(); + + bool indexIsDir(int index) Q_DECL_OVERRIDE; void setCount(int count); int count() const Q_DECL_OVERRIDE; QHash data(int index) const Q_DECL_OVERRIDE; @@ -53,6 +55,12 @@ return m_count; } +bool DummyModel::indexIsDir(int index) +{ + Q_UNUSED(index); + return false; +} + QHash DummyModel::data(int index) const { Q_UNUSED(index);