• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libplasma

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 
00023 #include <QGraphicsItem>
00024 
00025 #include <KConfig>
00026 #include <KConfigGroup>
00027 #include <KService>
00028 #include <KServiceTypeTrader>
00029 #include <KGlobalSettings>
00030 
00031 #include "animationdriver.h"
00032 
00033 namespace Plasma
00034 {
00035 
00036 static const int MIN_TICK_RATE_INT = 40;
00037 static const qreal MIN_TICK_RATE = 40;
00038 
00039 struct AnimationState
00040 {
00041     QGraphicsItem *item;
00042     QObject *qobj;
00043     Animator::Animation animation;
00044     Animator::CurveShape curve;
00045     int interval;
00046     int currentInterval;
00047     int frames;
00048     int currentFrame;
00049     int id;
00050 };
00051 
00052 struct ElementAnimationState
00053 {
00054     QGraphicsItem *item;
00055     QObject *qobj;
00056     Animator::CurveShape curve;
00057     Animator::Animation animation;
00058     int interval;
00059     int currentInterval;
00060     int frames;
00061     int currentFrame;
00062     int id;
00063     QPixmap pixmap;
00064 };
00065 
00066 struct MovementState
00067 {
00068     QGraphicsItem *item;
00069     QObject *qobj;
00070     Animator::CurveShape curve;
00071     Animator::Movement movement;
00072     int interval;
00073     int currentInterval;
00074     int frames;
00075     int currentFrame;
00076     QPoint start;
00077     QPoint destination;
00078     int id;
00079 };
00080 
00081 struct CustomAnimationState
00082 {
00083     Animator::CurveShape curve;
00084     int frames;
00085     int currentFrame;
00086     int interval;
00087     int currentInterval;
00088     int id;
00089     QObject* receiver;
00090     char* slot;
00091 };
00092 
00093 class AnimatorPrivate
00094 {
00095     public:
00096 
00097         AnimatorPrivate()
00098             : driver(0),
00099               animId(0),
00100               timerId(0)
00101         {
00102         }
00103 
00104         ~AnimatorPrivate()
00105         {
00106             qDeleteAll(animatedItems);
00107             qDeleteAll(animatedElements);
00108             qDeleteAll(movingItems);
00109 
00110             QMutableMapIterator<int, CustomAnimationState*> it(customAnims);
00111             while (it.hasNext()) {
00112                 delete it.value()->slot;
00113                 delete it.value();
00114                 it.remove();
00115             }
00116 
00117             // Animator is a QObject
00118             // and we don't own the items
00119         }
00120 
00121         qreal calculateProgress(int frames, int currentFrame)
00122         {
00123             if (!(KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects)) {
00124                 return qreal(1.0);
00125             }
00126 
00127             qreal progress = frames;
00128             progress = currentFrame / progress;
00129             progress = qMin(qreal(1.0), qMax(qreal(0.0), progress));
00130             return progress;
00131         }
00132 
00133         void performAnimation(qreal amount, const AnimationState* state)
00134         {
00135             switch (state->animation) {
00136                 case Animator::AppearAnimation:
00137                     driver->itemAppear(amount, state->item);
00138                     break;
00139                 case Animator::DisappearAnimation:
00140                     driver->itemDisappear(amount, state->item);
00141                     if (amount >= 1) {
00142                         state->item->hide();
00143                     }
00144                     break;
00145                 case Animator::ActivateAnimation:
00146                     driver->itemActivated(amount, state->item);
00147                     break;
00148             }
00149         }
00150 
00151         void performMovement(qreal amount, const MovementState* state)
00152         {
00153             switch (state->movement) {
00154                 case Animator::SlideInMovement:
00155                 case Animator::FastSlideInMovement:
00156                     //kDebug() << "performMovement, SlideInMovement";
00157                     driver->itemSlideIn(amount, state->item, state->start, state->destination);
00158                     break;
00159                 case Animator::SlideOutMovement:
00160                 case Animator::FastSlideOutMovement:
00161                     //kDebug() << "performMovement, SlideOutMovement";
00162                     driver->itemSlideOut(amount, state->item, state->start, state->destination);
00163                     break;
00164             }
00165         }
00166 
00167         void init(Animator *q);
00168         void animatedItemDestroyed(QObject*);
00169         void movingItemDestroyed(QObject*);
00170         void animatedElementDestroyed(QObject*);
00171         void customAnimReceiverDestroyed(QObject*);
00172 
00173         AnimationDriver* driver;
00174         int animId;
00175         int timerId;
00176         QTime time;
00177 
00178         //TODO: eventually perhaps we should allow multiple animations simulataneously
00179         //      which would imply changing this to a QMap<QGraphicsItem*, QList<QTimeLine*> >
00180         //      and really making the code fun ;)
00181         QMap<QGraphicsItem*, AnimationState*> animatedItems;
00182         QMap<QGraphicsItem*, MovementState*> movingItems;
00183         QMap<int, ElementAnimationState*> animatedElements;
00184         QMap<int, CustomAnimationState*> customAnims;
00185 };
00186 
00187 class AnimatorSingleton
00188 {
00189     public:
00190         Animator self;
00191 };
00192 
00193 K_GLOBAL_STATIC( AnimatorSingleton, privateSelf )
00194 
00195 Animator* Animator::self()
00196 {
00197     return &privateSelf->self;
00198 }
00199 
00200 
00201 Animator::Animator(QObject * parent)
00202     : QObject(parent),
00203       d(new AnimatorPrivate)
00204 {
00205     d->init(this);
00206 }
00207 
00208 Animator::~Animator()
00209 {
00210     delete d;
00211 }
00212 
00213 void AnimatorPrivate::animatedItemDestroyed(QObject* o)
00214 {
00215     //kDebug() << "testing for" << (void*)o;
00216     QMutableMapIterator<QGraphicsItem*, AnimationState*> it(animatedItems);
00217     while (it.hasNext()) {
00218         it.next();
00219         //kDebug() << "comparing against" << it.value()->qobj;
00220         if (it.value()->qobj == o) {
00221             kDebug() << "found deleted animated item";
00222             delete it.value();
00223             it.remove();
00224         }
00225     }
00226 }
00227 
00228 void AnimatorPrivate::movingItemDestroyed(QObject* o)
00229 {
00230     QMutableMapIterator<QGraphicsItem*, MovementState*> it(movingItems);
00231     while (it.hasNext()) {
00232         it.next();
00233         if (it.value()->qobj == o) {
00234             delete it.value();
00235             it.remove();
00236         }
00237     }
00238 }
00239 
00240 void AnimatorPrivate::animatedElementDestroyed(QObject* o)
00241 {
00242     QMutableMapIterator<int, ElementAnimationState*> it(animatedElements);
00243     while (it.hasNext()) {
00244         it.next();
00245         if (it.value()->qobj == o) {
00246             delete it.value();
00247             it.remove();
00248         }
00249     }
00250 }
00251 
00252 void AnimatorPrivate::customAnimReceiverDestroyed(QObject* o)
00253 {
00254     QMutableMapIterator<int, CustomAnimationState*> it(customAnims);
00255     while (it.hasNext()) {
00256         if (it.next().value()->receiver == o) {
00257             delete it.value()->slot;
00258             delete it.value();
00259             it.remove();
00260         }
00261     }
00262 }
00263 
00264 int Animator::animateItem(QGraphicsItem* item, Animation animation)
00265 {
00266      //kDebug();
00267     // get rid of any existing animations on this item.
00268     //TODO: shoudl we allow multiple anims per item?
00269     QMap<QGraphicsItem*, AnimationState*>::iterator it = d->animatedItems.find(item);
00270     if (it != d->animatedItems.end()) {
00271         delete it.value();
00272         d->animatedItems.erase(it);
00273     }
00274 
00275     int frames = d->driver->animationFps(animation);
00276 
00277     if (frames < 1) {
00278         // evidently this animator doesn't have an implementation
00279         // for this Animation
00280         return -1;
00281     }
00282 
00283     AnimationState* state = new AnimationState;
00284     state->id = ++d->animId;
00285     state->item = item;
00286     state->animation = animation;
00287     state->curve = d->driver->animationCurve(animation);
00288     //TODO: variance in times based on the value of animation
00289     state->frames = frames / 3;
00290     state->currentFrame = 0;
00291     state->interval = d->driver->animationDuration(animation) / state->frames;
00292     state->interval = (state->interval / MIN_TICK_RATE) * MIN_TICK_RATE;
00293     state->currentInterval = state->interval;
00294     state->qobj = dynamic_cast<QObject*>(item);
00295 
00296      if (state->qobj) {
00297          //kDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!! got us an object!";
00298          disconnect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(animatedItemDestroyed(QObject*)));
00299          connect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(animatedItemDestroyed(QObject*)));
00300      }
00301 
00302     d->animatedItems[item] = state;
00303     d->performAnimation(0, state);
00304 
00305     if (!d->timerId) {
00306         d->timerId = startTimer(MIN_TICK_RATE);
00307         d->time.restart();
00308     }
00309 
00310     return state->id;
00311 }
00312 
00313 int Animator::moveItem(QGraphicsItem* item, Movement movement, const QPoint &destination)
00314 {
00315      //kDebug();
00316      QMap<QGraphicsItem*, MovementState*>::iterator it = d->movingItems.find(item);
00317      if (it != d->movingItems.end()) {
00318           delete it.value();
00319           d->movingItems.erase(it);
00320      }
00321 
00322      int frames = d->driver->movementAnimationFps(movement);
00323      if (frames <= 1) {
00324           // evidently this animator doesn't have an implementation
00325           // for this Animation
00326           return -1;
00327      }
00328 
00329      MovementState* state = new MovementState;
00330      state->id = ++d->animId;
00331      state->destination = destination;
00332      state->start = item->pos().toPoint();
00333      state->item = item;
00334      state->movement = movement;
00335      state->curve = d->driver->movementAnimationCurve(movement);
00336      //TODO: variance in times based on the value of animation
00337      int duration = d->driver->movementAnimationDuration(movement);
00338      state->frames = (duration / 1000.0) * frames;
00339      state->currentFrame = 0;
00340      state->interval = duration / state->frames;
00341      state->interval -= qMax(MIN_TICK_RATE_INT, state->interval % MIN_TICK_RATE_INT);
00342 //     state->interval = (state->interval / MIN_TICK_RATE) * MIN_TICK_RATE;
00343      //kDebug() << "interval of" << state->interval;
00344      state->currentInterval = state->interval;
00345      state->qobj = dynamic_cast<QObject*>(item);
00346 
00347      if (state->qobj) {
00348         disconnect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(movingItemDestroyed(QObject*)));
00349         connect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(movingItemDestroyed(QObject*)));
00350      }
00351 
00352      d->movingItems[item] = state;
00353      d->performMovement(0, state);
00354 
00355      if (!d->timerId) {
00356           d->timerId = startTimer(MIN_TICK_RATE);
00357           d->time.restart();
00358      }
00359 
00360      return state->id;
00361 }
00362 
00363 int Animator::customAnimation(int frames, int duration, Animator::CurveShape curve,
00364                                      QObject* receiver, const char* slot)
00365 {
00366     if (frames < 1 || duration < 1 || !receiver || !slot) {
00367         return -1;
00368     }
00369 
00370     CustomAnimationState *state = new CustomAnimationState;
00371     state->id = ++d->animId;
00372     state->frames = frames;
00373     state->currentFrame = 0;
00374     state->curve = curve;
00375     state->interval = duration / qreal(state->frames);
00376     state->interval = qMax( 1, state->interval );
00377     state->interval = (state->interval / MIN_TICK_RATE) * MIN_TICK_RATE;
00378     state->currentInterval = state->interval;
00379     state->receiver = receiver;
00380     state->slot = qstrdup(slot);
00381 
00382     d->customAnims[state->id] = state;
00383 
00384     disconnect(receiver, SIGNAL(destroyed(QObject*)),
00385                this, SLOT(customAnimReceiverDestroyed(QObject*)));
00386     connect(receiver, SIGNAL(destroyed(QObject*)),
00387             this, SLOT(customAnimReceiverDestroyed(QObject*)));
00388 
00389     // try with only progress as argument
00390     if (!QMetaObject::invokeMethod(receiver, slot, Q_ARG(qreal, 0))) {
00391         //try to pass also the animation id
00392         QMetaObject::invokeMethod(receiver, slot, Q_ARG(qreal, 0), Q_ARG(int, state->id));
00393     }
00394 
00395     if (!d->timerId) {
00396         d->timerId = startTimer(MIN_TICK_RATE);
00397         d->time.restart();
00398     }
00399 
00400     return state->id;
00401 }
00402 
00403 void Animator::stopCustomAnimation(int id)
00404 {
00405     QMap<int, CustomAnimationState*>::iterator it = d->customAnims.find(id);
00406     if (it != d->customAnims.end()) {
00407         delete [] it.value()->slot;
00408         delete it.value();
00409         d->customAnims.erase(it);
00410     }
00411     //kDebug() << "stopCustomAnimation(AnimId " << id << ") done";
00412 }
00413 
00414 void Animator::stopItemAnimation(int id)
00415 {
00416     QMutableMapIterator<QGraphicsItem*, AnimationState*> it(d->animatedItems);
00417     while (it.hasNext()) {
00418         it.next();
00419         if (it.value()->id == id) {
00420             delete it.value();
00421             it.remove();
00422             return;
00423         }
00424     }
00425 }
00426 
00427 void Animator::stopItemMovement(int id)
00428 {
00429     QMutableMapIterator<QGraphicsItem*, MovementState*> it(d->movingItems);
00430     while (it.hasNext()) {
00431         it.next();
00432         if (it.value()->id == id) {
00433             delete it.value();
00434             it.remove();
00435             return;
00436         }
00437     }
00438 }
00439 
00440 int Animator::animateElement(QGraphicsItem *item, Animation animation)
00441 {
00442     //kDebug() << "startElementAnimation(AnimId " << animation << ")";
00443     ElementAnimationState *state = new ElementAnimationState;
00444     state->item = item;
00445     state->curve = d->driver->elementAnimationCurve(animation);
00446     state->animation = animation;
00447     //TODO: variance in times based on the value of animation
00448     state->frames = d->driver->elementAnimationFps(animation) / 5;
00449     state->currentFrame = 0;
00450     state->interval = d->driver->elementAnimationDuration(animation) / state->frames;
00451     state->interval = (state->interval / MIN_TICK_RATE) * MIN_TICK_RATE;
00452     state->currentInterval = state->interval;
00453     state->id = ++d->animId;
00454     state->qobj = dynamic_cast<QObject*>(item);
00455 
00456      if (state->qobj) {
00457          disconnect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(animatedElementDestroyed(QObject*)));
00458          connect(state->qobj, SIGNAL(destroyed(QObject*)), this, SLOT(animatedElementDestroyed(QObject*)));
00459      }
00460 
00461     //kDebug() << "animateElement " << animation << ", interval: " << state->interval << ", frames: " << state->frames;
00462     bool needTimer = true;
00463     if (state->frames < 1) {
00464         state->frames = 1;
00465         state->currentFrame = 1;
00466         needTimer = false;
00467     }
00468 
00469     d->animatedElements[state->id] = state;
00470     
00471     //kDebug() << "startElementAnimation(AnimId " << animation << ") returning " << state->id;
00472     if (needTimer && !d->timerId) {
00473         // start a 20fps timer;
00474         //TODO: should be started at the maximum frame rate needed only?
00475         d->timerId = startTimer(MIN_TICK_RATE);
00476         d->time.restart();
00477     }
00478     return state->id;
00479 }
00480 
00481 void Animator::stopElementAnimation(int id)
00482 {
00483     QMap<int, ElementAnimationState*>::iterator it = d->animatedElements.find(id);
00484     if (it != d->animatedElements.end()) {
00485         delete it.value();
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     QMap<int, ElementAnimationState*>::iterator it = d->animatedElements.find(id);
00494 
00495     if (it == d->animatedElements.end()) {
00496         kDebug() << "Animator::setInitialPixmap(" << id << ") found no entry for it!";
00497         return;
00498     }
00499 
00500     it.value()->pixmap = pixmap;
00501 }
00502 
00503 QPixmap Animator::currentPixmap(int id)
00504 {
00505     QMap<int, ElementAnimationState*>::const_iterator it = d->animatedElements.find(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 = state->frames;
00514     //kDebug() << "Animator::currentPixmap(" << id <<   " at " << progress;
00515     progress = state->currentFrame / progress;
00516     progress = qMin(qreal(1.0), qMax(qreal(0.0), progress));
00517     //kDebug() << "Animator::currentPixmap(" << id <<   " at " << progress;
00518 
00519     switch (state->animation) {
00520         case AppearAnimation:
00521             return d->driver->elementAppear(progress, state->pixmap);
00522             break;
00523         case DisappearAnimation:
00524             return d->driver->elementDisappear(progress, state->pixmap);
00525             break;
00526         case ActivateAnimation:
00527             break;
00528     }
00529 
00530     return state->pixmap;
00531 }
00532 
00533 bool Animator::isAnimating() const
00534 {
00535     return (!d->animatedItems.isEmpty() ||
00536             !d->movingItems.isEmpty() ||
00537             !d->animatedElements.isEmpty() ||
00538             !d->customAnims.isEmpty());
00539 }
00540 
00541 void Animator::timerEvent(QTimerEvent *event)
00542 {
00543     Q_UNUSED(event)
00544     bool animationsRemain = false;
00545     int elapsed = MIN_TICK_RATE;
00546     if (d->time.elapsed() > elapsed) {
00547         elapsed = d->time.elapsed();
00548     }
00549     d->time.restart();
00550     //kDebug() << "timeEvent, elapsed time: " << elapsed;
00551 
00552     foreach (AnimationState* state, d->animatedItems) {
00553         if (state->currentInterval <= elapsed) {
00554             // we need to step forward!
00555             state->currentFrame += (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00556                                    qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00557 
00558             if (state->currentFrame < state->frames) {
00559                 qreal progress = d->calculateProgress(state->frames, state->currentFrame);
00560                 d->performAnimation(progress, state);
00561                 state->currentInterval = state->interval;
00562                 //TODO: calculate a proper interval based on the curve
00563                 state->interval *= 1 - progress;
00564                 animationsRemain = true;
00565             } else {
00566                 d->performAnimation(1, state);
00567                 d->animatedItems.erase(d->animatedItems.find(state->item));
00568                 emit animationFinished(state->item, state->animation);
00569                 delete state;
00570             }
00571         } else {
00572             state->currentInterval -= elapsed;
00573             animationsRemain = true;
00574         }
00575     }
00576 
00577     foreach (MovementState* state, d->movingItems) {
00578         if (state->currentInterval <= elapsed) {
00579             // we need to step forward!
00580             state->currentFrame += (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00581                                    qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00582 
00583             if (state->currentFrame < state->frames) {
00584                 //kDebug() << "movement";
00585                 d->performMovement(d->calculateProgress(state->frames, state->currentFrame), state);
00586                 //TODO: calculate a proper interval based on the curve
00587                 state->currentInterval = state->interval;
00588                 animationsRemain = true;
00589             } else {
00590                 //kDebug() << "movement";
00591                 d->performMovement(1, state);
00592                 d->movingItems.erase(d->movingItems.find(state->item));
00593                 emit movementFinished(state->item);
00594                 delete state;
00595             }
00596         } else {
00597             state->currentInterval -= elapsed;
00598             animationsRemain = true;
00599         }
00600     }
00601 
00602     foreach (ElementAnimationState* state, d->animatedElements) {
00603         if (state->currentFrame == state->frames) {
00604             //kDebug() << "skipping" << state->id << "as its already at frame" << state->currentFrame << "of" << state->frames;
00605             // since we keep element animations around until they are
00606             // removed, we will end up with finished animations in the queue;
00607             // just skip them
00608             //TODO: should we move them to a separate QMap?
00609             continue;
00610         }
00611 
00612         if (state->currentInterval <= elapsed) {
00613             // we need to step forward!
00614             /*kDebug() << "stepping forwards element anim " << state->id << " from " << state->currentFrame
00615                     << " by " << qMax(1, elapsed / state->interval) << " to "
00616                     << state->currentFrame + qMax(1, elapsed / state->interval) << endl;*/
00617             state->currentFrame += (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00618                                    qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00619 
00620             state->item->update();
00621             if (state->currentFrame < state->frames) {
00622                 state->currentInterval = state->interval;
00623                 //TODO: calculate a proper interval based on the curve
00624                 state->interval *= 1 - d->calculateProgress(state->frames, state->currentFrame);
00625                 animationsRemain = true;
00626             } else {
00627                 d->animatedElements.remove(state->id);
00628                 emit elementAnimationFinished(state->id);
00629                 delete state;
00630             }
00631         } else {
00632             state->currentInterval -= elapsed;
00633             animationsRemain = true;
00634         }
00635     }
00636 
00637     foreach (CustomAnimationState *state, d->customAnims) {
00638         if (state->currentInterval <= elapsed) {
00639             // advance the frame
00640             state->currentFrame += (KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects) ?
00641                                    qMax(1, elapsed / state->interval) : state->frames - state->currentFrame;
00642             /*kDebug() << "custom anim for" << state->receiver << "to slot" << state->slot
00643                      << "with interval of" << state->interval << "at frame" << state->currentFrame;*/
00644 
00645             if (state->currentFrame < state->frames) {
00646                 //kDebug () << "not the final frame";
00647                 //TODO: calculate a proper interval based on the curve
00648                 state->currentInterval = state->interval;
00649                 animationsRemain = true;
00650                 // signal the object
00651                 // try with only progress as argument
00652                 if (!QMetaObject::invokeMethod(state->receiver, state->slot,
00653                                           Q_ARG(qreal,
00654                                                 d->calculateProgress(state->frames, state->currentFrame)))) {
00655                 //if fails try to add the animation id
00656                     QMetaObject::invokeMethod(state->receiver, state->slot,
00657                                             Q_ARG(qreal,
00658                                                   d->calculateProgress(state->frames, state->currentFrame)), Q_ARG(int, state->id));
00659                 }
00660             } else {
00661                 if (!QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, 1))) {
00662                     QMetaObject::invokeMethod(state->receiver, state->slot, Q_ARG(qreal, 1), Q_ARG(int, state->id));
00663                 }
00664                 d->customAnims.erase(d->customAnims.find(state->id));
00665                 emit customAnimationFinished(state->id);
00666                 delete [] state->slot;
00667                 delete state;
00668             }
00669         } else {
00670             state->currentInterval -= elapsed;
00671             animationsRemain = true;
00672         }
00673     }
00674 
00675     if (!animationsRemain && d->timerId) {
00676         killTimer(d->timerId);
00677         d->timerId = 0;
00678     }
00679 }
00680 
00681 void AnimatorPrivate::init(Animator *q)
00682 {
00683     //FIXME: usage between different applications?
00684     KConfig c("plasmarc");
00685     KConfigGroup cg(&c, "Animator");
00686     QString pluginName = cg.readEntry("driver", "default");
00687 
00688     if (!pluginName.isEmpty()) {
00689         QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(pluginName);
00690         KService::List offers = KServiceTypeTrader::self()->query("Plasma/Animator", constraint);
00691 
00692         if (!offers.isEmpty()) {
00693             QString error;
00694 
00695             KPluginLoader plugin(*offers.first());
00696 
00697             if (Plasma::isPluginVersionCompatible(plugin.pluginVersion()))
00698                 driver = offers.first()->createInstance<Plasma::AnimationDriver>(0, QVariantList(), &error);
00699 
00700             if (!driver) {
00701                 kDebug() << "Could not load requested animator " << offers.first() << ". Error given: " << error;
00702             }
00703         }
00704     }
00705 
00706     if (!driver) {
00707         driver = new AnimationDriver(q);
00708     }
00709 }
00710 
00711 } // namespace Plasma
00712 
00713 #include <animator.moc>

libplasma

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

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
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