diff -r 30f14686fb04 -r 2b1b11a301d2 homescreenapp/hsdomainmodel/src/hswidgethost.cpp --- a/homescreenapp/hsdomainmodel/src/hswidgethost.cpp Wed Jun 23 18:03:36 2010 +0300 +++ b/homescreenapp/hsdomainmodel/src/hswidgethost.cpp Tue Jul 06 14:06:53 2010 +0300 @@ -32,15 +32,18 @@ #include #include +#include #include "hsdatabase.h" #include "hsdomainmodeldatastructures.h" #include "hsscene.h" #include "hspage.h" #include "hswidgethost.h" +#include "hswidgettoucharea.h" #include "hswidgetcomponentregistry.h" #include "hswidgetcomponent.h" #include "hsconfiguration.h" +#include "hscontentservice.h" // Helper macros for connecting state entry and exit actions. #define ENTRY_ACTION(state, action) \ @@ -54,11 +57,12 @@ /*! \class HsWidgetHost \ingroup group_hsdomainmodel - \brief + \brief Each widget is controlled by the home screen framework through a widget host. */ /*! - + Constructs a new widget host with given \a databaseId and + \a parent item. */ HsWidgetHost::HsWidgetHost(int databaseId, QGraphicsItem *parent) : HbWidget(parent), @@ -78,15 +82,24 @@ grabGesture(Qt::PinchGesture); grabGesture(Qt::SwipeGesture); grabGesture(Qt::CustomGesture); - + + setupTouchArea(); setupEffects(); setupStates(); } +/*! + Destructor. +*/ HsWidgetHost::~HsWidgetHost() { } +/*! + Creates a new widget host instance based on the give + \a widgetData and \a preferences. Returns the created + instance. Return 0 in failure cases. +*/ HsWidgetHost *HsWidgetHost::createInstance(HsWidgetData &widgetData, const QVariantHash &preferences) { @@ -100,11 +113,18 @@ } } +/*! + Returns the databaseId. +*/ int HsWidgetHost::databaseId() const { return mDatabaseId; } +/*! + Sets the containing \a page for this widget host. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::setPage(HsPage *page) { HsDatabase *db = HsDatabase::instance(); @@ -128,23 +148,28 @@ return true; } +/*! + Returns the containing page for this widget. Returns 0 + if this widget has no containg page. +*/ HsPage *HsWidgetHost::page() const { return mPage; } -bool HsWidgetHost::isPannable(QGraphicsSceneMouseEvent *event) -{ - bool result = false; - mIsPannableMethod.invoke(mWidget, Q_RETURN_ARG(bool, result), Q_ARG(QGraphicsSceneMouseEvent *,event)); - return result; -} - +/*! + Loads presentation based on the current orientation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::loadPresentation() { return loadPresentation(HsScene::orientation()); } +/*! + Loads presentation based on the given \a orientation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::loadPresentation(Qt::Orientation orientation) { HsDatabase *db = HsDatabase::instance(); @@ -160,11 +185,19 @@ return true; } +/*! + Saves the current presentation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::savePresentation() { return savePresentation(HsScene::orientation()); } +/*! + Saves the current presentation for the given \a orientation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::savePresentation(Qt::Orientation orientation) { HsDatabase *db = HsDatabase::instance(); @@ -177,6 +210,10 @@ return db->setWidgetPresentation(data); } +/*! + Saves the given presentation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::savePresentation(HsWidgetPresentationData &presentation) { HsDatabase *db = HsDatabase::instance(); @@ -185,6 +222,11 @@ return db->setWidgetPresentation(presentation); } +/*! + Fills the \a presentation based on the orientation field in + the given \a presentation. Returns true on success, otherwise + returns false. +*/ bool HsWidgetHost::getPresentation(HsWidgetPresentationData &presentation) { HsDatabase *db = HsDatabase::instance(); @@ -193,12 +235,121 @@ return db->widgetPresentation(presentation); } +/*! + Removes the presentation for the given \a orientation. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::removePresentation(Qt::Orientation orientation) { HsDatabase *db = HsDatabase::instance(); return db->deleteWidgetPresentation(mDatabaseId, orientation); } +/*! + Reimplemented from QGraphicsItem. Returns the shape of the + this widget host. The shape is computed based on the contained + widget. +*/ +QPainterPath HsWidgetHost::shape() const +{ + QPainterPath path; + + if (mWidget) { + QRectF currRect = rect(); + path = mWidget->shape(); + + QRectF pathRect(path.boundingRect()); + + if (pathRect.width() > currRect.width() + || pathRect.height() > currRect.height()) { + QPainterPath newPath(currRect.topLeft()); + newPath.addRect(currRect); + path = path.intersected(newPath); + } + } + return path; +} + +/*! + \fn HsWidgetHost::event_startAndShow() + Initiates a transition to show state. +*/ + +/*! + \fn HsWidgetHost::event_startAndHide() + Initiates a transition to hide state. +*/ + +/*! + \fn HsWidgetHost::event_unload() + Initiates a transition to unloaded state. +*/ + +/*! + \fn HsWidgetHost::event_show() + Initiates a transition to show state. +*/ + +/*! + \fn HsWidgetHost::event_hide() + Initiates a transition to hide state. +*/ + +/*! + \fn HsWidgetHost::event_remove() + Initiates a transition to remove state. +*/ + +/*! + \fn HsWidgetHost::event_close() + Initiates a transition to final state. +*/ + +/*! + \fn HsWidgetHost::event_finished() + Initiates a transition to finished state. +*/ + +/*! + \fn HsWidgetHost::event_faulted() + Initiates a transition to faulted state. +*/ + +/*! + \fn HsWidgetHost::finished() + Notifies the home screen framework that this widget + host has moved to finished state. +*/ + +/*! + \fn HsWidgetHost::faulted() + Notifies the home screen framework that this widget + host has moved to faulted state. +*/ + +/*! + \fn HsWidgetHost::resized() + Notifies the home screen framework that this widget + host has resized itself. +*/ + +/*! + \fn HsWidgetHost::available() + Notifies the home screen framework that this widget + is now available. +*/ + +/*! + \fn HsWidgetHost::unavailable() + Notifies the home screen framework that this widget + is temporarily unavailable. +*/ + + +/*! + Starts the widget. The \a show parameter defines the + visibility of the widget. +*/ void HsWidgetHost::startWidget(bool show) { if (!mStateMachine->isRunning()) { @@ -216,21 +367,35 @@ } } +/*! + Puts the contained widget into show state. +*/ void HsWidgetHost::showWidget() { emit event_show(); } - + +/*! + Puts the contained widget into hidden state. +*/ void HsWidgetHost::hideWidget() { emit event_hide(); } +/*! + Notifies the conained widget about \a online + status changes. +*/ void HsWidgetHost::setOnline(bool online) { mIsOnlineProperty.write(mWidget, online); } +/*! + Deletes this widget instance, including the + database entries. +*/ void HsWidgetHost::remove() { if (mStateMachine->isRunning()) { @@ -241,6 +406,10 @@ } } +/*! + Deletes this widget instance, leaving the + database entries untouched. +*/ void HsWidgetHost::close() { if (mStateMachine->isRunning()) { @@ -250,6 +419,9 @@ } } +/*! + Starts the drag effect. +*/ void HsWidgetHost::startDragEffect() { /* TODO: Uncomment after the Qt bug has been fixed. @@ -277,6 +449,9 @@ animationGroup->start(QAbstractAnimation::DeleteWhenStopped); } +/*! + Starts the drop effect. +*/ void HsWidgetHost::startDropEffect() { /* TODO: Uncomment after the Qt bug has been fixed. @@ -302,6 +477,10 @@ animationGroup->start(QAbstractAnimation::DeleteWhenStopped); } +/*! + Reimplemented from QObject for monitoring changes in + contained widget's size. +*/ bool HsWidgetHost::eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::GraphicsSceneResize ) { @@ -313,6 +492,50 @@ return HbWidget::eventFilter(watched, event); } +/*! + Reimplemented from HbWidget for pan gesture handling. +*/ +void HsWidgetHost::gestureEvent(QGestureEvent *event) +{ + HsScene *scene = HsScene::instance(); + QGesture *gesture = event->gesture(Qt::PanGesture); + if (gesture) { + switch (gesture->state()) { + case Qt::GestureStarted: + grabMouse(); + emit scene->pagePanStarted(event); + break; + case Qt::GestureUpdated: + emit scene->pagePanUpdated(event); + break; + case Qt::GestureFinished: + case Qt::GestureCanceled: + ungrabMouse(); + emit scene->pagePanFinished(event); + break; + default: + break; + } + } +} + +/*! + \fn HsWidgetHost::mousePressEvent(QGraphicsSceneMouseEvent *) + Reimplemented from QGraphicsItem for eating all mouse presses. +*/ + +/*! + Configures the touch are for this widget host. +*/ +void HsWidgetHost::setupTouchArea() +{ + mTouchArea = new HsWidgetTouchArea(this); + mTouchArea->setZValue(1); +} + +/*! + Configures the effects for this widget host. +*/ void HsWidgetHost::setupEffects() { /* TODO: Uncomment after the Qt bug has been fixed. @@ -325,6 +548,9 @@ */ } +/*! + Configures the state machine for this widget host. +*/ void HsWidgetHost::setupStates() { // State machine @@ -409,6 +635,7 @@ ENTRY_ACTION(state_faulted, action_faulted) + ENTRY_ACTION(state_remove, action_notifyRemove) ENTRY_ACTION(state_remove, action_remove) // Delete on finish. @@ -417,6 +644,10 @@ Qt::QueuedConnection); } +/*! + Assigns the meta \a property based on the given property \a name. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::setProperty(const char *name, QMetaProperty &property) { const QMetaObject *object = mWidget->metaObject(); @@ -425,6 +656,10 @@ return index >= 0; } +/*! + Assigns the meta \a method based on the given method \a signature. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::setMethod(const char *signature, QMetaMethod &method) { const QMetaObject *object = mWidget->metaObject(); @@ -434,6 +669,10 @@ return index >= 0; } +/*! + Checks if the contained widget has implemented the + signal with the given \a signature. +*/ bool HsWidgetHost::hasSignal(const char *signature) { const QMetaObject *object = mWidget->metaObject(); @@ -442,12 +681,20 @@ return index >= 0; } +/*! + Resizes this widget host to the given \a size. +*/ void HsWidgetHost::setNewSize(const QSizeF &size) { + mTouchArea->resize(size); resize(size); setPreferredSize(size); } +/*! + Assigns preferences for the contained widget. + Returns true on success, otherwise returns false. +*/ bool HsWidgetHost::setPreferencesToWidget() { HsDatabase *db = HsDatabase::instance(); @@ -466,6 +713,10 @@ return true; } +/*! + Connects this widget host for monitoring changes + in its widget component. +*/ void HsWidgetHost::action_connectComponent() { HsDatabase *db = HsDatabase::instance(); @@ -487,11 +738,18 @@ connect(mComponent, SIGNAL(updated()), SIGNAL(available())); } +/*! + Disconnects this widget host from its widget component. +*/ void HsWidgetHost::action_disconnectComponent() { mComponent->disconnect(this); } +/*! + Loads the contained widget from a widget plugin and + connects to it's meta interface. +*/ void HsWidgetHost::action_load() { QServiceManager manager; @@ -517,22 +775,21 @@ setMethod("onInitialize()", mOnInitializeMethod); setMethod("onUninitialize()", mOnUninitializeMethod); - setMethod("isPannable(QGraphicsSceneMouseEvent*)", mIsPannableMethod); - + setProperty("isOnline", mIsOnlineProperty); setProperty("rootPath", mRootPathProperty); if (hasSignal("setPreferences(const QStringList&)")) { connect(mWidget, SIGNAL(setPreferences(QStringList)), - SLOT(onSetPreferences(QStringList))); + SLOT(onSetPreferences(QStringList)), Qt::QueuedConnection); } if (hasSignal("finished()")) { connect(mWidget, SIGNAL(finished()), - SLOT(onFinished())); + SLOT(onFinished()), Qt::QueuedConnection); } if (hasSignal("error()")) { connect(mWidget, SIGNAL(error()), - SLOT(onError())); + SLOT(onError()), Qt::QueuedConnection); } mWidget->installEventFilter(this); @@ -545,22 +802,36 @@ mWidget->setParentItem(this); setNewSize(mWidget->size()); + + QString objName(mComponent->uri()); + objName.append(":"); + objName.append(QString::number(mDatabaseId)); + setObjectName(objName); } +/*! + Unloads the contained widget. +*/ void HsWidgetHost::action_unload() { delete mWidget; mWidget = 0; - + // This is needed because QServicePluginCleanup is + // deleted asynchronously via the eventloop (deleteLater). + // Here we want the plugin to unload synchronously. + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + mOnInitializeMethod = QMetaMethod(); mOnShowMethod = QMetaMethod(); mOnHideMethod = QMetaMethod(); - mOnUninitializeMethod = QMetaMethod(); - mIsPannableMethod = QMetaMethod(); + mOnUninitializeMethod = QMetaMethod(); mIsOnlineProperty = QMetaProperty(); mRootPathProperty = QMetaProperty(); } +/*! + Initializes the contained widget. +*/ void HsWidgetHost::action_initialize() { mRootPathProperty.write(mWidget, mComponent->rootPath()); @@ -569,11 +840,17 @@ mOnInitializeMethod.invoke(mWidget); } +/*! + Uninitializes the contained widget. +*/ void HsWidgetHost::action_uninitialize() { mOnUninitializeMethod.invoke(mWidget); } +/*! + Puts the contained widget into show state. +*/ void HsWidgetHost::action_show() { if (!mIsFinishing) { @@ -581,6 +858,9 @@ } } +/*! + Puts the contained widget into hidden state. +*/ void HsWidgetHost::action_hide() { if (!mIsFinishing) { @@ -588,16 +868,28 @@ } } +/*! + Notifies the home screen framework that this widget + host has moved to finished state. +*/ void HsWidgetHost::action_finished() { emit finished(); } +/*! + Notifies the home screen framework that this widget + host has moved to faulted state. +*/ void HsWidgetHost::action_faulted() { emit faulted(); } +/*! + Removes the contained widget from the home screen + database. +*/ void HsWidgetHost::action_remove() { HsDatabase *db = HsDatabase::instance(); @@ -606,18 +898,42 @@ mDatabaseId = -1; } +/*! + Notifies the widget removal through the content service. +*/ +void HsWidgetHost::action_notifyRemove() +{ + HsDatabase *db = HsDatabase::instance(); + QVariantHash preferences; + db->widgetPreferences(mDatabaseId, preferences); + HsContentService::instance()->emitWidgetRemoved(mComponent->uri(), preferences); +} + +/*! + Handles contained widget's finished event. + Moves this widget host to finished state. +*/ void HsWidgetHost::onFinished() { mIsFinishing = true; emit event_finished(); } +/*! + Handles contained widget's error event. + Moves this widget host to faulted state. +*/ void HsWidgetHost::onError() { mIsFinishing = true; emit event_faulted(); } +/*! + Handles contained widget's setPreferences event. + Stores the preferences for the given \a names to + the home screen database. +*/ void HsWidgetHost::onSetPreferences(const QStringList &names) { if (names.isEmpty()) {