25 #include <QAbstractItemView>
26 #include <QPersistentModelIndex>
33 #include <qabstractproxymodel.h>
35 #include "delegateanimationhandler_p.moc"
41 class ProtectedAccessor :
public QAbstractItemView
44 bool draggingState()
const {
return state() == DraggingState; }
56 : state(state), regular(QPixmap(size)), hover(QPixmap(size)), valid(true), validityIndex(index)
59 hover.fill(Qt::transparent);
63 connect(index.model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
64 SLOT(dataChanged(QModelIndex,QModelIndex)));
65 connect(index.model(), SIGNAL(modelReset()), SLOT(modelReset()));
69 void CachedRendering::dataChanged(
const QModelIndex & topLeft,
const QModelIndex & bottomRight)
76 void CachedRendering::modelReset()
85 AnimationState::AnimationState(
const QModelIndex &index)
86 : index(index), direction(QTimeLine::
Forward),
87 animating(false), jobAnimation(false), progress(0.0), m_fadeProgress(1.0),
88 m_jobAnimationAngle(0.0), renderCache(NULL), fadeFromRenderCache(NULL)
97 delete fadeFromRenderCache;
101 bool AnimationState::update()
103 const qreal runtime = (direction == QTimeLine::Forward ? 150 : 250);
104 const qreal increment = 1000. / runtime / 1000.;
105 const qreal delta = increment * time.restart();
107 if (direction == QTimeLine::Forward)
109 progress = qMin(qreal(1.0), progress + delta);
110 animating = (progress < 1.0);
114 progress = qMax(qreal(0.0), progress - delta);
115 animating = (progress > 0.0);
119 if (fadeFromRenderCache)
122 m_fadeProgress = qMin(qreal(1.0), m_fadeProgress + delta);
123 animating |= (m_fadeProgress < 1.0);
124 if (m_fadeProgress == 1)
130 m_jobAnimationAngle += 1.0;
131 if (m_jobAnimationAngle == 360)
132 m_jobAnimationAngle = 0;
156 #define M_PI_2 1.57079632679489661923
158 return qRound(255.0 * std::sin(progress *
M_PI_2)) / 255.0;
163 return qRound(255.0 * std::sin(m_fadeProgress *
M_PI_2)) / 255.0;
168 return m_jobAnimationAngle;
178 jobAnimation = value;
188 iconSequenceTimer.setSingleShot(
true);
190 connect(&iconSequenceTimer, SIGNAL(
timeout()), SLOT(sequenceTimerTimeout()));;
197 QMapIterator<const QAbstractItemView*, AnimationList*> i(animationLists);
201 qDeleteAll(*i.value());
204 animationLists.clear();
207 void DelegateAnimationHandler::sequenceTimerTimeout()
211 QModelIndex index = sequenceModelIndex;
215 index = proxy->mapToSource(index);
216 model = proxy->sourceModel();
224 iconSequenceTimer.start();
233 if (sequenceModelIndex.isValid() && currentSequenceIndex)
234 iconSequenceTimer.start();
236 ++currentSequenceIndex;
239 void DelegateAnimationHandler::setSequenceIndex(
int sequenceIndex)
243 if (sequenceIndex > 0)
245 currentSequenceIndex = sequenceIndex;
246 iconSequenceTimer.start();
250 currentSequenceIndex = 0;
251 sequenceTimerTimeout();
252 currentSequenceIndex = 0;
253 iconSequenceTimer.stop();
257 void DelegateAnimationHandler::eventuallyStartIteration(QModelIndex index)
262 if (sequenceModelIndex.isValid())
266 sequenceModelIndex = index;
272 const QModelIndex &index,
273 const QAbstractItemView *view)
278 if (!view || static_cast<const ProtectedAccessor*>(view)->draggingState())
282 bool hover = option.state & QStyle::State_MouseOver;
288 addAnimationState(state, view);
290 if (!fadeInAddTime.isValid() ||
291 (fadeInAddTime.isValid() && fadeInAddTime.elapsed() > 300))
293 startAnimation(state);
297 state->animating =
false;
298 state->progress = 1.0;
299 state->direction = QTimeLine::Forward;
302 fadeInAddTime.restart();
304 eventuallyStartIteration(index);
309 if (!hover && (!state->animating || state->direction == QTimeLine::Forward))
311 state->direction = QTimeLine::Backward;
313 if (state->creationTime.elapsed() < 200)
314 state->progress = 0.0;
316 startAnimation(state);
319 if (index == sequenceModelIndex)
322 sequenceModelIndex = QPersistentModelIndex();
325 else if (hover && state->direction == QTimeLine::Backward)
331 state->direction = QTimeLine::Forward;
333 if (!state->animating)
334 startAnimation(state);
336 eventuallyStartIteration(index);
342 addAnimationState(state, view);
343 startAnimation(state);
351 AnimationState *DelegateAnimationHandler::findAnimationState(
const QAbstractItemView *view,
352 const QModelIndex &index)
const
355 AnimationList *
list = animationLists.value(view);
360 if (state->index == index)
368 void DelegateAnimationHandler::addAnimationState(AnimationState *state,
const QAbstractItemView *view)
370 AnimationList *list = animationLists.value(view);
375 connect(view, SIGNAL(destroyed(
QObject*)), SLOT(viewDeleted(
QObject*)));
377 list =
new AnimationList;
378 animationLists.insert(view, list);
386 startAnimation(state);
389 void DelegateAnimationHandler::startAnimation(
AnimationState *state)
392 state->animating =
true;
394 if (!timer.isActive())
395 timer.start(1000 / 30,
this);
398 int DelegateAnimationHandler::runAnimations(AnimationList *list,
const QAbstractItemView *view)
400 int activeAnimations = 0;
403 QMutableLinkedListIterator<AnimationState*> i(*list);
406 AnimationState *state = i.next();
408 if (!state->animating)
413 if (state->index.isValid())
415 bool finished = state->update();
416 region += view->visualRect(state->index);
428 if (state->direction == QTimeLine::Backward || !state->index.isValid())
436 if (!region.isEmpty())
437 const_cast<QAbstractItemView*>(view)->viewport()->update(region);
439 return activeAnimations;
443 void DelegateAnimationHandler::viewDeleted(
QObject *view)
445 AnimationList *list = animationLists.take(static_cast<QAbstractItemView*>(view));
451 void DelegateAnimationHandler::timerEvent(QTimerEvent *)
453 int activeAnimations = 0;
455 AnimationListsIterator i(animationLists);
459 AnimationList *list = i.value();
460 const QAbstractItemView *view = i.key();
462 activeAnimations += runAnimations(list, view);
465 if (activeAnimations == 0 && timer.isActive())
static int animationDebugArea()
qreal hoverProgress() const
CachedRendering(QStyle::State state, const QSize &size, QModelIndex validityIndex)
returns whether or not there is a job on an item (file/directory)
void restartAnimation(AnimationState *state)
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
void gotNewIcon(const QModelIndex &index)
qreal jobAnimationAngle() const
void requestSequenceIcon(const QModelIndex &index, int sequenceIndex)
This emits the needSequenceIcon signal, requesting another sequence icon.
bool hasJobAnimation() const
QPersistentModelIndex validityIndex
~DelegateAnimationHandler()
static int registerArea(const QByteArray &areaName, bool enabled=true)
qreal fadeProgress() const
AnimationState * animationState(const QStyleOption &option, const QModelIndex &index, const QAbstractItemView *view)
static const int switchIconInterval
void setJobAnimation(bool value)
void setCachedRenderingFadeFrom(CachedRendering *rendering)
DelegateAnimationHandler(QObject *parent=0)
A model for a KIO-based directory tree.
QStringList list(const QString &fileClass)
Returns a list of directories associated with this file-class.