--- 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 ¶ms )
{
+ 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);
}