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