bluetoothengine/btui/btuimodel/btdevicemodel_p.cpp
branchRCL_3
changeset 23 9386f31cc85b
parent 22 613943a21004
child 24 269724087bed
equal deleted inserted replaced
22:613943a21004 23:9386f31cc85b
     1 /*
       
     2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 #include "btdevicemodel_p.h"
       
    19 #include <QDateTime>
       
    20 #include <btservices/advancedevdiscoverer.h>
       
    21 #include <btengconnman.h>
       
    22 #include "btuiutil.h"
       
    23 #include "btuidevtypemap.h"
       
    24 #include "btqtconstants.h"
       
    25 
       
    26 /*!
       
    27     Constructor.
       
    28  */
       
    29 BtDeviceModelPrivate::BtDeviceModelPrivate( BtDeviceModel& model, QObject *parent )
       
    30     : QObject( parent ), mModel( model ), mDiscover( 0 ), mSeqNum( 0 )
       
    31 {
       
    32     mDeviceRepo = 0;
       
    33     isSearchingDevice = false;
       
    34     TRAP_IGNORE({
       
    35         mDeviceRepo = CBtDevRepository::NewL();
       
    36     });
       
    37     Q_CHECK_PTR( mDeviceRepo );
       
    38     TRAP_IGNORE( mDeviceRepo->AddObserverL( this ) );
       
    39     
       
    40     if ( mDeviceRepo->IsInitialized() ) {
       
    41         initializeDataStore();
       
    42     }
       
    43 }
       
    44 
       
    45 /*!
       
    46     Destructor.
       
    47  */
       
    48 BtDeviceModelPrivate::~BtDeviceModelPrivate()
       
    49 {
       
    50     delete mDeviceRepo;
       
    51     delete mDiscover;
       
    52 }
       
    53 
       
    54 
       
    55 /*!
       
    56     Tells whether the given column is in the range of the setting list.
       
    57     
       
    58     \param row the row number to be checked
       
    59     \param col the column number to be checked
       
    60     
       
    61     \return true if the given row and column are valid; false otherwise.
       
    62 */
       
    63 bool BtDeviceModelPrivate::isValid( int row, int column) const
       
    64 {
       
    65     return row >= 0 && row < mData.count() && column == 0;
       
    66 }
       
    67 
       
    68 /*!
       
    69     \return the total amount of rows.
       
    70     
       
    71 */
       
    72 int BtDeviceModelPrivate::rowCount() const
       
    73 {
       
    74     return mData.count();
       
    75 }
       
    76 
       
    77 /*!
       
    78     \return the total amount of columns.
       
    79     
       
    80 */
       
    81 int BtDeviceModelPrivate::columnCount() const
       
    82 {
       
    83     return 1;
       
    84 }
       
    85 
       
    86 /*!
       
    87     Gets the value within a data item.
       
    88     \param val contains the value at return.
       
    89     \param row the row number which the value is from
       
    90     \param col the column number which the value is from
       
    91     \param role the role identifier of the value.
       
    92  */
       
    93 void BtDeviceModelPrivate::data(QVariant& val, int row,  int col, int role ) const
       
    94 {
       
    95     if ( isValid( row, col ) ) {
       
    96         val = mData.at( row ).value( role );
       
    97     }
       
    98     else {
       
    99         val = QVariant( QVariant::Invalid );
       
   100     }
       
   101 }
       
   102 
       
   103 /*!
       
   104     Gets the whole item data at the specified column
       
   105     \param row the row number of the item data to be returned
       
   106     \param col the column number of the item data to be returned
       
   107     \return the item data
       
   108  */
       
   109 BtuiModelDataItem BtDeviceModelPrivate::itemData( int row, int col ) const
       
   110 {
       
   111     if ( isValid( row, col ) ) {
       
   112         return mData.at( row );
       
   113     }
       
   114     return BtuiModelDataItem();
       
   115 }
       
   116 
       
   117 
       
   118 /*!
       
   119     Requests the model to searching Bluetooth devices.
       
   120     \return true if the request is accepted; false otherwise
       
   121  */
       
   122 bool BtDeviceModelPrivate::searchDevice()
       
   123 {
       
   124     int err ( 0 );
       
   125     removeTransientDevices();
       
   126     if ( !mDiscover ) {
       
   127         TRAP(err, mDiscover = CAdvanceDevDiscoverer::NewL( *mDeviceRepo, *this) );
       
   128     }
       
   129     if ( !err ) {
       
   130         TRAP(err, mDiscover->DiscoverDeviceL() );
       
   131     }
       
   132     isSearchingDevice = true;
       
   133     return err == 0;
       
   134 }
       
   135 
       
   136 /*!
       
   137     Cancels a possible outstanding device search request.
       
   138  */
       
   139 void BtDeviceModelPrivate::cancelSearchDevice()
       
   140 {
       
   141     if ( mDiscover ) {
       
   142         isSearchingDevice = false;
       
   143         mDiscover->CancelDiscovery();
       
   144     }
       
   145 }
       
   146 
       
   147 /*!
       
   148     Removes transient (not-in-registry) devices 
       
   149     (added as the result of device search).
       
   150  */
       
   151 void BtDeviceModelPrivate::removeTransientDevices()
       
   152 {
       
   153     // clear in-range property for all device items in this model.
       
   154     int cnt = mData.count();
       
   155     for ( int i = mData.count() - 1; i > -1; --i)
       
   156         {
       
   157         const BtuiModelDataItem& qtdev = mData.at(i);
       
   158         if(isDeviceInRange(qtdev)) {
       
   159             if(isDeviceInRegistry(qtdev)) {
       
   160                 // we cannot remove this device as it is in registry.
       
   161                 // remove it in-range property.
       
   162                 setMajorProperty(mData[i], BtuiDevProperty::InRange, false);
       
   163                 updateRssi(mData[i], RssiInvalid);
       
   164                 updateSeqNum(mData[i], -1);
       
   165                 emit deviceDataChanged(i, this);
       
   166             }
       
   167             else {
       
   168                 // this device is not in-registry. Delete it from local
       
   169                 // store.
       
   170                 emit beginRemoveDevices(i, i, this);
       
   171                 mData.removeAt( i );
       
   172                 emit endRemoveDevices();
       
   173             }
       
   174         }
       
   175     }
       
   176 }
       
   177 
       
   178 /*!
       
   179     callback from repository.
       
   180     re-initialize our store.
       
   181  */
       
   182 void BtDeviceModelPrivate::RepositoryInitialized() 
       
   183 {
       
   184     initializeDataStore();
       
   185 }
       
   186 
       
   187 /*!
       
   188     callback from repository.
       
   189     update our store.
       
   190  */
       
   191 void BtDeviceModelPrivate::DeletedFromRegistry( const TBTDevAddr& addr ) 
       
   192 {
       
   193     int i = indexOf( addr );
       
   194     if ( i > -1 ) {
       
   195         if ( isSearchingDevice && isDeviceInRange( mData.at(i) ) ) {
       
   196             // device searching is ongoing, and it is in-range. we can not 
       
   197             // remove it from model now.
       
   198             // clear-registry related properties, so that
       
   199             // we get a chance to clean it after device searching later.
       
   200             setMajorProperty(mData[i], BtuiDevProperty::RegistryProperties, false);
       
   201             emit deviceDataChanged(i, this);
       
   202         }
       
   203         else {
       
   204             emit beginRemoveDevices(i, i, this);
       
   205             mData.removeAt( i );
       
   206             emit endRemoveDevices();
       
   207         }
       
   208     }
       
   209 }
       
   210 
       
   211 /*!
       
   212     callback from repository.
       
   213     update our store.
       
   214  */
       
   215 void BtDeviceModelPrivate::AddedToRegistry( const CBtDevExtension& dev ) 
       
   216 {
       
   217     ChangedInRegistry( dev, 0 );
       
   218 }
       
   219 
       
   220 /*!
       
   221     callback from repository.
       
   222     update our store.
       
   223  */
       
   224 void BtDeviceModelPrivate::ChangedInRegistry( 
       
   225         const CBtDevExtension& dev, TUint similarity )
       
   226 {
       
   227     int i = indexOf( dev.Addr() );
       
   228     if ( i == -1 ) {
       
   229         BtuiModelDataItem devData;
       
   230         if ( !isSearchingDevice ) {
       
   231             // Rssi is only available at device inquiry stage. 
       
   232             // We initialize this property to an invalid value
       
   233             updateRssi(devData, RssiInvalid);
       
   234         }
       
   235         // add device-in-registry property:
       
   236         setMajorProperty(devData, BtuiDevProperty::InRegistry, true);
       
   237         updateDeviceProperty(devData, dev, 0 );
       
   238         emit beginInsertDevices( mData.count(), mData.count(), this );
       
   239         mData.append( devData );
       
   240         emit endInsertDevices();
       
   241     }
       
   242     else {
       
   243         updateDeviceProperty(mData[i], dev, similarity );
       
   244         setMajorProperty(mData[i], BtuiDevProperty::InRegistry, true);
       
   245         emit deviceDataChanged( i, this );
       
   246     }
       
   247 }
       
   248 
       
   249 /*!
       
   250     callback from repository.
       
   251     update our store.
       
   252  */
       
   253 void BtDeviceModelPrivate::ServiceConnectionChanged(
       
   254         const CBtDevExtension& dev, TBool connected )
       
   255 {
       
   256     int i = indexOf( dev.Addr() );
       
   257     if ( i > -1 ) {
       
   258         int preconn =  BtuiDevProperty::Connected 
       
   259                 & mData[i][BtDeviceModel::MajorPropertyRole].toInt();
       
   260         // we only update and signal if connection status is really
       
   261         // changed:
       
   262         if ( ( preconn != 0 && !connected )
       
   263             || ( preconn == 0 && connected ) ) {
       
   264             setMajorProperty(mData[i], BtuiDevProperty::Connected, connected );
       
   265             emit deviceDataChanged( i, this );
       
   266         }
       
   267     }
       
   268     // it is impossible that a device has connected but it is not in
       
   269     // our local store according to current bteng services.
       
   270     // need to take more care in future when this becomes possible.
       
   271 }
       
   272 
       
   273 /*!
       
   274     callback from device search.
       
   275     update our store.
       
   276  */
       
   277 void BtDeviceModelPrivate::HandleNextDiscoveryResultL( 
       
   278         const TInquirySockAddr& inqAddr, const TDesC& name )
       
   279 {
       
   280     int pos = indexOf( inqAddr.BTAddr() );
       
   281     const CBtDevExtension* dev = mDeviceRepo->Device( inqAddr.BTAddr() );
       
   282     
       
   283     //RssiRole
       
   284     int rssi( RssiInvalid ); // initialize to an invalid value.
       
   285     if( inqAddr.ResultFlags() & TInquirySockAddr::ERssiValid ) {
       
   286         rssi = inqAddr.Rssi();
       
   287     }
       
   288     
       
   289     if ( pos == -1 ) {
       
   290         BtuiModelDataItem devData;
       
   291         setMajorProperty(devData, BtuiDevProperty::InRange, true);
       
   292         updateRssi(devData, rssi);
       
   293         updateSeqNum( devData, mSeqNum++ );
       
   294         CBtDevExtension* devExt(NULL);
       
   295         TRAP_IGNORE( {
       
   296             devExt = CBtDevExtension::NewLC( inqAddr, name );
       
   297             CleanupStack::Pop(); });
       
   298         updateDeviceProperty(devData, *devExt, 0);
       
   299         delete devExt;
       
   300         emit beginInsertDevices( mData.count(), mData.count(), this );
       
   301         mData.append( devData );
       
   302         emit endInsertDevices();
       
   303     }
       
   304     else {
       
   305         setMajorProperty(mData[pos], BtuiDevProperty::InRange, true);
       
   306         updateRssi(mData[pos], rssi);
       
   307         updateSeqNum( mData[pos], mSeqNum++ );
       
   308         emit deviceDataChanged( pos, this );
       
   309     }
       
   310 }
       
   311 
       
   312 /*!
       
   313     callback from device search.
       
   314     inform client.
       
   315  */
       
   316 void BtDeviceModelPrivate::HandleDiscoveryCompleted( TInt error )
       
   317 {
       
   318     isSearchingDevice = false;
       
   319     // Reset the sequence number for the next search
       
   320     mSeqNum = 0;
       
   321     emit deviceSearchCompleted( (int) error );
       
   322 }
       
   323 
       
   324 void BtDeviceModelPrivate::initializeDataStore()
       
   325     {
       
   326     
       
   327     mSeqNum = 0;  // reset when starting search again
       
   328     
       
   329     // it is possible that we are searching devices.
       
   330     // We use a simple but not-so-efficient method to update the model.
       
   331     
       
   332     // If the device store is not empty, we clear
       
   333     // registry property from these devices first.
       
   334     for (int i = 0; i < mData.count(); ++i) {
       
   335         setMajorProperty(mData[i], BtuiDevProperty::RegistryProperties, false);
       
   336     }
       
   337     if ( mData.count() ) {
       
   338         // need to update view because we have changed device properties.
       
   339         emit deviceDataChanged( 0, mData.count() - 1, this );
       
   340     }
       
   341 
       
   342     const RDevExtensionArray& devs = mDeviceRepo->AllDevices();
       
   343     for (int i = 0; i < devs.Count(); ++i) {
       
   344         int pos = indexOf( devs[i]->Addr() );
       
   345         if ( pos > -1 ) {
       
   346             // add device-in-registry property:
       
   347             setMajorProperty(mData[pos], BtuiDevProperty::InRegistry, true);            
       
   348             updateDeviceProperty(mData[pos], *(devs[i]), 0);
       
   349             updateSeqNum(mData[pos], -1);
       
   350             emit deviceDataChanged( pos, this );
       
   351         }
       
   352         else {
       
   353             BtuiModelDataItem devData;
       
   354             // add device-in-registry property:
       
   355             setMajorProperty(devData, BtuiDevProperty::InRegistry, true);
       
   356             updateDeviceProperty(devData, *( devs[i] ), 0 );
       
   357             updateSeqNum(devData, -1);
       
   358             emit beginInsertDevices(mData.count(), mData.count(), this );
       
   359             mData.append( devData );
       
   360             emit endInsertDevices();
       
   361         }
       
   362     }
       
   363 }
       
   364 
       
   365 void BtDeviceModelPrivate::updateDeviceProperty(BtuiModelDataItem& qtdev,
       
   366         const CBtDevExtension& dev, TUint similarity )
       
   367 {
       
   368     // similarity is not used currently. 
       
   369     // It is possible to gain better performance
       
   370     // with this info to avoid re-manipulate
       
   371     // unchanged properties.
       
   372     Q_UNUSED(similarity);
       
   373     
       
   374     //DevDisplayNameRole
       
   375     QString str = QString::fromUtf16( 
       
   376             dev.Alias().Ptr(), dev.Alias().Length() );
       
   377     qtdev[BtDeviceModel::NameAliasRole] = QVariant( str );
       
   378 
       
   379     //DevAddrReadableRole
       
   380     addrSymbianToReadbleString( str, dev.Addr() );
       
   381     qtdev[BtDeviceModel::ReadableBdaddrRole] = QVariant( str );
       
   382 
       
   383     //LastUsedTimeRole
       
   384     TDateTime symDt = dev.Device().Used().DateTime();
       
   385     QDate date( symDt.Year(), symDt.Month(), symDt.Day() );
       
   386     QTime time( symDt.Hour(), symDt.Minute(), symDt.MicroSecond() / 1000 );
       
   387     QDateTime qdt(date, time);
       
   388     qtdev[BtDeviceModel::LastUsedTimeRole] = QVariant(qdt);
       
   389  
       
   390     // set paired status:
       
   391     setMajorProperty(qtdev, BtuiDevProperty::Bonded, isBonded( dev.Device() ));
       
   392     
       
   393     // set blocked status:
       
   394     setMajorProperty(qtdev, BtuiDevProperty::Blocked, 
       
   395             dev.Device().GlobalSecurity().Banned() );
       
   396     // set trusted status:
       
   397     setMajorProperty(qtdev, BtuiDevProperty::Trusted, 
       
   398             dev.Device().GlobalSecurity().NoAuthorise() );
       
   399     // set connected status:
       
   400     // EBTEngConnecting is an intermediate state between connected and not-connected, 
       
   401     // we do not treat it as connected:         
       
   402     setMajorProperty(qtdev, BtuiDevProperty::Connected, dev.ServiceConnectionStatus() == EBTEngConnected);
       
   403 
       
   404     // Check whether the device has services that are connectable in bteng scope.
       
   405     CBTEngConnMan* connMan( 0 );
       
   406     TRAP_IGNORE( connMan = CBTEngConnMan::NewL(0));
       
   407     TBool connectable(EFalse);
       
   408     if ( connMan ) {
       
   409         (void) connMan->IsConnectable(dev.Addr(), dev.Device().DeviceClass(), connectable);
       
   410         delete connMan;
       
   411     }
       
   412     setMajorProperty(qtdev, BtuiDevProperty::Connectable, connectable);
       
   413     
       
   414     int cod = static_cast<int>( dev.Device().DeviceClass().DeviceClass() );
       
   415     qtdev[BtDeviceModel::CoDRole] = QVariant(cod);
       
   416 
       
   417     int majorDeviceType;
       
   418     int minorDeviceType;
       
   419     // device type is mapped according to CoD:
       
   420     BtuiDevProperty::mapDeiveType(majorDeviceType, minorDeviceType, cod);
       
   421 
       
   422 
       
   423 
       
   424     
       
   425     qtdev[BtDeviceModel::MajorPropertyRole] = 
       
   426             QVariant( qtdev[BtDeviceModel::MajorPropertyRole].toInt() | majorDeviceType );
       
   427     qtdev[BtDeviceModel::MinorPropertyRole] = QVariant( minorDeviceType );
       
   428 }
       
   429 
       
   430 int BtDeviceModelPrivate::indexOf( const TBTDevAddr& addr ) const
       
   431 {
       
   432     QString addrStr;
       
   433     addrSymbianToReadbleString( addrStr, addr );
       
   434     for (int i = 0; i < mData.count(); ++i ) {
       
   435         if ( mData.at( i ).value( BtDeviceModel::ReadableBdaddrRole ) 
       
   436                 == addrStr ) {
       
   437             return i;
       
   438         }
       
   439     }
       
   440     return -1;
       
   441 }
       
   442 
       
   443 void BtDeviceModelPrivate::updateRssi(BtuiModelDataItem& qtdev, int rssi )
       
   444 {
       
   445     qtdev[BtDeviceModel::RssiRole] = QVariant( rssi );
       
   446 }
       
   447 
       
   448 void BtDeviceModelPrivate::updateSeqNum(BtuiModelDataItem& qtdev, int seqNum )
       
   449 {
       
   450     qtdev[BtDeviceModel::SeqNumRole] = QVariant( seqNum );
       
   451 }
       
   452 
       
   453 /*!
       
   454     Add the specified major property to the device if addto is true.
       
   455     Otherwise the property is removed from the device. 
       
   456  */
       
   457 void BtDeviceModelPrivate::setMajorProperty(
       
   458         BtuiModelDataItem& qtdev, int prop, bool addto)
       
   459 {
       
   460     if ( addto ) {
       
   461         qtdev[BtDeviceModel::MajorPropertyRole] = 
       
   462             QVariant( qtdev[BtDeviceModel::MajorPropertyRole].toInt() | prop);
       
   463     }
       
   464     else {
       
   465         qtdev[BtDeviceModel::MajorPropertyRole] = 
       
   466             QVariant( qtdev[BtDeviceModel::MajorPropertyRole].toInt() & ~prop);
       
   467     }
       
   468 }
       
   469 
       
   470 bool BtDeviceModelPrivate::isDeviceInRange( const BtuiModelDataItem& qtdev )
       
   471 {   
       
   472     return BtuiDevProperty::InRange & qtdev[BtDeviceModel::MajorPropertyRole].toInt();
       
   473 }
       
   474 
       
   475 bool BtDeviceModelPrivate::isDeviceInRegistry( const BtuiModelDataItem& qtdev )
       
   476 {
       
   477     return BtuiDevProperty::InRegistry & qtdev[BtDeviceModel::MajorPropertyRole].toInt();
       
   478 }