]> cloud.milkyroute.net Git - dolphin.git/blob - src/kitemviews/private/kitemlistviewanimation.cpp
67ad192c6ecdadd689749d7a13d7694968f1bf7a
[dolphin.git] / src / kitemviews / private / kitemlistviewanimation.cpp
1 /***************************************************************************
2 * Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
19
20 #include "kitemlistviewanimation.h"
21
22 #include <kitemviews/kitemlistview.h>
23
24
25 #include <QGraphicsWidget>
26 #include <QPropertyAnimation>
27
28 KItemListViewAnimation::KItemListViewAnimation(QObject* parent) :
29 QObject(parent),
30 m_scrollOrientation(Qt::Vertical),
31 m_scrollOffset(0),
32 m_animation()
33 {
34 }
35
36 KItemListViewAnimation::~KItemListViewAnimation()
37 {
38 for (int type = 0; type < AnimationTypeCount; ++type) {
39 qDeleteAll(m_animation[type]);
40 }
41 }
42
43 void KItemListViewAnimation::setScrollOrientation(Qt::Orientation orientation)
44 {
45 m_scrollOrientation = orientation;
46 }
47
48 Qt::Orientation KItemListViewAnimation::scrollOrientation() const
49 {
50 return m_scrollOrientation;
51 }
52
53 void KItemListViewAnimation::setScrollOffset(qreal offset)
54 {
55 const qreal diff = m_scrollOffset - offset;
56 m_scrollOffset = offset;
57
58 // The change of the offset requires that the position of all
59 // animated QGraphicsWidgets get adjusted. An exception is made
60 // for the delete animation that should just fade away on the
61 // existing position.
62 for (int type = 0; type < AnimationTypeCount; ++type) {
63 if (type == DeleteAnimation) {
64 continue;
65 }
66
67 QHashIterator<QGraphicsWidget*, QPropertyAnimation*> it(m_animation[type]);
68 while (it.hasNext()) {
69 it.next();
70
71 QGraphicsWidget* widget = it.key();
72 QPropertyAnimation* propertyAnim = it.value();
73
74 QPointF currentPos = widget->pos();
75 if (m_scrollOrientation == Qt::Vertical) {
76 currentPos.ry() += diff;
77 } else {
78 currentPos.rx() += diff;
79 }
80
81 if (type == MovingAnimation) {
82 // Stop the animation, calculate the moved start- and end-value
83 // and restart the animation for the remaining duration.
84 const int remainingDuration = propertyAnim->duration()
85 - propertyAnim->currentTime();
86
87 const bool block = propertyAnim->signalsBlocked();
88 propertyAnim->blockSignals(true);
89 propertyAnim->stop();
90
91 QPointF endPos = propertyAnim->endValue().toPointF();
92 if (m_scrollOrientation == Qt::Vertical) {
93 endPos.ry() += diff;
94 } else {
95 endPos.rx() += diff;
96 }
97
98 propertyAnim->setDuration(remainingDuration);
99 propertyAnim->setStartValue(currentPos);
100 propertyAnim->setEndValue(endPos);
101 propertyAnim->start();
102 propertyAnim->blockSignals(block);
103 } else {
104 widget->setPos(currentPos);
105 }
106 }
107 }
108 }
109
110 qreal KItemListViewAnimation::scrollOffset() const
111 {
112 return m_scrollOffset;
113 }
114
115 void KItemListViewAnimation::start(QGraphicsWidget* widget, AnimationType type, const QVariant& endValue)
116 {
117 stop(widget, type);
118
119 QPropertyAnimation* propertyAnim = 0;
120 const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animate) ? 200 : 1;
121
122 switch (type) {
123 case MovingAnimation: {
124 const QPointF newPos = endValue.toPointF();
125 if (newPos == widget->pos()) {
126 return;
127 }
128
129 propertyAnim = new QPropertyAnimation(widget, "pos");
130 propertyAnim->setDuration(animationDuration);
131 propertyAnim->setEndValue(newPos);
132 break;
133 }
134
135 case CreateAnimation: {
136 propertyAnim = new QPropertyAnimation(widget, "opacity");
137 propertyAnim->setEasingCurve(QEasingCurve::InQuart);
138 propertyAnim->setDuration(animationDuration);
139 propertyAnim->setStartValue(0.0);
140 propertyAnim->setEndValue(1.0);
141 break;
142 }
143
144 case DeleteAnimation: {
145 propertyAnim = new QPropertyAnimation(widget, "opacity");
146 propertyAnim->setEasingCurve(QEasingCurve::OutQuart);
147 propertyAnim->setDuration(animationDuration);
148 propertyAnim->setStartValue(1.0);
149 propertyAnim->setEndValue(0.0);
150 break;
151 }
152
153 case ResizeAnimation: {
154 const QSizeF newSize = endValue.toSizeF();
155 if (newSize == widget->size()) {
156 return;
157 }
158
159 propertyAnim = new QPropertyAnimation(widget, "size");
160 propertyAnim->setDuration(animationDuration);
161 propertyAnim->setEndValue(newSize);
162 break;
163 }
164
165 default:
166 break;
167 }
168
169 Q_ASSERT(propertyAnim);
170 connect(propertyAnim, &QPropertyAnimation::finished, this, &KItemListViewAnimation::slotFinished);
171 m_animation[type].insert(widget, propertyAnim);
172
173 propertyAnim->start();
174 }
175
176 void KItemListViewAnimation::stop(QGraphicsWidget* widget, AnimationType type)
177 {
178 QPropertyAnimation* propertyAnim = m_animation[type].value(widget);
179 if (propertyAnim) {
180 propertyAnim->stop();
181
182 switch (type) {
183 case MovingAnimation: break;
184 case CreateAnimation: widget->setOpacity(1.0); break;
185 case DeleteAnimation: widget->setOpacity(0.0); break;
186 case ResizeAnimation: break;
187 default: break;
188 }
189
190 m_animation[type].remove(widget);
191 delete propertyAnim;
192
193 emit finished(widget, type);
194 }
195 }
196
197 void KItemListViewAnimation::stop(QGraphicsWidget* widget)
198 {
199 for (int type = 0; type < AnimationTypeCount; ++type) {
200 stop(widget, static_cast<AnimationType>(type));
201 }
202 }
203
204 bool KItemListViewAnimation::isStarted(QGraphicsWidget *widget, AnimationType type) const
205 {
206 return m_animation[type].value(widget);
207 }
208
209 bool KItemListViewAnimation::isStarted(QGraphicsWidget* widget) const
210 {
211 for (int type = 0; type < AnimationTypeCount; ++type) {
212 if (isStarted(widget, static_cast<AnimationType>(type))) {
213 return true;
214 }
215 }
216 return false;
217 }
218
219 void KItemListViewAnimation::slotFinished()
220 {
221 QPropertyAnimation* finishedAnim = qobject_cast<QPropertyAnimation*>(sender());
222 for (int type = 0; type < AnimationTypeCount; ++type) {
223 QMutableHashIterator<QGraphicsWidget*, QPropertyAnimation*> it(m_animation[type]);
224 while (it.hasNext()) {
225 it.next();
226 QPropertyAnimation* propertyAnim = it.value();
227 if (propertyAnim == finishedAnim) {
228 QGraphicsWidget* widget = it.key();
229 it.remove();
230 finishedAnim->deleteLater();
231
232 emit finished(widget, static_cast<AnimationType>(type));
233 return;
234 }
235 }
236 }
237 Q_ASSERT(false);
238 }
239