Группа :: Работа с файлами
Пакет: kde5-dolphin
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: alt-fix-unmounting-during-preview-generation.patch
Скачать
Скачать
From 3aa8ddfcaae883848f950603d2c07352efc214b8 Mon Sep 17 00:00:00 2001
From: Aleksei Nikiforov <darktemplar@basealt.ru>
Date: Fri, 27 Mar 2020 10:47:15 +0300
Subject: [PATCH] Fix unmounting during preview generation
Request all preview jobs for specific mount point to stop
and proceed with unmount request only when all such jobs reported stopping.
---
dolphin/src/dolphinmainwindow.cpp | 55 ++++++++++++++++---
dolphin/src/dolphinmainwindow.h | 10 ++++
dolphin/src/dolphintabpage.cpp | 27 +++++++++
dolphin/src/dolphintabpage.h | 7 +++
dolphin/src/dolphintabwidget.cpp | 15 +++++
dolphin/src/dolphintabwidget.h | 12 ++++
dolphin/src/kitemviews/kfileitemlistview.cpp | 10 ++++
dolphin/src/kitemviews/kfileitemlistview.h | 9 +++
.../kitemviews/kfileitemmodelrolesupdater.cpp | 46 ++++++++++++----
.../kitemviews/kfileitemmodelrolesupdater.h | 10 +++-
dolphin/src/views/dolphinview.cpp | 6 ++
dolphin/src/views/dolphinview.h | 12 ++++
12 files changed, 198 insertions(+), 21 deletions(-)
diff --git a/dolphin/src/dolphinmainwindow.cpp b/dolphin/src/dolphinmainwindow.cpp
index 52b3e8d6..28fffb5b 100644
--- a/dolphin/src/dolphinmainwindow.cpp
+++ b/dolphin/src/dolphinmainwindow.cpp
@@ -110,7 +110,10 @@ DolphinMainWindow::DolphinMainWindow() :
m_placesPanel(nullptr),
m_tearDownFromPlacesRequested(false),
m_backAction(nullptr),
- m_forwardAction(nullptr)
+ m_forwardAction(nullptr),
+ m_expectedUnmountSignals(0),
+ m_unmountSignals(0),
+ m_updateTerminalPanel(false)
{
Q_INIT_RESOURCE(dolphin);
@@ -154,6 +157,10 @@ DolphinMainWindow::DolphinMainWindow() :
this, &DolphinMainWindow::tabCountChanged);
connect(m_tabWidget, &DolphinTabWidget::currentUrlChanged,
this, &DolphinMainWindow::updateWindowTitle);
+ // use queued connection to ensure that expected results are counted before signals are processed
+ connect(m_tabWidget, &DolphinTabWidget::preparedToUnmount,
+ this, &DolphinMainWindow::slotStorageTearDownFromPlacesRequestTabFinished,
+ Qt::QueuedConnection);
setCentralWidget(m_tabWidget);
setupActions();
@@ -1325,12 +1332,36 @@ void DolphinMainWindow::slotStorageTearDownFromPlacesRequested(const QString& mo
setViewsToHomeIfMountPathOpen(mountPath);
});
- if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
- m_tearDownFromPlacesRequested = true;
- m_terminalPanel->goHome();
- // m_placesPanel->proceedWithTearDown() will be called in slotTerminalDirectoryChanged
- } else {
- m_placesPanel->proceedWithTearDown();
+ m_tearDownFromPlacesRequested = true;
+ m_updateTerminalPanel = (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath));
+ m_unmountSignals = 0;
+ m_expectedUnmountSignals = m_tabWidget->prepareToUnmount(mountPath);
+
+ if (m_expectedUnmountSignals == 0) {
+ if (m_updateTerminalPanel) {
+ m_terminalPanel->goHome();
+ // m_placesPanel->proceedWithTearDown() will be called in slotTerminalDirectoryChanged
+ } else {
+ m_placesPanel->proceedWithTearDown();
+ }
+ }
+}
+
+void DolphinMainWindow::slotStorageTearDownFromPlacesRequestTabFinished()
+{
+ if ((m_expectedUnmountSignals == 0) || (m_unmountSignals == m_expectedUnmountSignals)) {
+ return;
+ }
+
+ ++m_unmountSignals;
+
+ if (m_unmountSignals == m_expectedUnmountSignals) {
+ if (m_terminalPanel && m_updateTerminalPanel) {
+ m_terminalPanel->goHome();
+ // m_placesPanel->proceedWithTearDown() will be called in slotTerminalDirectoryChanged
+ } else {
+ m_placesPanel->proceedWithTearDown();
+ }
}
}
@@ -1340,8 +1371,14 @@ void DolphinMainWindow::slotStorageTearDownExternallyRequested(const QString& mo
setViewsToHomeIfMountPathOpen(mountPath);
});
- if (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath)) {
- m_tearDownFromPlacesRequested = false;
+ m_tearDownFromPlacesRequested = false;
+ m_updateTerminalPanel = (m_terminalPanel && m_terminalPanel->currentWorkingDirectory().startsWith(mountPath));
+ m_unmountSignals = 0;
+ m_expectedUnmountSignals = 0; // Don't count expected signals since dolphin doesn't do anything with it anyway
+
+ m_tabWidget->prepareToUnmount(mountPath);
+
+ if (m_updateTerminalPanel) {
m_terminalPanel->goHome();
}
}
diff --git a/dolphin/src/dolphinmainwindow.h b/dolphin/src/dolphinmainwindow.h
index 3a29d1c0..c627ee55 100644
--- a/dolphin/src/dolphinmainwindow.h
+++ b/dolphin/src/dolphinmainwindow.h
@@ -511,6 +511,12 @@ private Q_SLOTS:
*/
void slotStorageTearDownFromPlacesRequested(const QString& mountPath);
+ /**
+ * This slot is called when the user requested to unmount a removable media
+ * from the places menu and tab finished preparing for unmounting
+ */
+ void slotStorageTearDownFromPlacesRequestTabFinished();
+
/**
* This slot is called when the user requested to unmount a removable media
* _not_ from the dolphin's places menu (from the notification area for e.g.)
@@ -658,6 +664,10 @@ private:
KIO::OpenUrlJob *m_lastHandleUrlOpenJob;
+ int m_expectedUnmountSignals;
+ int m_unmountSignals;
+ bool m_updateTerminalPanel;
+
TerminalPanel* m_terminalPanel;
PlacesPanel* m_placesPanel;
bool m_tearDownFromPlacesRequested;
--- a/dolphin/src/dolphintabpage.cpp
+++ b/dolphin/src/dolphintabpage.cpp
@@ -10,6 +10,7 @@
#include "dolphin_generalsettings.h"
#include "dolphinviewcontainer.h"
+#include <QStorageInfo>
#include <QGridLayout>
#include <QStyle>
#include <QVariantAnimation>
@@ -405,6 +406,29 @@ void DolphinTabPage::slotAnimationValueC
}
+int DolphinTabPage::prepareToUnmount(const QString& mountPath)
+{
+ int result = 0;
+
+ if (m_primaryViewContainer) {
+ QStorageInfo storageInfo(m_primaryViewContainer->view()->url().toLocalFile());
+ if (storageInfo.rootPath() == mountPath) {
+ m_primaryViewContainer->view()->prepareToUnmount();
+ ++result;
+ }
+ }
+
+ if (m_secondaryViewContainer) {
+ QStorageInfo storageInfo(m_secondaryViewContainer->view()->url().toLocalFile());
+ if (storageInfo.rootPath() == mountPath) {
+ m_secondaryViewContainer->view()->prepareToUnmount();
+ ++result;
+ }
+ }
+
+ return result;
+}
+
void DolphinTabPage::slotViewActivated()
{
const DolphinView* oldActiveView = activeViewContainer()->view();
@@ -472,6 +496,9 @@ DolphinViewContainer* DolphinTabPage::cr
connect(view, &DolphinView::toggleActiveViewRequested,
this, &DolphinTabPage::switchActiveView);
+ connect(view, &DolphinView::preparedToUnmount,
+ this, &DolphinTabPage::preparedToUnmount);
+
return container;
}
diff --git a/dolphin/src/dolphintabpage.h b/dolphin/src/dolphintabpage.h
index 57a0c334..525d35f9 100644
--- a/dolphin/src/dolphintabpage.h
+++ b/dolphin/src/dolphintabpage.h
@@ -134,10 +134,17 @@ public:
*/
void setActive(bool active);
+ /**
+ * Is called when some partition is going to be unmounted
+ * to to prevent blocking pending unmounting
+ */
+ int prepareToUnmount(const QString& mountPath);
+
Q_SIGNALS:
void activeViewChanged(DolphinViewContainer* viewContainer);
void activeViewUrlChanged(const QUrl& url);
void splitterMoved(int pos, int index);
+ void preparedToUnmount();
private Q_SLOTS:
/**
diff --git a/dolphin/src/dolphintabwidget.cpp b/dolphin/src/dolphintabwidget.cpp
--- a/dolphin/src/dolphintabwidget.cpp
+++ b/dolphin/src/dolphintabwidget.cpp
@@ -162,6 +162,8 @@ void DolphinTabWidget::openNewTab(const
this, &DolphinTabWidget::activeViewChanged);
connect(tabPage, &DolphinTabPage::activeViewUrlChanged,
this, &DolphinTabWidget::tabUrlChanged);
+ connect(tabPage, &DolphinTabPage::preparedToUnmount,
+ this, &DolphinTabWidget::preparedToUnmount);
connect(tabPage->activeViewContainer(), &DolphinViewContainer::captionChanged, this, [this, tabPage]() {
const int tabIndex = indexOf(tabPage);
Q_ASSERT(tabIndex >= 0);
@@ -347,6 +349,19 @@ void DolphinTabWidget::moveToInactiveSpl
}
}
+int DolphinTabWidget::prepareToUnmount(const QString& mountPath)
+{
+ int result = 0;
+
+ const int tabCount = count();
+ for (int i = 0; i < tabCount; ++i) {
+ DolphinTabPage* tabPage = tabPageAt(i);
+ result += tabPage->prepareToUnmount(mountPath);
+ }
+
+ return result;
+}
+
void DolphinTabWidget::detachTab(int index)
{
Q_ASSERT(index >= 0);
diff --git a/dolphin/src/dolphintabwidget.h b/dolphin/src/dolphintabwidget.h
index e0146d7c..db5d8a4d 100644
--- a/dolphin/src/dolphintabwidget.h
+++ b/dolphin/src/dolphintabwidget.h
@@ -65,6 +65,12 @@ public:
*/
bool isUrlOpen(const QUrl& url) const;
+ /**
+ * Is called when some partition is going to be unmounted
+ * to to prevent blocking pending unmounting
+ */
+ int prepareToUnmount(const QString& mountPath);
+
Q_SIGNALS:
/**
* Is emitted when the active view has been changed, by changing the current
@@ -90,6 +96,12 @@ Q_SIGNALS:
*/
void currentUrlChanged(const QUrl& url);
+ /**
+ * Is emitted when prepareToUnmount() is called
+ * and all preparations are finished
+ */
+ void preparedToUnmount();
+
public Q_SLOTS:
/**
* Opens a new view with the current URL that is part of a tab and activates
diff --git a/dolphin/src/kitemviews/kfileitemlistview.cpp b/dolphin/src/kitemviews/kfileitemlistview.cpp
index adcc2d79..9e6bfa41 100644
--- a/dolphin/src/kitemviews/kfileitemlistview.cpp
+++ b/dolphin/src/kitemviews/kfileitemlistview.cpp
@@ -220,6 +220,15 @@ void KFileItemListView::setHoverSequenceState(const QUrl& itemUrl, int seqIdx)
}
}
+void KFileItemListView::prepareToUnmount()
+{
+ if (m_modelRolesUpdater->isPreviewJobRunning()) {
+ m_modelRolesUpdater->setPaused(true, false);
+ } else {
+ Q_EMIT preparedToUnmount();
+ }
+}
+
KItemListWidgetCreatorBase* KFileItemListView::defaultWidgetCreator() const
{
return new KItemListWidgetCreator<KFileItemListWidget>();
@@ -269,6 +278,7 @@ void KFileItemListView::onModelChanged(KItemModelBase* current, KItemModelBase*
m_modelRolesUpdater = new KFileItemModelRolesUpdater(static_cast<KFileItemModel*>(current), this);
m_modelRolesUpdater->setIconSize(availableIconSize());
m_modelRolesUpdater->setScanDirectories(scanDirectories());
+ connect(m_modelRolesUpdater, &KFileItemModelRolesUpdater::previewJobFinished, this, &KFileItemListView::preparedToUnmount);
applyRolesToModel();
}
diff --git a/dolphin/src/kitemviews/kfileitemlistview.h b/dolphin/src/kitemviews/kfileitemlistview.h
index bfbe85d1..931ab443 100644
--- a/dolphin/src/kitemviews/kfileitemlistview.h
+++ b/dolphin/src/kitemviews/kfileitemlistview.h
@@ -90,6 +90,15 @@ public:
*/
void setHoverSequenceState(const QUrl& itemUrl, int seqIdx);
+ /**
+ * Is called when some partition is going to be unmounted
+ * to to prevent blocking pending unmounting
+ */
+ void prepareToUnmount();
+
+Q_SIGNALS:
+ void preparedToUnmount();
+
protected:
KItemListWidgetCreatorBase* defaultWidgetCreator() const override;
void initializeItemListWidget(KItemListWidget* item) override;
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
index 978f5df6..308ce062 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -142,7 +142,7 @@ void KFileItemModelRolesUpdater::setIconSize(const QSize& size)
{
if (size != m_iconSize) {
m_iconSize = size;
- if (m_state == Paused) {
+ if (isPaused()) {
m_iconSizeChangedDuringPausing = true;
} else if (m_previewShown) {
// An icon size change requires the regenerating of
@@ -227,15 +227,19 @@ void KFileItemModelRolesUpdater::setEnabledPlugins(const QStringList& list)
}
}
-void KFileItemModelRolesUpdater::setPaused(bool paused)
+void KFileItemModelRolesUpdater::setPaused(bool paused, bool immediate)
{
- if (paused == (m_state == Paused)) {
+ if (paused == isPaused()) {
return;
}
if (paused) {
- m_state = Paused;
- killPreviewJob();
+ if (immediate) {
+ m_state = Paused;
+ killPreviewJob();
+ } else {
+ m_state = PausePending;
+ }
} else {
const bool updatePreviews = (m_iconSizeChangedDuringPausing && m_previewShown) ||
m_previewChangedDuringPausing;
@@ -290,7 +294,7 @@ void KFileItemModelRolesUpdater::setRoles(const QSet<QByteArray>& roles)
}
#endif
- if (m_state == Paused) {
+ if (isPaused()) {
m_rolesChangedDuringPausing = true;
} else {
startUpdating();
@@ -305,7 +309,12 @@ QSet<QByteArray> KFileItemModelRolesUpdater::roles() const
bool KFileItemModelRolesUpdater::isPaused() const
{
- return m_state == Paused;
+ return (m_state == Paused) || (m_state == PausePending);
+}
+
+bool KFileItemModelRolesUpdater::isPreviewJobRunning() const
+{
+ return m_state == PreviewJobRunning;
}
QStringList KFileItemModelRolesUpdater::enabledPlugins() const
@@ -529,6 +538,12 @@ void KFileItemModelRolesUpdater::slotSortRoleChanged(const QByteArray& current,
void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPixmap& pixmap)
{
+ if (m_state == PausePending) {
+ m_state = Paused;
+ killPreviewJob();
+ Q_EMIT previewJobFinished();
+ }
+
if (m_state != PreviewJobRunning) {
return;
}
@@ -574,6 +589,12 @@ void KFileItemModelRolesUpdater::slotGotPreview(const KFileItem& item, const QPi
void KFileItemModelRolesUpdater::slotPreviewFailed(const KFileItem& item)
{
+ if (m_state == PausePending) {
+ m_state = Paused;
+ killPreviewJob();
+ Q_EMIT previewJobFinished();
+ }
+
if (m_state != PreviewJobRunning) {
return;
}
@@ -600,6 +621,11 @@ void KFileItemModelRolesUpdater::slotPreviewJobFinished()
{
m_previewJob = nullptr;
+ if (m_state == PausePending) {
+ m_state = Paused;
+ Q_EMIT previewJobFinished();
+ }
+
if (m_state != PreviewJobRunning) {
return;
}
@@ -902,7 +928,7 @@ void KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived(const QStrin
void KFileItemModelRolesUpdater::startUpdating()
{
- if (m_state == Paused) {
+ if (isPaused()) {
return;
}
@@ -1164,7 +1190,7 @@ void KFileItemModelRolesUpdater::killHoverSequencePreviewJob()
void KFileItemModelRolesUpdater::updateChangedItems()
{
- if (m_state == Paused) {
+ if (isPaused()) {
return;
}
@@ -1372,7 +1398,7 @@ void KFileItemModelRolesUpdater::slotOverlaysChanged(const QUrl& url, const QStr
void KFileItemModelRolesUpdater::updateAllPreviews()
{
- if (m_state == Paused) {
+ if (isPaused()) {
m_previewChangedDuringPausing = true;
} else {
m_finishedItems.clear();
diff --git a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
index a03ab513..67bb15c5 100644
--- a/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/dolphin/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -117,7 +117,7 @@ public:
* State changes during pauses like changing the icon size or the preview-shown
* will be remembered and handled after unpausing.
*/
- void setPaused(bool paused);
+ void setPaused(bool paused, bool immediate = true);
bool isPaused() const;
/**
@@ -174,6 +174,11 @@ public:
*/
void setHoverSequenceState(const QUrl& itemUrl, int seqIdx);
+ bool isPreviewJobRunning() const;
+
+Q_SIGNALS:
+ void previewJobFinished();
+
private Q_SLOTS:
void slotItemsInserted(const KItemRangeList& itemRanges);
void slotItemsRemoved(const KItemRangeList& itemRanges);
@@ -343,7 +348,8 @@ private:
Paused,
ResolvingSortRole,
ResolvingAllRoles,
- PreviewJobRunning
+ PreviewJobRunning,
+ PausePending
};
State m_state;
diff --git a/dolphin/src/views/dolphinview.cpp b/dolphin/src/views/dolphinview.cpp
--- a/dolphin/src/views/dolphinview.cpp
+++ b/dolphin/src/views/dolphinview.cpp
@@ -192,6 +192,7 @@ DolphinView::DolphinView(const QUrl& url
this, &DolphinView::updatePlaceholderLabel);
m_view->installEventFilter(this);
+ connect(m_view, &KFileItemListView::preparedToUnmount, this, &DolphinView::preparedToUnmount);
connect(m_view, &DolphinItemListView::sortOrderChanged,
this, &DolphinView::slotSortOrderChangedByHeader);
connect(m_view, &DolphinItemListView::sortRoleChanged,
@@ -1657,6 +1658,11 @@ void DolphinView::updateViewState()
}
}
+void DolphinView::prepareToUnmount()
+{
+ m_view->prepareToUnmount();
+}
+
void DolphinView::hideToolTip(const ToolTipManager::HideBehavior behavior)
{
if (GeneralSettings::showToolTips()) {
diff --git a/dolphin/src/views/dolphinview.h b/dolphin/src/views/dolphinview.h
index e4d77983..e8a26e6c 100644
--- a/dolphin/src/views/dolphinview.h
+++ b/dolphin/src/views/dolphinview.h
@@ -315,6 +315,12 @@ public:
*/
void hideToolTip(const ToolTipManager::HideBehavior behavior = ToolTipManager::HideBehavior::Later);
+ /**
+ * Is called when some partition is going to be unmounted
+ * to to prevent blocking pending unmounting
+ */
+ void prepareToUnmount();
+
public Q_SLOTS:
/**
* Changes the directory to \a url. If the current directory is equal to
@@ -595,6 +601,12 @@ Q_SIGNALS:
void fileItemsChanged(const KFileItemList &changedFileItems);
+ /**
+ * Is emitted when prepareToUnmount() is called
+ * and all preparations are finished
+ */
+ void preparedToUnmount();
+
protected:
/** Changes the zoom level if Control is pressed during a wheel event. */
void wheelEvent(QWheelEvent* event) override;
--
2.32.0