src/hbwidgets/devicedialogs/hbdevicemessagebox.cpp
changeset 7 923ff622b8b9
parent 3 11d3954df52a
child 21 4633027730f5
child 34 ed14f46c0e55
--- a/src/hbwidgets/devicedialogs/hbdevicemessagebox.cpp	Wed Jun 23 18:33:25 2010 +0300
+++ b/src/hbwidgets/devicedialogs/hbdevicemessagebox.cpp	Tue Jul 06 14:36:53 2010 +0300
@@ -80,6 +80,17 @@
     TRACE_EXIT
 }
 
+void HbDeviceMessageBoxPrivate::initAction(int index)
+{
+    if (!mActions[index].mAction) {
+        if (!mDefaultActions[index]) {
+            mDefaultActions[index] = new QAction(0);
+        }
+        mActions[index].mAction = mDefaultActions[index];
+        connect(mActions[index].mAction, SIGNAL(changed()), SLOT(actionChanged()));
+    }
+}
+
 void HbDeviceMessageBoxPrivate::initProperties()
 {
     for(int i = 0; i < NumProperties; i++) {
@@ -101,17 +112,23 @@
     }
 
     switch(mProperties[Type].mValue.toInt()) {
+    case HbMessageBox::MessageTypeNone:
+        q_ptr->setIconVisible(false);
+        // Fall trough
     case HbMessageBox::MessageTypeInformation:
     case HbMessageBox::MessageTypeWarning:
         q_ptr->setDismissPolicy(HbPopup::TapAnywhere);
         q_ptr->setTimeout(timeoutValue(HbPopup::StandardTimeout));
-        // Use default accept button, reject button is empty
+        // HbMessageBox sets by default accept button to "Ok", reject button is empty
+        mProperties[StandardButtons].mValue.setValue(static_cast<int>(HbMessageBox::Ok));
         useActions[AcceptButton] = true;
         break;
     case HbMessageBox::MessageTypeQuestion:
         q_ptr->setTimeout(HbPopup::NoTimeout);
         q_ptr->setDismissPolicy(HbPopup::NoDismiss);
-        // Use default accept and reject buttons
+        // HbMessageBox sets by default accept button to "Ok", reject button is empty.
+        // Set default buttons to yes/no
+        setProperty(StandardButtons, HbMessageBox::Yes|HbMessageBox::No);
         useActions[AcceptButton] = true;
         useActions[RejectButton] = true;
         break;
@@ -121,11 +138,7 @@
 
     for(int i = 0; i < NumActions; i++) {
         if (useActions[i]) {
-            if (!mDefaultActions[i]) {
-                mDefaultActions[i] = new QAction(0);
-            }
-            mActions[i].mAction = mDefaultActions[i];
-            connect(mActions[i].mAction, SIGNAL(changed()), SLOT(actionChanged()));
+            initAction(i);
         }
     }
 }
@@ -145,6 +158,21 @@
     TRACE_EXIT
 }
 
