bluetoothengine/btui/btuidelegate/btdelegateconnect.cpp
changeset 42 b72428996822
parent 31 a0ea99b6fa53
child 51 625f43ae9362
--- a/bluetoothengine/btui/btuidelegate/btdelegateconnect.cpp	Fri May 28 17:03:06 2010 +0300
+++ b/bluetoothengine/btui/btuidelegate/btdelegateconnect.cpp	Mon Jul 12 18:51:05 2010 +0300
@@ -16,15 +16,25 @@
 */
 
 #include "btdelegateconnect.h"
+#include "btuiutil.h"
+#include "btqtconstants.h"
 #include <QModelIndex>
+#include <hblabel.h>
 #include <btsettingmodel.h>
 #include <btdevicemodel.h>
 #include <hbnotificationdialog.h>
+#include <hbmessagebox.h>
+#include "btuiiconutil.h"
+#include "btdelegatefactory.h"
+#include <bluetoothuitrace.h>
+#include <e32property.h>
+#include <ctsydomainpskeys.h>  
 
 BtDelegateConnect::BtDelegateConnect(
         BtSettingModel* settingModel, 
         BtDeviceModel* deviceModel, QObject *parent) :
-    BtAbstractDelegate(settingModel, deviceModel, parent), mBtengConnMan(0)
+    BtAbstractDelegate(settingModel, deviceModel, parent), mBtengConnMan(0),
+    mAbstractDelegate(0), mActiveHandling(false)
 {
     
 }
@@ -34,79 +44,245 @@
     delete mBtengConnMan;
 }
 
