13 * |
13 * |
14 * Description: |
14 * Description: |
15 * |
15 * |
16 */ |
16 */ |
17 |
17 |
18 #include <QMetaObject> |
18 #include <QApplication> |
|
19 #include <QStateMachine> |
|
20 #include <QState> |
|
21 #include <QFinalState> |
19 #include <QGraphicsLinearLayout> |
22 #include <QGraphicsLinearLayout> |
20 #include <QParallelAnimationGroup> |
23 #include <QParallelAnimationGroup> |
21 #include <QPropertyAnimation> |
24 #include <QPropertyAnimation> |
22 #include <QGraphicsDropShadowEffect> |
25 #include <QGraphicsDropShadowEffect> |
23 #include <QGraphicsSceneResizeEvent> |
26 #include <QGraphicsSceneResizeEvent> |
|
27 #include <QGesture> |
|
28 #include <QGraphicsScene> |
24 |
29 |
25 #include <qservicemanager.h> |
30 #include <qservicemanager.h> |
26 #include <qservicefilter.h> |
31 #include <qservicefilter.h> |
27 #include <qserviceinterfacedescriptor.h> |
32 #include <qserviceinterfacedescriptor.h> |
28 |
33 |
29 #include <HbInstance> |
|
30 #include <HbInstantFeedback> |
34 #include <HbInstantFeedback> |
31 |
35 |
32 #include "hswidgethost.h" |
|
33 #include "hsdatabase.h" |
36 #include "hsdatabase.h" |
34 #include "hsdomainmodeldatastructures.h" |
37 #include "hsdomainmodeldatastructures.h" |
|
38 #include "hsscene.h" |
35 #include "hspage.h" |
39 #include "hspage.h" |
36 #include "hsapp_defs.h" |
40 #include "hswidgethost.h" |
37 #include "hsscene.h" |
|
38 #include "hswidgetcomponentregistry.h" |
41 #include "hswidgetcomponentregistry.h" |
39 #include "hswidgetcomponent.h" |
42 #include "hswidgetcomponent.h" |
|
43 #include "hsconfiguration.h" |
|
44 |
|
45 // Helper macros for connecting state entry and exit actions. |
|
46 #define ENTRY_ACTION(state, action) \ |
|
47 connect(state, SIGNAL(entered()), SLOT(action())); |
|
48 #define EXIT_ACTION(state, action) \ |
|
49 connect(state, SIGNAL(exited()), SLOT(action())); |
40 |
50 |
41 QTM_USE_NAMESPACE |
51 QTM_USE_NAMESPACE |
42 |
52 |
43 /*! |
53 HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) |
44 \class HsWidgetHost |
54 : HbWidget(parent), |
45 \ingroup group_hsutils |
55 mDatabaseId(databaseId), |
46 \brief Homescreen widget runner. |
56 mStateMachine(0), |
47 Is responsible of running a homescreen widget. Each |
57 mWidget(0), |
48 homescreen widget has its own host. |
58 mPage(0), |
49 */ |
59 mComponent(0), |
50 |
60 mIsFinishing(false) |
51 HsWidgetHost* HsWidgetHost::createInstance(HsWidgetData &widgetData, |
61 { |
|
62 setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
|
63 setFlag(QGraphicsItem::ItemHasNoContents); |
|
64 |
|
65 grabGesture(Qt::TapGesture); |
|
66 grabGesture(Qt::TapAndHoldGesture); |
|
67 grabGesture(Qt::PanGesture); |
|
68 grabGesture(Qt::PinchGesture); |
|
69 grabGesture(Qt::SwipeGesture); |
|
70 grabGesture(Qt::CustomGesture); |
|
71 |
|
72 setupEffects(); |
|
73 setupStates(); |
|
74 } |
|
75 |
|
76 HsWidgetHost::~HsWidgetHost() |
|
77 { |
|
78 } |
|
79 |
|
80 HsWidgetHost *HsWidgetHost::createInstance(HsWidgetData &widgetData, |
52 const QVariantHash &preferences) |
81 const QVariantHash &preferences) |
53 { |
82 { |
54 HsDatabase* db = HsDatabase::instance(); |
83 HsDatabase *db = HsDatabase::instance(); |
55 Q_ASSERT(db); |
|
56 |
84 |
57 if (db->insertWidget(widgetData)) { |
85 if (db->insertWidget(widgetData)) { |
58 db->setWidgetPreferences(widgetData.id, preferences); |
86 db->setWidgetPreferences(widgetData.id, preferences); |
59 return new HsWidgetHost(widgetData.id); |
87 return new HsWidgetHost(widgetData.id); |
60 } |
88 } else { |
61 |
89 return 0; |
62 return 0; |
90 } |
63 } |
91 } |
64 /*! |
92 |
65 Construct a widget host for the given \a databaseId. |
93 int HsWidgetHost::databaseId() const |
66 \a parent becomes the parent item for the host. |
94 { |
67 */ |
95 return mDatabaseId; |
68 HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) |
|
69 : HbWidget(parent), |
|
70 mWidget(0), |
|
71 mPage(0), |
|
72 mState(Unloaded), |
|
73 mDatabaseId(databaseId) |
|
74 { |
|
75 setFlags(QGraphicsItem::ItemClipsChildrenToShape); |
|
76 |
|
77 HsDatabase *db = HsDatabase::instance(); |
|
78 |
|
79 // Find the widget data. |
|
80 HsWidgetData data; |
|
81 data.id = mDatabaseId; |
|
82 if (!db->widget(data)) { |
|
83 return; |
|
84 } |
|
85 |
|
86 mUri = data.uri; |
|
87 |
|
88 // bind host to component |
|
89 HsWidgetComponent *component = HsWidgetComponentRegistry::instance()->component(mUri); |
|
90 connect(component, SIGNAL(uninstalled()), SLOT(onFinished())); |
|
91 connect(component, SIGNAL(aboutToUninstall()), SLOT(onAboutToUninstall())); |
|
92 connect(component, SIGNAL(updated()), SLOT(onUpdated())); |
|
93 connect(component, SIGNAL(unavailable()), SLOT(onUnavailable())); |
|
94 connect(component, SIGNAL(available()), SLOT(onAvailable())); |
|
95 |
|
96 /* TODO: Uncomment after the Qt bug has been fixed. |
|
97 QGraphicsDropShadowEffect *effect = |
|
98 new QGraphicsDropShadowEffect(this); |
|
99 effect->setColor(QColor(0, 0, 0, 150)); |
|
100 effect->setBlurRadius(5); |
|
101 effect->setOffset(3); |
|
102 setGraphicsEffect(effect); |
|
103 */ |
|
104 } |
|
105 |
|
106 /*! |
|
107 Destructor. |
|
108 */ |
|
109 HsWidgetHost::~HsWidgetHost() |
|
110 { |
|
111 } |
|
112 |
|
113 /*! |
|
114 Load hosted widget from plugin and validate it. |
|
115 Returns true if widget construction is successfull. |
|
116 */ |
|
117 bool HsWidgetHost::load() |
|
118 { |
|
119 if (mState != Unloaded) { |
|
120 return false; |
|
121 } |
|
122 if (mWidget) { |
|
123 return false; |
|
124 } |
|
125 |
|
126 |
|
127 // Create the hosted widget. |
|
128 QServiceManager manager; |
|
129 QServiceFilter filter("com.nokia.symbian.IHomeScreenWidget"); |
|
130 filter.setServiceName(mUri); |
|
131 QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter); |
|
132 if (interfaces.isEmpty()) { |
|
133 return false; |
|
134 } |
|
135 |
|
136 QObject *widgetObject = manager.loadInterface(interfaces.first()); |
|
137 mWidget = qobject_cast<QGraphicsWidget *>(widgetObject); |
|
138 |
|
139 if (!mWidget || |
|
140 !setMethod("onShow()", mOnShowMethod) || |
|
141 !setMethod("onHide()", mOnHideMethod)) { |
|
142 mWidget = 0; |
|
143 delete widgetObject; |
|
144 return false; |
|
145 } |
|
146 |
|
147 setProperty("isOnline", mIsOnlineProperty); |
|
148 setProperty("rootPath", mRootPathProperty); |
|
149 |
|
150 setMethod("isPannable(QGraphicsSceneMouseEvent*)", mIsPannable); |
|
151 setMethod("onInitialize()", mOnInitializeMethod); |
|
152 setMethod("onUninitialize()", mOnUninitializeMethod); |
|
153 |
|
154 if (hasSignal("setPreferences(const QStringList&)")) { |
|
155 connect(mWidget, SIGNAL(setPreferences(QStringList)), |
|
156 SLOT(onSetPreferences(QStringList))); |
|
157 } |
|
158 if (hasSignal("finished()")) { |
|
159 connect(mWidget, SIGNAL(finished()), |
|
160 SLOT(onFinished())); |
|
161 } |
|
162 if (hasSignal("error()")) { |
|
163 connect(mWidget, SIGNAL(error()), |
|
164 SLOT(onError())); |
|
165 } |
|
166 |
|
167 mWidget->installEventFilter(this); |
|
168 |
|
169 loadWidgetPresentation(); |
|
170 |
|
171 HsScene *scene = HsScene::instance(); |
|
172 setMaximumSize(scene->maximumWidgetSizeInPixels()); |
|
173 setMinimumSize(scene->minimumWidgetSizeInPixels()); |
|
174 |
|
175 mWidget->setParentItem(this); |
|
176 |
|
177 setNewSize(mWidget->size()); |
|
178 mState = Loaded; |
|
179 |
|
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; |
|
195 } |
96 } |
196 |
97 |
197 bool HsWidgetHost::setPage(HsPage *page) |
98 bool HsWidgetHost::setPage(HsPage *page) |
198 { |
99 { |
199 HsDatabase* db = HsDatabase::instance(); |
100 HsDatabase *db = HsDatabase::instance(); |
200 Q_ASSERT(db); |
101 |
201 |
|
202 HsWidgetData data; |
102 HsWidgetData data; |
203 data.id = mDatabaseId; |
103 data.id = mDatabaseId; |
204 if (db->widget(data)) { |
104 if (db->widget(data)) { |
205 if (!page) { |
105 if (!page) { |
206 data.pageId = -1; |
106 data.pageId = -1; |
215 } |
115 } |
216 |
116 |
217 mPage = page; |
117 mPage = page; |
218 return true; |
118 return true; |
219 } |
119 } |
220 |
120 |
221 HsPage *HsWidgetHost::page() const |
121 HsPage *HsWidgetHost::page() const |
222 { |
122 { |
223 return mPage; |
123 return mPage; |
224 } |
124 } |
225 |
125 |
226 /*! |
126 bool HsWidgetHost::isPannable(QGraphicsSceneMouseEvent *event) |
227 Returns true if this host has a valid widget set. |
127 { |
228 Otherwise, return false. |
128 bool result = false; |
229 */ |
129 mIsPannableMethod.invoke(mWidget, Q_RETURN_ARG(bool, result), Q_ARG(QGraphicsSceneMouseEvent *,event)); |
230 bool HsWidgetHost::isValid() const |
130 return result; |
231 { |
131 } |
232 return mWidget; |
132 |
233 } |
133 bool HsWidgetHost::loadPresentation() |
234 |
134 { |
235 /*! |
135 return loadPresentation(HsScene::orientation()); |
236 Returns database id |
136 } |
237 */ |
137 |
238 int HsWidgetHost::databaseId() const |
138 bool HsWidgetHost::loadPresentation(Qt::Orientation orientation) |
239 { |
139 { |
240 return mDatabaseId; |
140 HsDatabase *db = HsDatabase::instance(); |
241 } |
141 |
242 |
|
243 /*! |
|
244 Returns true if this the database operation succeeds, |
|
245 false otherwise |
|
246 */ |
|
247 bool HsWidgetHost::deleteFromDatabase() |
|
248 { |
|
249 HsDatabase *db = HsDatabase::instance(); |
|
250 |
|
251 if (!db->deleteWidget(mDatabaseId)) { |
|
252 return false; |
|
253 } |
|
254 |
|
255 mDatabaseId = -1; |
|
256 return true; |
|
257 } |
|
258 |
|
259 /*! |
|
260 Set widget presentation by using current values. |
|
261 Return true if successfull. |
|
262 */ |
|
263 bool HsWidgetHost::setWidgetPresentation() |
|
264 { |
|
265 HsDatabase *db = HsDatabase::instance(); |
|
266 Q_ASSERT(db); |
|
267 |
|
268 QString key = HsScene::orientation() == Qt::Vertical ? |
|
269 "portrait" : "landscape"; |
|
270 |
|
271 HsWidgetPresentationData data; |
142 HsWidgetPresentationData data; |
272 data.key = key; |
143 data.orientation = orientation; |
273 data.setPos(pos()); |
|
274 data.zValue = zValue(); |
|
275 data.widgetId = databaseId(); |
|
276 |
|
277 return db->setWidgetPresentation(data); |
|
278 } |
|
279 |
|
280 /*! |
|
281 Set widget presentation data. Return true if successfull. |
|
282 */ |
|
283 bool HsWidgetHost::setWidgetPresentationData(HsWidgetPresentationData &presentationData) |
|
284 { |
|
285 HsDatabase *db = HsDatabase::instance(); |
|
286 Q_ASSERT(db); |
|
287 |
|
288 presentationData.widgetId = mDatabaseId; |
|
289 return db->setWidgetPresentation(presentationData); |
|
290 } |
|
291 |
|
292 /*! |
|
293 Get widget presentation data matching given \a key. |
|
294 Data is returned on given empty \a presentationData. Return true if successfull |
|
295 */ |
|
296 bool HsWidgetHost::widgetPresentationData(const QString &key, |
|
297 HsWidgetPresentationData &presentationData) |
|
298 { |
|
299 HsDatabase *db = HsDatabase::instance(); |
|
300 Q_ASSERT(db); |
|
301 |
|
302 presentationData.key = key; |
|
303 presentationData.widgetId = mDatabaseId; |
|
304 return db->widgetPresentation(presentationData); |
|
305 } |
|
306 |
|
307 /*! |
|
308 Return HsWidgetPresentationData for given \a orientation |
|
309 */ |
|
310 HsWidgetPresentationData HsWidgetHost::widgetPresentation(Qt::Orientation orientation) |
|
311 { |
|
312 HsDatabase *db = HsDatabase::instance(); |
|
313 Q_ASSERT(db); |
|
314 |
|
315 QString key = orientation == Qt::Vertical ? |
|
316 "portrait" : "landscape"; |
|
317 |
|
318 HsWidgetPresentationData data; |
|
319 data.key = key; |
|
320 data.widgetId = mDatabaseId; |
|
321 if (db->widgetPresentation(data)) { |
|
322 return data; |
|
323 } else { |
|
324 return HsWidgetPresentationData(); |
|
325 } |
|
326 } |
|
327 |
|
328 /*! |
|
329 Load HsWidgetPresentationData for current orientation |
|
330 */ |
|
331 bool HsWidgetHost::loadWidgetPresentation() |
|
332 { |
|
333 HsDatabase *db = HsDatabase::instance(); |
|
334 |
|
335 QString key = HsScene::orientation() == Qt::Vertical ? |
|
336 "portrait" : "landscape"; |
|
337 |
|
338 HsWidgetPresentationData data; |
|
339 data.key = key; |
|
340 data.widgetId = mDatabaseId; |
144 data.widgetId = mDatabaseId; |
341 if (!db->widgetPresentation(data)) { |
145 if (!db->widgetPresentation(data)) { |
342 return false; |
146 return false; |
343 } |
147 } |
344 |
|
345 setPos(data.x, data.y); |
148 setPos(data.x, data.y); |
346 setZValue(data.zValue); |
149 setZValue(data.zValue); |
347 |
|
348 return true; |
150 return true; |
349 } |
151 } |
350 |
152 |
351 /*! |
153 bool HsWidgetHost::savePresentation() |
352 Delete HsWidgetPresentationData for given \a orientation. |
154 { |
353 Return true if successfull. |
155 return savePresentation(HsScene::orientation()); |
354 */ |
156 } |
355 bool HsWidgetHost::deleteWidgetPresentation(Qt::Orientation orientation) |
157 |
356 { |
158 bool HsWidgetHost::savePresentation(Qt::Orientation orientation) |
357 HsDatabase *db = HsDatabase::instance(); |
159 { |
358 Q_ASSERT(db); |
160 HsDatabase *db = HsDatabase::instance(); |
359 |
161 |
360 QString key = orientation == Qt::Vertical ? |
162 HsWidgetPresentationData data; |
361 "portrait" : "landscape"; |
163 data.orientation = orientation; |
362 |
164 data.setPos(pos()); |
363 return db->deleteWidgetPresentation(mDatabaseId, key); |
165 data.zValue = zValue(); |
364 } |
166 data.widgetId = mDatabaseId; |
365 /*! |
167 return db->setWidgetPresentation(data); |
366 Check wheter widget uses pan gestures |
168 } |
367 Return true if successfull. |
169 |
368 */ |
170 bool HsWidgetHost::savePresentation(HsWidgetPresentationData &presentation) |
369 bool HsWidgetHost::isPannable(QGraphicsSceneMouseEvent *event) |
171 { |
370 { |
172 HsDatabase *db = HsDatabase::instance(); |
371 bool ret(false); |
173 |
372 mIsPannable.invoke(mWidget,Q_RETURN_ARG(bool,ret),Q_ARG(QGraphicsSceneMouseEvent *,event)); |
174 presentation.widgetId = mDatabaseId; |
373 return ret; |
175 return db->setWidgetPresentation(presentation); |
374 } |
176 } |
375 /*! |
177 |
376 \fn void HsWidgetHost::widgetFinished() |
178 bool HsWidgetHost::getPresentation(HsWidgetPresentationData &presentation) |
377 This signal is emitted after the contained widget |
179 { |
378 reported is completion. |
180 HsDatabase *db = HsDatabase::instance(); |
379 */ |
181 |
380 |
182 presentation.widgetId = mDatabaseId; |
381 /*! |
183 return db->widgetPresentation(presentation); |
382 \fn void HsWidgetHost::widgetError() |
184 } |
383 This signal is emitted after the contained widget |
185 |
384 reported an error. |
186 bool HsWidgetHost::removePresentation(Qt::Orientation orientation) |
385 */ |
187 { |
386 |
188 HsDatabase *db = HsDatabase::instance(); |
387 /*! |
189 return db->deleteWidgetPresentation(mDatabaseId, orientation); |
388 \fn void HsWidgetHost::widgetResized() |
190 } |
389 This signal is emitted after the contained widget |
191 |
390 sends a resize event. |
192 void HsWidgetHost::startWidget(bool show) |
391 */ |
193 { |
392 /*! |
194 if (!mStateMachine->isRunning()) { |
393 \fn void HsWidgetHost::mousePressEventIgnored() |
195 mStateMachine->start(); |
394 This signal is emitted if managed widget ignores mouse press event |
196 // This is needed because QStateMachine::start() starts |
395 |
197 // the state machine asynchronously via the eventloop. |
396 */ |
198 // Here we want the machine to start synchronously. |
397 |
199 QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); |
398 /*! |
200 } |
399 Calls the widget's onInitialize() slot if the |
201 |
400 widget defines it. |
202 if (show) { |
401 */ |
203 emit event_startAndShow(); |
402 void HsWidgetHost::initializeWidget() |
204 } else { |
403 { |
205 emit event_startAndHide(); |
404 if (mState != Loaded) { |
206 } |
405 return; |
207 } |
406 } |
208 |
407 HsWidgetComponent *component = HsWidgetComponentRegistry::instance()->component(mUri); |
|
408 Q_ASSERT(component); |
|
409 mRootPathProperty.write(mWidget, component->rootPath()); |
|
410 setPreferencesToWidget(); |
|
411 setOnline(HsScene::instance()->isOnline()); |
|
412 mOnInitializeMethod.invoke(mWidget); |
|
413 |
|
414 if (mState != Finished && |
|
415 mState != Faulted) { |
|
416 mState = Initialized; |
|
417 } |
|
418 } |
|
419 |
|
420 /*! |
|
421 Calls the widget's onShow() slot if the |
|
422 widget defines it. |
|
423 */ |
|
424 void HsWidgetHost::showWidget() |
209 void HsWidgetHost::showWidget() |
425 { |
210 { |
426 if (mState != Initialized && |
211 emit event_show(); |
427 mState != Hidden ) { |
212 } |
428 return; |
213 |
429 } |
|
430 |
|
431 mOnShowMethod.invoke(mWidget); |
|
432 |
|
433 mState = Visible; |
|
434 } |
|
435 |
|
436 /*! |
|
437 Calls the widget's onHide() slot if the |
|
438 widget defines it. |
|
439 */ |
|
440 void HsWidgetHost::hideWidget() |
214 void HsWidgetHost::hideWidget() |
441 { |
215 { |
442 if (mState != Initialized && |
216 emit event_hide(); |
443 mState != Visible) { |
217 } |
444 return; |
218 |
445 } |
|
446 |
|
447 mOnHideMethod.invoke(mWidget); |
|
448 |
|
449 mState = Hidden; |
|
450 } |
|
451 |
|
452 /*! |
|
453 Calls the widget's onUninitialize() slot if the |
|
454 widget defines it. |
|
455 */ |
|
456 void HsWidgetHost::uninitializeWidget() |
|
457 { |
|
458 if (mState != Visible && |
|
459 mState != Hidden) { |
|
460 return; |
|
461 } |
|
462 |
|
463 mOnUninitializeMethod.invoke(mWidget); |
|
464 |
|
465 mState = Uninitialized; |
|
466 } |
|
467 |
|
468 /*! |
|
469 Calls the widget's widgetOnlineState property if the |
|
470 widget defines it. |
|
471 */ |
|
472 void HsWidgetHost::setOnline(bool online) |
219 void HsWidgetHost::setOnline(bool online) |
473 { |
220 { |
474 mIsOnlineProperty.write(mWidget, online); |
221 mIsOnlineProperty.write(mWidget, online); |
475 } |
222 } |
476 |
223 |
477 /*! |
224 void HsWidgetHost::remove() |
478 Starts the widget drag animation. |
225 { |
479 */ |
226 if (mStateMachine->isRunning()) { |
|
227 emit event_remove(); |
|
228 } else { |
|
229 action_remove(); |
|
230 deleteLater(); |
|
231 } |
|
232 } |
|
233 |
|
234 void HsWidgetHost::close() |
|
235 { |
|
236 if (mStateMachine->isRunning()) { |
|
237 emit event_close(); |
|
238 } else { |
|
239 deleteLater(); |
|
240 } |
|
241 } |
|
242 |
480 void HsWidgetHost::startDragEffect() |
243 void HsWidgetHost::startDragEffect() |
481 { |
244 { |
482 /* TODO: Uncomment after the Qt bug has been fixed. |
245 /* TODO: Uncomment after the Qt bug has been fixed. |
483 QGraphicsDropShadowEffect *effect = |
246 QGraphicsDropShadowEffect *effect = |
484 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
247 static_cast<QGraphicsDropShadowEffect *>(graphicsEffect()); |
529 animationGroup->addAnimation(animation); |
289 animationGroup->addAnimation(animation); |
530 */ |
290 */ |
531 |
291 |
532 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
292 animationGroup->start(QAbstractAnimation::DeleteWhenStopped); |
533 } |
293 } |
534 /*! |
294 |
535 Overwritten to stop event propogation |
295 bool HsWidgetHost::eventFilter(QObject *watched, QEvent *event) |
536 */ |
|
537 void HsWidgetHost::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) |
|
538 { |
|
539 Q_UNUSED(event) |
|
540 } |
|
541 /*! |
|
542 Overwritten to stop event propogation |
|
543 */ |
|
544 void HsWidgetHost::mouseMoveEvent(QGraphicsSceneMouseEvent *event) |
|
545 { |
|
546 Q_UNUSED(event) |
|
547 } |
|
548 /*! |
|
549 Overwritten to stop event propogation |
|
550 */ |
|
551 void HsWidgetHost::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
552 { |
|
553 Q_UNUSED(event) |
|
554 |
|
555 } |
|
556 /*! |
|
557 Overwritten to stop event propogation |
|
558 */ |
|
559 void HsWidgetHost::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { |
|
560 Q_UNUSED(event) |
|
561 } |
|
562 /*! |
|
563 Filters resize events from widgets and resizes inside max/min size boundaries if needed. |
|
564 */ |
|
565 bool HsWidgetHost::eventFilter(QObject *obj, QEvent *event) |
|
566 { |
296 { |
567 if (event->type() == QEvent::GraphicsSceneResize ) { |
297 if (event->type() == QEvent::GraphicsSceneResize ) { |
568 QGraphicsSceneResizeEvent *resizeEvent = static_cast<QGraphicsSceneResizeEvent*>(event); |
298 QGraphicsSceneResizeEvent *resizeEvent = |
|
299 static_cast<QGraphicsSceneResizeEvent *>(event); |
569 setNewSize(resizeEvent->newSize()); |
300 setNewSize(resizeEvent->newSize()); |
570 emit widgetResized(this); |
301 emit resized(); |
571 return true; |
302 } |
572 } else { |
303 return HbWidget::eventFilter(watched, event); |
573 // standard event processing |
304 } |
574 return HbWidget::eventFilter(obj, event); |
305 |
575 } |
306 void HsWidgetHost::setupEffects() |
576 } |
307 { |
577 |
308 /* TODO: Uncomment after the Qt bug has been fixed. |
578 /*! |
309 QGraphicsDropShadowEffect *effect = |
579 Checks if a property with the given \a name |
310 new QGraphicsDropShadowEffect(this); |
580 in the contained widget. If the property exists the \a |
311 effect->setColor(QColor(0, 0, 0, 150)); |
581 metaProperty is made to reference to it. Returns true if |
312 effect->setBlurRadius(5); |
582 the property was found. Otherwise, returns false. |
313 effect->setOffset(3); |
583 */ |
314 setGraphicsEffect(effect); |
|
315 */ |
|
316 } |
|
317 |
|
318 void HsWidgetHost::setupStates() |
|
319 { |
|
320 // State machine |
|
321 |
|
322 mStateMachine = new QStateMachine(this); |
|
323 mStateMachine->setAnimated(false); |
|
324 |
|
325 // States |
|
326 |
|
327 QState *state_component = new QState; |
|
328 QState *state_unloaded = new QState(state_component); |
|
329 QState *state_running = new QState(state_component); |
|
330 QState *state_show = new QState(state_running); |
|
331 QState *state_hide = new QState(state_running); |
|
332 QState *state_finished = new QState; |
|
333 QState *state_faulted = new QState; |
|
334 QState *state_remove = new QState; |
|
335 QFinalState *state_final = new QFinalState; |
|
336 |
|
337 mStateMachine->addState(state_component); |
|
338 mStateMachine->addState(state_finished); |
|
339 mStateMachine->addState(state_faulted); |
|
340 mStateMachine->addState(state_remove); |
|
341 mStateMachine->addState(state_final); |
|
342 |
|
343 mStateMachine->setInitialState(state_component); |
|
344 state_component->setInitialState(state_unloaded); |
|
345 state_running->setInitialState(state_hide); |
|
346 |
|
347 // Transitions |
|
348 |
|
349 state_component->addTransition( |
|
350 this, SIGNAL(event_close()), state_final); |
|
351 state_component->addTransition( |
|
352 this, SIGNAL(event_remove()), state_remove); |
|
353 state_component->addTransition( |
|
354 this, SIGNAL(event_finished()), state_finished); |
|
355 state_component->addTransition( |
|
356 this, SIGNAL(event_faulted()), state_faulted); |
|
357 |
|
358 state_unloaded->addTransition( |
|
359 this, SIGNAL(event_startAndShow()), state_show); |
|
360 state_unloaded->addTransition( |
|
361 this, SIGNAL(event_startAndHide()), state_hide); |
|
362 |
|
363 state_running->addTransition( |
|
364 this, SIGNAL(event_unload()), state_unloaded); |
|
365 |
|
366 state_show->addTransition( |
|
367 this, SIGNAL(event_hide()), state_hide); |
|
368 |
|
369 state_hide->addTransition( |
|
370 this, SIGNAL(event_show()), state_show); |
|
371 |
|
372 state_finished->addTransition( |
|
373 this, SIGNAL(event_remove()), state_remove); |
|
374 state_finished->addTransition( |
|
375 this, SIGNAL(event_close()), state_final); |
|
376 |
|
377 state_faulted->addTransition( |
|
378 this, SIGNAL(event_remove()), state_remove); |
|
379 state_faulted->addTransition( |
|
380 this, SIGNAL(event_close()), state_final); |
|
381 |
|
382 state_remove->addTransition(state_final); |
|
383 |
|
384 // Actions |
|
385 |
|
386 ENTRY_ACTION(state_component, action_connectComponent) |
|
387 EXIT_ACTION(state_component, action_disconnectComponent) |
|
388 |
|
389 ENTRY_ACTION(state_running, action_load) |
|
390 ENTRY_ACTION(state_running, action_initialize) |
|
391 EXIT_ACTION(state_running, action_uninitialize) |
|
392 EXIT_ACTION(state_running, action_unload) |
|
393 |
|
394 ENTRY_ACTION(state_show, action_show) |
|
395 |
|
396 ENTRY_ACTION(state_hide, action_hide) |
|
397 |
|
398 ENTRY_ACTION(state_finished, action_finished) |
|
399 |
|
400 ENTRY_ACTION(state_faulted, action_faulted) |
|
401 |
|
402 ENTRY_ACTION(state_remove, action_remove) |
|
403 |
|
404 // Delete on finish. |
|
405 |
|
406 connect(mStateMachine, SIGNAL(finished()), SLOT(deleteLater()), |
|
407 Qt::QueuedConnection); |
|
408 } |
|
409 |
584 bool HsWidgetHost::setProperty(const char *name, QMetaProperty &property) |
410 bool HsWidgetHost::setProperty(const char *name, QMetaProperty &property) |
585 { |
411 { |
586 const QMetaObject *object = mWidget->metaObject(); |
412 const QMetaObject *object = mWidget->metaObject(); |
587 int index = object->indexOfProperty(name); |
413 int index = object->indexOfProperty(name); |
588 property = object->property(index); |
414 property = object->property(index); |
589 return index >= 0; |
415 return index >= 0; |
590 } |
416 } |
591 |
417 |
592 /*! |
|
593 Checks if a slot with the given \a signature exists |
|
594 in the contained widget. If the slot exists the \a |
|
595 method is made to reference to it. Returns true if |
|
596 the slot was found. Otherwise, returns false. |
|
597 */ |
|
598 bool HsWidgetHost::setMethod(const char *signature, QMetaMethod &method) |
418 bool HsWidgetHost::setMethod(const char *signature, QMetaMethod &method) |
599 { |
419 { |
600 const QMetaObject *object = mWidget->metaObject(); |
420 const QMetaObject *object = mWidget->metaObject(); |
601 int index = object->indexOfMethod( |
421 int index = object->indexOfMethod( |
602 QMetaObject::normalizedSignature(signature)); |
422 QMetaObject::normalizedSignature(signature)); |
603 method = object->method(index); |
423 method = object->method(index); |
604 return index >= 0; |
424 return index >= 0; |
605 } |
425 } |
606 |
426 |
607 /*! |
|
608 Returns true if a signal with the given \a signature |
|
609 exists in the contained widget. Otherwise, returns |
|
610 false. |
|
611 */ |
|
612 bool HsWidgetHost::hasSignal(const char *signature) |
427 bool HsWidgetHost::hasSignal(const char *signature) |
613 { |
428 { |
614 const QMetaObject *object = mWidget->metaObject(); |
429 const QMetaObject *object = mWidget->metaObject(); |
615 int index = object->indexOfSignal( |
430 int index = object->indexOfSignal( |
616 QMetaObject::normalizedSignature(signature)); |
431 QMetaObject::normalizedSignature(signature)); |
617 return index >= 0; |
432 return index >= 0; |
618 } |
433 } |
619 /*! |
434 |
620 Returns true if fetching widget preferences from db and setting those |
435 void HsWidgetHost::setNewSize(const QSizeF &size) |
621 to widget is successfull |
436 { |
622 */ |
437 resize(size); |
|
438 setPreferredSize(size); |
|
439 } |
|
440 |
623 bool HsWidgetHost::setPreferencesToWidget() |
441 bool HsWidgetHost::setPreferencesToWidget() |
624 { |
442 { |
625 HsDatabase *db = HsDatabase::instance(); |
443 HsDatabase *db = HsDatabase::instance(); |
626 Q_ASSERT(db); |
444 |
627 |
|
628 QVariantHash preferences; |
445 QVariantHash preferences; |
629 if (!db->widgetPreferences(mDatabaseId, preferences)) { |
446 if (!db->widgetPreferences(mDatabaseId, preferences)) { |
630 return false; |
447 return false; |
631 } |
448 } |
632 |
449 |
633 QStringList names = preferences.keys(); |
450 QStringList names = preferences.keys(); |
634 foreach(QString name, names) { |
451 foreach (QString name, names) { |
635 mWidget->setProperty(name.toLatin1(), |
452 mWidget->setProperty(name.toLatin1(), |
636 preferences.value(name)); |
453 preferences.value(name)); |
637 } |
454 } |
638 |
455 |
639 return true; |
456 return true; |
640 } |
457 } |
641 |
458 |
642 /*! |
459 void HsWidgetHost::action_connectComponent() |
643 Resizes and sets preferred size for widget layouts |
460 { |
644 */ |
461 HsDatabase *db = HsDatabase::instance(); |
645 void HsWidgetHost::setNewSize(const QSizeF &newSize) |
462 |
646 { |
463 HsWidgetData data; |
647 resize(newSize); |
464 data.id = mDatabaseId; |
648 setPreferredSize(newSize); |
465 if (!db->widget(data)) { |
649 } |
466 emit event_faulted(); |
650 |
467 return; |
651 /*! |
468 } |
652 This slot is connected to the contained widget's |
469 |
653 setPreferences() signal, if it was defined for |
470 mComponent = HsWidgetComponentRegistry::instance()->component(data.uri); |
654 the widget. The widget emits the signal for persisting |
471 |
655 its preferences named with \a names. The given |
472 connect(mComponent, SIGNAL(aboutToUninstall()), SIGNAL(event_unload())); |
656 preferences are read, validated, and written to |
473 connect(mComponent, SIGNAL(uninstalled()), SIGNAL(event_finished())); |
657 the database. |
474 connect(mComponent, SIGNAL(unavailable()), SIGNAL(event_unload())); |
658 */ |
475 connect(mComponent, SIGNAL(unavailable()), SIGNAL(unavailable())); |
|
476 connect(mComponent, SIGNAL(available()), SIGNAL(available())); |
|
477 connect(mComponent, SIGNAL(updated()), SIGNAL(available())); |
|
478 } |
|
479 |
|
480 void HsWidgetHost::action_disconnectComponent() |
|
481 { |
|
482 mComponent->disconnect(this); |
|
483 } |
|
484 |
|
485 void HsWidgetHost::action_load() |
|
486 { |
|
487 QServiceManager manager; |
|
488 QServiceFilter filter("com.nokia.symbian.IHomeScreenWidget"); |
|
489 filter.setServiceName(mComponent->uri()); |
|
490 QList<QServiceInterfaceDescriptor> interfaces = manager.findInterfaces(filter); |
|
491 if (interfaces.isEmpty()) { |
|
492 emit event_faulted(); |
|
493 return; |
|
494 } |
|
495 |
|
496 QObject *widgetObject = manager.loadInterface(interfaces.first()); |
|
497 mWidget = qobject_cast<QGraphicsWidget *>(widgetObject); |
|
498 |
|
499 if (!mWidget || |
|
500 !setMethod("onShow()", mOnShowMethod) || |
|
501 !setMethod("onHide()", mOnHideMethod)) { |
|
502 mWidget = 0; |
|
503 delete widgetObject; |
|
504 emit event_faulted(); |
|
505 return; |
|
506 } |
|
507 |
|
508 setMethod("onInitialize()", mOnInitializeMethod); |
|
509 setMethod("onUninitialize()", mOnUninitializeMethod); |
|
510 setMethod("isPannable(QGraphicsSceneMouseEvent*)", mIsPannableMethod); |
|
511 |
|
512 setProperty("isOnline", mIsOnlineProperty); |
|
513 setProperty("rootPath", mRootPathProperty); |
|
514 |
|
515 if (hasSignal("setPreferences(const QStringList&)")) { |
|
516 connect(mWidget, SIGNAL(setPreferences(QStringList)), |
|
517 SLOT(onSetPreferences(QStringList))); |
|
518 } |
|
519 if (hasSignal("finished()")) { |
|
520 connect(mWidget, SIGNAL(finished()), |
|
521 SLOT(onFinished())); |
|
522 } |
|
523 if (hasSignal("error()")) { |
|
524 connect(mWidget, SIGNAL(error()), |
|
525 SLOT(onError())); |
|
526 } |
|
527 |
|
528 mWidget->installEventFilter(this); |
|
529 |
|
530 HsScene *scene = HsScene::instance(); |
|
531 setMaximumSize(scene->maximumWidgetSizeInPixels()); |
|
532 setMinimumSize(scene->minimumWidgetSizeInPixels()); |
|
533 |
|
534 loadPresentation(); |
|
535 |
|
536 mWidget->setParentItem(this); |
|
537 |
|
538 setNewSize(mWidget->size()); |
|
539 } |
|
540 |
|
541 void HsWidgetHost::action_unload() |
|
542 { |
|
543 delete mWidget; |
|
544 mWidget = 0; |
|
545 |
|
546 mOnInitializeMethod = QMetaMethod(); |
|
547 mOnShowMethod = QMetaMethod(); |
|
548 mOnHideMethod = QMetaMethod(); |
|
549 mOnUninitializeMethod = QMetaMethod(); |
|
550 mIsPannableMethod = QMetaMethod(); |
|
551 mIsOnlineProperty = QMetaProperty(); |
|
552 mRootPathProperty = QMetaProperty(); |
|
553 } |
|
554 |
|
555 void HsWidgetHost::action_initialize() |
|
556 { |
|
557 mRootPathProperty.write(mWidget, mComponent->rootPath()); |
|
558 setPreferencesToWidget(); |
|
559 setOnline(HsScene::instance()->isOnline()); |
|
560 mOnInitializeMethod.invoke(mWidget); |
|
561 } |
|
562 |
|
563 void HsWidgetHost::action_uninitialize() |
|
564 { |
|
565 mOnUninitializeMethod.invoke(mWidget); |
|
566 } |
|
567 |
|
568 void HsWidgetHost::action_show() |
|
569 { |
|
570 if (!mIsFinishing) { |
|
571 mOnShowMethod.invoke(mWidget); |
|
572 } |
|
573 } |
|
574 |
|
575 void HsWidgetHost::action_hide() |
|
576 { |
|
577 if (!mIsFinishing) { |
|
578 mOnHideMethod.invoke(mWidget); |
|
579 } |
|
580 } |
|
581 |
|
582 void HsWidgetHost::action_finished() |
|
583 { |
|
584 emit finished(); |
|
585 } |
|
586 |
|
587 void HsWidgetHost::action_faulted() |
|
588 { |
|
589 emit faulted(); |
|
590 } |
|
591 |
|
592 void HsWidgetHost::action_remove() |
|
593 { |
|
594 HsDatabase *db = HsDatabase::instance(); |
|
595 |
|
596 db->deleteWidget(mDatabaseId); |
|
597 mDatabaseId = -1; |
|
598 } |
|
599 |
|
600 void HsWidgetHost::onFinished() |
|
601 { |
|
602 mIsFinishing = true; |
|
603 emit event_finished(); |
|
604 } |
|
605 |
|
606 void HsWidgetHost::onError() |
|
607 { |
|
608 mIsFinishing = true; |
|
609 emit event_faulted(); |
|
610 } |
|
611 |
659 void HsWidgetHost::onSetPreferences(const QStringList &names) |
612 void HsWidgetHost::onSetPreferences(const QStringList &names) |
660 { |
613 { |
661 if (names.isEmpty()) { |
614 if (names.isEmpty()) { |
662 return; |
615 return; |
663 } |
616 } |