+void HbDeviceMessageBoxPrivate::setStandardButtons(HbMessageBox::StandardButtons buttons)
+{
+    // Create actions for buttons. These will be signaled on button press.
+    int buttonCount = qMin(static_cast<int>(NumActions), countBits(buttons));
+    int i = 0;
+    for(; i < buttonCount; i++) {
+        initAction(i);
+    }
+    // Clear extra actions
+    for(; i < NumActions; i++) {
+      clearAction(mActions[i]);
+    }
+    setProperty(StandardButtons, buttons);
+}
+
 // Send properties to server
 void HbDeviceMessageBoxPrivate::sendToServer(bool show)
 {
@@ -168,6 +196,7 @@
 
     static const char * const propertyNames[] = {
         "type",
+        "standardButtons",
         "text",
         "iconName",
         "iconVisible",
@@ -347,6 +376,16 @@
     return timeoutValues[timeout].value;
 }
 
+int HbDeviceMessageBoxPrivate::countBits(unsigned int value)
+{
+    int count = 0;
+    while(value) {
+        count += value & 1;
+        value >>= 1;
+    }
+    return count;
+}
+
 HbDeviceMessageBoxPrivate::ActionSelector HbDeviceMessageBoxPrivate::actionSelector(
     HbDeviceMessageBox::ActionRole role)
 {
@@ -368,27 +407,53 @@
     @stable
     @hbwidgets
     \class HbDeviceMessageBox
-    \brief HbDeviceMessageBox displays a message to the user, on top of any running applications, which the user must acknowledge to dismiss.
+    \brief HbDeviceMessageBox displays a message box on top of any running applications.
 
-    HbDeviceMessageBox is a device dialog version of HbMessageBox. It displays a message box with text, icon or animation and optional reply button(s).
-    It differs from HbMessageBox by excluding functions which handle concrete UI-component related information.
+    HbDeviceMessageBox is a device dialog version of HbMessageBox. It displays a message box
+    with text, icon or animation and optional accept and reject buttons. It is not a widget.
+    The message box is displayed by a device dialog service which HbDeviceMessageBox is a
+    client of.
 
     Device dialogs are shown on top of any running applications and are always modal by nature.
 
-    A device message box is launched when exec() is called for an synchronous dialog or show() is called for an asynchronous
-    dialog. The launched dialog can be updated by the setter metods. Because updating a dialog
-    requires interprocess communication, it is advisable to fully construct the device message box before
-    calling show(). The device message box is closed when the user dismisses it by pressing a button, when
-    the client calls close(), or when the dialog timeout expires. If the system must close the device message
-    box while it is executing, it will have the same effect as having the message box's secondary action    
+    A device message box is lauched by a show(). A new message box is lauched every time show()
+    is called. aboutToClose() signal is emitted when the box has closed. There is also syncronous
+    exec() function which launches a message box and waits for it close. exec() is not compatible
+    with gestures and cannot be used from applications that have an user interface.
+
+    After message box has been launched, updating it's properties causes interprocess
+    communication. Therefore it's best to construct the message box fully before
+    calling show(). Changing a property while a message box is displayed, causes the property
+    to be updated to the displayed widget automatically next time event loop is entered
+    or updated values can be sent immediately by calling update().
+
+    Message box buttons are represented by two actions. Left button corrensponds to accept
+    action and the right one to reject action. triggered() signal of action is emitted when
+    corresponding button is pressed. Changing action text changes corresponding button text.
+    Icons on buttons are not suppported.
 
-    Static convenience functions are provided for launching message boxes.
-    Dialogs created by them contain default property values appropriate for
-    the message box type and their contents cannot be updated. Information and
-    warning convenience methods return immediately. Question waits for a message box
-    to close.
+    Device message box is closed when user dismisses it, when HbDeviceMessageBox::close() is
+    called, timeout expires and message box closes itself or system closes the message box for
+    some reason. aboutToClose() signal is always emitted after the box has closed.
+
+    Static convenience functions are provided for launching message boxes. They launch message boxes
+    containing default properties appropriate for the message box type and their contents cannot
+    be updated. Information and warning convenience methods return immediately. Question waits for
+    a message box to close and is not compatible with gestures.
 
-    Supported icon animation formats are following:
+    Four types of message boxes are predefined. The type determines a set of default properties that
+    are set on construction. Below is a table listing types and their default properties.
+
+    <table border="1">
+        <caption><b>HbDeviceMessageBox types and default properties</b></caption>
+        <tr><th>Type</th><th>Icon</th><th>Buttons</th><th>Timeout</th><th>Dismiss policy</th><th>Sound</th></tr>
+        <tr><td>None</td><td>No icon</td><td>"Ok" button</td><td>Standard timeout</td><td>Tap anywhere</td><td>No sound</td></tr>
+        <tr><td>Information</td><td>Info icon</td><td>"Ok" button</td><td>Standard timeout</td><td>Tap anywhere</td><td>Info sound</td></tr>
+        <tr><td>Warning</td><td>Warning icon</td><td>"Ok" button</td><td>Standard timeout</td><td>Tap anywhere</td><td>Warn sound</td></tr>
+        <tr><td>Question</td><td>Question icon</td><td>"Yes" and "No" buttons</td><td>No timeout</td><td>Button press</td><td>Question sound</td></tr>
+    </table>
+
+    In place of an icon, message box may conatain an animation. Supported icon animation formats are:
     - GIF (.gif)
     - MNG (.mng)
     - Frame animations (.axml)
@@ -405,7 +470,7 @@
     }
     \endcode
 
-    Alter the appearance of the message box with the methods provided by the class.
+    Modify appearance of a message box with the methods provided by the class.
 
     \code
     // Code below modifies the default properties of the message box.
@@ -425,6 +490,9 @@
     QAction rejectAction("Cancel", 0);
     messageBox.setAction(&rejectAction, HbDeviceMessageBox::RejectButtonRole);
 
+    // Set standard buttons
+    messageBox.setStandardButtons(HbMessageBox::Ok|HbMessageBox::Cancel);
+
     // Beware, application may exit during exec().
     // Beware, exec() is not compatible with gestures.
     QAction *result = messageBox.exec();
@@ -465,8 +533,8 @@
 /*!
     \fn void HbDeviceMessageBox::aboutToClose();
 
-    This signal is emitted when the device message box is about to be closed i.e.
-    when the question type of message is replied to by the user.
+    This signal is emitted when the message box has closed. If a button was pressed,
+    corresponding action's triggered() signal is emitted before this signal.
  */
 
 /*!
@@ -475,7 +543,7 @@
 */
 /*!
     \var HbDeviceMessageBox::ActionRole HbDeviceMessageBox::InvalidRole
-    No action.
+    No role.
 */
 /*!
     \var HbDeviceMessageBox::ActionRole HbDeviceMessageBox::AcceptButtonRole
@@ -503,7 +571,7 @@
 
 /*!
     Constructor.
-    \param text Text can be set in the constructor.
+    \param text Message box text.
     \param type Type of the message box.
     \param parent An optional parameter.
 */
@@ -529,7 +597,12 @@
 }
 
 /*!
-    Executes the dialog asynchronously.
+    Shows a message box and returns immediately without waiting for it to close. Closing of the
+    message box is indicated by aboutToClose() signal. Button presses are indicated by
+    QAction::triggered() signals. The message box can be updated while showing by property
+    setters.
+
+    \sa update(), aboutToClose()
 */
 void HbDeviceMessageBox::show()
 {
@@ -539,10 +612,10 @@
 }
 
 /*!
-    Updates changed properties of a launched message box to device dialog service using
-    interprocess communication. Has no effect if show() has not been called or dialog has
-    closed already. Calling show() is optional as updating any property schedules an event
-    and the dialog is updated next time Qt event loop executes.
+    Updates changed properties to a showing message box via interprocess communication.
+    Has no effect if show() has not been called or the message box has closed already.
+    Calling update() is optional as setting any property schedules an event and the
+    showing message box is updated next time Qt event loop executes.
 
     \sa show()
 */
