src/hbcore/devicedialogbase/hbdevicedialogsymbian.cpp
changeset 0 16d8024aca5e
child 2 06ff229162e9
--- /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)
+}