File indexing completed on 2024-05-12 05:47:31
0001 /* 0002 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kitemlistviewanimation.h" 0008 #include "kitemviews/kitemlistview.h" 0009 0010 #include <QPropertyAnimation> 0011 0012 KItemListViewAnimation::KItemListViewAnimation(QObject *parent) 0013 : QObject(parent) 0014 , m_scrollOrientation(Qt::Vertical) 0015 , m_scrollOffset(0) 0016 , m_animation() 0017 { 0018 } 0019 0020 KItemListViewAnimation::~KItemListViewAnimation() 0021 { 0022 for (int type = 0; type < AnimationTypeCount; ++type) { 0023 qDeleteAll(m_animation[type]); 0024 } 0025 } 0026 0027 void KItemListViewAnimation::setScrollOrientation(Qt::Orientation orientation) 0028 { 0029 m_scrollOrientation = orientation; 0030 } 0031 0032 Qt::Orientation KItemListViewAnimation::scrollOrientation() const 0033 { 0034 return m_scrollOrientation; 0035 } 0036 0037 void KItemListViewAnimation::setScrollOffset(qreal offset) 0038 { 0039 const qreal diff = m_scrollOffset - offset; 0040 m_scrollOffset = offset; 0041 0042 // The change of the offset requires that the position of all 0043 // animated QGraphicsWidgets get adjusted. An exception is made 0044 // for the delete animation that should just fade away on the 0045 // existing position. 0046 for (int type = 0; type < AnimationTypeCount; ++type) { 0047 if (type == DeleteAnimation) { 0048 continue; 0049 } 0050 0051 QHashIterator<QGraphicsWidget *, QPropertyAnimation *> it(m_animation[type]); 0052 while (it.hasNext()) { 0053 it.next(); 0054 0055 QGraphicsWidget *widget = it.key(); 0056 QPropertyAnimation *propertyAnim = it.value(); 0057 0058 QPointF currentPos = widget->pos(); 0059 if (m_scrollOrientation == Qt::Vertical) { 0060 currentPos.ry() += diff; 0061 } else { 0062 currentPos.rx() += diff; 0063 } 0064 0065 if (type == MovingAnimation) { 0066 // Stop the animation, calculate the moved start- and end-value 0067 // and restart the animation for the remaining duration. 0068 const int remainingDuration = propertyAnim->duration() - propertyAnim->currentTime(); 0069 0070 const bool block = propertyAnim->signalsBlocked(); 0071 propertyAnim->blockSignals(true); 0072 propertyAnim->stop(); 0073 0074 QPointF endPos = propertyAnim->endValue().toPointF(); 0075 if (m_scrollOrientation == Qt::Vertical) { 0076 endPos.ry() += diff; 0077 } else { 0078 endPos.rx() += diff; 0079 } 0080 0081 propertyAnim->setDuration(remainingDuration); 0082 propertyAnim->setStartValue(currentPos); 0083 propertyAnim->setEndValue(endPos); 0084 propertyAnim->start(); 0085 propertyAnim->blockSignals(block); 0086 } else { 0087 widget->setPos(currentPos); 0088 } 0089 } 0090 } 0091 } 0092 0093 qreal KItemListViewAnimation::scrollOffset() const 0094 { 0095 return m_scrollOffset; 0096 } 0097 0098 void KItemListViewAnimation::start(QGraphicsWidget *widget, AnimationType type, const QVariant &endValue) 0099 { 0100 stop(widget, type); 0101 0102 QPropertyAnimation *propertyAnim = nullptr; 0103 const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animate) ? 200 : 1; 0104 0105 switch (type) { 0106 case MovingAnimation: { 0107 const QPointF newPos = endValue.toPointF(); 0108 if (newPos == widget->pos()) { 0109 return; 0110 } 0111 0112 propertyAnim = new QPropertyAnimation(widget, "pos"); 0113 propertyAnim->setDuration(animationDuration); 0114 propertyAnim->setEndValue(newPos); 0115 break; 0116 } 0117 0118 case CreateAnimation: { 0119 propertyAnim = new QPropertyAnimation(widget, "opacity"); 0120 propertyAnim->setEasingCurve(QEasingCurve::InQuart); 0121 propertyAnim->setDuration(animationDuration); 0122 propertyAnim->setStartValue(0.0); 0123 propertyAnim->setEndValue(1.0); 0124 break; 0125 } 0126 0127 case DeleteAnimation: { 0128 propertyAnim = new QPropertyAnimation(widget, "opacity"); 0129 propertyAnim->setEasingCurve(QEasingCurve::OutQuart); 0130 propertyAnim->setDuration(animationDuration); 0131 propertyAnim->setStartValue(1.0); 0132 propertyAnim->setEndValue(0.0); 0133 break; 0134 } 0135 0136 case ResizeAnimation: { 0137 const QSizeF newSize = endValue.toSizeF(); 0138 if (newSize == widget->size()) { 0139 return; 0140 } 0141 0142 propertyAnim = new QPropertyAnimation(widget, "size"); 0143 propertyAnim->setDuration(animationDuration); 0144 propertyAnim->setEndValue(newSize); 0145 break; 0146 } 0147 0148 case IconResizeAnimation: { 0149 propertyAnim = new QPropertyAnimation(widget, QByteArrayLiteral("iconSize")); 0150 propertyAnim->setDuration(animationDuration); 0151 propertyAnim->setEndValue(endValue); 0152 break; 0153 } 0154 0155 default: 0156 Q_UNREACHABLE(); 0157 break; 0158 } 0159 0160 Q_ASSERT(propertyAnim); 0161 connect(propertyAnim, &QPropertyAnimation::finished, this, &KItemListViewAnimation::slotFinished); 0162 m_animation[type].insert(widget, propertyAnim); 0163 0164 propertyAnim->start(); 0165 } 0166 0167 void KItemListViewAnimation::stop(QGraphicsWidget *widget, AnimationType type) 0168 { 0169 QPropertyAnimation *propertyAnim = m_animation[type].value(widget); 0170 if (propertyAnim) { 0171 propertyAnim->stop(); 0172 0173 switch (type) { 0174 case MovingAnimation: 0175 break; 0176 case CreateAnimation: 0177 widget->setOpacity(1.0); 0178 break; 0179 case DeleteAnimation: 0180 widget->setOpacity(0.0); 0181 break; 0182 case ResizeAnimation: 0183 break; 0184 default: 0185 break; 0186 } 0187 0188 m_animation[type].remove(widget); 0189 delete propertyAnim; 0190 0191 Q_EMIT finished(widget, type); 0192 } 0193 } 0194 0195 void KItemListViewAnimation::stop(QGraphicsWidget *widget) 0196 { 0197 for (int type = 0; type < AnimationTypeCount; ++type) { 0198 stop(widget, static_cast<AnimationType>(type)); 0199 } 0200 } 0201 0202 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget, AnimationType type) const 0203 { 0204 return m_animation[type].value(widget); 0205 } 0206 0207 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget) const 0208 { 0209 for (int type = 0; type < AnimationTypeCount; ++type) { 0210 if (isStarted(widget, static_cast<AnimationType>(type))) { 0211 return true; 0212 } 0213 } 0214 return false; 0215 } 0216 0217 void KItemListViewAnimation::slotFinished() 0218 { 0219 QPropertyAnimation *finishedAnim = qobject_cast<QPropertyAnimation *>(sender()); 0220 for (int type = 0; type < AnimationTypeCount; ++type) { 0221 QMutableHashIterator<QGraphicsWidget *, QPropertyAnimation *> it(m_animation[type]); 0222 while (it.hasNext()) { 0223 it.next(); 0224 QPropertyAnimation *propertyAnim = it.value(); 0225 if (propertyAnim == finishedAnim) { 0226 QGraphicsWidget *widget = it.key(); 0227 it.remove(); 0228 finishedAnim->deleteLater(); 0229 0230 Q_EMIT finished(widget, static_cast<AnimationType>(type)); 0231 return; 0232 } 0233 } 0234 } 0235 Q_ASSERT(false); 0236 } 0237 0238 #include "moc_kitemlistviewanimation.cpp"