diff -r 474929a40a0f -r 87476091b3f5 homescreenapp/hsdomainmodel/src/hsidlewidget.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/homescreenapp/hsdomainmodel/src/hsidlewidget.cpp Fri Jul 23 13:47:57 2010 +0300 @@ -0,0 +1,409 @@ +/* +* 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 + +#include "hsidlewidget.h" +#include "hsscene.h" +#include "hspage.h" +#include "hspagevisual.h" +#include "hswidgethost.h" +#include "hswallpaper.h" +#include "hstrashbinwidget.h" +#include "hspageindicator.h" +#include "hsdocumentloader.h" +#include "hsconfiguration.h" +#include "hsapp_defs.h" +#include "hssnapline.h" +#include "hsgui.h" + + +namespace +{ + const char gControlLayerDocmlName[] = "controllayer.docml"; + const char gControlLayerName[] = "controlLayer"; + const char gTrashBinName[] = "trashBin"; + const char gPageIndicatorName[] = "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), mPageWallpaperLayer(0), + mSceneLayer(0), + mTrashBin(0), mPageIndicator(0), + mHorizontalSnapLine(0), mVerticalSnapLine(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(2); + + linearLayout = new QGraphicsLinearLayout(Qt::Horizontal); + linearLayout->setContentsMargins(0, 0, 0, 0); + linearLayout->setSpacing(0); + mPageWallpaperLayer = new HbWidget(this); + mPageWallpaperLayer->setLayout(linearLayout); + mPageWallpaperLayer->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() +{ + QList pages = HsScene::instance()->pages(); + foreach (HsPage *page, pages) { + page->visual()->setParentItem(0); + if (page->visual()->scene()) { + page->visual()->scene()->removeItem(page->visual()); + } + HsWallpaper *pageWallpaper = page->wallpaper(); + if (pageWallpaper) { + pageWallpaper->setParentItem(0); + if (pageWallpaper->scene()) { + pageWallpaper->scene()->removeItem(pageWallpaper); + } + } + } + + HsWallpaper *sceneWallpaper = HsScene::instance()->wallpaper(); + if (sceneWallpaper) { + sceneWallpaper->setParentItem(0); + if (sceneWallpaper->scene()) { + sceneWallpaper->scene()->removeItem(sceneWallpaper); + } + } +} + +qreal HsIdleWidget::sceneX() const +{ + return mPageLayer->x(); +} + +void HsIdleWidget::setSceneX(qreal x) +{ + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::SceneWallpaper) { + mPageLayer->setX(x); + mSceneLayer->setX((parallaxFactor() * x) - HSCONFIGURATION_GET(bounceEffect) / 2); + } else { + mPageLayer->setX(x); + mPageWallpaperLayer->setX(x); + } +} + +/*! + Layouts the ui layers according to the given \a rect. + If given \a rect has different size than a fullscreen view, rect + is lifted up by statuspane height. Normally HsIdleWidget position is 0,0 + relative to it's parent container (HbView). This functionality tackles + problem caused by HbStackedLayout which sets top most rect for all items + (views) in a stack (not considering fullscreen mode). +*/ +void HsIdleWidget::setGeometry(const QRectF &rect) +{ + + int n = HsScene::instance()->pages().count(); + QRectF layoutRect(HsGui::instance()->layoutRect()); + if (layoutRect == rect || (layoutRect.height() == rect.width() && layoutRect.width() == rect.height())) { + mControlLayer->resize(rect.size()); + mPageLayer->resize(n * rect.width(), rect.height()); + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::PageWallpapers) { + mPageWallpaperLayer->resize(n * rect.width(), rect.height()); + } + mSceneLayer->resize(2 * rect.width() + HSCONFIGURATION_GET(bounceEffect), rect.height()); + HbWidget::setGeometry(rect); + } else { + QRectF sceneRect = mapToScene(rect).boundingRect(); + // HbView is a container item for widget, thus 0,0 is relative to view's position. + // Lift rect by offset. Fullscreen view is in 0,0 position in scene coordinates otherwise + // it's e.g 0,68 (statuspane being at 0,0 and view at 0,68) + sceneRect.setTop(-sceneRect.top()); + HbWidget::setGeometry(sceneRect); + } +} + +/*! + Sets the active page \a index to the page + indicator. +*/ +void HsIdleWidget::setActivePage(int index) +{ + mPageIndicator->setActiveItemIndex(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->visual()); + mPageLayer->resize( + layout->count() * size().width(), size().height()); + + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::PageWallpapers) { + QGraphicsLinearLayout *layout = + static_cast(mPageWallpaperLayer->layout()); + layout->insertItem(index, page->wallpaper()); + mPageWallpaperLayer->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()); + + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::PageWallpapers) { + QGraphicsLinearLayout *layout = + static_cast(mPageWallpaperLayer->layout()); + layout->removeAt(index); + mPageWallpaperLayer->resize( + layout->count() * size().width(), size().height()); + } + mPageIndicator->removeItem(index); +} + +/*! + \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. +*/ + +/*! + 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->setSpacing(HSCONFIGURATION_GET(pageIndicatorSpacing)); // for usability optimization widget, can be removed later on + mPageIndicator->setVisible(1 < mPageIndicator->itemCount()); +} + +/*! + Shows the Vertical snapping lines showing the guidance +*/ +void HsIdleWidget::showVerticalSnapLine(const QLineF &snapLine) +{ + QVariantHash snapConfiguration; + snapConfiguration[SNAPLINEFADEINDURATION] = QString::number(HSCONFIGURATION_GET(snapLineFadeInDuration)); + snapConfiguration[SNAPLINEFADEOUTDURATION] = QString::number(HSCONFIGURATION_GET(snapLineFadeOutDuration)); + + mVerticalSnapLine->setConfiguration(snapConfiguration); + mVerticalSnapLine->showLine(snapLine); +} + +/*! + Shows the Horizontal snapping lines showing the guidance +*/ +void HsIdleWidget::showHorizontalSnapLine(const QLineF &snapLine) +{ + QVariantHash snapConfiguration; + snapConfiguration[SNAPLINEFADEINDURATION] = QString::number(HSCONFIGURATION_GET(snapLineFadeInDuration)); + snapConfiguration[SNAPLINEFADEOUTDURATION] = QString::number(HSCONFIGURATION_GET(snapLineFadeOutDuration)); + + mHorizontalSnapLine->setConfiguration(snapConfiguration); + mHorizontalSnapLine->showLine(snapLine); +} + +/*! + Hides the Vertical snapping line showing the guidance +*/ +void HsIdleWidget::hideVerticalSnapLine() +{ + mVerticalSnapLine->hideLine(); +} + +/*! + Hides the Horizontal snapping line showing the guidance +*/ +void HsIdleWidget::hideHorizontalSnapLine() +{ + mHorizontalSnapLine->hideLine(); +} + +/*! + Reimplements QGraphicsWidget::polishEvent(). +*/ +void HsIdleWidget::polishEvent() +{ + HsScene *scene = HsScene::instance(); + Q_ASSERT(scene); + + QGraphicsLinearLayout *pageLayout = + static_cast(mPageLayer->layout()); + + QList pages = scene->pages(); + + foreach (HsPage *page, pages) { + pageLayout->addItem(page->visual()); + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::PageWallpapers) { + QGraphicsLinearLayout *pageWallpaperLayout = + static_cast(mPageWallpaperLayer->layout()); + pageWallpaperLayout->addItem(page->wallpaper()); + } + } + if (HSCONFIGURATION_GET(sceneType) == HsConfiguration::SceneWallpaper) { + QGraphicsLinearLayout *sceneLayout = + static_cast(mSceneLayer->layout()); + HsWallpaper *wallpaper = HsScene::instance()->wallpaper(); + sceneLayout->addItem(wallpaper); + } + + mPageIndicator->initialize(pages.count(), scene->activePageIndex()); + showPageIndicator(); + + // HsGui::instance()->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/" + gControlLayerDocmlName; + QString fallbackPath = QString(":/") + gControlLayerDocmlName; + + 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(gControlLayerName)); + mControlLayer->setZValue(3); + mControlLayer->setParentItem(this); + + mTrashBin = qobject_cast(loader.findWidget(gTrashBinName)); + mTrashBin->setZValue(1e6); + + mPageIndicator = qobject_cast(loader.findWidget(gPageIndicatorName)); + mPageIndicator->setZValue(1e6); + + + mHorizontalSnapLine = new HsSnapLine(mControlLayer); + mHorizontalSnapLine->setZValue(10); + + mVerticalSnapLine = new HsSnapLine(mControlLayer); + mVerticalSnapLine->setZValue(10); + } else { + // TODO: Handle error. + } +} + +qreal HsIdleWidget::parallaxFactor() const +{ + qreal clw = mControlLayer->size().width(); + qreal slw = mSceneLayer->size().width() - HSCONFIGURATION_GET(bounceEffect); + int n = HsScene::instance()->pages().count(); + if (n < 2) { + return 1; + } else { + return (slw - clw) / ((n - 1) * clw); + } +}