]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Fix zooming animation
authorEugene Popov <popov895@ukr.net>
Sun, 13 Feb 2022 12:16:34 +0000 (12:16 +0000)
committerFelix Ernst <fe.a.ernst@gmail.com>
Sun, 13 Feb 2022 12:16:34 +0000 (12:16 +0000)
Current implementation of the zooming animation is a bit buggy.
This MR fixes the following issues:
* in the Icon view mode, the icons sometimes "jump"
* in the Compact view mode, the labels sometimes are cut off

BUG: 449179

src/kitemviews/kitemlistview.cpp
src/kitemviews/kitemlistwidget.cpp
src/kitemviews/kitemlistwidget.h
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/kstandarditemlistwidget.h
src/kitemviews/private/kitemlistviewanimation.cpp
src/kitemviews/private/kitemlistviewanimation.h

index 86583db1ec958a25ed5b3fa7e1ea3febec725f76..fa76c3b00b12a45c09379b643673515a0608cab0 100644 (file)
@@ -1462,8 +1462,7 @@ void KItemListView::slotAnimationFinished(QGraphicsWidget* widget,
     KItemListWidget* itemListWidget = qobject_cast<KItemListWidget*>(widget);
     Q_ASSERT(itemListWidget);
 
-    switch (type) {
-    case KItemListViewAnimation::DeleteAnimation: {
+    if (type == KItemListViewAnimation::DeleteAnimation) {
         // As we recycle the widget in this case it is important to assure that no
         // other animation has been started. This is a convention in KItemListView and
         // not a requirement defined by KItemListViewAnimation.
@@ -1474,22 +1473,13 @@ void KItemListView::slotAnimationFinished(QGraphicsWidget* widget,
         // been finished.
         recycleGroupHeaderForWidget(itemListWidget);
         widgetCreator()->recycle(itemListWidget);
-        break;
-    }
-
-    case KItemListViewAnimation::CreateAnimation:
-    case KItemListViewAnimation::MovingAnimation:
-    case KItemListViewAnimation::ResizeAnimation: {
+    } else {
         const int index = itemListWidget->index();
         const bool invisible = (index < m_layouter->firstVisibleIndex()) ||
                                (index > m_layouter->lastVisibleIndex());
         if (invisible && !m_animation->isStarted(itemListWidget)) {
             recycleWidget(itemListWidget);
         }
-        break;
-    }
-
-    default: break;
     }
 }
 
@@ -1904,6 +1894,15 @@ void KItemListView::doLayout(LayoutAnimationHint hint, int changedIndex, int cha
             }
         }
 
+        const int newIconSize = widget->styleOption().iconSize;
+        if (widget->iconSize() != newIconSize) {
+            if (animate) {
+                m_animation->start(widget, KItemListViewAnimation::IconResizeAnimation, newIconSize);
+            } else {
+                widget->setIconSize(newIconSize);
+            }
+        }
+
         // Updating the cell-information must be done as last step: The decision whether the
         // moving-animation should be started at all is based on the previous cell-information.
         const Cell cell(m_layouter->itemColumn(i), m_layouter->itemRow(i));
index 79ffee2102c8d89134da1e4fdf89a1cd6022cc77..f729f0239a5325fe06373ac71c7284e07d307ef4 100644 (file)
@@ -47,7 +47,8 @@ KItemListWidget::KItemListWidget(KItemListWidgetInformant* informant, QGraphicsI
     m_hoverAnimation(nullptr),
     m_hoverSequenceIndex(0),
     m_selectionToggle(nullptr),
-    m_editedRole()
+    m_editedRole(),
+    m_iconSize(-1)
 {
     connect(&m_hoverSequenceTimer, &QTimer::timeout, this, &KItemListWidget::slotHoverSequenceTimerTimeout);
 }
@@ -368,6 +369,20 @@ QByteArray KItemListWidget::editedRole() const
     return m_editedRole;
 }
 
+void KItemListWidget::setIconSize(int iconSize)
+{
+    if (m_iconSize != iconSize) {
+        const int previousIconSize = m_iconSize;
+        m_iconSize = iconSize;
+        iconSizeChanged(iconSize, previousIconSize);
+    }
+}
+
+int KItemListWidget::iconSize() const
+{
+    return m_iconSize;
+}
+
 bool KItemListWidget::contains(const QPointF& point) const
 {
     if (!QGraphicsWidget::contains(point)) {
@@ -451,8 +466,12 @@ void KItemListWidget::leadingPaddingChanged(qreal width)
 void KItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
                                          const KItemListStyleOption& previous)
 {
-    Q_UNUSED(current)
     Q_UNUSED(previous)
+
+    // set the initial value of m_iconSize if not set
+    if (m_iconSize == -1) {
+        m_iconSize = current.iconSize;
+    }
 }
 
 void KItemListWidget::currentChanged(bool current)
@@ -487,6 +506,12 @@ void KItemListWidget::editedRoleChanged(const QByteArray& current, const QByteAr
     Q_UNUSED(previous)
 }
 
+void KItemListWidget::iconSizeChanged(int current, int previous)
+{
+    Q_UNUSED(current)
+    Q_UNUSED(previous)
+}
+
 void KItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
 {
     QGraphicsWidget::resizeEvent(event);
index 0b82266c43b87a704dc727d3dc590f2b9af4851a..517f7e04986d66ec633321345237ff2b2ebd2586 100644 (file)
@@ -53,6 +53,8 @@ class DOLPHIN_EXPORT KItemListWidget : public QGraphicsWidget
 {
     Q_OBJECT
 
+    Q_PROPERTY(int iconSize READ iconSize WRITE setIconSize)
+
 public:
     KItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent);
     ~KItemListWidget() override;
@@ -128,6 +130,13 @@ public:
     void setEditedRole(const QByteArray& role);
     QByteArray editedRole() const;
 
+    /**
+     * Contains the actual icon size used to draw the icon.
+     * Also used during icon resizing animation.
+     */
+    void setIconSize(int iconSize);
+    int iconSize() const;
+
     /**
      * @return True if \a point is inside KItemListWidget::hoverRect(),
      *         KItemListWidget::textRect(), KItemListWidget::selectionToggleRect()
@@ -196,6 +205,7 @@ protected:
     virtual void alternateBackgroundChanged(bool enabled);
     virtual void siblingsInformationChanged(const QBitArray& current, const QBitArray& previous);
     virtual void editedRoleChanged(const QByteArray& current, const QByteArray& previous);
+    virtual void iconSizeChanged(int current, int previous);
     void resizeEvent(QGraphicsSceneResizeEvent* event) override;
     void clearHoverCache();
 
@@ -263,6 +273,7 @@ private:
     KItemListSelectionToggle* m_selectionToggle;
 
     QByteArray m_editedRole;
+    int m_iconSize;
 };
 
 inline const KItemListWidgetInformant* KItemListWidget::informant() const
index 668382cd519f15a2ba6504ea27d381dcfc049164..585a96fbf0d1380f45aa5a607cc3cc2e591f1c15 100644 (file)
@@ -532,12 +532,11 @@ QRectF KStandardItemListWidget::selectionToggleRect() const
 {
     const_cast<KStandardItemListWidget*>(this)->triggerCacheRefreshing();
 
-    const int iconHeight = styleOption().iconSize;
-
+    const int widgetIconSize = iconSize();
     int toggleSize = KIconLoader::SizeSmall;
-    if (iconHeight >= KIconLoader::SizeEnormous) {
+    if (widgetIconSize >= KIconLoader::SizeEnormous) {
         toggleSize = KIconLoader::SizeMedium;
-    } else if (iconHeight >= KIconLoader::SizeLarge) {
+    } else if (widgetIconSize >= KIconLoader::SizeLarge) {
         toggleSize = KIconLoader::SizeSmallMedium;
     }
 
@@ -736,8 +735,8 @@ void KStandardItemListWidget::leadingPaddingChanged(qreal padding) {
 void KStandardItemListWidget::styleOptionChanged(const KItemListStyleOption& current,
                                              const KItemListStyleOption& previous)
 {
-    Q_UNUSED(current)
-    Q_UNUSED(previous)
+    KItemListWidget::styleOptionChanged(current, previous);
+
     updateAdditionalInfoTextColor();
     m_dirtyLayout = true;
 }
@@ -833,6 +832,15 @@ void KStandardItemListWidget::editedRoleChanged(const QByteArray& current, const
     m_roleEditor->setFocus();
 }
 
+void KStandardItemListWidget::iconSizeChanged(int current, int previous)
+{
+    KItemListWidget::iconSizeChanged(current, previous);
+
+    invalidateIconCache();
+    triggerCacheRefreshing();
+    update();
+}
+
 void KStandardItemListWidget::resizeEvent(QGraphicsSceneResizeEvent* event)
 {
     if (m_roleEditor) {
@@ -944,13 +952,13 @@ void KStandardItemListWidget::updateExpansionArea()
         const QHash<QByteArray, QVariant> values = data();
         const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt();
         if (expandedParentsCount >= 0) {
-            const KItemListStyleOption& option = styleOption();
+            const int widgetIconSize = iconSize();
             const qreal widgetHeight = size().height();
-            const qreal inc = (widgetHeight - option.iconSize) / 2;
+            const qreal inc = (widgetHeight - widgetIconSize) / 2;
             const qreal x = expandedParentsCount * widgetHeight + inc;
             const qreal y = inc;
             const qreal xPadding = m_highlightEntireRow ? leadingPadding() : 0;
-            m_expansionArea = QRectF(xPadding + x, y, option.iconSize, option.iconSize);
+            m_expansionArea = QRectF(xPadding + x, y, widgetIconSize, widgetIconSize);
             return;
         }
     }
@@ -968,8 +976,9 @@ void KStandardItemListWidget::updatePixmapCache()
     const KItemListStyleOption& option = styleOption();
     const qreal padding = option.padding;
 
-    const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : option.iconSize;
-    const int maxIconHeight = option.iconSize;
+    const int widgetIconSize = iconSize();
+    const int maxIconWidth = iconOnTop ? widgetSize.width() - 2 * padding : widgetIconSize;
+    const int maxIconHeight = widgetIconSize;
 
     const QHash<QByteArray, QVariant> values = data();
 
@@ -1212,7 +1221,6 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
     const KItemListStyleOption& option = styleOption();
     const qreal padding = option.padding;
     const qreal maxWidth = size().width() - 2 * padding;
-    const qreal widgetHeight = size().height();
     const qreal lineSpacing = m_customizedFontMetrics.lineSpacing();
 
     // Initialize properties for the "text" role. It will be used as anchor
@@ -1266,12 +1274,8 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
     layout.endLayout();
 
     // Use one line for each additional information
-    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
     nameTextInfo->staticText.setTextWidth(maxWidth);
-    nameTextInfo->pos = QPointF(padding, widgetHeight -
-                                         nameHeight -
-                                         additionalRolesCount * lineSpacing -
-                                         padding);
+    nameTextInfo->pos = QPointF(padding, iconSize() + 2 * padding);
     m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2,
                         nameTextInfo->pos.y(),
                         nameWidth,
@@ -1336,10 +1340,9 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
     const qreal widgetHeight = size().height();
     const qreal lineSpacing = m_customizedFontMetrics.lineSpacing();
     const qreal textLinesHeight = qMax(visibleRoles().count(), 1) * lineSpacing;
-    const int scaledIconSize = (textLinesHeight < option.iconSize) ? widgetHeight - 2 * option.padding : option.iconSize;
 
     qreal maximumRequiredTextWidth = 0;
-    const qreal x = option.padding * 3 + scaledIconSize;
+    const qreal x = option.padding * 3 + iconSize();
     qreal y = qRound((widgetHeight - textLinesHeight) / 2);
     const qreal maxWidth = size().width() - x - option.padding;
     for (const QByteArray& role : qAsConst(m_sortedVisibleRoles)) {
@@ -1379,11 +1382,10 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache()
     const QHash<QByteArray, QVariant> values = data();
 
     const qreal widgetHeight = size().height();
-    const int scaledIconSize = widgetHeight - 2 * option.padding;
     const int fontHeight = m_customizedFontMetrics.height();
 
     const qreal columnWidthInc = columnPadding(option);
-    qreal firstColumnInc = scaledIconSize;
+    qreal firstColumnInc = iconSize();
     if (m_supportsItemExpanding) {
         firstColumnInc += (m_expansionArea.left() + m_expansionArea.right() + widgetHeight) / 2;
     } else {
index 3edec0db55c8e75d4ddf6f0cd9004fbc7787a6ff..060396a55fcb8ca4d50e288393ece2dc1586be3e 100644 (file)
@@ -177,6 +177,7 @@ protected:
     void selectedChanged(bool selected) override;
     void siblingsInformationChanged(const QBitArray& current, const QBitArray& previous) override;
     void editedRoleChanged(const QByteArray& current, const QByteArray& previous) override;
+    void iconSizeChanged(int current, int previous) override;
     void resizeEvent(QGraphicsSceneResizeEvent* event) override;
     void showEvent(QShowEvent* event) override;
     void hideEvent(QHideEvent* event) override;
index 9dc5fbadaf72cdb1579a5b47bad4666a825b1b21..0c16c8b0a00cc2c81bb2edfff7fc1213a7ca70ca 100644 (file)
@@ -146,7 +146,15 @@ void KItemListViewAnimation::start(QGraphicsWidget* widget, AnimationType type,
         break;
     }
 
+    case IconResizeAnimation: {
+        propertyAnim = new QPropertyAnimation(widget, QByteArrayLiteral("iconSize"));
+        propertyAnim->setDuration(animationDuration);
+        propertyAnim->setEndValue(endValue);
+        break;
+    }
+
     default:
+        Q_UNREACHABLE();
         break;
     }
 
index 8d11dbf89bfdd814d678156abbd4e2b96eef67cd..5e0ebf9824822d077cf751eabf67fa3d4f3a128d 100644 (file)
@@ -32,7 +32,9 @@ public:
         MovingAnimation,
         CreateAnimation,
         DeleteAnimation,
-        ResizeAnimation
+        ResizeAnimation,
+        IconResizeAnimation,
+        AnimationTypeCount
     };
 
     explicit KItemListViewAnimation(QObject* parent = nullptr);
@@ -79,8 +81,6 @@ private Q_SLOTS:
     void slotFinished();
 
 private:
-    enum { AnimationTypeCount = 4 };
-
     Qt::Orientation m_scrollOrientation;
     qreal m_scrollOffset;
     QHash<QGraphicsWidget*, QPropertyAnimation*> m_animation[AnimationTypeCount];