]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Add drag-open animation
authorFelix Ernst <felixernst@zohomail.eu>
Sun, 18 Feb 2024 12:15:18 +0000 (13:15 +0100)
committerFelix Ernst <felixernst@kde.org>
Fri, 23 Feb 2024 10:19:39 +0000 (10:19 +0000)
This commit adds an animation for folders that makes clear that
they will open or expand soon. This is the case when the option to
open folders during drag operations is enabled and a user drags an
item on top of a folder.

The animation goes like this:
- Replace the folder's icon with the "folder-open" icon
- Go back to the folder's original icon
- Replace the folder's icon with the "folder-open" icon once more

src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistwidget.cpp
src/kitemviews/kitemlistwidget.h
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/kstandarditemlistwidget.h

index b4d28047e9d9001523165a89c3fc1b6f2e1a5739..aea59c7110b34091d5e5736d81ec7a128a71014e 100644 (file)
@@ -830,6 +830,7 @@ bool KItemListController::dragMoveEvent(QGraphicsSceneDragDropEvent *event, cons
             if (!m_autoActivationTimer->isActive() && m_autoActivationTimer->interval() >= 0) {
                 m_autoActivationTimer->setProperty("index", index);
                 m_autoActivationTimer->start();
+                newHoveredWidget->startActivateSoonAnimation(m_autoActivationTimer->remainingTime());
             }
         } else {
             m_autoActivationTimer->stop();
index c4fa1f2ccf2691e4bc6b95dca15231e82e2aef34..4c9f259861104b141f6a624b2bda788767ec08f2 100644 (file)
@@ -438,6 +438,11 @@ QPixmap KItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem *option
     return pixmap;
 }
 
+void KItemListWidget::startActivateSoonAnimation(int timeUntilActivation)
+{
+    Q_UNUSED(timeUntilActivation)
+}
+
 void KItemListWidget::dataChanged(const QHash<QByteArray, QVariant> &current, const QSet<QByteArray> &roles)
 {
     Q_UNUSED(current)
index 55d92471907597d983d587f44da44853094fc038..fdfe5e78a2153093cc2edaab72dc21d9bbddf1e2 100644 (file)
@@ -188,6 +188,12 @@ public:
      */
     virtual QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
 
+    /**
+     * Starts an animation that makes clear that the item will be activated soon.
+     * @param timeUntilActivation time in milliseconds until the item will activate
+     */
+    virtual void startActivateSoonAnimation(int timeUntilActivation);
+
 Q_SIGNALS:
     void roleEditingCanceled(int index, const QByteArray &role, const QVariant &value);
     void roleEditingFinished(int index, const QByteArray &role, const QVariant &value);
index 2a28d198ab5ad8d4a6cb9b9631a91e5d46b74b3e..b534338ce6be37ddbc9b8b838ead46edf653d70b 100644 (file)
@@ -24,6 +24,7 @@
 #include <QGraphicsView>
 #include <QPixmapCache>
 #include <QStyleOption>
+#include <QVariantAnimation>
 
 // #define KSTANDARDITEMLISTWIDGET_DEBUG
 
@@ -589,6 +590,50 @@ QPixmap KStandardItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem
     return clippedPixmap;
 }
 
+void KStandardItemListWidget::startActivateSoonAnimation(int timeUntilActivation)
+{
+    if (m_activateSoonAnimation) {
+        m_activateSoonAnimation->stop(); // automatically DeleteWhenStopped
+    }
+
+    m_activateSoonAnimation = new QVariantAnimation{this};
+    m_activateSoonAnimation->setStartValue(0.0);
+    m_activateSoonAnimation->setEndValue(1.0);
+    m_activateSoonAnimation->setDuration(timeUntilActivation);
+
+    const QVariant originalIconName{data()["iconName"]};
+    connect(m_activateSoonAnimation, &QVariantAnimation::valueChanged, this, [originalIconName, this](const QVariant &value) {
+        auto progress = value.toFloat();
+
+        QVariant wantedIconName;
+        if (progress < 0.333) {
+            wantedIconName = "folder-open";
+        } else if (progress < 0.666) {
+            wantedIconName = originalIconName;
+        } else {
+            wantedIconName = "folder-open";
+        }
+
+        QHash<QByteArray, QVariant> itemData{data()};
+        if (itemData["iconName"] != wantedIconName) {
+            itemData.insert("iconName", wantedIconName);
+            setData(itemData);
+            invalidateIconCache();
+        }
+    });
+
+    connect(m_activateSoonAnimation, &QObject::destroyed, this, [originalIconName, this]() {
+        QHash<QByteArray, QVariant> itemData{data()};
+        if (itemData["iconName"] == "folder-open") {
+            itemData.insert("iconName", originalIconName);
+            setData(itemData);
+            invalidateIconCache();
+        }
+    });
+
+    m_activateSoonAnimation->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
 KItemListWidgetInformant *KStandardItemListWidget::createInformant()
 {
     return new KStandardItemListWidgetInformant();
@@ -736,7 +781,9 @@ void KStandardItemListWidget::styleOptionChanged(const KItemListStyleOption &cur
 
 void KStandardItemListWidget::hoveredChanged(bool hovered)
 {
-    Q_UNUSED(hovered)
+    if (!hovered && m_activateSoonAnimation) {
+        m_activateSoonAnimation->stop(); // automatically DeleteWhenStopped
+    }
     m_dirtyLayout = true;
 }
 
index 06bf0529adc44bec6cf492368208b40201dc9ac7..5afadd8cd28ada5a434b1bf4cbffcf7413227ac6 100644 (file)
@@ -17,6 +17,7 @@
 class KItemListRoleEditor;
 class KItemListStyleOption;
 class KItemListView;
+class QVariantAnimation;
 
 /**
  * @brief standard implementation of the ItemList widget informant for use with KStandardItemListView and KStandardItemModel.
@@ -103,6 +104,8 @@ public:
     QRectF expansionToggleRect() const override;
     QRectF selectionToggleRect() const override;
     QPixmap createDragPixmap(const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
+    /** @see KItemListWidget::startActivateSoonAnimation() */
+    void startActivateSoonAnimation(int timeUntilActivation) override;
 
     static KItemListWidgetInformant *createInformant();
 
@@ -282,6 +285,9 @@ private:
     KItemListRoleEditor *m_roleEditor;
     KItemListRoleEditor *m_oldRoleEditor;
 
+    /** @see startActivateSoonAnimation() */
+    QPointer<QVariantAnimation> m_activateSoonAnimation;
+
     friend class KStandardItemListWidgetInformant; // Accesses private static methods to be able to
                                                    // share a common layout calculation
 };