/****************************************************************************
**
** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (developer.feedback@nokia.com)
**
** This file is part of the HbWidgets module of the UI Extensions for Mobile.
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at developer.feedback@nokia.com.
**
****************************************************************************/
#include <hbdevicedialog.h>
#include <hbdevicedialogtrace_p.h>
#include "hbdevicemessagebox.h"
#include "hbdevicemessagebox_p.h"
#include <QTimer>
#include <QTimerEvent>
#include <QAction>
#include <QPointer>
HbDeviceMessageBoxPrivate::HbDeviceMessageBoxPrivate() : QObject(),
mDeviceDialog(0),
mVisible(false),
mUpdateTimerId(0)
{
TRACE_ENTRY
for(int i = 0; i < NumActions; i++) {
mDefaultActions[i] = 0;
mActions[i].mAction = 0;
}
TRACE_EXIT
}
HbDeviceMessageBoxPrivate::~HbDeviceMessageBoxPrivate()
{
TRACE_ENTRY
// Dialogs may be left at server when client is deleted. If there are no connected
// signals, device dialog widget is not deleted but runs at server and is closed by a timeout.
if (q_ptr->receivers(SIGNAL(aboutToClose())) <= 0) {
mDeviceDialog->disconnect(q_ptr, SLOT(aboutToClose()));
mDeviceDialog->disconnect(this, SLOT(triggerAction(QVariantMap)));
if (mUpdateTimerId != 0) {
// There's a pending update
sendToServer(false); // this also kills the timer
}
}
delete mDeviceDialog;
for(int i = 0; i < NumActions; i++) {
delete mDefaultActions[i];
}
TRACE_EXIT
}
void HbDeviceMessageBoxPrivate::init()
{
TRACE_ENTRY
initProperties();
mDeviceDialog = new HbDeviceDialog;
connect(mDeviceDialog, SIGNAL(deviceDialogClosed()), q_ptr, SIGNAL(aboutToClose()));
connect(mDeviceDialog, SIGNAL(dataReceived(QVariantMap)), this, SLOT(triggerAction(QVariantMap)));
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++) {
mProperties[i].mFlags = NoFlags;
}
for(int i = 0; i < NumActions; i++) {
clearAction(mActions[i]);
}
QString text;
q_ptr->setText(text);
q_ptr->setIconName(text);
q_ptr->setIconVisible(true);
q_ptr->setAnimationDefinition(text);
bool useActions[NumActions];
for(int i = 0; i < NumActions; i++) {
useActions[i] = false;
}
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));
// 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);
// 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;
default:
Q_ASSERT(false);
}
for(int i = 0; i < NumActions; i++) {
if (useActions[i]) {
initAction(i);
}
}
}
void HbDeviceMessageBoxPrivate::setAction(ActionSelector select, QAction *action)
{
TRACE_ENTRY
Action &dialogAction = mActions[select];
bool saveTriggered = dialogAction.mTriggered;
clearAction(dialogAction);
dialogAction.mTriggered = saveTriggered;
dialogAction.mFlags = Modified;
dialogAction.mAction = action;
if (dialogAction.mAction) {
connect(dialogAction.mAction, SIGNAL(changed()), SLOT(actionChanged()));
}
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)
{
killTimer(mUpdateTimerId);
mUpdateTimerId = 0;
// If this is update but show has not been called, return.
if (!show && !mVisible) {
return;
}
// If this is update but no properties have been mofified, return
if (!show && !propertiesModified()) {
return;
}
// If this is a show, send type property
if (show) {
mProperties[Type].mFlags = Modified;
}
static const char * const propertyNames[] = {
"type",
"standardButtons",
"text",
"iconName",
"iconVisible",
"timeout",
"dismissPolicy",
"animationDefinition"
};
QVariantMap parameters;
for(int i = 0; i < NumProperties; i++) {
if (mProperties[i].mFlags & Modified) {
if (show || !(mProperties[i].mFlags & SentToServer)) {
parameters.insert(propertyNames[i], mProperties[i].mValue);
mProperties[i].mFlags |= SentToServer;
}
}
}
static const char * const actionNames[] = {
"acceptAction",
"rejectAction"
};
for(int i = 0; i < NumActions; i++) {
if (mActions[i].mFlags & Modified) {
if (show || !(mActions[i].mFlags & SentToServer)) {
QString actionData; // empty removes action at the plugin
if (mActions[i].mAction) {
actionData.append("t:").append(mActions[i].mAction->text());
}
parameters.insert(actionNames[i], actionData);
mActions[i].mFlags |= SentToServer;
}
}
}
if (show) {
for(int i = 0; i < NumActions; i++) {
mActions[i].mTriggered = false;
}
if (mDeviceDialog->show("com.nokia.hb.devicemessagebox/1.0", parameters)) {
mVisible = true;
} else { // failed to show device dialog. Start a one shot to emit aboutToClose() signal.
QTimer::singleShot(0, q_ptr, SIGNAL(aboutToClose()));
}
} else {
mDeviceDialog->update(parameters);
}
}
// Check if any properties have been modified
bool HbDeviceMessageBoxPrivate::propertiesModified() const
{
for(int i = 0; i < NumProperties; i++) {
if ((mProperties[i].mFlags & Modified) && !(mProperties[i].mFlags & SentToServer)) {
return true;
}
}
for(int i = 0; i < NumActions; i++) {
if ((mActions[i].mFlags & Modified) && !(mActions[i].mFlags & SentToServer)) {
return true;
}
}
return false;
}
// Clear action
void HbDeviceMessageBoxPrivate::clearAction(Action &action)
{
if (action.mAction) {
disconnect(action.mAction, SIGNAL(changed()), this, SLOT(actionChanged()));
}
action.mAction = 0;
action.mFlags = NoFlags;
action.mTriggered = false;
}
void HbDeviceMessageBoxPrivate::close()
{
TRACE_ENTRY
mDeviceDialog->cancel();
mVisible = false;
TRACE_EXIT
return;
}
void HbDeviceMessageBoxPrivate::exec()
{
TRACE_ENTRY
sendToServer(true);
mDeviceDialog->waitForClosed();
TRACE_EXIT
}
void HbDeviceMessageBoxPrivate::triggerAction(QVariantMap data)
{
TRACE_ENTRY
const char *key = "act";
QVariantMap::const_iterator i = data.find(key);
if (i != data.constEnd()) {
QAction *action;
if (i.value().toString() == "p") {
mActions[AcceptButton].mTriggered = true;
action = mActions[AcceptButton].mAction;
} else {
mActions[RejectButton].mTriggered = true;
action = mActions[RejectButton].mAction;
}
if (action) {
action->trigger();
}
}
TRACE_EXIT
}
void HbDeviceMessageBoxPrivate::actionChanged()
{
QObject *action = sender();
for(int i = 0; i < NumActions; i++) {
if (mActions[i].mAction == action) {
mActions[i].mFlags = Modified;
scheduleUpdateEvent();
break;
}
}
}
void HbDeviceMessageBoxPrivate::setProperty(PropertySelector propertySelector, int value)
{
Property &property = mProperties[propertySelector];
property.mValue.setValue(value);
property.mFlags = Modified;
scheduleUpdateEvent();
}
void HbDeviceMessageBoxPrivate::setProperty(PropertySelector propertySelector,
const QString &value)
{
Property &property = mProperties[propertySelector];
property.mValue.setValue(value);
property.mFlags = Modified;
scheduleUpdateEvent();
}
// Schedule event to update changed properties to device dialog server. update() is not
// called after each time a property is set. Instead an event is scheduled in order to
// update all changed properties in one shot.
void HbDeviceMessageBoxPrivate::scheduleUpdateEvent()
{
if (mVisible && mUpdateTimerId == 0) {
mUpdateTimerId = startTimer(0);
}
}
void HbDeviceMessageBoxPrivate::timerEvent(QTimerEvent *event)
{
if (event->timerId() == mUpdateTimerId) {
sendToServer(false);
}
}
int HbDeviceMessageBoxPrivate::timeoutValue(HbPopup::DefaultTimeout timeout)
{
TRACE_STATIC_ENTRY
static const struct { HbPopup::DefaultTimeout timeout; int value; } timeoutValues[] = {
{HbPopup::NoTimeout,0},
{HbPopup::ConfirmationNoteTimeout,1500},
{HbPopup::StandardTimeout,3000},
{HbPopup::ContextMenuTimeout,6000}
};
int count = sizeof(timeoutValues) / sizeof(timeoutValues[0]);
if (timeout < 0 || timeout >= count) {
TRACE_EXIT
return timeoutValues[HbPopup::NoTimeout].value;
}
TRACE_EXIT
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)
{
static const ActionSelector selectors[] = {
AcceptButton, RejectButton
};
const unsigned numSelectors = sizeof(selectors) / sizeof(selectors[0]);
unsigned index = role;
if (index >= numSelectors) {
Q_ASSERT(false);
return InvalidSelector;
}
else {
return selectors[index];
}
}
/*!
@stable
@hbwidgets
\class HbDeviceMessageBox
\brief HbDeviceMessageBox displays a message box on top all applications.
HbDeviceMessageBox is a device-dialog version of HbMessageBox. It is a modal
dialog and displayed on top all applications by a device-dialog service.
HbDeviceMessageBox is a client of the service.
For content it provides text, icon or animation and optional accept and reject buttons.
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.
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.
If none of HbDeviceMessageBox signals have been connected to, the object can be deleted after
show() has been called and device-dialog service takes care showing the message box. If any
signals are connected, message box is closed when HbDeviceMessageBox object goes out of scope.
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 contain an animation. Supported icon animation formats are:
- GIF (.gif)
- MNG (.mng)
- Frame animations (.axml)
\section _platform_spec Platform-specific implementation notes for HbDeviceNotificationDialog
\subsection _nonsymbian Non-Symbian
Device dialog service is implemented only for the Symbian platform. On other platforms device
message boxes are displayed on client's main window.
\section _code_samples Sample code
\code
// Ask from user whether to continue operation or not.
// Uses default accept/reject buttons (yes/no).
bool value = HbDeviceMessageBox::question("Continue operation ?");
if (value) {
continueOperation();
}
\endcode
Modify appearance of a message box with the methods provided by the class.
\code
// Code below modifies the default properties of the message box.
HbDeviceMessageBox messageBox(HbMessageBox::MessageTypeQuestion);
messageBox.setText("End game?");
QString fileName("note_warning");
messageBox.setIconName(fileName);
// Change button text
messageBox.action(HbDeviceMessageBox::AcceptButtonRole)->setText("Ok");
messageBox.action(HbDeviceMessageBox::RejectButtonRole)->setText("Cancel");
// Set new actions (buttons)
QAction acceptAction("Ok", 0);
messageBox.setAction(&acceptAction, HbDeviceMessageBox::AcceptButtonRole);
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();
bool quit = messageBox.isAcceptAction(result);
if (quit) {
quit();
}
\endcode
Creating a frame animation.
Create an animation definition file:
\code
<animations>
<icon name="frame_anim_looping" playmode="loop">
<frame duration="100">c:\icon1.svg</frame>
<frame duration="200">c:\icon2.svg</frame>
<frame duration="300">c:\icon3.svg</frame>
</icon>
</animations>
\endcode
Create HbDeviceMessageBox in a way described before and
set definition file and animation's logical name.
\code
QString animationDefinitionXML("c:\animation.axml");
QString logicalIconName("frame_anim_looping");
msg->setAnimationDefinition(animationDefinitionXML);
msg->setIconName(logicalIconName);
msg->show();
\endcode
\sa HbMessageBox, HbDialog, HbDeviceDialog, CHbDeviceMessageBoxSymbian
*/
/*!
\fn void HbDeviceMessageBox::aboutToClose();
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.
*/
/*!
\enum HbDeviceMessageBox::ActionRole
Defines roles for actions set into a message box.
*/
/*!
\var HbDeviceMessageBox::ActionRole HbDeviceMessageBox::InvalidRole
No role.
*/
/*!
\var HbDeviceMessageBox::ActionRole HbDeviceMessageBox::AcceptButtonRole
Accept button action.
*/
/*!
\var HbDeviceMessageBox::ActionRole HbDeviceMessageBox::RejectButtonRole
Reject button action.
*/
/*!
Constructs HbDeviceMessageBox.
\param type Type of the message box.
\param parent Parent pointer or 0.
*/
HbDeviceMessageBox::HbDeviceMessageBox(HbMessageBox::MessageBoxType type, QObject *parent) :
QObject(parent), d_ptr(new HbDeviceMessageBoxPrivate)
{
TRACE_ENTRY
d_ptr->q_ptr = this;
d_ptr->mProperties[HbDeviceMessageBoxPrivate::Type].mValue.setValue(static_cast<int>(type));
d_ptr->init();
TRACE_EXIT
}
/*!
Constructs HbDeviceMessageBox.
\param text Message box text.
\param type Type of the message box.
\param parent Parent pointer or 0.
*/
HbDeviceMessageBox::HbDeviceMessageBox(const QString &text, HbMessageBox::MessageBoxType type,
QObject *parent) : QObject(parent), d_ptr(new HbDeviceMessageBoxPrivate)
{
TRACE_ENTRY
d_ptr->q_ptr = this;
d_ptr->mProperties[HbDeviceMessageBoxPrivate::Type].mValue.setValue(static_cast<int>(type));
d_ptr->init();
setText(text);
TRACE_EXIT
}
/*!
Destructs HbDeviceMessageBox. The message box launched by show() is closed if aboutToClose()
signal is connected to by an application. Otherwise the box is left executing
and should close itself by a timeout.
*/
HbDeviceMessageBox::~HbDeviceMessageBox()
{
TRACE_ENTRY
delete d_ptr;
TRACE_EXIT
}
/*!
Shows a message box and returns immediately without waiting for it to close. A new message box
is launched each time show() is called. 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()
{
TRACE_ENTRY
d_ptr->sendToServer(true);
TRACE_EXIT
}
/*!
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()
*/
void HbDeviceMessageBox::update()
{
d_ptr->sendToServer(false);
}
/*!
Closes a message box shown asynchronously.
*/
void HbDeviceMessageBox::close()
{
TRACE_ENTRY
d_ptr->close();
TRACE_EXIT
}
/*!
Executes the dialog synchronously.
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.
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
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().
\sa action(), setAction()
*/
const QAction *HbDeviceMessageBox::exec()
{
TRACE_ENTRY
const QAction *action;
QPointer<HbDeviceMessageBoxPrivate> guard = d_ptr;
d_ptr->exec();
if (guard.isNull()) {
action = 0;
} else {
action = triggeredAction();
}
TRACE_EXIT
return action;
}
/*!
Returns an action user triggered causing the dialog to close. Returns 0 if none of the actions were
triggered and dialog was closed for other reason.
\sa show(), exec(), action(), isAcceptAction()
*/
const QAction *HbDeviceMessageBox::triggeredAction() const
{
for(int i = 0; i < HbDeviceMessageBoxPrivate::NumActions; i++) {
if (d_ptr->mActions[i].mTriggered) {
return d_ptr->mActions[i].mAction;
}
}
return 0;
}
/*!
Returns true if an action is an accept action. This function should be used to check whether
user accepted message box by triggering accept action. In the future there could be several
accept actions instead of only one.
\sa exec(), action(), triggeredAction()
*/
bool HbDeviceMessageBox::isAcceptAction(const QAction *action) const
{
return action && action == d_ptr->mActions[HbDeviceMessageBoxPrivate::AcceptButton].mAction;
}
/*!
Sets message box type. All message box properties are reset to a default values for the type.
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.
\sa messageBoxType(), show()
*/
void HbDeviceMessageBox::setMessageBoxType(HbMessageBox::MessageBoxType type)
{
TRACE_ENTRY
// After setType(), a new message is launched by a show()
d_ptr->mVisible = false;
d_ptr->mProperties[HbDeviceMessageBoxPrivate::Type].mValue.setValue(static_cast<int>(type));
// All properties initialized to default
d_ptr->initProperties();
TRACE_EXIT
}
/*!
Returns message box type.
\sa setMessageBoxType()
*/
HbMessageBox::MessageBoxType HbDeviceMessageBox::messageBoxType() const
{
return static_cast<HbMessageBox::MessageBoxType>
(d_ptr->mProperties[HbDeviceMessageBoxPrivate::Type].mValue.toInt());
}
/*!
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(), show(), update()
*/
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.
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 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 pressed accept button, otherwise false.
\sa show()
*/
bool HbDeviceMessageBox::question(
const QString &text,
const QString &acceptButtonText,
const QString &rejectButtonText)
{
TRACE_STATIC_ENTRY
HbDeviceMessageBox messageBox(HbMessageBox::MessageTypeQuestion);
messageBox.setText(text);
messageBox.setStandardButtons(HbMessageBox::Yes|HbMessageBox::No);
if (!acceptButtonText.isNull()) {
messageBox.action(AcceptButtonRole)->setText(acceptButtonText);
}
if (!rejectButtonText.isNull()) {
messageBox.action(RejectButtonRole)->setText(rejectButtonText);
}
messageBox.exec();
TRACE_EXIT
// Return true if accept action was triggered
return messageBox.isAcceptAction(messageBox.triggeredAction());
}
/*!
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 Message box text.
*/
void HbDeviceMessageBox::information(const QString &text)
{
TRACE_STATIC_ENTRY
HbDeviceMessageBox(text, HbMessageBox::MessageTypeInformation).show();
TRACE_EXIT
}
/*!
Convenience method for showing warning message box. Launches a message box and returns
immediately.
\param text Message box text.
*/
void HbDeviceMessageBox::warning(const QString &text)
{
TRACE_STATIC_ENTRY
HbDeviceMessageBox(text, HbMessageBox::MessageTypeWarning).show();
TRACE_EXIT
}
/*!
Returns device message box action. The action returned may be a default
action that message box has set at constructor or one set by setAction().
\param role Selects an action to get.
\sa setAction()
*/
QAction *HbDeviceMessageBox::action(ActionRole role) const
{
HbDeviceMessageBoxPrivate::ActionSelector actionSelector =
HbDeviceMessageBoxPrivate::actionSelector(role);
return actionSelector != HbDeviceMessageBoxPrivate::InvalidSelector ?
d_ptr->mActions[actionSelector].mAction : 0;
}
/*!
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
of the action is not used. The message box does not take ownership of
the action.
HbDeviceMessageBox constructor sets a default accept and reject actions into
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.
\sa action(), show(), update()
*/
void HbDeviceMessageBox::setAction(QAction *action, ActionRole role)
{
TRACE_ENTRY
HbDeviceMessageBoxPrivate::ActionSelector actionSelector =
HbDeviceMessageBoxPrivate::actionSelector(role);
if (actionSelector != HbDeviceMessageBoxPrivate::InvalidSelector) {
d_ptr->setAction(HbDeviceMessageBoxPrivate::actionSelector(role), action);
d_ptr->scheduleUpdateEvent();
}
TRACE_EXIT
}
/*!
Sets message box text. Supported text formats are the same as HbMessageBox::setText().
\param text Message box text.
\sa text(), show(), update(), HbMessageBox::setText()
*/
void HbDeviceMessageBox::setText(const QString &text)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::Text, text);
TRACE_EXIT
}
/*!
Returns message box text.
\sa setText()
*/
QString HbDeviceMessageBox::text() const
{
return d_ptr->mProperties[HbDeviceMessageBoxPrivate::Text].mValue.toString();
}
/*!
Sets message box icon name or animation logical name.
\param aIconName Icon name. Icon can be from Hb resources or themes. Or can be a file in
a file system.
\sa IconName(), show(), update()
*/
void HbDeviceMessageBox::setIconName(const QString &iconName)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::IconName, iconName);
TRACE_EXIT
}
/*!
Returns name and path of the icon or animation's logical name.
\sa setIconName()
*/
QString HbDeviceMessageBox::iconName() const
{
return d_ptr->mProperties[HbDeviceMessageBoxPrivate::IconName].mValue.toString();
}
/*!
Enables/disables icon visibility.
\param visible Enables icon visibility.
\sa iconVisible(), show(), update()
*/
void HbDeviceMessageBox::setIconVisible(bool visible)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::IconVisible, visible);
TRACE_EXIT
}
/*!
Returns true if icon is visible.
\sa setIconVisible()
*/
bool HbDeviceMessageBox::iconVisible() const
{
return d_ptr->mProperties[HbDeviceMessageBoxPrivate::IconVisible].mValue.toBool();
}
/*!
Sets message box timeout.
\param timeout Timeout in milliseconds. 0 denotes no timeout (infinite).
\sa timeout(), setTimeout(HbPopup::DefaultTimeout), show(), update()
*/
void HbDeviceMessageBox::setTimeout(int timeout)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::Timeout, timeout);
TRACE_EXIT
}
/*!
Sets timeout to one of HbPopup::DefaultTimeout values. Helps achieving
common look and feel of message boxes.
\param timeout Timeout as an enumerated constant.
\sa enum HbPopup::DefaultTimeout, timeout(), setTimeout(int), show(), update()
*/
void HbDeviceMessageBox::setTimeout(HbPopup::DefaultTimeout timeout)
{
TRACE_ENTRY
setTimeout(HbDeviceMessageBoxPrivate::timeoutValue(timeout));
TRACE_EXIT
}
/*!
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()
*/
int HbDeviceMessageBox::timeout() const
{
return d_ptr->mProperties[HbDeviceMessageBoxPrivate::Timeout].mValue.toInt();
}
/*!
Sets message box dismiss policy.
\param dismissPolicy Dismiss policy.
\sa dismissPolicy(), show(), update()
*/
void HbDeviceMessageBox::setDismissPolicy(HbPopup::DismissPolicy dismissPolicy)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::DismissPolicy, dismissPolicy);
TRACE_EXIT
}
/*!
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()
*/
HbPopup::DismissPolicy HbDeviceMessageBox::dismissPolicy() const
{
return static_cast<HbPopup::DismissPolicy>
(d_ptr->mProperties[HbDeviceMessageBoxPrivate::DismissPolicy].mValue.toInt());
}
/*!
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.
Supported animation formats are following:
- GIF (.gif)
- MNG (.mng)
- Frame animations
\param animationDefinition Path and name of the animation definition file.
\sa setIcon(), animationDefinition(), HbIconAnimationManager::addDefinitionFile(), show(), update()
*/
void HbDeviceMessageBox::setAnimationDefinition(QString &animationDefinition)
{
TRACE_ENTRY
d_ptr->setProperty(HbDeviceMessageBoxPrivate::AnimationDefinition, animationDefinition);
TRACE_EXIT
}
/*!
Returns animation definition file name.
\sa setAnimationDefinition()
*/
QString HbDeviceMessageBox::animationDefinition() const
{
return d_ptr->mProperties[HbDeviceMessageBoxPrivate::AnimationDefinition].mValue.toString();
}