diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp index b4d28047e9..aea59c7110 100644 --- a/src/kitemviews/kitemlistcontroller.cpp +++ b/src/kitemviews/kitemlistcontroller.cpp @@ -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(); diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp index c4fa1f2ccf..4c9f259861 100644 --- a/src/kitemviews/kitemlistwidget.cpp +++ b/src/kitemviews/kitemlistwidget.cpp @@ -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 ¤t, const QSet &roles) { Q_UNUSED(current) diff --git a/src/kitemviews/kitemlistwidget.h b/src/kitemviews/kitemlistwidget.h index 55d9247190..fdfe5e78a2 100644 --- a/src/kitemviews/kitemlistwidget.h +++ b/src/kitemviews/kitemlistwidget.h @@ -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); diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index 2a28d198ab..b534338ce6 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // #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 itemData{data()}; + if (itemData["iconName"] != wantedIconName) { + itemData.insert("iconName", wantedIconName); + setData(itemData); + invalidateIconCache(); + } + }); + + connect(m_activateSoonAnimation, &QObject::destroyed, this, [originalIconName, this]() { + QHash 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; } diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h index 06bf0529ad..5afadd8cd2 100644 --- a/src/kitemviews/kstandarditemlistwidget.h +++ b/src/kitemviews/kstandarditemlistwidget.h @@ -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 m_activateSoonAnimation; + friend class KStandardItemListWidgetInformant; // Accesses private static methods to be able to // share a common layout calculation };