src/hbcore/effects/hbeffectgroup.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 5 627c4a0fd0e7
equal deleted inserted replaced
0:16d8024aca5e 1:f7ac710697a9
    26 #include "hbeffectgroup_p.h"
    26 #include "hbeffectgroup_p.h"
    27 #include "hbeffectabstract_p.h"
    27 #include "hbeffectabstract_p.h"
    28 #include "hbeffect.h"
    28 #include "hbeffect.h"
    29 #include "hbtimer_p.h"
    29 #include "hbtimer_p.h"
    30 #include "hbeffectdef_p.h"
    30 #include "hbeffectdef_p.h"
    31 #include "hbeffectinternal_p.h"
       
    32 #include "hbmainwindow.h"
    31 #include "hbmainwindow.h"
    33 #include "hbinstance.h"
    32 #include "hbinstance.h"
    34 
    33 
    35 #include <qglobal.h>
    34 #include <qglobal.h>
    36 #include <QMetaObject>
    35 #include <QMetaObject>
    37 #include <QTransform>
    36 #include <QTransform>
    38 #include <QGraphicsItem>
    37 #include <QGraphicsItem>
    39 #include <QGraphicsWidget>
    38 #include <QGraphicsWidget>
    40 #include <QGraphicsView>
    39 #include <QGraphicsView>
    41 #include <QTimer>
       
    42 
    40 
    43 #ifdef HB_FILTER_EFFECTS
    41 #ifdef HB_FILTER_EFFECTS
    44 #include "hbvgeffect_p.h"
    42 #include "hbvgeffect_p.h"
    45 #include "hbvgchainedeffect_p.h"
    43 #include "hbvgchainedeffect_p.h"
    46 #endif
    44 #endif
    47 
       
    48 
    45 
    49 HbEffectGroup::HbEffectGroup(
    46 HbEffectGroup::HbEffectGroup(
    50     const QString &effectEventType, 
    47     const QString &effectEventType, 
    51     QGraphicsItem *registrationItem, 
    48     QGraphicsItem *registrationItem, 
    52     QGraphicsItem *targetItem,
    49     QGraphicsItem *targetItem,
    61       mFinishedCount(0),
    58       mFinishedCount(0),
    62       mObserver(0),
    59       mObserver(0),
    63       mRunningState(NotRunning),
    60       mRunningState(NotRunning),
    64       mLooping(false),
    61       mLooping(false),
    65       mView(0),
    62       mView(0),
    66       mHideWhenFinished(false)
    63       mEffectFlags(HbEffectInternal::Normal),
       
    64       mRegItemHidden(false),
       
    65       mTargetItemHidden(false)
    67 {
    66 {
    68 }
    67 }
    69 
    68 
    70 HbEffectGroup::~HbEffectGroup()
    69 HbEffectGroup::~HbEffectGroup()
    71 {
    70 {
   156         if (gvw)
   155         if (gvw)
   157             gv = gvw->mainWindow();
   156             gv = gvw->mainWindow();
   158     }
   157     }
   159     QTransform transform;
   158     QTransform transform;
   160 
   159 
   161     Q_FOREACH(HbEffectAbstract *effect, mEffects) {
   160     foreach (HbEffectAbstract *effect, mEffects) {
   162         if (effect)
   161         if (effect)
   163             effect->updateItemTransform(transform);
   162             effect->updateItemTransform(transform);
   164     }
   163     }
   165     if (!gv)
   164     if (!gv) {
   166         mTargetItem->setTransform(transform);	
   165         mTargetItem->setTransform(transform);
   167     else 
   166     } else {
   168         gv->setTransform(transform);
   167         gv->setTransform(transform);
       
   168     }
   169 }
   169 }
   170 
   170 
   171 bool HbEffectGroup::dirty() const
   171 bool HbEffectGroup::dirty() const
   172 {
   172 {
   173     return mDirty;
   173     return mDirty;
   198     return mLooping;
   198     return mLooping;
   199 }
   199 }
   200 
   200 
   201 void HbEffectGroup::pause()
   201 void HbEffectGroup::pause()
   202 {
   202 {
   203     Q_FOREACH(HbEffectAbstract *effect, mEffects) {
   203     foreach (HbEffectAbstract *effect, mEffects) {
   204         effect->pause();
   204         effect->pause();
   205     }
   205     }
   206 }
   206 }
   207 
   207 
   208 void HbEffectGroup::resume()
   208 void HbEffectGroup::resume()
   209 {
   209 {
   210     Q_FOREACH(HbEffectAbstract *effect, mEffects) {
   210     foreach (HbEffectAbstract *effect, mEffects) {
   211         effect->resume();
   211         effect->resume();
   212     }
   212     }
   213 }
   213 }
   214 
   214 
   215 const QVariant &HbEffectGroup::userData() const
   215 const QVariant &HbEffectGroup::userData() const
   300         mFinishedCount = 0;
   300         mFinishedCount = 0;
   301     }
   301     }
   302 
   302 
   303     // First resolve parameters and set the start states for all the effects.
   303     // First resolve parameters and set the start states for all the effects.
   304     // This is done before starting the effect animations to avoid screen flickering.
   304     // This is done before starting the effect animations to avoid screen flickering.
   305 
       
   306     QTransform transform;
   305     QTransform transform;
   307 
   306     foreach (HbEffectAbstract *effect, mEffects) {
   308     Q_FOREACH(HbEffectAbstract *effect, mEffects) {
       
   309         // Resolve parameters etc.
   307         // Resolve parameters etc.
   310         effect->init();
   308         effect->init();
   311         if (effect->interval() == 0) {
   309         if (effect->interval() == 0) {
   312             // Set start state if effect starts immediately
   310             // Set start state if effect starts immediately
   313             effect->setStartState(transform);
   311             effect->setStartState(transform);
   314         }
   312         }
   315     }
   313     }
   316 
       
   317     mTargetItem->setTransform(transform);
   314     mTargetItem->setTransform(transform);
       
   315 
       
   316     // Make the target item visible, if needed, now that the start state is set
       
   317     // for all the effects.
       
   318     if (mEffectFlags.testFlag(HbEffectInternal::ShowItemOnFirstUpdate)) {
       
   319         // In case of a view switch the registration item may be the HbView
       
   320         // itself and the target item is just the view's content widget. Make
       
   321         // sure both are visible.
       
   322         mTargetItem->setVisible(true);
       
   323         if (mRegistrationItem != mTargetItem) {
       
   324             mRegistrationItem->setVisible(true);
       
   325         }
       
   326     }
       
   327 
       
   328     mRegItemHidden = false;
       
   329     mTargetItemHidden = false;
   318 
   330 
   319     if (mEffects.empty()) {
   331     if (mEffects.empty()) {
   320         // No effect exists but user wants notification when effect finishes. 
   332         // No effect exists but user wants notification when effect finishes. 
   321         // Let the user do whatever he wanted to do when effect finishes.
   333         // Let the user do whatever he wanted to do when effect finishes.
   322         invokeObserver(Hb::EffectNotStarted);
   334         invokeObserver(Hb::EffectNotStarted);
   323     }        
   335     } else {
   324     else {
       
   325         // Start state has been set for all the effects,
   336         // Start state has been set for all the effects,
   326         // next step is to start the effect animations.
   337         // next step is to start the effect animations.
   327         // Before that, resolve the view where the effect belongs if the effect is looping.
   338         // Before that, resolve the view where the effect belongs if the effect is looping.
   328         // This is needed for being able to pause looping effects when their view is inactive.
   339         // This is needed for being able to pause looping effects when their view is inactive.
   329         if (isLooping()) {
   340         if (isLooping()) {
   330             resolveView();
   341             resolveView();
   331         }
   342         }
   332 
   343         foreach (HbEffectAbstract *effect, mEffects) {
   333         Q_FOREACH(HbEffectAbstract *effect, mEffects) {
       
   334             // If the starttime is zero, start effect immediately
   344             // If the starttime is zero, start effect immediately
   335             if (effect->interval() == 0) {
   345             if (effect->interval() == 0) {
   336                 effect->start(); // This may call group's effectFinished if the effect was empty.
   346                 effect->start(); // This may call group's effectFinished if the effect was empty.
   337             } else {
   347             } else {
   338                 //Else register the effect to timeline to wait its turn.
   348                 //Else register the effect to timeline to wait its turn.
   340             }
   350             }
   341         }
   351         }
   342     }
   352     }
   343 }
   353 }
   344 
   354 
   345 void HbEffectGroup::resolveView() {
   355 void HbEffectGroup::resolveView()
   346     if (!mView) {
   356 {
   347         if (mTargetItem) {
   357     if (!mView && mTargetItem) {
   348             QGraphicsScene *scene = mTargetItem->scene();
   358         QGraphicsScene *scene = mTargetItem->scene();
   349             if (scene) {
   359         if (scene) {
   350                 // Resolve the main window having the same scene that the item belongs to
   360             // Resolve the main window having the same scene that the item belongs to
   351                 QList<HbMainWindow *> windowList = hbInstance->allMainWindows();
   361             QList<HbMainWindow *> windowList = hbInstance->allMainWindows();
   352                 Q_FOREACH(const HbMainWindow *window, windowList) {
   362             foreach (const HbMainWindow *window, windowList) {
   353                     if (window->scene() == scene) {
   363                 if (window->scene() == scene) {
   354                         mView = window->currentView();
   364                     mView = window->currentView();
   355                         break;
   365                     break;
   356                     }
       
   357                 }
   366                 }
   358             }
   367             }
   359         }
   368         }
   360     }
   369     }
   361 }
   370 }
   362 
   371 
   363 bool HbEffectGroup::hasTranslateEffect() const
   372 bool HbEffectGroup::hasTranslateEffect() const
   364 {
   373 {
   365     foreach(HbEffectAbstract *effect, mEffects) {
   374     foreach (HbEffectAbstract *effect, mEffects) {
   366         if (effect->name() == HB_EFFECT_NAME_TRANSLATE) {
   375         if (effect->name() == HB_EFFECT_NAME_TRANSLATE) {
   367             return true;
   376             return true;
   368         }
   377         }
   369     }
   378     }
   370 
       
   371     return false;
   379     return false;
   372 }
   380 }
   373 
   381 
   374 bool HbEffectGroup::hasRotateEffect() const
   382 bool HbEffectGroup::hasRotateEffect() const
   375 {
   383 {
   376     foreach(HbEffectAbstract *effect, mEffects) {
   384     foreach (HbEffectAbstract *effect, mEffects) {
   377         if (effect->name() == HB_EFFECT_NAME_ROTATE) {
   385         if (effect->name() == HB_EFFECT_NAME_ROTATE) {
   378             return true;
   386             return true;
   379         }
   387         }
   380     }
   388     }
   381 
   389 
   382     return false;
   390     return false;
   383 }
   391 }
   384 
   392 
   385 bool HbEffectGroup::hasScaleEffect() const
   393 bool HbEffectGroup::hasScaleEffect() const
   386 {
   394 {
   387     foreach(HbEffectAbstract *effect, mEffects) {
   395     foreach (HbEffectAbstract *effect, mEffects) {
   388         if (effect->name() == HB_EFFECT_NAME_SCALE) {
   396         if (effect->name() == HB_EFFECT_NAME_SCALE) {
   389             return true;
   397             return true;
   390         }
   398         }
   391     }
   399     }
   392 
       
   393     return false;
   400     return false;
   394 }
   401 }
   395 
   402 
   396 bool HbEffectGroup::hasOpacityEffect() const
   403 bool HbEffectGroup::hasOpacityEffect() const
   397 {
   404 {
   398     foreach(HbEffectAbstract *effect, mEffects) {
   405     foreach (HbEffectAbstract *effect, mEffects) {
   399         if (effect->name() == HB_EFFECT_NAME_OPACITY) {
   406         if (effect->name() == HB_EFFECT_NAME_OPACITY) {
   400             return true;
   407             return true;
   401         }
   408         }
   402     }
   409     }
   403 
       
   404     return false;
   410     return false;
   405 }
   411 }
   406 
   412 
   407 void HbEffectGroup::doHideEffect(const QTransform *transform, bool opacityEffectUsed)
   413 void HbEffectGroup::doClearEffect(const QTransform *transform, bool opacityEffectUsed)
   408 {
   414 {
       
   415     // Hide registration item if needed.
       
   416     if (mEffectFlags.testFlag(HbEffectInternal::HideRegItemBeforeClearingEffect)) {
       
   417         // We get here also from cancelAll() when starting a new effect so there
       
   418         // must be some guarding to do the hiding only once.
       
   419         if (!mRegItemHidden) {
       
   420             mRegItemHidden = true;
       
   421             // This flag affects the registration item only.
       
   422             mRegistrationItem->setVisible(false);
       
   423         }
       
   424     }
       
   425     // Same for the target item.
       
   426     if (mEffectFlags.testFlag(HbEffectInternal::HideTargetItemBeforeClearingEffect)) {
       
   427         if (!mTargetItemHidden) {
       
   428             mTargetItemHidden = true;
       
   429             mTargetItem->setVisible(false);
       
   430         }
       
   431     }
       
   432     // Reset the transformation.
   409     mTargetItem->setTransform(transform ? *transform : QTransform());
   433     mTargetItem->setTransform(transform ? *transform : QTransform());
       
   434     // Reset opacity.
   410     if (opacityEffectUsed) {
   435     if (opacityEffectUsed) {
   411         // Hide opacity effect by setting item fully opaque regardless of what
   436         // Hide opacity effect by setting item fully opaque regardless of what
   412         // its opacity value was before the effect.
   437         // its opacity value was before the effect.
   413         mTargetItem->setOpacity(1.0f);
   438         mTargetItem->setOpacity(1.0f);
   414     }
   439     }
       
   440     // Reset filter effects.
   415 #ifdef HB_FILTER_EFFECTS            
   441 #ifdef HB_FILTER_EFFECTS            
   416     deactivateVgEffect();
   442     deactivateVgEffect();
   417 #endif            
   443 #endif            
   418 }
   444 }
   419 
   445 
   420 void HbEffectGroup::cancelAll(bool sendCallback, bool itemIsValid, bool hideEffect, const QTransform &initialItemTransform)
   446 void HbEffectGroup::cancelAll(bool sendCallback, bool itemIsValid, bool clearEffect, const QTransform &initialItemTransform)
   421 {
   447 {
       
   448     // No checks for running state here. The cancellation (esp. the clearing of
       
   449     // the effect (if needed)) must be done always, regardless of the effect's
       
   450     // state.
       
   451 
   422     QTransform transform;
   452     QTransform transform;
   423     bool opacityEffectUsed = false;
   453     bool opacityEffectUsed = false;
   424 
   454 
   425     Q_FOREACH(HbEffectAbstract *effect, mEffects) {
   455     foreach (HbEffectAbstract *effect, mEffects) {
   426         if (effect) {
   456         if (effect) {
   427             HbTimer::instance()->unregisterEntry(effect);
   457             HbTimer::instance()->unregisterEntry(effect);
   428             effect->cancel(transform, itemIsValid);
   458             effect->cancel(transform, itemIsValid);
   429             if (effect->name() == HB_EFFECT_NAME_OPACITY) {
   459             if (effect->name() == HB_EFFECT_NAME_OPACITY) {
   430                 opacityEffectUsed = true;
   460                 opacityEffectUsed = true;
   432         }
   462         }
   433     }
   463     }
   434 
   464 
   435     if (itemIsValid) {
   465     if (itemIsValid) {
   436         // If effect needs to be removed, reset transform matrix and deactivate VG effect
   466         // If effect needs to be removed, reset transform matrix and deactivate VG effect
   437         if (hideEffect || mHideWhenFinished) {
   467         if (clearEffect || mEffectFlags.testFlag(HbEffectInternal::ClearEffectWhenFinished)) {
   438             doHideEffect(&initialItemTransform, opacityEffectUsed);
   468             doClearEffect(&initialItemTransform, opacityEffectUsed);
   439         } else { // Otherwise set transform corresponding to the end state of the effect
   469         } else { // Otherwise set transform corresponding to the end state of the effect
   440             mTargetItem->setTransform(initialItemTransform * transform);
   470             mTargetItem->setTransform(initialItemTransform * transform);
   441         }
   471         }
   442     }
   472     }
   443 
   473 
   444     // Do not set this to NotRunning before effect->cancel has been called because filter
   474     // Do not set this to NotRunning before effect->cancel has been called because filter
   445     // effects cancel does stuff that requires group->isRunning() return true.
   475     // effects cancel does stuff that requires group->isRunning() return true.
   446     mRunningState = NotRunning;
   476     mRunningState = NotRunning;
   447 
   477 
   448     // Invoke observer with cancel signal
   478     // Invoke observer with cancel signal
   449     if (sendCallback)
   479     if (sendCallback) {
   450         invokeObserver(Hb::EffectCancelled);
   480         invokeObserver(Hb::EffectCancelled);
       
   481     }
   451 }
   482 }
   452 
   483 
   453 void HbEffectGroup::effectFinished(Hb::EffectEvent reason)
   484 void HbEffectGroup::effectFinished(Hb::EffectEvent reason)
   454 {
   485 {
   455     // Inform the animated item when the whole effect group has finished.
   486     // Inform the animated item when the whole effect group has finished.
   456     if (++mFinishedCount == mEffects.count()) {
   487     if (++mFinishedCount == mEffects.count()) {
   457         mFinishedCount = 0;
   488         mFinishedCount = 0;
   458         
   489 
   459         // The animation framework funnily enough sends the finished signal before updating the animation with the final
   490         // The animation framework funnily enough sends the finished signal
   460         // value, so here we set running state to NotRunning asynchronously so the effect's final value gets still updated.
   491         // before updating the animation with the final value, so here we set
       
   492         // running state to NotRunning asynchronously so the effect's final
       
   493         // value gets still updated.
   461         mRunningState = FinishInProgress;
   494         mRunningState = FinishInProgress;
   462         QTimer::singleShot(0, this, SLOT(clearEffectRunning()));
   495         QMetaObject::invokeMethod(this, "clearEffectRunning", Qt::QueuedConnection);
   463 
   496 
   464         // Send callback if observer has been provided
   497         // Send callback if observer has been provided. Note that with the
       
   498         // EffectFinished reason the observer will be invoked asynchronously.
   465         invokeObserver(reason);
   499         invokeObserver(reason);
   466     }
   500     }
   467 
   501 
   468     // The effect group object is not deleted here,
   502     // The effect group object is not deleted here,
   469     // because it would need to be removed from the list of the effect groups in
   503     // because it would need to be removed from the list of the effect groups in
   476     // Comes here when effect has finished and running state is set to NotRunning asynchronously.
   510     // Comes here when effect has finished and running state is set to NotRunning asynchronously.
   477     // Only set running state to 'NotRunning' if the finish is still in progress, i.e. the effect
   511     // Only set running state to 'NotRunning' if the finish is still in progress, i.e. the effect
   478     // has not been restarted meanwhile.
   512     // has not been restarted meanwhile.
   479     if (mRunningState == FinishInProgress) {
   513     if (mRunningState == FinishInProgress) {
   480         mRunningState = NotRunning;
   514         mRunningState = NotRunning;
   481         // We are finished either normally or with EffectNotStarted. It is now the time to
   515         // We are finished either normally or with EffectNotStarted. It is now
   482         // get rid of all the "effects" caused by the effects in this group if the
   516         // the time to get rid of all the "effects" caused by the effects in
   483         // hide-when-finished flag is set.
   517         // this group, if needed.
   484         if (mHideWhenFinished) {
   518         if (mEffectFlags.testFlag(HbEffectInternal::ClearEffectWhenFinished)) {
   485             doHideEffect(0, hasOpacityEffect());
   519             doClearEffect(0, hasOpacityEffect());
   486         }
   520         }
   487     }
   521     }
   488 }
   522 }
   489 
   523 
   490 void HbEffectGroup::invokeObserver(Hb::EffectEvent reason)
   524 void HbEffectGroup::invokeObserver(Hb::EffectEvent reason)
   503         // This is done before invokeMethod to avoid crash if the callback
   537         // This is done before invokeMethod to avoid crash if the callback
   504         // deletes this object.
   538         // deletes this object.
   505         mObserver = 0;
   539         mObserver = 0;
   506 
   540 
   507         // Send callback if observer has been provided. Use queued connection if
   541         // Send callback if observer has been provided. Use queued connection if
   508         // the effect finished normally, because otherwise deleting the effect during the callback
   542         // the effect finished normally, because otherwise deleting the effect
   509         // would cause crash because this function finally returns back to animation framework code
   543         // during the callback would cause crash because this function finally
   510         // which assumes the effect objects are alive.
   544         // returns back to animation framework code which assumes the effect
       
   545         // objects are alive.
   511         QMetaObject::invokeMethod(
   546         QMetaObject::invokeMethod(
   512             observer,
   547             observer,
   513             mEffectFinishedSlotName.toAscii().data(),
   548             mEffectFinishedSlotName.toAscii().data(),
   514             reason == Hb::EffectFinished ? Qt::QueuedConnection : Qt::AutoConnection,
   549             reason == Hb::EffectFinished ? Qt::QueuedConnection : Qt::AutoConnection,
   515             QGenericReturnArgument(),
   550             QGenericReturnArgument(),
   518         // Do not access member variables after invoking the callback since it might
   553         // Do not access member variables after invoking the callback since it might
   519         // have deleted this object.
   554         // have deleted this object.
   520     }
   555     }
   521 }
   556 }
   522 
   557 
   523 void HbEffectGroup::setHideWhenFinished(bool hideWhenFinished)
   558 void HbEffectGroup::setEffectFlags(HbEffectInternal::EffectFlags flags)
   524 {
   559 {
   525     mHideWhenFinished = hideWhenFinished;
   560     mEffectFlags = flags;
   526 }
   561 }
   527 
   562 
   528 // End of File
   563 // End of File