@@ -552,7 +625,7 @@
 }
 
 /*!
-    Closes the dialog if the dialog is shown asynchronously.
+    Closes a message box shown asynchronously.
 */
 void HbDeviceMessageBox::close()
 {
@@ -564,10 +637,10 @@
 /*!
     Executes the dialog synchronously.
 
-    Returns a pointer to the action that was activated by the user, i.e. dialog's
-    accept or reject action. Return 0 if object was deleted during a call.
+    Returns a pointer to an action corresponding to a button pressed. Returns 0 if no button
+    was pressed (the dialog closed for other reason).
 
-    This functions starts a new event loop. Consider following caveats before using it
+    This functions starts a new event loop. Consider following caveats before using it.
     Stack usage increases. Depending on application program flow, several event
     loops may get instantiated on top of each other. Application event processing continues while
     exec() executes. When it returns application state may have changed. For example some
@@ -624,7 +697,8 @@
 
 /*!
     Sets message box type. All message box properties are reset to a default values for the type.
-    A show() must be called to launch a message box after setMessageBoxType() has been called.
+    Type of a showing message box cannot be changed on the fly. show() must be called to launch
+    a new message box after setMessageBoxType() has been called.
 
     \param type Message box type.
 
@@ -653,9 +727,39 @@
 }
 
 /*!
+    Sets message box buttons to standard buttons.
+
+    \param buttons Message box buttons. A combination of flags,
+    eg. HbMessageBox::Yes | HbMessageBox::No. Button flags are scanned starting from lsb.
+    First button found goes to accept position and so forth.
+
+    \sa standardButtons()
+*/
+void HbDeviceMessageBox::setStandardButtons(HbMessageBox::StandardButtons buttons)
+{
+    TRACE_ENTRY
+    d_ptr->setStandardButtons(buttons);
+    d_ptr->scheduleUpdateEvent();
+    TRACE_EXIT
+}
+
+/*!
+    Returns standard buttons set to a message box. A default value for question message box is
+    HbMessageBox::Yes|HbMessageBox::No. For all other message box types the default is
+    HbMessageBox::Ok.
+
+    \sa setStandardButtons()
+*/
+HbMessageBox::StandardButtons HbDeviceMessageBox::standardButtons() const
+{
+    return static_cast<HbMessageBox::StandardButtons>
+        (d_ptr->mProperties[HbDeviceMessageBoxPrivate::StandardButtons].mValue.toInt());
+}
+
+/*!
     Convenience method for showing question message box and waiting for it to close.
 
-    This functions starts a new event loop. Consider following caveats before using it
+    This functions starts a new event loop. Consider following caveats before using it.
     Stack usage increases. Depending on application program flow, several event
     loops may get instantiated on top of each other. Application event processing continues while
     question() executes. When it returns application state may have changed. For example some
@@ -665,11 +769,11 @@
     has an user interface, please don't use this function. Instead connect to signals and use
     asynchronous show().
 
-    \param text - text shown in message box.
-    \param acceptButtonText Accept button text. If string is null, a default button is used.
-    \param rejectButtonText Reject button text. If string is null, a default button is used.
+    \param text Message box text.
+    \param acceptButtonText Accept button text. If string is null, a default (Yes) button is used.
+    \param rejectButtonText Reject button text. If string is null, a default (No) button is used.
 
-    Returns true if user triggered accept action, otherwise false.
+    Returns true if user pressed accept button, otherwise false.
 
     \sa show()
 */
@@ -681,12 +785,12 @@
     TRACE_STATIC_ENTRY
     HbDeviceMessageBox messageBox(HbMessageBox::MessageTypeQuestion);
     messageBox.setText(text);
-
+    messageBox.setStandardButtons(HbMessageBox::Yes|HbMessageBox::No);
     if (!acceptButtonText.isNull()) {
-        messageBox.setAction(new QAction(acceptButtonText, &messageBox), AcceptButtonRole);
+        messageBox.action(AcceptButtonRole)->setText(acceptButtonText);
     }
     if (!rejectButtonText.isNull()) {
-        messageBox.setAction(new QAction(rejectButtonText, &messageBox), RejectButtonRole);
+        messageBox.action(RejectButtonRole)->setText(rejectButtonText);
     }
     messageBox.exec();
     TRACE_EXIT
@@ -695,10 +799,42 @@
 }
 
 /*!
+    Convenience method for showing question message box and waiting for it to close.
+
+    This functions starts a new event loop. Consider following caveats before using it.
+    Stack usage increases. Depending on application program flow, several event
+    loops may get instantiated on top of each other. Application event processing continues while
+    question() executes. When it returns application state may have changed. For example some
+    objects may have been deleted or application may have exited.
+
+    <b>Note that starting an event loop isn't compatible with gestures.</b> Therefore if an application
+    has an user interface, please don't use this function. Instead connect to signals and use
+    asynchronous show().
+
+    \param text Message box text.
+    \param buttons Specifies message box buttons. See setStandardButtons() for format.
+
+    Returns true if user pressed accept button, otherwise false.
+
+    \sa show()
+*/
+bool HbDeviceMessageBox::question(const QString &text, HbMessageBox::StandardButtons buttons)
+{
+    TRACE_STATIC_ENTRY
+    HbDeviceMessageBox messageBox(HbMessageBox::MessageTypeQuestion);
+    messageBox.setText(text);
+    messageBox.setStandardButtons(buttons);
+    messageBox.exec();
+    TRACE_EXIT
+    // Return true if accept action was triggered
+    return messageBox.isAcceptAction(messageBox.triggeredAction());
+}
+
+/*!
     Convenience method for showing information message box. Launches a message box and
     returns immediately.
 
-    \param text - text shown in message box.
+    \param text Message box text.
 */
 void HbDeviceMessageBox::information(const QString &text)
 {
@@ -711,7 +847,7 @@
     Convenience method for showing warning message box. Launches a message box and returns
     immediately.
 
-    \param text - text shown in message box.
+    \param text Message box text.
 */
 void HbDeviceMessageBox::warning(const QString &text)
 {
@@ -737,7 +873,7 @@
 }
 
 /*!
-    Sets an action into the device message box. Action role is either an
+    Sets an action into device message box. Action role is either an
     accept (left button in left-to-right layout) or reject (right button).
     Action can be null which removes corresponding button from the message
     box. Only text of the action is shown in the message box button. Icon
@@ -745,11 +881,11 @@
     the action.
 
     HbDeviceMessageBox constructor sets a default accept and reject actions into
-    question message box. Information and warning message boxes have only accept
-    action by default. Default actions are owned and deleted by the message box.
+    question message box. Other message boxes have only accept action by default.
+    Default actions are owned and deleted by the message box.
 
     \param action Action or null. Ownership does not transfer.
-    \param role Selects an action to set.
+    \param role Selects an action.
 
     \sa action()
 */
@@ -766,11 +902,11 @@
 }
 
 /*!
-    Sets text of the message dialog.
+    Sets message box text. Supported text formats are the same as HbMessageBox::setText().
 
-    \param text Message text.
+    \param text Message box text.
 
-    \sa text()
+    \sa text(), HbMessageBox::setText()
 */
 void HbDeviceMessageBox::setText(const QString &text)
 {
@@ -780,7 +916,7 @@
 }
 
 /*!
-    Returns text of the dialog.
+    Returns message box text.
 
     \sa setText()
 */
