src/hbcore/gui/hbpopup.cpp
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbCore module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 
       
    26 #include "hbpopup.h"
       
    27 #include "hbpopup_p.h"
       
    28 #include "hbinstance.h"
       
    29 #include "hbpopupmanager_p.h"
       
    30 #include "hbdeviceprofile.h"
       
    31 #include "hbevent.h"
       
    32 #include "hbgraphicsscene.h"
       
    33 #include "hbgraphicsscene_p.h"
       
    34 #include "hbtooltip.h"
       
    35 #include <QTimer>
       
    36 #include <QGraphicsSceneMouseEvent>
       
    37 #include <QShowEvent>
       
    38 #include <QHideEvent>
       
    39 #include <QEventLoop>
       
    40 #include <QPointer>
       
    41 #include <QApplication> // krazy:exclude=qclasses
       
    42 
       
    43 #include <hbwidgetfeedback.h>
       
    44 
       
    45 #ifdef HB_EFFECTS
       
    46 #include "hbeffectinternal_p.h"
       
    47 bool HbPopupPrivate::popupEffectsLoaded = false;
       
    48 #endif
       
    49 /*!
       
    50     @stable
       
    51     @hbcore
       
    52     \class HbPopup
       
    53     \brief HbPopup is a base class for different popup notes in Hb library.
       
    54 
       
    55     \image html hbpopup.png A popup with a header widget, a list as a content widget, and two
       
    56     action buttons.
       
    57 
       
    58     HbPopup is a concrete class. The content for a custom popup is implemented in
       
    59     a separate widget, which is set to the popup with method setContentWidget().
       
    60 
       
    61     Lastly shown popup is always positioned in Z order on the the top of already visible popups.
       
    62     A popup can be permanent or automatically dismissed after a time-out.
       
    63     Modal popups interrupt any other user interaction outside of the popup while they are visible,
       
    64     whereas non-modal popups do not.
       
    65 
       
    66     An example of how to create a simple modal popup and show it.
       
    67     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,13}
       
    68 
       
    69     An example of how to create a non-modal popup and show it.
       
    70     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,26}
       
    71 
       
    72 */
       
    73 
       
    74 /*!
       
    75     \reimp
       
    76     \fn int HbPopup::type() const
       
    77  */
       
    78 
       
    79 /*!
       
    80     \enum HbPopup::DefaultTimeout
       
    81 
       
    82     This enum defines available default timeout values to be used in method
       
    83     setTimeout(HbPopup::DefaultTimeout).
       
    84  */
       
    85 
       
    86 /*!
       
    87     \var HbPopup::NoTimeout
       
    88 
       
    89     No timeout is defined for automatically closing the popup. i.e. the popup is permanent.
       
    90  */
       
    91 
       
    92 /*!
       
    93     \var HbPopup::ConfirmationNoteTimeout
       
    94 
       
    95     Timeout value intended to be used by confirmation notes.
       
    96  */
       
    97 
       
    98 /*!
       
    99     \var HbPopup::StandardTimeout
       
   100 
       
   101     The default timeout value intended to be used by most non-permanent popups e.g. by notes.
       
   102  */
       
   103 
       
   104 /*!
       
   105     \var HbPopup::ContextMenuTimeout
       
   106 
       
   107     The default timeout value intended to be used by context menus.
       
   108  */
       
   109 
       
   110 /*!
       
   111     \enum HbPopup::DismissPolicy
       
   112 
       
   113     This enum defines available dismiss policy values.
       
   114 
       
   115     The dismiss policy defines what user actions will cause the popup to be dismissed i.e. closed.
       
   116  */
       
   117 
       
   118 /*!
       
   119     \var HbPopup::NoDismiss
       
   120 
       
   121     The popup cannot be dismissed automatically by user interaction.
       
   122  */
       
   123 
       
   124 /*!
       
   125     \var HbPopup::TapInside
       
   126 
       
   127     The popup is dismissed when user taps within the bounding rectangle of the popup.
       
   128  */
       
   129 
       
   130 /*!
       
   131     \var HbPopup::TapOutside
       
   132 
       
   133     The popup is dismissed when user taps outside of the bounding rectangle of the popup.
       
   134  */
       
   135 
       
   136 /*!
       
   137     \var HbPopup::TapAnywhere
       
   138 
       
   139     The popup is dismissed when user taps either within or outside
       
   140     of the bounding rectangle of the popup.
       
   141  */
       
   142 
       
   143 /*!
       
   144     \enum HbPopup::FrameType
       
   145 
       
   146     This enum defines available frame type values.
       
   147 
       
   148     The frame types defines what frame item backgrounds will be used by the popup.
       
   149  */
       
   150 
       
   151 /*!
       
   152     \var HbPopup::Strong
       
   153 
       
   154     The popup is using strong frame.
       
   155  */
       
   156 
       
   157 /*!
       
   158     \var HbPopup::Weak
       
   159 
       
   160     The popup is using weak frame.
       
   161  */
       
   162 
       
   163 /*!
       
   164     \fn void HbPopup::aboutToShow();
       
   165 
       
   166     This signal is emitted when the popup is about to be shown i.e. when method show() is called.
       
   167  */
       
   168 
       
   169 /*!
       
   170     \fn void HbPopup::aboutToHide();
       
   171 
       
   172     This signal is emitted when the popup is about to be hidden i.e. when method hide() is called.
       
   173  */
       
   174 
       
   175 
       
   176 /*!
       
   177     \fn void HbPopup::aboutToClose();
       
   178 
       
   179     This signal is emitted when the popup is about to be closed i.e. when method close() is called
       
   180     or the popup is
       
   181     dismissed by the user or timeout.
       
   182  */
       
   183 
       
   184 static const struct { HbPopup::DefaultTimeout timeout; int value; } timeoutValues[] =
       
   185 {
       
   186     {HbPopup::NoTimeout,0},
       
   187     {HbPopup::ConfirmationNoteTimeout,1500},
       
   188     {HbPopup::StandardTimeout,3000},
       
   189     {HbPopup::ContextMenuTimeout,6000},
       
   190 };
       
   191 
       
   192 HbPopupBackGround::HbPopupBackGround(HbPopup * popup, QGraphicsItem *parent) :
       
   193         QGraphicsItem(parent),
       
   194         popup(popup)
       
   195 {
       
   196     // This is needed to be able to block moving the focus to items behind background item by
       
   197     // clicking on them.
       
   198     setFlag(QGraphicsItem::ItemIsFocusable);
       
   199 
       
   200 #if QT_VERSION >= 0x040600
       
   201     setFlag(QGraphicsItem::ItemHasNoContents, true);
       
   202 #endif
       
   203 }
       
   204 
       
   205 HbPopupBackGround::~HbPopupBackGround()
       
   206 {
       
   207     // Set backgroundItem to 0 to avoid double deletion
       
   208     // e.g. when backgroundItem is deleted by scene before its popup
       
   209     if (popup) {
       
   210         HbPopupPrivate::d_ptr(popup)->backgroundItem = 0;
       
   211     }
       
   212 }
       
   213 
       
   214 void HbPopupBackGround::setRect(QRectF rect)
       
   215 {
       
   216     mRect = rect;
       
   217 }
       
   218 
       
   219 QRectF HbPopupBackGround::boundingRect() const
       
   220 {
       
   221     if(!mRect.isValid()){
       
   222         // set backgroundItem's size so that it is big enough
       
   223         // to cover the screen both landscape and portrait mode
       
   224         const QSizeF screenSize = HbDeviceProfile::profile(this).logicalSize();
       
   225         qreal dim = qMax(screenSize.width(), screenSize.height());
       
   226         mRect.adjust(0,0,dim,dim);
       
   227     }
       
   228     return mRect;
       
   229 }
       
   230 
       
   231 void HbPopupBackGround::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
       
   232 {
       
   233     Q_UNUSED(option)
       
   234     Q_UNUSED(widget);
       
   235     Q_UNUSED(painter);
       
   236 }
       
   237 
       
   238 bool HbPopupBackGround::sceneEvent(QEvent *event)
       
   239 {
       
   240     if (event->type() == QEvent::GraphicsSceneMousePress) {
       
   241         HbPopupPrivate::d_ptr(popup)->handleBackgroundMousePressEvent();
       
   242     }
       
   243     if (event->type() == QEvent::GraphicsSceneMouseRelease) {
       
   244         HbPopupPrivate::d_ptr(popup)->handleBackgroundMouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
       
   245     }
       
   246     if (event->type() == QEvent::FocusIn && scene()) {
       
   247         // Prevents last focus item losing its focus
       
   248         // This event is received only when popup is modal
       
   249         QFocusEvent restoreLastFocus(QEvent::FocusIn,Qt::OtherFocusReason);
       
   250         QApplication::sendEvent(scene(),&restoreLastFocus); // krazy:exclude=qclasses
       
   251     }
       
   252     // accept events only for modal popups
       
   253     if(popup->isModal()){
       
   254         event->accept();
       
   255         return true;
       
   256     } else {
       
   257         event->ignore();
       
   258     }
       
   259     return QGraphicsItem::sceneEvent(event);
       
   260 }
       
   261 
       
   262 HbPopupPrivate::HbPopupPrivate( ) :
       
   263     eventLoop(0),
       
   264     hasEffects(false),
       
   265     closed(false),
       
   266     hidingInProgress(true),
       
   267     delayedHide(false),
       
   268     deleteOnClose(false),
       
   269     modal(true), // must be in sync QGraphicsItem::ItemIsFocusable of backgroundItem
       
   270     fadeBackground(true),
       
   271     inDestruction(false),
       
   272     aboutToShowSignalGuard(false),
       
   273     duplicateShowEvent(false),
       
   274     timedOut(false),
       
   275     timeout(HbPopupPrivate::timeoutValue(HbPopup::StandardTimeout)),
       
   276     //    priorityValue(HbPopup::Default),
       
   277     priorityValue(0),
       
   278     dismissPolicy(HbPopup::TapOutside),
       
   279     backgroundItem(0),
       
   280     mousePressLocation(None),
       
   281     frameType(HbPopup::Strong),
       
   282     preferredPosSet(false),
       
   283     mStartEffect(false),
       
   284     timeoutTimerInstance(0)
       
   285 {
       
   286 }
       
   287 
       
   288 HbPopupPrivate::~HbPopupPrivate()
       
   289 {
       
   290 }
       
   291 
       
   292 void HbPopupPrivate::init()
       
   293 {
       
   294     Q_Q(HbPopup);
       
   295 
       
   296     q->setAttribute(Hb::InsidePopup);
       
   297 
       
   298     // By default popups are focusable
       
   299     q->setFocusPolicy(Qt::StrongFocus);    
       
   300     q->setBackgroundItem(HbStyle::P_Popup_background);
       
   301 
       
   302     // Only for popup without parent
       
   303     if (!q->parentItem()) {
       
   304         backgroundItem = new HbPopupBackGround(q);
       
   305         backgroundItem->setVisible(false);
       
   306 
       
   307         // Popup is invisible by default (explicit show or exec call is required)
       
   308         q->setVisible(false);
       
   309     }
       
   310     hidingInProgress = false;   
       
   311 }
       
   312 
       
   313 /*
       
   314 *  *********** Begin of private features ***********
       
   315 */
       
   316 
       
   317 /*
       
   318 * Sets the priority for a popup.
       
   319 * A popup with higher priority is always shown on top of a popup with lower priority.
       
   320 * In case of popups with same priority the lastly shown will be on top.
       
   321 * Default priority is HbPopup::Default
       
   322 * \sa priority()
       
   323 */
       
   324 void HbPopupPrivate::setPriority(quint8 priority)
       
   325 {
       
   326     //TODO: consider implementing dynamic change of prorities
       
   327     // i.e. if the priority changes while the popup is registered to popupManager
       
   328     // then re-register it to get its Z value updated
       
   329     priorityValue=priority;
       
   330 }
       
   331 
       
   332 /*
       
   333 *  *********** End of private features ***********
       
   334 */
       
   335 #ifdef HB_EFFECTS
       
   336 void HbPopupPrivate::_q_delayedHide(HbEffect::EffectStatus status)
       
   337 {
       
   338     Q_UNUSED(status);
       
   339 
       
   340     Q_Q(HbPopup);
       
   341 
       
   342     // Apply forceHide only if the effect started successfully
       
   343     if (status.reason != Hb::EffectNotStarted) {
       
   344         forceHide();
       
   345     } else {
       
   346         delayedHide = false;
       
   347     }
       
   348 
       
   349     if (deleteOnClose) {
       
   350         q->deleteLater();
       
   351     }
       
   352     hidingInProgress = false;
       
   353 }
       
   354 
       
   355 void HbPopupPrivate::_q_orientationChange(Qt::Orientation orient, bool animate)
       
   356 {
       
   357     Q_UNUSED(orient);
       
   358     if (animate) {
       
   359     Q_Q(HbPopup);
       
   360     HbEffect::start(q, "HB_POPUP", "orientationswitch");
       
   361     }
       
   362 
       
   363 }
       
   364 #endif // HB_EFFECTS
       
   365 
       
   366 void HbPopupPrivate::_q_timeoutFinished()
       
   367 {
       
   368     Q_Q(HbPopup);
       
   369     timedOut = true;
       
   370     q->close();
       
   371 }
       
   372 
       
   373 void HbPopupPrivate::stopTimeout()
       
   374 {
       
   375     if (timeoutTimerInstance)
       
   376         timeoutTimerInstance->stop();
       
   377 }
       
   378 
       
   379 void HbPopupPrivate::startTimeout()
       
   380 {
       
   381     if (timeout > 0) {
       
   382         timeoutTimer()->start();
       
   383         timedOut = false;
       
   384     }
       
   385 }
       
   386 
       
   387 QTimer *HbPopupPrivate::timeoutTimer()
       
   388 {
       
   389     Q_Q(HbPopup);
       
   390     if (!timeoutTimerInstance) {
       
   391         timeoutTimerInstance = new QTimer(q);
       
   392         timeoutTimerInstance->setSingleShot(true);
       
   393         q->connect(timeoutTimerInstance, SIGNAL(timeout()), q, SLOT(_q_timeoutFinished()));
       
   394     }
       
   395 
       
   396     return timeoutTimerInstance;
       
   397 }
       
   398 
       
   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.
       
   411 bool HbPopupPrivate::addPopupToScene()
       
   412 {
       
   413     Q_Q(HbPopup);
       
   414     bool popupAdded(false);
       
   415     if (!q->parentItem()) {
       
   416         if (!q->scene() && !HbInstance::instance()->allMainWindows().isEmpty()) {
       
   417             HbInstance::instance()->allMainWindows().at(0)->scene()->addItem(q);
       
   418             popupAdded = true;
       
   419             if (backgroundItem) {
       
   420                 q->scene()->addItem(backgroundItem);
       
   421             }
       
   422         } else if (q->scene() && backgroundItem && backgroundItem->scene() != q->scene()) {
       
   423             q->scene()->addItem(backgroundItem);
       
   424         }
       
   425     }
       
   426     return popupAdded;
       
   427 }
       
   428 
       
   429 void HbPopupPrivate::handleBackgroundMousePressEvent()
       
   430 {
       
   431     mousePressLocation = Background;
       
   432 }
       
   433 
       
   434 void HbPopupPrivate::handleBackgroundMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
       
   435 {
       
   436     Q_Q(HbPopup);
       
   437 
       
   438     // Handle cases only for Background or Popup originated mouse presses and when
       
   439     // any dismiss policy defined
       
   440     if (mousePressLocation != None && dismissPolicy != HbPopup::NoDismiss) {
       
   441 
       
   442         MouseEventLocationType mouseReleaseLocation = Background;
       
   443 
       
   444         if (q->contains (q->mapFromScene(event->scenePos()))) {
       
   445             mouseReleaseLocation = Popup;
       
   446         }
       
   447 
       
   448         // Mouse is released within popup
       
   449         if (mouseReleaseLocation == Popup) {
       
   450             // Handle cases only when TapInside is set
       
   451             if (dismissPolicy & HbPopup::TapInside) {
       
   452                 // Close popup if mouse press is initiated within popup or TapOutside is set
       
   453                 if (mousePressLocation == Popup || dismissPolicy & HbPopup::TapOutside) {
       
   454                     q->close();
       
   455                 }
       
   456             }
       
   457         }
       
   458         // Mouse is released within popup background
       
   459         else {
       
   460             // Handle cases only when TapOutside is set
       
   461             if (dismissPolicy & HbPopup::TapOutside) {
       
   462                 // Close popup if mouse press is initiated within popup background
       
   463                 // or TapInside is set
       
   464                 if (mousePressLocation == Background || dismissPolicy & HbPopup::TapInside) {
       
   465                     q->close();
       
   466                 }
       
   467             }
       
   468         }
       
   469     }
       
   470 
       
   471     // reset mousePressLocation
       
   472     mousePressLocation = None;
       
   473 }
       
   474 
       
   475 
       
   476 int HbPopupPrivate::timeoutValue(HbPopup::DefaultTimeout timeout)
       
   477 {
       
   478     int count = sizeof(timeoutValues) / sizeof(timeoutValues[0]);
       
   479     if (timeout < 0 || timeout >= count) {
       
   480         return timeoutValues[HbPopup::NoTimeout].value;
       
   481     }
       
   482     return timeoutValues[timeout].value;
       
   483 }
       
   484 
       
   485 void HbPopupPrivate::forceHide()
       
   486 {
       
   487     Q_Q(HbPopup);
       
   488 
       
   489     delayedHide = false;
       
   490     q->hide();
       
   491     delayedHide = hasEffects;
       
   492 }
       
   493 
       
   494 void HbPopupPrivate::addPopupEffects()
       
   495 {
       
   496 
       
   497 #ifdef HB_EFFECTS
       
   498     effectType = "HB_POPUP";
       
   499     hasEffects = popupEffectsLoaded;
       
   500     if (popupEffectsLoaded)
       
   501         return;
       
   502     popupEffectsLoaded = true;
       
   503     hasEffects = HbEffectInternal::add("HB_POPUP",
       
   504                                        "popup_appear",
       
   505                                        "appear");
       
   506     if (hasEffects) {
       
   507         hasEffects = HbEffectInternal::add("HB_POPUP",
       
   508                                            "popup_disappear",
       
   509                                            "disappear");
       
   510     }
       
   511     if (hasEffects ) {
       
   512         hasEffects = HbEffectInternal::add("HB_POPUP",
       
   513                                            "dialog_rotate",
       
   514                                            "orientationswitch");
       
   515     }
       
   516 #endif
       
   517 }
       
   518 
       
   519 
       
   520 void HbPopupPrivate::doSetModal( bool modal ) {
       
   521     if(backgroundItem) {
       
   522         // When the popup is modal background item must receive focus
       
   523         // events to be able to prevent last focus item losing its
       
   524         // focus
       
   525         backgroundItem->setFlag(QGraphicsItem::ItemIsFocusable, modal);
       
   526     }
       
   527 }
       
   528 
       
   529 /*!
       
   530 * Constructs a popup with given  \a parent graphics item.\n
       
   531 * Note: popups with \a parent set as 0 are behaving as real popups.
       
   532 * This is actually the intended use.
       
   533 *
       
   534 * However in some situation could be useful to embedd a popup into a QGraphicsItem.
       
   535 * In this case a non zero \a parent value must be passed.
       
   536 * Popups with parent items behaving just like any other QGraphicsWidget.
       
   537 * The following features are not supported (i.e. ignored) for popup with parents:
       
   538 *
       
   539 *       - modality
       
   540 *       - timeout
       
   541 *       - unfadedItems
       
   542 *       - dismissPolicy
       
   543 *       - signal aboutToClose
       
   544 */
       
   545 HbPopup::HbPopup(QGraphicsItem *parent) :
       
   546     HbWidget(*new HbPopupPrivate,parent)
       
   547 {
       
   548     Q_D(HbPopup);
       
   549     d->q_ptr = this;
       
   550     d->init();
       
   551 }
       
   552 
       
   553 
       
   554 /*!
       
   555     \internal
       
   556  */
       
   557 HbPopup::HbPopup(HbPopupPrivate &dd, QGraphicsItem *parent) :
       
   558     HbWidget(dd, parent)
       
   559 {
       
   560     Q_D(HbPopup);
       
   561     d->q_ptr = this;
       
   562     d->init();
       
   563 }
       
   564 /*!
       
   565 * Destroys the popup.
       
   566 */
       
   567 HbPopup::~HbPopup()
       
   568 {
       
   569     Q_D(HbPopup);
       
   570     d->inDestruction = true;
       
   571 
       
   572     // Deregister popup from HbPopupManager in case hideEvent() was not called
       
   573     // before destruction
       
   574     HbGraphicsScene *hbScene = qobject_cast<HbGraphicsScene *>(scene());
       
   575     if (hbScene) {
       
   576         hbScene->d_ptr->hidePopup(this);
       
   577     }
       
   578 
       
   579     if (d->eventLoop) {
       
   580         d->eventLoop->exit();
       
   581     }
       
   582     if (d->backgroundItem) {
       
   583         // Set backgroundItem->popup to 0 to avoid double deletion
       
   584         // e.g. when popup is deleted by scene before its backgroundItem
       
   585         d->backgroundItem->popup = 0;
       
   586 
       
   587         // Delete the background item only and only if it's not going
       
   588         // to be cleaned up by the destructing graphics scene
       
   589         QGraphicsScene *scene = d->backgroundItem->scene();   // krazy:exclude=qclasses
       
   590         if (!scene || !scene->property("destructed").isValid()) {
       
   591             delete d->backgroundItem;
       
   592         }
       
   593     }
       
   594 }
       
   595 
       
   596 
       
   597 /*!
       
   598 * Returns the popup timeout property in milliseconds.
       
   599 * If this property is not set the deafult is HbPopup::StandardTimeout.
       
   600 * \sa setTimeout()
       
   601 */
       
   602 int HbPopup::timeout() const
       
   603 {
       
   604     Q_D(const HbPopup);
       
   605     return d->timeout;
       
   606 }
       
   607 
       
   608 /*!
       
   609 * Sets the popup timeout property in milliseconds.
       
   610 * If timeout <= 0 then the popup is permanent and not closed automatically.
       
   611 * \sa timeout() setTimeout(HbPopup::DefaultTimeout) QGraphicsWidget::close()
       
   612 */
       
   613 void HbPopup::setTimeout(int timeout)
       
   614 {
       
   615     Q_D(HbPopup);
       
   616     d->timeout = timeout;
       
   617 }
       
   618 
       
   619 /*!
       
   620 * It is a convenience overload of \a timeout() for setting HbPopup::DefaultTimeout values
       
   621 * to achieve common look & feel.
       
   622 * \sa enum DefaultTimeout
       
   623 * \sa timeout() setTimeout(int) QGraphicsWidget::close()
       
   624 */
       
   625 void HbPopup::setTimeout(HbPopup::DefaultTimeout timeout)
       
   626 {
       
   627     setTimeout(HbPopupPrivate::timeoutValue(timeout));
       
   628 }
       
   629 
       
   630 /*!
       
   631 * Returns the popup modality property.
       
   632 * A modal popup blocks any user initiated events outside of the popup
       
   633 * until it is closed.
       
   634 * \sa setModal()
       
   635 */
       
   636 bool HbPopup::isModal() const
       
   637 {
       
   638     Q_D(const HbPopup);
       
   639     return d->modal;
       
   640 }
       
   641 
       
   642 /*!
       
   643 * Sets the popup modality property.
       
   644 * \sa isModal()
       
   645 */
       
   646 void HbPopup::setModal(bool enabled)
       
   647 {
       
   648     Q_D(HbPopup);
       
   649     d->modal = enabled;
       
   650     d->doSetModal( d->modal );
       
   651 }
       
   652 
       
   653 /*!
       
   654 * Sets the background of popup faded if \a fadeBackground is true otherwise
       
   655 * the background will not be faded.
       
   656 * \sa isBackgroundFaded()
       
   657 */
       
   658 void HbPopup::setBackgroundFaded(bool fadeBackground)
       
   659 {
       
   660     Q_D(HbPopup);
       
   661     d->fadeBackground = fadeBackground;
       
   662 }
       
   663 
       
   664 /*!
       
   665 * Returns if the background of the popup is faded or not.
       
   666 * Default: true
       
   667 * \sa isBackgroundFaded()
       
   668 */
       
   669 bool HbPopup::isBackgroundFaded() const
       
   670 {
       
   671     Q_D(const HbPopup);
       
   672     return d->backgroundItem && d->fadeBackground;
       
   673 }
       
   674 
       
   675 /*!
       
   676 * Returns the dismiss policy of the popup.
       
   677 * Default is HbPopup::TapOutside.
       
   678 * \sa setDismissPolicy()
       
   679 */
       
   680 HbPopup::DismissPolicy HbPopup::dismissPolicy() const
       
   681 {
       
   682     Q_D(const HbPopup);
       
   683     return d->dismissPolicy;
       
   684 }
       
   685 
       
   686 /*!
       
   687 * Sets the dismiss policy property for the the popup.
       
   688 *
       
   689 * \sa dismissPolicy()
       
   690 */
       
   691 void HbPopup::setDismissPolicy(HbPopup::DismissPolicy dismissPolicy)
       
   692 {
       
   693     Q_D(HbPopup);
       
   694     d->dismissPolicy = dismissPolicy;
       
   695 }
       
   696 
       
   697 /*!
       
   698 * Returns the frame type of the popup.
       
   699 * Default is HbPopup::Strong
       
   700 * \sa setFrameType()
       
   701 */
       
   702 HbPopup::FrameType HbPopup::frameType() const
       
   703 {
       
   704     Q_D(const HbPopup);
       
   705     return d->frameType;
       
   706 }
       
   707 
       
   708 /*!
       
   709 * Sets the frame typeproperty for the the popup.
       
   710 *
       
   711 * \sa frameType()
       
   712 */
       
   713 void HbPopup::setFrameType(HbPopup::FrameType frameType)
       
   714 {
       
   715     Q_D(HbPopup);
       
   716     if ( d->frameType != frameType ) {
       
   717         switch( frameType ) {
       
   718         case HbPopup::Weak:
       
   719             setBackgroundItem(HbStyle::P_Popup_background_weak);
       
   720             break;
       
   721         case HbPopup::Strong:
       
   722         default:
       
   723             setBackgroundItem(HbStyle::P_Popup_background);
       
   724             break;
       
   725         }
       
   726         d->frameType = frameType;
       
   727         updatePrimitives();
       
   728     }
       
   729 }
       
   730 
       
   731 
       
   732 /*!  @alpha 
       
   733 *
       
   734 * Shows the popup as modal popup returning immediately.  
       
   735 
       
   736 * Connects aboutToClose() signal to the slot specified by \a receiver and
       
   737 * \a member. The signal will be disconnected from the slot when the
       
   738 * popup is closed.
       
   739 *
       
   740 * For non modal popups, use show().  
       
   741 */
       
   742 void HbPopup::open( QObject *receiver, const char *member )
       
   743 {
       
   744     Q_D(HbPopup);
       
   745     connect(this, SIGNAL(aboutToClose()), receiver, member);
       
   746     d->receiverToDisconnectOnClose = receiver;
       
   747     d->memberToDisconnectOnClose = member;
       
   748 
       
   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();
       
   764 }
       
   765 
       
   766 
       
   767 /*!
       
   768     \deprecated HbPopup::exec()
       
   769         is deprecated. Please use HbPopup::show() or
       
   770         void HbPopup::open( QObject *receiver, const char *member ) instead.
       
   771 *
       
   772 * Executes the popup synchronously.
       
   773 * Note: when popup is executed syncronously it is always modal.
       
   774 * This function is deprecated. use \sa open() or \sa show() instead.
       
   775 */
       
   776 void HbPopup::exec()
       
   777 {
       
   778     //    Q_ASSERT(false);
       
   779     Q_D(HbPopup);
       
   780 
       
   781     HbMainWindow* w(mainWindow());
       
   782     if (w) {
       
   783         disconnect(w, SIGNAL(aboutToChangeOrientation(Qt::Orientation, bool)), this, SLOT(_q_orientationChange(Qt::Orientation, bool)));
       
   784         connect( w, SIGNAL(aboutToChangeOrientation(Qt::Orientation, bool)), this, SLOT(_q_orientationChange(Qt::Orientation, bool)) );
       
   785        }
       
   786 
       
   787     if (!d->eventLoop) {
       
   788         // Prevent deleting popup in eventloop
       
   789         bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
       
   790         setAttribute(Qt::WA_DeleteOnClose, false);
       
   791 
       
   792         // Set popup to modal before eventloop
       
   793         bool wasShowModal = isModal();
       
   794         setModal(true);      
       
   795 
       
   796          show();
       
   797 
       
   798         // Ungrab the mouse if it is currently grabbed
       
   799         // todo; currently needed menus to work ok, otherwise:
       
   800         // - quick multiple presses on menuitem causes multiple actions (menu relaunch?)
       
   801         // - closing menu with titlepane needs multiple presses (menu relaunch?)
       
   802         // Ungrab was removed when trying to fix problem when button pressed()-signal
       
   803         // was connected to menu launch. Button did not get anymore mouse release event.
       
   804         if (scene()) {
       
   805             QGraphicsItem *item = scene()->mouseGrabberItem();
       
   806             if (item) {
       
   807                 item->ungrabMouse();
       
   808             }
       
   809         }
       
   810 
       
   811         QEventLoop eventLoop;
       
   812         d->eventLoop = &eventLoop;
       
   813         QPointer<QObject> guard = this;
       
   814         d->eventLoop->exec();
       
   815         if (guard.isNull()) {
       
   816             return;
       
   817         }
       
   818         d->eventLoop = 0;
       
   819 
       
   820         // Reset modality
       
   821         setModal(wasShowModal);
       
   822 
       
   823         if (deleteOnClose) {
       
   824             delete this;
       
   825         }
       
   826     } else {
       
   827         qWarning("HbPopup::exec: Recursive call detected");
       
   828     }
       
   829 }
       
   830 
       
   831 /*!
       
   832     \reimp
       
   833  */
       
   834 QVariant HbPopup::itemChange ( GraphicsItemChange change, const QVariant & value )
       
   835 {
       
   836     Q_D(HbPopup);
       
   837 
       
   838     if (change == QGraphicsItem::ItemVisibleChange) {
       
   839         if (value.toBool()) {
       
   840             if(!d->hasEffects){
       
   841                 d->addPopupEffects();
       
   842             }
       
   843             if (!d->aboutToShowSignalGuard)
       
   844             {
       
   845                 d->aboutToShowSignalGuard = true;
       
   846                 emit aboutToShow();
       
   847             }
       
   848             // Note: when visibility changes to "visible" base class implementation needs
       
   849             //       to be called otherwise showEvent() is not called.
       
   850             
       
   851         } else {
       
   852             d->aboutToShowSignalGuard = false;
       
   853             if (!d->hidingInProgress) {
       
   854                 emit aboutToHide();
       
   855             }
       
   856 
       
   857             if (d->delayedHide &&  // about to hide and we wanna delay hiding
       
   858                 d->hasEffects && !parentItem()) { // only for popup without parent
       
   859                 if (!d->hidingInProgress) { // Prevent reentrance
       
   860                     d->hidingInProgress = true;
       
   861 #ifdef HB_EFFECTS
       
   862                     QRectF extRect(0.0,
       
   863                                    -boundingRect().height(),
       
   864                                    boundingRect().width(),
       
   865                                    0);
       
   866                     if (!HbEffect::start(this, d->effectType, "disappear",
       
   867                                          this, "_q_delayedHide",
       
   868                                          QVariant(), extRect)) {
       
   869                         d->delayedHide = false;
       
   870                     }
       
   871 #endif
       
   872                 }
       
   873                 if (d->delayedHide) {
       
   874                     return true;
       
   875                 } else {
       
   876                     d->delayedHide = d->hasEffects;
       
   877                     d->hidingInProgress = false;
       
   878                     // fallback to base class imp
       
   879                 }
       
   880             }
       
   881         }
       
   882     } else if (change == QGraphicsItem::ItemSceneHasChanged) {
       
   883         HbMainWindow* w(mainWindow());
       
   884         if ( w ){
       
   885             disconnect(this, SLOT(handlePopupPos()));
       
   886             connect( w, SIGNAL(orientationChanged(Qt::Orientation)),
       
   887                      this, SLOT(handlePopupPos()) );
       
   888         }
       
   889     }
       
   890     return HbWidget::itemChange(change, value);
       
   891 }
       
   892 
       
   893 /*!
       
   894 * Handles the popup position when Orientation changes
       
   895 */
       
   896 void HbPopup::handlePopupPos()
       
   897 {
       
   898     QEvent userEvent(QEvent::ContextMenu);
       
   899     QCoreApplication::sendEvent(this, &userEvent);
       
   900 }
       
   901 
       
   902 /*!
       
   903     \reimp
       
   904  */
       
   905 void HbPopup::mousePressEvent(QGraphicsSceneMouseEvent *event )
       
   906 {
       
   907     Q_D(HbPopup);
       
   908 
       
   909     Q_UNUSED(event);
       
   910 
       
   911     d->mousePressLocation = HbPopupPrivate::Popup;
       
   912 
       
   913     // We need to reimplement this function otherwise this events will be
       
   914     // ignored by default and we wont get further mouse events
       
   915     // not even mouseReleaseEvent. See doc of QGraphicsItem::mousePressEvent()
       
   916     // for more info.
       
   917     QGraphicsItem::mousePressEvent(event);
       
   918 
       
   919     // Event has to be accepted cause QGraphicsItem::mousePressEvent can mark it
       
   920     // to ignored
       
   921     event->accept();
       
   922 }
       
   923 
       
   924 /*!
       
   925     \reimp
       
   926  */
       
   927 void HbPopup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event )
       
   928 {
       
   929     QGraphicsItem::mouseReleaseEvent(event);        
       
   930     event->accept();
       
   931     // Note: Mouse release event is always handled in handleBackgroundMouseReleaseEvent
       
   932 }
       
   933 
       
   934 /*!
       
   935     \reimp
       
   936  */
       
   937 void HbPopup::keyPressEvent(QKeyEvent *event)
       
   938 {
       
   939     Q_D(HbPopup);
       
   940     d->handleKeyEvent(event);
       
   941 }
       
   942 
       
   943 /*!
       
   944     \reimp
       
   945  */
       
   946 //
       
   947 // Shows the popup with an animation and starts the timer to dismiss the popup,
       
   948 // unless it is a permanent popup.
       
   949 //
       
   950 void HbPopup::showEvent(QShowEvent *event)
       
   951 {
       
   952     Q_D(HbPopup);
       
   953 
       
   954     HbWidget::showEvent(event);
       
   955 
       
   956     // Only for popup without parent
       
   957     // Note:
       
   958     //  popups without parent are treated as popups i.e.:
       
   959     //  - can have background item
       
   960     //  - timeout
       
   961     //  - and registered to HbPopupManager
       
   962     //  otherwise popup is treated as normal widget
       
   963     if(d->duplicateShowEvent){
       
   964         d->duplicateShowEvent = false;
       
   965         return;
       
   966     }
       
   967     if (!parentItem()) {
       
   968         //check if popup needs to be added to scene.This can result in duplciate show event,
       
   969         // if popup is added to scene here.
       
   970            if(d->addPopupToScene())
       
   971               d->duplicateShowEvent = true;
       
   972 
       
   973         // Popup clears closed state
       
   974         d->closed = false;
       
   975         if (d->backgroundItem) {
       
   976             d->backgroundItem->setVisible(true);
       
   977             d->backgroundItem->setAcceptHoverEvents(isModal());
       
   978             // Let the background be a panel if the popup is one
       
   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);
       
   983             }
       
   984         }
       
   985         if (qobject_cast<HbGraphicsScene *>(scene())) {
       
   986             qobject_cast<HbGraphicsScene *>(scene())->d_ptr->showPopup(this);
       
   987             HbWidgetFeedback::triggered(this, Hb::InstantPopupOpened);
       
   988         }
       
   989 
       
   990         /*if(d->hasEffects && boundingRect().isValid()) {
       
   991 
       
   992         #ifdef HB_EFFECTS
       
   993             QRectF extRect(0.0,
       
   994                            -boundingRect().height(),
       
   995                            boundingRect().width(),
       
   996                            0);
       
   997             HbEffect::start(this, d->effectType, "appear", 0, 0, QVariant(), extRect);
       
   998         #endif//HB_EFFECTS
       
   999             d->mStartEffect = false;
       
  1000         } else {
       
  1001             d->mStartEffect = true;
       
  1002         }*/
       
  1003 
       
  1004         //workaround
       
  1005         resetTransform();
       
  1006         setOpacity(1);
       
  1007         //workaround ends
       
  1008 
       
  1009         // delay hiding if effects are enabled
       
  1010         d->delayedHide = d->hasEffects;
       
  1011 
       
  1012         // If it is not permanent launch a timer for closing the popup
       
  1013         if (0 < d->timeout) {
       
  1014             d->timeoutTimer()->setInterval(d->timeout);
       
  1015             d->timeoutTimer()->start();
       
  1016         }
       
  1017     }
       
  1018 }
       
  1019 
       
  1020 /*!
       
  1021     \reimp
       
  1022  */
       
  1023 void HbPopup::hideEvent(QHideEvent *event)
       
  1024 {
       
  1025     Q_D(HbPopup);
       
  1026 
       
  1027     HbWidget::hideEvent(event);
       
  1028 
       
  1029     // Only for popup without parent
       
  1030     if (!parentItem()) {
       
  1031         if (d->backgroundItem) {
       
  1032             d->backgroundItem->setVisible(false);
       
  1033         }
       
  1034         qobject_cast<HbGraphicsScene *>(scene())->d_ptr->hidePopup(this);
       
  1035     }
       
  1036 
       
  1037     HbWidgetFeedback::triggered(this, Hb::InstantPopupClosed);
       
  1038     if (d->eventLoop) {
       
  1039         d->eventLoop->exit();
       
  1040     }
       
  1041 
       
  1042     d->doSetModal( d->modal );
       
  1043 
       
  1044 }
       
  1045 
       
  1046 /*!
       
  1047     \reimp
       
  1048  */
       
  1049 void HbPopup::resizeEvent( QGraphicsSceneResizeEvent * event )
       
  1050 {
       
  1051     HbWidget::resizeEvent(event);
       
  1052     updatePrimitives();
       
  1053 }
       
  1054 
       
  1055 /*!
       
  1056     \reimp
       
  1057  */
       
  1058 void HbPopup::closeEvent ( QCloseEvent * event )
       
  1059 {
       
  1060     Q_D(HbPopup);
       
  1061     d->stopTimeout();
       
  1062     // Only for popup without parent
       
  1063     if (!d->closed && !parentItem()) {
       
  1064         // Popup goes to closed state
       
  1065         d->closed = true;
       
  1066 
       
  1067         emit aboutToClose();
       
  1068 
       
  1069         // prevent delete on close before effects are finished
       
  1070         if (d->hasEffects && isVisible()) {
       
  1071             d->deleteOnClose = testAttribute(Qt::WA_DeleteOnClose);
       
  1072             setAttribute(Qt::WA_DeleteOnClose,false);
       
  1073         }
       
  1074         HbToolTip::hideText(qobject_cast<HbGraphicsScene *>(scene()));
       
  1075     }
       
  1076     if (d->receiverToDisconnectOnClose) {
       
  1077         disconnect(this, SIGNAL(aboutToClose()),
       
  1078                    d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
       
  1079         d->receiverToDisconnectOnClose = 0;
       
  1080     }
       
  1081     d->memberToDisconnectOnClose.clear();
       
  1082     HbWidget::closeEvent(event);
       
  1083 }
       
  1084 
       
  1085 /*!
       
  1086     \reimp
       
  1087  */
       
  1088 bool HbPopup::event(QEvent *event)
       
  1089 {
       
  1090     /*Q_D(HbPopup);
       
  1091     if (event->type() == QEvent::GraphicsSceneResize) {
       
  1092         //Workaround when showing first time                   
       
  1093         #ifdef HB_EFFECTS
       
  1094         if(d->mStartEffect && boundingRect().isValid()) {
       
  1095             QRectF extRect(0.0,
       
  1096                            -boundingRect().height(),
       
  1097                            boundingRect().width(),
       
  1098                            0);
       
  1099             HbEffect::start(this, d->effectType, "appear", 0, 0, QVariant(), extRect);
       
  1100             d->mStartEffect = false;
       
  1101         }
       
  1102             #endif//HB_EFFECTS        
       
  1103         //workaround ends
       
  1104     }*/
       
  1105     return HbWidget::event(event);
       
  1106 }
       
  1107 
       
  1108 
       
  1109 /*!
       
  1110   Sets preferred position\a position for popup with \a placement
       
  1111   as origin.
       
  1112 
       
  1113   \param position is the position at which the popup is shown.
       
  1114   \param placement is the corner or edge which \a position refers to
       
  1115 
       
  1116   Example usage:
       
  1117   \code
       
  1118   HbDialog popup;
       
  1119   ...
       
  1120   popup.setPreferredPosition( QPointF(x,y), HbPopupBase::BottomEdgeCenter );
       
  1121   popup.exec();
       
  1122   \endcode
       
  1123 
       
  1124  */
       
  1125 
       
  1126 void HbPopup::setPreferredPos( const QPointF& preferredPos,
       
  1127                                HbPopup::Placement placement )
       
  1128 
       
  1129 {
       
  1130     Q_D(HbPopup);
       
  1131     bool layoutFlag = false;
       
  1132     if (d->preferredPos != preferredPos ) {
       
  1133         d->preferredPos = preferredPos;
       
  1134         layoutFlag = true;
       
  1135     }
       
  1136     if (d->placement != placement) {
       
  1137         d->placement = placement;
       
  1138         layoutFlag = true;
       
  1139     }
       
  1140     d->preferredPosSet = true;
       
  1141     //If position updated, informing layoutproxy with layoutrequest
       
  1142     if (layoutFlag) {
       
  1143         QApplication::postEvent(this, new QEvent(QEvent::LayoutRequest));
       
  1144     }
       
  1145 }
       
  1146 
       
  1147 #include "moc_hbpopup.cpp"