]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/private/kitemlistviewanimation.cpp
Merge remote-tracking branch 'origin/release/21.08'
[dolphin.git] / src / kitemviews / private / kitemlistviewanimation.cpp
1 /*
2 * SPDX-FileCopyrightText: 2011 Peter Penz <peter.penz19@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7 #include "kitemlistviewanimation.h"
8 #include "kitemviews/kitemlistview.h"
9
10 #include <QPropertyAnimation>
11
12 KItemListViewAnimation::KItemListViewAnimation(QObject* parent) :
13 QObject(parent),
14 m_scrollOrientation(Qt::Vertical),
15 m_scrollOffset(0),
16 m_animation()
17 {
18 }
19
20 KItemListViewAnimation::~KItemListViewAnimation()
21 {
22 for (int type = 0; type < AnimationTypeCount; ++type) {
23 qDeleteAll(m_animation[type]);
24 }
25 }
26
27 void KItemListViewAnimation::setScrollOrientation(Qt::Orientation orientation)
28 {
29 m_scrollOrientation = orientation;
30 }
31
32 Qt::Orientation KItemListViewAnimation::scrollOrientation() const
33 {
34 return m_scrollOrientation;
35 }
36
37 void KItemListViewAnimation::setScrollOffset(qreal offset)
38 {
39 const qreal diff = m_scrollOffset - offset;
40 m_scrollOffset = offset;
41
42 // The change of the offset requires that the position of all
43 // animated QGraphicsWidgets get adjusted. An exception is made
44 // for the delete animation that should just fade away on the
45 // existing position.
46 for (int type = 0; type < AnimationTypeCount; ++type) {
47 if (type == DeleteAnimation) {
48 continue;
49 }
50
51 QHashIterator<QGraphicsWidget*, QPropertyAnimation*> it(m_animation[type]);
52 while (it.hasNext()) {
53 it.next();
54
55 QGraphicsWidget* widget = it.key();
56 QPropertyAnimation* propertyAnim = it.value();
57
58 QPointF currentPos = widget->pos();
59 if (m_scrollOrientation == Qt::Vertical) {
60 currentPos.ry() += diff;
61 } else {
62 currentPos.rx() += diff;
63 }
64
65 if (type == MovingAnimation) {
66 // Stop the animation, calculate the moved start- and end-value
67 // and restart the animation for the remaining duration.
68 const int remainingDuration = propertyAnim->duration()
69 - propertyAnim->currentTime();
70
71 const bool block = propertyAnim->signalsBlocked();
72 propertyAnim->blockSignals(true);
73 propertyAnim->stop();
74
75 QPointF endPos = propertyAnim->endValue().toPointF();
76 if (m_scrollOrientation == Qt::Vertical) {
77 endPos.ry() += diff;
78 } else {
79 endPos.rx() += diff;
80 }
81
82 propertyAnim->setDuration(remainingDuration);
83 propertyAnim->setStartValue(currentPos);
84 propertyAnim->setEndValue(endPos);
85 propertyAnim->start();
86 propertyAnim->blockSignals(block);
87 } else {
88 widget->setPos(currentPos);
89 }
90 }
91 }
92 }
93
94 qreal KItemListViewAnimation::scrollOffset() const
95 {
96 return m_scrollOffset;
97 }
98
99 void KItemListViewAnimation::start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue)
100 {
101 stop(widget, type);
102
103 QPropertyAnimation* propertyAnim = nullptr;
104 const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animate) ? 200 : 1;
105
106 switch (type) {
107 case MovingAnimation: {
108 const QPointF newPos = endValue.toPointF();
109 if (newPos == widget->pos()) {
110 return;
111 }
112
113 propertyAnim = new QPropertyAnimation(widget, "pos");
114 propertyAnim->setDuration(animationDuration);
115 propertyAnim->setEndValue(newPos);
116 break;
117 }
118
119 case CreateAnimation: {
120 propertyAnim = new QPropertyAnimation(widget, "opacity");
121 propertyAnim->setEasingCurve(QEasingCurve::InQuart);
122 propertyAnim->setDuration(animationDuration);
123 propertyAnim->setStartValue(0.0);
124 propertyAnim->setEndValue(1.0);
125 break;
126 }
127
128 case DeleteAnimation: {
129 propertyAnim = new QPropertyAnimation(widget, "opacity");
130 propertyAnim->setEasingCurve(QEasingCurve::OutQuart);
131 propertyAnim->setDuration(animationDuration);
132 propertyAnim->setStartValue(1.0);
133 propertyAnim->setEndValue(0.0);
134 break;
135 }
136
137 case ResizeAnimation: {
138 const QSizeF newSize = endValue.toSizeF();
139 if (newSize == widget->size()) {
140 return;
141 }
142
143 propertyAnim = new QPropertyAnimation(widget, "size");
144 propertyAnim->setDuration(animationDuration);
145 propertyAnim->setEndValue(newSize);
146 break;
147 }
148
149 default:
150 break;
151 }
152
153 Q_ASSERT(propertyAnim);
154 connect(propertyAnim, &QPropertyAnimation::finished, this, &KItemListViewAnimation::slotFinished);
155 m_animation[type].insert(widget, propertyAnim);
156
157 propertyAnim->start();
158 }
159
160 void KItemListViewAnimation::stop(QGraphicsWidget* widget, AnimationType type)
161 {
162 QPropertyAnimation* propertyAnim = m_animation[type].value(widget);
163 if (propertyAnim) {
164 propertyAnim->stop();
165
166 switch (type) {
167 case MovingAnimation: break;
168 case CreateAnimation: widget->setOpacity(1.0); break;
169 case DeleteAnimation: widget->setOpacity(0.0); break;
170 case ResizeAnimation: break;
171 default: break;
172 }
173
174 m_animation[type].remove(widget);
175 delete propertyAnim;
176
177 Q_EMIT finished(widget, type);
178 }
179 }
180
181 void KItemListViewAnimation::stop(QGraphicsWidget* widget)
182 {
183 for (int type = 0; type < AnimationTypeCount; ++type) {
184 stop(widget, static_cast<AnimationType>(type));
185 }
186 }
187
188 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget, AnimationType type) const
189 {
190 return m_animation[type].value(widget);
191 }
192
193 bool KItemListViewAnimation::isStarted(QGraphicsWidget* widget) const
194 {
195 for (int type = 0; type < AnimationTypeCount; ++type) {
196 if (isStarted(widget, static_cast<AnimationType>(type))) {
197 return true;
198 }
199 }
200 return false;
201 }
202
203 void KItemListViewAnimation::slotFinished()
204 {
205 QPropertyAnimation* finishedAnim = qobject_cast<QPropertyAnimation*>(sender());
206 for (int type = 0; type < AnimationTypeCount; ++type) {
207 QMutableHashIterator<QGraphicsWidget*, QPropertyAnimation*> it(m_animation[type]);
208 while (it.hasNext()) {
209 it.next();
210 QPropertyAnimation* propertyAnim = it.value();
211 if (propertyAnim == finishedAnim) {
212 QGraphicsWidget* widget = it.key();
213 it.remove();
214 finishedAnim->deleteLater();
215
216 Q_EMIT finished(widget, static_cast<AnimationType>(type));
217 return;
218 }
219 }
220 }
221 Q_ASSERT(false);
222 }
223