17 |
17 |
18 #include <QApplication> |
18 #include <QApplication> |
19 #include <QStateMachine> |
19 #include <QStateMachine> |
20 #include <QState> |
20 #include <QState> |
21 #include <QFinalState> |
21 #include <QFinalState> |
22 #include <QGraphicsLinearLayout> |
|
23 #include <QParallelAnimationGroup> |
|
24 #include <QPropertyAnimation> |
|
25 #include <QGraphicsDropShadowEffect> |
|
26 #include <QGraphicsSceneResizeEvent> |
|
27 #include <QGesture> |
|
28 #include <QGraphicsScene> |
|
29 |
|
30 #include <qservicemanager.h> |
|
31 #include <qservicefilter.h> |
|
32 #include <qserviceinterfacedescriptor.h> |
|
33 |
|
34 #include <HbInstantFeedback> |
|
35 #include <HbTouchArea> |
|
36 |
22 |
37 #include "hsdatabase.h" |
23 #include "hsdatabase.h" |
38 #include "hsdomainmodeldatastructures.h" |
24 #include "hsdomainmodeldatastructures.h" |
39 #include "hsscene.h" |
25 #include "hsscene.h" |
40 #include "hspage.h" |
26 #include "hspage.h" |
41 #include "hswidgethost.h" |
27 #include "hswidgethost.h" |
42 #include "hswidgettoucharea.h" |
28 #include "hswidgethostvisual.h" |
|
29 #include "hshostedwidgetfactory.h" |
|
30 |
43 #include "hswidgetcomponentregistry.h" |
31 #include "hswidgetcomponentregistry.h" |
44 #include "hswidgetcomponent.h" |
32 #include "hswidgetcomponent.h" |
45 #include "hsconfiguration.h" |
33 #include "hsconfiguration.h" |
46 #include "hscontentservice.h" |
34 #include "hscontentservice.h" |
|
35 #include "hsgui.h" |
47 |
36 |
48 // Helper macros for connecting state entry and exit actions. |
37 // Helper macros for connecting state entry and exit actions. |
49 #define ENTRY_ACTION(state, action) \ |
38 #define ENTRY_ACTION(state, action) \ |
50 connect(state, SIGNAL(entered()), SLOT(action())); |
39 connect(state, SIGNAL(entered()), SLOT(action())); |
51 #define EXIT_ACTION(state, action) \ |
40 #define EXIT_ACTION(state, action) \ |
52 connect(state, SIGNAL(exited()), SLOT(action())); |
41 connect(state, SIGNAL(exited()), SLOT(action())); |
53 |
42 |
54 QTM_USE_NAMESPACE |
43 |
55 |
44 |
56 |
45 |
57 /*! |
46 /*! |
58 \class HsWidgetHost |
47 \class HsWidgetHost |
59 \ingroup group_hsdomainmodel |
48 \ingroup group_hsdomainmodel |
62 |
51 |
63 /*! |
52 /*! |
64 Constructs a new widget host with given \a databaseId and |
53 Constructs a new widget host with given \a databaseId and |
65 \a parent item. |
54 \a parent item. |
66 */ |
55 */ |
67 HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) |
56 HsWidgetHost::HsWidgetHost(int databaseId, QObject *parent) |
68 : HbWidget(parent), |
57 : QObject(parent), |
|
58 mVisual(new HsWidgetHostVisual), |
69 mDatabaseId(databaseId), |
59 mDatabaseId(databaseId), |
70 mStateMachine(0), |
60 mStateMachine(0), |
71 mWidget(0), |
61 mWidget(0), |
72 mPage(0), |
62 mPage(0), |
73 mComponent(0), |
63 mComponent(0), |
74 mIsFinishing(false) |
64 mIsFinishing(false) |
75 { |
65 { |
76 setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
|
77 setFlag(QGraphicsItem::ItemHasNoContents); |
|
78 |
|
79 grabGesture(Qt::TapGesture); |
|
80 grabGesture(Qt::TapAndHoldGesture); |
|
81 grabGesture(Qt::PanGesture); |
|
82 grabGesture(Qt::PinchGesture); |
|
83 grabGesture(Qt::SwipeGesture); |
|
84 grabGesture(Qt::CustomGesture); |
|
85 |
|
86 setupTouchArea(); |
|
87 setupEffects(); |
|
88 setupStates(); |
66 setupStates(); |
|
67 mVisual->setVisualModel(this); |
89 } |
68 } |
90 |
69 |
91 /*! |
70 /*! |
92 Destructor. |
71 Destructor. |
93 */ |
72 */ |
94 HsWidgetHost::~HsWidgetHost() |
73 HsWidgetHost::~HsWidgetHost() |
95 { |
74 { |
|
75 delete mVisual; |
96 } |
76 } |
97 |
77 |
98 /*! |
78 /*! |
99 Creates a new widget host instance based on the give |
79 Creates a new widget host instance based on the give |
100 \a widgetData and \a preferences. Returns the created |
80 \a widgetData and \a preferences. Returns the created |
178 data.orientation = orientation; |
159 data.orientation = orientation; |
179 data.widgetId = mDatabaseId; |
160 data.widgetId = mDatabaseId; |
180 if (!db->widgetPresentation(data)) { |
161 if (!db->widgetPresentation(data)) { |
181 return false; |
162 return false; |
182 } |
163 } |
183 setPos(data.x, data.y); |
164 mVisual->setPos(data.x, data.y); |
184 setZValue(data.zValue); |
165 mVisual->setZValue(data.zValue); |
185 return true; |
166 return true; |
186 } |
167 } |
187 |
168 |
188 /*! |
169 /*! |
189 Saves the current presentation. |
170 Saves the current presentation. |
190 Returns true on success, otherwise returns false. |
171 Returns true on success, otherwise returns false. |
191 */ |
172 */ |
192 bool HsWidgetHost::savePresentation() |
173 bool HsWidgetHost::savePresentation() |
193 { |
174 { |
194 return savePresentation(HsScene::orientation()); |
175 return savePresentation(HsGui::instance()->orientation()); |
195 } |
176 } |
196 |
177 |
197 /*! |
178 /*! |
198 Saves the current presentation for the given \a orientation. |
179 Saves the current presentation for the given \a orientation. |
199 Returns true on success, otherwise returns false. |
180 Returns true on success, otherwise returns false. |
243 { |
224 { |
244 HsDatabase *db = HsDatabase::instance(); |
225 HsDatabase *db = HsDatabase::instance(); |
245 return db->deleteWidgetPresentation(mDatabaseId, orientation); |
226 return db->deleteWidgetPresentation(mDatabaseId, orientation); |
246 } |
227 } |
247 |
228 |
248 /*! |
229 HsWidgetHostVisual *HsWidgetHost::visual() const |
249 Reimplemented from QGraphicsItem. Returns the shape of the |
230 { |
250 this widget host. The shape is computed based on the contained |
231 return mVisual; |
251 widget. |
|
252 */ |
|
253 QPainterPath HsWidgetHost::shape() const |
|
254 { |
|
255 QPainterPath path; |
|
256 |
|
257 if (mWidget) { |
|
258 QRectF currRect = rect(); |
|
259 path = mWidget->shape(); |
|
260 |
|
261 QRectF pathRect(path.boundingRect()); |
|
262 |
|
263 if (pathRect.width() > currRect.width() |
|
264 || pathRect.height() > currRect.height()) { |
|
265 QPainterPath newPath(currRect.topLeft()); |
|
266 newPath.addRect(currRect); |
|
267 path = path.intersected(newPath); |
|
268 } |
|
269 } |
|
270 return path; |
|
271 } |
232 } |
272 |
233 |
273 /*! |
234 /*! |
274 \fn HsWidgetHost::event_startAndShow() |
235 \fn HsWidgetHost::event_startAndShow() |
275 Initiates a transition to show state. |
236 Initiates a transition to show state. |
422 /*! |
379 /*! |
423 Starts the drag effect. |
380 Starts the drag effect. |
424 */ |
381 */ |
425 void HsWidgetHost::startDragEffect() |
382 void HsWidgetHost::startDragEffect() |
426 { |
383 { |
427 /* TODO: Uncomment after the Qt bug has been fixed. |
384 mVisual->startDragEffect(); |
428 QGraphicsDropShadowEffect *effect = |
|
429 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
|
430 */ |
|
431 HbInstantFeedback::play(HbFeedback::ItemPick); |
|
432 |
|
433 setTransformOriginPoint(rect().center()); |
|
434 |
|
435 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup(); |
|
436 |
|
437 QPropertyAnimation *animation = new QPropertyAnimation(this, "scale"); |
|
438 animation->setDuration(HSCONFIGURATION_GET(widgetDragEffectDuration)); |
|
439 animation->setEndValue(1.1); |
|
440 animationGroup->addAnimation(animation); |
|
441 |
|
442 /* TODO: Uncomment after the Qt bug has been fixed. |
|
443 animation = new QPropertyAnimation(effect, "offset"); |
|
444 animation->setDuration(200); |
|
445 animation->setEndValue(QPointF(8 ,8)); |
|
446 animationGroup->addAnimation(animation); |
|
447 */ |
|
448 |
|
449 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
|
450 } |
385 } |
451 |
386 |
452 /*! |
387 /*! |
453 Starts the drop effect. |
388 Starts the drop effect. |
454 */ |
389 */ |
455 void HsWidgetHost::startDropEffect() |
390 void HsWidgetHost::startDropEffect() |
456 { |
391 { |
457 /* TODO: Uncomment after the Qt bug has been fixed. |
392 mVisual->startDropEffect(); |
458 QGraphicsDropShadowEffect *effect = |
|
459 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
|
460 */ |
|
461 HbInstantFeedback::play(HbFeedback::ItemDrop); |
|
462 |
|
463 QParallelAnimationGroup *animationGroup = new QParallelAnimationGroup; |
|
464 |
|
465 QPropertyAnimation *animation = new QPropertyAnimation(this, "scale"); |
|
466 animation->setDuration(HSCONFIGURATION_GET(widgetDropEffectDuration)); |
|
467 animation->setEndValue(1); |
|
468 animationGroup->addAnimation(animation); |
|
469 |
|
470 /* TODO: Uncomment after the Qt bug has been fixed. |
|
471 animation = new QPropertyAnimation(effect, "offset"); |
|
472 animation->setDuration(200); |
|
473 animation->setEndValue(QPointF(3, 3)); |
|
474 animationGroup->addAnimation(animation); |
|
475 */ |
|
476 |
|
477 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
|
478 } |
|
479 |
|
480 /*! |
|
481 Reimplemented from QObject for monitoring changes in |
|
482 contained widget's size. |
|
483 */ |
|
484 bool HsWidgetHost::eventFilter(QObject *watched, QEvent *event) |
|
485 { |
|
486 if (event->type() == QEvent::GraphicsSceneResize ) { |
|
487 QGraphicsSceneResizeEvent *resizeEvent = |
|
488 static_cast<QGraphicsSceneResizeEvent *>(event); |
|
489 setNewSize(resizeEvent->newSize()); |
|
490 emit resized(); |
|
491 } |
|
492 return HbWidget::eventFilter(watched, event); |
|
493 } |
|
494 |
|
495 /*! |
|
496 Reimplemented from HbWidget for pan gesture handling. |
|
497 */ |
|
498 void HsWidgetHost::gestureEvent(QGestureEvent *event) |
|
499 { |
|
500 HsScene *scene = HsScene::instance(); |
|
501 QGesture *gesture = event->gesture(Qt::PanGesture); |
|
502 if (gesture) { |
|
503 switch (gesture->state()) { |
|
504 case Qt::GestureStarted: |
|
505 grabMouse(); |
|
506 emit scene->pagePanStarted(event); |
|
507 break; |
|
508 case Qt::GestureUpdated: |
|
509 emit scene->pagePanUpdated(event); |
|
510 break; |
|
511 case Qt::GestureFinished: |
|
512 case Qt::GestureCanceled: |
|
513 ungrabMouse(); |
|
514 emit scene->pagePanFinished(event); |
|
515 break; |
|
516 default: |
|
517 break; |
|
518 } |
|
519 } |
|
520 } |
|
521 |
|
522 /*! |
|
523 \fn HsWidgetHost::mousePressEvent(QGraphicsSceneMouseEvent *) |
|
524 Reimplemented from QGraphicsItem for eating all mouse presses. |
|
525 */ |
|
526 |
|
527 /*! |
|
528 Configures the touch are for this widget host. |
|
529 */ |
|
530 void HsWidgetHost::setupTouchArea() |
|
531 { |
|
532 mTouchArea = new HsWidgetTouchArea(this); |
|
533 mTouchArea->setZValue(1); |
|
534 } |
|
535 |
|
536 /*! |
|
537 Configures the effects for this widget host. |
|
538 */ |
|
539 void HsWidgetHost::setupEffects() |
|
540 { |
|
541 /* TODO: Uncomment after the Qt bug has been fixed. |
|
542 QGraphicsDropShadowEffect *effect = |
|
543 new QGraphicsDropShadowEffect(this); |
|
544 effect->setColor(QColor(0, 0, 0, 150)); |
|
545 effect->setBlurRadius(5); |
|
546 effect->setOffset(3); |
|
547 setGraphicsEffect(effect); |
|
548 */ |
|
549 } |
393 } |
550 |
394 |
551 /*! |
395 /*! |
552 Configures the state machine for this widget host. |
396 Configures the state machine for this widget host. |
553 */ |
397 */ |
750 Loads the contained widget from a widget plugin and |
585 Loads the contained widget from a widget plugin and |
751 connects to it's meta interface. |
586 connects to it's meta interface. |
752 */ |
587 */ |
753 void HsWidgetHost::action_load() |
588 void HsWidgetHost::action_load() |
754 { |
589 { |
755 QServiceManager manager; |
590 mWidget = HsHostedWidgetFactory::instance()->createWidget(mComponent->uri()); |
756 QServiceFilter filter("com.nokia.symbian.IHomeScreenWidget"); |
591 if (!mWidget) { |
757 filter.setServiceName(mComponent->uri()); |
|
758 QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter); |
|
759 if (interfaces.isEmpty()) { |
|
760 emit event_faulted(); |
592 emit event_faulted(); |
761 return; |
593 return; |
762 } |
594 } |
763 |
595 // must have fuctions |
764 QObject *widgetObject = manager.loadInterface(interfaces.first()); |
596 if (!setMethod("onShow()", mOnShowMethod) || |
765 mWidget = qobject_cast<QGraphicsWidget *>(widgetObject); |
|
766 |
|
767 if (!mWidget || |
|
768 !setMethod("onShow()", mOnShowMethod) || |
|
769 !setMethod("onHide()", mOnHideMethod)) { |
597 !setMethod("onHide()", mOnHideMethod)) { |
|
598 delete mWidget; |
770 mWidget = 0; |
599 mWidget = 0; |
771 delete widgetObject; |
|
772 emit event_faulted(); |
600 emit event_faulted(); |
773 return; |
601 return; |
774 } |
602 } |
|
603 |
|
604 mVisual->setWidget(mWidget); |
775 |
605 |
776 setMethod("onInitialize()", mOnInitializeMethod); |
606 setMethod("onInitialize()", mOnInitializeMethod); |
777 setMethod("onUninitialize()", mOnUninitializeMethod); |
607 setMethod("onUninitialize()", mOnUninitializeMethod); |
778 |
608 |
779 setProperty("isOnline", mIsOnlineProperty); |
609 setProperty("isOnline", mIsOnlineProperty); |
790 if (hasSignal("error()")) { |
620 if (hasSignal("error()")) { |
791 connect(mWidget, SIGNAL(error()), |
621 connect(mWidget, SIGNAL(error()), |
792 SLOT(onError()), Qt::QueuedConnection); |
622 SLOT(onError()), Qt::QueuedConnection); |
793 } |
623 } |
794 |
624 |
795 mWidget->installEventFilter(this); |
|
796 |
|
797 setMinimumSize(HSCONFIGURATION_GET(minimumWidgetSizeInPixels)); |
|
798 setMaximumSize(HSCONFIGURATION_GET(maximumWidgetSizeInPixels)); |
|
799 |
|
800 loadPresentation(); |
625 loadPresentation(); |
801 |
626 |
802 mWidget->setParentItem(this); |
|
803 |
|
804 setNewSize(mWidget->size()); |
|
805 |
|
806 QString objName(mComponent->uri()); |
627 QString objName(mComponent->uri()); |
807 objName.append(":"); |
628 objName.append(":"); |
808 objName.append(QString::number(mDatabaseId)); |
629 objName.append(QString::number(mDatabaseId)); |
809 setObjectName(objName); |
630 mVisual->setObjectName(objName); |
810 } |
631 } |
811 |
632 |
812 /*! |
633 /*! |
813 Unloads the contained widget. |
634 Unloads the contained widget. |
814 */ |
635 */ |
815 void HsWidgetHost::action_unload() |
636 void HsWidgetHost::action_unload() |
816 { |
637 { |
|
638 mVisual->setWidget(0); |
817 delete mWidget; |
639 delete mWidget; |
818 mWidget = 0; |
640 mWidget = 0; |
819 // This is needed because QServicePluginCleanup is |
641 // This is needed because QServicePluginCleanup is |
820 // deleted asynchronously via the eventloop (deleteLater). |
642 // deleted asynchronously via the eventloop (deleteLater). |
821 // Here we want the plugin to unload synchronously. |
643 // Here we want the plugin to unload synchronously. |