--- /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