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 screen runtime. |
|
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 "hsdefaultruntime.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 HsDefaultRuntime |
|
71 \ingroup group_hsdefaultruntimeplugin |
|
72 \brief Default implementation of the home screen runtime. |
|
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 runtime with \a parent as the parent object. |
|
82 */ |
|
83 HsDefaultRuntime::HsDefaultRuntime(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::HsDefaultRuntime::HsDefaultRuntime"); |
|
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 assignServices(); |
|
123 |
|
124 // create the instance so that singleton is accessible from elsewhere |
|
125 HsShortcutService::instance(this); |
|
126 |
|
127 QCoreApplication::instance()->installEventFilter(this); |
|
128 |
|
129 if (hbApp) { // Qt test framework uses QApplication. |
|
130 connect(hbApp->activityManager(), SIGNAL(activityRequested(QString)), |
|
131 this, SLOT(activityRequested(QString))); |
|
132 } |
|
133 HSTEST_FUNC_EXIT("HS::HsDefaultRuntime::HsDefaultRuntime"); |
|
134 } |
|
135 |
|
136 /*! |
|
137 Destructor. |
|
138 */ |
|
139 HsDefaultRuntime::~HsDefaultRuntime() |
|
140 { |
|
141 HsWidgetPositioningOnOrientationChange::setInstance(0); |
|
142 delete mPublisher; |
|
143 } |
|
144 |
|
145 /*! |
|
146 \fn void HsDefaultRuntime::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 HsDefaultRuntime::eventFilter(QObject *watched, QEvent *event) |
|
154 { |
|
155 Q_UNUSED(watched); |
|
156 |
|
157 switch (event->type()) { |
|
158 case QEvent::ApplicationActivate: |
|
159 qDebug() << "HsDefaultRuntime::eventFilter: QEvent::ApplicationActivate"; |
|
160 #ifdef Q_OS_SYMBIAN |
|
161 keyCapture.captureKey(applicationKey); |
|
162 #endif |
|
163 mHomeScreenActive = true; |
|
164 updatePSKeys(); |
|
165 break; |
|
166 case QEvent::ApplicationDeactivate: |
|
167 qDebug() << "HsDefaultRuntime::eventFilter: QEvent::ApplicationDeactivate"; |
|
168 #ifdef Q_OS_SYMBIAN |
|
169 keyCapture.cancelCaptureKey(applicationKey); |
|
170 #endif |
|
171 mHomeScreenActive = false; |
|
172 updatePSKeys(); |
|
173 break; |
|
174 default: |
|
175 break; |
|
176 } |
|
177 |
|
178 bool result = QStateMachine::eventFilter(watched, event); |
|
179 // temporary hack as we should not register twice for events |
|
180 if (event->type() == QEvent::KeyPress ) { |
|
181 QKeyEvent* ke = static_cast<QKeyEvent *>(event); |
|
182 // Key_Launch0 should be removed when QT starts to send Key_Menu |
|
183 result = (ke->key() == applicationKey) || ke->key() == Qt::Key_Launch0; |
|
184 } |
|
185 return result; |
|
186 } |
|
187 |
|
188 |
|
189 /*! |
|
190 Registers framework animations. |
|
191 */ |
|
192 void HsDefaultRuntime::registerAnimations() |
|
193 { |
|
194 HbIconAnimationManager *manager = HbIconAnimationManager::global(); |
|
195 manager->addDefinitionFile(QLatin1String("qtg_anim_loading.axml")); |
|
196 } |
|
197 |
|
198 /*! |
|
199 Creates Home screen state publisher. |
|
200 */ |
|
201 void HsDefaultRuntime::createStatePublisher() |
|
202 { |
|
203 mPublisher = new QValueSpacePublisher(QValueSpace::PermanentLayer, HsStatePSKeyPath); |
|
204 |
|
205 if (!mPublisher->isConnected()){ |
|
206 // No permanent layer available |
|
207 mPublisher = new QValueSpacePublisher(HsStatePSKeyPath); |
|
208 } |
|
209 |
|
210 mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive); |
|
211 } |
|
212 |
|
213 /*! |
|
214 Creates content service parts. |
|
215 */ |
|
216 void HsDefaultRuntime::createContentServiceParts() |
|
217 { |
|
218 HSTEST_FUNC_ENTRY("HS::HsDefaultRuntime::createContentServiceParts"); |
|
219 |
|
220 mContentService = new HsContentService(this); |
|
221 |
|
222 HSTEST_FUNC_EXIT("HS::HsDefaultRuntime::createContentServiceParts"); |
|
223 } |
|
224 |
|
225 /*! |
|
226 Creates states. |
|
227 */ |
|
228 void HsDefaultRuntime::createStates() |
|
229 { |
|
230 HSTEST_FUNC_ENTRY("HS::HsDefaultRuntime::createStates"); |
|
231 |
|
232 QFinalState *finalState = new QFinalState(); |
|
233 addState(finalState); |
|
234 |
|
235 QState *guiRootState = new QState(); |
|
236 addState(guiRootState); |
|
237 |
|
238 guiRootState->addTransition(this, SIGNAL(event_exit()), finalState); |
|
239 |
|
240 QServiceManager manager; |
|
241 |
|
242 |
|
243 QObject *loadSceneStateObj = manager.loadInterface(KHsLoadSceneStateInterface); |
|
244 QState *loadSceneState = qobject_cast<QState *>(loadSceneStateObj); |
|
245 loadSceneState->setParent(guiRootState); |
|
246 loadSceneState->setObjectName(KHsLoadSceneStateInterface); |
|
247 |
|
248 QObject *rootStateObj = manager.loadInterface(KHsRootStateInterface); |
|
249 QState *rootState = qobject_cast<QState *>(rootStateObj); |
|
250 rootState->setParent(guiRootState); |
|
251 rootState->setObjectName(KHsRootStateInterface); |
|
252 |
|
253 QObject *idleStateObj = manager.loadInterface(KHsIdleStateInterface); |
|
254 QState *idleState = qobject_cast<QState *>(idleStateObj); |
|
255 idleState->setParent(rootState); |
|
256 idleState->setObjectName(KHsIdleStateInterface); |
|
257 connect(idleState, SIGNAL(entered()), SLOT(onIdleStateEntered())); |
|
258 connect(idleState, SIGNAL(exited()), SLOT(onIdleStateExited())); |
|
259 |
|
260 |
|
261 //menu state |
|
262 QState *menuParallelState = new QState( |
|
263 QState::ParallelStates, rootState); |
|
264 QState *menuRootState = new QState(menuParallelState); |
|
265 |
|
266 QObject *appLibraryStateObj = manager.loadInterface(KHsAppLibraryStateInterface); |
|
267 QState *appLibraryState = qobject_cast<QState *>(appLibraryStateObj); |
|
268 appLibraryState->setParent(menuRootState); |
|
269 appLibraryState->setObjectName(KHsAppLibraryStateInterface); |
|
270 menuRootState->setInitialState(appLibraryState); |
|
271 |
|
272 QHistoryState *historyState = new QHistoryState(rootState); |
|
273 historyState->setDefaultState(idleState); |
|
274 |
|
275 loadSceneState->addTransition( |
|
276 loadSceneState, SIGNAL(event_history()), historyState); |
|
277 |
|
278 QObject *menuWorkerStateObj = manager.loadInterface(KHsMenuWorkerStateInterface); |
|
279 QState *menuWorkerState = qobject_cast<QState *>(menuWorkerStateObj); |
|
280 menuWorkerState->setParent(menuParallelState); |
|
281 menuWorkerState->setObjectName(KHsMenuWorkerStateInterface); |
|
282 |
|
283 connect(appLibraryState, SIGNAL(collectionEntered()), |
|
284 menuWorkerState, SIGNAL(reset())); |
|
285 connect(appLibraryState, SIGNAL(allAppsStateEntered ()), |
|
286 menuWorkerState, SIGNAL(reset())); |
|
287 connect(appLibraryState, SIGNAL(allCollectionsStateEntered ()), |
|
288 menuWorkerState, SIGNAL(reset())); |
|
289 |
|
290 //Backup/Restore state |
|
291 QObject *backupRestoreStateObj = manager.loadInterface(KHsBacupRestoreStateInterface); |
|
292 QState *backupRestoreState = qobject_cast<QState *>(backupRestoreStateObj); |
|
293 backupRestoreState->setParent(guiRootState); |
|
294 backupRestoreState->setObjectName(KHsBacupRestoreStateInterface); |
|
295 backupRestoreState->addTransition( |
|
296 backupRestoreState, SIGNAL(event_loadScene()), loadSceneState); |
|
297 |
|
298 // root state transitions |
|
299 idleState->addTransition(idleState, SIGNAL(event_applicationLibrary()), menuRootState); |
|
300 appLibraryState->addTransition( |
|
301 appLibraryState, SIGNAL(toHomescreenState()), idleState); |
|
302 rootState->addTransition(rootState, SIGNAL(event_backupRestore()), backupRestoreState); |
|
303 // opening shortcut to Application Library |
|
304 HsMenuEventTransition *idleToAppLibTransition = |
|
305 new HsMenuEventTransition(HsMenuEvent::OpenApplicationLibrary, |
|
306 idleState, appLibraryState); |
|
307 idleState->addTransition(idleToAppLibTransition); |
|
308 |
|
309 HsMenuEventTransition *appLibToIdleTransition = |
|
310 new HsMenuEventTransition( |
|
311 HsMenuEvent::OpenHomeScreen, appLibraryState, idleState); |
|
312 appLibraryState->addTransition(appLibToIdleTransition); |
|
313 |
|
314 HbMainWindow *window = hbInstance->allMainWindows().first(); |
|
315 |
|
316 // key driven transition from idle to menu |
|
317 QKeyEventTransition *idleToMenuRootTransition = |
|
318 new QKeyEventTransition( |
|
319 window, QEvent::KeyPress, applicationKey); |
|
320 idleToMenuRootTransition->setTargetState(menuRootState); |
|
321 idleState->addTransition(idleToMenuRootTransition); |
|
322 // key driven transition from menu to idle |
|
323 QKeyEventTransition *menuToIdleTransition = |
|
324 new QKeyEventTransition( |
|
325 window, QEvent::KeyPress, applicationKey); |
|
326 menuToIdleTransition->setTargetState(idleState); |
|
327 menuRootState->addTransition(menuToIdleTransition); |
|
328 |
|
329 // transition for Key_Launch0 should be removed |
|
330 // when OT starts to send Key_Menu (maybe wk14) |
|
331 QKeyEventTransition *idleToMenuRootTransition2 = |
|
332 new QKeyEventTransition( |
|
333 window, QEvent::KeyPress, Qt::Key_Launch0); |
|
334 idleToMenuRootTransition2->setTargetState(menuRootState); |
|
335 idleState->addTransition(idleToMenuRootTransition2); |
|
336 // key driven transition from menu to idle |
|
337 QKeyEventTransition *menuToIdleTransition2 = |
|
338 new QKeyEventTransition( |
|
339 window, QEvent::KeyPress, Qt::Key_Launch0); |
|
340 menuToIdleTransition2->setTargetState(idleState); |
|
341 menuRootState->addTransition(menuToIdleTransition2); |
|
342 // add transition to switch to idle |
|
343 menuRootState->addTransition( this, SIGNAL(event_toIdle()), idleState); |
|
344 |
|
345 // transitions to child states |
|
346 // opening shortcut to a colleciton |
|
347 QList<QState *> collectionStates = |
|
348 appLibraryState-> |
|
349 findChildren<QState *> |
|
350 ("homescreen.nokia.com/state/applibrarystate/collectionstate"); |
|
351 qDebug( |
|
352 "Found %d \"collectionstate\" children for Application Library State", |
|
353 collectionStates.count()); |
|
354 if (collectionStates.count()) { |
|
355 HsMenuEventTransition *idleToCollectionTransition = |
|
356 new HsMenuEventTransition(HsMenuEvent::OpenCollection, |
|
357 idleState, collectionStates[0]); |
|
358 idleState->addTransition(idleToCollectionTransition); |
|
359 } |
|
360 |
|
361 guiRootState->setInitialState(loadSceneState); |
|
362 setInitialState(guiRootState); |
|
363 |
|
364 HSTEST_FUNC_EXIT("HS::HsDefaultRuntime::createStates"); |
|
365 } |
|
366 |
|
367 /*! |
|
368 Assigns services to states based on value of property HS_SERVICES_REGISTRATION_KEY. |
|
369 */ |
|
370 void HsDefaultRuntime::assignServices() |
|
371 { |
|
372 HSTEST_FUNC_ENTRY("HS::HsDefaultRuntime::assignServices"); |
|
373 |
|
374 QList<QState*> children = findChildren<QState*>(); |
|
375 foreach (QState *state, children) { |
|
376 QList<QVariant> services = state->property(HS_SERVICES_REGISTRATION_KEY).toList(); |
|
377 foreach (const QVariant &service, services) { |
|
378 QString name = service.toString(); |
|
379 qDebug() << "Assign service:" << name << "\n to " << state->objectName(); |
|
380 if (name == CONTENT_SERVICE_KEY) { |
|
381 state->setProperty(name.toAscii().data(), qVariantFromValue(mContentService)); |
|
382 } else if (name == SHORTCUT_SERVICE_KEY) { |
|
383 state->setProperty(name.toAscii().data(), |
|
384 qVariantFromValue(HsShortcutService::instance(this))); |
|
385 } else { |
|
386 qWarning() << "WARNING: Service " << name << " is unknown"; |
|
387 } |
|
388 } |
|
389 } |
|
390 |
|
391 HSTEST_FUNC_EXIT("HS::HsDefaultRuntime::assignServices"); |
|
392 } |
|
393 |
|
394 /*! |
|
395 Publishes Home screen states via Publish & Subscribe. |
|
396 */ |
|
397 void HsDefaultRuntime::updatePSKeys() |
|
398 { |
|
399 if (!mPublisher){ |
|
400 createStatePublisher(); |
|
401 } |
|
402 |
|
403 if (mHomeScreenActive && mIdleStateActive){ |
|
404 qDebug() << "HsDefaultRuntime::updatePSKeys: EHomeScreenIdleState"; |
|
405 mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenIdleState); |
|
406 } |
|
407 else{ |
|
408 qDebug() << "HsDefaultRuntime::updatePSKeys: EHomeScreenInactive"; |
|
409 mPublisher->setValue(HsStatePSKeySubPath, EHomeScreenInactive); |
|
410 } |
|
411 } |
|
412 |
|
413 /*! |
|
414 Called when state machine is in Idle state. |
|
415 */ |
|
416 void HsDefaultRuntime::onIdleStateEntered() |
|
417 { |
|
418 mIdleStateActive = true; |
|
419 updatePSKeys(); |
|
420 } |
|
421 |
|
422 /*! |
|
423 Called when state machine leaves the Idle state. |
|
424 */ |
|
425 void HsDefaultRuntime::onIdleStateExited() |
|
426 { |
|
427 mIdleStateActive = false; |
|
428 updatePSKeys(); |
|
429 } |
|
430 |
|
431 /*! |
|
432 Activity requested by another client |
|
433 */ |
|
434 void HsDefaultRuntime::activityRequested(const QString &name) |
|
435 { |
|
436 if (name == appLibActivity()) { |
|
437 this->postEvent( |
|
438 HsMenuEventFactory::createOpenAppLibraryEvent(NormalHsMenuMode)); |
|
439 } |
|
440 else if (name == groupAppLibRecentView()) { |
|
441 this->postEvent( |
|
442 HsMenuEventFactory::createOpenCollectionEvent(0, |
|
443 collectionDownloadedTypeName())); |
|
444 } else if (name == activityHsIdleView()) { |
|
445 emit event_toIdle(); |
|
446 } |
|
447 } |
|