phonebookengines/VirtualPhonebook/VPbkCntModel/src/CContactStore.cpp
branchRCL_3
changeset 23 5586b4d2ec3e
parent 3 04ab22b956c2
child 32 2828b4d142c0
equal deleted inserted replaced
21:b3431bff8c19 23:5586b4d2ec3e
   296     return result;
   296     return result;
   297     }
   297     }
   298 
   298 
   299 }  // unnamed namespace
   299 }  // unnamed namespace
   300 
   300 
   301 
   301 // --------------------------------------------------------------------------
       
   302 // CContactStoreOpenOperation
       
   303 // --------------------------------------------------------------------------
       
   304 //
       
   305 class CContactStoreOpenOperation : public CActive
       
   306 {
       
   307 public: // construction & destruction
       
   308 
       
   309     /**
       
   310      * Open native contact database operation. Started automatically.
       
   311      *
       
   312      * @param aStore Store that will receive events when operation is complete 
       
   313      * @param aReplace replace contact database (instead of open)
       
   314      */
       
   315     CContactStoreOpenOperation( CContactStore& aStore, TBool aReplace );
       
   316     
       
   317     ~CContactStoreOpenOperation();
       
   318 
       
   319 private: // From CActive
       
   320     void DoCancel();
       
   321     void RunL();
       
   322     TInt RunError( TInt aError );
       
   323 
       
   324 private: // data types
       
   325 
       
   326     /// Operation states
       
   327     enum TStates
       
   328         {
       
   329         // Operation: Replace default store
       
   330         // Next states: [EStateDone]
       
   331         EStateReplaceStore,
       
   332         
       
   333         // Operation: Open default store
       
   334         // Next states: [EStateStoreOpened]
       
   335         EStateOpenStore,
       
   336         
       
   337         // Result: State when store has been opened (success or failure) 
       
   338         // Next states: [EStateStoreOpenedAfterError, EStateDone]
       
   339         EStateStoreOpened,
       
   340         
       
   341         // Result: State after second attempt to open store (first have failed).
       
   342         // Next states: [EStateDone]
       
   343         EStateStoreOpenedAfterError,
       
   344         
       
   345         // Result: DB has been opened successfully. Report it to store. 
       
   346         // Next states: -
       
   347         EStateDone,
       
   348         };
       
   349 
       
   350 private: // implementation
       
   351     
       
   352     /**
       
   353      * Move to next state asynchronously
       
   354      */
       
   355     void IssueRequest( TStates aNextState, TInt aError = KErrNone );
       
   356     
       
   357     /**
       
   358      * Handle state EStateStoreOpened
       
   359      */
       
   360     void HandleStoreOpenedL( TInt aError );
       
   361     
       
   362 private: // data
       
   363     
       
   364     /// Active state
       
   365     TStates iState;
       
   366     /// Ref: Contact store
       
   367     CContactStore& iStore;
       
   368     /// Own: Native contact database
       
   369     CContactDatabase* iDb;
       
   370     /// Own: Native contact database open operation
       
   371     CContactOpenOperation* iOperation;
       
   372 };
       
   373 
       
   374 // --------------------------------------------------------------------------
       
   375 // CContactStoreOpenOperation::~CContactStoreOpenOperation
       
   376 // --------------------------------------------------------------------------
       
   377 //
       
   378 CContactStoreOpenOperation::~CContactStoreOpenOperation()
       
   379     {
       
   380     Cancel();
       
   381     delete iDb;
       
   382     delete iOperation;
       
   383     }
       
   384 
       
   385 // --------------------------------------------------------------------------
       
   386 // CContactStoreOpenOperation::DoCancel
       
   387 // --------------------------------------------------------------------------
       
   388 //
       
   389 void CContactStoreOpenOperation::DoCancel()
       
   390     {
       
   391     delete iOperation;
       
   392     iOperation = NULL;
       
   393     }
       
   394 
       
   395 // --------------------------------------------------------------------------
       
   396 // CContactStoreOpenOperation::RunL
       
   397 // --------------------------------------------------------------------------
       
   398 //
       
   399 void CContactStoreOpenOperation::RunL()
       
   400     {
       
   401     switch( iState )
       
   402         {
       
   403         case EStateReplaceStore:
       
   404             {
       
   405             iDb = CContactDatabase::ReplaceL( 
       
   406                 iStore.StoreProperties().Name().UriDes() );
       
   407             IssueRequest( EStateDone );
       
   408             break;
       
   409             }
       
   410         case EStateOpenStore:
       
   411             {
       
   412             iOperation = CContactDatabase::Open( 
       
   413                 iStore.StoreProperties().Name().UriDes(), iStatus );
       
   414             SetActive();
       
   415             iState = EStateStoreOpened;
       
   416             break;
       
   417             }
       
   418         case EStateStoreOpened:
       
   419             {
       
   420             HandleStoreOpenedL( iStatus.Int() );
       
   421             break;
       
   422             }
       
   423         case EStateStoreOpenedAfterError:
       
   424             {
       
   425             User::LeaveIfError( iStatus.Int() ); // report errors immediately
       
   426             iDb = iOperation->TakeDatabase();
       
   427             IssueRequest( EStateDone );
       
   428             break;
       
   429             }
       
   430         case EStateDone:
       
   431             {
       
   432             CContactDatabase* db = iDb;
       
   433             iDb = NULL; // give ownership
       
   434             CContactStore& store = iStore;
       
   435             
       
   436             TRAPD( err, store.StoreOpenedL( db ) );
       
   437             // NOTE! Don't touch members after this call.
       
   438             // This instance could be deleted
       
   439             if( err )
       
   440                 {
       
   441                 store.StoreOpenFailed( err );
       
   442                 }
       
   443             break;
       
   444             }
       
   445         default:
       
   446             {
       
   447             // unknown state
       
   448             __ASSERT_DEBUG( EFalse,
       
   449                 ContactStorePanic( EPreCond_OpenOperationState ) );
       
   450             iStore.StoreOpenFailed( KErrUnknown );
       
   451             }
       
   452         }
       
   453     }
       
   454 
       
   455 // --------------------------------------------------------------------------
       
   456 // CContactStoreOpenOperation::RunError
       
   457 // --------------------------------------------------------------------------
       
   458 //
       
   459 TInt CContactStoreOpenOperation::RunError( TInt aError )
       
   460     {
       
   461     iStore.StoreOpenFailed( aError );
       
   462     return KErrNone;
       
   463     }
       
   464 
       
   465 // --------------------------------------------------------------------------
       
   466 // CContactStoreOpenOperation::CContactStoreOpenOperation
       
   467 // --------------------------------------------------------------------------
       
   468 //
       
   469 CContactStoreOpenOperation::CContactStoreOpenOperation( 
       
   470     CContactStore& aStore, TBool aReplace ) : 
       
   471     CActive( EPriorityLow ),
       
   472     iStore( aStore )
       
   473     {
       
   474     CActiveScheduler::Add( this );
       
   475     IssueRequest( aReplace ? EStateReplaceStore : EStateOpenStore ); // start working
       
   476     }
       
   477 
       
   478 // --------------------------------------------------------------------------
       
   479 // CContactStoreOpenOperation::IssueRequest
       
   480 // --------------------------------------------------------------------------
       
   481 //
       
   482 void CContactStoreOpenOperation::IssueRequest( TStates aNextState, TInt aError )
       
   483     {
       
   484     if( !IsActive() )
       
   485         {
       
   486         TRequestStatus* status = &iStatus;
       
   487         User::RequestComplete( status, aError );
       
   488         SetActive();
       
   489         iState = aNextState; 
       
   490         }
       
   491     }
       
   492 
       
   493 // --------------------------------------------------------------------------
       
   494 // CContactStoreOpenOperation::HandleStoreOpenedL
       
   495 // --------------------------------------------------------------------------
       
   496 //
       
   497 void CContactStoreOpenOperation::HandleStoreOpenedL( TInt aError )
       
   498     {
       
   499     if( aError == KErrNone )
       
   500         {
       
   501         // Store opened succesfully
       
   502         iDb = iOperation->TakeDatabase();
       
   503         IssueRequest( EStateDone );
       
   504         }
       
   505     else // some error happened
       
   506         {
       
   507         delete iOperation;
       
   508         iOperation = NULL;
       
   509         
       
   510         const TDesC& dbName = iStore.StoreProperties().Name().UriDes();
       
   511         TInt creating = EFalse;
       
   512         
       
   513         if( aError == KErrNotFound )
       
   514             {
       
   515             // Database not found --> Creating it
       
   516             creating = ETrue;
       
   517             TRAP( aError, iDb = CContactDatabase::CreateL( dbName ) );
       
   518             }
       
   519     
       
   520         if ( KErrDiskFull == aError )
       
   521             {
       
   522             // Try to release space for contact db opening
       
   523             if( iStore.RequestFreeDiskSpaceLC( KDiskSpaceForDbOpening ) )
       
   524                 {
       
   525                 aError = KErrNone;
       
   526                 if( creating )
       
   527                     {
       
   528                     // Databse was not found --> Creating it
       
   529                     iDb = CContactDatabase::CreateL( dbName );
       
   530                     }
       
   531                 else
       
   532                     {
       
   533                     // Opening database
       
   534                     iOperation = CContactDatabase::Open( dbName, iStatus );
       
   535                     SetActive();
       
   536                     iState = EStateStoreOpenedAfterError;
       
   537                     }
       
   538                 CleanupStack::PopAndDestroy();  // RequestFreeDiskSpaceLC
       
   539                 }
       
   540             }
       
   541         
       
   542         // leave on unhandled error
       
   543         User::LeaveIfError( aError );
       
   544         
       
   545         if( iDb )
       
   546             {
       
   547             IssueRequest( EStateDone );
       
   548             }
       
   549         }
       
   550     }
   302 
   551 
   303 // --------------------------------------------------------------------------
   552 // --------------------------------------------------------------------------
   304 // CContactStore::CContactStore
   553 // CContactStore::CContactStore
   305 // --------------------------------------------------------------------------
   554 // --------------------------------------------------------------------------
   306 //
   555 //
   329     delete iStoreURI;
   578     delete iStoreURI;
   330     delete iFieldFactory;
   579     delete iFieldFactory;
   331     delete iFieldsInfo;
   580     delete iFieldsInfo;
   332     delete iProperties;
   581     delete iProperties;
   333     delete iDiskSpaceCheck;
   582     delete iDiskSpaceCheck;
       
   583     delete iOpenOperation;
   334     FeatureManager::UnInitializeLib();
   584     FeatureManager::UnInitializeLib();
   335     }
   585     }
   336 
   586 
   337 // --------------------------------------------------------------------------
   587 // --------------------------------------------------------------------------
   338 // CContactStore::NewL
   588 // CContactStore::NewL
   876         (MVPbkContactObserver::EContactSetOwn, aContactItem, aObserver);
  1126         (MVPbkContactObserver::EContactSetOwn, aContactItem, aObserver);
   877     iAsyncContactOperation->Execute();
  1127     iAsyncContactOperation->Execute();
   878 	}
  1128 	}
   879 
  1129 
   880 // --------------------------------------------------------------------------
  1130 // --------------------------------------------------------------------------
       
  1131 // CContactStore::StoreOpenedL
       
  1132 // --------------------------------------------------------------------------
       
  1133 //
       
  1134 void CContactStore::StoreOpenedL( CContactDatabase* aDB )
       
  1135     {
       
  1136     VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING
       
  1137         ("VPbkCntModel: CContactStore::StoreOpenedL"));
       
  1138     
       
  1139     CleanupStack::PushL( aDB );
       
  1140     
       
  1141     delete iOpenOperation;
       
  1142     iOpenOperation = NULL;
       
  1143 
       
  1144     if( !iGoldenTemplateUpdated )
       
  1145         {
       
  1146         iSysTemplate = aDB->OpenContactL(aDB->TemplateId());
       
  1147         // set contact model template label texts according to localisation
       
  1148         // must be done in order for contact field labels to be correct after language change
       
  1149         if( UpdateSystemTemplateFieldsL( *iSysTemplate, *iFieldsInfo ) )
       
  1150             {
       
  1151             aDB->CommitContactL( *iSysTemplate );
       
  1152             iGoldenTemplateUpdated = ETrue;
       
  1153             }
       
  1154         CloseSystemTemplate( aDB );
       
  1155     
       
  1156         // reopen the contact database if the golden template has been changed
       
  1157         if( iGoldenTemplateUpdated )
       
  1158             {
       
  1159             // template updated -> reopen store
       
  1160             CleanupStack::PopAndDestroy( aDB );
       
  1161             iOpenOperation = new(ELeave) CContactStoreOpenOperation( *this, EFalse );
       
  1162             return;
       
  1163             }
       
  1164         }
       
  1165 
       
  1166     // read the system template and create the field factory accordingly
       
  1167     iSysTemplate = aDB->ReadContactL(aDB->TemplateId());
       
  1168     iFieldFactory = CFieldFactory::NewL(iStoreDomain.FieldTypeMap(),
       
  1169         iSysTemplate, MasterFieldTypeList(), iStoreDomain.FsSession() );
       
  1170     iSysTemplate = NULL;
       
  1171 
       
  1172     // set supported fields for this store
       
  1173     iProperties->SetSupportedFields(*iFieldFactory);
       
  1174     SetStaticPropertiesL();
       
  1175 
       
  1176     iDbNotifier = CContactChangeNotifier::NewL(*aDB, this);
       
  1177     CleanupStack::Pop(aDB);
       
  1178     iContactDb = aDB;
       
  1179 
       
  1180     // Activate remote views so that contacts server will build
       
  1181     // the view as soon as possible when system boots.
       
  1182     // This is trapped because it's not wanted to block
       
  1183     // the store opening if the view building failed.
       
  1184     TRAP_IGNORE( DoActivateRemoteViewsL() );
       
  1185 
       
  1186     // Send event to all observers. This means that multiple pending open requests
       
  1187     // are all signalled as complete here and we can cancel all other open operations.
       
  1188     SendEventL(iObservers, &MVPbkContactStoreObserver::StoreReady, *this);
       
  1189     iAsyncOpenOp->Purge();
       
  1190     }
       
  1191 
       
  1192 // --------------------------------------------------------------------------
       
  1193 // CContactStore::StoreOpenFailed
       
  1194 // --------------------------------------------------------------------------
       
  1195 //
       
  1196 void CContactStore::StoreOpenFailed( TInt aError )
       
  1197     {
       
  1198     VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING
       
  1199         ("VPbkCntModel: CContactStore::StoreOpenFailed(%d)"), aError);
       
  1200     
       
  1201     delete iOpenOperation;
       
  1202     iOpenOperation = NULL;
       
  1203     
       
  1204     SendErrorEvent(iObservers, &MVPbkContactStoreObserver::StoreUnavailable,
       
  1205         *this, aError );
       
  1206     }
       
  1207 
       
  1208 // --------------------------------------------------------------------------
       
  1209 // CContactStore::RequestFreeDiskSpaceLC
       
  1210 // --------------------------------------------------------------------------
       
  1211 //
       
  1212 TBool CContactStore::RequestFreeDiskSpaceLC( TInt aSpace )
       
  1213     {
       
  1214     RSharedDataClient* sharedDataClient = iStoreDomain.SharedDataClient();
       
  1215     if( sharedDataClient )
       
  1216         {
       
  1217         // Try to release space for contact db opening
       
  1218         sharedDataClient->RequestFreeDiskSpaceLC( aSpace );
       
  1219         return ETrue;
       
  1220         }
       
  1221     return EFalse;
       
  1222     }
       
  1223 
       
  1224 // --------------------------------------------------------------------------
   881 // CContactStore::CreateContactRetrieverL
  1225 // CContactStore::CreateContactRetrieverL
   882 // --------------------------------------------------------------------------
  1226 // --------------------------------------------------------------------------
   883 //
  1227 //
   884 MVPbkContactOperation* CContactStore::CreateContactRetrieverL(
  1228 MVPbkContactOperation* CContactStore::CreateContactRetrieverL(
   885         const MVPbkContactLink& aLink,
  1229         const MVPbkContactLink& aLink,
  1160     VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING
  1504     VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING
  1161         ("CContactStore::DoOpenL(0x%x)"), &aObserver);
  1505         ("CContactStore::DoOpenL(0x%x)"), &aObserver);
  1162 
  1506 
  1163     if (!iContactDb)
  1507     if (!iContactDb)
  1164         {
  1508         {
  1165         CContactDatabase* db = NULL;
  1509         // start opening store if it's not already pending
  1166         if (aReplace)
  1510         if( !iOpenOperation )
  1167             {
  1511             {
  1168             db = CContactDatabase::ReplaceL(StoreProperties().Name().UriDes());
  1512             iOpenOperation = new(ELeave) CContactStoreOpenOperation( *this, EFalse );
  1169             }
  1513             }
  1170         else
       
  1171             {
       
  1172             db = OpenInternalL();
       
  1173             }
       
  1174         CleanupStack::PushL(db);
       
  1175 
       
  1176         // opens the Symbian Contacts model golden template
       
  1177         TBool updated = EFalse;
       
  1178         iSysTemplate = db->OpenContactL(db->TemplateId());
       
  1179         // set contact model template label texts according to localisation
       
  1180         // must be done in order for contact field labels to be correct after language change
       
  1181         if (UpdateSystemTemplateFieldsL(*iSysTemplate, *iFieldsInfo))
       
  1182             {
       
  1183             db->CommitContactL(*iSysTemplate);
       
  1184             updated = ETrue;
       
  1185             }
       
  1186         CloseSystemTemplate(db);
       
  1187 
       
  1188         // reopen the contact database if the golden template has been changed
       
  1189         if(updated)
       
  1190             {
       
  1191             CleanupStack::PopAndDestroy(db);
       
  1192             db = NULL;
       
  1193             // db already exists so we just reopen it
       
  1194             db = OpenInternalL();
       
  1195             CleanupStack::PushL(db);
       
  1196             }
       
  1197         // read the system template and create the field factory accordingly
       
  1198         iSysTemplate = db->ReadContactL(db->TemplateId());
       
  1199         iFieldFactory = CFieldFactory::NewL(iStoreDomain.FieldTypeMap(),
       
  1200             iSysTemplate, MasterFieldTypeList(), iStoreDomain.FsSession() );
       
  1201         iSysTemplate = NULL;
       
  1202 
       
  1203         // set supported fields for this store
       
  1204         iProperties->SetSupportedFields(*iFieldFactory);
       
  1205         SetStaticPropertiesL();
       
  1206 
       
  1207         iDbNotifier = CContactChangeNotifier::NewL(*db, this);
       
  1208         CleanupStack::Pop(db);
       
  1209         iContactDb = db;
       
  1210 
       
  1211         // Activate remote views so that contacts server will build
       
  1212         // the view as soon as possible when system boots.
       
  1213         // This is trapped because it's not wanted to block
       
  1214         // the store opening if the view building failed.
       
  1215         TRAP_IGNORE( DoActivateRemoteViewsL() );
       
  1216 
       
  1217         // Send event to all observers. This means that multiple pending open requests
       
  1218         // are all signalled as complete here and we can cancel all other open operations.
       
  1219         SendEventL(iObservers, &MVPbkContactStoreObserver::StoreReady, *this);
       
  1220         iAsyncOpenOp->Purge();
       
  1221         }
  1514         }
  1222     else
  1515     else
  1223         {
  1516         {
  1224         // In case the contact database is already open, we come here
  1517         // In case the contact database is already open, we come here
  1225         SendEventL(&aObserver, &MVPbkContactStoreObserver::StoreReady, *this);
  1518         SendEventL(&aObserver, &MVPbkContactStoreObserver::StoreReady, *this);