homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlestate.cpp
changeset 35 f9ce957a272c
child 36 cdae8c6c3876
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlestate.cpp	Fri Mar 19 09:27:44 2010 +0200
@@ -0,0 +1,1207 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#include <QStateMachine>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsLinearLayout>
+#include <QParallelAnimationGroup>
+#include <QPropertyAnimation>
+#include <QApplication>
+#include <QDir>
+
+#include <HbMainWindow>
+#include <HbView>
+#include <HbMenu>
+#include <HbAction>
+#include <HbIcon>
+
+#include "hsidlestate.h"
+#include "hsidlewidget.h"
+#include "hsscene.h"
+#include "hspage.h"
+#include "hswidgethost.h"
+#include "hswallpaper.h"
+#include "hspagedata.h"
+#include "hsselectbackgroundstate.h"
+#include "hstrashbinwidget.h"
+#include "hspageindicator.h"
+#include "hsapptranslator.h"
+#include "hswidgetpositioningonorientationchange.h"
+#include "hsmenueventfactory.h"
+
+// Helper macros for connecting state entry and exit actions.
+#define ENTRY_ACTION(state, action) \
+    connect(state, SIGNAL(entered()), SLOT(action()));
+#define EXIT_ACTION(state, action) \
+    connect(state, SIGNAL(exited()), SLOT(action()));
+
+// Helper macros for connecting and disconnecting mouse event handlers.
+#define CONNECT_MOUSE_EVENT_HANDLER(signal, slot) \
+    connect(mUiWidget, SIGNAL(signal(QGraphicsItem*, QGraphicsSceneMouseEvent*, bool&)), \
+        SLOT(slot(QGraphicsItem*, QGraphicsSceneMouseEvent*, bool&)));
+#define DISCONNECT_MOUSE_EVENT_HANDLER(signal, slot) \
+    disconnect(mUiWidget, SIGNAL(signal(QGraphicsItem*, QGraphicsSceneMouseEvent*, bool&)), \
+        this, SLOT(slot(QGraphicsItem*, QGraphicsSceneMouseEvent*, bool&)));
+
+
+namespace
+{
+    const char APP_LIB_BUTTON[] = 
+        "hs_applib_button.png";
+    /*const char TXT_HOMESCREEN_TITLE_OFFLINE[] = 
+        "txt_homescreen_title_offline";*/
+    const char TXT_HOMESCREEN_OPT_ADD_PAGE[] = 
+        "txt_homescreen_opt_add_page";
+    const char TXT_HOMESCREEN_OPT_REMOVE_PAGE[] = 
+        "txt_homescreen_opt_remove_page";
+    const char TXT_HOMESCREEN_OPT_HOME_SCREEN_TO_ONLINE[] = 
+        "txt_homescreen_opt_home_screen_to_online";
+    const char TXT_HOMESCREEN_OPT_HOME_SCREEN_TO_OFFLINE[] = 
+        "txt_homescreen_opt_home_screen_to_offline";
+    const char TXT_HOMESCREEN_LIST_CHANGE_WALLPAPER[] = 
+        "txt_homescreen_list_change_wallpaper";
+    const char TXT_HOMESCREEN_LIST_ADD_CONTENT[] = 
+        "txt_homescreen_list_add_content";
+}
+
+/*!
+    \class HsIdleState
+    \ingroup group_hshomescreenstateplugin
+    \brief Controller part of the home screen idle state.
+
+    Controls the home screen idle state execution. See the
+    state chart below for the state structure.
+
+    \image html hsidlestate_statechart.png
+*/
+
+/*!
+    Constructs a new idle state with the given \a parent.
+*/
+HsIdleState::HsIdleState(QState *parent)
+  : QState(parent),
+    mView(0), mSoftKeyAction(0), mUiWidget(0),
+    mTapAndHoldDistance(16),
+    mPageChangeZoneWidth(60)
+{
+    setupStates();
+    mTimer.setSingleShot(true);
+}
+
+/*!
+    Destroys this idle state.
+*/
+HsIdleState::~HsIdleState()
+{
+}
+
+/*!
+    \fn HsIdleState::event_applicationLibrary()
+
+    This signal initiates a transition to application library.
+*/
+
+/*!
+    \fn HsIdleState::event_waitInput()  
+
+    This signal initiates a transition to the waitInput state.
+*/
+
+/*!
+    \fn HsIdleState::event_widgetInteraction()  
+
+    This signal initiates a transition to the widgetInteraction state.
+*/
+
+/*!
+    \fn HsIdleState::event_sceneInteraction()  
+
+    This signal initiates a transition to the sceneInteraction state.
+*/
+
+/*!
+    \fn HsIdleState::event_moveWidget()  
+
+    This signal initiates a transition to the moveWidget state.
+*/
+
+/*!
+    \fn HsIdleState::event_moveScene()  
+
+    This signal initiates a transition to the moveScene state.
+*/
+
+/*!
+    \fn HsIdleState::event_sceneMenu()  
+
+    This signal initiates a transition to the sceneMenu state.
+*/
+
+/*!
+    \fn HsIdleState::event_selectSceneWallpaper()  
+
+    This signal initiates a transition to the selectSceneWallpaper state.
+*/
+
+/*!
+    \fn HsIdleState::event_addPage()  
+
+    This signal initiates a transition to the addPage state.
+*/
+
+/*!
+    \fn HsIdleState::event_removePage()  
+
+    This signal initiates a transition to the removePage state.
+*/
+
+/*!
+    \fn HsIdleState::event_toggleConnection()  
+
+    This signal initiates a transition to the toggleConnection state.
+*/
+
+/*!
+    Creates the internal state structure and connects
+    state entry and exit actions.
+*/
+void HsIdleState::setupStates()
+{   
+    // States
+
+    QState *state_waitInput = new QState(this);
+    setInitialState(state_waitInput);
+    QState *state_widgetInteraction = new QState(this);
+    QState *state_sceneInteraction = new QState(this);
+    QState *state_moveWidget = new QState(this);
+    QState *state_moveScene = new QState(this);
+    QState *state_sceneMenu = new QState(this);
+    HsSelectBackgroundState *state_selectSceneWallpaper = 
+        new HsSelectBackgroundState(this);
+    QState *state_addPage = new QState(this);
+    QState *state_removePage = new QState(this);
+    QState *state_toggleConnection = new QState(this);
+
+    // Transitions
+
+    state_waitInput->addTransition(
+        this, SIGNAL(event_widgetInteraction()), state_widgetInteraction);
+    state_waitInput->addTransition(
+        this, SIGNAL(event_sceneInteraction()), state_sceneInteraction);
+    state_waitInput->addTransition(
+        this, SIGNAL(event_addPage()), state_addPage);
+    state_waitInput->addTransition(
+        this, SIGNAL(event_removePage()), state_removePage);
+    state_waitInput->addTransition(
+        this, SIGNAL(event_toggleConnection()), state_toggleConnection);
+
+    state_widgetInteraction->addTransition(
+        this, SIGNAL(event_waitInput()), state_waitInput);
+    state_widgetInteraction->addTransition(
+        this, SIGNAL(event_moveWidget()), state_moveWidget);
+
+    state_sceneInteraction->addTransition(
+        this, SIGNAL(event_waitInput()), state_waitInput);
+    state_sceneInteraction->addTransition(
+        this, SIGNAL(event_moveScene()), state_moveScene);
+    state_sceneInteraction->addTransition(
+        this, SIGNAL(event_sceneMenu()), state_sceneMenu);
+    
+    state_moveWidget->addTransition(
+        this, SIGNAL(event_waitInput()), state_waitInput);
+    
+    state_moveScene->addTransition(
+        this, SIGNAL(event_waitInput()), state_waitInput);
+
+    state_sceneMenu->addTransition(
+        this, SIGNAL(event_waitInput()), state_waitInput);
+    state_sceneMenu->addTransition(
+        this, SIGNAL(event_selectSceneWallpaper()), state_selectSceneWallpaper);
+
+    state_selectSceneWallpaper->addTransition(
+        state_selectSceneWallpaper, SIGNAL(event_waitInput()), state_waitInput);
+
+    state_addPage->addTransition(state_waitInput);
+
+    state_removePage->addTransition(state_waitInput);
+
+    state_toggleConnection->addTransition(state_waitInput);
+
+    // Actions
+
+    ENTRY_ACTION(this, action_idle_setupView)
+    ENTRY_ACTION(this, action_idle_layoutNewWidgets)
+    ENTRY_ACTION(this, action_idle_showActivePage)
+    ENTRY_ACTION(this, action_idle_connectOrientationChangeEventHandler)
+    EXIT_ACTION(this, action_idle_cleanupView)
+    EXIT_ACTION(this, action_idle_disconnectOrientationChangeEventHandler)
+
+    ENTRY_ACTION(state_waitInput, action_waitInput_updateOptionsMenu)
+    ENTRY_ACTION(state_waitInput, action_waitInput_connectMouseEventHandlers)
+    EXIT_ACTION(state_waitInput, action_waitInput_disconnectMouseEventHandlers)
+
+    ENTRY_ACTION(state_widgetInteraction, action_widgetInteraction_connectMouseEventHandlers)
+    ENTRY_ACTION(state_widgetInteraction, action_widgetInteraction_connectGestureTimers)
+    EXIT_ACTION(state_widgetInteraction, action_widgetInteraction_disconnectMouseEventHandlers)
+    EXIT_ACTION(state_widgetInteraction, action_widgetInteraction_disconnectGestureTimers)
+
+    ENTRY_ACTION(state_sceneInteraction, action_sceneInteraction_connectMouseEventHandlers)
+    ENTRY_ACTION(state_sceneInteraction, action_sceneInteraction_connectGestureTimers)
+    EXIT_ACTION(state_sceneInteraction, action_sceneInteraction_disconnectMouseEventHandlers)
+    EXIT_ACTION(state_sceneInteraction, action_sceneInteraction_disconnectGestureTimers)
+
+    ENTRY_ACTION(state_moveWidget, action_moveWidget_reparentToControlLayer)
+    ENTRY_ACTION(state_moveWidget, action_moveWidget_startWidgetDragAnimation)
+    ENTRY_ACTION(state_moveWidget, action_moveWidget_connectMouseEventHandlers)
+    ENTRY_ACTION(state_moveWidget, action_moveWidget_connectGestureTimers)
+    EXIT_ACTION(state_moveWidget, action_moveWidget_reparentToPage)
+    EXIT_ACTION(state_moveWidget, action_moveWidget_startWidgetDropAnimation)
+    EXIT_ACTION(state_moveWidget, action_moveWidget_disconnectMouseEventHandlers)
+    EXIT_ACTION(state_moveWidget, action_moveWidget_disconnectGestureTimers)
+
+    ENTRY_ACTION(state_moveScene, action_moveScene_connectMouseEventHandlers)
+    EXIT_ACTION(state_moveScene, action_moveScene_disconnectMouseEventHandlers)
+
+    ENTRY_ACTION(state_sceneMenu, action_sceneMenu_showMenu)
+    
+    ENTRY_ACTION(state_addPage, action_disableUserInteraction)
+    ENTRY_ACTION(state_addPage, action_addPage_addPage)
+    EXIT_ACTION(state_addPage, action_enableUserInteraction)
+    
+    ENTRY_ACTION(state_removePage, action_disableUserInteraction)
+    ENTRY_ACTION(state_removePage, action_removePage_removePage)
+    EXIT_ACTION(state_removePage, action_enableUserInteraction)
+
+    ENTRY_ACTION(state_toggleConnection, action_disableUserInteraction)
+    ENTRY_ACTION(state_toggleConnection, action_toggleConnection_toggleConnection)
+    EXIT_ACTION(state_toggleConnection, action_enableUserInteraction)
+}
+
+/*!
+    Computes the page layer x position based on the given \a pageIndex.
+*/
+qreal HsIdleState::pageLayerXPos(int pageIndex) const
+{
+    return -pageIndex * HsScene::mainWindow()->layoutRect().width() - 0.5;
+}
+
+/*!
+    Starts the page change animation based on the given \a targetPageIndex
+    and \a duration.
+*/
+void HsIdleState::startPageChangeAnimation(int targetPageIndex, int duration)
+{
+    QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup;
+
+    QPropertyAnimation *animation = new QPropertyAnimation(mUiWidget->pageLayer(), "x");
+    animation->setEndValue(pageLayerXPos(targetPageIndex));
+    animation->setDuration(duration);
+    animationGroup->addAnimation(animation);
+
+    animation = new QPropertyAnimation(mUiWidget->sceneLayer(), "x");
+    animation->setEndValue(parallaxFactor() * pageLayerXPos(targetPageIndex));
+    animation->setDuration(duration);
+    animationGroup->addAnimation(animation);
+        
+    animationGroup->start(QAbstractAnimation::DeleteWhenStopped);
+
+    mUiWidget->showPageIndicator();
+    mUiWidget->setActivePage(targetPageIndex);
+}
+
+/*!
+    Checks if the active widget is located inside the left or right 
+    page change zone.
+*/
+bool HsIdleState::isInPageChangeZone()
+{
+    qreal widgetXPos = HsScene::instance()->activeWidget()->geometry().center().x();
+    qreal pageWidth = HsScene::mainWindow()->layoutRect().width();
+    return widgetXPos < mPageChangeZoneWidth ||
+           pageWidth - mPageChangeZoneWidth < widgetXPos;
+}
+
+/*!
+    Checks if the active widget is located inside the left
+    page change zone.
+*/
+bool HsIdleState::isInLeftPageChangeZone()
+{
+    qreal widgetXPos = HsScene::instance()->activeWidget()->geometry().center().x();
+    return widgetXPos < mPageChangeZoneWidth;
+}
+
+/*!
+    Checks if the active widget is located inside the right
+    page change zone.
+*/
+bool HsIdleState::isInRightPageChangeZone()
+{
+    qreal widgetXPos = HsScene::instance()->activeWidget()->geometry().center().x();
+    qreal pageWidth = HsScene::mainWindow()->layoutRect().width();
+    return pageWidth - mPageChangeZoneWidth < widgetXPos;
+}
+
+/*!
+    Inserts new page at index position \a pageIndex in the scene.
+*/
+void HsIdleState::addPageToScene(int pageIndex)
+{
+    HsPageData data;
+    data.setIndex(pageIndex);
+    HsPage *page = HsPage::createInstance(data);
+    page->load();
+    HsScene::instance()->addPage(page);    
+    mUiWidget->insertPage(pageIndex, page);
+}
+
+/*!
+    Computes the parallax factor based on the current scene and
+    page layer widths, and page count.
+*/
+qreal HsIdleState::parallaxFactor() const
+{
+    qreal clw = mUiWidget->controlLayer()->size().width();
+    qreal slw = mUiWidget->sceneLayer()->size().width();
+    int n = HsScene::instance()->pages().count();
+    if (n < 2) {
+        return 1;
+    } else {
+        return (slw - clw) / ((n - 1) * clw);
+    }
+}
+
+/*!
+    Disables the main window user interaction.
+*/
+void HsIdleState::action_disableUserInteraction()
+{
+    HsScene::mainWindow()->setInteractive(false);
+}
+
+/*!
+    Enables the main window user interaction.
+*/
+void HsIdleState::action_enableUserInteraction()
+{
+    HsScene::mainWindow()->setInteractive(true);
+}
+
+/*!
+    If called for the first time, setups the idle view.
+    Updates the soft key action and sets the idle view 
+    as the current view to the main window.
+*/
+void HsIdleState::action_idle_setupView()
+{
+    if (!mView) {
+        mUiWidget = new HsIdleWidget;
+        mView = HsScene::mainWindow()->addView(mUiWidget);
+        mView->setContentFullScreen();
+        mView->setTitle("Home Screen"/*hbTrId(TXT_HOMESCREEN_TITLE_OFFLINE)*/);
+        
+        mSoftKeyAction = new HbAction(this);
+        mSoftKeyAction->setIcon(HbIcon(APP_LIB_BUTTON));
+        connect(mSoftKeyAction, SIGNAL(triggered()), SIGNAL(event_applicationLibrary()));
+        
+#ifndef Q_OS_SYMBIAN
+        connect(HsAppTranslator::instance(), 
+            SIGNAL(languageChanged()), SLOT(translateUi()));
+#endif
+        // TODO: Workaround to Qt/Hb layouting bugs.
+        QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+    }
+
+    HsScene::mainWindow()->addSoftKeyAction(Hb::SecondarySoftKey, mSoftKeyAction);
+    HsScene::mainWindow()->setCurrentView(mView);
+}
+
+/*!
+    Lays out the active page's new widgets that were added
+    from the application library.
+*/
+void HsIdleState::action_idle_layoutNewWidgets()
+{
+    HsPage *page = HsScene::instance()->activePage();    
+    if (!page) {
+        return;
+    }
+
+    QList<HsWidgetHost *> widgets = page->newWidgets();     
+    if (widgets.isEmpty()) {
+        return;
+    }
+
+    foreach (HsWidgetHost *widget, widgets) {
+        widget->initializeWidget();
+        widget->showWidget();
+    }
+
+    page->layoutNewWidgets();
+    page->resetNewWidgets();
+}
+
+/*!
+    Moves the scene and page layers so that the active
+    page is shown.
+*/
+void HsIdleState::action_idle_showActivePage()
+{
+    qreal x = pageLayerXPos(HsScene::instance()->activePageIndex());
+    mUiWidget->pageLayer()->setX(x);
+    mUiWidget->sceneLayer()->setX(parallaxFactor() * x);
+}
+
+/*!
+    Connects the orientation change event handler.
+*/
+void HsIdleState::action_idle_connectOrientationChangeEventHandler()
+{
+    connect(HsScene::mainWindow(), 
+        SIGNAL(orientationChanged(Qt::Orientation)),
+        SLOT(onOrientationChanged(Qt::Orientation)));
+}
+
+/*!
+    Cleans up the idle view.
+*/
+void HsIdleState::action_idle_cleanupView()
+{
+    HsScene::mainWindow()->removeSoftKeyAction(
+        Hb::SecondarySoftKey, mSoftKeyAction);
+}
+
+/*!
+    Disconnects the orientation change event handler.
+*/
+void HsIdleState::action_idle_disconnectOrientationChangeEventHandler()
+{
+    disconnect(HsScene::mainWindow(), 
+        SIGNAL(orientationChanged(Qt::Orientation)),
+        this, SLOT(onOrientationChanged(Qt::Orientation)));
+}
+
+/*!
+    Updates the options menu content.
+*/
+void HsIdleState::action_waitInput_updateOptionsMenu()
+{
+    HbMenu *menu = new HbMenu();
+    
+    menu->addAction(hbTrId(TXT_HOMESCREEN_OPT_ADD_PAGE), 
+        this, SIGNAL(event_addPage()));
+    menu->addAction(hbTrId(TXT_HOMESCREEN_OPT_REMOVE_PAGE), 
+        this, SIGNAL(event_removePage()))->setEnabled(
+        HsScene::instance()->activePage()->isRemovable());
+        
+    if (HsScene::instance()->isOnline()) {
+        menu->addAction(hbTrId(TXT_HOMESCREEN_OPT_HOME_SCREEN_TO_OFFLINE),
+            this, SIGNAL(event_toggleConnection()));
+    } else {
+        menu->addAction(hbTrId(TXT_HOMESCREEN_OPT_HOME_SCREEN_TO_ONLINE),
+            this, SIGNAL(event_toggleConnection())); 
+    }
+
+#ifndef Q_OS_SYMBIAN
+    menu->addAction(hbTrId("txt_homescreen_opt_switch_language"),
+        this, SLOT(switchLanguage()));
+#endif
+
+    mView->setMenu(menu);
+}
+
+/*!
+    Connects the waitInput state's mouse event handlers.
+*/
+void HsIdleState::action_waitInput_connectMouseEventHandlers()
+{
+    CONNECT_MOUSE_EVENT_HANDLER(mousePressed, waitInput_onMousePressed)
+}
+ 
+/*!
+    Disconnects the waitInput state's mouse event handlers.
+*/
+void HsIdleState::action_waitInput_disconnectMouseEventHandlers()
+{
+    DISCONNECT_MOUSE_EVENT_HANDLER(mousePressed, waitInput_onMousePressed)    
+}
+
+/*!
+    Connects the widgetInteraction state's mouse event handlers.
+*/
+void HsIdleState::action_widgetInteraction_connectMouseEventHandlers()
+{
+    CONNECT_MOUSE_EVENT_HANDLER(mouseMoved, widgetInteraction_onMouseMoved)
+    CONNECT_MOUSE_EVENT_HANDLER(mouseReleased, widgetInteraction_onMouseReleased)
+}
+
+/*!
+    Connects the widgetInteraction state's gesture timers.
+*/
+void HsIdleState::action_widgetInteraction_connectGestureTimers()
+{
+    mTimer.setInterval(500);
+    connect(&mTimer, SIGNAL(timeout()), 
+        SLOT(widgetInteraction_onTapAndHoldTimeout()));
+    mTimer.start();
+}
+ 
+/*!
+    Disconnects the widgetInteraction state's mouse event handlers.
+*/
+void HsIdleState::action_widgetInteraction_disconnectMouseEventHandlers()
+{
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseMoved, widgetInteraction_onMouseMoved)
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseReleased, widgetInteraction_onMouseReleased)
+}
+
+/*!
+    Disconnects the widgetInteraction state's gesture timers.
+*/
+void HsIdleState::action_widgetInteraction_disconnectGestureTimers()
+{
+    disconnect(&mTimer, SIGNAL(timeout()), 
+        this, SLOT(widgetInteraction_onTapAndHoldTimeout()));
+}
+
+/*!
+    Connects the sceneInteraction state's mouse event handlers.
+*/
+void HsIdleState::action_sceneInteraction_connectMouseEventHandlers()
+{
+    CONNECT_MOUSE_EVENT_HANDLER(mouseMoved, sceneInteraction_onMouseMoved)
+    CONNECT_MOUSE_EVENT_HANDLER(mouseReleased, sceneInteraction_onMouseReleased)
+}
+
+/*!
+    Connects the sceneInteraction state's gesture timers.
+*/
+void HsIdleState::action_sceneInteraction_connectGestureTimers()
+{
+    mTimer.setInterval(500);
+    connect(&mTimer, SIGNAL(timeout()), 
+        SLOT(sceneInteraction_onTapAndHoldTimeout()));
+    mTimer.start();
+}
+ 
+/*!
+    Disconnects the sceneInteraction state's mouse event handlers.
+*/
+void HsIdleState::action_sceneInteraction_disconnectMouseEventHandlers()
+{
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseMoved, sceneInteraction_onMouseMoved)
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseReleased, sceneInteraction_onMouseReleased)
+}
+
+/*!
+    Disconnects the sceneInteraction state's gesture timers.
+*/
+void HsIdleState::action_sceneInteraction_disconnectGestureTimers()
+{
+    disconnect(&mTimer, SIGNAL(timeout()), 
+        this, SLOT(sceneInteraction_onTapAndHoldTimeout()));
+}
+
+/*!
+    Reparents the active widget to the control layer.
+*/
+void HsIdleState::action_moveWidget_reparentToControlLayer()
+{
+    HsWidgetHost *widget = HsScene::instance()->activeWidget();
+    Q_ASSERT(widget);
+    widget->setParentItem(mUiWidget->controlLayer());
+
+    mUiWidget->showTrashBin();
+}
+
+/*!
+    Starts the widget drag animation for the active widget.
+*/
+void HsIdleState::action_moveWidget_startWidgetDragAnimation()
+{
+    HsWidgetHost *widget = HsScene::instance()->activeWidget();
+    Q_ASSERT(widget);
+    widget->startDragAnimation();
+}
+
+/*!
+    Connects the moveWidget state's mouse event handlers.
+*/
+void HsIdleState::action_moveWidget_connectMouseEventHandlers()
+{
+    CONNECT_MOUSE_EVENT_HANDLER(mouseMoved, moveWidget_onMouseMoved)
+    CONNECT_MOUSE_EVENT_HANDLER(mouseReleased, moveWidget_onMouseReleased)
+}
+
+/*!
+    Connects the moveWidget state's gesture timers.
+*/
+void HsIdleState::action_moveWidget_connectGestureTimers()
+{
+    mTimer.setInterval(800);
+    connect(&mTimer, SIGNAL(timeout()), 
+        SLOT(moveWidget_onHoldTimeout()));
+}
+
+/*!
+    Reparents the active widget to the active page.
+*/
+void HsIdleState::action_moveWidget_reparentToPage()
+{
+    HsWidgetHost *widget = HsScene::instance()->activeWidget();
+    if (widget) {
+        widget->setParentItem(HsScene::instance()->activePage());
+    }
+    
+    mUiWidget->showPageIndicator();
+}
+
+/*!
+    Starts the widget drop animation for the active widget.
+*/
+void HsIdleState::action_moveWidget_startWidgetDropAnimation()
+{
+    HsWidgetHost *widget = HsScene::instance()->activeWidget();
+    if (widget) {
+        widget->startDropAnimation();
+    }
+}
+
+/*!
+    Disconnects the moveWidget state's mouse event handlers.
+*/
+void HsIdleState::action_moveWidget_disconnectMouseEventHandlers()
+{
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseMoved, moveWidget_onMouseMoved)
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseReleased, moveWidget_onMouseReleased)
+}
+
+/*!
+    Disconnects the moveWidget state's gesture timers.
+*/
+void HsIdleState::action_moveWidget_disconnectGestureTimers()
+{
+    disconnect(&mTimer, SIGNAL(timeout()), 
+        this, SLOT(moveWidget_onHoldTimeout()));
+}
+
+/*!
+    Connects the moveScene state's mouse event handlers.
+*/
+void HsIdleState::action_moveScene_connectMouseEventHandlers()
+{
+    CONNECT_MOUSE_EVENT_HANDLER(mouseMoved, moveScene_onMouseMoved)
+    CONNECT_MOUSE_EVENT_HANDLER(mouseReleased, moveScene_onMouseReleased)
+}
+ 
+/*!
+    Disconnects the moveScene state's mouse event handlers.
+*/
+void HsIdleState::action_moveScene_disconnectMouseEventHandlers()
+{
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseMoved, moveScene_onMouseMoved)
+    DISCONNECT_MOUSE_EVENT_HANDLER(mouseReleased, moveScene_onMouseReleased)
+}
+
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC SKIP
+#endif //COVERAGE_MEASUREMENT
+/*!
+    Shows the scene menu.
+*/
+void HsIdleState::action_sceneMenu_showMenu()
+{
+    HbMenu menu;
+
+    HbAction *changeWallpaperAction = 
+        menu.addAction(hbTrId(TXT_HOMESCREEN_LIST_CHANGE_WALLPAPER));
+    HbAction *addContentAction = 
+        menu.addAction(hbTrId(TXT_HOMESCREEN_LIST_ADD_CONTENT));
+
+    HbAction *action = menu.exec(mSceneMenuPos);
+    if (action == changeWallpaperAction) {
+        emit event_selectSceneWallpaper();
+    } else if (action == addContentAction) {
+        machine()->postEvent(
+            HsMenuEventFactory::createOpenAppLibraryEvent(AddHsMenuMode));
+    } else {
+        emit event_waitInput();
+    }
+}
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC ENDSKIP
+#endif //COVERAGE_MEASUREMENT
+
+/*!
+    Adds a new page to the scene.
+*/
+void HsIdleState::action_addPage_addPage()
+{
+    HsScene *scene = HsScene::instance();    
+    int pageIndex = scene->pages().count();    
+    addPageToScene(pageIndex);    
+    scene->setActivePageIndex(pageIndex);
+    startPageChangeAnimation(pageIndex, 700);
+    mUiWidget->pageIndicator()->addItem(true, true);
+}
+
+/*!
+    Removes an existing page from the scene.
+*/
+void HsIdleState::action_removePage_removePage()
+{
+    HsScene *scene = HsScene::instance();
+    HsPage *page = scene->activePage();    
+    int pageIndex = scene->activePageIndex();
+
+    mUiWidget->removePage(pageIndex);
+    scene->removePage(page);
+    page->deleteFromDatabase();
+    delete page;
+
+    pageIndex = pageIndex == 0 ? 0 : pageIndex - 1;
+    scene->setActivePageIndex(pageIndex);
+
+    startPageChangeAnimation(pageIndex, 200);
+
+    mUiWidget->pageIndicator()->removeItem();
+    mUiWidget->setActivePage(pageIndex);
+}
+
+/*!
+    Toggles the homescreen online/offline state.
+*/
+void HsIdleState::action_toggleConnection_toggleConnection()
+{
+    HsScene *scene = HsScene::instance();    
+    scene->setOnline(!scene->isOnline());
+}
+
+/*!
+    Handles mouse press events for the waitInput state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::waitInput_onMousePressed(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    filtered = true;
+
+    HsScene *scene = HsScene::instance();
+    HsPage *page = scene->activePage();
+    QList<HsWidgetHost *> widgets = page->widgets();
+
+    if (mUiWidget->controlLayer() == watched ||
+        mUiWidget->controlLayer()->isAncestorOf(watched)) {
+        filtered = false;
+        return;
+    }
+
+    mUiWidget->captureDelayedPress(event);
+
+    foreach (HsWidgetHost *widget, widgets) {
+        if (widget == watched || widget->isAncestorOf(watched)) {
+            scene->setActiveWidget(widget);
+            emit event_widgetInteraction();
+            return;
+        }
+    }
+
+    mSceneMenuPos = event->scenePos();
+    emit event_sceneInteraction();
+}
+
+/*!
+    Handles mouse move events for the widgetInteraction state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::widgetInteraction_onMouseMoved(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(filtered)
+
+    if (!mTimer.isActive()) {
+        return;
+    }
+
+    QPointF point = 
+        event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton);
+    if (mTapAndHoldDistance < point.manhattanLength()) {
+        mTimer.stop();
+        mUiWidget->sendDelayedPress();
+    }
+}
+
+/*!
+    Handles mouse release events for the widgetInteraction state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::widgetInteraction_onMouseReleased(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(event)
+    Q_UNUSED(filtered)
+
+    if (mTimer.isActive()) {
+        mTimer.stop();
+        mUiWidget->sendDelayedPress();
+    }
+
+    HsScene::instance()->activePage()->updateZValues();
+
+    emit event_waitInput();
+}
+
+/*!
+    Handles mouse move events for the sceneInteraction state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::sceneInteraction_onMouseMoved(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(filtered)
+
+    mSceneMenuPos = event->scenePos();
+
+    if (!mTimer.isActive()) {
+        return;
+    }
+
+    QPointF point = 
+        event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton);
+    if (mTapAndHoldDistance < point.manhattanLength()) {
+        mTimer.stop();
+        mUiWidget->clearDelayedPress();
+        emit event_moveScene();
+    }
+}
+
+/*!
+    Handles mouse release events for the sceneInteraction state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::sceneInteraction_onMouseReleased(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(event)
+    Q_UNUSED(filtered)
+
+    if (mTimer.isActive()) {
+        mTimer.stop();
+        mUiWidget->sendDelayedPress();
+    }
+
+    emit event_waitInput();
+}
+
+/*!
+    Handles mouse move events for the moveWidget state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::moveWidget_onMouseMoved(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(filtered)
+
+    HsWidgetHost *widget = HsScene::instance()->activeWidget();
+    Q_ASSERT(widget);
+
+    QPointF delta(event->screenPos() - event->lastScreenPos());
+    QRectF region =  mView->rect().adjusted(10, 55, -10, -10);
+    QPointF position = widget->geometry().center() + delta;
+    if (!region.contains(position)) {
+        position.setX(qBound(region.left(), position.x(), region.right()));
+        position.setY(qBound(region.top(), position.y(), region.bottom()));
+    }
+
+    widget->setPos(position - widget->rect().center());
+
+    if (mTimer.isActive()) {
+        if (mTapAndHoldDistance < delta.manhattanLength()) {
+            mTimer.stop();
+        }
+    } else {
+        if (isInPageChangeZone()) {
+            mTimer.start();
+        }
+    }
+
+    if (mUiWidget->trashBin()->isUnderMouse()) {
+        mUiWidget->trashBin()->activate();
+    } else {
+        mUiWidget->trashBin()->deactivate();
+    }
+
+    if (!mUiWidget->pageIndicator()->isAnimatingCurrentItemChange()) {
+        mUiWidget->showTrashBin();
+    }
+}
+
+/*!
+    Handles mouse release events for the moveWidget state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::moveWidget_onMouseReleased(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(event)
+
+    mTimer.stop();
+
+    HsScene *scene = HsScene::instance();
+    HsPage *page = scene->activePage();
+    HsWidgetHost *widget = scene->activeWidget();
+
+    if (mUiWidget->trashBin()->isUnderMouse()) {
+        widget->page()->removeWidget(widget);
+        widget->uninitializeWidget();
+        widget->deleteFromDatabase();
+        widget->deleteLater();
+        scene->setActiveWidget(0);
+    } else {
+        if (widget->page() != page) {
+            widget->page()->removeWidget(widget);
+            page->addExistingWidget(widget);
+            if (HsScene::orientation() == Qt::Horizontal) {
+                widget->deleteWidgetPresentation(Qt::Vertical);
+            } else {
+                widget->deleteWidgetPresentation(Qt::Horizontal);
+            }
+        }
+        widget->setWidgetPresentation();
+        page->updateZValues();
+    }
+
+    filtered = true;
+    emit event_waitInput();
+}
+
+/*!
+    Handles mouse move events for the moveScene state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::moveScene_onMouseMoved(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(filtered)
+    
+    HsScene *scene = HsScene::instance();
+    qreal delta = 
+        event->screenPos().x() - event->buttonDownScreenPos(Qt::LeftButton).x();
+    
+    qreal x = qBound(pageLayerXPos(scene->pages().count() - 1),
+                     pageLayerXPos(scene->activePageIndex()) + delta,
+                     pageLayerXPos(0));
+    
+    mUiWidget->pageLayer()->setX(x);
+    mUiWidget->sceneLayer()->setX(parallaxFactor() * x);
+}
+
+/*!
+    Handles mouse release events for the moveScene state.
+    Filters events for the item \a watched. \a event is the 
+    filtered event. Sets the \a filtered true if the event
+    was filtered by this handler.
+*/
+void HsIdleState::moveScene_onMouseReleased(
+    QGraphicsItem *watched, QGraphicsSceneMouseEvent *event, bool &filtered)
+{
+    Q_UNUSED(watched)
+    Q_UNUSED(filtered)
+    
+    QList<HsPage *> pages = HsScene::instance()->pages();
+    QSizeF pageSize = pages.first()->size();
+
+    int pageIndex = HsScene::instance()->activePageIndex();
+
+    QPointF delta(
+        event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton));
+    if (delta.x() < -pageSize.width() / 2) {
+        pageIndex = qMin(pageIndex + 1, pages.count() - 1);
+    } else if(pageSize.width() / 2 < delta.x()) {
+        pageIndex = qMax(pageIndex - 1, 0);
+    }
+
+    HsScene::instance()->setActivePageIndex(pageIndex);
+    
+    startPageChangeAnimation(pageIndex, 200);
+
+    emit event_waitInput();
+}
+
+/*!
+    Handles orientation change events. \a orientation is the 
+    new orientation.
+*/
+void HsIdleState::onOrientationChanged(Qt::Orientation orientation)
+{
+    QList<HsPage *> pages = HsScene::instance()->pages();
+    QList<HsWidgetHost *> widgets;
+    HsWidgetHost *widget = 0;
+    
+    for (int i = 0; i < pages.count(); ++i) {        
+        widgets = pages[i]->widgets();
+        for (int j = 0; j < widgets.count(); ++j) {
+            widget = widgets[j];
+            HsWidgetPresentationData presentation = widget->widgetPresentation(orientation);
+            if (presentation.id() < 0) {
+                QList<QRectF> geometries = 
+                    HsWidgetPositioningOnOrientationChange::instance()->convert(
+                        pages[i]->rect().adjusted(10, 10, -10, -10), QList<QRectF>() << widget->geometry(),
+                        QRectF(0, 0, pages[i]->rect().height() + 40, 
+                        pages[i]->rect().width() - 40).adjusted(10, 10, -10, -10));
+                widget->setGeometry(geometries.first());
+                widget->setWidgetPresentation();
+            } else {
+                widget->setGeometry(QRectF(presentation.position(), presentation.size()));
+                widget->setZValue(presentation.zValue());
+            }
+        }
+    }
+    
+    action_idle_showActivePage();
+}
+
+/*!
+    Handles tap-and-hold events for the widgetInteraction state.
+*/
+void HsIdleState::widgetInteraction_onTapAndHoldTimeout()
+{
+    mUiWidget->clearDelayedPress();
+    emit event_moveWidget();
+}
+
+/*!
+    Handles tap-and-hold events for the sceneInteraction state.
+*/
+void HsIdleState::sceneInteraction_onTapAndHoldTimeout()
+{
+    mUiWidget->clearDelayedPress();
+    emit event_sceneMenu();
+}
+
+/*!
+    Handles page change zone hold events for the moveWidget state.
+*/
+void HsIdleState::moveWidget_onHoldTimeout()
+{
+    HsScene *scene = HsScene::instance();
+    
+    int pageIndex = scene->activePageIndex();
+
+    if (isInLeftPageChangeZone() && 
+        0 < pageIndex) {
+        --pageIndex;
+    } else if (isInRightPageChangeZone() && 
+        pageIndex < scene->pages().count()) {
+        ++pageIndex;
+    } else {
+        return;
+    }
+
+    if (pageIndex == scene->pages().count()) {
+        if (scene->pages().last()->widgets().isEmpty()) {
+            return;
+        } else {
+            addPageToScene(pageIndex);
+            mUiWidget->showPageIndicator();
+            mUiWidget->pageIndicator()->addItem(true);
+        }
+    }
+
+    scene->setActivePageIndex(pageIndex);
+    startPageChangeAnimation(pageIndex, 200);
+}
+
+#ifndef Q_OS_SYMBIAN
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC SKIP
+#endif //COVERAGE_MEASUREMENT
+/*!
+    Switch the home screen language.
+*/
+void HsIdleState::switchLanguage()
+{
+    QString locale;
+    QFile file("hslocale.txt");
+    QTextStream stream(&file);
+    if (file.open(QIODevice::ReadWrite | QIODevice::Text)) {
+        QString word;
+        stream >> word;
+        if (!word.isEmpty()) {
+            locale = word;
+        } else {
+            locale = "en_US";
+        }
+    } else {
+        locale = QLocale::system().name();
+    }
+
+    if (locale == "en_US") {
+        locale = "fi_FI";
+    } else {
+        locale = "en_US";
+    }
+
+    file.seek(0);
+    stream << locale;
+    file.close();
+    
+    QEvent event(QEvent::LocaleChange);
+    QApplication::sendEvent(qApp, &event);
+}
+
+/*!
+    Translates the home screen ui.
+*/
+void HsIdleState::translateUi()
+{
+    mView->setTitle("Home Screen"/*hbTrId(TXT_HOMESCREEN_TITLE_OFFLINE)*/);
+    action_waitInput_updateOptionsMenu();
+}
+#ifdef COVERAGE_MEASUREMENT
+#pragma CTC ENDSKIP
+#endif //COVERAGE_MEASUREMENT
+#endif // Q_OS_SYMBIAN
+
+// Undefine the helper macros.
+#undef ENTRY_ACTION
+#undef EXIT_ACTION
+#undef CONNECT_MOUSE_EVENT_HANDLER
+#undef DISCONNECT_MOUSE_EVENT_HANDLER