Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37873461
en ru br
Репозитории ALT

Группа :: Работа с файлами
Пакет: 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
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin