Home · All Classes · Main Classes · Deprecated

mwidget.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (directui@nokia.com)
00006 **
00007 ** This file is part of libmeegotouch.
00008 **
00009 ** If you have questions regarding the use of this file, please contact
00010 ** Nokia at directui@nokia.com.
00011 **
00012 ** This library is free software; you can redistribute it and/or
00013 ** modify it under the terms of the GNU Lesser General Public
00014 ** License version 2.1 as published by the Free Software Foundation
00015 ** and appearing in the file LICENSE.LGPL included in the packaging
00016 ** of this file.
00017 **
00018 ****************************************************************************/
00019 
00020 #include "mwidget.h"
00021 #include "mwidget_p.h"
00022 
00023 #include <QPainter>
00024 #include <QObject>
00025 #include <QGraphicsSceneContextMenuEvent>
00026 #include <MDebug>
00027 #include <QApplication>
00028 #include <QGraphicsLayout>
00029 #include <QApplication>
00030 #include <QGraphicsItem>
00031 
00032 #include <QGestureEvent>
00033 #include <QTapAndHoldGesture>
00034 #include <QPanGesture>
00035 #include <QPinchGesture>
00036 #include <QTapGesture>
00037 #include <QSwipeGesture>
00038 
00039 #include <mapplicationwindow.h>
00040 #include <mpannableviewport.h>
00041 #include <maction.h>
00042 #include <mcancelevent.h>
00043 #include <mondisplaychangeevent.h>
00044 #include <morientationchangeevent.h>
00045 #include <mscene.h>
00046 #include <mscenemanager.h>
00047 
00048 #include "mobjectmenu.h"
00049 
00050 
00051 MWidgetPrivate::MWidgetPrivate() :
00052     explicitlyHidden(false),
00053     layoutHidden(false),
00054     q_ptr(NULL),
00055     onDisplay(false),
00056     onDisplaySet(false),
00057     selected(false)
00058 {
00059 }
00060 
00061 MWidgetPrivate::~MWidgetPrivate()
00062 {
00063 }
00064 
00065 /*
00066  * protected constructor
00067  */
00068 MWidget::MWidget(MWidgetPrivate &dd, QGraphicsItem *parent)
00069     : QGraphicsWidget(parent)
00070     , d_ptr(& dd) // this is a special case, since we start our shared d-pointer hierarchy within m right here
00071 {
00072     Q_D(MWidget);
00073     if (d)
00074         d->q_ptr = this;
00075 }
00076 
00077 /*
00078  * public constructor
00079  */
00080 MWidget::MWidget(QGraphicsItem *parent)
00081     : QGraphicsWidget(parent)
00082     , d_ptr(new MWidgetPrivate())
00083 {
00084     Q_D(MWidget);
00085     d->q_ptr = this;
00086 }
00087 
00088 /*
00089  * destructor
00090  */
00091 MWidget::~MWidget()
00092 {
00093     delete d_ptr;
00094 }
00095 
00096 void MWidgetPrivate::doEnterDisplayEvent()
00097 {
00098     Q_Q(MWidget);
00099 
00100     onDisplay = true;
00101     onDisplaySet = true;
00102 
00103     q->enterDisplayEvent();
00104     emit q->displayEntered();
00105 }
00106 
00107 void MWidgetPrivate::doExitDisplayEvent()
00108 {
00109     Q_Q(MWidget);
00110 
00111     onDisplay = false;
00112     onDisplaySet = true;
00113 
00114     q->exitDisplayEvent();
00115     emit q->displayExited();
00116 }
00117 
00118 void MWidgetPrivate::sendOnDisplayChangeEvent(MWidget *widget, const QRectF *visibleSceneRect)
00119 {
00120     Q_Q(MWidget);
00121     MOnDisplayChangeEvent *event = 0;
00122 
00123     QRectF widgetSceneRect = widget->sceneBoundingRect();
00124 
00125     if (visibleSceneRect) {
00126         if (visibleSceneRect->intersects(widgetSceneRect)) {
00127             if (visibleSceneRect->contains(widgetSceneRect)) {
00128                 event = new MOnDisplayChangeEvent(MOnDisplayChangeEvent::FullyOnDisplay, *visibleSceneRect);
00129             } else {
00130                 event = new MOnDisplayChangeEvent(MOnDisplayChangeEvent::PartiallyOnDisplay, *visibleSceneRect);
00131             }
00132         } else {
00133             event = new MOnDisplayChangeEvent(MOnDisplayChangeEvent::FullyOffDisplay, *visibleSceneRect);
00134         }
00135 
00136         q->scene()->sendEvent(widget, event);
00137         delete event;
00138     }
00139 }
00140 
00141 void MWidgetPrivate::resolveIsOnDisplay(QGraphicsItem *item, const QRectF *visibleSceneRect,
00142                                         MOnDisplayChangeEvent *event)
00143 {
00144     Q_Q(MWidget);
00145     MWidget *mWidget;
00146 
00147     if (item->isWidget()) {
00148         mWidget = qobject_cast<MWidget *>(static_cast<QGraphicsWidget *>(item));
00149         if (mWidget) {
00150             // Check if event was defined explicitly. If so then send it, otherwise
00151             // let sendOnDisplayChangeEvent() resolve visibility and send
00152             // the corresponding event.
00153             if (event) {
00154                 q->scene()->sendEvent(mWidget, event);
00155             } else {
00156                 sendOnDisplayChangeEvent(mWidget, visibleSceneRect);
00157             }
00158         }
00159     }
00160 
00161     QList<QGraphicsItem *> childItemsList = item->childItems();
00162     int childItemsCount = childItemsList.count();
00163 
00164     for (int i = 0; i < childItemsCount; i++) {
00165         resolveIsOnDisplay(childItemsList.at(i), visibleSceneRect, event);
00166     }
00167 }
00168 
00169 QGraphicsView *MWidgetPrivate::fetchGraphicsView()
00170 {
00171     Q_Q(MWidget);
00172     QGraphicsView *graphicsView = 0;
00173 
00174     QGraphicsScene *scene = q->scene();
00175     if (scene) {
00176         QList<QGraphicsView *> viewsList = scene->views();
00177         // We assume that there's only one QGraphicsView rendering our scene
00178         if (viewsList.count() > 0) {
00179             if (viewsList.count() > 1) {
00180                 mWarning("MWidget") << "There's more than one QGraphicsView rendering a MScene.";
00181             }
00182 
00183             graphicsView = viewsList.at(0);
00184         }
00185     }
00186 
00187     return graphicsView;
00188 }
00189 
00190 void MWidget::onDisplayChangeEvent(MOnDisplayChangeEvent *event)
00191 {
00192     Q_D(MWidget);
00193 
00194     switch (event->state()) {
00195     case MOnDisplayChangeEvent::FullyOnDisplay:
00196     case MOnDisplayChangeEvent::PartiallyOnDisplay:
00197         // If the widget has not previously gotten enterDisplayEvent
00198         // and it hasn't been hidden by hide() (setVisible(false)),
00199         // consider this event as entering the display.
00200         if ((!d->onDisplay || !d->onDisplaySet) && isVisible()) {
00201             d->doEnterDisplayEvent();
00202         }
00203         break;
00204 
00205     case MOnDisplayChangeEvent::FullyOffDisplay:
00206         if (d->onDisplay || !d->onDisplaySet) {
00207             d->doExitDisplayEvent();
00208         }
00209         break;
00210 
00211     case MOnDisplayChangeEvent::MustBeResolved: {
00212         // We assume that there's only one QGraphicsView rendering our scene
00213         QGraphicsView *graphicsView = d->fetchGraphicsView();
00214         if (graphicsView) {
00215             QRectF visibleSceneRect = graphicsView->sceneRect();
00216             d->resolveIsOnDisplay(this, &visibleSceneRect);
00217         } else {
00218             d->resolveIsOnDisplay(this, 0);
00219         }
00220     }
00221     break;
00222 
00223     default:
00224         break;
00225     }
00226 }
00227 
00228 void MWidget::enterDisplayEvent()
00229 {
00230 }
00231 
00232 void MWidget::exitDisplayEvent()
00233 {
00234 }
00235 
00236 bool MWidget::isOnDisplay() const
00237 {
00238     bool result = false;
00239 
00240     if (!isVisible()) {
00241         return false;
00242     }
00243 
00244     if (!scene()) {
00245         return false;
00246     }
00247 
00248     QList<QGraphicsView *> viewsList = scene()->views();
00249     int viewCount = viewsList.count();
00250     QGraphicsView *graphicsView;
00251     MWindow *mWindow;
00252     QRect viewportRect; // viewport rectangle. (0, 0, width, height)
00253     QRect widgetViewportRect; // widget bounding rect in viewport coordinates
00254     int i = 0;
00255 
00256     while (result == false && i < viewCount) {
00257 
00258         graphicsView = viewsList.at(i);
00259         ++i;
00260 
00261         if (!graphicsView->isVisible()) {
00262             continue;
00263         }
00264 
00265         mWindow = qobject_cast<MWindow *>(graphicsView);
00266         if (mWindow && !mWindow->isOnDisplay()) {
00267             continue;
00268         }
00269 
00270         widgetViewportRect = graphicsView->mapFromScene(sceneBoundingRect()).boundingRect();
00271 
00272         viewportRect.setWidth(graphicsView->viewport()->width());
00273         viewportRect.setHeight(graphicsView->viewport()->height());
00274 
00275         if (widgetViewportRect.intersects(viewportRect)) {
00276             result = true;
00277         }
00278     }
00279 
00280     return result;
00281 }
00282 
00283 MSceneManager *MWidget::sceneManager() const
00284 {
00285     MScene *mScene = qobject_cast<MScene *>(scene());
00286     if (mScene)
00287         return mScene->sceneManager();
00288     return 0;
00289 }
00290 
00291 QPainterPath MWidget::shape() const
00292 {
00293     QPainterPath path;
00294     path.addRect(boundingRect());
00295     return path;
00296 }
00297 
00298 
00299 void MWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option,
00300                                  QWidget *widget)
00301 {
00302     Q_UNUSED(painter);
00303     Q_UNUSED(option);
00304     Q_UNUSED(widget);
00305 }
00306 
00307 void MWidget::setObjectName(const QString &name)
00308 {
00309     QGraphicsWidget::setObjectName(name);
00310 }
00311 
00312 void MWidget::clearActions()
00313 {
00314     QList<QAction *> acts = actions();
00315     const int actsSize = acts.size();
00316     for (int i = 0; i < actsSize; ++i) {
00317         removeAction(acts[i]);
00318     }
00319 }
00320 
00321 void MWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
00322 {
00323     QList<QAction *> actionList = actions();
00324     bool hasObjectMenuActions = false;
00325     const int actionListCount = actionList.count();
00326     for (int i = 0; i < actionListCount; ++i) {
00327         MAction *action = qobject_cast<MAction *>(actionList.at(i));
00328         if (action && action->isVisible() && (action->location() & MAction::ObjectMenuLocation)) {
00329             hasObjectMenuActions = true;
00330             break;
00331         }
00332     }
00333 
00334     if (hasObjectMenuActions) {
00335         MObjectMenu *menu = new MObjectMenu(this);
00336         menu->setCursorPosition(event->scenePos());
00337         sceneManager()->appearSceneWindow(menu, MSceneWindow::DestroyWhenDone);
00338     } else {
00339         event->ignore();
00340     }
00341 }
00342 
00343 void MWidget::gestureEvent(QGestureEvent *event)
00344 {
00345     foreach(QGesture* gesture, event->gestures()) {
00346         if (Qt::TapAndHoldGesture == gesture->gestureType()) {
00347             QTapAndHoldGesture* tapAndHoldState = static_cast<QTapAndHoldGesture *>(gesture);
00348             tapAndHoldGestureEvent(event,tapAndHoldState);
00349         } else if (Qt::PanGesture == gesture->gestureType()) {
00350             QPanGesture* panState = static_cast<QPanGesture *>(gesture);
00351             panGestureEvent(event,panState);
00352         } else if (Qt::PinchGesture == gesture->gestureType()) {
00353             QPinchGesture* pinchState = static_cast<QPinchGesture *>(gesture);
00354             pinchGestureEvent(event,pinchState);
00355         } else if (Qt::TapGesture == gesture->gestureType()) {
00356             QTapGesture* tapState = static_cast<QTapGesture *>(gesture);
00357             tapGestureEvent(event,tapState);
00358         } else if (Qt::SwipeGesture == gesture->gestureType()) {
00359             QSwipeGesture* swipeState = static_cast<QSwipeGesture *>(gesture);
00360             swipeGestureEvent(event,swipeState);
00361         }
00362     }
00363 }
00364 
00365 void MWidget::tapAndHoldGestureEvent(QGestureEvent *event, QTapAndHoldGesture *gesture)
00366 {
00367     event->ignore(gesture);
00368 }
00369 
00370 void MWidget::panGestureEvent(QGestureEvent *event, QPanGesture *gesture)
00371 {
00372     event->ignore(gesture);
00373 }
00374 
00375 void MWidget::pinchGestureEvent(QGestureEvent *event, QPinchGesture* gesture)
00376 {
00377     event->ignore(gesture);
00378 }
00379 
00380 void MWidget::tapGestureEvent(QGestureEvent *event, QTapGesture* gesture)
00381 {
00382     event->ignore(gesture);
00383 }
00384 
00385 void MWidget::swipeGestureEvent(QGestureEvent *event, QSwipeGesture* gesture)
00386 {
00387     event->ignore(gesture);
00388 }
00389 
00390 bool MWidget::event(QEvent *event)
00391 {
00392     QEvent::Type type = event->type();
00393     switch(type) {
00394         case QEvent::ActionAdded:
00395         case QEvent::ActionChanged:
00396         case QEvent::ActionRemoved:
00397             actionEvent(static_cast<QActionEvent *>(event));
00398             break;
00399         case QEvent::LanguageChange:
00400             // retranslate the ui strings of this MWidget:
00401             retranslateUi();
00402             break;
00403         case QEvent::Gesture:
00404             gestureEvent(static_cast<QGestureEvent*>(event));
00405             break;
00406         case QEvent::LayoutRequest: {
00407             //When you have a widget inside a layout in a widget inside a layout in a widget...
00408             //and the innermost widget or layout's sizehint is invalidated only the parent is notified in the next
00409             //event loop. And that will notify its parent in the event loop after, and so on.  It can thus take many iterations
00410             //of the event loop before the layout has settled down, leading to a visual 'jumping around' effect.
00411             //So we manually invalidate the sizehint for all the parents immediately.
00412             QGraphicsLayoutItem *item = this;
00413             do {
00414                 item->updateGeometry();
00415             } while( (item = item->parentLayoutItem()) );
00416             break;
00417         }
00418         default:
00419            if(type >= QEvent::User) {
00420                if (type == MCancelEvent::eventNumber())
00421                    cancelEvent((MCancelEvent *)event);
00422                else if (type == MOrientationChangeEvent::eventNumber())
00423                    orientationChangeEvent( static_cast<MOrientationChangeEvent *>(event) );
00424                else if (type == MOnDisplayChangeEvent::eventNumber())
00425                    onDisplayChangeEvent( static_cast<MOnDisplayChangeEvent *>(event) );
00426            }
00427     }
00428     return QGraphicsWidget::event(event);
00429 }
00430 
00431 bool MWidget::sceneEvent(QEvent *event)
00432 {
00433     QEvent::Type type = event->type();
00434     switch(type) {
00435         case QEvent::TouchBegin:
00436            if(acceptTouchEvents()) {
00437                event->setAccepted(true);
00438                return true;
00439            }
00440            break;
00441         default:
00442            break;
00443     }
00444     return QGraphicsWidget::sceneEvent(event);
00445 }
00446 
00447 void MWidget::cancelEvent(MCancelEvent *event)
00448 {
00449     Q_UNUSED(event);
00450 }
00451 
00452 void MWidget::orientationChangeEvent(MOrientationChangeEvent *event)
00453 {
00454     Q_UNUSED(event);
00455 }
00456 
00457 void MWidget::actionEvent(QActionEvent *)
00458 {
00459 }
00460 
00461 void MWidget::retranslateUi()
00462 {
00463     // do nothing
00464 }
00465 
00466 void MWidget::setSelected(bool selected)
00467 {
00468     Q_D(MWidget);
00469 
00470     if (d->selected == selected)
00471         return;
00472 
00473     const QVariant newSelectedVariant(itemChange(QGraphicsItem::ItemSelectedChange, quint32(selected)));
00474 
00475     bool newSelected = newSelectedVariant.toBool();
00476     if (d->selected == newSelected)
00477         return;
00478     d->selected = newSelected;
00479 
00480     update();
00481 
00482     // Deliver post-change notification.
00483     itemChange(QGraphicsItem::ItemSelectedHasChanged, newSelectedVariant);
00484 }
00485 
00486 bool MWidget::isSelected() const
00487 {
00488     Q_D(const MWidget);
00489 
00490     return d->selected;
00491 }
00492 
00493 void MWidget::setVisible(bool visible)
00494 {
00495     Q_D(MWidget);
00496     d->explicitlyHidden = !visible;
00497 
00498     // Only show if the layout is not hiding this
00499     if (!d->layoutHidden) {
00500 
00501         // FIXME: Workaround for bug NB#186278.
00502         QGraphicsItem *focused = focusItem();
00503         if (visible && focused && !focused->hasFocus()) {
00504             focused->setFlag(QGraphicsItem::ItemIsFocusable, false);
00505             QGraphicsWidget::setVisible(true);
00506             focused->setFlag(QGraphicsItem::ItemIsFocusable, true);
00507         } else {
00508             QGraphicsWidget::setVisible(visible);
00509         }
00510 
00511         // Propagate visibility events
00512         QGraphicsView *graphicsView = d->fetchGraphicsView();
00513         if (graphicsView) {
00514             QRectF visibleSceneRect = graphicsView->sceneRect();
00515 
00516             // show() called: resolve visibility
00517             if (visible) {
00518                 if (isOnDisplay()) {
00519                     MOnDisplayChangeEvent event(MOnDisplayChangeEvent::FullyOnDisplay,
00520                                             visibleSceneRect);
00521                     d->resolveIsOnDisplay(this, &visibleSceneRect, &event);
00522                 }
00523             // hide() called: explicitly send FullyOffDisplay
00524             } else {
00525                 MOnDisplayChangeEvent event(MOnDisplayChangeEvent::FullyOffDisplay,
00526                                             visibleSceneRect);
00527                 d->resolveIsOnDisplay(this, &visibleSceneRect, &event);
00528             }
00529         }
00530     }
00531 }
00532 
00533 QPointF MWidget::paintOffset() const
00534 {
00535     return QPointF(transform().dx(), transform().dy());
00536 }
00537 
00538 void MWidget::setPaintOffset(const QPointF &newOffset)
00539 {
00540     setTransform(QTransform::fromTranslate(newOffset.x(), newOffset.y()));
00541 }

Copyright © 2010 Nokia Corporation Generated on Thu Nov 4 2010 18:14:22 (PDT)
Doxygen 1.7.1
MeeGo Touch