00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "animator.h"
00022
00023 #include <QGraphicsItem>
00024 #include <QTimeLine>
00025 #include <QTimerEvent>
00026
00027 #include <kconfig.h>
00028 #include <kconfiggroup.h>
00029 #include <kservice.h>
00030 #include <kservicetypetrader.h>
00031 #include <kglobalsettings.h>
00032
00033 #include "animationdriver.h"
00034
00035 namespace Plasma
00036 {
00037
00038 static const int MIN_TICK_RATE_INT = 10;
00039 static const qreal MIN_TICK_RATE = 10;
00040
00041 struct AnimationState
00042 {
00043 QGraphicsItem *item;
00044 QObject *qobj;
00045 Animator::Animation animation;
00046 Animator::CurveShape curve;
00047 int interval;
00048 int currentInterval;
00049 int frames;
00050 int currentFrame;
00051 int id;
00052 };
00053
00054 struct ElementAnimationState
00055 {
00056 QGraphicsItem *item;
00057 QObject *qobj;
00058 Animator::CurveShape curve;
00059 Animator::Animation animation;
00060 int interval;
00061 int currentInterval;
00062 int frames;
00063 int currentFrame;
00064 int id;
00065 QPixmap pixmap;
00066 };
00067
00068 struct MovementState
00069 {
00070 QGraphicsItem *item;
00071 QObject *qobj;
00072 Animator::CurveShape curve;
00073 Animator::Movement movement;
00074 int interval;
00075 int currentInterval;
00076 int frames;
00077 int currentFrame;
00078 QPoint start;
00079 QPoint destination;
00080 int id;
00081 };
00082
00083 struct CustomAnimationState
00084 {
00085 Animator::CurveShape curve;
00086 int frames;
00087 int currentFrame;
00088 int frameInterval;
00089 int interval;
00090 int currentInterval;
00091 int id;
00092 QObject *receiver;
00093 char *slot;
00094 };
00095
00096 class AnimatorPrivate
00097 {
00098 public:
00099
00100 AnimatorPrivate()
00101 : driver(0),
00102 animId(0),
00103 timerId(0)
00104 {
00105 }
00106
00107 ~AnimatorPrivate()
00108 {
00109 cleanupStates();
00110 qDeleteAll(animatedItems);
00111 qDeleteAll(animatedElements);
00112 qDeleteAll(movingItems);
00113
00114 QMutableMapIterator<int, CustomAnimationState*> it(customAnims);
00115 while (it.hasNext()) {
00116 it.next();
00117 delete[] it.value()->slot;
00118 delete it.value();
00119 it.remove();
00120 }
00121
00122
00123
00124 }
00125
00126 qreal calculateProgress(int time, int duration, Animator::CurveShape curve)
00127 {
00128 if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
00129 return qreal(1.0);
00130 }
00131
00132 timeline.setCurveShape(static_cast<QTimeLine::CurveShape>(curve));
00133 timeline.setDuration(duration);
00134 qreal progress = timeline.valueForTime(time);
00135 return progress;
00136 }
00137
00138 void performAnimation(qreal amount, const AnimationState *state)
00139 {
00140 switch (state->animation) {
00141 case Animator::AppearAnimation:
00142 driver->itemAppear(amount, state->item);
00143 break;
00144 case Animator::DisappearAnimation:
00145 driver->itemDisappear(amount, state->item);
00146 if (amount >= 1) {
00147 state->item->hide();
00148 }
00149 break;
00150 case Animator::ActivateAnimation:
00151 driver->itemActivated(amount, state->item);
00152 break;
00153 }
00154 }
00155
00156 void performMovement(qreal amount, const MovementState *state)
00157 {
00158 switch (state->movement) {
00159 case Animator::SlideInMovement:
00160 case Animator::FastSlideInMovement:
00161
00162 driver->itemSlideIn(amount, state->item, state->start, state->destination);
00163 break;
00164 case Animator::SlideOutMovement:
00165 case Animator::FastSlideOutMovement:
00166
00167 driver->itemSlideOut(amount, state->item, state->start, state->destination);
00168 break;
00169 }
00170 }
00171
00172
00173 void init(Animator *q);
00174 void cleanupStates();
00175 void animatedItemDestroyed(QObject*);
00176 void movingItemDestroyed(QObject*);
00177 void animatedElementDestroyed(QObject*);
00178 void customAnimReceiverDestroyed(QObject*);
00179
00180 AnimationDriver *driver;
00181 int animId;
00182 int timerId;
00183 QTime time;
00184 QTimeLine timeline;
00185
00186
00187 QMap<QGraphicsItem *, AnimationState *> animatedItems;
00188 QMap<QGraphicsItem *, MovementState *> movingItems;
00189 QMap<int, ElementAnimationState *> animatedElements;
00190 QMap<int, CustomAnimationState *> customAnims;
00191
00192
00193 QSet<AnimationState *> animatedItemsToDelete;
00194 QSet<MovementState *> movingItemsToDelete;
00195 QSet<ElementAnimationState *> animatedElementsToDelete;
00196 QSet<CustomAnimationState *> customAnimsToDelete;
00197 };
00198
00199 class AnimatorSingleton
00200 {
00201 public:
00202 Animator self;
00203 };
00204
00205 K_GLOBAL_STATIC(AnimatorSingleton, privateSelf)
00206
00207 Animator *Animator::self()
00208 {
00209 return &privateSelf->self;
00210 }
00211
00212 Animator::Animator(QObject *parent)
00213 : QObject(parent),
00214 d(new AnimatorPrivate)
00215 {
00216 d->init(this);
00217 }
00218
00219 Animator::~Animator()
00220 {
00221 delete d;
00222 }
00223
00224 void AnimatorPrivate::animatedItemDestroyed(QObject *o)
00225 {
00226
00227 QMutableMapIterator<QGraphicsItem*, AnimationState*> it(animatedItems);
00228 while (it.hasNext()) {
00229 it.next();
00230
00231 if (it.value()->qobj == o) {
00232 kDebug() << "found deleted animated item";
00233 if (timerId) {
00234 animatedItemsToDelete.insert(it.value());
00235 } else {
00236 delete it.value();
00237 }
00238
00239 it.remove();
00240 }
00241 }
00242 }
00243
00244 void AnimatorPrivate::movingItemDestroyed(QObject *o)
00245 {
00246 QMutableMapIterator<QGraphicsItem*, MovementState*> it(movingItems);
00247 while (it.hasNext()) {
00248 it.next();
00249 if (it.value()->qobj == o) {
00250 if (timerId) {
00251 movingItemsToDelete.insert(it.value());
00252 } else {
00253 delete it.value();
00254 }
00255
00256 it.remove();
00257 }
00258 }
00259 }
00260
00261 void AnimatorPrivate::animatedElementDestroyed(QObject *o)
00262 {
00263 QMutableMapIterator<int, ElementAnimationState*> it(animatedElements);
00264 while (it.hasNext()) {
00265 it.next();
00266 if (it.value()->qobj == o) {
00267 if (timerId) {
00268 animatedElementsToDelete.insert(it.value());
00269 } else {
00270 delete it.value();
00271 }
00272
00273 it.remove();
00274 }
00275 }
00276 }
00277
00278 void AnimatorPrivate::customAnimReceiverDestroyed(QObject *o)
00279 {
00280 QMutableMapIterator<int, CustomAnimationState*> it(customAnims);
00281 while (it.hasNext()) {
00282 if (it.next().value()->receiver == o) {
00283 if (timerId) {
00284 customAnimsToDelete.insert(it.value());
00285 } else {
00286 delete[] it.value()->slot;
00287 delete it.value();
00288 }
00289
00290 it.remove();
00291 }
00292 }
00293 }
00294
00295 int Animator::animateItem(QGraphicsItem *item, Animation animation)
00296 {
00297
00298
00299
00300 QMap<QGraphicsItem*, AnimationState*>::iterator it = d->animatedItems.find(item);
00301 if (it != d->animatedItems.end()) {
00302 if (d->timerId) {
00303 d->animatedItemsToDelete.insert(it.value());
00304 } else {
00305 delete it.value();
00306 }
00307
00308 d->animatedItems.erase(it);
00309 }
00310
00311 int frames = d->driver->animationFps(animation);
00312
00313 if (frames < 1) {
00314
00315
00316 return -1;
00317 }
00318
00319 int duration = d->driver->animationDuration(animation);
00320
00321 AnimationState *state = new AnimationState;
00322 state->id = ++d->animId;
00323 state->item = item;
00324 state->animation = animation;
00325 state->curve = d->driver->animationCurve(animation);
00326 state->frames = qMax(1.0, frames * (duration / 1000.0));
00327 state->currentFrame = 0;
00328 state->interval = d->driver->animationDuration(animation) / qreal(state->frames);
00329 state->interval = qMax(MIN_TICK_RATE_INT, state->interval - (state->interval % MIN_TICK_RATE_INT));
00330 state->currentInterval = state->interval;
00331 state->qobj = dynamic_cast<QObject*>(item);
00332
00333 if (state->qobj) {
00334
00335 disconnect(state->qobj, SIGNAL(destroyed(QObject*)),
00336 this, SLOT(animatedItemDestroyed(QObject*)));
00337 connect(state->qobj, SIGNAL(destroyed(QObject*)),
00338 this, SLOT(animatedItemDestroyed(QObject*)));
00339 }
00340
00341 d->animatedItems[item] = state;
00342 d->performAnimation(0, state);
00343
00344 if (!d->timerId) {
00345 d->timerId = startTimer(MIN_TICK_RATE);
00346 d->time.restart();
00347 }
00348
00349 return state->id;
00350 }
00351
00352 int Animator::moveItem(QGraphicsItem *item, Movement movement, const QPoint &destination)
00353 {
00354
00355 QMap<QGraphicsItem*, MovementState*>::iterator it = d->movingItems.find(item);
00356 if (it != d->movingItems.end()) {
00357 if (d->timerId) {
00358 d->movingItemsToDelete.insert(it.value());
00359 } else {
00360 delete it.value();
00361 }
00362
00363 d->movingItems.erase(it);
00364 }
00365
00366 int frames = d->driver->movementAnimationFps(movement);
00367 if (frames <= 1) {
00368
00369
00370 return -1;
00371 }
00372
00373 MovementState *state = new MovementState;
00374 state->id = ++d->animId;
00375 state->destination = destination;
00376 state->start = item->pos().toPoint();
00377 state->item = item;
00378 state->movement = movement;
00379 state->curve = d->driver->movementAnimationCurve(movement);
00380
00381 int duration = d->driver->movementAnimationDuration(movement);
00382 state->frames = qMax(1.0, frames * (duration / 1000.0));
00383 state->currentFrame = 0;
00384 state->interval = duration / qreal(state->frames);
00385 state->interval = qMax(MIN_TICK_RATE_INT, state->interval - (state->interval % MIN_TICK_RATE_INT));
00386
00387
00388 state->currentInterval = state->interval;
00389 state->qobj = dynamic_cast<QObject*>(item);
00390
00391 if (state->qobj) {
00392 disconnect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(movingItemDestroyed(QObject*)));
00393 connect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(movingItemDestroyed(QObject*)));
00394 }
00395
00396 d->movingItems[item] = state;
00397 d->performMovement(0, state);
00398
00399 if (!d->timerId) {
00400 d->timerId = startTimer(MIN_TICK_RATE);
00401 d->time.restart();
00402 }
00403
00404 return state->id;
00405 }
00406
00407 int Animator::customAnimation(int frames, int duration, Animator::CurveShape curve,
00408 QObject *receiver, const char *slot)
00409 {
00410 if (frames < 1 || duration < 1 || !receiver || !slot) {
00411 return -1;
00412 }
00413
00414 CustomAnimationState *state = new CustomAnimationState;
00415 state->id = ++d->animId;
00416 state->frames = frames;
00417 state->currentFrame = 0;
00418 state->curve = curve;
00419 state->frameInterval = qMax(qreal(1.0), duration / qreal(state->frames));
00420 state->interval = qMax(MIN_TICK_RATE_INT, state->frameInterval - (state->frameInterval % MIN_TICK_RATE_INT));
00421 state->currentInterval = state->interval;
00422 state->receiver = receiver;
00423 state->slot = qstrdup(slot);
00424
00425 d->customAnims[state->id] = state;
00426
00427 disconnect(receiver, SIGNAL(destroyed(QObject*)),
00428 this, SLOT(customAnimReceiverDestroyed(QObject*)));
00429 connect(receiver, SIGNAL(destroyed(QObject*)),
00430 this, SLOT(customAnimReceiverDestroyed(QObject*)));
00431
00432
00433 if (!QMetaObject::invokeMethod(receiver, slot, Q_ARG(qreal, 0))) {
00434
00435 QMetaObject::invokeMethod(receiver, slot, Q_ARG(qreal, 0), Q_ARG(int, state->id));
00436 }
00437
00438 if (!d->timerId) {
00439 d->timerId = startTimer(MIN_TICK_RATE);
00440 d->time.restart();
00441 }
00442
00443 return state->id;
00444 }
00445
00446 void Animator::stopCustomAnimation(int id)
00447 {
00448 QMap<int, CustomAnimationState*>::iterator it = d->customAnims.find(id);
00449 if (it != d->customAnims.end()) {
00450 if (d->timerId) {
00451 d->customAnimsToDelete.insert(it.value());
00452 } else {
00453 delete[] it.value()->slot;
00454 delete it.value();
00455 }
00456
00457 d->customAnims.erase(it);
00458 }
00459
00460 }
00461
00462 void Animator::stopItemAnimation(int id)
00463 {
00464 QMutableMapIterator<QGraphicsItem*, AnimationState*> it(d->animatedItems);
00465 while (it.hasNext()) {
00466 it.next();
00467 if (it.value()->id == id) {
00468 if (d->timerId) {
00469 d->animatedItemsToDelete.insert(it.value());
00470 } else {
00471 delete it.value();
00472 }
00473
00474 it.remove();
00475 return;
00476 }
00477 }
00478 }
00479
00480 void Animator::stopItemMovement(int id)
00481 {
00482 QMutableMapIterator<QGraphicsItem*, MovementState*> it(d->movingItems);
00483 while (it.hasNext()) {
00484 it.next();
00485 if (it.value()->id == id) {
00486 if (d->timerId) {
00487 d->movingItemsToDelete.insert(it.value());
00488 } else {
00489 delete it.value();
00490 }
00491
00492 it.remove();
00493 return;
00494 }
00495 }
00496 }
00497
00498 int Animator::animateElement(QGraphicsItem *item, Animation animation)
00499 {
00500
00501 int frames = d->driver->elementAnimationFps(animation);
00502 int duration = d->driver->animationDuration(animation);
00503
00504 ElementAnimationState *state = new ElementAnimationState;
00505 state->item = item;
00506 state->curve = d->driver->elementAnimationCurve(animation);
00507 state->animation = animation;
00508 state->frames = qMax(1.0, frames * (duration / 1000.0));
00509 state->currentFrame = 0;
00510 state->interval = duration / qreal(state->frames);
00511 state->interval = qMax(MIN_TICK_RATE_INT, state->interval - (state->interval % MIN_TICK_RATE_INT));
00512 state->currentInterval = state->interval;
00513 state->id = ++d->animId;
00514 state->qobj = dynamic_cast<QObject*>(item);
00515
00516 if (state->qobj) {
00517 disconnect(state->qobj, SIGNAL(destroyed(QObject*)),
00518 this, SLOT(animatedElementDestroyed(QObject*)));
00519 connect(state->qobj, SIGNAL(destroyed(QObject*)),
00520 this, SLOT(animatedElementDestroyed(QObject*)));
00521 }
00522
00523
00524
00525 bool needTimer = true;
00526 if (state->frames < 1) {
00527 state->frames = 1;
00528 state->currentFrame = 1;
00529 needTimer = false;
00530 }
00531
00532 d->animatedElements[state->id] = state;
00533
00534
00535 if (needTimer && !d->timerId) {
00536
00537
00538 d->timerId = startTimer(MIN_TICK_RATE);
00539 d->time.restart();
00540 }
00541 return state->id;
00542 }
00543
00544 void Animator::stopElementAnimation(int id)
00545 {
00546 QMap<int, ElementAnimationState*>::iterator it = d->animatedElements.find(id);
00547 if (it != d->animatedElements.end()) {
00548 if (d->timerId) {
00549 d->animatedElementsToDelete.insert(it.value());
00550 } else {
00551 delete it.value();
00552 }
00553
00554 d->animatedElements.erase(it);
00555 }
00556
00557 }
00558
00559 void Animator::setInitialPixmap(int id, const QPixmap &pixmap)
00560 {
00561 QMap<int, ElementAnimationState*>::iterator it = d->animatedElements.find(id);
00562
00563 if (it == d->animatedElements.end()) {
00564 kDebug() << "No entry found for id " << id;
00565 return;
00566 }
00567
00568 it.value()->pixmap = pixmap;
00569 }
00570
00571 QPixmap Animator::currentPixmap(int id)
00572 {
00573 QMap<int, ElementAnimationState*>::const_iterator it = d->animatedElements.constFind(id);
00574
00575 if (it == d->animatedElements.constEnd()) {
00576
00577 return QPixmap();
00578 }
00579
00580 ElementAnimationState *state = it.value();
00581 qreal progress = d->calculateProgress(state->currentFrame * state->interval,
00582 state->frames * state->interval,
00583 state->curve);
00584
00585
00586 switch (state->animation) {
00587 case AppearAnimation:
00588 return d->driver->elementAppear(progress, state->pixmap);
00589 break;
00590 case DisappearAnimation:
00591 return d->driver->elementDisappear(progress, state->pixmap);
00592 break;
00593 case ActivateAnimation:
00594 break;
00595 }
00596
00597 return state->pixmap;
00598 }
00599
00600 bool Animator::isAnimating() const
00601 {
00602 return (!d->animatedItems.isEmpty() ||
00603 !d->movingItems.isEmpty() ||
00604 !d->animatedElements.isEmpty() ||
00605 !d->customAnims.isEmpty());
00606 }
00607
00608 void Animator::timerEvent(QTimerEvent *event)
00609 {
00610 if (event->timerId() != d->timerId) {
00611 QObject::timerEvent(event);
00612 return;
00613 }
00614
00615 Q_UNUSED(event)
00616 bool animationsRemain = false;
00617 int elapsed = MIN_TICK_RATE;
00618 if (d->time.elapsed() > elapsed) {
00619 elapsed = d->time.elapsed();
00620 }
00621 d->time.restart();
00622
00623
00624 foreach (AnimationState *state, d->animatedItems) {
00625 if (d->animatedItemsToDelete.contains(state)) {
00626 continue;
00627 }
00628
00629 if (state->currentInterval <= elapsed) {
00630
00631 state->currentFrame +=
00632 (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00633 qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00634
00635 if (state->currentFrame < state->frames) {
00636 qreal progress = d->calculateProgress(state->currentFrame * state->interval,
00637 state->frames * state->interval,
00638 state->curve);
00639 d->performAnimation(progress, state);
00640 state->currentInterval = state->interval;
00641 animationsRemain = true;
00642 } else {
00643 d->performAnimation(1, state);
00644 d->animatedItems.erase(d->animatedItems.find(state->item));
00645 emit animationFinished(state->item, state->animation);
00646 d->animatedItemsToDelete.insert(state);
00647 }
00648 } else {
00649 state->currentInterval -= elapsed;
00650 animationsRemain = true;
00651 }
00652 }
00653
00654 foreach (MovementState *state, d->movingItems) {
00655 if (d->movingItemsToDelete.contains(state)) {
00656 continue;
00657 }
00658
00659 if (state->currentInterval <= elapsed) {
00660
00661 state->currentFrame +=
00662 (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00663 qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00664
00665 if (state->currentFrame < state->frames) {
00666
00667 qreal progress = d->calculateProgress(state->currentFrame * state->interval,
00668 state->frames * state->interval,
00669 state->curve);
00670 d->performMovement(progress, state);
00671 animationsRemain = true;
00672 } else {
00673
00674 d->performMovement(1, state);
00675 d->movingItems.erase(d->movingItems.find(state->item));
00676 emit movementFinished(state->item);
00677 d->movingItemsToDelete.insert(state);
00678 }
00679 } else {
00680 state->currentInterval -= elapsed;
00681 animationsRemain = true;
00682 }
00683 }
00684
00685 foreach (ElementAnimationState *state, d->animatedElements) {
00686 if (d->animatedElementsToDelete.contains(state)) {
00687 continue;
00688 }
00689
00690 if (state->currentFrame == state->frames) {
00691
00692
00693
00694
00695
00696
00697 continue;
00698 }
00699
00700 if (state->currentInterval <= elapsed) {
00701
00702
00703
00704
00705
00706 state->currentFrame +=
00707 (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00708 qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00709
00710 state->item->update();
00711 if (state->currentFrame < state->frames) {
00712 state->currentInterval = state->interval;
00713 animationsRemain = true;
00714 } else {
00715 d->animatedElements.remove(state->id);
00716 emit elementAnimationFinished(state->id);
00717 d->animatedElementsToDelete.insert(state);
00718 }
00719 } else {
00720 state->currentInterval -= elapsed;
00721 animationsRemain = true;
00722 }
00723 }
00724
00725 foreach (CustomAnimationState *state, d->customAnims) {
00726 if (d->customAnimsToDelete.contains(state)) {
00727 continue;
00728 }
00729
00730 if (state->currentInterval <= elapsed) {
00731
00732 state->currentFrame +=
00733 (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00734 qMax(1, elapsed / state->frameInterval) : state->frames - state->currentFrame;
00735
00736
00737
00738
00739
00740 if (state->currentFrame < state->frames) {
00741
00742
00743 state->currentInterval = state->interval;
00744 animationsRemain = true;
00745
00746
00747 qreal progress = d->calculateProgress(state->currentFrame * state->interval,
00748 state->frames * state->interval,
00749 state->curve);
00750 if (!QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, progress))) {
00751
00752 QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, progress),
00753 Q_ARG(int, state->id));
00754 }
00755 } else {
00756 if (!QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, 1))) {
00757 QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, 1), Q_ARG(int, state->id));
00758 }
00759 d->customAnims.erase(d->customAnims.find(state->id));
00760 emit customAnimationFinished(state->id);
00761 d->customAnimsToDelete.insert(state);
00762 }
00763 } else {
00764 state->currentInterval -= elapsed;
00765 animationsRemain = true;
00766 }
00767 }
00768
00769 if (!animationsRemain && d->timerId) {
00770 killTimer(d->timerId);
00771 d->timerId = 0;
00772 }
00773
00774 d->cleanupStates();
00775 }
00776
00777 void AnimatorPrivate::init(Animator *q)
00778 {
00779
00780 KConfig c("plasmarc");
00781 KConfigGroup cg(&c, "Animator");
00782 QString pluginName = cg.readEntry("driver", "default");
00783
00784 if (!pluginName.isEmpty()) {
00785 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(pluginName);
00786 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Animator", constraint);
00787
00788 if (!offers.isEmpty()) {
00789 QString error;
00790
00791 KPluginLoader plugin(*offers.first());
00792
00793 if (Plasma::isPluginVersionCompatible(plugin.pluginVersion())) {
00794 driver = offers.first()->createInstance<Plasma::AnimationDriver>(q, QVariantList(), &error);
00795 }
00796
00797 if (!driver) {
00798 kDebug() << "Could not load requested animator "
00799 << offers.first() << ". Error given: " << error;
00800 }
00801 }
00802 }
00803
00804 if (!driver) {
00805 driver = new AnimationDriver(q);
00806 }
00807 }
00808
00809 void AnimatorPrivate::cleanupStates()
00810 {
00811
00812
00813
00814
00815 qDeleteAll(animatedItemsToDelete);
00816 animatedItemsToDelete.clear();
00817 qDeleteAll(animatedElementsToDelete);
00818 animatedElementsToDelete.clear();
00819 qDeleteAll(movingItemsToDelete);
00820 movingItemsToDelete.clear();
00821
00822 QSetIterator<CustomAnimationState*> it(customAnimsToDelete);
00823 while (it.hasNext()) {
00824 CustomAnimationState *state = it.next();
00825 delete[] state->slot;
00826 delete state;
00827 }
00828 customAnimsToDelete.clear();
00829 }
00830
00831 }
00832
00833 #include <animator.moc>