homescreenapp/hsapplication/src/hsstatemachine.cpp
changeset 77 4b195f3bea29
child 85 35368b604b28
equal deleted inserted replaced
61:2b1b11a301d2 77:4b195f3bea29
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Default implementation of the home state machine.
       
    15 *
       
    16 */
       
    17 
       
    18 #include <QState>
       
    19 #include <QFinalState>
       
    20 #include <QHistoryState>
       
    21 #include <QSignalTransition>
       
    22 #include <QKeyEventTransition>
       
    23 #include <QKeyEvent>
       
    24 
       
    25 #include <qvaluespacepublisher.h>
       
    26 #include <qservicemanager.h>
       
    27 #include <qservicefilter.h>
       
    28 #include <qserviceinterfacedescriptor.h>
       
    29 
       
    30 #include <HbApplication>
       
    31 #include <HbActivityManager>
       
    32 #include <HbInstance>
       
    33 #include <HbIconAnimationManager>
       
    34 #include <HbIconAnimationDefinition>
       
    35 
       
    36 #include "hsmenueventfactory.h"
       
    37 #include "homescreendomainpskeys.h"
       
    38 #include "hsstatemachine.h"
       
    39 #include "hsdatabase.h"
       
    40 #include "hscontentservice.h"
       
    41 #include "hsshortcutservice.h"
       
    42 #include "hsmenueventtransition.h"
       
    43 #include "hswidgetpositioningonorientationchange.h"
       
    44 #include "hswidgetpositioningonwidgetadd.h"
       
    45 #include "hsconfiguration.h"
       
    46 #include "hstest_global.h"
       
    47 #include "hswidgetpositioningonwidgetmove.h"
       
    48 
       
    49 QTM_USE_NAMESPACE
       
    50 #define hbApp qobject_cast<HbApplication*>(qApp)
       
    51 
       
    52 namespace
       
    53 {
       
    54     const char KHsRootStateInterface[] = "com.nokia.homescreen.state.HsRootState";
       
    55     const char KHsLoadSceneStateInterface[] = "com.nokia.homescreen.state.HsLoadSceneState";
       
    56     const char KHsIdleStateInterface[] = "com.nokia.homescreen.state.HsIdleState";
       
    57     const char KHsAppLibraryStateInterface[] = "com.nokia.homescreen.state.HsAppLibraryState";
       
    58     const char KHsMenuWorkerStateInterface[] = "com.nokia.homescreen.state.HsMenuWorkerState";
       
    59     const char KHsBacupRestoreStateInterface[] = "com.nokia.homescreen.state.HsBackupRestoreState";
       
    60 }
       
    61 
       
    62 
       
    63 /*!
       
    64     \class HsStateMachine
       
    65     \ingroup group_hsstatemachine
       
    66     \brief Default implementation of the home screen state machine.
       
    67     Creates an execution context (EC) and populates it with
       
    68     runtime services. States are loaded from state plugins.
       
    69     Each state is given an access to the EC. States
       
    70     are added to a state machine. Finally, the state machine
       
    71     is started.
       
    72 */
       
    73 
       
    74 /*!
       
    75     Constructs state machine with \a parent as the parent object.
       
    76 */
       
    77 HsStateMachine::HsStateMachine(QObject *parent)
       
    78     : QStateMachine(parent),
       
    79       mContentService(0),	  
       
    80       mHomeScreenActive(false),
       
    81       mIdleStateActive(false),
       
    82       mEndKeyCaptured(false),
       
    83       mPublisher(NULL)
       
    84 #ifdef Q_OS_SYMBIAN
       
    85 	  ,keyCapture()
       
    86 #endif
       
    87 {
       
    88     HSTEST_FUNC_ENTRY("HS::HsStateMachine::HsStateMachine");
       
    89 
       
    90     HsDatabase *db = new HsDatabase(QCoreApplication::instance());
       
    91     db->setConnectionName("homescreen.dbc");
       
    92 #ifdef Q_OS_SYMBIAN
       
    93     db->setDatabaseName("c:/private/20022f35/homescreen.db");
       
    94 #else
       
    95     db->setDatabaseName("private/20022f35/homescreen.db");
       
    96 #endif    
       
    97     db->open();
       
    98     HsDatabase::setInstance(db);
       
    99 
       
   100     HsConfiguration::setInstance(new HsConfiguration(QCoreApplication::instance()));
       
   101     HsConfiguration::instance()->load();
       
   102             
       
   103     HsWidgetPositioningOnOrientationChange::setInstance(
       
   104         new HsAdvancedWidgetPositioningOnOrientationChange);
       
   105 #ifdef HSWIDGETORGANIZER_ALGORITHM
       
   106     HsWidgetPositioningOnWidgetAdd::setInstance(
       
   107         new HsWidgetOrganizer);
       
   108 #else
       
   109     HsWidgetPositioningOnWidgetAdd::setInstance(
       
   110         new HsAnchorPointInBottomRight);
       
   111 #endif
       
   112 
       
   113     HsWidgetPositioningOnWidgetMove::setInstance(
       
   114         new HsSnapToLines);
       
   115 
       
   116     registerAnimations();
       
   117 
       
   118     createStatePublisher();
       
   119     createContentServiceParts();
       
   120     createStates();    
       
   121 
       
   122     // create the instance so that singleton is accessible from elsewhere
       
   123     HsShortcutService::instance(this);
       
   124 
       
   125     QCoreApplication::instance()->installEventFilter(this);
       
   126 
       
   127     if (hbApp) { // Qt test framework uses QApplication.
       
   128         connect(hbApp->activityManager(), SIGNAL(activityRequested(QString)), 
       
   129                 this, SLOT(activityRequested(QString)));
       
   130     }
       
   131     HSTEST_FUNC_EXIT("HS::HsStateMachine::HsStateMachine");
       
   132 }
       
   133 
       
   134 /*!
       
   135     Destructor.
       
   136 */
       
   137 HsStateMachine::~HsStateMachine()
       
   138 {
       
   139     HsWidgetPositioningOnOrientationChange::setInstance(0);
       
   140     HsWidgetPositioningOnWidgetAdd::setInstance(0);
       
   141     HsWidgetPositioningOnWidgetMove::setInstance(0);
       
   142     delete mPublisher;
       
   143 }
       
   144 
       
   145 /*!
       
   146     \fn void HsStateMachine::stopStateMachine()
       
   147     Emission of this signal initiates a transition to the final state.
       
   148 */
       
   149 
       
   150 /*!
       
   151     \copydoc QObject::eventFilter(QObject *watched, QEvent *event)
       
   152 */
       
   153 bool HsStateMachine::eventFilter(QObject *watched, QEvent *event)
       
   154 {
       
   155     Q_UNUSED(watched);
       
   156 
       
   157     switch (event->type()) {
       
   158         case QEvent::ApplicationActivate:
       
   159             qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationActivate";
       
   160             mHomeScreenActive = true;
       
   161             updatePSKeys();
       
   162             break;
       
   163         case QEvent::ApplicationDeactivate:
       
   164             qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationDeactivate";
       
   165             mHomeScreenActive = false;
       
   166             updatePSKeys();
       
   167             break;
       
   168         default:
       
   169             break;
       
   170     }
       
   171         
       
   172     bool result =  QStateMachine::eventFilter(watched, event);    
       
   173     if (event->type() == QEvent::KeyPress ) {
       
   174         QKeyEvent* ke = static_cast<QKeyEvent *>(event);                 
       
   175         result = (ke->key() == Qt::Key_Home);
       
   176     }
       
   177     return result;
       
   178 }
       
   179 
       
   180 
       
   181 /*!
       
   182     Registers framework animations.
       
   183 */
       
   184 void HsStateMachine::registerAnimations()
       
   185 {
       
   186     HbIconAnimationManager *manager = HbIconAnimationManager::global();
       
   187     manager->addDefinitionFile(QLatin1String("qtg_anim_loading.axml"));
       
   188 }
       
   189 
       
   190 /*!
       
   191     Creates Home screen state publisher.
       
   192 */
       
   193 void HsStateMachine::createStatePublisher()
       
   194 {
       
   195     mPublisher = new QValueSpacePublisher(QValueSpace::PermanentLayer, HsStatePSKeyPath);
       
   196 
       
   197     if (!mPublisher->isConnected()){
       
   198     	// No permanent layer available
       
   199     	mPublisher = new QValueSpacePublisher(HsStatePSKeyPath);
       
   200     }
       
   201 
       
   202     mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive);
       
   203 }
       
   204 
       
   205 /*!
       
   206     Creates content service parts.
       
   207 */
       
   208 void HsStateMachine::createContentServiceParts()
       
   209 {
       
   210     HSTEST_FUNC_ENTRY("HS::HsStateMachine::createContentServiceParts");
       
   211 
       
   212     mContentService = new HsContentService(this);
       
   213 
       
   214     HSTEST_FUNC_EXIT("HS::HsStateMachine::createContentServiceParts");
       
   215 }
       
   216 
       
   217 /*!
       
   218     Creates states.
       
   219 */
       
   220 void HsStateMachine::createStates()
       
   221 {
       
   222     HSTEST_FUNC_ENTRY("HS::HsStateMachine::createStates");
       
   223 
       
   224     QFinalState *finalState = new QFinalState();
       
   225     addState(finalState);
       
   226 
       
   227     QState *guiRootState = new QState();
       
   228     addState(guiRootState);
       
   229 
       
   230     guiRootState->addTransition(this, SIGNAL(event_exit()), finalState);
       
   231 
       
   232     QServiceManager manager;
       
   233 
       
   234     
       
   235     QObject *loadSceneStateObj = manager.loadInterface(KHsLoadSceneStateInterface);
       
   236     QState *loadSceneState = qobject_cast<QState *>(loadSceneStateObj);
       
   237     loadSceneState->setParent(guiRootState);
       
   238     loadSceneState->setObjectName(KHsLoadSceneStateInterface);
       
   239 
       
   240     QObject *rootStateObj = manager.loadInterface(KHsRootStateInterface);
       
   241     QState *rootState = qobject_cast<QState *>(rootStateObj);   
       
   242     rootState->setParent(guiRootState);
       
   243     rootState->setObjectName(KHsRootStateInterface);       
       
   244 
       
   245     QObject *idleStateObj = manager.loadInterface(KHsIdleStateInterface);
       
   246     QState *idleState = qobject_cast<QState *>(idleStateObj);
       
   247     idleState->setParent(rootState);
       
   248     idleState->setObjectName(KHsIdleStateInterface);
       
   249 	connect(idleState, SIGNAL(entered()), SLOT(onIdleStateEntered()));
       
   250 	connect(idleState, SIGNAL(exited()), SLOT(onIdleStateExited()));
       
   251 
       
   252 
       
   253     //menu state
       
   254     QState *menuParallelState = new QState(
       
   255             QState::ParallelStates, rootState);
       
   256     QState *menuRootState = new QState(menuParallelState);
       
   257 
       
   258     QObject *appLibraryStateObj = manager.loadInterface(KHsAppLibraryStateInterface);
       
   259     QState *appLibraryState = qobject_cast<QState *>(appLibraryStateObj);
       
   260     appLibraryState->setParent(menuRootState);
       
   261     appLibraryState->setObjectName(KHsAppLibraryStateInterface);
       
   262     menuRootState->setInitialState(appLibraryState);
       
   263 
       
   264     QHistoryState *historyState = new QHistoryState(rootState);
       
   265     historyState->setDefaultState(idleState);
       
   266     
       
   267     loadSceneState->addTransition(
       
   268             loadSceneState, SIGNAL(event_history()), historyState);            
       
   269 
       
   270     QObject *menuWorkerStateObj = manager.loadInterface(KHsMenuWorkerStateInterface);
       
   271     QState *menuWorkerState = qobject_cast<QState *>(menuWorkerStateObj);
       
   272     menuWorkerState->setParent(menuParallelState);
       
   273     menuWorkerState->setObjectName(KHsMenuWorkerStateInterface);
       
   274 
       
   275     connect(appLibraryState, SIGNAL(collectionEntered()), 
       
   276             menuWorkerState, SIGNAL(reset()));
       
   277 
       
   278     //Backup/Restore state
       
   279     QObject *backupRestoreStateObj = manager.loadInterface(KHsBacupRestoreStateInterface);
       
   280     QState *backupRestoreState = qobject_cast<QState *>(backupRestoreStateObj);   
       
   281     backupRestoreState->setParent(guiRootState);
       
   282     backupRestoreState->setObjectName(KHsBacupRestoreStateInterface);
       
   283     backupRestoreState->addTransition(
       
   284             backupRestoreState, SIGNAL(event_loadScene()), loadSceneState);
       
   285 
       
   286     // root state transitions
       
   287     idleState->addTransition(idleState, SIGNAL(event_applicationLibrary()), menuRootState);
       
   288     appLibraryState->addTransition(
       
   289             appLibraryState, SIGNAL(toHomescreenState()), idleState);
       
   290     rootState->addTransition(rootState, SIGNAL(event_backupRestore()), backupRestoreState);
       
   291     // opening shortcut to Application Library
       
   292     HsMenuEventTransition *idleToAppLibTransition =
       
   293         new HsMenuEventTransition(HsMenuEvent::OpenApplicationLibrary,
       
   294                                   idleState, appLibraryState);
       
   295     idleState->addTransition(idleToAppLibTransition);
       
   296 
       
   297     HsMenuEventTransition *appLibToIdleTransition =
       
   298         new HsMenuEventTransition(
       
   299             HsMenuEvent::OpenHomeScreen, appLibraryState, idleState);
       
   300     appLibraryState->addTransition(appLibToIdleTransition);
       
   301 
       
   302     HbMainWindow *window = hbInstance->allMainWindows().first();
       
   303 
       
   304 #ifndef  Q_OS_SYMBIAN   
       
   305     // key driven transition from idle to menu
       
   306     QKeyEventTransition *idleToMenuRootTransition =
       
   307         new QKeyEventTransition(
       
   308                 window, QEvent::KeyPress, Qt::Key_Home);
       
   309     idleToMenuRootTransition->setTargetState(menuRootState);
       
   310     idleState->addTransition(idleToMenuRootTransition);
       
   311     // key driven transition from menu to idle
       
   312     QKeyEventTransition *menuToIdleTransition =
       
   313         new QKeyEventTransition(
       
   314                 window, QEvent::KeyPress, Qt::Key_Home);
       
   315     menuToIdleTransition->setTargetState(idleState);
       
   316     menuRootState->addTransition(menuToIdleTransition);
       
   317 #endif 
       
   318     // key driven transition from menu to idle
       
   319     QKeyEventTransition *menuToIdleTransitionNoKey =
       
   320         new QKeyEventTransition(
       
   321                 window, QEvent::KeyPress, Qt::Key_No);
       
   322     menuToIdleTransitionNoKey->setTargetState(idleState);
       
   323     menuRootState->addTransition(menuToIdleTransitionNoKey);
       
   324     
       
   325     // add transition to switch to idle
       
   326     menuRootState->addTransition( this, SIGNAL(event_toIdle()), idleState);    
       
   327     // add transition to switch to applib 
       
   328     idleState->addTransition( this, SIGNAL(event_toAppLib()), menuRootState);
       
   329     
       
   330     // transitions to child states
       
   331     // opening shortcut to a colleciton
       
   332     QList<QState *> collectionStates =
       
   333         appLibraryState->
       
   334             findChildren<QState *>
       
   335                 ("homescreen.nokia.com/state/applibrarystate/collectionstate");
       
   336     qDebug(
       
   337         "Found %d \"collectionstate\" children for Application Library State",
       
   338             collectionStates.count());
       
   339     if (collectionStates.count()) {
       
   340         HsMenuEventTransition *idleToCollectionTransition =
       
   341             new HsMenuEventTransition(HsMenuEvent::OpenCollection,
       
   342                                       idleState, collectionStates[0]);
       
   343         idleState->addTransition(idleToCollectionTransition);
       
   344     }
       
   345 
       
   346     guiRootState->setInitialState(loadSceneState);
       
   347     setInitialState(guiRootState);
       
   348     
       
   349     HSTEST_FUNC_EXIT("HS::HsStateMachine::createStates");
       
   350 }
       
   351 
       
   352 
       
   353 /*!
       
   354     Publishes Home screen states via Publish & Subscribe.
       
   355 */
       
   356 void HsStateMachine::updatePSKeys()
       
   357 {	
       
   358 	if (!mPublisher){
       
   359 		createStatePublisher();
       
   360 	}
       
   361 
       
   362 	if (mHomeScreenActive && mIdleStateActive){
       
   363     	qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenIdleState";
       
   364     	mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenIdleState);
       
   365     }
       
   366     else{
       
   367     	qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenInactive";
       
   368     	mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive);
       
   369     }	
       
   370     
       
   371     if (mHomeScreenActive && !mIdleStateActive) {
       
   372         captureEndKey(true);
       
   373     } else {
       
   374         captureEndKey(false);
       
   375     }
       
   376 }
       
   377 
       
   378 /*!
       
   379     capture End key 
       
   380 */
       
   381 void HsStateMachine::captureEndKey(bool enable) 
       
   382 {
       
   383 #ifdef Q_OS_SYMBIAN
       
   384     if (enable && !mEndKeyCaptured) {
       
   385         mEndKeyCaptured = true;
       
   386         keyCapture.captureKey(Qt::Key_No);        
       
   387     } else if (mEndKeyCaptured) {
       
   388         mEndKeyCaptured = false;
       
   389         keyCapture.cancelCaptureKey(Qt::Key_No);
       
   390     }
       
   391 #endif
       
   392 }
       
   393 
       
   394 /*!
       
   395     Called when state machine is in Idle state.
       
   396 */
       
   397 void HsStateMachine::onIdleStateEntered()
       
   398 {
       
   399 	mIdleStateActive = true;
       
   400 	updatePSKeys();
       
   401 }
       
   402 
       
   403 /*!
       
   404     Called when state machine leaves the Idle state.
       
   405 */
       
   406 void HsStateMachine::onIdleStateExited()
       
   407 {
       
   408 	mIdleStateActive = false;
       
   409 	updatePSKeys();
       
   410 }
       
   411 
       
   412 /*!
       
   413     Activity requested by another client 
       
   414 */
       
   415 void HsStateMachine::activityRequested(const QString &name) 
       
   416 {
       
   417     if (name == groupAppLibRecentView()) {
       
   418         this->postEvent(
       
   419             HsMenuEventFactory::createOpenCollectionEvent(0,
       
   420             collectionDownloadedTypeName()));
       
   421     } else if (name == activityHsIdleView()) {
       
   422         emit event_toIdle();
       
   423     } else if (name == activityAppLibMainView()) {
       
   424         emit event_toAppLib();
       
   425     }
       
   426 }