30 #include "hbdeviceprofile.h" |
30 #include "hbdeviceprofile.h" |
31 #include "hbevent.h" |
31 #include "hbevent.h" |
32 #include "hbgraphicsscene.h" |
32 #include "hbgraphicsscene.h" |
33 #include "hbgraphicsscene_p.h" |
33 #include "hbgraphicsscene_p.h" |
34 #include "hbtooltip.h" |
34 #include "hbtooltip.h" |
|
35 #include "hbglobal_p.h" |
35 #include <QTimer> |
36 #include <QTimer> |
36 #include <QGraphicsSceneMouseEvent> |
37 #include <QGraphicsSceneMouseEvent> |
37 #include <QShowEvent> |
38 #include <QShowEvent> |
38 #include <QHideEvent> |
39 #include <QHideEvent> |
39 #include <QEventLoop> |
40 #include <QEventLoop> |
40 #include <QPointer> |
41 #include <QPointer> |
|
42 #include <QDebug> |
|
43 #include <QBitmap> |
41 #include <QApplication> // krazy:exclude=qclasses |
44 #include <QApplication> // krazy:exclude=qclasses |
42 |
45 |
43 #include <hbwidgetfeedback.h> |
46 #include <hbwidgetfeedback.h> |
44 |
47 |
45 #ifdef HB_EFFECTS |
48 #ifdef HB_EFFECTS |
46 #include "hbeffectinternal_p.h" |
49 #include "hbeffectinternal_p.h" |
47 bool HbPopupPrivate::popupEffectsLoaded = false; |
50 bool HbPopupPrivate::popupEffectsLoaded = false; |
48 #endif |
51 #endif |
49 /*! |
52 /*! |
50 @stable |
53 @beta |
51 @hbcore |
54 @hbcore |
52 \class HbPopup |
55 \class HbPopup |
53 \brief HbPopup is a base class for different popup notes in Hb library. |
56 \brief HbPopup is a base class for different popup notes in Hb library. |
54 |
57 |
55 \image html hbpopup.png A popup with a header widget, a list as a content widget, and two |
58 \image html hbpopup.png A popup with a header widget, a list as a content widget, and two |
279 backgroundItem(0), |
282 backgroundItem(0), |
280 mousePressLocation(None), |
283 mousePressLocation(None), |
281 frameType(HbPopup::Strong), |
284 frameType(HbPopup::Strong), |
282 preferredPosSet(false), |
285 preferredPosSet(false), |
283 mStartEffect(false), |
286 mStartEffect(false), |
|
287 mScreenMargin(0.0), |
|
288 mPath(0), |
284 timeoutTimerInstance(0) |
289 timeoutTimerInstance(0) |
285 { |
290 { |
286 } |
291 } |
287 |
292 |
288 HbPopupPrivate::~HbPopupPrivate() |
293 HbPopupPrivate::~HbPopupPrivate() |
302 // Only for popup without parent |
307 // Only for popup without parent |
303 if (!q->parentItem()) { |
308 if (!q->parentItem()) { |
304 backgroundItem = new HbPopupBackGround(q); |
309 backgroundItem = new HbPopupBackGround(q); |
305 backgroundItem->setVisible(false); |
310 backgroundItem->setVisible(false); |
306 |
311 |
307 // Popup is invisible by default (explicit show or exec call is required) |
312 // Popup is invisible by default (explicit show or open call is required) |
308 q->setVisible(false); |
313 q->setVisible(false); |
309 } |
314 } |
310 hidingInProgress = false; |
315 hidingInProgress = false; |
|
316 |
|
317 q->setFlag(QGraphicsItem::ItemClipsToShape); |
|
318 q->setFlag(QGraphicsItem::ItemClipsChildrenToShape); |
|
319 |
|
320 #if QT_VERSION > 0x040602 |
|
321 q->grabGesture(Qt::TapGesture); |
|
322 q->grabGesture(Qt::TapAndHoldGesture); |
|
323 q->grabGesture(Qt::PanGesture); |
|
324 q->grabGesture(Qt::SwipeGesture); |
|
325 q->grabGesture(Qt::PinchGesture); |
|
326 #endif |
|
327 |
311 } |
328 } |
312 |
329 |
313 /* |
330 /* |
314 * *********** Begin of private features *********** |
331 * *********** Begin of private features *********** |
315 */ |
332 */ |
394 } |
411 } |
395 |
412 |
396 return timeoutTimerInstance; |
413 return timeoutTimerInstance; |
397 } |
414 } |
398 |
415 |
399 void HbPopupPrivate::handleKeyEvent(QKeyEvent *event) |
|
400 { |
|
401 Q_Q(HbPopup); |
|
402 event->accept(); |
|
403 |
|
404 // Any key event dismisses the popup if dismissPolicy includes TapInside flag |
|
405 if (dismissPolicy & HbPopup::TapInside && !q->parentItem()) { |
|
406 q->close(); |
|
407 } |
|
408 } |
|
409 |
|
410 //returns true if popup has been added to scene here. |
416 //returns true if popup has been added to scene here. |
411 bool HbPopupPrivate::addPopupToScene() |
417 bool HbPopupPrivate::addPopupToScene() |
412 { |
418 { |
413 Q_Q(HbPopup); |
419 Q_Q(HbPopup); |
414 bool popupAdded(false); |
420 bool popupAdded(false); |
415 if (!q->parentItem()) { |
421 if (!q->parentItem()) { |
416 if (!q->scene() && !HbInstance::instance()->allMainWindows().isEmpty()) { |
422 if (!q->scene() && !HbInstance::instance()->allMainWindows().isEmpty()) { |
417 HbInstance::instance()->allMainWindows().at(0)->scene()->addItem(q); |
423 HbInstance::instance()->allMainWindows().at(0)->scene()->addItem(q); |
418 popupAdded = true; |
424 popupAdded = true; |
419 if (backgroundItem) { |
425 if (backgroundItem) { |
420 q->scene()->addItem(backgroundItem); |
426 q->scene()->addItem(backgroundItem); |
421 } |
427 } |
422 } else if (q->scene() && backgroundItem && backgroundItem->scene() != q->scene()) { |
428 } else if (q->scene() && backgroundItem && backgroundItem->scene() != q->scene()) { |
521 if(backgroundItem) { |
527 if(backgroundItem) { |
522 // When the popup is modal background item must receive focus |
528 // When the popup is modal background item must receive focus |
523 // events to be able to prevent last focus item losing its |
529 // events to be able to prevent last focus item losing its |
524 // focus |
530 // focus |
525 backgroundItem->setFlag(QGraphicsItem::ItemIsFocusable, modal); |
531 backgroundItem->setFlag(QGraphicsItem::ItemIsFocusable, modal); |
526 } |
532 backgroundItem->setFlag(QGraphicsItem::ItemIsPanel, modal); |
|
533 if(modal) { |
|
534 backgroundItem->setPanelModality(QGraphicsItem::PanelModal); |
|
535 } else { |
|
536 backgroundItem->setPanelModality(QGraphicsItem::NonModal); |
|
537 } |
|
538 } |
|
539 } |
|
540 |
|
541 void HbPopupPrivate::calculateShape() |
|
542 { |
|
543 Q_Q(HbPopup); |
|
544 if (mPath) |
|
545 delete mPath; |
|
546 mPath = new QPainterPath(); |
|
547 #if 1 |
|
548 QPixmap image(QSize(static_cast<int>(q->backgroundItem()->boundingRect().width() + 0.5), |
|
549 static_cast<int>(q->backgroundItem()->boundingRect().height() + 0.5))); |
|
550 image.fill(Qt::transparent); |
|
551 |
|
552 QPainter imagePainter(&image); |
|
553 |
|
554 q->backgroundItem()->paint(&imagePainter, 0, 0); |
|
555 |
|
556 imagePainter.end(); |
|
557 |
|
558 mPath->addRegion(image.mask()); |
|
559 #else |
|
560 QRectF rect(-0.5, -0.5, q->boundingRect().width() + 0.5, q->boundingRect().height() + 0.5); |
|
561 mPath->addRoundedRect(rect, 12, 12); |
|
562 #endif |
|
563 |
|
564 mPath->translate(-0.5, -0.5); |
527 } |
565 } |
528 |
566 |
529 /*! |
567 /*! |
530 * Constructs a popup with given \a parent graphics item.\n |
568 * Constructs a popup with given \a parent graphics item.\n |
531 * Note: popups with \a parent set as 0 are behaving as real popups. |
569 * Note: popups with \a parent set as 0 are behaving as real popups. |
740 * For non modal popups, use show(). |
778 * For non modal popups, use show(). |
741 */ |
779 */ |
742 void HbPopup::open( QObject *receiver, const char *member ) |
780 void HbPopup::open( QObject *receiver, const char *member ) |
743 { |
781 { |
744 Q_D(HbPopup); |
782 Q_D(HbPopup); |
745 connect(this, SIGNAL(aboutToClose()), receiver, member); |
783 if (receiver) { |
|
784 connect(this, SIGNAL(aboutToClose()), receiver, member); |
|
785 } |
746 d->receiverToDisconnectOnClose = receiver; |
786 d->receiverToDisconnectOnClose = receiver; |
747 d->memberToDisconnectOnClose = member; |
787 d->memberToDisconnectOnClose = member; |
748 |
788 |
749 #if needed |
|
750 // Ungrab the mouse if it is currently grabbed |
|
751 // todo; currently needed menus to work ok, otherwise: |
|
752 // - quick multiple presses on menuitem causes multiple actions (menu relaunch?) |
|
753 // - closing menu with titlepane needs multiple presses (menu relaunch?) |
|
754 // Ungrab was removed when trying to fix problem when button pressed()-signal |
|
755 // was connected to menu launch. Button did not get anymore mouse release event. |
|
756 if (scene()) { |
|
757 QGraphicsItem *item = scene()->mouseGrabberItem(); |
|
758 if (item) { |
|
759 item->ungrabMouse(); |
|
760 } |
|
761 } |
|
762 #endif |
|
763 show(); |
789 show(); |
764 } |
790 } |
765 |
791 |
766 |
792 |
767 /*! |
793 /*! |
768 \deprecated HbPopup::exec() |
794 \deprecated HbPopup::exec() |
769 is deprecated. Please use HbPopup::show() or |
795 is deprecated. Please use HbPopup::show() or |
770 void HbPopup::open( QObject *receiver, const char *member ) instead. |
796 void HbPopup::open( QObject *receiver, const char *member ) instead. |
771 * |
797 |
772 * Executes the popup synchronously. |
798 Executes the popup synchronously. |
773 * Note: when popup is executed syncronously it is always modal. |
799 Note: when popup is executed syncronously it is always modal. |
774 * This function is deprecated. use \sa open() or \sa show() instead. |
800 This function is deprecated. use \sa open() or \sa show() instead. |
775 */ |
801 */ |
776 void HbPopup::exec() |
802 void HbPopup::exec() |
777 { |
803 { |
778 // Q_ASSERT(false); |
804 HB_DEPRECATED("HbPopup::exec is deprecated. Use HbPopup::show() or HbPopup::open() instead!"); |
779 Q_D(HbPopup); |
805 Q_D(HbPopup); |
780 |
806 |
781 HbMainWindow* w(mainWindow()); |
807 HbMainWindow* w(mainWindow()); |
782 if (w) { |
808 if (w) { |
783 disconnect(w, SIGNAL(aboutToChangeOrientation(Qt::Orientation, bool)), this, SLOT(_q_orientationChange(Qt::Orientation, bool))); |
809 disconnect(w, SIGNAL(aboutToChangeOrientation(Qt::Orientation, bool)), this, SLOT(_q_orientationChange(Qt::Orientation, bool))); |
845 d->aboutToShowSignalGuard = true; |
871 d->aboutToShowSignalGuard = true; |
846 emit aboutToShow(); |
872 emit aboutToShow(); |
847 } |
873 } |
848 // Note: when visibility changes to "visible" base class implementation needs |
874 // Note: when visibility changes to "visible" base class implementation needs |
849 // to be called otherwise showEvent() is not called. |
875 // to be called otherwise showEvent() is not called. |
850 |
|
851 } else { |
876 } else { |
852 d->aboutToShowSignalGuard = false; |
877 d->aboutToShowSignalGuard = false; |
853 if (!d->hidingInProgress) { |
878 if (!d->hidingInProgress) { |
854 emit aboutToHide(); |
879 emit aboutToHide(); |
855 } |
880 } |
965 return; |
981 return; |
966 } |
982 } |
967 if (!parentItem()) { |
983 if (!parentItem()) { |
968 //check if popup needs to be added to scene.This can result in duplciate show event, |
984 //check if popup needs to be added to scene.This can result in duplciate show event, |
969 // if popup is added to scene here. |
985 // if popup is added to scene here. |
970 if(d->addPopupToScene()) |
986 if(d->addPopupToScene()) { |
971 d->duplicateShowEvent = true; |
987 d->duplicateShowEvent = true; |
972 |
988 } |
973 // Popup clears closed state |
989 // Popup clears closed state |
974 d->closed = false; |
990 d->closed = false; |
975 if (d->backgroundItem) { |
991 if (d->backgroundItem) { |
976 d->backgroundItem->setVisible(true); |
992 d->backgroundItem->setVisible(true); |
977 d->backgroundItem->setAcceptHoverEvents(isModal()); |
993 d->backgroundItem->setAcceptHoverEvents(isModal()); |
978 // Let the background be a panel if the popup is one |
994 if (isModal()) { |
979 // However if the popup is not modal we don't want the background |
|
980 // to be a panel. A panel provides contained focus handling |
|
981 if ((flags() & QGraphicsItem::ItemIsPanel) && isModal()) { |
|
982 d->backgroundItem->setFlag(QGraphicsItem::ItemIsPanel); |
995 d->backgroundItem->setFlag(QGraphicsItem::ItemIsPanel); |
983 } |
996 } |
984 } |
997 } |
985 if (qobject_cast<HbGraphicsScene *>(scene())) { |
998 if (qobject_cast<HbGraphicsScene *>(scene())) { |
986 qobject_cast<HbGraphicsScene *>(scene())->d_ptr->showPopup(this); |
999 qobject_cast<HbGraphicsScene *>(scene())->d_ptr->showPopup(this); |
987 HbWidgetFeedback::triggered(this, Hb::InstantPopupOpened); |
1000 HbWidgetFeedback::triggered(this, Hb::InstantPopupOpened); |
988 } |
1001 } |
1085 /*! |
1104 /*! |
1086 \reimp |
1105 \reimp |
1087 */ |
1106 */ |
1088 bool HbPopup::event(QEvent *event) |
1107 bool HbPopup::event(QEvent *event) |
1089 { |
1108 { |
1090 /*Q_D(HbPopup); |
1109 /* Q_D(HbPopup); |
1091 if (event->type() == QEvent::GraphicsSceneResize) { |
1110 if (event->type() == QEvent::LayoutRequest) { |
1092 //Workaround when showing first time |
1111 //Workaround when showing first time |
1093 #ifdef HB_EFFECTS |
1112 #ifdef HB_EFFECTS |
1094 if(d->mStartEffect && boundingRect().isValid()) { |
1113 if(d->mStartEffect && boundingRect().isValid()) { |
|
1114 d->mStartEffect = false; |
|
1115 QCoreApplication::sendPostedEvents(this, QEvent::LayoutRequest); |
1095 QRectF extRect(0.0, |
1116 QRectF extRect(0.0, |
1096 -boundingRect().height(), |
1117 -boundingRect().height(), |
1097 boundingRect().width(), |
1118 boundingRect().width(), |
1098 0); |
1119 0); |
1099 HbEffect::start(this, d->effectType, "appear", 0, 0, QVariant(), extRect); |
1120 HbEffect::start(this, d->effectType, "appear", 0, 0, QVariant(), extRect); |
1100 d->mStartEffect = false; |
1121 qDebug() << "effect start"; |
1101 } |
1122 } |
1102 #endif//HB_EFFECTS |
1123 #endif//HB_EFFECTS |
1103 //workaround ends |
1124 //workaround ends |
|
1125 } |
|
1126 qDebug() << "event: " << event;*/ |
|
1127 /*Q_D(HbPopup); |
|
1128 if (event->type() == QEvent::LayoutDirectionChange) { |
|
1129 d->calculateShape(); |
1104 }*/ |
1130 }*/ |
1105 return HbWidget::event(event); |
1131 return HbWidget::event(event); |
1106 } |
1132 } |
1107 |
|
1108 |
1133 |
1109 /*! |
1134 /*! |
1110 Sets preferred position\a position for popup with \a placement |
1135 Sets preferred position\a position for popup with \a placement |
1111 as origin. |
1136 as origin. |
1112 |
1137 |
1123 |
1148 |
1124 */ |
1149 */ |
1125 |
1150 |
1126 void HbPopup::setPreferredPos( const QPointF& preferredPos, |
1151 void HbPopup::setPreferredPos( const QPointF& preferredPos, |
1127 HbPopup::Placement placement ) |
1152 HbPopup::Placement placement ) |
1128 |
|
1129 { |
1153 { |
1130 Q_D(HbPopup); |
1154 Q_D(HbPopup); |
1131 bool layoutFlag = false; |
1155 bool layoutFlag = false; |
1132 if (d->preferredPos != preferredPos ) { |
1156 if (d->preferredPos != preferredPos ) { |
1133 d->preferredPos = preferredPos; |
1157 d->preferredPos = preferredPos; |
1138 layoutFlag = true; |
1162 layoutFlag = true; |
1139 } |
1163 } |
1140 d->preferredPosSet = true; |
1164 d->preferredPosSet = true; |
1141 //If position updated, informing layoutproxy with layoutrequest |
1165 //If position updated, informing layoutproxy with layoutrequest |
1142 if (layoutFlag) { |
1166 if (layoutFlag) { |
1143 QApplication::postEvent(this, new QEvent(QEvent::LayoutRequest)); |
1167 QApplication::sendEvent(this, new QEvent(QEvent::LayoutRequest)); |
1144 } |
1168 } |
|
1169 } |
|
1170 |
|
1171 QPainterPath HbPopup::shape() const |
|
1172 { |
|
1173 #if 1 |
|
1174 Q_D(const HbPopup); |
|
1175 if (backgroundItem() && d->mPath) { |
|
1176 return *d->mPath; |
|
1177 } else { |
|
1178 return HbWidget::shape(); |
|
1179 } |
|
1180 #else |
|
1181 return HbWidget::shape(); |
|
1182 #endif |
1145 } |
1183 } |
1146 |
1184 |
1147 #include "moc_hbpopup.cpp" |
1185 #include "moc_hbpopup.cpp" |