--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlewidget.cpp Fri Mar 19 09:27:44 2010 +0200
@@ -0,0 +1,426 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsLinearLayout>
+#include <QDir>
+
+#include <HbMainWindow>
+#include <HbInputMethod>
+
+#include "hsidlewidget.h"
+#include "hsscene.h"
+#include "hspage.h"
+#include "hswidgethost.h"
+#include "hswallpaper.h"
+#include "hstrashbinwidget.h"
+#include "hspageindicator.h"
+#include "hsdocumentloader.h"
+
+namespace
+{
+ const char CONTROL_LAYER_DOCML_FILE[] = "controllayer.docml";
+ const char CONTROL_LAYER[] = "controlLayer";
+ const char TRASH_BIN[] = "trashBin";
+ const char PAGE_INDICATOR[] = "pageIndicator";
+}
+
+/*!
+ \class HsIdleWidget
+ \ingroup group_hshomescreenstateplugin
+ \brief View part of the home screen idle state.
+
+ Maintains the idle view ui layers and takes care of
+ receiving user input and communicating it to the idle
+ state for further processing.
+*/
+
+/*!
+ Constructs a new idle widget with the given \a parent.
+*/
+HsIdleWidget::HsIdleWidget(QGraphicsItem *parent)
+ : HbWidget(parent),
+ mControlLayer(0), mPageLayer(0), mSceneLayer(0),
+ mDelayedPressEvent(0),
+ mTrashBin(0), mPageIndicator(0)
+{
+ setFlag(ItemHasNoContents);
+
+ loadControlLayer();
+
+ QGraphicsLinearLayout *linearLayout = 0;
+
+ linearLayout = new QGraphicsLinearLayout(Qt::Horizontal);
+ linearLayout->setContentsMargins(0, 0, 0, 0);
+ linearLayout->setSpacing(0);
+ mPageLayer = new HbWidget(this);
+ mPageLayer->setLayout(linearLayout);
+ mPageLayer->setZValue(1);
+
+ linearLayout = new QGraphicsLinearLayout(Qt::Horizontal);
+ linearLayout->setContentsMargins(0, 0, 0, 0);
+ linearLayout->setSpacing(0);
+ mSceneLayer = new HbWidget(this);
+ mSceneLayer->setLayout(linearLayout);
+ mSceneLayer->setZValue(0);
+}
+
+/*!
+ Destroys this idle widget.
+*/
+HsIdleWidget::~HsIdleWidget()
+{
+ clearDelayedPress();
+
+ QList<HsPage *> pages = HsScene::instance()->pages();
+ foreach (HsPage *page, pages) {
+ page->setParentItem(0);
+ if (page->scene()) {
+ page->scene()->removeItem(page);
+ }
+ }
+
+ HsWallpaper *wallpaper = HsScene::instance()->wallpaper();
+ wallpaper->setParentItem(0);
+ if (wallpaper->scene()) {
+ wallpaper->scene()->removeItem(wallpaper);
+ }
+}
+
+/*!
+ Layouts the ui layers according to the given \a rect.
+*/
+void HsIdleWidget::setGeometry(const QRectF &rect)
+{
+ int n = HsScene::instance()->pages().count();
+ mControlLayer->resize(rect.size());
+ mPageLayer->resize(n * rect.width(), rect.height());
+ mSceneLayer->resize(2 * rect.width(), rect.height());
+ HbWidget::setGeometry(rect);
+}
+
+/*!
+ Stores the given mouse press \a event.
+*/
+void HsIdleWidget::captureDelayedPress(QGraphicsSceneMouseEvent *event)
+{
+ if (event) {
+ mDelayedPressEvent = new QMouseEvent(QEvent::MouseButtonPress,
+ event->scenePos().toPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
+ mDelayedPressEvent->setAccepted(false);
+ }
+}
+
+/*!
+ Sends the stored mouse press event.
+*/
+void HsIdleWidget::sendDelayedPress()
+{
+ if (mDelayedPressEvent) {
+ QApplication::sendEvent(HsScene::mainWindow()->viewport(), mDelayedPressEvent);
+ clearDelayedPress();
+ }
+}
+
+/*!
+ Deletes the stored mouse press event.
+*/
+void HsIdleWidget::clearDelayedPress()
+{
+ if (mDelayedPressEvent) {
+ delete mDelayedPressEvent;
+ mDelayedPressEvent = 0;
+ }
+}
+
+/*!
+ Sets the active page \a index to the page
+ indicator.
+*/
+void HsIdleWidget::setActivePage(int index)
+{
+ mPageIndicator->setCurrentIndex(index);
+}
+
+/*!
+ Inserts the given \a page at index position
+ \a index in the page layer.
+*/
+void HsIdleWidget::insertPage(int index, HsPage *page)
+{
+ QGraphicsLinearLayout *layout =
+ static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
+ layout->insertItem(index, page);
+ mPageLayer->resize(
+ layout->count() * size().width(), size().height());
+}
+
+/*!
+ Removes the page at index position
+ \a index in the page layer.
+*/
+void HsIdleWidget::removePage(int index)
+{
+ QGraphicsLinearLayout *layout =
+ static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
+ layout->removeAt(index);
+ mPageLayer->resize(
+ layout->count() * size().width(), size().height());
+}
+
+/*!
+ \fn HsIdleWidget::controlLayer() const
+
+ Returns the control layer.
+*/
+
+/*!
+ \fn HsIdleWidget::pageLayer() const
+
+ Returns the page layer.
+*/
+
+/*!
+ \fn HsIdleWidget::sceneLayer() const
+
+ Returns the scene layer.
+*/
+
+/*!
+ \fn HsIdleWidget::trashBin() const
+
+ Returns the trashbin widget.
+*/
+
+/*!
+ \fn HsIdleWidget::pageIndicator() const
+
+ Returns the page indicator widget.
+*/
+
+/*!
+ \fn HsIdleWidget::mousePressed(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
+
+ The idle state connects to this signal for handling mouse
+ press events. It filters events for the item \a watched.
+ \a event is the filtered event. Sets the \a filtered true
+ if the event was filtered by this handler.
+*/
+
+/*!
+ \fn HsIdleWidget::mouseMoved(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
+
+ The idle state connects to this signal for handling mouse
+ move events. It filters events for the item \a watched.
+ \a event is the filtered event. Sets the \a filtered true
+ if the event was filtered by this handler.
+*/
+
+/*!
+ \fn HsIdleWidget::mouseReleased(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
+
+ The idle state connects to this signal for handling mouse
+ release events. It filters events for the item \a watched.
+ \a event is the filtered event. Sets the \a filtered true
+ if the event was filtered by this handler.
+*/
+
+/*!
+ Sets the trashbin visible and hides the page indicator.
+*/
+void HsIdleWidget::showTrashBin()
+{
+ mPageIndicator->hide();
+ mTrashBin->show();
+}
+
+/*!
+ Sets the page indicator visible and hides the trashbin.
+*/
+void HsIdleWidget::showPageIndicator()
+{
+ mTrashBin->hide();
+ mTrashBin->deactivate();
+ mPageIndicator->setVisible(1 < mPageIndicator->itemCount());
+}
+
+/*!
+ Filters the main window's graphics scene (\a object) \a event.
+*/
+bool HsIdleWidget::eventFilter(QObject *object, QEvent *event)
+{
+ Q_UNUSED(object)
+
+ if (HbInputMethod::activeInputMethod() &&
+ HbInputMethod::activeInputMethod()->focusObject()) {
+ setFiltersChildEvents(false);
+ return false;
+ }
+
+ bool filtered = false;
+
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ if (mDelayedPressEvent &&
+ scene()->mouseGrabberItem()) {
+ scene()->mouseGrabberItem()->ungrabMouse();
+ }
+ setFiltersChildEvents(!mDelayedPressEvent);
+ break;
+ case QEvent::GraphicsSceneMouseMove:
+ emit mouseMoved(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
+ break;
+ case QEvent::GraphicsSceneMouseRelease:
+ setItemsFocusable();
+ emit mouseReleased(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
+ if (filtered && scene()->mouseGrabberItem()) {
+ scene()->mouseGrabberItem()->ungrabMouse();
+ }
+ break;
+ default:
+ break;
+ }
+
+ return filtered;
+}
+
+/*!
+ Filters events for the item \a watched. \a event is the filtered event.
+*/
+bool HsIdleWidget::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+{
+ bool filtered = false;
+
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ emit mousePressed(watched, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
+ if (filtered) {
+ setItemsUnfocusable(static_cast<QGraphicsSceneMouseEvent *>(event));
+ }
+ break;
+ default:
+ break;
+ }
+
+ return filtered;
+}
+
+/*!
+ Reimplements QGraphicsWidget::polishEvent().
+*/
+void HsIdleWidget::polishEvent()
+{
+ HsScene *scene = HsScene::instance();
+ Q_ASSERT(scene);
+
+ QGraphicsLinearLayout *layout =
+ static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
+ QList<HsPage *> pages = scene->pages();
+ foreach (HsPage *page, pages) {
+ layout->addItem(page);
+ }
+
+ layout = static_cast<QGraphicsLinearLayout *>(mSceneLayer->layout());
+ HsWallpaper *wallpaper = HsScene::instance()->wallpaper();
+ layout->addItem(wallpaper);
+
+ mPageIndicator->setItemCount(pages.count());
+ setActivePage(scene->activePageIndex());
+ showPageIndicator();
+
+ HsScene::mainWindow()->scene()->installEventFilter(this);
+}
+
+/*!
+ Loads the control layer declared in a docml file.
+*/
+void HsIdleWidget::loadControlLayer()
+{
+ HsDocumentLoader loader;
+ bool loaded = false;
+
+#ifndef Q_OS_SYMBIAN
+ QString path = QDir::currentPath();
+#else
+ QString path = "c:";
+#endif
+
+ QString file = path + "/hsresources/" + CONTROL_LAYER_DOCML_FILE;
+ QString fallbackPath = QString(":/") + CONTROL_LAYER_DOCML_FILE;
+
+ if (QFile::exists(file)) {
+ loader.load(file, &loaded);
+ if (!loaded) {
+ loader.load(fallbackPath, &loaded);
+ }
+ } else {
+ loader.load(fallbackPath, &loaded);
+ }
+
+ if (loaded) {
+ mControlLayer = qobject_cast<HbWidget *>(loader.findWidget(CONTROL_LAYER));
+ mControlLayer->setZValue(2);
+ mControlLayer->setParentItem(this);
+
+ mTrashBin = qobject_cast<HsTrashBinWidget *>(loader.findWidget(TRASH_BIN));
+ mTrashBin->setZValue(1e6);
+
+ mPageIndicator = qobject_cast<HsPageIndicator *>(loader.findWidget(PAGE_INDICATOR));
+ mPageIndicator->setZValue(1e6);
+ } else {
+ // TODO: Handle error.
+ }
+}
+
+/*!
+ Sets the items under the given mouse \a event scene position
+ unfocusable and stores the items.
+*/
+void HsIdleWidget::setItemsUnfocusable(QGraphicsSceneMouseEvent *event)
+{
+ mFocusableItems.clear();
+ QList<QGraphicsItem *> items =
+ HsScene::mainWindow()->scene()->items(event->scenePos());
+ int i = 0;
+ while (!mPageLayer->isAncestorOf(items[i++])) {}
+ HsPage *page = HsScene::instance()->activePage();
+ QList<HsWidgetHost *> widgets = page->widgets();
+ for (; i < items.count(); ++i) {
+ QGraphicsItem *item = items.at(i);
+ if (page->isAncestorOf(item)) {
+ foreach (HsWidgetHost *widget, widgets) {
+ if ((item == widget || widget->isAncestorOf(item))&& item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
+ if (!item->isWidget() || static_cast<QGraphicsWidget*>(item)->focusPolicy() & Qt::ClickFocus) {
+ item->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ mFocusableItems.append(item);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*!
+ Sets the stored items focusable.
+*/
+void HsIdleWidget::setItemsFocusable()
+{
+ foreach (QGraphicsItem *item, mFocusableItems) {
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ }
+ mFocusableItems.clear();
+}