--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hbcore/devicedialogbase/hbdevicedialogsymbian.cpp Mon Apr 19 14:02:13 2010 +0300
@@ -0,0 +1,568 @@
+/****************************************************************************
+**
+** 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 HbCore 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 <QVariant>
+
+#include "hbdevicedialogserverdefs_p.h"
+#include "hbdevicedialogerrors_p.h"
+#include "hbdevicedialogclientsession_p.h"
+#include <e32cmn.h>
+
+#include "hbdevicedialogsymbian.h"
+#include "hbsymbianvariant.h"
+#include "hbsymbianvariantconverter_p.h"
+#include "hbdeleteguardsymbian_p.h"
+
+/*!
+ \class CHbDeviceDialogSymbian
+ \brief CHbDeviceDialog displays dialogs on top of applications. It is a client interface for Symbian applications to Hb
+ device dialogs.
+ \sa HbDeviceDialog
+
+ Data given to this API in symbian format is packed to QVariantMap. See
+ CHbSymbianVariant to see which Qt datatypes are supported.
+ \sa CHbSymbianVariant
+ \sa CHbSymbianVariantMap
+
+ When plugin returns data in Qt format, the data is converted, if possible,
+ to CHbSymbianVariantMap.
+
+ \proto
+
+ \hbcore
+ */
+
+/*!
+ \enum CHbDeviceDialogSymbian::TDeviceDialogError
+ Defines device dialog error codes and ranges.
+*/
+/*!
+ \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EFrameworkErrors
+ Start of an error range for errors originating from device dialog framework (client or server).
+*/
+/*!
+ \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EPluginErrors
+ Start of an error range for errors originating from device dialog plugins. The framework passes
+ these from the plugin unmodified.
+*/
+/*!
+ \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::EErrorTypeMask
+ Mask for error type part of the error code.
+*/
+/*!
+ \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::ECancelledError
+ Operation was cancelled by Cancel().
+*/
+/*!
+ \var TDeviceDialogError::DeviceDialogError HbDeviceDialog::ESystemCancelledError
+ Operation was cancelled by device dialog framework.
+*/
+
+/*!
+ \fn void MHbDeviceDialogObserver::DataReceived(CHbSymbianVariantMap& aData)
+
+ This callback is called when data is received from a device dialog.
+ \a aData contains data from the dialog plugin.
+ The structure and meaning of the data is a contract between the dialog and
+ a client. Structure should be aligned with the data types supported by
+ CHbSymbianVariantMap.
+
+ \sa CHbSymbianVariantMap.
+*/
+
+/*!
+ \fn void MHbDeviceDialogObserver::DeviceDialogClosed(TInt aCompletionCode)
+
+ This callback is called when a device dialog is closed. Any data sent by
+ the dialog is indicated by the dataReceived() callback. If no observer is
+ set in CHbDeviceDialogSymbian::Show the latest data can be retrieved with
+ CHbDeviceDialogSymbian::receivedData()
+
+ \a aCompletionCode gives the result of the dialog completion. Code can be
+ either Symbian error code or device dialog error code.
+
+ \sa DataReceived() ReceivedData()
+*/
+
+// Device dialogs are implemented only for Symbian/S60 OS.
+
+class CHbDeviceDialogSymbianPrivate : public CActive
+{
+public:
+ CHbDeviceDialogSymbianPrivate();
+ ~CHbDeviceDialogSymbianPrivate();
+ TInt Show( const QByteArray& aArray );
+ TInt Update( const QByteArray& aArray );
+ void CancelDialog();
+ TInt Error() const;
+ void SetObserver( MHbDeviceDialogObserver* aObserver );
+
+ // CActive
+ void RunL();
+ void DoCancel();
+ TInt RunError( TInt aError );
+
+ void Start();
+ TInt SymToDeviceDialogError( TInt errorCode );
+ void SetError(TInt aError);
+ bool CallDialogClosedObserver(TInt aCompletionCode);
+ bool CallDataReceivedObserver(CHbSymbianVariantMap& aData);
+
+public:
+ TInt iFlags;
+ RHbDeviceDialogClientSession iHbSession;
+ TInt iLastError;
+ TPckgBuf<THbDeviceDialogSrvUpdateInfo> iUpdateInfo;
+ TPckgBuf<int> iDeviceDialogId;
+ HBufC8* iBuffer;
+ TPtr8 iDataPtr;
+ TBool iRequesting;
+ QVariantMap iDataReceived;
+ CActiveSchedulerWait* iWait;
+ MHbDeviceDialogObserver* iObserver;
+ bool *iDeleted;
+};
+
+CHbDeviceDialogSymbianPrivate::CHbDeviceDialogSymbianPrivate():
+CActive( EPriorityStandard ),
+iFlags(0),
+iLastError(0),
+iDeviceDialogId(0),
+iBuffer(NULL),
+iDataPtr(NULL, 0, 0),
+iRequesting(EFalse),
+iObserver(NULL)
+{
+ if (!iBuffer) {
+ iBuffer = HBufC8::NewL(64);
+ if (iBuffer) {
+ iDataPtr.Set(iBuffer->Des());
+ }
+ }
+}
+
+CHbDeviceDialogSymbianPrivate::~CHbDeviceDialogSymbianPrivate()
+{
+ // Inform the server to finish the dialog session and not to cancel it
+ if(!iObserver) {
+ iHbSession.SendSyncRequest(EHbSrvClientClosing);
+ }
+
+ Cancel();
+ iHbSession.Close();
+
+ delete iBuffer;
+ iBuffer = NULL;
+
+ iObserver= NULL;
+ // Set object deleted flag
+ if (iDeleted) {
+ // Mark the object as deleted.
+ *iDeleted = true;
+ iDeleted = 0;
+ }
+}
+
+TInt CHbDeviceDialogSymbianPrivate::Show(const QByteArray& aArray )
+{
+ TInt error = iLastError = KErrNone;
+
+ TPtrC8 ptr( reinterpret_cast<const TUint8*>(aArray.data()), aArray.size() );
+ // Synchronous call to server to show dialog.
+ error = iHbSession.SendSyncRequest( EHbSrvShowDeviceDialog, ptr, &iDeviceDialogId );
+ //error = SymToDeviceDialogError(error);
+
+ if (error == KErrNone) {
+ // Start listening for server updates. Device dialog update and closing is
+ // received via this channel. Error status received in RunL method.
+ Start();
+ }
+ // Error, just return the error code
+ else {
+ SetError(error);
+ }
+ return error;
+}
+
+/*!
+ \internal
+
+ Send device dialog update.
+*/
+TInt CHbDeviceDialogSymbianPrivate::Update( const QByteArray& aArray )
+{
+ TInt error = iLastError = KErrNone;
+ if (iRequesting) {
+
+ TPtrC8 ptr( reinterpret_cast<const TUint8*>(aArray.data()), aArray.size() );
+
+ error = iHbSession.SendSyncRequest( EHbSrvUpdateDeviceDialog, ptr );
+ //error = SymToDeviceDialogError(error);
+ if (error != KErrNone) {
+ SetError(error);
+ }
+ }
+ else {
+ SetError(KErrBadHandle);
+ error = KErrBadHandle;
+ }
+ return error;
+}
+
+/*!
+ \internal
+
+ Cancel a scheduled popup on HbDeviceDialogManager. Event buffer is cleared
+ at server.
+*/
+void CHbDeviceDialogSymbianPrivate::CancelDialog()
+{
+ iLastError = KErrNone;
+ int error = KErrNotFound;
+
+ if (iRequesting) {
+ // Ignore other than server errors.
+ error = iHbSession.SendSyncRequest(EHbSrvCancelDeviceDialog, iDeviceDialogId());
+ // error = SymToDeviceDialogError(error);
+ }
+ if (error != KErrNone) {
+ SetError(error);
+ }
+}
+
+/*!
+ \internal
+
+ Return last error.
+*/
+TInt CHbDeviceDialogSymbianPrivate::Error() const
+{
+ return iLastError;
+}
+
+void CHbDeviceDialogSymbianPrivate::SetObserver( MHbDeviceDialogObserver* aObserver )
+{
+ iObserver = aObserver;
+}
+/*!
+ \internal
+ RunL from CActive.
+*/
+void CHbDeviceDialogSymbianPrivate::RunL()
+{
+ TInt completionCode = iStatus.Int();
+ //int errorCode = SymToDeviceDialogError(completionCode);
+
+ if (completionCode < KErrNone) {
+ // Any Symbian error, stop requesting, sycnhoronous requests are stopped
+ // in the end of the RunL
+ iRequesting = EFalse;
+ SetError(completionCode);
+ if (CallDialogClosedObserver(completionCode)) {
+ return; // observed deleted this object, do not touch it
+ }
+ }
+ else {
+ // Check that event is for latest device dialog. iDeviceDialogId was updated by server
+ // during show()
+ THbDeviceDialogSrvUpdateInfo &updateInfo = iUpdateInfo();
+ if (updateInfo.iDeviceDialogId == iDeviceDialogId()) {
+ switch(updateInfo.iUpdateType) {
+ case EHbDeviceDialogUpdateData: {
+ if (completionCode == KErrNone &&
+ updateInfo.iInfo.iDataInfo.iDataSize > 0) {
+ // Resize buffer and get new data synchronously
+ delete iBuffer;
+ iBuffer = NULL;
+ iBuffer = HBufC8::NewL(updateInfo.iInfo.iDataInfo.iDataSize);
+ iDataPtr.Set(iBuffer->Des());
+ completionCode = iHbSession.SendSyncRequest(EHbSrvUpdateData, iDataPtr);
+ //errorCode = SymToDeviceDialogError(completionCode);
+
+ // data request failed
+ if (completionCode < KErrNone) {
+ iRequesting = EFalse;
+ SetError(completionCode);
+ if (CallDialogClosedObserver(completionCode)) {
+ return; // observed deleted this object, do not touch it
+ }
+ }
+ }
+ if (completionCode == KErrNone) {
+ // Signal data if there are connections. Otherwise keep a copy.
+ QByteArray resArray((const char*)iDataPtr.Ptr(), iDataPtr.Size());
+ QDataStream stream(&resArray, QIODevice::ReadOnly);
+
+ iDataReceived.clear();
+
+ QVariant var;
+ stream >> var;
+ QVariantMap varMap = var.toMap();
+
+ if (iObserver) {
+ CHbSymbianVariantMap* symbianMap =
+ HbSymbianVariantConverter::fromQVariantMapL(varMap);
+ bool thisIsDeleted = CallDataReceivedObserver(*symbianMap);
+ delete symbianMap;
+ symbianMap = 0;
+ if (thisIsDeleted) { // observer deleted this, do not touch anymore
+ return;
+ }
+ }
+ else {
+ iDataReceived = varMap;
+ }
+ }
+ break;
+ }
+ case EHbDeviceDialogUpdateClosed:
+ // Signal possible cancelled error
+ if (completionCode != KErrNone) {
+ SetError(completionCode);
+ }
+ iRequesting = EFalse;
+ if (CallDialogClosedObserver(completionCode)) {
+ return; // observed deleted this object, do not touch it
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ // Make a new request if there was no errors and device dialog wasn't closed
+ if (iRequesting) {
+ Start();
+ }
+}
+
+/*!
+ \internal
+ DoCancel from CActive.
+*/
+void CHbDeviceDialogSymbianPrivate::DoCancel()
+{
+ SetError(KErrCancel);
+ iRequesting = EFalse;
+ iHbSession.SendSyncRequest(EHbSrvCancelUpdateChannel);
+}
+
+/*!
+ \internal
+ RunError from CActive.
+*/
+TInt CHbDeviceDialogSymbianPrivate::RunError( TInt /*aError*/ )
+{
+ SetError( KErrGeneral );
+ return KErrNone;
+}
+
+/*!
+ \internal
+ Starts asynchronous message to receive update and close events from session.
+*/
+void CHbDeviceDialogSymbianPrivate::Start()
+{
+ iDataPtr.Zero();
+
+ if ( !IsActive() ) {
+ iHbSession.SendASyncRequest( EHbSrvOpenUpdateChannel, iDataPtr, iUpdateInfo, iStatus );
+ SetActive();
+ iRequesting = ETrue;
+ }
+}
+
+// Convert symbian error code into HbDeviceDialog error code
+int CHbDeviceDialogSymbianPrivate::SymToDeviceDialogError( TInt errorCode )
+{
+ if (errorCode != HbDeviceDialogNoError) {
+ // Any Symbian error, close session handle. It will be reopened on next show()
+ if (errorCode < KErrNone) {
+ iHbSession.Close();
+ }
+ // All Symbian errors are connected to HbDeviceDialogConnectError
+ if (errorCode < KErrNone) {
+ errorCode = HbDeviceDialogConnectError;
+ }
+ }
+ return errorCode;
+}
+
+void CHbDeviceDialogSymbianPrivate::SetError( TInt aError )
+{
+ iLastError = aError;
+}
+
+// Call device dialog closed observer. Return true if observer deleted this object.
+bool CHbDeviceDialogSymbianPrivate::CallDialogClosedObserver(TInt aCompletionCode)
+{
+ if (iObserver) {
+ RHbDeleteGuardSymbian guard;
+ guard.OpenAndPushL(&iDeleted);
+ iObserver->DeviceDialogClosed(aCompletionCode);
+ return guard.PopAndClose();
+ } else {
+ return false;
+ }
+}
+
+// Call device dialog data received observer. Return true if observer deleted this object.
+bool CHbDeviceDialogSymbianPrivate::CallDataReceivedObserver(CHbSymbianVariantMap& aData)
+{
+ if (iObserver) {
+ RHbDeleteGuardSymbian guard;
+ guard.OpenAndPushL(&iDeleted);
+ iObserver->DataReceived(aData);
+ return guard.PopAndClose();
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Constructs CHbDeviceDialogSymbian object. \a f contains construct flags. Device
+ dialog service will clean all dialogs launched when the instance is deleted.
+*/
+
+EXPORT_C CHbDeviceDialogSymbian* CHbDeviceDialogSymbian::NewL( TInt aFlags )
+{
+ CHbDeviceDialogSymbian* deviceDialog = new (ELeave) CHbDeviceDialogSymbian(aFlags);
+ int error = KErrNone;
+ if(deviceDialog->d) {
+ error = deviceDialog->d->iHbSession.Connect();
+ }
+ if(error != KErrNone) {
+ CleanupStack::PushL(deviceDialog);
+ User::Leave(error);
+ delete deviceDialog;
+ deviceDialog = 0;
+ }
+ return deviceDialog;
+}
+
+EXPORT_C CHbDeviceDialogSymbian::~CHbDeviceDialogSymbian()
+{
+ delete d;
+}
+
+/*!
+ Show of device dialog. Each time a Show() is called a new dialog is launched.
+ aParameter data is sent to device dialog in Qt's QVariantMap object.
+ The function is asynchronous and returns immediately. Closing and data events from the
+ dialog can be received by observer interface. Deleting CHbDeviceDialogSymbian object
+ closes and deletes the device dialog at server if observer is set. If observer is null
+ the dialog is left executing at the server and it's assumed it closes itself by a timeout.
+ Cancel() to closes the device dialog.
+
+ \a aDeviceDialogType is name of the device dialog. Identifies the device
+ dialog plugin. \a aParameters is a buffer containing data for the device dialog.
+
+ \a aObserver is used to observe the session.
+
+ Return value informs if the call was successful.
+
+ \sa Update() Cancel()
+ */
+EXPORT_C TInt CHbDeviceDialogSymbian::Show(const TDesC& aDeviceDialogType, const CHbSymbianVariantMap& aParameters, MHbDeviceDialogObserver* aObserver)
+{
+ d->SetObserver(aObserver);
+
+ QString deviceDialogType = QString::fromUtf16(aDeviceDialogType.Ptr(), aDeviceDialogType.Length());
+
+ QVariantMap parameters;
+ HbSymbianVariantConverter::toQtVariantMap(aParameters, parameters);
+
+ QByteArray array;
+ QDataStream stream( &array, QIODevice::WriteOnly );
+
+ QVariant var( parameters );
+ stream << deviceDialogType;
+ stream << var;
+
+ return d->Show(array);
+}
+
+/*!
+ Updates device dialog parameters by a set of new values. Show() must be called before an
+ Update() can be called. Returns true on success and false
+ if error occurred.
+
+ \sa Show()
+*/
+EXPORT_C TInt CHbDeviceDialogSymbian::Update(const CHbSymbianVariantMap& aParameters)
+{
+ if(!d) {
+ return KErrNotReady;
+ }
+ QVariantMap parameters;
+
+ HbSymbianVariantConverter::toQtVariantMap(aParameters, parameters);
+
+ QByteArray array;
+ QDataStream stream( &array, QIODevice::WriteOnly );
+
+ QVariant var( parameters );
+ stream << var;
+
+ return d->Update(array);
+}
+
+/*!
+ Get the data received from device dialog if using synchronous Show
+ in s60 data types. Caller gets the ownership.
+*/
+EXPORT_C CHbSymbianVariantMap* CHbDeviceDialogSymbian::ReceivedDataL() const
+{
+ CHbSymbianVariantMap* map = HbSymbianVariantConverter::fromQVariantMapL(d->iDataReceived);
+ return map;
+}
+
+/*!
+ Cancel device dialog session. Visible dialog is removed from the screen.
+ Waiting dialogs are canceled and no effect if dialog already dismissed
+*/
+EXPORT_C void CHbDeviceDialogSymbian::Cancel()
+{
+ d->CancelDialog();
+}
+
+/*!
+ Set observer for device dialog events. \aObserver is pointer to the
+ observer. Null disables observing.
+*/
+EXPORT_C void CHbDeviceDialogSymbian::SetObserver(MHbDeviceDialogObserver* aObserver)
+{
+ d->SetObserver(aObserver);
+}
+
+CHbDeviceDialogSymbian::CHbDeviceDialogSymbian(TInt aFlags) : d(NULL)
+{
+ d = new CHbDeviceDialogSymbianPrivate;
+ d->iFlags = aFlags;
+ CActiveScheduler::Add(d);
+
+ // Is needed to implement?
+ //if (mDeviceDialogFlags & HbDeviceDialog::ImmediateResourceReservationFlag)
+}