diff -r 2b1b11a301d2 -r 4b195f3bea29 homescreenapp/hsapplication/src/hsstatemachine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/homescreenapp/hsapplication/src/hsstatemachine.cpp Wed Aug 18 09:40:07 2010 +0300 @@ -0,0 +1,426 @@ +/* +* 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: Default implementation of the home state machine. +* +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "hsmenueventfactory.h" +#include "homescreendomainpskeys.h" +#include "hsstatemachine.h" +#include "hsdatabase.h" +#include "hscontentservice.h" +#include "hsshortcutservice.h" +#include "hsmenueventtransition.h" +#include "hswidgetpositioningonorientationchange.h" +#include "hswidgetpositioningonwidgetadd.h" +#include "hsconfiguration.h" +#include "hstest_global.h" +#include "hswidgetpositioningonwidgetmove.h" + +QTM_USE_NAMESPACE +#define hbApp qobject_cast(qApp) + +namespace +{ + const char KHsRootStateInterface[] = "com.nokia.homescreen.state.HsRootState"; + const char KHsLoadSceneStateInterface[] = "com.nokia.homescreen.state.HsLoadSceneState"; + const char KHsIdleStateInterface[] = "com.nokia.homescreen.state.HsIdleState"; + const char KHsAppLibraryStateInterface[] = "com.nokia.homescreen.state.HsAppLibraryState"; + const char KHsMenuWorkerStateInterface[] = "com.nokia.homescreen.state.HsMenuWorkerState"; + const char KHsBacupRestoreStateInterface[] = "com.nokia.homescreen.state.HsBackupRestoreState"; +} + + +/*! + \class HsStateMachine + \ingroup group_hsstatemachine + \brief Default implementation of the home screen state machine. + Creates an execution context (EC) and populates it with + runtime services. States are loaded from state plugins. + Each state is given an access to the EC. States + are added to a state machine. Finally, the state machine + is started. +*/ + +/*! + Constructs state machine with \a parent as the parent object. +*/ +HsStateMachine::HsStateMachine(QObject *parent) + : QStateMachine(parent), + mContentService(0), + mHomeScreenActive(false), + mIdleStateActive(false), + mEndKeyCaptured(false), + mPublisher(NULL) +#ifdef Q_OS_SYMBIAN + ,keyCapture() +#endif +{ + HSTEST_FUNC_ENTRY("HS::HsStateMachine::HsStateMachine"); + + HsDatabase *db = new HsDatabase(QCoreApplication::instance()); + db->setConnectionName("homescreen.dbc"); +#ifdef Q_OS_SYMBIAN + db->setDatabaseName("c:/private/20022f35/homescreen.db"); +#else + db->setDatabaseName("private/20022f35/homescreen.db"); +#endif + db->open(); + HsDatabase::setInstance(db); + + HsConfiguration::setInstance(new HsConfiguration(QCoreApplication::instance())); + HsConfiguration::instance()->load(); + + HsWidgetPositioningOnOrientationChange::setInstance( + new HsAdvancedWidgetPositioningOnOrientationChange); +#ifdef HSWIDGETORGANIZER_ALGORITHM + HsWidgetPositioningOnWidgetAdd::setInstance( + new HsWidgetOrganizer); +#else + HsWidgetPositioningOnWidgetAdd::setInstance( + new HsAnchorPointInBottomRight); +#endif + + HsWidgetPositioningOnWidgetMove::setInstance( + new HsSnapToLines); + + registerAnimations(); + + createStatePublisher(); + createContentServiceParts(); + createStates(); + + // create the instance so that singleton is accessible from elsewhere + HsShortcutService::instance(this); + + QCoreApplication::instance()->installEventFilter(this); + + if (hbApp) { // Qt test framework uses QApplication. + connect(hbApp->activityManager(), SIGNAL(activityRequested(QString)), + this, SLOT(activityRequested(QString))); + } + HSTEST_FUNC_EXIT("HS::HsStateMachine::HsStateMachine"); +} + +/*! + Destructor. +*/ +HsStateMachine::~HsStateMachine() +{ + HsWidgetPositioningOnOrientationChange::setInstance(0); + HsWidgetPositioningOnWidgetAdd::setInstance(0); + HsWidgetPositioningOnWidgetMove::setInstance(0); + delete mPublisher; +} + +/*! + \fn void HsStateMachine::stopStateMachine() + Emission of this signal initiates a transition to the final state. +*/ + +/*! + \copydoc QObject::eventFilter(QObject *watched, QEvent *event) +*/ +bool HsStateMachine::eventFilter(QObject *watched, QEvent *event) +{ + Q_UNUSED(watched); + + switch (event->type()) { + case QEvent::ApplicationActivate: + qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationActivate"; + mHomeScreenActive = true; + updatePSKeys(); + break; + case QEvent::ApplicationDeactivate: + qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationDeactivate"; + mHomeScreenActive = false; + updatePSKeys(); + break; + default: + break; + } + + bool result = QStateMachine::eventFilter(watched, event); + if (event->type() == QEvent::KeyPress ) { + QKeyEvent* ke = static_cast(event); + result = (ke->key() == Qt::Key_Home); + } + return result; +} + + +/*! + Registers framework animations. +*/ +void HsStateMachine::registerAnimations() +{ + HbIconAnimationManager *manager = HbIconAnimationManager::global(); + manager->addDefinitionFile(QLatin1String("qtg_anim_loading.axml")); +} + +/*! + Creates Home screen state publisher. +*/ +void HsStateMachine::createStatePublisher() +{ + mPublisher = new QValueSpacePublisher(QValueSpace::PermanentLayer, HsStatePSKeyPath); + + if (!mPublisher->isConnected()){ + // No permanent layer available + mPublisher = new QValueSpacePublisher(HsStatePSKeyPath); + } + + mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive); +} + +/*! + Creates content service parts. +*/ +void HsStateMachine::createContentServiceParts() +{ + HSTEST_FUNC_ENTRY("HS::HsStateMachine::createContentServiceParts"); + + mContentService = new HsContentService(this); + + HSTEST_FUNC_EXIT("HS::HsStateMachine::createContentServiceParts"); +} + +/*! + Creates states. +*/ +void HsStateMachine::createStates() +{ + HSTEST_FUNC_ENTRY("HS::HsStateMachine::createStates"); + + QFinalState *finalState = new QFinalState(); + addState(finalState); + + QState *guiRootState = new QState(); + addState(guiRootState); + + guiRootState->addTransition(this, SIGNAL(event_exit()), finalState); + + QServiceManager manager; + + + QObject *loadSceneStateObj = manager.loadInterface(KHsLoadSceneStateInterface); + QState *loadSceneState = qobject_cast(loadSceneStateObj); + loadSceneState->setParent(guiRootState); + loadSceneState->setObjectName(KHsLoadSceneStateInterface); + + QObject *rootStateObj = manager.loadInterface(KHsRootStateInterface); + QState *rootState = qobject_cast(rootStateObj); + rootState->setParent(guiRootState); + rootState->setObjectName(KHsRootStateInterface); + + QObject *idleStateObj = manager.loadInterface(KHsIdleStateInterface); + QState *idleState = qobject_cast(idleStateObj); + idleState->setParent(rootState); + idleState->setObjectName(KHsIdleStateInterface); + connect(idleState, SIGNAL(entered()), SLOT(onIdleStateEntered())); + connect(idleState, SIGNAL(exited()), SLOT(onIdleStateExited())); + + + //menu state + QState *menuParallelState = new QState( + QState::ParallelStates, rootState); + QState *menuRootState = new QState(menuParallelState); + + QObject *appLibraryStateObj = manager.loadInterface(KHsAppLibraryStateInterface); + QState *appLibraryState = qobject_cast(appLibraryStateObj); + appLibraryState->setParent(menuRootState); + appLibraryState->setObjectName(KHsAppLibraryStateInterface); + menuRootState->setInitialState(appLibraryState); + + QHistoryState *historyState = new QHistoryState(rootState); + historyState->setDefaultState(idleState); + + loadSceneState->addTransition( + loadSceneState, SIGNAL(event_history()), historyState); + + QObject *menuWorkerStateObj = manager.loadInterface(KHsMenuWorkerStateInterface); + QState *menuWorkerState = qobject_cast(menuWorkerStateObj); + menuWorkerState->setParent(menuParallelState); + menuWorkerState->setObjectName(KHsMenuWorkerStateInterface); + + connect(appLibraryState, SIGNAL(collectionEntered()), + menuWorkerState, SIGNAL(reset())); + + //Backup/Restore state + QObject *backupRestoreStateObj = manager.loadInterface(KHsBacupRestoreStateInterface); + QState *backupRestoreState = qobject_cast(backupRestoreStateObj); + backupRestoreState->setParent(guiRootState); + backupRestoreState->setObjectName(KHsBacupRestoreStateInterface); + backupRestoreState->addTransition( + backupRestoreState, SIGNAL(event_loadScene()), loadSceneState); + + // root state transitions + idleState->addTransition(idleState, SIGNAL(event_applicationLibrary()), menuRootState); + appLibraryState->addTransition( + appLibraryState, SIGNAL(toHomescreenState()), idleState); + rootState->addTransition(rootState, SIGNAL(event_backupRestore()), backupRestoreState); + // opening shortcut to Application Library + HsMenuEventTransition *idleToAppLibTransition = + new HsMenuEventTransition(HsMenuEvent::OpenApplicationLibrary, + idleState, appLibraryState); + idleState->addTransition(idleToAppLibTransition); + + HsMenuEventTransition *appLibToIdleTransition = + new HsMenuEventTransition( + HsMenuEvent::OpenHomeScreen, appLibraryState, idleState); + appLibraryState->addTransition(appLibToIdleTransition); + + HbMainWindow *window = hbInstance->allMainWindows().first(); + +#ifndef Q_OS_SYMBIAN + // key driven transition from idle to menu + QKeyEventTransition *idleToMenuRootTransition = + new QKeyEventTransition( + window, QEvent::KeyPress, Qt::Key_Home); + idleToMenuRootTransition->setTargetState(menuRootState); + idleState->addTransition(idleToMenuRootTransition); + // key driven transition from menu to idle + QKeyEventTransition *menuToIdleTransition = + new QKeyEventTransition( + window, QEvent::KeyPress, Qt::Key_Home); + menuToIdleTransition->setTargetState(idleState); + menuRootState->addTransition(menuToIdleTransition); +#endif + // key driven transition from menu to idle + QKeyEventTransition *menuToIdleTransitionNoKey = + new QKeyEventTransition( + window, QEvent::KeyPress, Qt::Key_No); + menuToIdleTransitionNoKey->setTargetState(idleState); + menuRootState->addTransition(menuToIdleTransitionNoKey); + + // add transition to switch to idle + menuRootState->addTransition( this, SIGNAL(event_toIdle()), idleState); + // add transition to switch to applib + idleState->addTransition( this, SIGNAL(event_toAppLib()), menuRootState); + + // transitions to child states + // opening shortcut to a colleciton + QList collectionStates = + appLibraryState-> + findChildren + ("homescreen.nokia.com/state/applibrarystate/collectionstate"); + qDebug( + "Found %d \"collectionstate\" children for Application Library State", + collectionStates.count()); + if (collectionStates.count()) { + HsMenuEventTransition *idleToCollectionTransition = + new HsMenuEventTransition(HsMenuEvent::OpenCollection, + idleState, collectionStates[0]); + idleState->addTransition(idleToCollectionTransition); + } + + guiRootState->setInitialState(loadSceneState); + setInitialState(guiRootState); + + HSTEST_FUNC_EXIT("HS::HsStateMachine::createStates"); +} + + +/*! + Publishes Home screen states via Publish & Subscribe. +*/ +void HsStateMachine::updatePSKeys() +{ + if (!mPublisher){ + createStatePublisher(); + } + + if (mHomeScreenActive && mIdleStateActive){ + qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenIdleState"; + mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenIdleState); + } + else{ + qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenInactive"; + mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive); + } + + if (mHomeScreenActive && !mIdleStateActive) { + captureEndKey(true); + } else { + captureEndKey(false); + } +} + +/*! + capture End key +*/ +void HsStateMachine::captureEndKey(bool enable) +{ +#ifdef Q_OS_SYMBIAN + if (enable && !mEndKeyCaptured) { + mEndKeyCaptured = true; + keyCapture.captureKey(Qt::Key_No); + } else if (mEndKeyCaptured) { + mEndKeyCaptured = false; + keyCapture.cancelCaptureKey(Qt::Key_No); + } +#endif +} + +/*! + Called when state machine is in Idle state. +*/ +void HsStateMachine::onIdleStateEntered() +{ + mIdleStateActive = true; + updatePSKeys(); +} + +/*! + Called when state machine leaves the Idle state. +*/ +void HsStateMachine::onIdleStateExited() +{ + mIdleStateActive = false; + updatePSKeys(); +} + +/*! + Activity requested by another client +*/ +void HsStateMachine::activityRequested(const QString &name) +{ + if (name == groupAppLibRecentView()) { + this->postEvent( + HsMenuEventFactory::createOpenCollectionEvent(0, + collectionDownloadedTypeName())); + } else if (name == activityHsIdleView()) { + emit event_toIdle(); + } else if (name == activityAppLibMainView()) { + emit event_toAppLib(); + } +}