X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/0603e18cd4e36b988196a99810f2e3e803fe3125..4cbeb81b2b8e2d37c93cda4d88787e08e0658291:/src/panels/places/placespanel.cpp diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 8fc81bb32..8bdb18ba2 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -11,32 +11,30 @@ #include "placespanel.h" -#include "dolphinplacesmodelsingleton.h" #include "dolphin_generalsettings.h" #include "dolphin_placespanelsettings.h" -#include "global.h" -#include "views/draganddrophelper.h" +#include "dolphinplacesmodelsingleton.h" #include "settings/dolphinsettingsdialog.h" +#include "views/draganddrophelper.h" #include #include #include -#include #include +#include #include #include +#include #include -#include #include -PlacesPanel::PlacesPanel(QWidget* parent) +PlacesPanel::PlacesPanel(QWidget *parent) : KFilePlacesView(parent) { setDropOnPlaceEnabled(true); - connect(this, &PlacesPanel::urlsDropped, - this, &PlacesPanel::slotUrlsDropped); + connect(this, &PlacesPanel::urlsDropped, this, &PlacesPanel::slotUrlsDropped); setAutoResizeItemsEnabled(false); @@ -49,15 +47,24 @@ PlacesPanel::PlacesPanel(QWidget* parent) connect(m_configureTrashAction, &QAction::triggered, this, &PlacesPanel::slotConfigureTrash); addAction(m_configureTrashAction); + m_openInSplitView = new QAction(QIcon::fromTheme(QStringLiteral("view-right-new")), i18nc("@action:inmenu", "Open in Split View")); + m_openInSplitView->setPriority(QAction::HighPriority); + connect(m_openInSplitView, &QAction::triggered, this, [this]() { + const QUrl url = currentIndex().data(KFilePlacesModel::UrlRole).toUrl(); + Q_EMIT openInSplitViewRequested(url); + }); + + addAction(m_openInSplitView); + connect(this, &PlacesPanel::contextMenuAboutToShow, this, &PlacesPanel::slotContextMenuAboutToShow); - connect(this, &PlacesPanel::iconSizeChanged, this, [this](const QSize &newSize) { + connect(this, &PlacesPanel::iconSizeChanged, this, [](const QSize &newSize) { int iconSize = qMin(newSize.width(), newSize.height()); if (iconSize == 0) { // Don't store 0 size, let's keep -1 for default/small/automatic iconSize = -1; } - PlacesPanelSettings* settings = PlacesPanelSettings::self(); + PlacesPanelSettings *settings = PlacesPanelSettings::self(); settings->setIconSize(iconSize); settings->save(); }); @@ -73,7 +80,7 @@ void PlacesPanel::setUrl(const QUrl &url) KFilePlacesView::setUrl(url); } -QList PlacesPanel::customContextMenuActions() const +QList PlacesPanel::customContextMenuActions() const { return m_customContextMenuActions; } @@ -85,34 +92,27 @@ void PlacesPanel::setCustomContextMenuActions(const QList &actions) void PlacesPanel::proceedWithTearDown() { - Q_ASSERT(m_deviceToTearDown); - - connect(m_deviceToTearDown, &Solid::StorageAccess::teardownDone, - this, &PlacesPanel::slotTearDownDone); - m_deviceToTearDown->teardown(); + if (m_indexToTearDown.isValid()) { + auto *placesModel = static_cast(model()); + placesModel->requestTeardown(m_indexToTearDown); + } else { + qWarning() << "Places entry to tear down is no longer valid"; + } } 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()); setIconSize(QSize(iconSize, iconSize)); } -void PlacesPanel::showEvent(QShowEvent* event) +void PlacesPanel::showEvent(QShowEvent *event) { if (!event->spontaneous() && !model()) { readSettings(); @@ -121,6 +121,7 @@ void PlacesPanel::showEvent(QShowEvent* event) setModel(placesModel); connect(placesModel, &KFilePlacesModel::errorMessage, this, &PlacesPanel::errorMessage); + connect(placesModel, &KFilePlacesModel::teardownDone, this, &PlacesPanel::slotTearDownDone); connect(placesModel, &QAbstractItemModel::rowsInserted, this, &PlacesPanel::slotRowsInserted); connect(placesModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &PlacesPanel::slotRowsAboutToBeRemoved); @@ -135,61 +136,55 @@ void PlacesPanel::showEvent(QShowEvent* event) 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->position().toPoint()); + if (index.isValid()) { + auto *placesModel = static_cast(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); + } } + + KFilePlacesView::dragMoveEvent(event); } void PlacesPanel::slotConfigureTrash() { const QUrl url = currentIndex().data(KFilePlacesModel::UrlRole).toUrl(); - DolphinSettingsDialog* settingsDialog = new DolphinSettingsDialog(url, this); + DolphinSettingsDialog *settingsDialog = new DolphinSettingsDialog(url, this); settingsDialog->setCurrentPage(settingsDialog->trashSettings); settingsDialog->setAttribute(Qt::WA_DeleteOnClose); settingsDialog->show(); } -void PlacesPanel::slotDragActivationTimeout() -{ - if (!m_pendingDragActivation.isValid()) { - return; - } - - auto *placesModel = static_cast(model()); - Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(placesModel->url(m_pendingDragActivation))); -} - -void PlacesPanel::slotUrlsDropped(const QUrl& dest, QDropEvent* event, QWidget* parent) +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()); + } + }); } } @@ -202,6 +197,7 @@ void PlacesPanel::slotContextMenuAboutToShow(const QModelIndex &index, QMenu *me const Solid::Device device = placesModel->deviceForIndex(index); m_configureTrashAction->setVisible(url.scheme() == QLatin1String("trash")); + m_openInSplitView->setVisible(url.isValid()); // show customContextMenuActions only on the view's context menu if (!url.isValid() && !device.isValid()) { @@ -225,7 +221,7 @@ void PlacesPanel::slotTearDownRequested(const QModelIndex &index) return; } - m_deviceToTearDown = storageAccess; + m_indexToTearDown = QPersistentModelIndex(index); // disconnect the Solid::StorageAccess::teardownRequested // to prevent emitting PlacesPanel::storageTearDownExternallyRequested @@ -237,44 +233,22 @@ void PlacesPanel::slotTearDownRequested(const QModelIndex &index) void PlacesPanel::slotTearDownRequestedExternally(const QString &udi) { Q_UNUSED(udi); - auto *storageAccess = static_cast(sender()); + auto *storageAccess = static_cast(sender()); Q_EMIT storageTearDownExternallyRequested(storageAccess->filePath()); } -void PlacesPanel::slotTearDownDone(Solid::ErrorType error, const QVariant& errorData) +void PlacesPanel::slotTearDownDone(const QModelIndex &index, Solid::ErrorType error, const QVariant &errorData) { - if (error && errorData.isValid()) { - 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(); - QString errorString; - if (blockingProcesses.isEmpty()) { - errorString = i18n("One or more files on this device are open within an application."); - } else { - QStringList blockingApps; - for (const auto& process : blockingProcesses) { - blockingApps << process.name(); - } - blockingApps.removeDuplicates(); - errorString = xi18np("One or more files on this device are opened in application \"%2\".", - "One or more files on this device are opened in following applications: %2.", - blockingApps.count(), blockingApps.join(i18nc("separator in list of apps blocking device unmount", ", "))); - } - Q_EMIT errorMessage(errorString); - }); - listOpenFilesJob->start(); - } else { - Q_EMIT errorMessage(errorData.toString()); + Q_UNUSED(errorData); // All error handling is currently done in frameworks. + + if (index == m_indexToTearDown) { + if (error == Solid::ErrorType::NoError) { + // No error; it must have been unmounted successfully + Q_EMIT storageTearDownSuccessful(); } - } else { - // No error; it must have been unmounted successfully - Q_EMIT storageTearDownSuccessful(); + m_indexToTearDown = QPersistentModelIndex(); } - disconnect(m_deviceToTearDown, &Solid::StorageAccess::teardownDone, - this, &PlacesPanel::slotTearDownDone); - m_deviceToTearDown = nullptr; } void PlacesPanel::slotRowsInserted(const QModelIndex &parent, int first, int last) @@ -311,3 +285,5 @@ void PlacesPanel::connectDeviceSignals(const QModelIndex &index) connect(storageAccess, &Solid::StorageAccess::teardownRequested, this, &PlacesPanel::slotTearDownRequestedExternally); } + +#include "moc_placespanel.cpp"