@@ -839,10 +975,9 @@
 }
 
 /*!
-    Sets the timeout property in milliseconds.
-    If timeout <= 0 then the note is permanent and not closed automatically.
+    Sets message box timeout.
 
-    \param timeout Timeout in milliseconds.
+    \param timeout Timeout in milliseconds. 0 denotes no timeout (infinite).
 
     \sa timeout() setTimeout(HbPopup::DefaultTimeout)
 */
@@ -854,8 +989,8 @@
 }
 
 /*!
-    This is a convenience overload of \a timeout() for setting HbPopup::DefaultTimeout values
-    to achive common look & feel.
+    Sets timeout to one of HbPopup::DefaultTimeout values. Helps achieving
+    common look and feel of message boxes.
 
     \param timeout Timeout as an enumerated constant.
 
@@ -869,9 +1004,9 @@
 }
 
 /*!
-    Returns the timeout property in milliseconds.
-    If this property is not set the default is HbPopup::StandardTimeout except for
-    HbMessageBox::MessageTypeQuestion type of message box for which default is HbPopup::NoTimeout.
+    Returns message box timeout in milliseconds. Default value depends on message box type.
+    Question message box has a default of HbPopup::NoTimeout. All other boxes, the default is
+    HbPopup::StandardTimeout.
 
     \sa setTimeout()
 */
@@ -881,9 +1016,9 @@
 }
 
 /*!
-    Sets the dismiss policy for the dialog.
+    Sets message box dismiss policy.
 
-    \param dismissPolicy Dismiss policy of the message box.
+    \param dismissPolicy Dismiss policy.
 
     \sa dismissPolicy()
 */
@@ -895,9 +1030,8 @@
 }
 
 /*!
-    Returns the dismiss policy of the dialog.
-    Default is HbPopup::TapAnywhere except for HbMessageBox::MessageTypeQuestion type of
-    message box for which default is HbPopup::NoDismiss.
+    Returns dismiss policy of a message box. Default depends on message box type.
+    Question box has default HbPopup::NoDismiss and all other boxes HbPopup::TapAnywhere.
 
     \sa setDismissPolicy()
 */
@@ -908,7 +1042,7 @@
 }
 
 /*!
-    Sets animation definition to a dialog. Animation's logical name has to be set
+    Sets animation a message box. Animation's logical name has to be set
     using setIcon(). Animation definition files must be stored to a place where they
     can be accessed by device dialog service.