Commit a0534353 authored by Eugene Popov's avatar Eugene Popov 🇺🇦 Committed by Felix Ernst
Browse files

Fix zooming animation

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
parent e9bd295b
Pipeline #136750 passed with stage
in 2 minutes and 18 seconds
......@@ -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));
......
......@@ -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);
......
......@@ -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
......
......@@ -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 {
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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];
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment