homescreenapp/stateplugins/hshomescreenstateplugin/src/hsidlewidget.cpp
changeset 35 f9ce957a272c
child 36 cdae8c6c3876
equal deleted inserted replaced
5:c743ef5928ba 35:f9ce957a272c
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <QGraphicsSceneMouseEvent>
       
    19 #include <QGraphicsLinearLayout>
       
    20 #include <QDir>
       
    21 
       
    22 #include <HbMainWindow>
       
    23 #include <HbInputMethod>
       
    24 
       
    25 #include "hsidlewidget.h"
       
    26 #include "hsscene.h"
       
    27 #include "hspage.h"
       
    28 #include "hswidgethost.h"
       
    29 #include "hswallpaper.h"
       
    30 #include "hstrashbinwidget.h"
       
    31 #include "hspageindicator.h"
       
    32 #include "hsdocumentloader.h"
       
    33 
       
    34 namespace
       
    35 {
       
    36     const char CONTROL_LAYER_DOCML_FILE[] = "controllayer.docml";
       
    37     const char CONTROL_LAYER[] = "controlLayer";
       
    38     const char TRASH_BIN[] = "trashBin";
       
    39     const char PAGE_INDICATOR[] = "pageIndicator";
       
    40 }
       
    41 
       
    42 /*!
       
    43     \class HsIdleWidget
       
    44     \ingroup group_hshomescreenstateplugin
       
    45     \brief View part of the home screen idle state.
       
    46 
       
    47     Maintains the idle view ui layers and takes care of 
       
    48     receiving user input and communicating it to the idle 
       
    49     state for further processing.
       
    50 */
       
    51 
       
    52 /*!
       
    53     Constructs a new idle widget with the given \a parent.
       
    54 */
       
    55 HsIdleWidget::HsIdleWidget(QGraphicsItem *parent)
       
    56   : HbWidget(parent),
       
    57     mControlLayer(0), mPageLayer(0), mSceneLayer(0),
       
    58     mDelayedPressEvent(0),
       
    59     mTrashBin(0), mPageIndicator(0)
       
    60 {
       
    61     setFlag(ItemHasNoContents);
       
    62     
       
    63     loadControlLayer();
       
    64 
       
    65     QGraphicsLinearLayout *linearLayout = 0;
       
    66 
       
    67     linearLayout = new QGraphicsLinearLayout(Qt::Horizontal);
       
    68     linearLayout->setContentsMargins(0, 0, 0, 0);
       
    69     linearLayout->setSpacing(0);
       
    70     mPageLayer = new HbWidget(this);
       
    71     mPageLayer->setLayout(linearLayout);
       
    72     mPageLayer->setZValue(1);
       
    73     
       
    74     linearLayout = new QGraphicsLinearLayout(Qt::Horizontal);
       
    75     linearLayout->setContentsMargins(0, 0, 0, 0);
       
    76     linearLayout->setSpacing(0);
       
    77     mSceneLayer = new HbWidget(this);
       
    78     mSceneLayer->setLayout(linearLayout);
       
    79     mSceneLayer->setZValue(0);
       
    80 }
       
    81 
       
    82 /*!
       
    83     Destroys this idle widget.
       
    84 */
       
    85 HsIdleWidget::~HsIdleWidget()
       
    86 {
       
    87     clearDelayedPress();
       
    88 
       
    89     QList<HsPage *> pages = HsScene::instance()->pages();
       
    90     foreach (HsPage *page, pages) {
       
    91         page->setParentItem(0);
       
    92         if (page->scene()) {
       
    93             page->scene()->removeItem(page);
       
    94         }
       
    95     }
       
    96 
       
    97     HsWallpaper *wallpaper = HsScene::instance()->wallpaper();
       
    98     wallpaper->setParentItem(0);
       
    99     if (wallpaper->scene()) {
       
   100         wallpaper->scene()->removeItem(wallpaper);
       
   101     }
       
   102 }
       
   103 
       
   104 /*!
       
   105     Layouts the ui layers according to the given \a rect.
       
   106 */
       
   107 void HsIdleWidget::setGeometry(const QRectF &rect)
       
   108 {
       
   109     int n = HsScene::instance()->pages().count();
       
   110     mControlLayer->resize(rect.size());
       
   111     mPageLayer->resize(n * rect.width(), rect.height());
       
   112     mSceneLayer->resize(2 * rect.width(), rect.height());
       
   113     HbWidget::setGeometry(rect);
       
   114 }
       
   115 
       
   116 /*!
       
   117     Stores the given mouse press \a event.
       
   118 */
       
   119 void HsIdleWidget::captureDelayedPress(QGraphicsSceneMouseEvent *event)
       
   120 {
       
   121     if (event) {
       
   122         mDelayedPressEvent = new QMouseEvent(QEvent::MouseButtonPress,
       
   123             event->scenePos().toPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
       
   124         mDelayedPressEvent->setAccepted(false);
       
   125     }
       
   126 }
       
   127 
       
   128 /*!
       
   129     Sends the stored mouse press event.
       
   130 */
       
   131 void HsIdleWidget::sendDelayedPress()
       
   132 {
       
   133     if (mDelayedPressEvent) {
       
   134         QApplication::sendEvent(HsScene::mainWindow()->viewport(), mDelayedPressEvent);
       
   135         clearDelayedPress();     
       
   136     }
       
   137 }
       
   138 
       
   139 /*!
       
   140     Deletes the stored mouse press event.
       
   141 */
       
   142 void HsIdleWidget::clearDelayedPress()
       
   143 {    
       
   144     if (mDelayedPressEvent) {
       
   145         delete mDelayedPressEvent;
       
   146         mDelayedPressEvent = 0;
       
   147     }
       
   148 }
       
   149 
       
   150 /*!
       
   151     Sets the active page \a index to the page 
       
   152     indicator.
       
   153 */
       
   154 void HsIdleWidget::setActivePage(int index)
       
   155 {
       
   156     mPageIndicator->setCurrentIndex(index);
       
   157 }
       
   158 
       
   159 /*!
       
   160     Inserts the given \a page at index position
       
   161     \a index in the page layer.
       
   162 */
       
   163 void HsIdleWidget::insertPage(int index, HsPage *page)
       
   164 {
       
   165     QGraphicsLinearLayout *layout = 
       
   166         static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
       
   167     layout->insertItem(index, page);
       
   168     mPageLayer->resize(
       
   169         layout->count() * size().width(), size().height());
       
   170 }
       
   171 
       
   172 /*!
       
   173     Removes the page at index position
       
   174     \a index in the page layer.
       
   175 */
       
   176 void HsIdleWidget::removePage(int index)
       
   177 {
       
   178     QGraphicsLinearLayout *layout = 
       
   179         static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
       
   180     layout->removeAt(index);
       
   181     mPageLayer->resize(
       
   182         layout->count() * size().width(), size().height());
       
   183 }
       
   184 
       
   185 /*!
       
   186     \fn HsIdleWidget::controlLayer() const
       
   187 
       
   188     Returns the control layer.
       
   189 */
       
   190 
       
   191 /*!
       
   192     \fn HsIdleWidget::pageLayer() const
       
   193 
       
   194     Returns the page layer.
       
   195 */
       
   196 
       
   197 /*!
       
   198     \fn HsIdleWidget::sceneLayer() const
       
   199 
       
   200     Returns the scene layer.
       
   201 */
       
   202 
       
   203 /*!
       
   204     \fn HsIdleWidget::trashBin() const
       
   205 
       
   206     Returns the trashbin widget.
       
   207 */
       
   208 
       
   209 /*!
       
   210     \fn HsIdleWidget::pageIndicator() const
       
   211 
       
   212     Returns the page indicator widget.
       
   213 */
       
   214 
       
   215 /*!
       
   216     \fn HsIdleWidget::mousePressed(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
       
   217 
       
   218     The idle state connects to this signal for handling mouse
       
   219     press events. It filters events for the item \a watched. 
       
   220     \a event is the filtered event. Sets the \a filtered true 
       
   221     if the event was filtered by this handler.
       
   222 */
       
   223 
       
   224 /*!
       
   225     \fn HsIdleWidget::mouseMoved(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
       
   226 
       
   227     The idle state connects to this signal for handling mouse
       
   228     move events. It filters events for the item \a watched. 
       
   229     \a event is the filtered event. Sets the \a filtered true 
       
   230     if the event was filtered by this handler.
       
   231 */
       
   232 
       
   233 /*!
       
   234     \fn HsIdleWidget::mouseReleased(QGraphicsItem *, QGraphicsSceneMouseEvent *, bool &)
       
   235 
       
   236     The idle state connects to this signal for handling mouse
       
   237     release events. It filters events for the item \a watched. 
       
   238     \a event is the filtered event. Sets the \a filtered true 
       
   239     if the event was filtered by this handler.
       
   240 */
       
   241 
       
   242 /*!
       
   243     Sets the trashbin visible and hides the page indicator.
       
   244 */
       
   245 void HsIdleWidget::showTrashBin()
       
   246 {
       
   247     mPageIndicator->hide();
       
   248     mTrashBin->show();
       
   249 }
       
   250  
       
   251 /*!
       
   252     Sets the page indicator visible and hides the trashbin.
       
   253 */
       
   254 void HsIdleWidget::showPageIndicator()
       
   255 {
       
   256     mTrashBin->hide();
       
   257     mTrashBin->deactivate();
       
   258     mPageIndicator->setVisible(1 < mPageIndicator->itemCount());
       
   259 }
       
   260 
       
   261 /*!
       
   262     Filters the main window's graphics scene (\a object) \a event.
       
   263 */
       
   264 bool HsIdleWidget::eventFilter(QObject *object, QEvent *event)
       
   265 {
       
   266     Q_UNUSED(object)
       
   267 
       
   268     if (HbInputMethod::activeInputMethod() &&
       
   269         HbInputMethod::activeInputMethod()->focusObject()) {
       
   270         setFiltersChildEvents(false);
       
   271         return false;
       
   272     }
       
   273 
       
   274     bool filtered = false;
       
   275 
       
   276     switch (event->type()) {
       
   277     case QEvent::GraphicsSceneMousePress:
       
   278         if (mDelayedPressEvent &&
       
   279             scene()->mouseGrabberItem()) {
       
   280             scene()->mouseGrabberItem()->ungrabMouse();
       
   281         }
       
   282         setFiltersChildEvents(!mDelayedPressEvent);
       
   283         break;
       
   284     case QEvent::GraphicsSceneMouseMove:
       
   285         emit mouseMoved(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
       
   286         break;
       
   287     case QEvent::GraphicsSceneMouseRelease:
       
   288         setItemsFocusable();
       
   289         emit mouseReleased(0, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
       
   290         if (filtered && scene()->mouseGrabberItem()) {
       
   291             scene()->mouseGrabberItem()->ungrabMouse();
       
   292         }        
       
   293         break;
       
   294     default:
       
   295         break;
       
   296     }
       
   297 
       
   298     return filtered;
       
   299 }
       
   300 
       
   301 /*!
       
   302     Filters events for the item \a watched. \a event is the filtered event.
       
   303 */
       
   304 bool HsIdleWidget::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
       
   305 {
       
   306     bool filtered = false;
       
   307 
       
   308     switch (event->type()) {
       
   309     case QEvent::GraphicsSceneMousePress:
       
   310         emit mousePressed(watched, static_cast<QGraphicsSceneMouseEvent *>(event), filtered);
       
   311         if (filtered) {
       
   312             setItemsUnfocusable(static_cast<QGraphicsSceneMouseEvent *>(event));
       
   313         }
       
   314         break;    
       
   315     default:
       
   316         break;
       
   317     }
       
   318 
       
   319     return filtered;
       
   320 }
       
   321 
       
   322 /*!
       
   323     Reimplements QGraphicsWidget::polishEvent().
       
   324 */
       
   325 void HsIdleWidget::polishEvent()
       
   326 {
       
   327     HsScene *scene = HsScene::instance();
       
   328     Q_ASSERT(scene);
       
   329 
       
   330     QGraphicsLinearLayout *layout = 
       
   331         static_cast<QGraphicsLinearLayout *>(mPageLayer->layout());
       
   332     QList<HsPage *> pages = scene->pages();
       
   333     foreach (HsPage *page, pages) {
       
   334         layout->addItem(page);
       
   335     }
       
   336 
       
   337     layout = static_cast<QGraphicsLinearLayout *>(mSceneLayer->layout());
       
   338     HsWallpaper *wallpaper = HsScene::instance()->wallpaper();
       
   339     layout->addItem(wallpaper);
       
   340            
       
   341     mPageIndicator->setItemCount(pages.count());
       
   342     setActivePage(scene->activePageIndex());
       
   343     showPageIndicator();
       
   344 
       
   345     HsScene::mainWindow()->scene()->installEventFilter(this);
       
   346 }
       
   347 
       
   348 /*!
       
   349     Loads the control layer declared in a docml file.
       
   350 */
       
   351 void HsIdleWidget::loadControlLayer()
       
   352 {
       
   353     HsDocumentLoader loader;
       
   354     bool loaded = false;
       
   355 
       
   356 #ifndef Q_OS_SYMBIAN
       
   357     QString path = QDir::currentPath();
       
   358 #else
       
   359     QString path = "c:";
       
   360 #endif
       
   361 
       
   362     QString file = path + "/hsresources/" + CONTROL_LAYER_DOCML_FILE;
       
   363     QString fallbackPath = QString(":/") + CONTROL_LAYER_DOCML_FILE;
       
   364 
       
   365     if (QFile::exists(file)) {
       
   366         loader.load(file, &loaded);
       
   367         if (!loaded) {
       
   368             loader.load(fallbackPath, &loaded);
       
   369         }
       
   370     } else {
       
   371         loader.load(fallbackPath, &loaded);       
       
   372     }
       
   373 
       
   374     if (loaded) {
       
   375         mControlLayer = qobject_cast<HbWidget *>(loader.findWidget(CONTROL_LAYER));
       
   376         mControlLayer->setZValue(2);
       
   377         mControlLayer->setParentItem(this);
       
   378 
       
   379         mTrashBin = qobject_cast<HsTrashBinWidget *>(loader.findWidget(TRASH_BIN));
       
   380         mTrashBin->setZValue(1e6);
       
   381 
       
   382         mPageIndicator = qobject_cast<HsPageIndicator *>(loader.findWidget(PAGE_INDICATOR));
       
   383         mPageIndicator->setZValue(1e6);
       
   384     } else {
       
   385         // TODO: Handle error.
       
   386     }
       
   387 }
       
   388 
       
   389 /*!
       
   390     Sets the items under the given mouse \a event scene position 
       
   391     unfocusable and stores the items.
       
   392 */
       
   393 void HsIdleWidget::setItemsUnfocusable(QGraphicsSceneMouseEvent *event)
       
   394 {
       
   395     mFocusableItems.clear();
       
   396     QList<QGraphicsItem *> items = 
       
   397         HsScene::mainWindow()->scene()->items(event->scenePos());
       
   398     int i = 0;
       
   399     while (!mPageLayer->isAncestorOf(items[i++])) {}
       
   400     HsPage *page = HsScene::instance()->activePage();
       
   401     QList<HsWidgetHost *> widgets = page->widgets();
       
   402     for (; i < items.count(); ++i) {
       
   403         QGraphicsItem *item = items.at(i);
       
   404         if (page->isAncestorOf(item)) {
       
   405             foreach (HsWidgetHost *widget, widgets) {
       
   406                 if ((item == widget || widget->isAncestorOf(item))&& item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
       
   407                     if (!item->isWidget() || static_cast<QGraphicsWidget*>(item)->focusPolicy() & Qt::ClickFocus) {
       
   408                         item->setFlag(QGraphicsItem::ItemIsFocusable, false);
       
   409                         mFocusableItems.append(item);
       
   410                     }
       
   411                 }
       
   412             }
       
   413         }
       
   414     }
       
   415 }
       
   416  
       
   417 /*!
       
   418     Sets the stored items focusable.
       
   419 */
       
   420 void HsIdleWidget::setItemsFocusable()
       
   421 {
       
   422     foreach (QGraphicsItem *item, mFocusableItems) {
       
   423         item->setFlag(QGraphicsItem::ItemIsFocusable);
       
   424     }
       
   425     mFocusableItems.clear();
       
   426 }