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