src/hbcore/effects/hbeffect.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/effects/hbeffect.cpp	Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,1527 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (developer.feedback@nokia.com)
+**
+** This file is part of the HbCore module of the UI Extensions for Mobile.
+**
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at developer.feedback@nokia.com.
+**
+****************************************************************************/
+
+#include "hbeffect.h"
+#include "hbeffect_p.h"
+#include "hbeffectinternal_p.h"
+#include "hbeffectabstract_p.h"
+#include "hbeffectgroup_p.h"
+#include "hbinstance.h"
+#include "hbinstance_p.h"
+#include "hbimagetraces_p.h"
+#include <hbglobal.h>
+#include <QObject>
+#include <QGraphicsItem>
+#include <QGraphicsWidget>
+
+// Uncomment next define in order to get warning prints.
+//#define HBEFFECT_WARNING
+
+// Effect definitions for effect item strings starting with this prefix cannot
+// be added with this public API. This prevents overriding HB's effects by
+// mistake in 3rd party software.
+#define HB_EFFECT_ITEM_PREFIX "HB_"
+// This itemType is used internally to manage object specific effects and should
+// not be used by 3rd party software.
+#define HB_EFFECT_INTERNAL_ITEM "HB_INTERNAL"
+
+static HbEffectPrivate d;
+
+// ===========================================================================
+
+class EffectMapKey
+{
+public:
+    EffectMapKey(QGraphicsItem *item, const QString &effectEvent);
+
+public:
+    QGraphicsItem *mItem;
+    QString mEffectEvent;
+};
+
+EffectMapKey::EffectMapKey(QGraphicsItem *item, const QString &effectEvent) :
+    mItem(item), mEffectEvent(effectEvent)
+{
+}
+
+bool operator <(const EffectMapKey &key1, const EffectMapKey &key2)
+{
+    // First compare item pointer address
+    int result = key1.mItem - key2.mItem;
+    // If that is same, compare effect event string
+    if (!result) {
+        result = key1.mEffectEvent.compare(key2.mEffectEvent);
+    }
+    return result<0;
+}
+
+static void fixEffectGroupOrder(QList<HbEffectGroup *> *groupList)
+{
+    // If there is only one group, no need to change order
+    if (groupList->count() > 1) {
+        int last = groupList->count() - 1;
+
+        int movedCount = 0; // number of groups moved last in the list
+
+        for (int i = last; i >= 0; --i) {
+            HbEffectGroup *group = groupList->at(i);
+            // If the group has a translate effect, move it last
+            if (group->hasTranslateEffect()) {
+                groupList->takeAt(i);
+                groupList->append(group);
+                movedCount++;
+            }
+        }
+
+        if (last - movedCount > 0 ) {
+            for (int i = last - movedCount; i >= 0; --i) {
+                HbEffectGroup *group = groupList->at(i);
+                // If the group has a scale effect, move it second last before groups that had translate effects
+                if (group->hasScaleEffect()) {
+                    groupList->takeAt(i);
+                    groupList->insert(last - movedCount, group);
+                }
+            }
+        }
+    }
+}
+
+static bool privateDestroyed = false;
+
+HbEffectPrivate::HbEffectPrivate() :
+    mController(),
+    mFactory(mController),
+    mEventEffectList(),
+    mEnabled(true),
+    mDisabledItems(),
+    mViewChangeConnected(false),
+    mEffectsEnabled(true)
+{
+    // Needed for notifying effect finish asynchronously
+    qRegisterMetaType<HbEffect::EffectStatus>();
+}
+
+HbEffectPrivate::~HbEffectPrivate()
+{   
+    privateDestroyed = true;
+    mDisabledItems.clear();
+}
+
+void HbEffectPrivate::connectViewChanges()
+{
+    // Connect to view change signals if not done yet
+    if (!mViewChangeConnected) {
+        mViewChangeConnected = true;
+        QList<HbMainWindow *> windowList = hbInstance->allMainWindows();
+        foreach (const HbMainWindow *window, windowList) {
+            connect(window, SIGNAL(currentViewChanged(HbView*)), SLOT(handleViewChanged(HbView*)));
+        }
+        // Need a notification when a mainwindow is added in the future.
+        connect(HbInstancePrivate::d_ptr(), SIGNAL(windowAdded(HbMainWindow*)), SLOT(handleWindowAdded(HbMainWindow*)));
+    }
+}
+
+void HbEffectPrivate::handleWindowAdded(HbMainWindow *window)
+{
+    connect(window, SIGNAL(currentViewChanged(HbView*)), SLOT(handleViewChanged(HbView*)));
+}
+
+void HbEffectPrivate::handleViewChanged(HbView *view)
+{
+     // Observers may be notified during cancellations which may result in starting a new
+    // effect during which groups may be deleted and removed from
+    // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
+    QList<HbEffectGroup *> groupsToBeHandled;
+    foreach (HbEffectGroup *group, d.mEventEffectList) {
+        groupsToBeHandled.append(group);
+    }
+
+    foreach (HbEffectGroup *group, groupsToBeHandled) {
+    // Check if the real list still contains the group. If not then it may have been
+    // deleted and removed meanwhile so do nothing.
+    if (d.mEventEffectList.values().contains(group)) {
+        if (group->isRunning()) {
+            // Looping effect
+            if (group->isLooping()) {
+                if (group->view() == view) {    
+                    group->resume(); // Effect's view activated, resume effect
+                } else {
+                    group->pause(); // Effect's view deactivated, pause effect
+                }
+            } else { // Non-looping effect
+                if (group->view() != view) { // Effect's view deactivated, cancel the effect
+                    group->cancelAll(true);
+              
+                    // remove group from eventEffectsList
+                    QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
+                     while (e != d.mEventEffectList.end()) {
+                         if (e.value() == group) { // found, erase from event effect list
+                             d.mEventEffectList.erase(e);
+                             e = d.mEventEffectList.end();
+                         }
+                         else
+                            e++;  // try next one
+                     }
+                     delete group; // once removed from list, delete group
+                }
+            }
+        }
+    }    
+}
+}
+
+
+HbAnimatedItemGroup::HbAnimatedItemGroup(
+    const QList<QGraphicsItem *> &items,
+    QObject *receiver,
+    const char *member,
+    const QVariant &userData) :
+    QObject(),
+    mItems(items),
+    mFinishedCount(0),
+    mReceiver(receiver),
+    mFunction(member ? QString(member) : QString()),
+    mUserData(userData)
+{
+    // Need information of receiver destroyed because this class gets
+    // the notifications asynchronously so it must not invoke the
+    // receiver if it has been destroyed meanwhile.
+    connect(mReceiver, SIGNAL(destroyed()), this, SLOT(receiverDestroyed())); 
+}
+
+void HbAnimatedItemGroup::finished(const HbEffect::EffectStatus &status)
+{
+    if (++mFinishedCount == mItems.count()) {
+        if (mReceiver && !mFunction.isEmpty()) {
+            QMetaObject::invokeMethod(
+                mReceiver,
+                mFunction.toAscii().data(),
+                Qt::AutoConnection,
+                QGenericReturnArgument(),
+                Q_ARG(HbEffect::EffectStatus, status));
+        }
+        // We are done, delete self.
+        deleteLater();
+    }
+}
+
+void HbAnimatedItemGroup::receiverDestroyed()
+{
+    // Receiver object was destroyed, set pointer to NULL so it is not invoked any more.
+    mReceiver = 0;
+}
+
+// ===========================================================================
+
+/*!
+  @stable
+  @hbcore
+  \class HbEffect
+
+  \brief HbEffect is used to control effects on graphics components.
+
+  HbEffect has functions to start or cancel effects (like scaling, fading,
+  rotation, various filter effects). The effects are usually trigerred by
+  various events and are themable.  The effect definition is read from FXML
+  files. All the widgets which want to show an effect should have their effects
+  defined in an FXML file.  For example, view can have an effect animation
+  defined in albumitem_anim.fxml with the following content:
+
+  \code
+
+  <layers>
+  <visual>
+
+  <param name="scale_x" type="anim">
+  <duration>0.1</duration>
+  <style>inoutback</style>
+  <keyframe at="0.0">1.0</keyframe>
+  <keyframe at="1.0">2.0</keyframe>
+  </param>
+  <param name="scale_y" type="anim">
+  <keyframe at="0.0">1.0</keyframe>
+  <keyframe at="1.0">2.0</keyframe>
+  </param>
+  <param name="scale_origin_x" ref="visual.width">0.5</param>
+  <param name="scale_origin_y" ref="visual.height">0.5</param>
+  <param name="opacity" type="anim">
+  <duration>0.1</duration>
+  <style>linear</style>
+  <keyframe at="0.0">1.0</keyframe>
+  <keyframe at="1.0">0.5</keyframe>
+  </param>
+
+  </visual>
+  </layers>
+
+  \endcode
+
+  Example of how to use HbEffect
+
+  \snippet{HbShow/hbsalbumsview.cpp,1}
+
+*/
+
+/*!
+  \struct HbEffect::EffectStatus
+  \brief Stores status information of the effect that has finished.
+  It is passed as an argument to the receiver slot provided by the user of the API.
+*/
+
+/*!
+  \var QGraphicsItem* HbEffect::EffectStatus::item
+
+  The graphics item that has completed its effect.
+*/
+
+/*!
+  \var QString HbEffect::EffectStatus::effectEvent
+
+  The effect event that was passed in the HbEffect::start when the effect was started.
+*/
+
+/*!
+  \var Hb::EffectEvent HbEffect::EffectStatus::reason
+
+  The reason why the effect finished.
+*/
+
+/*!
+  \var QVariant HbEffect::EffectStatus::userData
+
+  Optional user data that was passed in the HbEffect::start when the effect was started.
+*/
+
+
+/*!  This function can be used to register an FXML file for a particular type of
+  component (so that the effect is not tied to any particular widget or graphics
+  item instance).
+
+  \param itemType Type of the item effect is targeted to. The same type
+  identifier should be used when HbEffect::start is called.  Avoid
+  over-simplified item type strings like "item" if there is any risk that it
+  will clash with other effect definitions.  Item type strings starting with
+  prefix "HB_" are reserved for effects defined internally in HB library.  Such
+  definitions cannot be added with this API.
+  \param filePath The path of effect definition XML file or the logical name rather than the whole path.
+  The logical name corresponds to the XML filename without the extension).
+
+  \param effectEvent Effect event identifier that the effect is targeted to.
+
+  The same type identifier should be used when HbEffect::start is called.
+*/
+bool HbEffect::add(
+    const QString &itemType,
+    const QString &filePath,
+    const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    // This API cannot be used to add HB library's effect definitions.
+    // There is internal API in class HbEffectInternal for that.
+    if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) 
+    {
+        return false;
+    }
+    return HbEffectInternal::add(itemType, filePath, effectEvent);
+
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!  Registers multiple FXML files at the same time and guarantees that either
+  all or none of them are registered. This means that if one of the files cannot
+  be found or parsed then none of the others will be registered.
+
+  \param itemType A list of types. The number of elements in all three
+  lists must be the same or else the function will fail and return \i
+  false. As a special exception \a effectEvent is allowed to be empty
+  even when the other lists are not.
+
+  \param filePath A list of file names.
+
+  \param effectEvent A list of effect event identifiers.
+
+  \return True if all the files were registered, false if none. Also returns
+  false if the lists' element counts do not match.
+
+  \sa HbEffect::add(const QString &, const QString &, const QString &)
+ */
+bool HbEffect::add(
+    const QStringList &itemType,
+    const QStringList &filePath,
+    const QStringList &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    foreach (const QString &type, itemType) {
+        if (type.startsWith(HB_EFFECT_ITEM_PREFIX))
+            return false;
+    }
+    return HbEffectInternal::add(itemType, filePath, effectEvent);
+#endif // HB_EFFECT_API_OFF
+}
+
+/*!  This function can be used to register an FXML file for a particular object
+  instance.  The registered effect will be used when HbEffect::start() is called
+  with the matching graphics item and effect event parameters.
+
+  The function takes the following parameters:
+  \param item Item which the effect in bound to.
+  \param filePath The path of effect definition XML file or the logical name rather than the whole path.
+  The logical name corresponds to the XML filename without the extension).
+  \param effectEvent Effect event identifier.
+
+*/
+bool HbEffect::add(
+    QGraphicsItem *item,
+    const QString &filePath,
+    const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    return HbEffectInternal::add(item, filePath, effectEvent);
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! Registers multiple FXML files for a particular graphics item and guarantees
+ *  that either all or none of them are registered. This means that if one of
+ *  the files cannot be found or parsed then none of the others will be
+ *  registered.
+ *
+ * \param item Item to which the effect is bound.
+ *
+ * \param filePath Name of the FXML file.
+ *
+ * \param effectEvent Effect event identifier. The number of elements
+ * in \a filePath and \a effectEvent must match, unless effectEvent is
+ * empty.
+ */
+bool HbEffect::add(QGraphicsItem *item, const QStringList &filePath, const QStringList &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+#else
+    return HbEffectInternal::add(item, filePath, effectEvent);
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! This function can be used to unregister an FXML file for a particular
+  component. Note that you have to have the effect registered with a matching
+  itemType identifier to remove it with this method.
+
+  This will not stop any on-going effects (even if the effect is the one being unregistered),
+  for that call also cancel() before remove().
+
+  The function takes following parameters:
+  \param itemType Type of the item, for example "menu", "button" or "listitem"
+  \param filePath The path of effect definition XML file.
+  \param effectEvent Effect event identifier.
+*/
+bool HbEffect::remove(
+    const QString &itemType,
+    const QString &filePath,
+    const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    // This API cannot be used to remove HB library's effect definitions.
+    // There is internal API in class HbEffectInternal for that.
+    if (itemType.startsWith(HB_EFFECT_ITEM_PREFIX)) 
+    {
+        return false;
+    }
+    HbEffectInternal::remove(itemType, filePath, effectEvent);
+    return true;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! This function can be used to unregister an FXML file for a particular item.
+
+  This will not stop any on-going effects (even if the effect is the one being unregistered),
+  for that call also cancel() before remove().
+
+  The function takes following parameters:
+  \param item The widget or graphics item
+  \param filePath The path of effect definition XML file.
+  \param effectEvent Effect event identifier.
+*/
+bool HbEffect::remove(
+    QGraphicsItem *item,
+    const QString &filePath,
+    const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    HbEffectInternal::remove(item, filePath, effectEvent);
+    return true;
+#endif //HB_EFFECT_API_OFF
+
+}
+
+/*! This function can be used to unregister all FXML files for a particular item.
+
+  This will not stop any on-going effects (even if the effect is the one being unregistered),
+  for that call also cancel() before remove().
+
+  The function takes following parameters:
+  \param item The instance for which all FXML files must be unregistered
+*/
+bool HbEffect::remove(QGraphicsItem *item)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    return false;
+#else
+    HbEffectInternal::remove(item);
+    return true;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! \brief This function is used to start an effect on a graphics item. 
+
+  The effect definition is taken from the FXML file registered for the graphics
+  item with matching itemType and effectEvent.
+
+  \param item The target item for the effect
+
+  \param itemType This is an string identifying type of item. For example,
+  "menu", "button", "scrollbar" or "listitem". This should be same as the one
+  passed in HbEffect::add() function for adding the xml.
+
+  \param effectEvent A string identifying effect event type (e.g "appear").
+  This should be same as the one passed in HbEffect::add() function for adding
+  the xml.
+
+  \param receiver This is an QObject which is notified by calling its slot
+  when this effect is finished. This is optional parameter and default value is
+  NULL.
+
+  \param member The name of the function of receiver which will be called when
+  effect is finished. This is an optional parameter and its default value is 0.
+  The signature of the function must be the following: \c void
+  memberSlotName(const HbEffect::EffectStatus &status)
+
+  \note It is guaranteed that the slot is always invoked once, unless prohobited
+  when canceling the effect.  Normally the slot is invoked asynchronously when
+  the effect has finished or it has been canceled.  If the effect is not started
+  at all, the slot is invoked synchronously with the reason
+  Hb::EffectNotStarted.
+
+  \param userData Any user data provided here will be passed back in the
+  HbEffectStatus struct when the effect being finished is notified to the client
+  via the given slot.  This may help the client to keep track of the states when
+  the effect was started and ended.
+
+  \param extRect Defines external rectangle to be used with the effect. It has
+  effect only with scale and translate effects, which use the "extrect" keyword
+  in the effect definition. With this parameter you can e.g. create an effect,
+  which scales and translates the item from any given rectangle to its own
+  rectangle.
+
+  \sa HbEffect::EffectStatus
+
+  The function returns \c false if some invalid parameter is passed, or if the
+  effect was disabled using disable().
+
+  Example to get notification of effect completion.
+  \code
+  // Create a public slot in a the widget class if you want to get effect-finished 
+  // notification. In normal scenario, the widget itself can be receiver. But it is possible 
+  // to use any QObject as receiver.
+  class MyHbWidget : public HbWidget
+  {
+  Q_OBJECT
+  public slots:
+  void effectFinished(const HbEffect::EffectStatus &status);
+  // Other stuffs 
+  };
+    
+  void MyObserver::effectFinished(const HbEffect::EffectStatus &status)
+  {
+  // Effect is finished. Do something.
+  }
+
+  // Some function which starts effect..
+  void MyHbWidget::myFunction()
+  {
+  // myFunction related other stuff
+  // calling startefect
+  HbEffect::start(myGraphicsItem, 
+  "myItemType",
+  "myEvent",
+  this,
+  "effectFinished");
+        
+  // myFunction related other stuff
+  }
+  \endcode
+  \sa cancel()
+*/
+bool HbEffect::start(QGraphicsItem *item, 
+                     const QString &itemType, 
+                     const QString &effectEvent,
+                     QObject *receiver,
+                     const char *member,
+                     const QVariant &userData,
+                     const QRectF &extRect)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item)
+    Q_UNUSED(itemType);
+    Q_UNUSED(effectEvent);
+    Q_UNUSED(receiver)
+    Q_UNUSED(member);
+    Q_UNUSED(userData)
+    Q_UNUSED(extRect)
+    return false;
+#else
+    return HbEffectInternal::start(item, item, false, itemType, effectEvent, receiver, member, userData, extRect);
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! \brief This function starts the same effect for a given graphics item.
+
+  \param item The target item for the effect
+
+  \param effectEvent A string identifying effect event type (e.g "appear").
+  This should be same as the one passed in HbEffect::add() function for adding the xml.
+
+  \param receiver This is a QObject which is notified once by calling its slot
+  when all of the items have finished their effects. This is an optional
+  parameter and its default value is NULL. Ownership is not transferred.
+
+  \param member The name of the function of receiver which will be called when
+  effect is finished. This is an optional parameter and its default value is 0.
+  The signature of the function must be the following: \c void
+  memberSlotName(const HbEffect::EffectStatus &status)
+
+  \note It is guaranteed that the slot is always invoked once, unless prohobited
+  when canceling the effect.  Normally the slot is invoked asynchronously when
+  the effect has finished or it has been canceled.  If the effect is not started
+  at all, the slot is invoked synchronously with the reason
+  Hb::EffectNotStarted.
+
+  \param userData Any user data provided here will be passed back in the
+  HbEffectStatus struct when the effect being finished is notified to the client
+  via the given slot.  This may help the client to keep track of the states when
+  the effect was started and ended.
+
+  \sa HbEffect::EffectStatus
+
+  The function returns \c false if some invalid parameter is passed, or if the
+  effect was disabled using disable().
+*/
+bool HbEffect::start(QGraphicsItem *item, 
+                     const QString &effectEvent,
+                     QObject *receiver,
+                     const char *member,
+                     const QVariant &userData,
+                     const QRectF &extRect)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(effectEvent);
+    Q_UNUSED(receiver);
+    Q_UNUSED(member);
+    Q_UNUSED(userData);
+    Q_UNUSED(extRect);
+    return false;
+#else
+    return HbEffect::start(
+        item, HB_EFFECT_INTERNAL_ITEM, effectEvent, receiver, member, userData, extRect);
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!  \brief This function starts the same effect simultaneously for a given list
+  of graphics items.
+
+  The effect definition is taken from the FXML file registered to the given item
+  type.
+
+  \param items The target items for the effect
+
+  \param itemType A string identifying the type of the items. For example,
+  "button".  This should be same as the one passed in HbEffect::add() function
+  for adding the xml.
+
+  \param effectEvent A string identifying effect event type (e.g "appear").
+  This should be same as the one passed in HbEffect::add() function for adding
+  the xml.
+
+  \param receiver This is a QObject which is notified once by calling its slot
+  when all of the items have finished their effects. This is an optional
+  parameter and its default value is NULL. Ownership is not transferred.
+
+  \param member The name of the function of receiver which will be called when
+  effect is finished. This is an optional parameter and its default value is 0.
+  The signature of the function must be the following: \c void
+  memberSlotName(const HbEffect::EffectStatus &status)
+
+  \note It is guaranteed that the slot is always invoked once, unless prohobited
+  when canceling the effect.  Normally the slot is invoked asynchronously when
+  the effect has finished or it has been canceled.  If the effect is not started
+  at all, the slot is invoked synchronously with the reason
+  Hb::EffectNotStarted.
+
+  \param userData Any user data provided here will be passed back in the
+  HbEffectStatus struct when the effect being finished is notified to the client
+  via the given slot.  This may help the client to keep track of the states when
+  the effect was started and ended.
+
+  \sa HbEffect::EffectStatus
+
+  The function returns \c false if some invalid parameter is passed, or if the
+  effect was disabled using disable().
+*/
+bool HbEffect::start(
+    const QList<QGraphicsItem *> &items, 
+    const QString &itemType, 
+    const QString &effectEvent,
+    QObject *receiver,
+    const char *member,
+    const QVariant &userData)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(items);
+    Q_UNUSED(itemType); 
+    Q_UNUSED(effectEvent);
+    Q_UNUSED(receiver);
+    Q_UNUSED(member);
+    Q_UNUSED(userData);
+    return false;
+#else
+    if (privateDestroyed) {
+        return false;
+    }
+
+    // Connect to view changes if not done yet
+    d.connectViewChanges();
+
+    // This object deletes itself when the effect has finished.
+    HbAnimatedItemGroup *group = new HbAnimatedItemGroup(items, receiver, member, userData);
+
+    bool ret = false;
+
+    QObject *groupReceiver = 0;
+    const char *groupMember = "";
+
+    // If caller has given observer for the group of items,
+    // set the group object as observer in HbEffect::start calls.
+    // It gives callback to the caller when the whole group has finished.
+
+    if (receiver) {
+        groupReceiver = group;
+        groupMember = "finished";
+    }
+
+    foreach (QGraphicsItem *item, items) {
+        if (HbEffect::start(item, itemType, effectEvent, groupReceiver, groupMember, userData)) {
+            // If at least one item succeeded to start, set return value to true
+            ret = true;
+        }
+    }
+
+    return ret;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! Reports whether the given graphics \a item is currently running an effect.
+
+  \param item pointer to the graphics item in question.
+
+  \param effectEvent String identifying effect-event type (eg "appear"). If this
+  string is empty, the function returns true if the item is running any effect.
+
+  The function returns \c false if some invalid parameter is passed.
+*/
+bool HbEffect::effectRunning(QGraphicsItem *item, const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    bool ret = false;
+
+    // Return true if the given item is running any effect
+    if (effectEvent.isEmpty()) {
+        for (QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.constBegin();
+             e != d.mEventEffectList.constEnd();
+             ++e ) {
+            HbEffectGroup *group = *e;
+            if (group->registrationItem() == item && group->isRunning()) {
+                ret = true;
+                break;
+            }
+        }
+    } else {
+        // effectEvent was specified, check if effect matching that is running
+        EffectMapKey key(item, effectEvent);
+        QMap<EffectMapKey, HbEffectGroup *>::const_iterator e = d.mEventEffectList.find(key);
+    
+        // Effect found in the list?
+        if(e != d.mEventEffectList.constEnd()) {
+            HbEffectGroup* group = *e;
+            ret = group->isRunning();
+        }
+    }
+
+    return ret;
+#endif //HB_EFFECT_API_OFF
+}
+
+
+/*! This function is used to cancel a running effect. The end state of the item
+  is reached after cancelation of effect.
+
+  \param item  pointer to a QGraphicsItem
+
+  \param effectEvent  String identifying effect-event type (eg "appear"). If
+  not passed, all the effects running currently on the item are canceled.
+
+  \param hideEffect   If false, the effect is left in its end state in the
+                      graphics item.  If true, the effect is hidden from the
+                      graphics item.
+
+  \param sendCallback   Optional boolean parameter (true if omitted), which
+                        controls if the cancel call results to our
+                        effectFinished slot being called.  This should be false
+                        in (for example) in destructor where you are cancelling
+                        effects but not wanting any callbacks.
+
+  \param itemIsValid This parameter tells whether the passed item pointer points
+  to a valid object and can accessed when canceling the effect. For example, if
+  this method is called from a graphics item base class destructor, the item
+  object may be already partially destructed and this parameter should be set to
+  false.
+
+  The function returns \c false if some invalid parameter is passed.
+
+  \sa start()
+*/
+bool HbEffect::cancel(
+    QGraphicsItem *item,
+    const QString &effectEvent,
+    bool hideEffect,
+    bool sendCallback,
+    bool itemIsValid)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(effectEvent);
+    Q_UNUSED(hideEffect);
+    Q_UNUSED(sendCallback);
+    Q_UNUSED(itemIsValid);
+    return false;
+#else 
+    if ( privateDestroyed ) {
+        return false;
+    }
+
+    bool ret = false;
+
+    if (effectEvent.isEmpty()) {
+        // Stop all the effects running on item at that point of time.
+        // (iterator way had some problem and caused crash so using foreach)
+
+        QList<HbEffectGroup *> groupsToBeCanceled;
+
+        foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
+            if (key.mItem == item) {
+                HbEffectGroup* group = d.mEventEffectList.take(key);
+                groupsToBeCanceled.append(group);
+            }
+        }
+
+        // Before blindly calling cancelAll to the effect groups, try to fix their order so that
+        // combining different transformation end states works as well as possible. Note that there
+        // may still be incorrect end state if there are multiple effect groups which each have multiple effects,
+        // but this at least fixes cases, where there are multiple effect groups which each consist of a single effect.
+        fixEffectGroupOrder(&groupsToBeCanceled);
+
+        bool first = true;
+
+        foreach(HbEffectGroup *group, groupsToBeCanceled) {
+            // If hideEffect is false then it is important to pass a default transform
+            // first so the matrix multiplication in cancelAll ends up correct.
+            group->cancelAll(sendCallback, itemIsValid, hideEffect, first || !itemIsValid ? QTransform() : item->transform());
+            if (first) {
+                first = false;
+            }
+            delete group;
+            // return true if any of the effect was canceled
+            ret = true;
+        }
+
+        return ret;
+    }
+    else {
+        EffectMapKey key(item, effectEvent);
+        HbEffectGroup* group = d.mEventEffectList.take(key);
+        if (group) {
+            group->cancelAll(sendCallback, itemIsValid, hideEffect);
+            delete group;
+            return true;
+        } else {
+            return false;
+        }
+    }
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! This function can be used to reverse the effect of disable(). So if the
+  effect for a graphicsitem was disabled this method can be used to enable the
+  effect again for that item.
+
+  The function takes following parameters:
+  \param item pointer to QGraphicsItem for which the effect will be enabled.
+    
+  \sa disable()
+*/
+void HbEffect::enable(QGraphicsItem *item)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+#else
+    d.mDisabledItems.removeOne(item);
+#endif //HB_EFFECT_API_OFF
+}
+
+/*! This function can be used to disable an effect for a graphicsitem. This is
+  useful in cases where you have a component which usually shows an effect but
+  you want to skip the effect for your object.
+    
+  You can enable the effect using enable(), and you should always call enable()
+  once you do not need the object to be disabled, at latest when you're deleting
+  your animated graphicsitem. This should be done to clean up the list of
+  disabled items. Note that if the animated item is an HbWidget, then the
+  enable() call happens automatically at the HbWidget destructor.
+    
+  Unlike remove()-methods, this won't touch the effect definition at all. The
+  effect is just skipped when trying to start the effect.  Note also that
+  start()-method returns false if the effect is disabled.
+
+  \param item pointer to QGraphicsItem for which the effect will be disabled
+    
+  \sa enable()
+  \sa start()
+*/
+void HbEffect::disable(QGraphicsItem *item)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+#else
+    if (!d.mDisabledItems.contains(item)) {
+        d.mDisabledItems.append(item);
+    }
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+HbGVWrapperItem::HbGVWrapperItem():mMainWindow(0)
+{
+}
+
+void HbGVWrapperItem::setMainWindow(HbMainWindow& mainWindow)
+{
+    mMainWindow = &mainWindow;
+}
+
+HbMainWindow *HbGVWrapperItem::mainWindow() const
+{
+    return mMainWindow;
+}
+
+QRectF HbGVWrapperItem::boundingRect() const
+{
+    QRectF bRect;
+    // viewportitem is used as a boundingrect since viewport item gets resized when changing orientation
+    if( mMainWindow ) {
+        QGraphicsWidget *viewPortItem = mMainWindow->element(HbMainWindow::ViewportItem);
+        if( viewPortItem ) {
+            bRect.setRect( 0,0,viewPortItem->geometry().width(),viewPortItem->geometry().height() );
+        }
+    }
+    return bRect;
+}
+void HbGVWrapperItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) 
+{
+    Q_UNUSED(painter);
+    Q_UNUSED(option);
+    Q_UNUSED(widget);
+};
+
+/*!
+  \internal
+*/
+bool HbEffectInternal::add(const QString &itemType, const QString &filePath, const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    // Add and try to use sharing.
+    bool ret = d.mController.addFXML(itemType, filePath, effectEvent, true);
+    if (ret) {
+        // Mark all effects using the given item type dirty,
+        // so that they get re-created when the effect is shown next time
+        for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
+             e != d.mEventEffectList.end();
+             ++e ) {
+            HbEffectGroup *group = *e;
+
+            if (group->itemType() == itemType) {
+                group->setDirty(true);
+            }
+        }
+    }
+
+    return ret;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+bool HbEffectInternal::add(const QStringList &itemType, const QStringList &filePath, const QStringList &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    int count = itemType.count();
+    if (count != filePath.count() || (count != effectEvent.count() && !effectEvent.isEmpty())) {
+        return false;
+    }
+    bool ret = false;
+    // Try to add all the files, stop when one fails.
+    for (int i = 0; i < count; ++i) {
+        ret = add(itemType.at(i), filePath.at(i), effectEvent.isEmpty() ? QString() : effectEvent.at(i));
+        if (!ret) {
+            break;
+        }
+    }
+    // If any of the files were not added then remove all the others too.
+    if (!ret) {
+        for (int i = 0; i < count; ++i) {
+            remove(itemType.at(i), filePath.at(i), effectEvent.isEmpty() ? QString() : effectEvent.at(i));
+        }
+    }
+    return ret;
+#endif // HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+bool HbEffectInternal::add(QGraphicsItem *item, const QString &filePath, const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    bool ret = false;
+
+    // FXML
+    // Add and try to use sharing.
+    ret = d.mController.addFXML(item, filePath, effectEvent, true);
+
+    if (ret) {
+        // Mark all effects using the given item type dirty,
+        // so that they get re-created when the effect is shown next time
+        for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
+             e != d.mEventEffectList.end();
+             ++e ) {
+            HbEffectGroup *group = *e;
+
+            if (group->registrationItem() == item) {
+                group->setDirty(true);
+            }
+        }
+    }
+
+    return ret;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+bool HbEffectInternal::add(QGraphicsItem *item, const QStringList &filePath, const QStringList &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+    return false;
+#else
+    int count = filePath.count();
+    if (count != effectEvent.count() && !effectEvent.isEmpty()) {
+        return false;
+    }
+    bool ret = false;
+    // Try to add all the files, stop when one fails.
+    for (int i = 0; i < count; ++i) {
+        ret = add(item, filePath.at(i), effectEvent.isEmpty() ? QString() : effectEvent.at(i));
+        if (!ret) {
+            break;
+        }
+    }
+    // If any of the files were not added then remove all the others too.
+    if (!ret) {
+        for (int i = 0; i < count; ++i) {
+            remove(item, filePath.at(i), effectEvent.isEmpty() ? QString() : effectEvent.at(i));
+        }
+    }
+    return ret;
+#endif // HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+void HbEffectInternal::remove(const QString &itemType, const QString &filePath, const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(itemType);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+#else
+    // FXML
+    // If extension is not given then try both with and without .fxml
+    if (!filePath.endsWith(".fxml")) {
+        d.mController.removeFXML(itemType, filePath + ".fxml", effectEvent);       
+    }
+    d.mController.removeFXML(itemType, filePath, effectEvent);
+    // Clean up mEventEffectList.
+    foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
+        if (key.mEffectEvent == effectEvent) {
+            HbEffectGroup *group = d.mEventEffectList.value(key);
+            group->setDirty(true); // so the next start() will try to recreate the effect instead of re-using it
+        }
+    }
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+void HbEffectInternal::remove(QGraphicsItem *item, const QString &filePath, const QString &effectEvent)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+    Q_UNUSED(filePath);
+    Q_UNUSED(effectEvent);
+#else
+    // FXML
+    // If extension is not given then try both with and without .fxml
+    if (!filePath.endsWith(".fxml")) {
+        d.mController.removeFXML(item, filePath + ".fxml", effectEvent);       
+    }
+    d.mController.removeFXML(item, filePath, effectEvent);
+    // Clean up mEventEffectList.
+    foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
+        if (key.mItem == item && key.mEffectEvent == effectEvent) {
+            HbEffectGroup *group = d.mEventEffectList.value(key);
+            group->setDirty(true);
+        }
+    }
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  \internal
+*/
+void HbEffectInternal::remove(QGraphicsItem *item)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(item);
+#else
+    if (item) {
+        d.mDisabledItems.removeOne(item); // clean the disabled list as well
+        d.mController.removeFXML(item);
+        // Clean up mEventEffectList.
+        foreach (const EffectMapKey &key, d.mEventEffectList.keys()) {
+            if (key.mItem == item) {
+                HbEffectGroup *group = d.mEventEffectList.value(key);
+                group->setDirty(true);
+            }
+        }
+    }
+#endif //HB_EFFECT_API_OFF
+}
+
+void HbEffectInternal::reloadFxmlFiles()
+{
+    QList<HbEffectInfo> parsedDataList = d.mController.effectEntries();
+    //ToDo Currently all the parsed Fxml Data is being deleted with themechange.
+    //     Make this function intelligent enough to delete only theme specific Fxml
+    //     data.
+    //parsedDataList.clear();
+    QList<HbEffectInfo> newDataList;
+    for (int i=0; i < parsedDataList.count(); i++) {
+        if (parsedDataList[i].fromTheme()) {
+            newDataList.append(parsedDataList[i]);
+            parsedDataList.removeAt(i);
+            i--;
+        }
+    }
+    for (int i=0; i < newDataList.count(); i++) {
+        HbEffectInfo effectData = newDataList.at(i);            
+        bool ret = false;
+        QStringList  splitList = effectData.xmlFileFullPath().split(QRegExp("[\\\\ /]"));
+        QString relativename = splitList.takeLast();
+        relativename.chop(5);
+        if (effectData.item() != 0) {
+            ret = d.mController.addFXML(effectData.item(), relativename,
+                                        effectData.effectEvent(), true);
+        }
+        else if (!effectData.componentType().isEmpty()) {
+            ret = d.mController.addFXML(effectData.componentType(), relativename,
+                                        effectData.effectEvent(), true);
+        }
+        if (ret) {
+            // Mark all effects using the given item type dirty,
+            // so that they get re-created when the effect is shown next time
+            for (QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.begin();
+                 e != d.mEventEffectList.end();
+                 ++e ) {
+                HbEffectGroup *group = *e;
+                if (group->registrationItem() == effectData.item()) {
+                    group->setDirty(true);
+                }
+            }
+        }
+    }
+    newDataList.clear();
+}
+
+/*!
+  Cancels all effects. List of graphicsitems can be given as an exception which are not cancelled.
+  This is used for example when changing orientation; all but the orientation change effects
+  are cancelled.
+*/
+void HbEffectInternal::cancelAll(const QList<QGraphicsItem*> *exceptionList, bool ignoreLooping)
+{
+    // Observers may be notified during cancelations which may result in starting a new
+    // effect during which groups may be deleted and removed from
+    // mEventEffectList. Therefore we cannot directly iterate on mEventEffectList.
+    QList<HbEffectGroup *> groupsToBeCanceled;
+    foreach (HbEffectGroup *group, d.mEventEffectList) {
+        groupsToBeCanceled.append(group);
+    }
+    foreach (HbEffectGroup *group, groupsToBeCanceled) {
+        // Check if the real list still contains the group. If not then it may have been
+        // deleted and removed meanwhile so do nothing.
+        if (d.mEventEffectList.values().contains(group)) {
+            if (!exceptionList || !exceptionList->contains(group->registrationItem())) {
+                // Already cancelled effects may refer to graphics items that do not
+                // exist anymore. Cancel only "running" (that is, running or paused,
+                // i.e. non-canceled) effects.
+                if (group->isRunning() && (!ignoreLooping || !group->isLooping())) {
+                    group->cancelAll(true);
+                }
+            }
+        }
+    }
+}
+
+/*!
+  Like cancelAll() but no observers are invoked and items are not assumed to
+  be valid anymore.
+ */
+void HbEffectInternal::safeCancelAll()
+{
+    QList<HbEffectGroup *> groupsToBeCanceled;
+    foreach (HbEffectGroup *group, d.mEventEffectList) {
+        groupsToBeCanceled.append(group);
+    }
+    foreach (HbEffectGroup *group, groupsToBeCanceled) {
+        if (d.mEventEffectList.values().contains(group)) {
+            group->cancelAll(false, false);
+        }
+    }
+}
+
+/*!
+  This is a master switch, which stops all effects in the application.
+  Looping effects are paused and other effects are moved in their end state.
+
+  The effect framework automatically stops effects when the application moves in background
+  or display is turned off.
+
+  \sa HbEffectInternal::resumeEffects()
+*/
+void HbEffectInternal::stopEffects()
+{
+    // Pause looping effects and stop others
+    foreach (HbEffectGroup *group, d.mEventEffectList) {
+        if (group->isRunning()) {
+            if (group->isLooping()) {
+                group->pause();
+            } else {
+                group->cancelAll(true);
+            }
+        }
+    }
+}
+
+/*!
+  This is a master switch, which resumes effects in the application.
+  Any looping effects that were paused due to HbEffect::stopEffects() call are resumed.
+
+  The effect framework automatically resumes effects when the application comes back to
+  foreground or display is turned back on.
+
+  \sa HbEffectInternal::stopEffects()
+*/
+void HbEffectInternal::resumeEffects()
+{
+    // Resume any looping effects that were paused with stopEffects call.
+    foreach (HbEffectGroup *group, d.mEventEffectList) {
+        if (group->isRunning() && group->isLooping()) {
+            group->resume();
+        }
+    }
+}
+
+/*!
+  The real implementation for HbEffect::start().
+
+  Watch out for the difference between the registration and target items. Even though in
+  most cases HbEffect::start() will invoke this by passing the same pointer to both, there
+  are certain situations when they can be different (e.g. when a view switch effect is
+  registered via add() by the user for the HbView instance, but effect has to operate on
+  another graphics item, e.g. the view's content widget or some other "screen" item, etc.)
+
+  \a registrationItem is used for all bookeeping (for fxml lookup, in the event-effect
+  list, in effect groups, etc.).  \a targetItem is used only for the actual transformation
+  or filter effect implementations.
+
+  For functions that operate with one graphics item parameter (e.g. cancel()), that
+  parameter corresponds to the \a registrationItem. The internal difference (and
+  possibility) of having separate registration and target items is not exposed to the
+  users of the HbEffect API in any way.
+
+  When \a hideWhenFinished is true (it is typically false when coming from the standard
+  HbEffect APIs) the effect is always hidden when it is finished or canceled (similarly to
+  when cancel() is called with hideEffect set to true).
+
+  \sa HbEffect::start()
+ */
+bool HbEffectInternal::start(QGraphicsItem *registrationItem,
+                             QGraphicsItem *targetItem,
+                             bool hideWhenFinished,
+                             const QString &itemType, 
+                             const QString &effectEvent,
+                             QObject *receiver,
+                             const char *member,
+                             const QVariant &userData,
+                             const QRectF &extRect)
+{
+#ifdef HB_EFFECT_API_OFF
+    Q_UNUSED(registrationItem);
+    Q_UNUSED(targetItem);
+    Q_UNUSED(itemType);
+    Q_UNUSED(effectEvent);
+    Q_UNUSED(receiver)
+    Q_UNUSED(member);
+    Q_UNUSED(userData)
+    Q_UNUSED(extRect)
+    return false;
+#else
+    // Connect to view changes if not done yet
+    d.connectViewChanges();
+
+    // Test error conditions first.
+    bool error = false;
+    if (!targetItem || !registrationItem) {
+#ifdef HBEFFECT_WARNING
+        qWarning("HbEffect Warning: Item is NULL");
+#endif //HBEFFECT_WARNING
+        error = true;
+    }
+
+    if (!d.mEffectsEnabled && targetItem && targetItem->type() != HbGVWrapperItemType) {
+        // Everything was disabled via setEffectsEnabled().
+        error = true;
+    }
+
+    if (!d.mEnabled) {
+#ifdef HBEFFECT_WARNING
+        qWarning("HbEffect Warning: Effect is not enabled");
+#endif //HBEFFECT_WARNING
+        error = true;
+    }
+
+    if (d.mDisabledItems.contains(registrationItem)) {
+#ifdef HBEFFECT_WARNING
+        qWarning("HbEffect Warning: Effect for this item was disabled by an effect client");
+#endif //HBEFFECT_WARNING
+        error = true;
+    }
+
+    // If there was an error in parameters, give notification that the effect was not started.
+    if (error) {
+        if (receiver && member) {
+            HbEffect::EffectStatus status;
+            status.item = registrationItem;
+            status.effectEvent = effectEvent;
+            status.userData = userData;
+            status.reason = Hb::EffectNotStarted;
+
+            QMetaObject::invokeMethod(
+                receiver,
+                member,
+                Qt::AutoConnection,
+                QGenericReturnArgument(),
+                Q_ARG(HbEffect::EffectStatus, status));
+        }
+
+        return false;
+    }
+
+    // Warning conditions here
+    if (!targetItem->boundingRect().isValid()) {
+#ifdef HBEFFECT_WARNING
+        qWarning("HbEffect Warning: Item size not valid in %s", qPrintable(itemType));
+#endif //HBEFFECT_WARNING
+    }
+
+    bool started = false;
+
+    EffectMapKey key(registrationItem, effectEvent);
+    QMap<EffectMapKey, HbEffectGroup *>::iterator e = d.mEventEffectList.find(key);
+
+    // Same effect found in the list?
+    if(e != d.mEventEffectList.end()) {
+        HbEffectGroup *group = e.value();
+        if (!group->dirty()) {
+            // if the effect group is not dirty, restart it. Cancel possible earlier effect first so that
+            // end position gets correct.
+            group->cancelAll(true);
+            
+            // Update with given notification parameters
+            group->setObserver(receiver, member ? QString(member) : QString());
+            group->setUserData(userData);
+            group->setExtRect(extRect);
+            group->setHideWhenFinished(hideWhenFinished);
+
+            group->startAll();
+            started = true;
+        } else {
+            // Delete the effect group if it was dirty
+            delete d.mEventEffectList.take(key);
+        }
+    }
+
+    if (!started) {
+        // Create the effect.
+        HbEffectGroup *group = d.mFactory.createEffect(registrationItem, targetItem, itemType, effectEvent);
+        
+        group->setObserver(receiver, member ? QString(member) : QString());
+        group->setUserData(userData);
+        group->setExtRect(extRect);
+        group->setHideWhenFinished(hideWhenFinished);
+
+        // Store effect to support cancelation and deletion of effect
+        d.mEventEffectList.insert(key, group);
+        group->startAll();
+        // check if definition had effects
+        if( group->effectCount() == 0 ){
+#ifdef HBEFFECT_WARNING
+            qWarning("HbEffect Warning: Starting effect with effect count zero");
+#endif //HBEFFECT_WARNING
+        }
+    }
+
+    return true;
+#endif //HB_EFFECT_API_OFF
+}
+
+/*!
+  A simpler version without itemType.
+ */
+bool HbEffectInternal::start(QGraphicsItem *registrationItem,
+                             QGraphicsItem *targetItem,
+                             bool hideWhenFinished,
+                             const QString &effectEvent,
+                             QObject *receiver,
+                             const char *member,
+                             const QVariant &userData,
+                             const QRectF &extRect)
+{
+    return HbEffectInternal::start(registrationItem, targetItem, hideWhenFinished,
+                                   HB_EFFECT_INTERNAL_ITEM,
+                                   effectEvent, receiver, member, userData, extRect);
+}
+
+/*!  By default effects are enabled. However with this function every effect can
+  be disabled, meaning that HbEffect::start() will have no effect (and will
+  always return false).
+
+  Note that "every effect" is not really every effect, it does not include the
+  orientation switch effect (or any effect performed in the graphics view
+  wrapper item, actually), that is always enabled regardless of this setting.
+
+  \internal
+ */
+void HbEffectInternal::setEffectsEnabled(bool enabled)
+{
+    d.mEffectsEnabled = enabled;
+    if (!d.mEffectsEnabled) {
+        cancelAll();
+    }
+}