25 #include <qservicemanager.h> |
25 #include <qservicemanager.h> |
26 #include <qservicefilter.h> |
26 #include <qservicefilter.h> |
27 #include <qserviceinterfacedescriptor.h> |
27 #include <qserviceinterfacedescriptor.h> |
28 |
28 |
29 #include <HbInstance> |
29 #include <HbInstance> |
|
30 #include <HbInstantFeedback> |
30 |
31 |
31 #include "hswidgethost.h" |
32 #include "hswidgethost.h" |
32 #include "hsdatabase.h" |
33 #include "hsdatabase.h" |
33 #include "hsdomainmodeldatastructures.h" |
34 #include "hsdomainmodeldatastructures.h" |
34 #include "hspage.h" |
35 #include "hspage.h" |
41 |
42 |
42 /*! |
43 /*! |
43 \class HsWidgetHost |
44 \class HsWidgetHost |
44 \ingroup group_hsutils |
45 \ingroup group_hsutils |
45 \brief Homescreen widget runner. |
46 \brief Homescreen widget runner. |
46 Is responsible of running a homescreen widget. Each |
47 Is responsible of running a homescreen widget. Each |
47 homescreen widget has its own host. |
48 homescreen widget has its own host. |
48 */ |
49 */ |
49 |
50 |
50 HsWidgetHost* HsWidgetHost::createInstance(HsWidgetData &widgetData, |
51 HsWidgetHost* HsWidgetHost::createInstance(HsWidgetData &widgetData, |
51 const QVariantHash &preferences) |
52 const QVariantHash &preferences) |
52 { |
53 { |
53 HsDatabase* db = HsDatabase::instance(); |
54 HsDatabase* db = HsDatabase::instance(); |
54 Q_ASSERT(db); |
55 Q_ASSERT(db); |
55 |
56 |
59 } |
60 } |
60 |
61 |
61 return 0; |
62 return 0; |
62 } |
63 } |
63 /*! |
64 /*! |
64 Construct a widget host for the given \a databaseId. |
65 Construct a widget host for the given \a databaseId. |
65 \a parent becomes the parent item for the host. |
66 \a parent becomes the parent item for the host. |
66 */ |
67 */ |
67 HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) |
68 HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) |
68 : HbWidget(parent), |
69 : HbWidget(parent), |
69 mWidget(0), |
70 mWidget(0), |
70 mPage(0), |
71 mPage(0), |
71 mState(Constructed), |
72 mState(Unloaded), |
72 mDatabaseId(databaseId), |
73 mDatabaseId(databaseId), |
73 mTapAndHoldIcon(0) |
74 mTapAndHoldIcon(0) |
74 { |
75 { |
75 setFlags(QGraphicsItem::ItemClipsChildrenToShape); |
76 setFlags(QGraphicsItem::ItemClipsChildrenToShape); |
76 |
77 |
|
78 HsDatabase *db = HsDatabase::instance(); |
|
79 |
|
80 // Find the widget data. |
|
81 HsWidgetData data; |
|
82 data.id = mDatabaseId; |
|
83 if (!db->widget(data)) { |
|
84 return; |
|
85 } |
|
86 |
|
87 mUri = data.uri; |
|
88 |
|
89 // bind host to component |
|
90 HsWidgetComponent *component = HsWidgetComponentRegistry::instance()->component(mUri); |
|
91 connect(component, SIGNAL(uninstalled()), SLOT(onFinished())); |
|
92 connect(component, SIGNAL(aboutToUninstall()), SLOT(onAboutToUninstall())); |
|
93 connect(component, SIGNAL(updated()), SLOT(onUpdated())); |
|
94 connect(component, SIGNAL(unavailable()), SLOT(onUnavailable())); |
|
95 connect(component, SIGNAL(available()), SLOT(onAvailable())); |
|
96 |
77 /* TODO: Uncomment after the Qt bug has been fixed. |
97 /* TODO: Uncomment after the Qt bug has been fixed. |
78 QGraphicsDropShadowEffect *effect = |
98 QGraphicsDropShadowEffect *effect = |
79 new QGraphicsDropShadowEffect(this); |
99 new QGraphicsDropShadowEffect(this); |
80 effect->setColor(QColor(0, 0, 0, 150)); |
100 effect->setColor(QColor(0, 0, 0, 150)); |
81 effect->setBlurRadius(5); |
101 effect->setBlurRadius(5); |
82 effect->setOffset(3); |
102 effect->setOffset(3); |
83 setGraphicsEffect(effect); |
103 setGraphicsEffect(effect); |
95 Load hosted widget from plugin and validate it. |
115 Load hosted widget from plugin and validate it. |
96 Returns true if widget construction is successfull. |
116 Returns true if widget construction is successfull. |
97 */ |
117 */ |
98 bool HsWidgetHost::load() |
118 bool HsWidgetHost::load() |
99 { |
119 { |
|
120 if (mState != Unloaded) { |
|
121 return false; |
|
122 } |
100 if (mWidget) { |
123 if (mWidget) { |
101 return false; |
124 return false; |
102 } |
125 } |
103 |
126 |
104 HsDatabase *db = HsDatabase::instance(); |
127 |
105 |
|
106 // Find the widget data. |
|
107 HsWidgetData data; |
|
108 data.id = mDatabaseId; |
|
109 if (!db->widget(data)) { |
|
110 return false; |
|
111 } |
|
112 |
|
113 mUri = data.uri; |
|
114 // Create the hosted widget. |
128 // Create the hosted widget. |
115 QServiceManager manager; |
129 QServiceManager manager; |
116 QServiceFilter filter("com.nokia.symbian.IHomeScreenWidget"); |
130 QServiceFilter filter("com.nokia.symbian.IHomeScreenWidget"); |
117 filter.setServiceName(mUri); |
131 filter.setServiceName(mUri); |
118 QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter); |
132 QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter); |
121 } |
135 } |
122 |
136 |
123 QObject *widgetObject = manager.loadInterface(interfaces.first()); |
137 QObject *widgetObject = manager.loadInterface(interfaces.first()); |
124 mWidget = qobject_cast<QGraphicsWidget *>(widgetObject); |
138 mWidget = qobject_cast<QGraphicsWidget *>(widgetObject); |
125 |
139 |
126 if (!mWidget || |
140 if (!mWidget || |
127 !setMethod("onShow()", mOnShowMethod) || |
141 !setMethod("onShow()", mOnShowMethod) || |
128 !setMethod("onHide()", mOnHideMethod)) { |
142 !setMethod("onHide()", mOnHideMethod)) { |
129 mWidget = 0; |
143 mWidget = 0; |
130 delete widgetObject; |
144 delete widgetObject; |
131 return false; |
145 return false; |
132 } |
146 } |
133 |
147 |
134 setProperty("isOnline", mIsOnlineProperty); |
148 setProperty("isOnline", mIsOnlineProperty); |
135 setProperty("rootPath", mRootPathProperty); |
149 setProperty("rootPath", mRootPathProperty); |
136 |
150 |
137 setMethod("onInitialize()", mOnInitializeMethod); |
151 setMethod("onInitialize()", mOnInitializeMethod); |
138 setMethod("onUninitialize()", mOnUninitializeMethod); |
152 setMethod("onUninitialize()", mOnUninitializeMethod); |
139 |
153 |
140 if (hasSignal("setPreferences(const QStringList&)")) { |
154 if (hasSignal("setPreferences(const QStringList&)")) { |
141 connect(mWidget, SIGNAL(setPreferences(QStringList)), |
155 connect(mWidget, SIGNAL(setPreferences(QStringList)), |
142 SLOT(onSetPreferences(QStringList))); |
156 SLOT(onSetPreferences(QStringList))); |
143 } |
157 } |
144 if (hasSignal("finished()")) { |
158 if (hasSignal("finished()")) { |
147 } |
161 } |
148 if (hasSignal("error()")) { |
162 if (hasSignal("error()")) { |
149 connect(mWidget, SIGNAL(error()), |
163 connect(mWidget, SIGNAL(error()), |
150 SLOT(onError())); |
164 SLOT(onError())); |
151 } |
165 } |
152 |
166 |
153 mWidget->installEventFilter(this); |
167 mWidget->installEventFilter(this); |
154 |
168 |
155 loadWidgetPresentation(); |
169 loadWidgetPresentation(); |
156 |
170 |
157 HsScene *scene = HsScene::instance(); |
171 HsScene *scene = HsScene::instance(); |
158 setMaximumSize(scene->maximumWidgetSizeInPixels()); |
172 setMaximumSize(scene->maximumWidgetSizeInPixels()); |
159 setMinimumSize(scene->minimumWidgetSizeInPixels()); |
173 setMinimumSize(scene->minimumWidgetSizeInPixels()); |
160 |
174 |
161 mWidget->setParentItem(this); |
175 mWidget->setParentItem(this); |
162 |
176 |
163 setNewSize(mWidget->size()); |
177 setNewSize(mWidget->size()); |
164 |
178 mState = Loaded; |
|
179 |
165 return true; |
180 return true; |
|
181 } |
|
182 |
|
183 void HsWidgetHost::unload() |
|
184 { |
|
185 if (mState != Uninitialized) { |
|
186 return; |
|
187 } |
|
188 if (mWidget) { |
|
189 mWidget->setParentItem(0); |
|
190 } |
|
191 delete mWidget; |
|
192 QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); |
|
193 mWidget = 0; |
|
194 mState = Unloaded; |
166 } |
195 } |
167 |
196 |
168 bool HsWidgetHost::setPage(HsPage *page) |
197 bool HsWidgetHost::setPage(HsPage *page) |
169 { |
198 { |
170 HsDatabase* db = HsDatabase::instance(); |
199 HsDatabase* db = HsDatabase::instance(); |
234 bool HsWidgetHost::setWidgetPresentation() |
263 bool HsWidgetHost::setWidgetPresentation() |
235 { |
264 { |
236 HsDatabase *db = HsDatabase::instance(); |
265 HsDatabase *db = HsDatabase::instance(); |
237 Q_ASSERT(db); |
266 Q_ASSERT(db); |
238 |
267 |
239 QString key = HsScene::orientation() == Qt::Vertical ? |
268 QString key = HsScene::orientation() == Qt::Vertical ? |
240 "portrait" : "landscape"; |
269 "portrait" : "landscape"; |
241 |
270 |
242 HsWidgetPresentationData data; |
271 HsWidgetPresentationData data; |
243 data.key = key; |
272 data.key = key; |
244 data.setPos(pos()); |
273 data.setPos(pos()); |
245 data.zValue = zValue(); |
274 data.zValue = zValue(); |
246 data.widgetId = databaseId(); |
275 data.widgetId = databaseId(); |
247 |
276 |
248 return db->setWidgetPresentation(data); |
277 return db->setWidgetPresentation(data); |
249 } |
278 } |
250 |
279 |
251 /*! |
280 /*! |
252 Set widget presentation data. Return true if successfull. |
281 Set widget presentation data. Return true if successfull. |
259 presentationData.widgetId = mDatabaseId; |
288 presentationData.widgetId = mDatabaseId; |
260 return db->setWidgetPresentation(presentationData); |
289 return db->setWidgetPresentation(presentationData); |
261 } |
290 } |
262 |
291 |
263 /*! |
292 /*! |
264 Get widget presentation data matching given \a key. |
293 Get widget presentation data matching given \a key. |
265 Data is returned on given empty \a presentationData. Return true if successfull |
294 Data is returned on given empty \a presentationData. Return true if successfull |
266 */ |
295 */ |
267 bool HsWidgetHost::widgetPresentationData(const QString &key, |
296 bool HsWidgetHost::widgetPresentationData(const QString &key, |
268 HsWidgetPresentationData &presentationData) |
297 HsWidgetPresentationData &presentationData) |
269 { |
298 { |
270 HsDatabase *db = HsDatabase::instance(); |
299 HsDatabase *db = HsDatabase::instance(); |
281 HsWidgetPresentationData HsWidgetHost::widgetPresentation(Qt::Orientation orientation) |
310 HsWidgetPresentationData HsWidgetHost::widgetPresentation(Qt::Orientation orientation) |
282 { |
311 { |
283 HsDatabase *db = HsDatabase::instance(); |
312 HsDatabase *db = HsDatabase::instance(); |
284 Q_ASSERT(db); |
313 Q_ASSERT(db); |
285 |
314 |
286 QString key = orientation == Qt::Vertical ? |
315 QString key = orientation == Qt::Vertical ? |
287 "portrait" : "landscape"; |
316 "portrait" : "landscape"; |
288 |
317 |
289 HsWidgetPresentationData data; |
318 HsWidgetPresentationData data; |
290 data.key = key; |
319 data.key = key; |
291 data.widgetId = mDatabaseId; |
320 data.widgetId = mDatabaseId; |
300 Load HsWidgetPresentationData for current orientation |
329 Load HsWidgetPresentationData for current orientation |
301 */ |
330 */ |
302 bool HsWidgetHost::loadWidgetPresentation() |
331 bool HsWidgetHost::loadWidgetPresentation() |
303 { |
332 { |
304 HsDatabase *db = HsDatabase::instance(); |
333 HsDatabase *db = HsDatabase::instance(); |
305 |
334 |
306 QString key = HsScene::orientation() == Qt::Vertical ? |
335 QString key = HsScene::orientation() == Qt::Vertical ? |
307 "portrait" : "landscape"; |
336 "portrait" : "landscape"; |
308 |
337 |
309 HsWidgetPresentationData data; |
338 HsWidgetPresentationData data; |
310 data.key = key; |
339 data.key = key; |
326 bool HsWidgetHost::deleteWidgetPresentation(Qt::Orientation orientation) |
355 bool HsWidgetHost::deleteWidgetPresentation(Qt::Orientation orientation) |
327 { |
356 { |
328 HsDatabase *db = HsDatabase::instance(); |
357 HsDatabase *db = HsDatabase::instance(); |
329 Q_ASSERT(db); |
358 Q_ASSERT(db); |
330 |
359 |
331 QString key = orientation == Qt::Vertical ? |
360 QString key = orientation == Qt::Vertical ? |
332 "portrait" : "landscape"; |
361 "portrait" : "landscape"; |
333 |
362 |
334 return db->deleteWidgetPresentation(mDatabaseId, key); |
363 return db->deleteWidgetPresentation(mDatabaseId, key); |
335 } |
364 } |
336 |
365 |
337 /*! |
366 /*! |
338 \fn void HsWidgetHost::finished() |
367 \fn void HsWidgetHost::widgetFinished() |
339 This signal is emitten after the contained widget |
368 This signal is emitten after the contained widget |
340 hs reported is completion. |
369 reported is completion. |
341 */ |
370 */ |
342 |
371 |
343 /*! |
372 /*! |
344 \fn void HsWidgetHost::error() |
373 \fn void HsWidgetHost::widgetError() |
345 This signal is emitten after the contained widget |
374 This signal is emitten after the contained widget |
346 hs reported an error. |
375 reported an error. |
|
376 */ |
|
377 |
|
378 /*! |
|
379 \fn void HsWidgetHost::widgetResized() |
|
380 This signal is emitten after the contained widget |
|
381 sends a resize event. |
347 */ |
382 */ |
348 |
383 |
349 /*! |
384 /*! |
350 Calls the widget's onInitialize() slot if the |
385 Calls the widget's onInitialize() slot if the |
351 widget defines it. |
386 widget defines it. |
352 */ |
387 */ |
353 void HsWidgetHost::initializeWidget() |
388 void HsWidgetHost::initializeWidget() |
354 { |
389 { |
355 if (mState != Constructed) { |
390 if (mState != Loaded) { |
356 return; |
391 return; |
357 } |
392 } |
358 // bind component to instance |
393 HsWidgetComponent *component = HsWidgetComponentRegistry::instance()->component(mUri); |
359 HsWidgetComponent *component = HsWidgetComponentRegistry::instance()->component(mUri); |
394 Q_ASSERT(component); |
360 Q_ASSERT(component); |
395 mRootPathProperty.write(mWidget, component->rootPath()); |
361 connect(component, SIGNAL(aboutToUninstall()), SLOT(onFinished()),Qt::QueuedConnection); |
|
362 mRootPathProperty.write(mWidget, component->rootPath()); |
|
363 |
|
364 setPreferencesToWidget(); |
396 setPreferencesToWidget(); |
365 setOnline(HsScene::instance()->isOnline()); |
397 setOnline(HsScene::instance()->isOnline()); |
366 mOnInitializeMethod.invoke(mWidget); |
398 mOnInitializeMethod.invoke(mWidget); |
367 |
399 |
368 mState = Initialized; |
400 mState = Initialized; |
369 } |
401 } |
370 |
402 |
371 /*! |
403 /*! |
372 Calls the widget's onShow() slot if the |
404 Calls the widget's onShow() slot if the |
373 widget defines it. |
405 widget defines it. |
374 */ |
406 */ |
375 void HsWidgetHost::showWidget() |
407 void HsWidgetHost::showWidget() |
376 { |
408 { |
377 if (mState != Initialized && |
409 if (mState != Initialized && |
378 mState != Hidden) { |
410 mState != Hidden ) { |
379 return; |
411 return; |
380 } |
412 } |
381 |
413 |
382 mOnShowMethod.invoke(mWidget); |
414 mOnShowMethod.invoke(mWidget); |
383 |
415 |
384 mState = Visible; |
416 mState = Visible; |
385 } |
417 } |
386 |
418 |
387 /*! |
419 /*! |
388 Calls the widget's onHide() slot if the |
420 Calls the widget's onHide() slot if the |
427 } |
458 } |
428 |
459 |
429 /*! |
460 /*! |
430 Starts the widget drag animation. |
461 Starts the widget drag animation. |
431 */ |
462 */ |
432 void HsWidgetHost::startDragAnimation() |
463 void HsWidgetHost::startDragEffect() |
433 { |
464 { |
434 /* TODO: Uncomment after the Qt bug has been fixed. |
465 /* TODO: Uncomment after the Qt bug has been fixed. |
435 QGraphicsDropShadowEffect *effect = |
466 QGraphicsDropShadowEffect *effect = |
436 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
467 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
437 */ |
468 */ |
|
469 HbInstantFeedback::play(HbFeedback::ItemPick); |
438 |
470 |
439 setTransformOriginPoint(rect().center()); |
471 setTransformOriginPoint(rect().center()); |
440 |
472 |
441 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(); |
473 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(); |
442 |
474 |
452 animationGroup->addAnimation(animation); |
484 animationGroup->addAnimation(animation); |
453 */ |
485 */ |
454 |
486 |
455 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
487 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
456 } |
488 } |
457 |
489 |
458 /*! |
490 /*! |
459 Starts the widget drop animation. |
491 Starts the widget drop animation. |
460 */ |
492 */ |
461 void HsWidgetHost::startDropAnimation() |
493 void HsWidgetHost::startDropEffect() |
462 { |
494 { |
463 /* TODO: Uncomment after the Qt bug has been fixed. |
495 /* TODO: Uncomment after the Qt bug has been fixed. |
464 QGraphicsDropShadowEffect *effect = |
496 QGraphicsDropShadowEffect *effect = |
465 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
497 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
466 */ |
498 */ |
|
499 HbInstantFeedback::play(HbFeedback::ItemDrop); |
467 |
500 |
468 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup; |
501 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup; |
469 |
502 |
470 QPropertyAnimation *animation = new QPropertyAnimation(this, "scale"); |
503 QPropertyAnimation *animation = new QPropertyAnimation(this, "scale"); |
471 animation->setDuration(200); |
504 animation->setDuration(200); |
507 bool HsWidgetHost::eventFilter(QObject *obj, QEvent *event) |
540 bool HsWidgetHost::eventFilter(QObject *obj, QEvent *event) |
508 { |
541 { |
509 if (event->type() == QEvent::GraphicsSceneResize ) { |
542 if (event->type() == QEvent::GraphicsSceneResize ) { |
510 QGraphicsSceneResizeEvent *resizeEvent = static_cast<QGraphicsSceneResizeEvent*>(event); |
543 QGraphicsSceneResizeEvent *resizeEvent = static_cast<QGraphicsSceneResizeEvent*>(event); |
511 setNewSize(resizeEvent->newSize()); |
544 setNewSize(resizeEvent->newSize()); |
|
545 emit widgetResized(this); |
512 return true; |
546 return true; |
513 } else { |
547 } else { |
514 // standard event processing |
548 // standard event processing |
515 return HbWidget::eventFilter(obj, event); |
549 return HbWidget::eventFilter(obj, event); |
516 } |
550 } |
617 onError(); |
651 onError(); |
618 } |
652 } |
619 } |
653 } |
620 |
654 |
621 /*! |
655 /*! |
622 This slot reacts to the widgets finished() signal, if |
656 This slot reacts to the widgets finished() signal, if |
623 it was defined for the widget. The widget emits the signal |
657 it was defined for the widget. The widget emits the signal |
624 when it has finished its execution and is ready for |
658 when it has finished its execution and is ready for |
625 removal from the homescreen. |
659 removal from the homescreen. |
626 */ |
660 */ |
627 void HsWidgetHost::onFinished() |
661 void HsWidgetHost::onFinished() |
628 { |
662 { |
629 mState = Finished; |
|
630 emit widgetFinished(this); |
663 emit widgetFinished(this); |
631 } |
664 } |
632 |
665 |
633 /*! |
666 /*! |
634 This slot reacts to the widgets error() signal, if it was |
667 This slot reacts to the widgets error() signal, if it was |
635 defined for the widget. The widget emits the signal in |
668 defined for the widget. The widget emits the signal in |
636 failure cases. |
669 failure cases. |
637 */ |
670 */ |
638 void HsWidgetHost::onError() |
671 void HsWidgetHost::onError() |
639 { |
672 { |
640 mState = Faulted; |
673 mState = Faulted; |
641 emit widgetError(this); |
674 emit widgetError(this); |
642 } |
675 } |
643 |
676 /*! |
644 |
677 This slot is called when component is about to uninstall or |
|
678 update. Widget need to release all handles to resources installing |
|
679 to succeed. |
|
680 */ |
|
681 void HsWidgetHost::onAboutToUninstall() |
|
682 { |
|
683 uninitializeWidget(); |
|
684 unload(); |
|
685 } |
|
686 |
|
687 void HsWidgetHost::onUpdated() |
|
688 { |
|
689 if(mState != Unloaded) { |
|
690 return; |
|
691 } |
|
692 load(); |
|
693 initializeWidget(); |
|
694 if (HsScene::instance()->activePage() == mPage) { |
|
695 showWidget(); |
|
696 } else { |
|
697 hideWidget(); |
|
698 } |
|
699 |
|
700 } |
|
701 void HsWidgetHost::onUnavailable() |
|
702 { |
|
703 if (mState != Visible && mState != Hidden) { |
|
704 return; |
|
705 } |
|
706 uninitializeWidget(); |
|
707 unload(); |
|
708 } |
|
709 |
|
710 void HsWidgetHost::onAvailable() |
|
711 { |
|
712 if (mState != Unloaded) { |
|
713 return; |
|
714 } |
|
715 load(); |
|
716 initializeWidget(); |
|
717 if (HsScene::instance()->activePage() == mPage) { |
|
718 showWidget(); |
|
719 } else { |
|
720 hideWidget(); |
|
721 } |
|
722 } |
|
723 |
|
724 |
|
725 |
|
726 |
|
727 |