From f4c960025167b7c7e04e1290ac9d9fee03a9b62d Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Thu, 12 Jul 2012 00:27:53 +0200 Subject: [PATCH] Re-implement dropping of files on folders in the Places Panel. This resolves a regression caused by the Places Panel rewrite. There is a small glitch left when reordering items (dragging below the last or above the first item only shows the drop indicator when first dragging out of the item and then back), but I prefer not to fix this glitch right now because this would require a more intrusive change, and I do not want to risk regressions because is not much time left to fix them before 4.9.0 is released. Thanks to Peter Penz for providing some advice about this issue. CCBUG: 302557 --- .../src/kitemviews/kitemlistcontroller.cpp | 43 +++++++++++-------- dolphin/src/kitemviews/kitemlistcontroller.h | 9 ++++ dolphin/src/kitemviews/kitemlistview.cpp | 7 +++ .../panels/places/placesitemlistwidget.cpp | 2 + dolphin/src/panels/places/placesitemmodel.cpp | 7 ++- dolphin/src/panels/places/placesitemmodel.h | 5 ++- dolphin/src/panels/places/placespanel.cpp | 19 +++++++- dolphin/src/panels/places/placespanel.h | 1 + 8 files changed, 72 insertions(+), 21 deletions(-) diff --git a/dolphin/src/kitemviews/kitemlistcontroller.cpp b/dolphin/src/kitemviews/kitemlistcontroller.cpp index 76f7fa1cd6..88f5d9f7cf 100644 --- a/dolphin/src/kitemviews/kitemlistcontroller.cpp +++ b/dolphin/src/kitemviews/kitemlistcontroller.cpp @@ -778,7 +778,6 @@ bool KItemListController::dragLeaveEvent(QGraphicsSceneDragDropEvent* event, con bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform) { - Q_UNUSED(transform); if (!m_model || !m_view) { return false; } @@ -799,20 +798,23 @@ bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, cons } if (newHoveredWidget) { - const int index = newHoveredWidget->index(); - if (m_model->supportsDropping(index)) { - newHoveredWidget->setHovered(true); - } else if (m_model->sortRole().isEmpty()) { - // The model supports inserting of items on - // the given index. Assure that a drop-indicator - // is shown by the view. - m_view->showDropIndicator(pos); + bool droppingBetweenItems = false; + if (m_model->sortRole().isEmpty()) { + // The model supports inserting items between other items. + droppingBetweenItems = (m_view->showDropIndicator(pos) >= 0); } - emit itemHovered(index); - if (m_autoActivationTimer->interval() >= 0) { - m_autoActivationTimer->setProperty("index", index); - m_autoActivationTimer->start(); + const int index = newHoveredWidget->index(); + if (!droppingBetweenItems && m_model->supportsDropping(index)) { + // Something has been dragged on an item. + m_view->hideDropIndicator(); + newHoveredWidget->setHovered(true); + emit itemHovered(index); + + if (m_autoActivationTimer->interval() >= 0) { + m_autoActivationTimer->setProperty("index", index); + m_autoActivationTimer->start(); + } } } } @@ -822,7 +824,6 @@ bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent* event, cons bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QTransform& transform) { - Q_UNUSED(transform) if (!m_view) { return false; } @@ -831,13 +832,19 @@ bool KItemListController::dropEvent(QGraphicsSceneDragDropEvent* event, const QT m_view->setAutoScroll(false); const QPointF pos = transform.map(event->pos()); + + int dropAboveIndex = -1; if (m_model->sortRole().isEmpty()) { - // The model supports inserting of items on - // a given index. - const int dropIndex = m_view->showDropIndicator(pos); + // The model supports inserting of items between other items. + dropAboveIndex = m_view->showDropIndicator(pos); + } + + if (dropAboveIndex >= 0) { + // Something has been dropped between two items. m_view->hideDropIndicator(); - emit itemDropEvent(dropIndex, event); + emit aboveItemDropEvent(dropAboveIndex, event); } else { + // Something has been dropped on an item or on an empty part of the view. emit itemDropEvent(m_view->itemAt(pos), event); } diff --git a/dolphin/src/kitemviews/kitemlistcontroller.h b/dolphin/src/kitemviews/kitemlistcontroller.h index db31d50c3d..a88152622b 100644 --- a/dolphin/src/kitemviews/kitemlistcontroller.h +++ b/dolphin/src/kitemviews/kitemlistcontroller.h @@ -201,9 +201,18 @@ signals: * Is emitted if a drop event is done above the item with the index * \a index. If \a index is < 0 the drop event is done above an * empty area of the view. + * TODO: Introduce a new signal viewDropEvent(QGraphicsSceneDragDropEvent), + * which is emitted if the drop event occurs on an empty area in + * the view, and make sure that index is always >= 0 in itemDropEvent(). */ void itemDropEvent(int index, QGraphicsSceneDragDropEvent* event); + /** + * Is emitted if a drop event is done between the item with the index + * \a index and the previous item. + */ + void aboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event); + void modelChanged(KItemModelBase* current, KItemModelBase* previous); void viewChanged(KItemListView* current, KItemListView* previous); diff --git a/dolphin/src/kitemviews/kitemlistview.cpp b/dolphin/src/kitemviews/kitemlistview.cpp index 64b33f96f3..72b3fd8fcb 100644 --- a/dolphin/src/kitemviews/kitemlistview.cpp +++ b/dolphin/src/kitemviews/kitemlistview.cpp @@ -2318,6 +2318,13 @@ int KItemListView::showDropIndicator(const QPointF& pos) const QPointF mappedPos = widget->mapFromItem(this, pos); const QRectF rect = itemRect(widget->index()); if (mappedPos.y() >= 0 && mappedPos.y() <= rect.height()) { + if (m_model->supportsDropping(widget->index())) { + const int gap = qMax(4, m_styleOption.padding); + if (mappedPos.y() >= gap && mappedPos.y() <= rect.height() - gap) { + return -1; + } + } + const bool isAboveItem = (mappedPos.y () < rect.height() / 2); const qreal y = isAboveItem ? rect.top() : rect.bottom(); diff --git a/dolphin/src/panels/places/placesitemlistwidget.cpp b/dolphin/src/panels/places/placesitemlistwidget.cpp index 3f4c92dfad..24c2b3f11f 100644 --- a/dolphin/src/panels/places/placesitemlistwidget.cpp +++ b/dolphin/src/panels/places/placesitemlistwidget.cpp @@ -19,6 +19,8 @@ #include "placesitemlistwidget.h" +#include "kdebug.h" + PlacesItemListWidget::PlacesItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) : KStandardItemListWidget(informant, parent) { diff --git a/dolphin/src/panels/places/placesitemmodel.cpp b/dolphin/src/panels/places/placesitemmodel.cpp index 00ab9670bb..4979013453 100644 --- a/dolphin/src/panels/places/placesitemmodel.cpp +++ b/dolphin/src/panels/places/placesitemmodel.cpp @@ -396,7 +396,12 @@ QMimeData* PlacesItemModel::createMimeData(const QSet& indexes) const return mimeData; } -void PlacesItemModel::dropMimeData(int index, const QMimeData* mimeData) +bool PlacesItemModel::supportsDropping(int index) const +{ + return index >= 0 && index < count(); +} + +void PlacesItemModel::dropMimeDataBefore(int index, const QMimeData* mimeData) { if (mimeData->hasFormat(internalMimeType())) { // The item has been moved inside the view diff --git a/dolphin/src/panels/places/placesitemmodel.h b/dolphin/src/panels/places/placesitemmodel.h index a060f45491..463e564e35 100644 --- a/dolphin/src/panels/places/placesitemmodel.h +++ b/dolphin/src/panels/places/placesitemmodel.h @@ -120,7 +120,10 @@ public: /** @reimp */ virtual QMimeData* createMimeData(const QSet& indexes) const; - void dropMimeData(int index, const QMimeData* mimeData); + /** @reimp */ + virtual bool supportsDropping(int index) const; + + void dropMimeDataBefore(int index, const QMimeData* mimeData); /** * @return Converts the URL, which contains "virtual" URLs for system-items like diff --git a/dolphin/src/panels/places/placespanel.cpp b/dolphin/src/panels/places/placespanel.cpp index 64de516fae..429c5399a8 100644 --- a/dolphin/src/panels/places/placespanel.cpp +++ b/dolphin/src/panels/places/placespanel.cpp @@ -93,6 +93,7 @@ void PlacesPanel::showEvent(QShowEvent* event) connect(m_controller, SIGNAL(itemContextMenuRequested(int,QPointF)), this, SLOT(slotItemContextMenuRequested(int,QPointF))); connect(m_controller, SIGNAL(viewContextMenuRequested(QPointF)), this, SLOT(slotViewContextMenuRequested(QPointF))); connect(m_controller, SIGNAL(itemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotItemDropEvent(int,QGraphicsSceneDragDropEvent*))); + connect(m_controller, SIGNAL(aboveItemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotAboveItemDropEvent(int,QGraphicsSceneDragDropEvent*))); KItemListContainer* container = new KItemListContainer(m_controller, this); container->setEnabledFrame(false); @@ -253,7 +254,23 @@ void PlacesPanel::slotViewContextMenuRequested(const QPointF& pos) void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event) { - m_model->dropMimeData(index, event->mimeData()); + if (index < 0) { + return; + } + + KUrl destUrl = m_model->placesItem(index)->url(); + QDropEvent dropEvent(event->pos().toPoint(), + event->possibleActions(), + event->mimeData(), + event->buttons(), + event->modifiers()); + + DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent); +} + +void PlacesPanel::slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event) +{ + m_model->dropMimeDataBefore(index, event->mimeData()); } void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent) diff --git a/dolphin/src/panels/places/placespanel.h b/dolphin/src/panels/places/placespanel.h index 427b01248f..8a84e00a0b 100644 --- a/dolphin/src/panels/places/placespanel.h +++ b/dolphin/src/panels/places/placespanel.h @@ -56,6 +56,7 @@ private slots: void slotItemContextMenuRequested(int index, const QPointF& pos); void slotViewContextMenuRequested(const QPointF& pos); void slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* event); + void slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event); void slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent); void slotTrashUpdated(KJob* job); void slotStorageSetupDone(int index, bool success);