X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/0eed595268d2b0478eee1d5bf5ed6bbd100cdf4c..231200e6800a20aef5a1ba68dd3d64ecbee01000:/src/views/draganddrophelper.cpp diff --git a/src/views/draganddrophelper.cpp b/src/views/draganddrophelper.cpp index 7b9949df4..7163507a6 100644 --- a/src/views/draganddrophelper.cpp +++ b/src/views/draganddrophelper.cpp @@ -73,20 +73,85 @@ bool DragAndDropHelper::supportsDropping(const KFileItem &destItem) return (destItem.isDir() && destItem.isWritable()) || destItem.isDesktopFile(); } +DragAndDropHelper::DragAndDropHelper(QObject *parent) + : QObject(parent) +{ + m_destItemCacheInvalidationTimer.setSingleShot(true); + m_destItemCacheInvalidationTimer.setInterval(30000); + connect(&m_destItemCacheInvalidationTimer, &QTimer::timeout, this, [this]() { + m_destItemCache = KFileItem(); + }); +} + void DragAndDropHelper::updateDropAction(QDropEvent *event, const QUrl &destUrl) { + auto processEvent = [this](QDropEvent *event) { + if (supportsDropping(m_destItemCache)) { + event->setDropAction(event->proposedAction()); + event->accept(); + } else { + event->setDropAction(Qt::IgnoreAction); + event->ignore(); + } + }; + + m_lastUndecidedEvent = nullptr; + if (urlListMatchesUrl(event->mimeData()->urls(), destUrl)) { event->setDropAction(Qt::IgnoreAction); event->ignore(); + return; } - KFileItem item(destUrl); - if (!item.isLocalFile() || supportsDropping(item)) { - event->setDropAction(event->proposedAction()); - event->accept(); - } else { - event->setDropAction(Qt::IgnoreAction); - event->ignore(); + + if (destUrl == m_destItemCache.url()) { + // We already received events for this URL, and already have the + // stat result cached because: + // 1. it's a local file, and we already called KFileItem(destUrl) + // 2. it's a remote file, and StatJob finished + processEvent(event); + return; } + + if (m_statJob) { + if (destUrl == m_statJobUrl) { + // We already received events for this URL. Still waiting for + // the stat result. StatJob will process the event when it finishes. + m_lastUndecidedEvent = event; + return; + } + + // We are waiting for the stat result of a different URL. Cancel. + m_statJob->kill(); + m_statJob = nullptr; + m_statJobUrl.clear(); + } + + if (destUrl.isLocalFile()) { + // New local URL. KFileItem will stat on demand. + m_destItemCache = KFileItem(destUrl); + m_destItemCacheInvalidationTimer.start(); + processEvent(event); + return; + } + + // New remote URL. Start a StatJob and process the event when it finishes. + m_lastUndecidedEvent = event; + m_statJob = KIO::stat(destUrl, KIO::StatJob::SourceSide, KIO::StatDetail::StatBasic, KIO::JobFlag::HideProgressInfo); + m_statJobUrl = destUrl; + connect(m_statJob, &KIO::StatJob::result, this, [this, processEvent](KJob *job) { + KIO::StatJob *statJob = static_cast(job); + + m_destItemCache = KFileItem(statJob->statResult(), m_statJobUrl); + m_destItemCacheInvalidationTimer.start(); + + if (m_lastUndecidedEvent) { + processEvent(m_lastUndecidedEvent); + m_lastUndecidedEvent = nullptr; + } + + m_statJob = nullptr; + m_statJobUrl.clear(); + }); } void DragAndDropHelper::clearUrlListMatchesUrlCache()