]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/private/kitemlistviewanimation.cpp
GIT_SILENT Update Appstream for new release
[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() - propertyAnim->currentTime();
69
70 const bool block = propertyAnim->signalsBlocked();
71 propertyAnim->blockSignals(true);
72 propertyAnim->stop();
73
74 QPointF endPos = propertyAnim->endValue().toPointF();
75 if (m_scrollOrientation == Qt::Vertical) {
76 endPos.ry() += diff;
77 } else {
78 endPos.rx() += diff;
79 }
80
81 propertyAnim->setDuration(remainingDuration);
82 propertyAnim->setStartValue(currentPos);
83 propertyAnim->setEndValue(endPos);
84 propertyAnim->start();
85 propertyAnim->blockSignals(block);
86 } else {
87 widget->setPos(currentPos);
88 }
89 }
90 }
91 }
92
93 qreal KItemListViewAnimation::scrollOffset() const
94 {
95 return m_scrollOffset;
96 }
97
98 void KItemListViewAnimation::start(QGraphicsWidget *widget, AnimationType type, const QVariant &endValue)
99 {
100 stop(widget, type);
101
102 QPropertyAnimation *propertyAnim = nullptr;
103 const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animate) ? 200 : 1;
104
105 switch (type) {
106 case MovingAnimation: {
107 const QPointF newPos = endValue.toPointF();
108 if (newPos == widget->pos()) {
109 return;
110 }
111
112 propertyAnim = new QPropertyAnimation(widget, "pos");
113 propertyAnim->setDuration(animationDuration);
114 propertyAnim->setEndValue(newPos);
115 break;
116 }
117
118 case CreateAnimation: {
119 propertyAnim = new QPropertyAnimation(widget, "opacity");
120 propertyAnim->setEasingCurve(QEasingCurve::InQuart);
121 propertyAnim->setDuration(animationDuration);
122 propertyAnim->setStartValue(0.0);
123 propertyAnim->setEndValue(1.0);
124 break;
125 }
126
127 case DeleteAnimation: {
128 propertyAnim = new QPropertyAnimation(widget, "opacity");
129 propertyAnim->setEasingCurve(QEasingCurve::OutQuart);
130 propertyAnim->setDuration(animationDuration);
131 propertyAnim->setStartValue(1.0);
132 propertyAnim->setEndValue(0.0);
133 break;
134 }
135
136 case ResizeAnimation: {
137 const QSizeF newSize = endValue.toSizeF();
138 if (newSize == widget->size()) {
139 return;
140 }
141
142 propertyAnim = new QPropertyAnimation(widget, "size");
143 propertyAnim->setDuration(animationDuration);
144 propertyAnim->setEndValue(newSize);
145 break;
146 }
147
148 case IconResizeAnimation: {
149 propertyAnim = new QPropertyAnimation(widget, QByteArrayLiteral("iconSize"));
150 propertyAnim->setDuration(animationDuration);
151 propertyAnim->setEndValue(endValue);
152 break;
153 }
154
155 default:
156 Q_UNREACHABLE();
157 break;
158 }
159
160 Q_ASSERT(propertyAnim);
161 connect(propertyAnim, &QPropertyAnimation::finished, this, &KItemListViewAnimation::slotFinished);
162 m_animation[type].insert(widget, propertyAnim);
163
164 propertyAnim->start();
165 }
166
167 void KItemListViewAnimation::stop(QGraphicsWidget *widget, AnimationType type)
168 {
169 QPropertyAnimation *propertyAnim = m_animation[type].value(widget);
170 if (propertyAnim) {
171 propertyAnim->stop();
172
173 switch (type) {
174 case MovingAnimation:
175 break;
176 case CreateAnimation:
177 widget->setOpacity(1.0);
178 break;
179 case DeleteAnimation:
180 widget->setOpacity(0.0);
181 break;
182 case ResizeAnimation:
183 break;
184 default:
185 break;
186 }
187
188 m_animation[type].remove(widget);
189 delete propertyAnim;
190
191 Q_EMIT finished(widget, type);
192 }
193 }
194
195 void KItemListViewAnimation::stop(QGraphicsWidget *widget)
196 {
197 for (int type = 0; type < AnimationTypeCount; ++type) {
198 stop(widget, static_cast<AnimationType>(type));
199 }
200 }
201
202 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget, AnimationType type) const
203 {
204 return m_animation[type].value(widget);
205 }
206
207 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget) const
208 {
209 for (int type = 0; type < AnimationTypeCount; ++type) {
210 if (isStarted(widget, static_cast<AnimationType>(type))) {
211 return true;
212 }
213 }
214 return false;
215 }
216
217 void KItemListViewAnimation::slotFinished()
218 {
219 QPropertyAnimation *finishedAnim = qobject_cast<QPropertyAnimation *>(sender());
220 for (int type = 0; type < AnimationTypeCount; ++type) {
221 QMutableHashIterator<QGraphicsWidget *, QPropertyAnimation *> it(m_animation[type]);
222 while (it.hasNext()) {
223 it.next();
224 QPropertyAnimation *propertyAnim = it.value();
225 if (propertyAnim == finishedAnim) {
226 QGraphicsWidget *widget = it.key();
227 it.remove();
228 finishedAnim->deleteLater();
229
230 Q_EMIT finished(widget, static_cast<AnimationType>(type));
231 return;
232 }
233 }
234 }
235 Q_ASSERT(false);
236 }
237
238 #include "moc_kitemlistviewanimation.cpp"