#include <KIO/Job>
#include <KListOpenFilesJob>
#include <KLocalizedString>
+#include <KProtocolManager>
#include <QIcon>
#include <QMenu>
+#include <QMimeData>
#include <QShowEvent>
-#include <QTimer>
#include <Solid/StorageAccess>
void PlacesPanel::readSettings()
{
if (GeneralSettings::autoExpandFolders()) {
- if (!m_dragActivationTimer) {
- m_dragActivationTimer = new QTimer(this);
- m_dragActivationTimer->setInterval(750);
- m_dragActivationTimer->setSingleShot(true);
- connect(m_dragActivationTimer, &QTimer::timeout,
- this, &PlacesPanel::slotDragActivationTimeout);
- }
+ setDragAutoActivationDelay(750);
} else {
- delete m_dragActivationTimer;
- m_dragActivationTimer = nullptr;
- m_pendingDragActivation = QPersistentModelIndex();
+ setDragAutoActivationDelay(0);
}
const int iconSize = qMax(0, PlacesPanelSettings::iconSize());
KFilePlacesView::showEvent(event);
}
-void PlacesPanel::dragMoveEvent(QDragMoveEvent *event)
+static bool isInternalDrag(const QMimeData *mimeData)
{
- KFilePlacesView::dragMoveEvent(event);
-
- if (!m_dragActivationTimer) {
- return;
- }
-
- const QModelIndex index = indexAt(event->pos());
- if (!index.isValid()) {
- return;
- }
-
- QPersistentModelIndex persistentIndex(index);
- if (!m_pendingDragActivation.isValid() || m_pendingDragActivation != persistentIndex) {
- m_pendingDragActivation = persistentIndex;
- m_dragActivationTimer->start();
+ const auto formats = mimeData->formats();
+ for (const auto &format : formats) {
+ // from KFilePlacesModel::_k_internalMimetype
+ if (format.startsWith(QLatin1String("application/x-kfileplacesmodel-"))) {
+ return true;
+ }
}
+ return false;
}
-void PlacesPanel::dragLeaveEvent(QDragLeaveEvent *event)
+void PlacesPanel::dragMoveEvent(QDragMoveEvent *event)
{
- KFilePlacesView::dragLeaveEvent(event);
-
- if (m_dragActivationTimer) {
- m_dragActivationTimer->stop();
- m_pendingDragActivation = QPersistentModelIndex();
+ const QModelIndex index = indexAt(event->pos());
+ if (index.isValid()) {
+ auto *placesModel = static_cast<KFilePlacesModel *>(model());
+
+ // Reject drag ontop of a non-writable protocol
+ // We don't know whether we're dropping inbetween or ontop of a place
+ // so still allow internal drag events so that re-arranging still works.
+ const QUrl url = placesModel->url(index);
+ if (url.isValid() && !isInternalDrag(event->mimeData()) && !KProtocolManager::supportsWriting(url)) {
+ event->setDropAction(Qt::IgnoreAction);
+ }
}
-}
-
-void PlacesPanel::dropEvent(QDropEvent *event)
-{
- KFilePlacesView::dropEvent(event);
- if (m_dragActivationTimer) {
- m_dragActivationTimer->stop();
- m_pendingDragActivation = QPersistentModelIndex();
- }
+ KFilePlacesView::dragMoveEvent(event);
}
void PlacesPanel::slotConfigureTrash()
settingsDialog->show();
}
-void PlacesPanel::slotDragActivationTimeout()
-{
- if (!m_pendingDragActivation.isValid()) {
- return;
- }
-
- auto *placesModel = static_cast<KFilePlacesModel *>(model());
- Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(placesModel->url(m_pendingDragActivation)));
-}
-
void PlacesPanel::slotUrlsDropped(const QUrl& dest, QDropEvent* event, QWidget* parent)
{
KIO::DropJob *job = DragAndDropHelper::dropUrls(dest, event, parent);
if (job) {
- connect(job, &KIO::DropJob::result, this, [this](KJob *job) { if (job->error()) Q_EMIT errorMessage(job->errorString()); });
+ connect(job, &KIO::DropJob::result, this, [this](KJob *job) {
+ if (job->error() && job->error() != KIO::ERR_USER_CANCELED) {
+ Q_EMIT errorMessage(job->errorString());
+ }
+ });
}
}
void PlacesPanel::slotTearDownDone(Solid::ErrorType error, const QVariant& errorData)
{
if (error && errorData.isValid()) {
- if (error == Solid::ErrorType::DeviceBusy) {
+ if (error == Solid::ErrorType::UserCanceled) {
+ // No need to tell the user what they just did.
+ } else if (error == Solid::ErrorType::DeviceBusy) {
KListOpenFilesJob* listOpenFilesJob = new KListOpenFilesJob(m_deviceToTearDown->filePath());
connect(listOpenFilesJob, &KIO::Job::result, this, [this, listOpenFilesJob](KJob*) {
const KProcessList::KProcessInfoList blockingProcesses = listOpenFilesJob->processInfoList();