diff -r c743ef5928ba -r f9ce957a272c homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlewidget.cpp --- /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 +#include +#include + +#include +#include + +#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 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(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(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(event), filtered); + break; + case QEvent::GraphicsSceneMouseRelease: + setItemsFocusable(); + emit mouseReleased(0, static_cast(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(event), filtered); + if (filtered) { + setItemsUnfocusable(static_cast(event)); + } + break; + default: + break; + } + + return filtered; +} + +/*! + Reimplements QGraphicsWidget::polishEvent(). +*/ +void HsIdleWidget::polishEvent() +{ + HsScene *scene = HsScene::instance(); + Q_ASSERT(scene); + + QGraphicsLinearLayout *layout = + static_cast(mPageLayer->layout()); + QList pages = scene->pages(); + foreach (HsPage *page, pages) { + layout->addItem(page); + } + + layout = static_cast(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(loader.findWidget(CONTROL_LAYER)); + mControlLayer->setZValue(2); + mControlLayer->setParentItem(this); + + mTrashBin = qobject_cast(loader.findWidget(TRASH_BIN)); + mTrashBin->setZValue(1e6); + + mPageIndicator = qobject_cast(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 items = + HsScene::mainWindow()->scene()->items(event->scenePos()); + int i = 0; + while (!mPageLayer->isAncestorOf(items[i++])) {} + HsPage *page = HsScene::instance()->activePage(); + QList 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(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(); +}