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 // |
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); |