[PATCH] KFilePlacesView: Show busy indicator while emptying trash
authorKai Uwe Broulik <kde@privat.broulik.de>
Thu, 1 May 2025 17:02:48 +0000 (19:02 +0200)
committerAurélien COUDERC <coucouf@debian.org>
Sun, 8 Jun 2025 12:42:29 +0000 (14:42 +0200)
Provide some feedback to the user in case it's taking a bit.

Gbp-Pq: Name upstream_3e6175e4_KFilePlacesView-Show-busy-indicator-while-emptying-trash.patch

src/filewidgets/kfileplacesview.cpp
src/filewidgets/kfileplacesview_p.h

index d2488ec32d276be3bc216b6efc4c6c3e417eeb80..30ca95f22109b7cfd51d6a955672e5d6b042c7cd 100644 (file)
@@ -154,7 +154,8 @@ void KFilePlacesViewDelegate::paint(QPainter *painter, const QStyleOptionViewIte
     QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter);
 
     const auto accessibility = placesModel->deviceAccessibility(index);
-    const bool isBusy = (accessibility == KFilePlacesModel::SetupInProgress || accessibility == KFilePlacesModel::TeardownInProgress);
+    const bool isBusy = (accessibility == KFilePlacesModel::SetupInProgress || accessibility == KFilePlacesModel::TeardownInProgress)
+        || (m_emptyingTrashIndex.isValid() && m_emptyingTrashIndex == index);
 
     QIcon actionIcon;
     if (isBusy) {
@@ -458,6 +459,16 @@ void KFilePlacesViewDelegate::setHoveredAction(const QModelIndex &index)
     m_hoveredAction = index;
 }
 
+QModelIndex KFilePlacesViewDelegate::emptyingTrashIndex() const
+{
+    return m_emptyingTrashIndex;
+}
+
+void KFilePlacesViewDelegate::setEmptyingTrashIndex(const QModelIndex &index)
+{
+    m_emptyingTrashIndex = index;
+}
+
 bool KFilePlacesViewDelegate::pointIsHeaderArea(const QPoint &pos) const
 {
     // we only accept drag events starting from item body, ignore drag request from header
@@ -769,9 +780,11 @@ public:
     void itemAppearUpdate(qreal value);
     void itemDisappearUpdate(qreal value);
     void enableSmoothItemResizing();
-    void slotEmptyTrash();
+    void slotEmptyTrash(const QModelIndex &index);
 
     void deviceBusyAnimationValueChanged(const QVariant &value);
+    void startOrStopBusyAnimation();
+    void setEmptyingTrashIndex(const QModelIndex &index);
 
     KFilePlacesView *const q;
 
@@ -1123,8 +1136,9 @@ void KFilePlacesViewPrivate::writeConfig()
     cg.sync();
 }
 
-void KFilePlacesViewPrivate::slotEmptyTrash()
+void KFilePlacesViewPrivate::slotEmptyTrash(const QModelIndex &index)
 {
+    QPersistentModelIndex persistentIndex(index);
     auto *parentWindow = q->window();
 
     using AskIface = KIO::AskUserActionInterface;
@@ -1132,9 +1146,26 @@ void KFilePlacesViewPrivate::slotEmptyTrash()
                                                     AskIface::EmptyTrash,
                                                     AskIface::DefaultConfirmation,
                                                     parentWindow);
+    QObject::connect(emptyTrashJob, &KIO::DeleteOrTrashJob::started, q, [this, persistentIndex] {
+        m_delegate->setEmptyingTrashIndex(persistentIndex);
+        startOrStopBusyAnimation();
+    });
+    QObject::connect(emptyTrashJob, &KJob::finished, q, [this] {
+        m_delegate->setEmptyingTrashIndex({});
+        startOrStopBusyAnimation();
+    });
     emptyTrashJob->start();
 }
 
+void KFilePlacesViewPrivate::startOrStopBusyAnimation()
+{
+    if (!m_busyDevices.isEmpty() || m_delegate->emptyingTrashIndex().isValid()) {
+        m_deviceBusyAnimation.start();
+    } else {
+        m_deviceBusyAnimation.stop();
+    }
+}
+
 void KFilePlacesView::contextMenuEvent(QContextMenuEvent *event)
 {
     KFilePlacesModel *placesModel = qobject_cast<KFilePlacesModel *>(model());
@@ -1327,7 +1358,7 @@ void KFilePlacesView::contextMenuEvent(QContextMenuEvent *event)
 
     if (result) {
         if (result == emptyTrash) {
-            d->slotEmptyTrash();
+            d->slotEmptyTrash(index);
 
         } else if (result == eject) {
             placesModel->requestEject(index);
@@ -2136,6 +2167,9 @@ void KFilePlacesViewPrivate::deviceBusyAnimationValueChanged(const QVariant &val
     for (const auto &idx : std::as_const(m_busyDevices)) {
         q->update(idx);
     }
+    if (m_delegate->emptyingTrashIndex().isValid()) {
+        q->update(m_delegate->emptyingTrashIndex());
+    }
 }
 
 void KFilePlacesView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles)
@@ -2156,12 +2190,7 @@ void KFilePlacesView::dataChanged(const QModelIndex &topLeft, const QModelIndex
         }
 
         d->m_busyDevices = busyDevices;
-
-        if (busyDevices.isEmpty()) {
-            d->m_deviceBusyAnimation.stop();
-        } else {
-            d->m_deviceBusyAnimation.start();
-        }
+        d->startOrStopBusyAnimation();
     }
 }
 
index 694d555e01a357346708f4de498ba34fd26d7aeb..b51516dce24ecac3096bdf4e6bece6104754f327 100644 (file)
@@ -58,6 +58,9 @@ public:
     void setHoveredHeaderArea(const QModelIndex &index);
     void setHoveredAction(const QModelIndex &index);
 
+    QModelIndex emptyingTrashIndex() const;
+    void setEmptyingTrashIndex(const QModelIndex &index);
+
     qreal contentsOpacity(const QModelIndex &index) const;
 
     bool pointIsHeaderArea(const QPoint &pos) const;
@@ -100,6 +103,7 @@ private:
     qreal m_disappearingOpacity;
 
     qreal m_busyAnimationRotation = 0.0;
+    QPersistentModelIndex m_emptyingTrashIndex;
 
     bool m_showHoverIndication;
     QPersistentModelIndex m_hoveredHeaderArea;