+/*!
+ * execute connect operation
+ *    first check if power is on
+ */
 void BtDelegateConnect::exec( const QVariant &params )
 {
+    if ( mActiveHandling ) {
+        emit commandCompleted( KErrAlreadyExists );
+        return;
+    }
+    mIndex = params.value<QModelIndex>();
+    mActiveHandling = true;
+    // save needed values from model
+    mDeviceName = (mIndex.data(BtDeviceModel::NameAliasRole)).toString();
+    QString addrStr = (mIndex.data(BtDeviceModel::ReadableBdaddrRole)).toString(); 
+    addrReadbleStringToSymbian( addrStr, mAddr );  
+    
+    mCod = (mIndex.data(BtDeviceModel::CoDRole)).toInt();
+    mMajorProperty = (mIndex.data(BtDeviceModel::MajorPropertyRole)).toInt();
+    
+    // first turn on power if needed
+    if (!isBtPowerOn()) {
+        if (!mAbstractDelegate) //if there is no other delegate running
+        { 
+            mAbstractDelegate = BtDelegateFactory::newDelegate(BtDelegate::ManagePower, 
+                    getSettingModel(), getDeviceModel() ); 
+            connect( mAbstractDelegate, SIGNAL(commandCompleted(int)), this, SLOT(powerDelegateCompleted(int)) );
+            mAbstractDelegate->exec(QVariant(BtPowerOn));
+        }
+    } 
+    else {
+        // power is already on
+        exec_connect();
+    }
+}
+
+/*!
+ * power delegate has completed, continue processing
+ */
+void BtDelegateConnect::powerDelegateCompleted(int status)
+{
+    if (mAbstractDelegate)
+    {
+        disconnect(mAbstractDelegate);
+        delete mAbstractDelegate;
+        mAbstractDelegate = 0;
+    }
+    if ( status == KErrNone ) {
+        // continue connecting
+        exec_connect();
+    } 
+    else {
+        // error
+        emitCommandComplete(status);
+    }
+}
+
+/*!
+ * execute connect operation
+ */
+void BtDelegateConnect::exec_connect()
+{
     int error = KErrNone;
-    QModelIndex index = params.value<QModelIndex>();
-    
-    mdeviceName = getDeviceModel()->data(index,BtDeviceModel::NameAliasRole).toString();
-    
-    QString strBtAddr = getDeviceModel()->data(index,
-            BtDeviceModel::ReadableBdaddrRole).toString();
-    int cod = getDeviceModel()->data(index,BtDeviceModel::CoDRole).toInt();
     
     if ( ! mBtengConnMan ){
-        TRAP_IGNORE( mBtengConnMan = CBTEngConnMan::NewL(this) );
+        TRAP( error, mBtengConnMan = CBTEngConnMan::NewL(this) );
     }
-    Q_CHECK_PTR( mBtengConnMan );
-    
-    TBTDeviceClass btEngDeviceClass(cod);
-    TPtrC ptrName(reinterpret_cast<const TText*>(strBtAddr.constData()));
-        
-    RBuf16 btName;
-    error = btName.Create(ptrName.Length());
-    
-    if(error == KErrNone) {
-        btName.Copy(ptrName);
-        mBtEngddr.SetReadable(btName);
-        error = mBtengConnMan->Connect(mBtEngddr, btEngDeviceClass);
-        btName.Close();
+
+    if ( !error ) {
+        TBTDeviceClass btEngDeviceClass(mCod);
+        error = mBtengConnMan->Connect(mAddr, btEngDeviceClass);
     }
     
-    
-    if(error) {
+    if( error ) {
         emitCommandComplete(error);
     }
-    
 }
 
+/*!
+ * connect callback from CBTengConnMan
+ */
 void BtDelegateConnect::ConnectComplete( TBTDevAddr& aAddr, TInt aErr, 
                                    RBTDevAddrArray* aConflicts )
 {
-    Q_UNUSED(aAddr);
-    Q_UNUSED(aConflicts);  
-    emitCommandComplete(aErr);
+    // It is possible that another audio device has just connected to phone when we are
+    // connecting to this audio device. Or a device is connected while this command
+    // is idle. No handling for these cases.
+    if ( mAddr != aAddr || !mActiveHandling ) {  
+        return;
+    }
+    
+    // conflict could occur as well if another audio device is already connected
+    // since currently we don't support multiple audio device connections.
+    if ( aErr && aConflicts && aConflicts->Count() ) {
+        // get the display name of the device that is 
+        // causing the conflict 
+        QString conflictDevAddr;
+        addrSymbianToReadbleString(conflictDevAddr, (*aConflicts)[0] );
+        QModelIndex start = getDeviceModel()->index(0,0);
+        QModelIndexList indexList = getDeviceModel()->match(start, BtDeviceModel::ReadableBdaddrRole, conflictDevAddr);
+        BTUI_ASSERT_X(indexList.count(), "BtDelegateConnect::ConnectComplete()", "device missing from model!");
+        mConflictDevIndex = indexList.at(0);
+      
+        // check if conflict device is being used in a call
+        // Note:  actually only checking if *any* audio device is involved in a call, not necessarily the
+        // one we are concerned with here.  Btaudioman does not currently support finding out the actual 
+        // device involved in a call. 
+        if (callOngoing()) {
+            HbMessageBox::warning(hbTrId("txt_bt_info_not_possible_during_a_call"));
+            emitCommandComplete(KErrCancel);
+        }
+        else {
+            // no call, check if user wants to disconnect conflict device 
+            QString conflictDevName = (mConflictDevIndex.data(BtDeviceModel::NameAliasRole)).toString();    
+    
+            QString questionText(hbTrId("txt_bt_info_to_connect_1_2_needs_to_be_disconnec")
+                    .arg(mDeviceName).arg(conflictDevName));
+            
+            HbMessageBox::question( questionText, this, SLOT(handleUserAnswer(HbAction*)), 
+                    hbTrId("txt_common_button_continue"), hbTrId("txt_common_button_cancel") );        
+        }
+    }
+    else {
+        // command is finished
+        emitCommandComplete(aErr);
+    }
 }
 
+/*!
+ * handle user response to query about disconnecting conflict device
+ */
+void BtDelegateConnect::handleUserAnswer( HbAction* answer )
+{
+    HbMessageBox* dlg = static_cast<HbMessageBox*>( sender() );
+    if( dlg->actions().first() == answer ) { 
+        // Continue, ie. disconnect conflict device and then try reconnecting again
+        if (!mAbstractDelegate) //if there is no other delegate running
+        { 
+            QList<QVariant>list;
+            QVariant paramFirst;
+            paramFirst.setValue(mConflictDevIndex);    
+            QVariant paramSecond(ServiceLevel);
+            list.append(paramFirst);
+            list.append(paramSecond);
+            QVariant paramsList(list);
+            mAbstractDelegate = BtDelegateFactory::newDelegate(BtDelegate::Disconnect, 
+                    getSettingModel(), getDeviceModel() ); 
+            connect( mAbstractDelegate, SIGNAL(commandCompleted(int)), this, SLOT(disconnectDelegateCompleted(int)) );
+            mAbstractDelegate->exec(paramsList);
+        }
+    }
+    else {
+        // Cancel connect operation
+        emitCommandComplete(KErrCancel);
+    }
+}
+
+/*!
+ * returns true if phone call is ongoing
+ */
+bool BtDelegateConnect::callOngoing()
+{
+    // ToDo:  check if there exists Qt PS key for ongoing call
+    int callState;
+    int err = RProperty::Get(KPSUidCtsyCallInformation, KCTsyCallState, callState);
+    if (!err && (callState == EPSCTsyCallStateNone || callState == EPSCTsyCallStateUninitialized)) {
+        return false;
+    }
+    else {
+        return true;
+    }
+}
+
+/*!
+ * disconnecting conflict device has completed, continue connecting
+ */
+void BtDelegateConnect::disconnectDelegateCompleted(int status)
+{
+    if (mAbstractDelegate)
+    {
+        disconnect(mAbstractDelegate);
+        delete mAbstractDelegate;
+        mAbstractDelegate = 0;
+    }
+    // finished disconnecting conflict device, now reconnect to original device
+    if ( status == KErrNone ) {
+        exec_connect();
+    }
+    else {
+        // disconnect failed, abort
+        emitCommandComplete( status );
+    }
+}
+
+/*!
+ * not used here
+ */
 void BtDelegateConnect::DisconnectComplete( TBTDevAddr& aAddr, TInt aErr )
 {
     Q_UNUSED(aAddr);
     Q_UNUSED(aErr);    
 }
 
-void BtDelegateConnect::PairingComplete( TBTDevAddr& aAddr, TInt aErr )
-{
-    Q_UNUSED(aAddr);
-    Q_UNUSED(aErr);
-}
-
+/*!
+ * cancel connect operation
+ *   ConnectComplete() callback will be called upon completion of cancel with KErrCancel
+ */
 void BtDelegateConnect::cancel()
 {
-    mBtengConnMan->CancelConnect(mBtEngddr);
+    if ( mBtengConnMan ) {
+        mBtengConnMan->CancelConnect(mAddr);
+    }
 }
 
+/*!
+ * shows user notes with connection success/failure information
+ *    cancel operation is handled without a user note
+ */
 void BtDelegateConnect::emitCommandComplete(int error)
 {
-    QString str(hbTrId("Connected to %1"));
-    QString err(hbTrId("Connecting with %1 Failed"));
-    
-    if(error != KErrNone) {
-        HbNotificationDialog::launchDialog(err.arg(mdeviceName));
+    if ( error == KErrNone ) {
+        // success, show indicator with connection status
+        
+        HbIcon icon = getBadgedDeviceTypeIcon( mCod, mMajorProperty, BtuiNoCorners); 
+        QString str(hbTrId("txt_bt_dpopinfo_connected_to_1"));
+        HbNotificationDialog::launchDialog( icon, hbTrId("txt_bt_dpophead_connected"), 
+            str.arg(mDeviceName) );  
+    }
+    else if ( error == KErrCancel ) {
+        // no user note, return success since cancel operation completed successfully
+        error = KErrNone;
     }
     else {
-        HbNotificationDialog::launchDialog(str.arg(mdeviceName));
+        // failure to connect, show user note
+        QString err(hbTrId("txt_bt_info_unable_to_connect_with_bluetooth"));
+        HbMessageBox::warning(err.arg(mDeviceName));
     }
-
+    mActiveHandling = false;
+    
     emit commandCompleted(error);
 }