diff --git a/src/widgets/dropjob.cpp b/src/widgets/dropjob.cpp --- a/src/widgets/dropjob.cpp +++ b/src/widgets/dropjob.cpp @@ -37,12 +37,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -143,8 +145,10 @@ const QList m_urls; QMap m_metaData; Qt::DropAction m_dropAction; + Qt::DropActions m_possibleActions; QPoint m_relativePos; Qt::KeyboardModifiers m_keyboardModifiers; + KFileItemListProperties m_itemProps; QUrl m_destUrl; KFileItem m_destItem; // null for remote URLs not found in the dirlister cache const JobFlags m_flags; @@ -267,21 +271,68 @@ return KIO::ERR_WRITE_ACCESS_DENIED; } + // Check what the source can do + // TODO: Determining the mimetype of the source URLs is difficult for remote URLs, + // we would need to KIO::stat each URL in turn, asynchronously.... + KFileItemList fileItems; + fileItems.reserve(m_urls.size()); + bool allItemsAreFromTrash = true; + bool allItemsAreLocal = true; + bool allItemsAreSameDevice = true; bool containsTrashRoot = false; + bool equalDestination = true; + + KMountPoint::List mountPoints = KMountPoint::currentMountPoints(); + const QString &destDevice = mountPoints.findByPath(m_destUrl.path())->mountedFrom(); + for (const QUrl &url : m_urls) { const bool local = url.isLocalFile(); if (!local /*optimization*/ && url.scheme() == QLatin1String("trash")) { if (url.path().isEmpty() || url.path() == QLatin1String("/")) { containsTrashRoot = true; } } else { allItemsAreFromTrash = false; + + if (!local && allItemsAreLocal) { + allItemsAreLocal = false; + } } + + if (equalDestination && !m_destUrl.matches(url.adjusted(QUrl::RemoveFilename), QUrl::StripTrailingSlash)) { + equalDestination = false; + } + + if (allItemsAreSameDevice) { + const QString &sourceDevice = mountPoints.findByPath(url.path())->mountedFrom(); + if (sourceDevice != destDevice && !KFileItem(url).isLink()) { + allItemsAreSameDevice = false; + } + } + + fileItems.append(KFileItem(url)); + if (url.matches(m_destUrl, QUrl::StripTrailingSlash)) { return KIO::ERR_DROP_ON_ITSELF; } } + m_itemProps.setItems(fileItems); + + m_possibleActions = Qt::LinkAction; + const bool sReading = m_itemProps.supportsReading(); + const bool sDeleting = m_itemProps.supportsDeleting(); + const bool sMoving = m_itemProps.supportsMoving(); + + if (sReading) { + m_possibleActions |= Qt::CopyAction; + } + + if (sMoving || (sReading && sDeleting)) { + if (!equalDestination) { + m_possibleActions |= Qt::MoveAction; + } + } const bool trashing = m_destUrl.scheme() == QLatin1String("trash"); if (trashing) { @@ -310,6 +361,19 @@ m_dropAction = Qt::MoveAction; return KJob::NoError; // ok } + + // if the default behavior has been changed to MoveAction, read from kdeglobals + const KConfigGroup g = KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("KDE")); + if (g.readEntry("dndToMove", false) && (m_possibleActions & Qt::MoveAction) && allItemsAreLocal && allItemsAreSameDevice) { + if (m_keyboardModifiers == Qt::NoModifier) { + m_dropAction = Qt::MoveAction; + return KJob::NoError; // ok + } else if (m_keyboardModifiers == Qt::ShiftModifier) { + // the user requests to show the menu + return KIO::ERR_UNKNOWN; + } + } + if (m_keyboardModifiers & (Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier)) { // Qt determined m_dropAction from the modifiers already return KJob::NoError; // ok @@ -323,21 +387,7 @@ { Q_Q(DropJob); - // Check what the source can do - // TODO: Determining the mimetype of the source URLs is difficult for remote URLs, - // we would need to KIO::stat each URL in turn, asynchronously.... - KFileItemList fileItems; - fileItems.reserve(m_urls.size()); - for (const QUrl &url : m_urls) { - fileItems.append(KFileItem(url)); - } - const KFileItemListProperties itemProps(fileItems); - - emit q->popupMenuAboutToShow(itemProps); - - const bool sReading = itemProps.supportsReading(); - const bool sDeleting = itemProps.supportsDeleting(); - const bool sMoving = itemProps.supportsMoving(); + emit q->popupMenuAboutToShow(m_itemProps); QString seq = QKeySequence(Qt::ShiftModifier).toString(); Q_ASSERT(seq.endsWith(QLatin1Char('+'))); @@ -358,27 +408,17 @@ popupLinkAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-link"))); popupLinkAction->setData(QVariant::fromValue(Qt::LinkAction)); - if (sMoving || (sReading && sDeleting)) { - bool equalDestination = true; - for (const QUrl &src : m_urls) { - if (!m_destUrl.matches(src.adjusted(QUrl::RemoveFilename), QUrl::StripTrailingSlash)) { - equalDestination = false; - break; - } - } - - if (!equalDestination) { - popup->addAction(popupMoveAction); - } + if (m_possibleActions & Qt::MoveAction) { + popup->addAction(popupMoveAction); } - if (sReading) { + if (m_possibleActions & Qt::CopyAction) { popup->addAction(popupCopyAction); } popup->addAction(popupLinkAction); - addPluginActions(popup, itemProps); + addPluginActions(popup, m_itemProps); popup->addSeparator(); }