• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Plasma

animator.cpp

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

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal