X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/600166152d857ccfc9df15b25bd1237b74c71d43..9df6ef77aadbd2c142bc666d3c998d9ece47f7fe:/src/views/draganddrophelper.cpp diff --git a/src/views/draganddrophelper.cpp b/src/views/draganddrophelper.cpp index f8ae0ad03..7b9949df4 100644 --- a/src/views/draganddrophelper.cpp +++ b/src/views/draganddrophelper.cpp @@ -1,67 +1,100 @@ -/*************************************************************************** - * Copyright (C) 2007-2011 by Peter Penz * - * Copyright (C) 2007 by David Faure * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2007-2011 Peter Penz + * SPDX-FileCopyrightText: 2007 David Faure + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "draganddrophelper.h" -#include -#include -#include -#include -#include -#include +#include +#include + +#include +#include #include +#include -KonqOperations* DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destUrl, QDropEvent* event, QString& error) -{ - error.clear(); +QHash DragAndDropHelper::m_urlListMatchesUrlCache; - if (!destItem.isNull() && !destItem.isWritable()) { - error = i18nc("@info:status", "Access denied. Could not write to %1", destUrl.pathOrUrl()); - return 0; +bool DragAndDropHelper::urlListMatchesUrl(const QList &urls, const QUrl &destUrl) +{ + auto iteratorResult = m_urlListMatchesUrlCache.constFind(destUrl); + if (iteratorResult != m_urlListMatchesUrlCache.constEnd()) { + return *iteratorResult; } - const QMimeData* mimeData = event->mimeData(); - if (mimeData->hasFormat("application/x-kde-ark-dndextract-service") && - mimeData->hasFormat("application/x-kde-ark-dndextract-path")) { - const QString remoteDBusClient = mimeData->data("application/x-kde-ark-dndextract-service"); - const QString remoteDBusPath = mimeData->data("application/x-kde-ark-dndextract-path"); + const bool destUrlMatches = std::find_if(urls.constBegin(), + urls.constEnd(), + [destUrl](const QUrl &url) { + return url.matches(destUrl, QUrl::StripTrailingSlash); + }) + != urls.constEnd(); - QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, remoteDBusPath, - "org.kde.ark.DndExtract", "extractSelectedFilesTo"); - message.setArguments(QVariantList() << destUrl.pathOrUrl()); + return *m_urlListMatchesUrlCache.insert(destUrl, destUrlMatches); +} + +KIO::DropJob *DragAndDropHelper::dropUrls(const QUrl &destUrl, QDropEvent *event, QWidget *window) +{ + const QMimeData *mimeData = event->mimeData(); + if (isArkDndMimeType(mimeData)) { + const QString remoteDBusClient = QString::fromUtf8(mimeData->data(arkDndServiceMimeType())); + const QString remoteDBusPath = QString::fromUtf8(mimeData->data(arkDndPathMimeType())); + + QDBusMessage message = QDBusMessage::createMethodCall(remoteDBusClient, + remoteDBusPath, + QStringLiteral("org.kde.ark.DndExtract"), + QStringLiteral("extractSelectedFilesTo")); + message.setArguments({destUrl.toDisplayString(QUrl::PreferLocalFile)}); QDBusConnection::sessionBus().call(message); - } else if (!destItem.isNull() && (destItem.isDir() || destItem.isDesktopFile())) { - // Drop into a directory or a desktop-file - const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); - foreach (const KUrl& url, urls) { - if (url == destUrl) { - error = i18nc("@info:status", "A folder cannot be dropped into itself"); - return 0; - } + } else { + if (urlListMatchesUrl(event->mimeData()->urls(), destUrl)) { + return nullptr; } - return KonqOperations::doDrop(destItem, destUrl, event, QApplication::activeWindow(), QList()); + // TODO: remove this check once Qt is fixed so that it doesn't emit a QDropEvent on Wayland + // when we called QDragMoveEvent::ignore() + // https://codereview.qt-project.org/c/qt/qtwayland/+/541750 + KFileItem item(destUrl); + // KFileItem(QUrl) only stat local URLs, so we always allow dropping on non-local URLs + if (!item.isLocalFile() || supportsDropping(item)) { + // Drop into a directory or a desktop-file + KIO::DropJob *job = KIO::drop(event, destUrl); + KJobWidgets::setWindow(job, window); + return job; + } + } + + return nullptr; +} + +bool DragAndDropHelper::supportsDropping(const KFileItem &destItem) +{ + return (destItem.isDir() && destItem.isWritable()) || destItem.isDesktopFile(); +} + +void DragAndDropHelper::updateDropAction(QDropEvent *event, const QUrl &destUrl) +{ + if (urlListMatchesUrl(event->mimeData()->urls(), destUrl)) { + event->setDropAction(Qt::IgnoreAction); + event->ignore(); + } + KFileItem item(destUrl); + if (!item.isLocalFile() || supportsDropping(item)) { + event->setDropAction(event->proposedAction()); + event->accept(); } else { - return KonqOperations::doDrop(KFileItem(), destUrl, event, QApplication::activeWindow(), QList()); + event->setDropAction(Qt::IgnoreAction); + event->ignore(); } +} - return 0; +void DragAndDropHelper::clearUrlListMatchesUrlCache() +{ + DragAndDropHelper::m_urlListMatchesUrlCache.clear(); } +bool DragAndDropHelper::isArkDndMimeType(const QMimeData *mimeData) +{ + return mimeData->hasFormat(arkDndServiceMimeType()) && mimeData->hasFormat(arkDndPathMimeType()); +}