homescreenapp/hsapplication/src/hsstatemachine.cpp
changeset 63 52b0f64eeb51
child 69 87476091b3f5
equal deleted inserted replaced
62:341166945d65 63:52b0f64eeb51
       
     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 #ifdef Q_OS_SYMBIAN
       
    53 const static Qt::Key applicationKey = Qt::Key_Menu;
       
    54 #else
       
    55 const static Qt::Key applicationKey = Qt::Key_Home;
       
    56 #endif
       
    57 
       
    58 namespace
       
    59 {
       
    60     const char KHsRootStateInterface[] = "com.nokia.homescreen.state.HsRootState";
       
    61     const char KHsLoadSceneStateInterface[] = "com.nokia.homescreen.state.HsLoadSceneState";
       
    62     const char KHsIdleStateInterface[] = "com.nokia.homescreen.state.HsIdleState";
       
    63     const char KHsAppLibraryStateInterface[] = "com.nokia.homescreen.state.HsAppLibraryState";
       
    64     const char KHsMenuWorkerStateInterface[] = "com.nokia.homescreen.state.HsMenuWorkerState";
       
    65     const char KHsBacupRestoreStateInterface[] = "com.nokia.homescreen.state.HsBackupRestoreState";
       
    66 }
       
    67 
       
    68 
       
    69 /*!
       
    70     \class HsStateMachine
       
    71     \ingroup group_hsstatemachine
       
    72     \brief Default implementation of the home screen state machine.
       
    73     Creates an execution context (EC) and populates it with
       
    74     runtime services. States are loaded from state plugins.
       
    75     Each state is given an access to the EC. States
       
    76     are added to a state machine. Finally, the state machine
       
    77     is started.
       
    78 */
       
    79 
       
    80 /*!
       
    81     Constructs state machine with \a parent as the parent object.
       
    82 */
       
    83 HsStateMachine::HsStateMachine(QObject *parent)
       
    84     : QStateMachine(parent),
       
    85       mContentService(0),	  
       
    86       mHomeScreenActive(false),
       
    87       mIdleStateActive(false),
       
    88       mPublisher(NULL)
       
    89 #ifdef Q_OS_SYMBIAN
       
    90 	  ,keyCapture()
       
    91 #endif
       
    92 {
       
    93     HSTEST_FUNC_ENTRY("HS::HsStateMachine::HsStateMachine");
       
    94 
       
    95     HsDatabase *db = new HsDatabase;
       
    96     db->setConnectionName("homescreen.dbc");
       
    97 #ifdef Q_OS_SYMBIAN
       
    98     db->setDatabaseName("c:/private/20022f35/homescreen.db");
       
    99 #else
       
   100     db->setDatabaseName("private/20022f35/homescreen.db");
       
   101 #endif    
       
   102     db->open();
       
   103     HsDatabase::setInstance(db);
       
   104 
       
   105     HsConfiguration::setInstance(new HsConfiguration);
       
   106     HsConfiguration::instance()->load();
       
   107             
       
   108     HsWidgetPositioningOnOrientationChange::setInstance(
       
   109         new HsAdvancedWidgetPositioningOnOrientationChange);
       
   110 
       
   111     HsWidgetPositioningOnWidgetAdd::setInstance(
       
   112         new HsAnchorPointInBottomRight);
       
   113 
       
   114     HsWidgetPositioningOnWidgetMove::setInstance(
       
   115         new HsSnapToLines);
       
   116 
       
   117     registerAnimations();
       
   118 
       
   119     createStatePublisher();
       
   120     createContentServiceParts();
       
   121     createStates();    
       
   122 
       
   123     // create the instance so that singleton is accessible from elsewhere
       
   124     HsShortcutService::instance(this);
       
   125 
       
   126     QCoreApplication::instance()->installEventFilter(this);
       
   127 
       
   128     if (hbApp) { // Qt test framework uses QApplication.
       
   129         connect(hbApp->activityManager(), SIGNAL(activityRequested(QString)), 
       
   130                 this, SLOT(activityRequested(QString)));
       
   131     }
       
   132     HSTEST_FUNC_EXIT("HS::HsStateMachine::HsStateMachine");
       
   133 }
       
   134 
       
   135 /*!
       
   136     Destructor.
       
   137 */
       
   138 HsStateMachine::~HsStateMachine()
       
   139 {
       
   140     HsWidgetPositioningOnOrientationChange::setInstance(0);
       
   141     delete mPublisher;
       
   142 }
       
   143 
       
   144 /*!
       
   145     \fn void HsStateMachine::stopStateMachine()
       
   146     Emission of this signal initiates a transition to the final state.
       
   147 */
       
   148 
       
   149 /*!
       
   150     \copydoc QObject::eventFilter(QObject *watched, QEvent *event)
       
   151 */
       
   152 bool HsStateMachine::eventFilter(QObject *watched, QEvent *event)
       
   153 {
       
   154     Q_UNUSED(watched);
       
   155 
       
   156     switch (event->type()) {
       
   157         case QEvent::ApplicationActivate:
       
   158             qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationActivate";
       
   159 #ifdef Q_OS_SYMBIAN
       
   160             keyCapture.captureKey(applicationKey);
       
   161 #endif
       
   162             mHomeScreenActive = true;
       
   163             updatePSKeys();
       
   164             break;
       
   165         case QEvent::ApplicationDeactivate:
       
   166             qDebug() << "HsStateMachine::eventFilter: QEvent::ApplicationDeactivate";
       
   167 #ifdef Q_OS_SYMBIAN
       
   168             keyCapture.cancelCaptureKey(applicationKey);
       
   169 #endif
       
   170             mHomeScreenActive = false;
       
   171             updatePSKeys();
       
   172             break;
       
   173         default:
       
   174             break;
       
   175     }
       
   176    
       
   177     bool result =  QStateMachine::eventFilter(watched, event);
       
   178     // temporary hack as we should not register twice for events
       
   179     if (event->type() == QEvent::KeyPress ) {
       
   180         QKeyEvent* ke = static_cast<QKeyEvent *>(event);         
       
   181         // Key_Launch0 should be removed when QT starts to send Key_Menu
       
   182         result = (ke->key() == applicationKey) || ke->key() == Qt::Key_Launch0;        
       
   183     }
       
   184     return result;
       
   185 }
       
   186 
       
   187 
       
   188 /*!
       
   189     Registers framework animations.
       
   190 */
       
   191 void HsStateMachine::registerAnimations()
       
   192 {
       
   193     HbIconAnimationManager *manager = HbIconAnimationManager::global();
       
   194     manager->addDefinitionFile(QLatin1String("qtg_anim_loading.axml"));
       
   195 }
       
   196 
       
   197 /*!
       
   198     Creates Home screen state publisher.
       
   199 */
       
   200 void HsStateMachine::createStatePublisher()
       
   201 {
       
   202     mPublisher = new QValueSpacePublisher(QValueSpace::PermanentLayer, HsStatePSKeyPath);
       
   203 
       
   204     if (!mPublisher->isConnected()){
       
   205     	// No permanent layer available
       
   206     	mPublisher = new QValueSpacePublisher(HsStatePSKeyPath);
       
   207     }
       
   208 
       
   209     mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive);
       
   210 }
       
   211 
       
   212 /*!
       
   213     Creates content service parts.
       
   214 */
       
   215 void HsStateMachine::createContentServiceParts()
       
   216 {
       
   217     HSTEST_FUNC_ENTRY("HS::HsStateMachine::createContentServiceParts");
       
   218 
       
   219     mContentService = new HsContentService(this);
       
   220 
       
   221     HSTEST_FUNC_EXIT("HS::HsStateMachine::createContentServiceParts");
       
   222 }
       
   223 
       
   224 /*!
       
   225     Creates states.
       
   226 */
       
   227 void HsStateMachine::createStates()
       
   228 {
       
   229     HSTEST_FUNC_ENTRY("HS::HsStateMachine::createStates");
       
   230 
       
   231     QFinalState *finalState = new QFinalState();
       
   232     addState(finalState);
       
   233 
       
   234     QState *guiRootState = new QState();
       
   235     addState(guiRootState);
       
   236 
       
   237     guiRootState->addTransition(this, SIGNAL(event_exit()), finalState);
       
   238 
       
   239     QServiceManager manager;
       
   240 
       
   241     
       
   242     QObject *loadSceneStateObj = manager.loadInterface(KHsLoadSceneStateInterface);
       
   243     QState *loadSceneState = qobject_cast<QState *>(loadSceneStateObj);
       
   244     loadSceneState->setParent(guiRootState);
       
   245     loadSceneState->setObjectName(KHsLoadSceneStateInterface);
       
   246 
       
   247     QObject *rootStateObj = manager.loadInterface(KHsRootStateInterface);
       
   248     QState *rootState = qobject_cast<QState *>(rootStateObj);   
       
   249     rootState->setParent(guiRootState);
       
   250     rootState->setObjectName(KHsRootStateInterface);       
       
   251 
       
   252     QObject *idleStateObj = manager.loadInterface(KHsIdleStateInterface);
       
   253     QState *idleState = qobject_cast<QState *>(idleStateObj);
       
   254     idleState->setParent(rootState);
       
   255     idleState->setObjectName(KHsIdleStateInterface);
       
   256 	connect(idleState, SIGNAL(entered()), SLOT(onIdleStateEntered()));
       
   257 	connect(idleState, SIGNAL(exited()), SLOT(onIdleStateExited()));
       
   258 
       
   259 
       
   260     //menu state
       
   261     QState *menuParallelState = new QState(
       
   262             QState::ParallelStates, rootState);
       
   263     QState *menuRootState = new QState(menuParallelState);
       
   264 
       
   265     QObject *appLibraryStateObj = manager.loadInterface(KHsAppLibraryStateInterface);
       
   266     QState *appLibraryState = qobject_cast<QState *>(appLibraryStateObj);
       
   267     appLibraryState->setParent(menuRootState);
       
   268     appLibraryState->setObjectName(KHsAppLibraryStateInterface);
       
   269     menuRootState->setInitialState(appLibraryState);
       
   270 
       
   271     QHistoryState *historyState = new QHistoryState(rootState);
       
   272     historyState->setDefaultState(idleState);
       
   273     
       
   274     loadSceneState->addTransition(
       
   275             loadSceneState, SIGNAL(event_history()), historyState);            
       
   276 
       
   277     QObject *menuWorkerStateObj = manager.loadInterface(KHsMenuWorkerStateInterface);
       
   278     QState *menuWorkerState = qobject_cast<QState *>(menuWorkerStateObj);
       
   279     menuWorkerState->setParent(menuParallelState);
       
   280     menuWorkerState->setObjectName(KHsMenuWorkerStateInterface);
       
   281 
       
   282     connect(appLibraryState, SIGNAL(collectionEntered()), 
       
   283             menuWorkerState, SIGNAL(reset()));
       
   284 
       
   285     //Backup/Restore state
       
   286     QObject *backupRestoreStateObj = manager.loadInterface(KHsBacupRestoreStateInterface);
       
   287     QState *backupRestoreState = qobject_cast<QState *>(backupRestoreStateObj);   
       
   288     backupRestoreState->setParent(guiRootState);
       
   289     backupRestoreState->setObjectName(KHsBacupRestoreStateInterface);
       
   290     backupRestoreState->addTransition(
       
   291             backupRestoreState, SIGNAL(event_loadScene()), loadSceneState);
       
   292 
       
   293     // root state transitions
       
   294     idleState->addTransition(idleState, SIGNAL(event_applicationLibrary()), menuRootState);
       
   295     appLibraryState->addTransition(
       
   296             appLibraryState, SIGNAL(toHomescreenState()), idleState);
       
   297     rootState->addTransition(rootState, SIGNAL(event_backupRestore()), backupRestoreState);
       
   298     // opening shortcut to Application Library
       
   299     HsMenuEventTransition *idleToAppLibTransition =
       
   300         new HsMenuEventTransition(HsMenuEvent::OpenApplicationLibrary,
       
   301                                   idleState, appLibraryState);
       
   302     idleState->addTransition(idleToAppLibTransition);
       
   303 
       
   304     HsMenuEventTransition *appLibToIdleTransition =
       
   305         new HsMenuEventTransition(
       
   306             HsMenuEvent::OpenHomeScreen, appLibraryState, idleState);
       
   307     appLibraryState->addTransition(appLibToIdleTransition);
       
   308 
       
   309     HbMainWindow *window = hbInstance->allMainWindows().first();
       
   310 
       
   311     // key driven transition from idle to menu
       
   312     QKeyEventTransition *idleToMenuRootTransition =
       
   313         new QKeyEventTransition(
       
   314                 window, QEvent::KeyPress, applicationKey);
       
   315     idleToMenuRootTransition->setTargetState(menuRootState);
       
   316     idleState->addTransition(idleToMenuRootTransition);
       
   317     // key driven transition from menu to idle
       
   318     QKeyEventTransition *menuToIdleTransition =
       
   319         new QKeyEventTransition(
       
   320                 window, QEvent::KeyPress, applicationKey);
       
   321     menuToIdleTransition->setTargetState(idleState);
       
   322     menuRootState->addTransition(menuToIdleTransition);
       
   323     
       
   324     // transition for Key_Launch0 should be removed 
       
   325     // when OT starts to send Key_Menu (maybe wk14)
       
   326     QKeyEventTransition *idleToMenuRootTransition2 =
       
   327         new QKeyEventTransition(
       
   328                 window, QEvent::KeyPress, Qt::Key_Launch0);
       
   329     idleToMenuRootTransition2->setTargetState(menuRootState);
       
   330     idleState->addTransition(idleToMenuRootTransition2);
       
   331     // key driven transition from menu to idle
       
   332     QKeyEventTransition *menuToIdleTransition2 =
       
   333         new QKeyEventTransition(
       
   334                 window, QEvent::KeyPress, Qt::Key_Launch0);
       
   335     menuToIdleTransition2->setTargetState(idleState);
       
   336     menuRootState->addTransition(menuToIdleTransition2);
       
   337     // add transition to switch to idle
       
   338     menuRootState->addTransition( this, SIGNAL(event_toIdle()), idleState);    
       
   339     
       
   340     // transitions to child states
       
   341     // opening shortcut to a colleciton
       
   342     QList<QState *> collectionStates =
       
   343         appLibraryState->
       
   344             findChildren<QState *>
       
   345                 ("homescreen.nokia.com/state/applibrarystate/collectionstate");
       
   346     qDebug(
       
   347         "Found %d \"collectionstate\" children for Application Library State",
       
   348             collectionStates.count());
       
   349     if (collectionStates.count()) {
       
   350         HsMenuEventTransition *idleToCollectionTransition =
       
   351             new HsMenuEventTransition(HsMenuEvent::OpenCollection,
       
   352                                       idleState, collectionStates[0]);
       
   353         idleState->addTransition(idleToCollectionTransition);
       
   354     }
       
   355 
       
   356     guiRootState->setInitialState(loadSceneState);
       
   357     setInitialState(guiRootState);
       
   358     
       
   359     HSTEST_FUNC_EXIT("HS::HsStateMachine::createStates");
       
   360 }
       
   361 
       
   362 
       
   363 /*!
       
   364     Publishes Home screen states via Publish & Subscribe.
       
   365 */
       
   366 void HsStateMachine::updatePSKeys()
       
   367 {	
       
   368 	if (!mPublisher){
       
   369 		createStatePublisher();
       
   370 	}
       
   371 
       
   372 	if (mHomeScreenActive && mIdleStateActive){
       
   373     	qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenIdleState";
       
   374     	mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenIdleState);
       
   375     }
       
   376     else{
       
   377     	qDebug() << "HsStateMachine::updatePSKeys: EHomeScreenInactive";
       
   378     	mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive);
       
   379     }	
       
   380 }
       
   381 
       
   382 /*!
       
   383     Called when state machine is in Idle state.
       
   384 */
       
   385 void HsStateMachine::onIdleStateEntered()
       
   386 {
       
   387 	mIdleStateActive = true;
       
   388 	updatePSKeys();
       
   389 }
       
   390 
       
   391 /*!
       
   392     Called when state machine leaves the Idle state.
       
   393 */
       
   394 void HsStateMachine::onIdleStateExited()
       
   395 {
       
   396 	mIdleStateActive = false;
       
   397 	updatePSKeys();
       
   398 }
       
   399 
       
   400 /*!
       
   401     Activity requested by another client 
       
   402 */
       
   403 void HsStateMachine::activityRequested(const QString &name) 
       
   404 {
       
   405     if (name == groupAppLibRecentView()) {
       
   406         this->postEvent(
       
   407             HsMenuEventFactory::createOpenCollectionEvent(0,
       
   408             collectionDownloadedTypeName()));
       
   409     } else if (name == activityHsIdleView()) {
       
   410         emit event_toIdle();
       
   411     }
       
   412 }