From cad758b31f9dd9f2916a756748b9d86e444d3819 Mon Sep 17 00:00:00 2001 From: reionwong Date: Thu, 4 Nov 2021 01:35:09 +0800 Subject: [PATCH] Support drag and drop to move files --- model/foldermodel.cpp | 52 +++++++++++++++++++++++++++++++++++++++ model/foldermodel.h | 1 + qml/FolderGridView.qml | 55 ++++++++++++++++++++++++++++++------------ qml/FolderListView.qml | 42 ++++++++++++++++++++++++++++++++ 4 files changed, 135 insertions(+), 15 deletions(-) diff --git a/model/foldermodel.cpp b/model/foldermodel.cpp index e237afd..8508bec 100644 --- a/model/foldermodel.cpp +++ b/model/foldermodel.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1008,6 +1009,57 @@ void FolderModel::dragSelected(int x, int y) QMetaObject::invokeMethod(this, "dragSelectedInternal", Qt::QueuedConnection, Q_ARG(int, x), Q_ARG(int, y)); } +void FolderModel::drop(QQuickItem *target, QObject *dropEvent, int row) +{ + QMimeData *mimeData = qobject_cast(dropEvent->property("mimeData").value()); + + if (!mimeData) { + return; + } + + QModelIndex idx; + KFileItem item; + + if (row > -1 && row < rowCount()) { + idx = index(row, 0); + item = itemForIndex(idx); + } + + QUrl dropTargetUrl; + + // So we get to run mostLocalUrl() over the current URL. + if (item.isNull()) { + item = rootItem(); + } + + if (item.isNull()) { + dropTargetUrl = m_dirModel->dirLister()->url(); + } else { + dropTargetUrl = item.mostLocalUrl(); + } + + if (idx.isValid() && !(flags(idx) & Qt::ItemIsDropEnabled)) { + return; + } + + // 处理url + QList sourceUrls; + for (const QUrl &url : mimeData->urls()) { + QFileInfo info(url.toLocalFile()); + QUrl newUrl = QUrl::fromLocalFile(info.dir().path()); + + // 相同的目录下不加入 + if (newUrl != dropTargetUrl) { + sourceUrls.append(url); + } + } + + if (!sourceUrls.isEmpty()) { + KIO::Job *job = KIO::move(sourceUrls, dropTargetUrl, KIO::HideProgressInfo); + job->start(); + } +} + void FolderModel::setWallpaperSelected() { if (!m_selectionModel) diff --git a/model/foldermodel.h b/model/foldermodel.h index e40e236..d6595a1 100644 --- a/model/foldermodel.h +++ b/model/foldermodel.h @@ -197,6 +197,7 @@ public: Q_INVOKABLE void addItemDragImage(int row, int x, int y, int width, int height, const QVariant &image); Q_INVOKABLE void clearDragImages(); Q_INVOKABLE void dragSelected(int x, int y); + Q_INVOKABLE void drop(QQuickItem *target, QObject *dropEvent, int row); Q_INVOKABLE void setWallpaperSelected(); diff --git a/qml/FolderGridView.qml b/qml/FolderGridView.qml index 39a2961..0482aa2 100644 --- a/qml/FolderGridView.qml +++ b/qml/FolderGridView.qml @@ -21,6 +21,7 @@ import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import Cutefish.FileManager 1.0 +import Cutefish.DragDrop 1.0 as DragDrop import FishUI 1.0 as FishUI GridView { @@ -147,6 +148,38 @@ GridView { cPress = null } + function drop(target, event, pos) { + var dropPos = mapToItem(control.contentItem, pos.x, pos.y) + var dropIndex = control.indexAt(dropPos.x, dropPos.y) + var dragPos = mapToItem(control.contentItem, control.dragX, control.dragY) + var dragIndex = control.indexAt(dragPos.x, dragPos.y) + + if (control.dragX === -1 || dragIndex !== dropIndex) { + dirModel.drop(control, event, dropItemAt(dropPos)) + } + } + + function dropItemAt(pos) { + var item = control.itemAt(pos.x, pos.y) + + if (item) { + if (item.blank) { + return -1 + } + + var hOffset = Math.abs(Math.min(control.contentX, control.originX)) + var hPos = mapToItem(item, pos.x + hOffset, pos.y) + + if ((hPos.x < 0 || hPos.y < 0 || hPos.x > item.width || hPos.y > item.height)) { + return -1 + } else { + return positioner.map(item.index) + } + } + + return -1 + } + highlightMoveDuration: 0 keyNavigationEnabled : true keyNavigationWraps : true @@ -205,7 +238,7 @@ GridView { var newIndex = positioner.nearestItem(currentIndex, effectiveNavDirection(control.flow, control.effectiveLayoutDirection, Qt.LeftArrow)) if (newIndex !== -1) { - currentIndex = newIndex; + currentIndex = newIndex updateSelection(event.modifiers) } } @@ -215,7 +248,7 @@ GridView { var newIndex = positioner.nearestItem(currentIndex, effectiveNavDirection(control.flow, control.effectiveLayoutDirection, Qt.RightArrow)) if (newIndex !== -1) { - currentIndex = newIndex; + currentIndex = newIndex updateSelection(event.modifiers) } } @@ -276,22 +309,14 @@ GridView { folderModel: dirModel perStripe: Math.floor(((control.flow == GridView.FlowLeftToRight) ? control.width : control.height) / ((control.flow == GridView.FlowLeftToRight) - ? control.cellWidth : control.cellHeight)); + ? control.cellWidth : control.cellHeight)) } - DropArea { - id: _dropArea + DragDrop.DropArea { anchors.fill: parent - onDropped: { - var dropPos = mapToItem(control.contentItem, drop.x, drop.y) - var dropIndex = control.indexAt(drop.x, drop.y) - var dragPos = mapToItem(control.contentItem, control.dragX, control.dragY) - var dragIndex = control.indexAt(dragPos.x, dragPos.y) - - if (control.dragX == -1 || dragIndex !== dropIndex) { - - } + onDrop: { + control.drop(control, event, mapToItem(control, event.x, event.y)) } } @@ -429,7 +454,7 @@ GridView { clearPressState() } else { if (control.editor && control.editor.targetItem) - return; + return dirModel.pinSelection() control.rubberBand = rubberBandObject.createObject(control.contentItem, {x: cPress.x, y: cPress.y}) diff --git a/qml/FolderListView.qml b/qml/FolderListView.qml index 82f1dfb..9903f85 100644 --- a/qml/FolderListView.qml +++ b/qml/FolderListView.qml @@ -21,6 +21,7 @@ import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import FishUI 1.0 as FishUI import Cutefish.FileManager 1.0 +import Cutefish.DragDrop 1.0 as DragDrop ListView { id: control @@ -91,6 +92,39 @@ ListView { cPress = null } + + function drop(target, event, pos) { + var dropPos = mapToItem(control.contentItem, pos.x, pos.y) + var dropIndex = control.indexAt(dropPos.x, dropPos.y) + var dragPos = mapToItem(control.contentItem, control.dragX, control.dragY) + var dragIndex = control.indexAt(dragPos.x, dragPos.y) + + if (control.dragX === -1 || dragIndex !== dropIndex) { + dirModel.drop(control, event, dropItemAt(dropPos)) + } + } + + function dropItemAt(pos) { + var item = control.itemAt(pos.x, pos.y) + + if (item) { + if (item.blank) { + return -1 + } + + var hOffset = Math.abs(Math.min(control.contentX, control.originX)) + var hPos = mapToItem(item, pos.x + hOffset, pos.y) + + if ((hPos.x < 0 || hPos.y < 0 || hPos.x > item.width || hPos.y > item.height)) { + return -1 + } else { + return item.index + } + } + + return -1 + } + highlightMoveDuration: 0 Keys.enabled: true Keys.onPressed: { @@ -174,6 +208,14 @@ ListView { cPress = mapToItem(control.contentItem, pressX, pressY) } + DragDrop.DropArea { + anchors.fill: parent + + onDrop: { + control.drop(control, event, mapToItem(control, event.x, event.y)) + } + } + MouseArea { id: _mouseArea anchors.fill: parent