| Home · All Classes · Main Classes · Deprecated |
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 |