src/hbcore/gui/hbdialog.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 "hbdialog.h"
       
    27 #include "hbdialog_p.h"
       
    28 #include "hbinstance.h"
       
    29 #include "hbaction.h"
       
    30 #include "hbstyleoptionpopup.h"
       
    31 #include "hbdeviceprofile.h"
       
    32 #include "hbevent.h"
       
    33 #include "hbtoolbar_p.h"
       
    34 
       
    35 #include <QPainter>
       
    36 #include <QGraphicsSceneMouseEvent>
       
    37 #include <QStyleOptionGraphicsItem>
       
    38 #include <QShowEvent>
       
    39 #include <QHideEvent>
       
    40 #include <QEventLoop>
       
    41 #include <QPointer>
       
    42 #include <QDebug>
       
    43 #include <QGraphicsLinearLayout>
       
    44 #include <QApplication> // krazy:exclude=qclasses
       
    45 
       
    46 #include <hbfeedbackmanager.h>
       
    47 
       
    48 #ifdef HB_EFFECTS
       
    49 #include "hbeffectinternal_p.h"
       
    50 #define HB_POPUP_ITEM_TYPE "HB_POPUP"
       
    51 #endif
       
    52 
       
    53 /*!
       
    54     @stable
       
    55     @hbcore
       
    56     \class HbDialog
       
    57     \brief HbDialog is a base class for different popup notes in Hb library.
       
    58 
       
    59     \image html hbpopup.png A popup with a header widget, a list as a content widget, 
       
    60     and two action buttons.
       
    61 
       
    62     HbDialog is a concrete class. The content for a custom popup is implemented in
       
    63     a separate widget, which is set to the popup with method setContentWidget().
       
    64 
       
    65     Lastly shown popup is always positioned in Z order on the the top of already visible popups.
       
    66     A popup can be permanent or automatically dismissed after a time-out.
       
    67     Modal popups interrupt any other user interaction outside of the popup while they are visible,
       
    68     whereas non-modal popups do not.
       
    69 
       
    70     An example of how to create a simple modal popup and show it.
       
    71     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,13}
       
    72 
       
    73     An example of how to create a non-modal popup and show it.
       
    74     \snippet{ultimatecodesnippet/ultimatecodesnippet.cpp,26}
       
    75 */
       
    76 
       
    77 /*!
       
    78     \reimp
       
    79     \fn int HbDialog::type() const
       
    80  */
       
    81 
       
    82 HbDialogPrivate::HbDialogPrivate( ) :
       
    83     contentWidget(0),
       
    84     headingWidget(0),
       
    85     mainLayout(new QGraphicsLinearLayout(Qt::Vertical)),
       
    86     primaryAction(0),
       
    87     secondaryAction(0),
       
    88     closingAction(0),
       
    89     toolBar(0)
       
    90 {
       
    91 }
       
    92 
       
    93 HbDialogPrivate::~HbDialogPrivate()
       
    94 {
       
    95 }
       
    96 
       
    97 void HbDialogPrivate::init()
       
    98 {
       
    99     Q_Q(HbDialog);
       
   100 
       
   101     // Content is responsible of adding spacings & margins
       
   102     mainLayout->setSpacing(0);
       
   103     mainLayout->setContentsMargins(0,0,0,0);
       
   104 
       
   105     q->setLayout(mainLayout);
       
   106     mainLayout->setMinimumSize(0, 0);    
       
   107 }
       
   108 
       
   109 void HbDialogPrivate::setWidget(int layoutIndex, QGraphicsWidget *&destWidget, QGraphicsWidget *widget)
       
   110 {
       
   111     Q_Q(HbDialog);
       
   112     if (destWidget != widget) {
       
   113         if (destWidget) {
       
   114             mainLayout->removeItem(destWidget);
       
   115             delete destWidget;
       
   116             destWidget = 0;
       
   117         }
       
   118         if (widget) {
       
   119             destWidget = widget;
       
   120             destWidget->setParentItem(q);
       
   121             mainLayout->insertItem(layoutIndex, widget);
       
   122             mainLayout->setAlignment(widget, Qt::AlignCenter);
       
   123         }
       
   124 
       
   125         doLayout();
       
   126     }
       
   127 }
       
   128 
       
   129 /*
       
   130   Relayouts the popup. If expandSize is true it the new calculated size of the popup
       
   131   cannot be smaller than the current size.
       
   132 */
       
   133 void HbDialogPrivate::doLayout()
       
   134 {
       
   135     Q_Q(HbDialog);
       
   136     if(q->mainWindow() && contentWidget)
       
   137     {
       
   138         if ( q->mainWindow()->layoutDirection() != contentWidget->layoutDirection() ) {
       
   139            contentWidget->setLayoutDirection(q->mainWindow()->layoutDirection());
       
   140         }
       
   141     }
       
   142 
       
   143     if (q->mainWindow() && headingWidget) {
       
   144         if (q->mainWindow()->layoutDirection() != headingWidget->layoutDirection()) {
       
   145             headingWidget->setLayoutDirection(q->mainWindow()->layoutDirection());
       
   146         }
       
   147     }
       
   148 
       
   149     q->updateGeometry();
       
   150 }
       
   151 
       
   152 
       
   153 /*!
       
   154 * Constructs a popup with given  \a parent graphics item.\n
       
   155 * Note: popups with \a parent set as 0 are behaving as real popups. 
       
   156 * This is actually the intended use.
       
   157 *
       
   158 * However in some situation could be useful to embedd a popup into a QGraphicsItem.
       
   159 * In this case a non zero \a parent value must be passed.
       
   160 * Popups with parent items behaving just like any other QGraphicsWidget.
       
   161 * The following features are not supported (i.e. ignored) for popup with parents:
       
   162 *
       
   163 *       - modality
       
   164 *       - timeout
       
   165 *       - unfadedItems
       
   166 *       - dismissPolicy
       
   167 *       - signal aboutToClose
       
   168 */
       
   169 HbDialog::HbDialog(QGraphicsItem *parent) :
       
   170     HbPopup(*new HbDialogPrivate, parent)
       
   171 {
       
   172     Q_D(HbDialog);
       
   173     d->q_ptr = this;
       
   174     d->init();
       
   175 }
       
   176 
       
   177 /*!
       
   178     \internal
       
   179  */
       
   180 HbDialog::HbDialog(HbDialogPrivate &dd, QGraphicsItem *parent) :
       
   181     HbPopup(dd, parent)
       
   182 {
       
   183     Q_D(HbDialog);
       
   184     d->q_ptr = this;
       
   185     d->init();
       
   186 }
       
   187 
       
   188 /*!
       
   189 * Destroys the popup.
       
   190 */
       
   191 HbDialog::~HbDialog()
       
   192 {
       
   193 }
       
   194 
       
   195 /*!
       
   196 @beta
       
   197 * It returns the widget which is being added to the heading area
       
   198 * \sa setHeadingWidget()
       
   199 */
       
   200 QGraphicsWidget * HbDialog::headingWidget() const
       
   201 {
       
   202     Q_D(const HbDialog);
       
   203     return (d->headingWidget);
       
   204 }
       
   205 
       
   206 /*!
       
   207 @beta
       
   208 * Adds \a widget to the heading area. Ownership of the widget is transferred
       
   209 * to popup. If \a headingWidget is 0 the heading widget is removed.
       
   210 * \sa headingWidget()
       
   211 */
       
   212 void HbDialog::setHeadingWidget(QGraphicsWidget *headingWidget)
       
   213 {
       
   214     Q_D(HbDialog);
       
   215     HbStyle::setItemName(headingWidget,"heading");
       
   216     d->setWidget(0, d->headingWidget, headingWidget);
       
   217 }
       
   218 
       
   219 /*!
       
   220 * Returns the content widget property of the popup.
       
   221 * HbDialog only draws a bordered rect, the rest is drawn by the content widget.
       
   222 * \sa setContentWidget()
       
   223 */
       
   224 QGraphicsWidget *HbDialog::contentWidget() const
       
   225 {
       
   226     Q_D(const HbDialog);
       
   227     return d->contentWidget;
       
   228 }
       
   229 
       
   230 /*!
       
   231 * Sets the content widget property of the popup.
       
   232 * HbDialog only draws a bordered rect, the rest is drawn by the content widget.
       
   233 * Ownership of the widget is transferred
       
   234 * to popup. If \a contentWidget is 0 the content widget is removed.
       
   235 * \sa contentWidget()
       
   236 */
       
   237 void HbDialog::setContentWidget(QGraphicsWidget *contentWidget)
       
   238 {
       
   239    Q_D(HbDialog);
       
   240    HbStyle::setItemName(contentWidget,"content");
       
   241    d->setWidget((d->headingWidget?1:0), d->contentWidget, contentWidget);
       
   242 }
       
   243 
       
   244 /*!
       
   245 * It returns the primary action added to the control area
       
   246 * \sa setPrimaryAction()
       
   247 */
       
   248 HbAction* HbDialog::primaryAction() const
       
   249 {
       
   250     Q_D(const HbDialog);
       
   251     return d->primaryAction;
       
   252 }
       
   253 
       
   254 /*!
       
   255 * It adds the given action to the control area.
       
   256 * It is added to the left side of the control area if the layout direction of the application
       
   257 * is left-to-right and in the vice-versa if the layout direction of the application
       
   258 * is right-to-left.
       
   259 * \sa primaryAction()
       
   260 */
       
   261 void HbDialog::setPrimaryAction(HbAction *action)
       
   262 {
       
   263     Q_D(HbDialog);
       
   264     if (d->primaryAction && action != d->primaryAction) {
       
   265         removeAction(d->primaryAction);
       
   266     }
       
   267     d->primaryAction = action;
       
   268     QAction *before = 0;        //krazy:exclude=qclasses
       
   269     if (actions().count()) {
       
   270         before = actions().first();
       
   271     }
       
   272     insertAction(before, action);
       
   273 }
       
   274 
       
   275 /*!
       
   276 * It returns the secondary action added to the control area
       
   277 * \sa setSecondaryAction()
       
   278 */
       
   279 HbAction* HbDialog::secondaryAction() const
       
   280 {
       
   281     Q_D(const HbDialog);
       
   282     return(d->secondaryAction);
       
   283 }
       
   284 
       
   285 /*!
       
   286 * It adds the given action to the control area.
       
   287 * It is added to the right side of the control area if the layout direction of the application
       
   288 * is left-to-right and in the vice-versa if the layout direction of the application
       
   289 * is right-to-left.
       
   290 * \sa secondaryAction()
       
   291 */
       
   292 void HbDialog::setSecondaryAction(HbAction *action)
       
   293 {
       
   294     Q_D(HbDialog);
       
   295     if (d->secondaryAction && action != d->secondaryAction) {
       
   296         removeAction(d->secondaryAction);
       
   297     }
       
   298     d->secondaryAction = action;
       
   299     addAction(action);
       
   300 }
       
   301 
       
   302 /*!
       
   303     \deprecated HbDialog::exec()
       
   304         is deprecated. Please use HbDialog::open( QObject* receiver, const char* member ) instead.
       
   305 *
       
   306 * Executes the popup synchronously.
       
   307 * Note: when popup is executed syncronously it is always modal.
       
   308 */
       
   309 HbAction* HbDialog::exec()
       
   310 {
       
   311     Q_D(HbDialog);
       
   312 
       
   313     HbAction *action = 0;
       
   314     QPointer<QObject> guard = this;
       
   315     HbPopup::exec();
       
   316     if (!guard.isNull()) {
       
   317         action = d->closingAction;
       
   318         d->closingAction = 0;
       
   319     }
       
   320     return action;
       
   321 }
       
   322 
       
   323 /*!  @alpha 
       
   324 *
       
   325 * Shows the dialog as modal dialog returning immediately.  
       
   326 
       
   327 * Connects finished(HbAction*) signal to the slot specified by \a receiver and
       
   328 * \a member. The signal will be disconnected from the slot when the
       
   329 * popup is closed.
       
   330 *
       
   331 * For non modal popups, use show().  
       
   332 */
       
   333 
       
   334 void HbDialog::open( QObject* receiver, const char* member )
       
   335 {
       
   336     Q_D(HbDialog);
       
   337     if ( receiver && member ) {
       
   338         connect( this, SIGNAL(finished(HbAction*)), receiver, member );
       
   339         d->receiverToDisconnectOnClose = receiver;
       
   340         d->memberToDisconnectOnClose = member;
       
   341     } else {
       
   342         d->receiverToDisconnectOnClose = 0;
       
   343         d->memberToDisconnectOnClose.clear();
       
   344     }
       
   345     HbPopup::open();
       
   346 }
       
   347 
       
   348 /*!
       
   349 * \reimp
       
   350 */
       
   351 //
       
   352 // Sets the focus to its content widget.
       
   353 //
       
   354 void HbDialog::focusInEvent(QFocusEvent *event)
       
   355 {
       
   356     Q_UNUSED(event);
       
   357     if(contentWidget()) {
       
   358         contentWidget()->setFocus();
       
   359     }
       
   360 }
       
   361 
       
   362 /*!
       
   363     \reimp
       
   364  */
       
   365 void HbDialog::closeEvent ( QCloseEvent * event )
       
   366 {
       
   367     Q_D(HbDialog);
       
   368 
       
   369     HbAction *closingAction = qobject_cast<HbAction *>(sender());
       
   370     if (closingAction && actions().contains(closingAction)) {
       
   371         d->closingAction = closingAction;
       
   372         emit finished( d->closingAction );
       
   373     } else {
       
   374         HbAction* nullAction(0);
       
   375         emit finished( nullAction );
       
   376     }
       
   377 
       
   378     HbPopup::closeEvent(event);
       
   379 }
       
   380 
       
   381 /*!
       
   382     \reimp
       
   383  */
       
   384 void HbDialog::changeEvent(QEvent *event)
       
   385 {
       
   386     Q_D(HbDialog);
       
   387     if (event->type() == QEvent::StyleChange ||
       
   388         event->type() == QEvent::LayoutDirectionChange) {
       
   389         d->doLayout();
       
   390     }
       
   391 
       
   392     HbPopup::changeEvent(event);
       
   393 }
       
   394 
       
   395 /*!
       
   396     \reimp
       
   397  */
       
   398 bool HbDialog::event(QEvent *event)
       
   399 {
       
   400     Q_D(HbDialog);
       
   401     event->accept();
       
   402 
       
   403     if (event->type() == QEvent::ActionAdded) {
       
   404         if (!d->toolBar) {
       
   405             // TODO: HbToolBar private interface should make it possible to choose
       
   406             // different graphics for tool buttons.            
       
   407             d->toolBar = new HbToolBar();
       
   408             HbStyle::setItemName(d->toolBar ,"controls");
       
   409             d->toolBar->setParentItem(this);
       
   410             d->toolBar->setOrientation(Qt::Horizontal);
       
   411             HbToolBarPrivate::d_ptr(d->toolBar)->mDialogToolBar = true;
       
   412             // prevent stretching buttons, should the content be small
       
   413             // but dialog size forcibly large
       
   414             d->mainLayout->addStretch();
       
   415             d->mainLayout->addItem(d->toolBar);
       
   416         }
       
   417         QActionEvent *actionEvent = static_cast<QActionEvent *>(event);
       
   418         d->toolBar->insertAction (actionEvent->before(), actionEvent->action());
       
   419         if (!parentItem()) { // only for popup without parent
       
   420             connect(actionEvent->action(), SIGNAL(triggered()), this, SLOT(close()));
       
   421         }
       
   422         d->doLayout();
       
   423         return true;
       
   424 
       
   425     } else if (event->type() == QEvent::ActionRemoved) {
       
   426 
       
   427         QActionEvent *actionEvent = static_cast<QActionEvent *>(event);
       
   428         // remove primary or secondary action if set
       
   429         if (actionEvent->action() == d->primaryAction) {
       
   430             d->primaryAction = 0;
       
   431         } else if (actionEvent->action() == d->secondaryAction) {
       
   432             d->secondaryAction = 0;
       
   433         }
       
   434         disconnect(actionEvent->action(), 0, this, 0);
       
   435 
       
   436         if (d->toolBar) {
       
   437            d->toolBar->removeAction(actionEvent->action());
       
   438            if (!d->toolBar->actions().count()) {
       
   439                d->mainLayout->removeItem(d->toolBar);
       
   440                d->toolBar->deleteLater();
       
   441                d->toolBar = 0;
       
   442            }
       
   443         }
       
   444         d->doLayout();
       
   445         return true;
       
   446  
       
   447     } else if (event->type() == HbEvent::LayoutRequest) {
       
   448         if (d->toolBar
       
   449             && mainWindow()
       
   450             && d->toolBar->layoutDirection() != mainWindow()->layoutDirection()
       
   451             && !d->toolBar->testAttribute(Qt::WA_SetLayoutDirection)) {
       
   452             d->toolBar->setLayoutDirection(mainWindow()->layoutDirection());
       
   453             d->toolBar->setAttribute(Qt::WA_SetLayoutDirection, false);
       
   454         }
       
   455         d->doLayout();
       
   456     }
       
   457     return HbPopup::event(event);
       
   458 }
       
   459 
       
   460 #include "moc_hbdialog.cpp"