src/hbcore/effects/hbeffect.cpp
changeset 5 627c4a0fd0e7
parent 1 f7ac710697a9
child 21 4633027730f5
child 34 ed14f46c0e55
equal deleted inserted replaced
3:11d3954df52a 5:627c4a0fd0e7
    72     int result = key1.mItem - key2.mItem;
    72     int result = key1.mItem - key2.mItem;
    73     // If that is same, compare effect event string
    73     // If that is same, compare effect event string
    74     if (!result) {
    74     if (!result) {
    75         result = key1.mEffectEvent.compare(key2.mEffectEvent);
    75         result = key1.mEffectEvent.compare(key2.mEffectEvent);
    76     }
    76     }
    77     return result<0;
    77     return result < 0;
    78 }
    78 }
    79 
    79 
    80 static void fixEffectGroupOrder(QList<HbEffectGroup *> *groupList)
    80 static void fixEffectGroupOrder(QList<HbEffectGroup *> *groupList)
    81 {
    81 {
    82     // If there is only one group, no need to change order
    82     // If there is only one group, no need to change order
    93                 groupList->append(group);
    93                 groupList->append(group);
    94                 movedCount++;
    94                 movedCount++;
    95             }
    95             }
    96         }
    96         }
    97 
    97 
    98         if (last - movedCount > 0 ) {
    98         if (last - movedCount > 0) {
    99             for (int i = last - movedCount; i >= 0; --i) {
    99             for (int i = last - movedCount; i >= 0; --i) {
   100                 HbEffectGroup *group = groupList->at(i);
   100                 HbEffectGroup *group = groupList->at(i);
   101                 // If the group has a scale effect, move it second last before groups that had translate effects
   101                 // If the group has a scale effect, move it second last before groups that had translate effects
   102                 if (group->hasScaleEffect()) {
   102                 if (group->hasScaleEffect()) {
   103                     groupList->takeAt(i);
   103                     groupList->takeAt(i);
   122     // Needed for notifying effect finish asynchronously
   122     // Needed for notifying effect finish asynchronously
   123     qRegisterMetaType<HbEffect::EffectStatus>();
   123     qRegisterMetaType<HbEffect::EffectStatus>();
   124 }
   124 }
   125 
   125 
   126 HbEffectPrivate::~HbEffectPrivate()
   126 HbEffectPrivate::~HbEffectPrivate()
   127 {   
   127 {
   128     privateDestroyed = true;
   128     privateDestroyed = true;
   129     mDisabledItems.clear();
   129     mDisabledItems.clear();
   130 }
   130 }
   131 
   131 
   132 void HbEffectPrivate::connectViewChanges()
   132 void HbEffectPrivate::connectViewChanges()
   133 {
   133 {
   134     // Connect to view change signals if not done yet
   134     // Connect to view change signals if not done yet
   135     if (!mViewChangeConnected) {
   135     if (!mViewChangeConnected) {
   136         mViewChangeConnected = true;
   136         mViewChangeConnected = true;
   137         QList<HbMainWindow *> windowList = hbInstance->allMainWindows();
   137         QList<HbMainWindow *> windowList = hbInstance->allMainWindows();
   138         foreach (const HbMainWindow *window, windowList) {
   138         foreach(const HbMainWindow * window, windowList) {
   139             connect(window, SIGNAL(currentViewChanged(HbView*)), SLOT(handleViewChanged(HbView*)));
   139             connect(window, SIGNAL(currentViewChanged(HbView *)), SLOT(handleViewChanged(HbView *)));
   140         }
   140         }
   141         // Need a notification when a mainwindow is added in the future.
   141         // Need a notification when a mainwindow is added in the future.
   142         connect(HbInstancePrivate::d_ptr(), SIGNAL(windowAdded(HbMainWindow*)), SLOT(handleWindowAdded(HbMainWindow*)));
   142         connect(HbInstancePrivate::d_ptr(), SIGNAL(windowAdded(HbMainWindow *)), SLOT(handleWindowAdded(HbMainWindow *)));
   143     }
   143     }
   144 }
   144 }
   145 
   145 
   146 void HbEffectPrivate::handleWindowAdded(HbMainWindow *window)
   146 void HbEffectPrivate::handleWindowAdded(HbMainWindow *window)
   147 {
   147 {
   148     connect(window, SIGNAL(currentViewChanged(HbView*)), SLOT(handleViewChanged(HbView*)));
   148     connect(window, SIGNAL(currentViewChanged(HbView *)), SLOT(handleViewChanged(HbView *)));
   149 }
   149 }
   150 
   150 
   151 void HbEffectPrivate::handleViewChanged(HbView *view)
   151 void HbEffectPrivate::handleViewChanged(HbView *view)
   152 {
   152 {
   153      // Observers may be notified during cancellations which may result in starting a new
   153     // Observers may be notified during cancellations which may result in starting a new
   154     // effect during which groups may be deleted and removed from
   154     // effect during which groups may be deleted and removed from
   155     // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
   155     // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
   156     QList<HbEffectGroup *> groupsToBeHandled;
   156     QList<HbEffectGroup *> groupsToBeHandled;
   157     foreach (HbEffectGroup *group, d.mEventEffectList) {
   157     foreach(HbEffectGroup * group, d.mEventEffectList) {
   158         groupsToBeHandled.append(group);
   158         groupsToBeHandled.append(group);
   159     }
   159     }
   160 
   160 
   161     foreach (HbEffectGroup *group, groupsToBeHandled) {
   161     foreach(HbEffectGroup * group, groupsToBeHandled) {
   162     // Check if the real list still contains the group. If not then it may have been
   162         // Check if the real list still contains the group. If not then it may have been
   163     // deleted and removed meanwhile so do nothing.
   163         // deleted and removed meanwhile so do nothing.
   164     if (d.mEventEffectList.values().contains(group)) {
   164         if (d.mEventEffectList.values().contains(group)) {
   165         if (group->isRunning()) {
   165             if (group->isRunning()) {
   166             // Looping effect
   166                 // Looping effect
   167             if (group->isLooping()) {
   167                 if (group->isLooping()) {
   168                 if (group->view() == view) {    
   168                     if (group->view() == view) {
   169                     group->resume(); // Effect's view activated, resume effect
   169                         group->resume(); // Effect's view activated, resume effect
   170                 } else {
   170                     } else {
   171                     group->pause(); // Effect's view deactivated, pause effect
   171                         group->pause(); // Effect's view deactivated, pause effect
   172                 }
   172                     }
   173             } else { // Non-looping effect
   173                 } else { // Non-looping effect
   174                 if (group->view() != view) { // Effect's view deactivated, cancel the effect
   174                     if (group->view() != view) { // Effect's view deactivated, cancel the effect
   175                     group->cancelAll(true);
   175                         group->cancelAll(true);
   176               
   176                         // remove group from eventEffectsList
   177                     // remove group from eventEffectsList
   177                         QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
   178                     QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
   178                         while (e != d.mEventEffectList.end()) {
   179                      while (e != d.mEventEffectList.end()) {
   179                             if (e.value() == group) { // found, erase from event effect list
   180                          if (e.value() == group) { // found, erase from event effect list
   180                                 d.mEventEffectList.erase(e);
   181                              d.mEventEffectList.erase(e);
   181                                 delete group; // once removed from list, delete group
   182 							 delete group; // once removed from list, delete group
   182                                 e = d.mEventEffectList.end();
   183                              e = d.mEventEffectList.end();
   183                             } else {
   184                          }
   184                                 e++;  // try next one
   185                          else
   185                             }
   186                             e++;  // try next one
   186                         }
   187                      }
   187                     }
   188                 }
   188                 }
   189             }
   189             }
   190         }
   190         }
   191     }    
   191     }
   192 }
       
   193 }
   192 }
   194 
   193 
   195 
   194 
   196 HbAnimatedItemGroup::HbAnimatedItemGroup(
   195 HbAnimatedItemGroup::HbAnimatedItemGroup(
   197     const QList<QGraphicsItem *> &items,
   196     const QList<QGraphicsItem *> &items,
   206     mUserData(userData)
   205     mUserData(userData)
   207 {
   206 {
   208     // Need information of receiver destroyed because this class gets
   207     // Need information of receiver destroyed because this class gets
   209     // the notifications asynchronously so it must not invoke the
   208     // the notifications asynchronously so it must not invoke the
   210     // receiver if it has been destroyed meanwhile.
   209     // receiver if it has been destroyed meanwhile.
   211     connect(mReceiver, SIGNAL(destroyed()), this, SLOT(receiverDestroyed())); 
   210     connect(mReceiver, SIGNAL(destroyed()), this, SLOT(receiverDestroyed()));
   212 }
   211 }
   213 
   212 
   214 void HbAnimatedItemGroup::finished(const HbEffect::EffectStatus &status)
   213 void HbAnimatedItemGroup::finished(const HbEffect::EffectStatus &status)
   215 {
   214 {
   216     if (++mFinishedCount == mItems.count()) {
   215     if (++mFinishedCount == mItems.count()) {
   343     Q_UNUSED(effectEvent);
   342     Q_UNUSED(effectEvent);
   344     return false;
   343     return false;
   345 #else
   344 #else
   346     // This API cannot be used to add HB library's effect definitions.
   345     // This API cannot be used to add HB library's effect definitions.
   347     // There is internal API in class HbEffectInternal for that.
   346     // There is internal API in class HbEffectInternal for that.
   348     if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) 
   347     if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) {
   349     {
       
   350         return false;
   348         return false;
   351     }
   349     }
   352     return HbEffectInternal::add(itemType, filePath, effectEvent);
   350     return HbEffectInternal::add(itemType, filePath, effectEvent);
   353 
   351 
   354 #endif //HB_EFFECT_API_OFF
   352 #endif //HB_EFFECT_API_OFF
   381     Q_UNUSED(itemType);
   379     Q_UNUSED(itemType);
   382     Q_UNUSED(filePath);
   380     Q_UNUSED(filePath);
   383     Q_UNUSED(effectEvent);
   381     Q_UNUSED(effectEvent);
   384     return false;
   382     return false;
   385 #else
   383 #else
   386     foreach (const QString &type, itemType) {
   384     foreach(const QString & type, itemType) {
   387         if (type.startsWith(HB_EFFECT_ITEM_PREFIX))
   385         if (type.startsWith(HB_EFFECT_ITEM_PREFIX)) {
   388             return false;
   386             return false;
       
   387         }
   389     }
   388     }
   390     return HbEffectInternal::add(itemType, filePath, effectEvent);
   389     return HbEffectInternal::add(itemType, filePath, effectEvent);
   391 #endif // HB_EFFECT_API_OFF
   390 #endif // HB_EFFECT_API_OFF
   392 }
   391 }
   393 
   392 
   465     Q_UNUSED(effectEvent);
   464     Q_UNUSED(effectEvent);
   466     return false;
   465     return false;
   467 #else
   466 #else
   468     // This API cannot be used to remove HB library's effect definitions.
   467     // This API cannot be used to remove HB library's effect definitions.
   469     // There is internal API in class HbEffectInternal for that.
   468     // There is internal API in class HbEffectInternal for that.
   470     if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) 
   469     if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) {
   471     {
       
   472         return false;
   470         return false;
   473     }
   471     }
   474     HbEffectInternal::remove(itemType, filePath, effectEvent);
   472     HbEffectInternal::remove(itemType, filePath, effectEvent);
   475     return true;
   473     return true;
   476 #endif //HB_EFFECT_API_OFF
   474 #endif //HB_EFFECT_API_OFF
   520     HbEffectInternal::remove(item);
   518     HbEffectInternal::remove(item);
   521     return true;
   519     return true;
   522 #endif //HB_EFFECT_API_OFF
   520 #endif //HB_EFFECT_API_OFF
   523 }
   521 }
   524 
   522 
   525 /*! \brief This function is used to start an effect on a graphics item. 
   523 /*! \brief This function is used to start an effect on a graphics item.
   526 
   524 
   527   The effect definition is taken from the FXML file registered for the graphics
   525   The effect definition is taken from the FXML file registered for the graphics
   528   item with matching itemType and effectEvent.
   526   item with matching itemType and effectEvent.
   529 
   527 
   530   \param item The target item for the effect
   528   \param item The target item for the effect
   568   The function returns \c false if some invalid parameter is passed, or if the
   566   The function returns \c false if some invalid parameter is passed, or if the
   569   effect was disabled using disable().
   567   effect was disabled using disable().
   570 
   568 
   571   Example to get notification of effect completion.
   569   Example to get notification of effect completion.
   572   \code
   570   \code
   573   // Create a public slot in a the widget class if you want to get effect-finished 
   571   // Create a public slot in a the widget class if you want to get effect-finished
   574   // notification. In normal scenario, the widget itself can be receiver. But it is possible 
   572   // notification. In normal scenario, the widget itself can be receiver. But it is possible
   575   // to use any QObject as receiver.
   573   // to use any QObject as receiver.
   576   class MyHbWidget : public HbWidget
   574   class MyHbWidget : public HbWidget
   577   {
   575   {
   578   Q_OBJECT
   576   Q_OBJECT
   579   public slots:
   577   public slots:
   580   void effectFinished(const HbEffect::EffectStatus &status);
   578   void effectFinished(const HbEffect::EffectStatus &status);
   581   // Other stuffs 
   579   // Other stuffs
   582   };
   580   };
   583     
   581 
   584   void MyObserver::effectFinished(const HbEffect::EffectStatus &status)
   582   void MyObserver::effectFinished(const HbEffect::EffectStatus &status)
   585   {
   583   {
   586   // Effect is finished. Do something.
   584   // Effect is finished. Do something.
   587   }
   585   }
   588 
   586 
   589   // Some function which starts effect..
   587   // Some function which starts effect..
   590   void MyHbWidget::myFunction()
   588   void MyHbWidget::myFunction()
   591   {
   589   {
   592   // myFunction related other stuff
   590   // myFunction related other stuff
   593   // calling startefect
   591   // calling startefect
   594   HbEffect::start(myGraphicsItem, 
   592   HbEffect::start(myGraphicsItem,
   595   "myItemType",
   593   "myItemType",
   596   "myEvent",
   594   "myEvent",
   597   this,
   595   this,
   598   "effectFinished");
   596   "effectFinished");
   599         
   597 
   600   // myFunction related other stuff
   598   // myFunction related other stuff
   601   }
   599   }
   602   \endcode
   600   \endcode
   603   \sa cancel()
   601   \sa cancel()
   604 */
   602 */
   605 bool HbEffect::start(QGraphicsItem *item, 
   603 bool HbEffect::start(QGraphicsItem *item,
   606                      const QString &itemType, 
   604                      const QString &itemType,
   607                      const QString &effectEvent,
   605                      const QString &effectEvent,
   608                      QObject *receiver,
   606                      QObject *receiver,
   609                      const char *member,
   607                      const char *member,
   610                      const QVariant &userData,
   608                      const QVariant &userData,
   611                      const QRectF &extRect)
   609                      const QRectF &extRect)
   654   \sa HbEffect::EffectStatus
   652   \sa HbEffect::EffectStatus
   655 
   653 
   656   The function returns \c false if some invalid parameter is passed, or if the
   654   The function returns \c false if some invalid parameter is passed, or if the
   657   effect was disabled using disable().
   655   effect was disabled using disable().
   658 */
   656 */
   659 bool HbEffect::start(QGraphicsItem *item, 
   657 bool HbEffect::start(QGraphicsItem *item,
   660                      const QString &effectEvent,
   658                      const QString &effectEvent,
   661                      QObject *receiver,
   659                      QObject *receiver,
   662                      const char *member,
   660                      const char *member,
   663                      const QVariant &userData,
   661                      const QVariant &userData,
   664                      const QRectF &extRect)
   662                      const QRectF &extRect)
   671     Q_UNUSED(userData);
   669     Q_UNUSED(userData);
   672     Q_UNUSED(extRect);
   670     Q_UNUSED(extRect);
   673     return false;
   671     return false;
   674 #else
   672 #else
   675     return HbEffect::start(
   673     return HbEffect::start(
   676         item, HB_EFFECT_INTERNAL_ITEM, effectEvent, receiver, member, userData, extRect);
   674                item, HB_EFFECT_INTERNAL_ITEM, effectEvent, receiver, member, userData, extRect);
   677 #endif //HB_EFFECT_API_OFF
   675 #endif //HB_EFFECT_API_OFF
   678 }
   676 }
   679 
   677 
   680 /*!  \brief This function starts the same effect simultaneously for a given list
   678 /*!  \brief This function starts the same effect simultaneously for a given list
   681   of graphics items.
   679   of graphics items.
   717 
   715 
   718   The function returns \c false if some invalid parameter is passed, or if the
   716   The function returns \c false if some invalid parameter is passed, or if the
   719   effect was disabled using disable().
   717   effect was disabled using disable().
   720 */
   718 */
   721 bool HbEffect::start(
   719 bool HbEffect::start(
   722     const QList<QGraphicsItem *> &items, 
   720     const QList<QGraphicsItem *> &items,
   723     const QString &itemType, 
   721     const QString &itemType,
   724     const QString &effectEvent,
   722     const QString &effectEvent,
   725     QObject *receiver,
   723     QObject *receiver,
   726     const char *member,
   724     const char *member,
   727     const QVariant &userData)
   725     const QVariant &userData)
   728 {
   726 {
   729 #ifdef HB_EFFECT_API_OFF
   727 #ifdef HB_EFFECT_API_OFF
   730     Q_UNUSED(items);
   728     Q_UNUSED(items);
   731     Q_UNUSED(itemType); 
   729     Q_UNUSED(itemType);
   732     Q_UNUSED(effectEvent);
   730     Q_UNUSED(effectEvent);
   733     Q_UNUSED(receiver);
   731     Q_UNUSED(receiver);
   734     Q_UNUSED(member);
   732     Q_UNUSED(member);
   735     Q_UNUSED(userData);
   733     Q_UNUSED(userData);
   736     return false;
   734     return false;
   757     if (receiver) {
   755     if (receiver) {
   758         groupReceiver = group;
   756         groupReceiver = group;
   759         groupMember = "finished";
   757         groupMember = "finished";
   760     }
   758     }
   761 
   759 
   762     foreach (QGraphicsItem *item, items) {
   760     foreach(QGraphicsItem * item, items) {
   763         if (HbEffect::start(item, itemType, effectEvent, groupReceiver, groupMember, userData)) {
   761         if (HbEffect::start(item, itemType, effectEvent, groupReceiver, groupMember, userData)) {
   764             // If at least one item succeeded to start, set return value to true
   762             // If at least one item succeeded to start, set return value to true
   765             ret = true;
   763             ret = true;
   766         }
   764         }
   767     }
   765     }
   789     bool ret = false;
   787     bool ret = false;
   790 
   788 
   791     // Return true if the given item is running any effect
   789     // Return true if the given item is running any effect
   792     if (effectEvent.isEmpty()) {
   790     if (effectEvent.isEmpty()) {
   793         for (QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.constBegin();
   791         for (QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.constBegin();
   794              e != d.mEventEffectList.constEnd();
   792                 e != d.mEventEffectList.constEnd();
   795              ++e ) {
   793                 ++e) {
   796             HbEffectGroup *group = *e;
   794             HbEffectGroup *group = *e;
   797             if (group->registrationItem() == item && group->isRunning()) {
   795             if (group->registrationItem() == item && group->isRunning()) {
   798                 ret = true;
   796                 ret = true;
   799                 break;
   797                 break;
   800             }
   798             }
   801         }
   799         }
   802     } else {
   800     } else {
   803         // effectEvent was specified, check if effect matching that is running
   801         // effectEvent was specified, check if effect matching that is running
   804         EffectMapKey key(item, effectEvent);
   802         EffectMapKey key(item, effectEvent);
   805         QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.find(key);
   803         QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.find(key);
   806     
   804 
   807         // Effect found in the list?
   805         // Effect found in the list?
   808         if(e != d.mEventEffectList.constEnd()) {
   806         if (e != d.mEventEffectList.constEnd()) {
   809             HbEffectGroup* group = *e;
   807             HbEffectGroup *group = *e;
   810             ret = group->isRunning();
   808             ret = group->isRunning();
   811         }
   809         }
   812     }
   810     }
   813 
   811 
   814     return ret;
   812     return ret;
   856     Q_UNUSED(effectEvent);
   854     Q_UNUSED(effectEvent);
   857     Q_UNUSED(clearEffect);
   855     Q_UNUSED(clearEffect);
   858     Q_UNUSED(sendCallback);
   856     Q_UNUSED(sendCallback);
   859     Q_UNUSED(itemIsValid);
   857     Q_UNUSED(itemIsValid);
   860     return false;
   858     return false;
   861 #else 
   859 #else
   862     if (privateDestroyed) {
   860     if (privateDestroyed) {
   863         return false;
   861         return false;
   864     }
   862     }
   865 
   863 
   866     bool ret = false;
   864     bool ret = false;
   867 
   865 
   868     if (effectEvent.isEmpty()) {
   866     if (effectEvent.isEmpty()) {
   869         // Stop all the effects running on item at that point of time.
   867         // Stop all the effects running on item at that point of time.
   870         // (iterator way had some problem and caused crash so using foreach)
   868         // (iterator way had some problem and caused crash so using foreach)
   871         QList<HbEffectGroup *> groupsToBeCanceled;
   869         QList<HbEffectGroup *> groupsToBeCanceled;
   872         foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
   870         QList<EffectMapKey> keys = d.mEventEffectList.keys();
       
   871         foreach(const EffectMapKey & key, keys) {
   873             if (key.mItem == item) {
   872             if (key.mItem == item) {
   874                 HbEffectGroup* group = d.mEventEffectList.take(key);
   873                 HbEffectGroup *group = d.mEventEffectList.take(key);
   875                 groupsToBeCanceled.append(group);
   874                 groupsToBeCanceled.append(group);
   876             }
   875             }
   877         }
   876         }
   878 
   877 
   879         // Before blindly calling cancelAll to the effect groups, try to fix their order so that
   878         // Before blindly calling cancelAll to the effect groups, try to fix their order so that
   881         // may still be incorrect end state if there are multiple effect groups which each have multiple effects,
   880         // may still be incorrect end state if there are multiple effect groups which each have multiple effects,
   882         // but this at least fixes cases, where there are multiple effect groups which each consist of a single effect.
   881         // but this at least fixes cases, where there are multiple effect groups which each consist of a single effect.
   883         fixEffectGroupOrder(&groupsToBeCanceled);
   882         fixEffectGroupOrder(&groupsToBeCanceled);
   884 
   883 
   885         bool first = true;
   884         bool first = true;
   886         foreach (HbEffectGroup *group, groupsToBeCanceled) {
   885         foreach(HbEffectGroup * group, groupsToBeCanceled) {
   887             // If clearEffect is false then it is important to pass a default transform
   886             // If clearEffect is false then it is important to pass a default transform
   888             // first so the matrix multiplication in cancelAll ends up correct.
   887             // first so the matrix multiplication in cancelAll ends up correct.
   889             group->cancelAll(sendCallback, itemIsValid, clearEffect, first || !itemIsValid ? QTransform() : item->transform());
   888             group->cancelAll(sendCallback, itemIsValid, clearEffect, first || !itemIsValid ? QTransform() : item->transform());
   890             if (first) {
   889             if (first) {
   891                 first = false;
   890                 first = false;
   895             ret = true;
   894             ret = true;
   896         }
   895         }
   897         return ret;
   896         return ret;
   898     } else {
   897     } else {
   899         EffectMapKey key(item, effectEvent);
   898         EffectMapKey key(item, effectEvent);
   900         HbEffectGroup* group = d.mEventEffectList.take(key);
   899         HbEffectGroup *group = d.mEventEffectList.take(key);
   901         if (group) {
   900         if (group) {
   902             group->cancelAll(sendCallback, itemIsValid, clearEffect);
   901             group->cancelAll(sendCallback, itemIsValid, clearEffect);
   903             delete group;
   902             delete group;
   904             return true;
   903             return true;
   905         } else {
   904         } else {
   913   effect for a graphicsitem was disabled this method can be used to enable the
   912   effect for a graphicsitem was disabled this method can be used to enable the
   914   effect again for that item.
   913   effect again for that item.
   915 
   914 
   916   The function takes following parameters:
   915   The function takes following parameters:
   917   \param item pointer to QGraphicsItem for which the effect will be enabled.
   916   \param item pointer to QGraphicsItem for which the effect will be enabled.
   918     
   917 
   919   \sa disable()
   918   \sa disable()
   920 */
   919 */
   921 void HbEffect::enable(QGraphicsItem *item)
   920 void HbEffect::enable(QGraphicsItem *item)
   922 {
   921 {
   923 #ifdef HB_EFFECT_API_OFF
   922 #ifdef HB_EFFECT_API_OFF
   928 }
   927 }
   929 
   928 
   930 /*! This function can be used to disable an effect for a graphicsitem. This is
   929 /*! This function can be used to disable an effect for a graphicsitem. This is
   931   useful in cases where you have a component which usually shows an effect but
   930   useful in cases where you have a component which usually shows an effect but
   932   you want to skip the effect for your object.
   931   you want to skip the effect for your object.
   933     
   932 
   934   You can enable the effect using enable(), and you should always call enable()
   933   You can enable the effect using enable(), and you should always call enable()
   935   once you do not need the object to be disabled, at latest when you're deleting
   934   once you do not need the object to be disabled, at latest when you're deleting
   936   your animated graphicsitem. This should be done to clean up the list of
   935   your animated graphicsitem. This should be done to clean up the list of
   937   disabled items. Note that if the animated item is an HbWidget, then the
   936   disabled items. Note that if the animated item is an HbWidget, then the
   938   enable() call happens automatically at the HbWidget destructor.
   937   enable() call happens automatically at the HbWidget destructor.
   939     
   938 
   940   Unlike remove()-methods, this won't touch the effect definition at all. The
   939   Unlike remove()-methods, this won't touch the effect definition at all. The
   941   effect is just skipped when trying to start the effect.  Note also that
   940   effect is just skipped when trying to start the effect.  Note also that
   942   start()-method returns false if the effect is disabled.
   941   start()-method returns false if the effect is disabled.
   943 
   942 
   944   \param item pointer to QGraphicsItem for which the effect will be disabled
   943   \param item pointer to QGraphicsItem for which the effect will be disabled
   945     
   944 
   946   \sa enable()
   945   \sa enable()
   947   \sa start()
   946   \sa start()
   948 */
   947 */
   949 void HbEffect::disable(QGraphicsItem *item)
   948 void HbEffect::disable(QGraphicsItem *item)
   950 {
   949 {
   958 }
   957 }
   959 
   958 
   960 /*!
   959 /*!
   961   \internal
   960   \internal
   962 */
   961 */
   963 HbGVWrapperItem::HbGVWrapperItem():mMainWindow(0)
   962 HbGVWrapperItem::HbGVWrapperItem(): mMainWindow(0)
   964 {
   963 {
   965 }
   964 }
   966 
   965 
   967 void HbGVWrapperItem::setMainWindow(HbMainWindow& mainWindow)
   966 void HbGVWrapperItem::setMainWindow(HbMainWindow &mainWindow)
   968 {
   967 {
   969     mMainWindow = &mainWindow;
   968     mMainWindow = &mainWindow;
   970 }
   969 }
   971 
   970 
   972 HbMainWindow *HbGVWrapperItem::mainWindow() const
   971 HbMainWindow *HbGVWrapperItem::mainWindow() const
   976 
   975 
   977 QRectF HbGVWrapperItem::boundingRect() const
   976 QRectF HbGVWrapperItem::boundingRect() const
   978 {
   977 {
   979     QRectF bRect;
   978     QRectF bRect;
   980     // viewportitem is used as a boundingrect since viewport item gets resized when changing orientation
   979     // viewportitem is used as a boundingrect since viewport item gets resized when changing orientation
   981     if( mMainWindow ) {
   980     if (mMainWindow) {
   982         bRect = mMainWindow->layoutRect();
   981         bRect = mMainWindow->layoutRect();
   983     }
   982     }
   984     return bRect;
   983     return bRect;
   985 }
   984 }
   986 void HbGVWrapperItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 
   985 void HbGVWrapperItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
   987 {
   986 {
   988     Q_UNUSED(painter);
   987     Q_UNUSED(painter);
   989     Q_UNUSED(option);
   988     Q_UNUSED(option);
   990     Q_UNUSED(widget);
   989     Q_UNUSED(widget);
   991 };
   990 };
  1005     bool ret = d.mController.addFXML(itemType, filePath, effectEvent, true);
  1004     bool ret = d.mController.addFXML(itemType, filePath, effectEvent, true);
  1006     if (ret) {
  1005     if (ret) {
  1007         // Mark all effects using the given item type dirty,
  1006         // Mark all effects using the given item type dirty,
  1008         // so that they get re-created when the effect is shown next time
  1007         // so that they get re-created when the effect is shown next time
  1009         for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1008         for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1010              e != d.mEventEffectList.end();
  1009                 e != d.mEventEffectList.end();
  1011              ++e ) {
  1010                 ++e) {
  1012             HbEffectGroup *group = *e;
  1011             HbEffectGroup *group = *e;
  1013 
       
  1014             if (group->itemType() == itemType) {
  1012             if (group->itemType() == itemType) {
  1015                 group->setDirty(true);
  1013                 group->setDirty(true);
  1016             }
  1014             }
  1017         }
  1015         }
  1018     }
  1016     }
  1073 
  1071 
  1074     if (ret) {
  1072     if (ret) {
  1075         // Mark all effects using the given item type dirty,
  1073         // Mark all effects using the given item type dirty,
  1076         // so that they get re-created when the effect is shown next time
  1074         // so that they get re-created when the effect is shown next time
  1077         for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1075         for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1078              e != d.mEventEffectList.end();
  1076                 e != d.mEventEffectList.end();
  1079              ++e ) {
  1077                 ++e) {
  1080             HbEffectGroup *group = *e;
  1078             HbEffectGroup *group = *e;
  1081 
       
  1082             if (group->registrationItem() == item) {
  1079             if (group->registrationItem() == item) {
  1083                 group->setDirty(true);
  1080                 group->setDirty(true);
  1084             }
  1081             }
  1085         }
  1082         }
  1086     }
  1083     }
  1132     Q_UNUSED(filePath);
  1129     Q_UNUSED(filePath);
  1133     Q_UNUSED(effectEvent);
  1130     Q_UNUSED(effectEvent);
  1134 #else
  1131 #else
  1135     // FXML
  1132     // FXML
  1136     // If extension is not given then try both with and without .fxml
  1133     // If extension is not given then try both with and without .fxml
  1137     if (!filePath.endsWith(".fxml")) {
  1134     if (!filePath.endsWith(QLatin1String(".fxml"))) {
  1138         d.mController.removeFXML(itemType, filePath + ".fxml", effectEvent);       
  1135         d.mController.removeFXML(itemType, filePath + QLatin1String(".fxml"), effectEvent);
  1139     }
  1136     }
  1140     d.mController.removeFXML(itemType, filePath, effectEvent);
  1137     d.mController.removeFXML(itemType, filePath, effectEvent);
  1141     // Clean up mEventEffectList.
  1138     // Clean up mEventEffectList.
  1142     foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
  1139     QList<EffectMapKey> keys = d.mEventEffectList.keys();
       
  1140     foreach(const EffectMapKey & key, keys) {
  1143         if (key.mEffectEvent == effectEvent) {
  1141         if (key.mEffectEvent == effectEvent) {
  1144             HbEffectGroup *group = d.mEventEffectList.value(key);
  1142             HbEffectGroup *group = d.mEventEffectList.value(key);
  1145             group->setDirty(true); // so the next start() will try to recreate the effect instead of re-using it
  1143             group->setDirty(true); // so the next start() will try to recreate the effect instead of re-using it
  1146         }
  1144         }
  1147     }
  1145     }
  1158     Q_UNUSED(filePath);
  1156     Q_UNUSED(filePath);
  1159     Q_UNUSED(effectEvent);
  1157     Q_UNUSED(effectEvent);
  1160 #else
  1158 #else
  1161     // FXML
  1159     // FXML
  1162     // If extension is not given then try both with and without .fxml
  1160     // If extension is not given then try both with and without .fxml
  1163     if (!filePath.endsWith(".fxml")) {
  1161     if (!filePath.endsWith(QLatin1String(".fxml"))) {
  1164         d.mController.removeFXML(item, filePath + ".fxml", effectEvent);       
  1162         d.mController.removeFXML(item, filePath + QLatin1String(".fxml"), effectEvent);
  1165     }
  1163     }
  1166     d.mController.removeFXML(item, filePath, effectEvent);
  1164     d.mController.removeFXML(item, filePath, effectEvent);
  1167     // Clean up mEventEffectList.
  1165     // Clean up mEventEffectList.
  1168     foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
  1166     QList<EffectMapKey> keys = d.mEventEffectList.keys();
       
  1167     foreach(const EffectMapKey & key, keys) {
  1169         if (key.mItem == item && key.mEffectEvent == effectEvent) {
  1168         if (key.mItem == item && key.mEffectEvent == effectEvent) {
  1170             HbEffectGroup *group = d.mEventEffectList.value(key);
  1169             HbEffectGroup *group = d.mEventEffectList.value(key);
  1171             group->setDirty(true);
  1170             group->setDirty(true);
  1172         }
  1171         }
  1173     }
  1172     }
  1184 #else
  1183 #else
  1185     if (item) {
  1184     if (item) {
  1186         d.mDisabledItems.removeOne(item); // clean the disabled list as well
  1185         d.mDisabledItems.removeOne(item); // clean the disabled list as well
  1187         d.mController.removeFXML(item);
  1186         d.mController.removeFXML(item);
  1188         // Clean up mEventEffectList.
  1187         // Clean up mEventEffectList.
  1189         foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
  1188         QList<EffectMapKey> keys = d.mEventEffectList.keys();
       
  1189         foreach(const EffectMapKey & key, keys) {
  1190             if (key.mItem == item) {
  1190             if (key.mItem == item) {
  1191                 HbEffectGroup *group = d.mEventEffectList.value(key);
  1191                 HbEffectGroup *group = d.mEventEffectList.value(key);
  1192                 group->setDirty(true);
  1192                 group->setDirty(true);
  1193             }
  1193             }
  1194         }
  1194         }
  1202     //ToDo Currently all the parsed Fxml Data is being deleted with themechange.
  1202     //ToDo Currently all the parsed Fxml Data is being deleted with themechange.
  1203     //     Make this function intelligent enough to delete only theme specific Fxml
  1203     //     Make this function intelligent enough to delete only theme specific Fxml
  1204     //     data.
  1204     //     data.
  1205     //parsedDataList.clear();
  1205     //parsedDataList.clear();
  1206     QList<HbEffectInfo> newDataList;
  1206     QList<HbEffectInfo> newDataList;
  1207     for (int i=0; i < parsedDataList.count(); i++) {
  1207     for (int i = 0; i < parsedDataList.count(); i++) {
  1208         if (parsedDataList[i].fromTheme()) {
  1208         if (parsedDataList[i].fromTheme()) {
  1209             newDataList.append(parsedDataList[i]);
  1209             newDataList.append(parsedDataList[i]);
  1210             parsedDataList.removeAt(i);
  1210             parsedDataList.removeAt(i);
  1211             i--;
  1211             i--;
  1212         }
  1212         }
  1213     }
  1213     }
  1214     for (int i=0; i < newDataList.count(); i++) {
  1214     for (int i = 0; i < newDataList.count(); i++) {
  1215         HbEffectInfo effectData = newDataList.at(i);            
  1215         HbEffectInfo effectData = newDataList.at(i);
  1216         bool ret = false;
  1216         bool ret = false;
  1217         QString relativename = QFileInfo(effectData.xmlFileFullPath()).baseName();
  1217         QString relativename = QFileInfo(effectData.xmlFileFullPath()).baseName();
  1218         if (effectData.item() != 0) {
  1218         if (effectData.item() != 0) {
  1219             ret = d.mController.addFXML(effectData.item(), relativename,
  1219             ret = d.mController.addFXML(effectData.item(), relativename,
  1220                                         effectData.effectEvent(), true);
  1220                                         effectData.effectEvent(), true);
  1221         }
  1221         } else if (!effectData.componentType().isEmpty()) {
  1222         else if (!effectData.componentType().isEmpty()) {
       
  1223             ret = d.mController.addFXML(effectData.componentType(), relativename,
  1222             ret = d.mController.addFXML(effectData.componentType(), relativename,
  1224                                         effectData.effectEvent(), true);
  1223                                         effectData.effectEvent(), true);
  1225         }
  1224         }
  1226         if (ret) {
  1225         if (ret) {
  1227             // Mark all effects using the given item type dirty,
  1226             // Mark all effects using the given item type dirty,
  1228             // so that they get re-created when the effect is shown next time
  1227             // so that they get re-created when the effect is shown next time
  1229             for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1228             for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
  1230                  e != d.mEventEffectList.end();
  1229                     e != d.mEventEffectList.end();
  1231                  ++e ) {
  1230                     ++e) {
  1232                 HbEffectGroup *group = *e;
  1231                 HbEffectGroup *group = *e;
  1233                 if (group->registrationItem() == effectData.item()) {
  1232                 if (group->registrationItem() == effectData.item()) {
  1234                     group->setDirty(true);
  1233                     group->setDirty(true);
  1235                 }
  1234                 }
  1236             }
  1235             }
  1242 /*!
  1241 /*!
  1243   Cancels all effects. List of graphicsitems can be given as an exception which are not cancelled.
  1242   Cancels all effects. List of graphicsitems can be given as an exception which are not cancelled.
  1244   This is used for example when changing orientation; all but the orientation change effects
  1243   This is used for example when changing orientation; all but the orientation change effects
  1245   are cancelled.
  1244   are cancelled.
  1246 */
  1245 */
  1247 void HbEffectInternal::cancelAll(const QList<QGraphicsItem*> *exceptionList, bool ignoreLooping)
  1246 void HbEffectInternal::cancelAll(const QList<QGraphicsItem *> *exceptionList, bool ignoreLooping)
  1248 {
  1247 {
  1249     // Observers may be notified during cancelations which may result in starting a new
  1248     // Observers may be notified during cancelations which may result in starting a new
  1250     // effect during which groups may be deleted and removed from
  1249     // effect during which groups may be deleted and removed from
  1251     // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
  1250     // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
  1252     QList<HbEffectGroup *> groupsToBeCanceled;
  1251     QList<HbEffectGroup *> groupsToBeCanceled;
  1253     foreach (HbEffectGroup *group, d.mEventEffectList) {
  1252     foreach(HbEffectGroup * group, d.mEventEffectList) {
  1254         groupsToBeCanceled.append(group);
  1253         groupsToBeCanceled.append(group);
  1255     }
  1254     }
  1256     foreach (HbEffectGroup *group, groupsToBeCanceled) {
  1255     foreach(HbEffectGroup * group, groupsToBeCanceled) {
  1257         // Check if the real list still contains the group. If not then it may have been
  1256         // Check if the real list still contains the group. If not then it may have been
  1258         // deleted and removed meanwhile so do nothing.
  1257         // deleted and removed meanwhile so do nothing.
  1259         if (d.mEventEffectList.values().contains(group)) {
  1258         if (d.mEventEffectList.values().contains(group)) {
  1260             if (!exceptionList || !exceptionList->contains(group->registrationItem())) {
  1259             if (!exceptionList || !exceptionList->contains(group->registrationItem())) {
  1261                 // Already cancelled effects may refer to graphics items that do not
  1260                 // Already cancelled effects may refer to graphics items that do not
  1274   be valid anymore.
  1273   be valid anymore.
  1275  */
  1274  */
  1276 void HbEffectInternal::safeCancelAll(bool clear)
  1275 void HbEffectInternal::safeCancelAll(bool clear)
  1277 {
  1276 {
  1278     QList<HbEffectGroup *> groupsToBeCanceled;
  1277     QList<HbEffectGroup *> groupsToBeCanceled;
  1279     foreach (HbEffectGroup *group, d.mEventEffectList) {
  1278     foreach(HbEffectGroup * group, d.mEventEffectList) {
  1280         groupsToBeCanceled.append(group);
  1279         groupsToBeCanceled.append(group);
  1281     }
  1280     }
  1282     foreach (HbEffectGroup *group, groupsToBeCanceled) {
  1281     foreach(HbEffectGroup * group, groupsToBeCanceled) {
  1283         if (d.mEventEffectList.values().contains(group)) {
  1282         if (d.mEventEffectList.values().contains(group)) {
  1284             group->cancelAll(false, false, clear);
  1283             group->cancelAll(false, false, clear);
  1285         }
  1284         }
  1286     }
  1285     }
  1287 }
  1286 }
  1295 
  1294 
  1296   \sa HbEffectInternal::resumeEffects()
  1295   \sa HbEffectInternal::resumeEffects()
  1297 */
  1296 */
  1298 void HbEffectInternal::stopEffects()
  1297 void HbEffectInternal::stopEffects()
  1299 {
  1298 {
  1300     // Pause looping effects and stop others
  1299     // Pause looping effects and stop others. As usual, we cannot just
  1301     foreach (HbEffectGroup *group, d.mEventEffectList) {
  1300     // simply iterate through the list as cancelAll() may change the
  1302         if (group->isRunning()) {
  1301     // elements in mEventEffectList.
  1303             if (group->isLooping()) {
  1302     QList<HbEffectGroup *> groupsToBeChecked;
  1304                 group->pause();
  1303     foreach(HbEffectGroup * group, d.mEventEffectList) {
  1305             } else {
  1304         groupsToBeChecked.append(group);
  1306                 group->cancelAll(true);
  1305     }
       
  1306     foreach(HbEffectGroup * group, groupsToBeChecked) {
       
  1307         if (d.mEventEffectList.values().contains(group)) {
       
  1308             if (group->isRunning()) {
       
  1309                 if (group->isLooping()) {
       
  1310                     group->pause();
       
  1311                 } else {
       
  1312                     group->cancelAll(true);
       
  1313                 }
  1307             }
  1314             }
  1308         }
  1315         }
  1309     }
  1316     }
  1310 }
  1317 }
  1311 
  1318 
  1319   \sa HbEffectInternal::stopEffects()
  1326   \sa HbEffectInternal::stopEffects()
  1320 */
  1327 */
  1321 void HbEffectInternal::resumeEffects()
  1328 void HbEffectInternal::resumeEffects()
  1322 {
  1329 {
  1323     // Resume any looping effects that were paused with stopEffects call.
  1330     // Resume any looping effects that were paused with stopEffects call.
  1324     foreach (HbEffectGroup *group, d.mEventEffectList) {
  1331     foreach(HbEffectGroup * group, d.mEventEffectList) {
  1325         if (group->isRunning() && group->isLooping()) {
  1332         if (group->isRunning() && group->isLooping()) {
  1326             group->resume();
  1333             group->resume();
  1327         }
  1334         }
  1328     }
  1335     }
  1329 }
  1336 }
  1371   \sa HbEffect::start()
  1378   \sa HbEffect::start()
  1372  */
  1379  */
  1373 bool HbEffectInternal::start(QGraphicsItem *registrationItem,
  1380 bool HbEffectInternal::start(QGraphicsItem *registrationItem,
  1374                              QGraphicsItem *targetItem,
  1381                              QGraphicsItem *targetItem,
  1375                              EffectFlags flags,
  1382                              EffectFlags flags,
  1376                              const QString &itemType, 
  1383                              const QString &itemType,
  1377                              const QString &effectEvent,
  1384                              const QString &effectEvent,
  1378                              QObject *receiver,
  1385                              QObject *receiver,
  1379                              const char *member,
  1386                              const char *member,
  1380                              const QVariant &userData,
  1387                              const QVariant &userData,
  1381                              const QRectF &extRect)
  1388                              const QRectF &extRect)
  1460 
  1467 
  1461     EffectMapKey key(registrationItem, effectEvent);
  1468     EffectMapKey key(registrationItem, effectEvent);
  1462     QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.find(key);
  1469     QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.find(key);
  1463 
  1470 
  1464     // Same effect found in the list?
  1471     // Same effect found in the list?
  1465     if(e != d.mEventEffectList.end()) {
  1472     if (e != d.mEventEffectList.end()) {
  1466         HbEffectGroup *group = e.value();
  1473         HbEffectGroup *group = e.value();
  1467         if (!group->dirty()) {
  1474         if (!group->dirty()) {
  1468             // if the effect group is not dirty, restart it. Cancel possible earlier
  1475             // if the effect group is not dirty, restart it. Cancel possible earlier
  1469             // effect first so that end position gets correct.
  1476             // effect first so that end position gets correct.
  1470             group->cancelAll(true);
  1477             group->cancelAll(true);
  1471             
  1478 
  1472             // Update with given notification parameters
  1479             // Update with given notification parameters
  1473             updateGroup(group, receiver, member, userData, extRect, flags);
  1480             updateGroup(group, receiver, member, userData, extRect, flags);
  1474 
  1481 
  1475             group->startAll();
  1482             group->startAll();
  1476             started = true;
  1483             started = true;