|
1 /* |
|
2 * Copyright (c) 2008 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: Handles PIM contact list <-> Contacts Model conversions |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // CLASS HEADER |
|
20 #include "cpimcontactlistadapter.h" |
|
21 |
|
22 // INTERNAL INCLUDES |
|
23 #include "cpimcontactcategorymanager.h" |
|
24 #include "cpimcontactitemadapter.h" |
|
25 #include "mpimcontactitem.h" |
|
26 #include "mpimitemdata.h" |
|
27 #include "logger.h" |
|
28 |
|
29 // EXTERNAL INCLUDES |
|
30 #include <badesca.h> |
|
31 #include <cntdb.h> |
|
32 #include <cntitem.h> // CContactGroup |
|
33 #include <cntfilt.h> // CCntFilter |
|
34 |
|
35 |
|
36 // ============================ MEMBER FUNCTIONS =============================== |
|
37 |
|
38 // ----------------------------------------------------------------------------- |
|
39 // CPIMContactListAdapter::NewL |
|
40 // Two-phased constructor. |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 CPIMContactListAdapter* CPIMContactListAdapter::NewL( |
|
44 java::util::FunctionServer* aFuncServer) |
|
45 { |
|
46 JELOG2(EPim); |
|
47 CPIMContactListAdapter* self = |
|
48 new(ELeave) CPIMContactListAdapter(aFuncServer); |
|
49 |
|
50 CallMethodL(self, &CPIMContactListAdapter::ConstructL, self->iFuncServer); |
|
51 |
|
52 return self; |
|
53 } |
|
54 |
|
55 // Destructor |
|
56 CPIMContactListAdapter::~CPIMContactListAdapter() |
|
57 { |
|
58 JELOG2(EPim); |
|
59 Close(); |
|
60 } |
|
61 // ----------------------------------------------------------------------------- |
|
62 // CPIMContactListAdapter::HandleDatabaseEventL |
|
63 // Tests the contact database observer event type and handles it. The ID of |
|
64 // a contact affected by the change event, if relevant, can be retrieved |
|
65 // via TContactDbObserverEvent::iContactId. |
|
66 // ----------------------------------------------------------------------------- |
|
67 // |
|
68 void CPIMContactListAdapter::HandleDatabaseEventL( |
|
69 TContactDbObserverEvent aEvent) // information about the change event |
|
70 { |
|
71 JELOG2(EPim); |
|
72 switch (aEvent.iType) |
|
73 { |
|
74 case EContactDbObserverEventGroupAdded: |
|
75 { |
|
76 ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeNew); |
|
77 break; |
|
78 } |
|
79 case EContactDbObserverEventGroupChanged: |
|
80 { |
|
81 ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeModified); |
|
82 break; |
|
83 } |
|
84 case EContactDbObserverEventGroupDeleted: |
|
85 { |
|
86 ExternalGroupChangeL(aEvent.iContactId, EPIMExternalChangeRemoved); |
|
87 break; |
|
88 } |
|
89 case EContactDbObserverEventContactAdded: |
|
90 { |
|
91 ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeNew); |
|
92 break; |
|
93 } |
|
94 case EContactDbObserverEventContactChanged: |
|
95 { |
|
96 ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeModified); |
|
97 break; |
|
98 } |
|
99 case EContactDbObserverEventContactDeleted: |
|
100 { |
|
101 ExternalItemChangeL(aEvent.iContactId, EPIMExternalChangeRemoved); |
|
102 break; |
|
103 } |
|
104 default: |
|
105 { |
|
106 // we don't care about other changes |
|
107 return; |
|
108 } |
|
109 } |
|
110 } |
|
111 |
|
112 |
|
113 // ----------------------------------------------------------------------------- |
|
114 // CPIMContactListAdapter::GetCategoriesL |
|
115 // Provides all categories currently existing in the native database. |
|
116 // Returns: Array of categories |
|
117 // ----------------------------------------------------------------------------- |
|
118 // |
|
119 const CDesCArray& CPIMContactListAdapter::GetCategoriesL() |
|
120 { |
|
121 JELOG2(EPim); |
|
122 __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); |
|
123 return iCategoryManager->CallGetCategoriesL(); |
|
124 } |
|
125 |
|
126 // ----------------------------------------------------------------------------- |
|
127 // CPIMContactListAdapter::AddCategoryL |
|
128 // Adds a new category to the native database. |
|
129 // If the category already exists, nothing is done and the method returns |
|
130 // successfully. |
|
131 // ----------------------------------------------------------------------------- |
|
132 // |
|
133 void CPIMContactListAdapter::AddCategoryL(const TDesC& aNewCategory) |
|
134 { |
|
135 JELOG2(EPim); |
|
136 __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); |
|
137 CallMethodL(iCategoryManager, &CPIMContactCategoryManager::AddCategoryL, |
|
138 aNewCategory, iFuncServer); |
|
139 } |
|
140 |
|
141 // ----------------------------------------------------------------------------- |
|
142 // CPIMContactListAdapter::DeleteCategoryL |
|
143 // Deletes an existing category. |
|
144 // If there is no such category, nothing is done and the method returns |
|
145 // successfully. |
|
146 // ----------------------------------------------------------------------------- |
|
147 // |
|
148 void CPIMContactListAdapter::DeleteCategoryL(const TDesC& aCategory) |
|
149 { |
|
150 JELOG2(EPim); |
|
151 __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); |
|
152 CallMethodL(iCategoryManager, &CPIMContactCategoryManager::DeleteCategoryL, |
|
153 aCategory, iFuncServer); |
|
154 } |
|
155 |
|
156 // ----------------------------------------------------------------------------- |
|
157 // CPIMContactListAdapter::RenameCategoryL |
|
158 // Renames an existing category. |
|
159 // Entries in the old category are moved to the new category. |
|
160 // ----------------------------------------------------------------------------- |
|
161 // |
|
162 void CPIMContactListAdapter::RenameCategoryL(const TDesC& aOldCategory, // The old category name |
|
163 const TDesC& aNewCategory) // The new category name |
|
164 { |
|
165 JELOG2(EPim); |
|
166 __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); |
|
167 CallMethodL(iCategoryManager, &CPIMContactCategoryManager::RenameCategoryL, |
|
168 aOldCategory, aNewCategory, iFuncServer); |
|
169 } |
|
170 |
|
171 // ----------------------------------------------------------------------------- |
|
172 // CPIMContactListAdapter::IsCategoriesExternallyModified |
|
173 // Checks whether there have been external changes to the categories in |
|
174 // the native database after last call to |
|
175 // GetExternalCategoryModifications or list adapter creation. |
|
176 // Returns: ETrue: If there are any external changes |
|
177 // EFalse: Otherwise |
|
178 // ----------------------------------------------------------------------------- |
|
179 // |
|
180 TBool CPIMContactListAdapter::IsCategoriesExternallyModified() |
|
181 { |
|
182 JELOG2(EPim); |
|
183 if (iCategoryChanges) |
|
184 { |
|
185 return ETrue; |
|
186 } |
|
187 return EFalse; |
|
188 } |
|
189 |
|
190 // ----------------------------------------------------------------------------- |
|
191 // CPIMContactListAdapter::GetExternalCategoryModificationsL |
|
192 // Provides the external changes to the categories in the native database. |
|
193 // Returns: An array of category state change objects. The ownership |
|
194 // of the array is transferred to the caller. Note that the |
|
195 // array elements contain heap-allocated data. |
|
196 // ----------------------------------------------------------------------------- |
|
197 // |
|
198 RPointerArray<CPIMCategoryStateChange>* |
|
199 CPIMContactListAdapter::GetExternalCategoryModificationsL() |
|
200 { |
|
201 JELOG2(EPim); |
|
202 CallMethodL(this, &CPIMContactListAdapter::IsDatabaseReadyL, iFuncServer); |
|
203 RPointerArray<CPIMCategoryStateChange>* retval = iCategoryChanges; |
|
204 iCategoryChanges = NULL; |
|
205 return retval; |
|
206 } |
|
207 |
|
208 // ----------------------------------------------------------------------------- |
|
209 // CPIMContactListAdapter::IsItemsExternallyModified |
|
210 // Checks whether there have been external changes to the items in |
|
211 // the native database after last call to |
|
212 // GetExternalItemModifications or list adapter creation. |
|
213 // Returns: EExternalChangesMinor: If there are any external changes |
|
214 // EExternalChangesNone: Otherwise |
|
215 // ----------------------------------------------------------------------------- |
|
216 // |
|
217 MPIMListAdapter::TExternalItemChangeClass CPIMContactListAdapter::IsItemsExternallyModified() |
|
218 { |
|
219 JELOG2(EPim); |
|
220 if ((iItemChanges || iFirstItemChanges)) |
|
221 { |
|
222 return MPIMListAdapter::EExternalChangesMinor; |
|
223 } |
|
224 return MPIMListAdapter::EExternalChangesNone; |
|
225 } |
|
226 |
|
227 // ----------------------------------------------------------------------------- |
|
228 // CPIMContactListAdapter::GetExternalItemModificationsL |
|
229 // Provides the external changes to the items in the native database. |
|
230 // Returns: An array of item state change objects. The ownership |
|
231 // of the array is transferred to the caller. Note that the |
|
232 // array elements contain heap-allocated data. |
|
233 // ----------------------------------------------------------------------------- |
|
234 // |
|
235 RPointerArray<CPIMItemStateChange>* |
|
236 CPIMContactListAdapter::GetExternalItemModificationsL() |
|
237 { |
|
238 JELOG2(EPim); |
|
239 CallMethodL(this, &CPIMContactListAdapter::IsDatabaseReadyL, iFuncServer); |
|
240 |
|
241 // the first time, |
|
242 // we check for all cards |
|
243 if (iFirstItemChanges) |
|
244 { |
|
245 //FilterAllContactsL(); |
|
246 CallMethodL(this, &CPIMContactListAdapter::FilterAllContactsL, |
|
247 iFuncServer); |
|
248 iFirstItemChanges = EFalse; |
|
249 } |
|
250 |
|
251 RPointerArray<CPIMItemStateChange>* retval = iItemChanges; |
|
252 iItemChanges = NULL; |
|
253 return retval; |
|
254 } |
|
255 |
|
256 // ----------------------------------------------------------------------------- |
|
257 // CPIMContactListAdapter::Close |
|
258 // Used to inform the list adapter that the list has been closed. |
|
259 // The list adapter may then release all resources it has reserved. |
|
260 // ----------------------------------------------------------------------------- |
|
261 // |
|
262 void CPIMContactListAdapter::Close() |
|
263 { |
|
264 JELOG2(EPim); |
|
265 CallMethod(this, &CPIMContactListAdapter::DoClose, iFuncServer); |
|
266 } |
|
267 |
|
268 void CPIMContactListAdapter::DoClose() |
|
269 { |
|
270 JELOG2(EPim); |
|
271 if (iCategoryChanges) |
|
272 { |
|
273 iCategoryChanges->ResetAndDestroy(); |
|
274 delete iCategoryChanges; |
|
275 iCategoryChanges = NULL; |
|
276 } |
|
277 if (iItemChanges) |
|
278 { |
|
279 iItemChanges->ResetAndDestroy(); |
|
280 delete iItemChanges; |
|
281 iItemChanges = NULL; |
|
282 } |
|
283 delete iNotifier; |
|
284 iNotifier = NULL; |
|
285 delete iItemAdapter; |
|
286 iItemAdapter = NULL; |
|
287 delete iCategoryManager; |
|
288 iCategoryManager = NULL; |
|
289 delete iDatabase; |
|
290 iDatabase = NULL; |
|
291 delete iMinimalFieldsViewDef; |
|
292 iMinimalFieldsViewDef = NULL; |
|
293 } |
|
294 |
|
295 // ----------------------------------------------------------------------------- |
|
296 // CPIMContactListAdapter::GetPimListAdapter |
|
297 // Provides access to the MPIMListAdapter representation of this |
|
298 // MPIMContactListAdapter object. |
|
299 // ----------------------------------------------------------------------------- |
|
300 // |
|
301 MPIMListAdapter* CPIMContactListAdapter::GetPimListAdapter() |
|
302 { |
|
303 JELOG2(EPim); |
|
304 return this; |
|
305 } |
|
306 |
|
307 // ----------------------------------------------------------------------------- |
|
308 // CPIMContactListAdapter::CreateContactItemL |
|
309 // Creates a new contact item (entry) in the native database. |
|
310 // The adapter creates a new native database entry, sets its data |
|
311 // according to the data in aContactItem, adds it to the database |
|
312 // and sets the Item ID of aContactItem. aContactItem must |
|
313 // contain valid data and have Item ID KPIMNullItemID. |
|
314 // ----------------------------------------------------------------------------- |
|
315 // |
|
316 void CPIMContactListAdapter::CreateContactItemL(MPIMContactItem& aContactItem) // The contact item to add |
|
317 { |
|
318 JELOG2(EPim); |
|
319 CallMethodL(this, &CPIMContactListAdapter::DoCreateContactItemL, |
|
320 aContactItem, iFuncServer); |
|
321 ReadContactItemL(aContactItem); |
|
322 } |
|
323 |
|
324 void CPIMContactListAdapter::DoCreateContactItemL(MPIMContactItem& aContactItem) // The contact item to add |
|
325 { |
|
326 JELOG2(EPim); |
|
327 __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); |
|
328 CContactCard* card = iItemAdapter->CardL(aContactItem); |
|
329 CleanupStack::PushL(card); |
|
330 // Leaves with KErrDiskFull if there is not enough disk |
|
331 // space to create a new contact item |
|
332 TContactItemId id = iDatabase->AddNewContactL(*card); |
|
333 // Set new item id. If this leaves it means that |
|
334 // SetContactItemIdL leaved with KErrOutNoMemory |
|
335 TRAPD(err, aContactItem.SetContactItemIdL(id)); |
|
336 if (KErrNone != err) |
|
337 { |
|
338 TBuf8<KPIMItemIdDesSize> entryId; |
|
339 entryId.Num(static_cast<TUint>(id)); |
|
340 DoRemoveContactItemL(entryId); |
|
341 User::Leave(err); |
|
342 } |
|
343 iItemAdapter->UpdateCategoriesL(aContactItem, *card); |
|
344 CleanupStack::PopAndDestroy(card); |
|
345 // update possible changes (e.g. dropped attributes) to the item |
|
346 aContactItem.PrepareForLoadL(); |
|
347 } |
|
348 |
|
349 // ----------------------------------------------------------------------------- |
|
350 // CPIMContactListAdapter::ReadContactItemL |
|
351 // Reads an existing contact item from the native database. |
|
352 // The adapter maps the Item ID in aContactItem to a native database |
|
353 // entry identifier, reads the entry and sets the data of |
|
354 // aContactItem according to the data in the native entry. This operation |
|
355 // is very performance sensitive, so it must be used with cause and only |
|
356 // when the full contact item is needed |
|
357 // ----------------------------------------------------------------------------- |
|
358 // |
|
359 void CPIMContactListAdapter::ReadContactItemL(MPIMContactItem& aContactItem) // The contact item to be read |
|
360 { |
|
361 JELOG2(EPim); |
|
362 CallMethodL(this, &CPIMContactListAdapter::DoCallReadContactItemL, |
|
363 aContactItem, iFuncServer); |
|
364 } |
|
365 |
|
366 void CPIMContactListAdapter::DoCallReadContactItemL( |
|
367 MPIMContactItem& aContactItem) // The contact item to be read |
|
368 { |
|
369 JELOG2(EPim); |
|
370 __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); |
|
371 const TContactItemId id = aContactItem.ContactItemIdL(); |
|
372 __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); |
|
373 // If the contact item contains data we don't want to overwrite it |
|
374 // so we create a mask item view definition if needed. Otherwise |
|
375 // we just read full contact item from the database |
|
376 CContactItemViewDef* itemViewDef = CContactItemViewDef::NewLC( |
|
377 CContactItemViewDef::EMaskFields, |
|
378 CContactItemViewDef::EIncludeHiddenFields); |
|
379 CArrayFix<TPIMField>* fields = aContactItem.ItemData().FieldsLC(); |
|
380 TInt count = fields->Count(); |
|
381 |
|
382 // Mask fields and do not include. Note that if there is no fields in the |
|
383 // item the view should provide all possible fields from the database |
|
384 for (TInt i = 0; i < count; i++) |
|
385 { |
|
386 TPIMContactField field = static_cast<TPIMContactField>(fields->At(i)); |
|
387 // Get Contacts Model fields mapped to PIM fields |
|
388 CArrayFix<TInt>* fieldArray = iItemAdapter->ContactsModelFieldTypeL( |
|
389 field); |
|
390 CleanupStack::PushL(fieldArray); |
|
391 // Add retrieved fields to the item view definition |
|
392 TInt fieldCount = fieldArray->Count(); |
|
393 for (TInt j = 0; j < fieldCount; j++) |
|
394 { |
|
395 const TUid fieldUid = |
|
396 { fieldArray->At(j) }; |
|
397 // Do not add the field to the view if it already contains |
|
398 // this type of a field (e.g the field is a name array element) |
|
399 if (itemViewDef->Find(fieldUid) == KErrNotFound) |
|
400 { |
|
401 itemViewDef->AddL(fieldUid); |
|
402 } |
|
403 } |
|
404 CleanupStack::PopAndDestroy(fieldArray); |
|
405 } |
|
406 DoReadContactItemL(aContactItem, *itemViewDef); |
|
407 CleanupStack::PopAndDestroy(2, itemViewDef); |
|
408 } |
|
409 |
|
410 // ----------------------------------------------------------------------------- |
|
411 // CPIMContactListAdapter::ReadMinimalContactItemL |
|
412 // This version reads a minimal contact item from the native database by using |
|
413 // contact database view definition. The view definition is initialized in |
|
414 // the constructor of this class and needs to be up to date with currently |
|
415 // required contact fields when the item is read for the first time. This |
|
416 // function was introduced due to improve poor performance of the PIM API |
|
417 // ContactList |
|
418 // ----------------------------------------------------------------------------- |
|
419 |
|
420 void CPIMContactListAdapter::ReadMinimalContactItemL( |
|
421 MPIMContactItem& aContactItem) |
|
422 { |
|
423 JELOG2(EPim); |
|
424 CallMethodL(this, &CPIMContactListAdapter::DoCallReadMinimalContactItemL, |
|
425 aContactItem, iFuncServer); |
|
426 } |
|
427 |
|
428 void CPIMContactListAdapter::DoCallReadMinimalContactItemL( |
|
429 MPIMContactItem& aContactItem) |
|
430 { |
|
431 JELOG2(EPim); |
|
432 __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); |
|
433 TContactItemId id = aContactItem.ContactItemIdL(); |
|
434 __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); |
|
435 |
|
436 // Reset item for reading |
|
437 aContactItem.PrepareForLoadL(); |
|
438 |
|
439 // Use contact database filtering. Currently only all name elements |
|
440 // are retrieved from the database to improve performance of the list |
|
441 DoReadContactItemL(aContactItem, *iMinimalFieldsViewDef); |
|
442 |
|
443 } |
|
444 |
|
445 // ----------------------------------------------------------------------------- |
|
446 // CPIMContactListAdapter::ReadMinimalContactItemL |
|
447 // This version reads a minimal contact item from the native database by using |
|
448 // contact database view definition. The view definition is initialized in |
|
449 // the constructor of this class and it can be modified to fetch specified fields |
|
450 // by the matching item given as an argument to this function |
|
451 // ----------------------------------------------------------------------------- |
|
452 |
|
453 void CPIMContactListAdapter::ReadMinimalContactItemL( |
|
454 MPIMContactItem& aContactItem, const MPIMContactItem& aMatchingContactItem) |
|
455 { |
|
456 JELOG2(EPim); |
|
457 // Get fields from the matching item and add those to the view definition |
|
458 CArrayFix<TPIMField>* fields = aMatchingContactItem.ItemData().FieldsLC(); |
|
459 TInt count = fields->Count(); |
|
460 for (TInt i = 0; i < count; i++) |
|
461 { |
|
462 TPIMContactField field = static_cast<TPIMContactField>(fields->At(i)); |
|
463 // Get Contacts Model fields mapped to PIM fields |
|
464 CArrayFix<TInt>* fieldArray = iItemAdapter->ContactsModelFieldTypeL( |
|
465 field); |
|
466 CleanupStack::PushL(fieldArray); |
|
467 // Add retrieved fields to the item view definition |
|
468 TInt fieldCount = fieldArray->Count(); |
|
469 for (TInt j = 0; j < fieldCount; j++) |
|
470 { |
|
471 const TUid fieldUid = |
|
472 { fieldArray->At(j) }; |
|
473 // Do not add the field to the view if it already contains |
|
474 // this type of a field (e.g the field is a name array element) |
|
475 if (iMinimalFieldsViewDef->Find(fieldUid) == KErrNotFound) |
|
476 { |
|
477 iMinimalFieldsViewDef->AddL(fieldUid); |
|
478 } |
|
479 } |
|
480 CleanupStack::PopAndDestroy(fieldArray); |
|
481 } |
|
482 CleanupStack::PopAndDestroy(fields); |
|
483 // Read contact item using minimal field definition |
|
484 ReadMinimalContactItemL(aContactItem); |
|
485 // Reset the view definition to its previous state |
|
486 InitializeMinimalViewDefinitionL(); |
|
487 } |
|
488 |
|
489 // ----------------------------------------------------------------------------- |
|
490 // CPIMContactListAdapter::ReadContactFieldL |
|
491 // Reads one field from the contact database |
|
492 // ----------------------------------------------------------------------------- |
|
493 // |
|
494 void CPIMContactListAdapter::ReadContactFieldL(MPIMContactItem& aContactItem, |
|
495 TPIMContactField aContactField) |
|
496 { |
|
497 JELOG2(EPim); |
|
498 CallMethodL(this, &CPIMContactListAdapter::DoReadContactFieldL, |
|
499 aContactItem, aContactField, iFuncServer); |
|
500 } |
|
501 |
|
502 void CPIMContactListAdapter::DoReadContactFieldL(MPIMContactItem& aContactItem, |
|
503 TPIMContactField aContactField) |
|
504 { |
|
505 JELOG2(EPim); |
|
506 __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); |
|
507 TContactItemId id = aContactItem.ContactItemIdL(); |
|
508 __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); |
|
509 |
|
510 // Create new view definition |
|
511 CContactItemViewDef* itemViewDef = CContactItemViewDef::NewLC( |
|
512 CContactItemViewDef::EIncludeFields, |
|
513 CContactItemViewDef::EIncludeHiddenFields); |
|
514 CArrayFix<TInt>* fieldArray = iItemAdapter->ContactsModelFieldTypeL( |
|
515 aContactField); |
|
516 CleanupStack::PushL(fieldArray); |
|
517 // Add retrieved fields to the item view definition |
|
518 TInt fieldCount = fieldArray->Count(); |
|
519 for (TInt i = 0; i < fieldCount; i++) |
|
520 { |
|
521 const TUid fieldUid = |
|
522 { fieldArray->At(i) }; |
|
523 itemViewDef->AddL(fieldUid); |
|
524 } |
|
525 // The view cannot be empty so check the field count in debug builds |
|
526 __ASSERT_DEBUG(itemViewDef->Count() > 0, User::Panic(KPIMPanicCategory, |
|
527 EPIMPanicInvalidState)); |
|
528 CleanupStack::PopAndDestroy(fieldArray); |
|
529 DoReadContactItemL(aContactItem, *itemViewDef); |
|
530 CleanupStack::PopAndDestroy(itemViewDef); |
|
531 } |
|
532 |
|
533 // ----------------------------------------------------------------------------- |
|
534 // CPIMContactListAdapter::WriteContactItemL |
|
535 // Writes an existing contact item to the native database. |
|
536 // The adapter maps the Item ID in aContactItem to a native database |
|
537 // entry identifier, reads the entry and sets the data of the entry |
|
538 // according to the data in aContactItem. |
|
539 // ----------------------------------------------------------------------------- |
|
540 // |
|
541 void CPIMContactListAdapter::WriteContactItemL(MPIMContactItem& aContactItem) // The contact item to write |
|
542 { |
|
543 JELOG2(EPim); |
|
544 CallMethodL(this, &CPIMContactListAdapter::DoWriteContactItemL, |
|
545 aContactItem, iFuncServer); |
|
546 ReadContactItemL(aContactItem); |
|
547 } |
|
548 |
|
549 void CPIMContactListAdapter::DoWriteContactItemL(MPIMContactItem& aContactItem) // The contact item to write |
|
550 { |
|
551 JELOG2(EPim); |
|
552 __ASSERT_ALWAYS(iItemAdapter || iDatabase, User::Leave(KErrNotReady)); |
|
553 TContactItemId id = aContactItem.ContactItemIdL(); |
|
554 __ASSERT_ALWAYS(id != 0, User::Leave(KErrArgument)); |
|
555 |
|
556 // OpenContactLX leaves the lock item in the cleanup stack |
|
557 CContactCard* contactItem = |
|
558 static_cast<CContactCard*>(iDatabase->OpenContactLX(id)); |
|
559 CleanupStack::PushL(contactItem); |
|
560 iItemAdapter->UpdateCardL(aContactItem, *contactItem); |
|
561 iDatabase->CommitContactL(*contactItem); |
|
562 // Note: Even though the above line closed the contact, we can still |
|
563 // keep the lock item in the cleanup stack as closing a contact |
|
564 // twice is harmless |
|
565 iItemAdapter->UpdateCategoriesL(aContactItem, *contactItem); |
|
566 CleanupStack::PopAndDestroy(contactItem); |
|
567 CleanupStack::Pop(); // contactItem lock item |
|
568 // update possible changes (e.g. dropped attributes) to the item |
|
569 aContactItem.PrepareForLoadL(); |
|
570 } |
|
571 |
|
572 // ----------------------------------------------------------------------------- |
|
573 // CPIMContactListAdapter::ReadContactItemL |
|
574 // Removes an existing contact from the native database. |
|
575 // The adapter maps aItemID to a native database entry and removes it. |
|
576 // ----------------------------------------------------------------------------- |
|
577 // |
|
578 void CPIMContactListAdapter::RemoveContactItemL(TPIMItemID aItemID) |
|
579 { |
|
580 JELOG2(EPim); |
|
581 CallMethodL(this, &CPIMContactListAdapter::DoRemoveContactItemL, aItemID, |
|
582 iFuncServer); |
|
583 } |
|
584 |
|
585 void CPIMContactListAdapter::DoRemoveContactItemL(TPIMItemID aItemID) |
|
586 { |
|
587 JELOG2(EPim); |
|
588 __ASSERT_ALWAYS(iDatabase, User::Leave(KErrNotReady)); |
|
589 // Convert string id to integer id |
|
590 TUint id; |
|
591 TLex8 lex(aItemID); |
|
592 TInt status = lex.Val(id); |
|
593 User::LeaveIfError(status); |
|
594 // Delete contact from the contact database |
|
595 iDatabase->DeleteContactL(id); |
|
596 } |
|
597 |
|
598 // ----------------------------------------------------------------------------- |
|
599 // CPIMContactListAdapter::CPIMContactListAdapter |
|
600 // C++ default constructor can NOT contain any code, that |
|
601 // might leave. |
|
602 // ----------------------------------------------------------------------------- |
|
603 // |
|
604 CPIMContactListAdapter::CPIMContactListAdapter( |
|
605 java::util::FunctionServer* aFuncServer) |
|
606 { |
|
607 JELOG2(EPim); |
|
608 iFirstItemChanges = ETrue; |
|
609 iFuncServer = aFuncServer; |
|
610 } |
|
611 |
|
612 // ----------------------------------------------------------------------------- |
|
613 // CPIMContactListAdapter::ConstructL |
|
614 // Symbian 2nd phase constructor can leave. |
|
615 // ----------------------------------------------------------------------------- |
|
616 // |
|
617 void CPIMContactListAdapter::ConstructL() |
|
618 { |
|
619 JELOG2(EPim); |
|
620 // Create default contact database if it does not exist. This may happen |
|
621 // if the current Phonebook engine is not running or started during |
|
622 // device boot. Usually, the database should be available but this is precaution |
|
623 if (!CContactDatabase::DefaultContactDatabaseExistsL()) |
|
624 { |
|
625 iDatabase |
|
626 = CContactDatabase::CreateL(/*CContactDatabase::EMultiThread*/); |
|
627 } |
|
628 else |
|
629 { |
|
630 iDatabase = CContactDatabase::OpenL(/*CContactDatabase::EMultiThread*/); |
|
631 } |
|
632 |
|
633 // Create other contact adapter resources and initialize item view |
|
634 iCategoryManager |
|
635 = CPIMContactCategoryManager::NewL(*iDatabase, iFuncServer); |
|
636 iNotifier = CContactChangeNotifier::NewL(*iDatabase, this); |
|
637 iItemAdapter = CPIMContactItemAdapter::NewL(*iCategoryManager); |
|
638 // Initialize minimal fields view definition |
|
639 iMinimalFieldsViewDef = CContactItemViewDef::NewL( |
|
640 CContactItemViewDef::EIncludeFields, |
|
641 CContactItemViewDef::EIncludeHiddenFields); |
|
642 InitializeMinimalViewDefinitionL(); |
|
643 } |
|
644 |
|
645 // ----------------------------------------------------------------------------- |
|
646 // CPIMContactListAdapter::ExternalGroupChangeL |
|
647 // Adds an entry to external category change list. |
|
648 // Also causes the category cache to be flushed. |
|
649 // ----------------------------------------------------------------------------- |
|
650 // |
|
651 void CPIMContactListAdapter::ExternalGroupChangeL(TContactItemId aId, // Id of the changed category |
|
652 TPIMExternalChangeType aType) // type of the change |
|
653 { |
|
654 JELOG2(EPim); |
|
655 iCategoryManager->FlushCache(); |
|
656 |
|
657 // This should never happen |
|
658 __ASSERT_ALWAYS(iCategoryManager, User::Leave(KErrNotReady)); |
|
659 |
|
660 if (!iCategoryChanges) |
|
661 { |
|
662 iCategoryChanges |
|
663 = new(ELeave) RPointerArray<CPIMCategoryStateChange> (1); |
|
664 } |
|
665 CPIMCategoryStateChange* change = NULL; |
|
666 switch (aType) |
|
667 { |
|
668 case EPIMExternalChangeModified: |
|
669 { |
|
670 HBufC* newCategoryName = iCategoryManager->GroupLabelL(aId); |
|
671 CleanupStack::PushL(newCategoryName); |
|
672 HBufC* oldCategoryName = iCategoryManager->LabelFromCacheL(aId); |
|
673 CleanupStack::PushL(oldCategoryName); |
|
674 change |
|
675 = new(ELeave) CPIMCategoryStateChange(oldCategoryName, aType, newCategoryName); |
|
676 CleanupStack::Pop(2); // newCategoryName and oldCategoryName are |
|
677 // now owned by change |
|
678 break; |
|
679 } |
|
680 case EPIMExternalChangeNew: |
|
681 { |
|
682 HBufC* newCategoryName = iCategoryManager->GroupLabelL(aId); |
|
683 CleanupStack::PushL(newCategoryName); |
|
684 change = new(ELeave) CPIMCategoryStateChange(newCategoryName, aType); |
|
685 CleanupStack::Pop(); // newCategoryName is now owned by change |
|
686 break; |
|
687 } |
|
688 case EPIMExternalChangeRemoved: |
|
689 { |
|
690 HBufC* oldCategoryName = iCategoryManager->LabelFromCacheL(aId); |
|
691 CleanupStack::PushL(oldCategoryName); |
|
692 change = new(ELeave) CPIMCategoryStateChange(oldCategoryName, aType); |
|
693 CleanupStack::Pop(); // newCategoryName is now owned by change |
|
694 break; |
|
695 } |
|
696 default: |
|
697 { |
|
698 User::Leave(KErrArgument); |
|
699 } |
|
700 } |
|
701 |
|
702 CleanupStack::PushL(change); |
|
703 User::LeaveIfError(iCategoryChanges->Append(change)); |
|
704 CleanupStack::Pop(change); |
|
705 } |
|
706 |
|
707 // ----------------------------------------------------------------------------- |
|
708 // CPIMContactListAdapter::ExternalItemChangeL |
|
709 // Adds an entry to external item change list. |
|
710 // ----------------------------------------------------------------------------- |
|
711 // |
|
712 void CPIMContactListAdapter::ExternalItemChangeL(TContactItemId aId, // Id of the changed category |
|
713 TPIMExternalChangeType aType) // type of the change |
|
714 { |
|
715 JELOG2(EPim); |
|
716 if (!iItemChanges) |
|
717 { |
|
718 iItemChanges = new(ELeave) RPointerArray<CPIMItemStateChange> (10); |
|
719 } |
|
720 HBufC8* changeId = HBufC8::NewLC(KPIMItemIdDesSize); |
|
721 TPtr8 entryId = changeId->Des(); |
|
722 entryId.Num(static_cast<TUint>(aId)); |
|
723 CPIMItemStateChange* change = |
|
724 new(ELeave) CPIMItemStateChange(changeId, aType); |
|
725 // The ownership of changeId is transferred to the item state change object |
|
726 CleanupStack::Pop(changeId); |
|
727 |
|
728 CleanupStack::PushL(change); |
|
729 iItemChanges->AppendL(change); |
|
730 CleanupStack::Pop(change); |
|
731 } |
|
732 |
|
733 // ----------------------------------------------------------------------------- |
|
734 // CPIMContactListAdapter::FilterAllContacts |
|
735 // Filters all contact items from the database to the changes list |
|
736 // ----------------------------------------------------------------------------- |
|
737 // |
|
738 void CPIMContactListAdapter::FilterAllContactsL() |
|
739 { |
|
740 JELOG2(EPim); |
|
741 CCntFilter* filter = CCntFilter::NewLC(); |
|
742 filter->SetIncludeNewContacts(EFalse); |
|
743 if (!iItemChanges) |
|
744 { |
|
745 iItemChanges = new(ELeave) RPointerArray<CPIMItemStateChange> (10); |
|
746 } |
|
747 filter->SetContactFilterTypeALL(EFalse); |
|
748 filter->SetContactFilterTypeCard(ETrue); |
|
749 iDatabase->FilterDatabaseL(*filter); |
|
750 CContactIdArray* idArray = filter->iIds; |
|
751 TInt idCount = idArray->Count(); |
|
752 TInt i = 0; |
|
753 for (i = 0; i < idCount; i++) |
|
754 { |
|
755 TContactItemId id = (*idArray)[i]; |
|
756 TBool wasInList = EFalse; |
|
757 TInt changeCount = iItemChanges->Count(); |
|
758 for (TInt j = 0; j < changeCount; j++) |
|
759 { |
|
760 TBuf8<KPIMItemIdDesSize> entryId; |
|
761 entryId.Num(static_cast<TUint>(id)); |
|
762 if ((*iItemChanges)[j]->ItemID().Compare(entryId) == 0) |
|
763 { |
|
764 wasInList = ETrue; |
|
765 } |
|
766 } |
|
767 if (!wasInList) |
|
768 { |
|
769 ExternalItemChangeL(id, EPIMExternalChangeNew); |
|
770 } |
|
771 } |
|
772 CleanupStack::PopAndDestroy(); // filter |
|
773 } |
|
774 |
|
775 // ----------------------------------------------------------------------------- |
|
776 // CPIMContactListAdapter::InitializeMinimalViewDefinitionL |
|
777 // Initializes minimal view definition |
|
778 // ----------------------------------------------------------------------------- |
|
779 // |
|
780 void CPIMContactListAdapter::InitializeMinimalViewDefinitionL() |
|
781 { |
|
782 JELOG2(EPim); |
|
783 __ASSERT_DEBUG(iMinimalFieldsViewDef, User::Panic(KPIMPanicCategory, |
|
784 EPIMPanicInvalidState)); |
|
785 // Reset view definition |
|
786 iMinimalFieldsViewDef->Reset(); |
|
787 // Add fields which are to retrieved from the native database |
|
788 // when minimal item is to be created or read |
|
789 iMinimalFieldsViewDef->AddL(KUidContactFieldAdditionalName); |
|
790 iMinimalFieldsViewDef->AddL(KUidContactFieldGivenName); |
|
791 iMinimalFieldsViewDef->AddL(KUidContactFieldFamilyName); |
|
792 iMinimalFieldsViewDef->AddL(KUidContactFieldGivenNamePronunciation); |
|
793 iMinimalFieldsViewDef->AddL(KUidContactFieldFamilyNamePronunciation); |
|
794 iMinimalFieldsViewDef->AddL(KUidContactFieldPrefixName); |
|
795 iMinimalFieldsViewDef->AddL(KUidContactFieldSuffixName); |
|
796 } |
|
797 |
|
798 // ----------------------------------------------------------------------------- |
|
799 // CPIMContactListAdapter::DoReadContactItemL |
|
800 // Reads contact from the contacts database using item view definition |
|
801 // ----------------------------------------------------------------------------- |
|
802 // |
|
803 void CPIMContactListAdapter::DoReadContactItemL(MPIMContactItem& aContactItem, |
|
804 const CContactItemViewDef& aContactItemViewDef) |
|
805 { |
|
806 JELOG2(EPim); |
|
807 const TContactItemId id = aContactItem.ContactItemIdL(); |
|
808 __ASSERT_DEBUG(id != 0, User::Panic(KPIMPanicCategory, |
|
809 EPIMPanicInvalidItemID)); |
|
810 // Read contact item using the item view definition |
|
811 CContactCard* contactItem = |
|
812 static_cast<CContactCard*>(iDatabase->ReadContactLC(id, |
|
813 aContactItemViewDef)); |
|
814 // Set date and fill the PIM item |
|
815 TTime lastModified = contactItem->LastModified(); |
|
816 aContactItem.SetLastModifiedL(lastModified); |
|
817 iItemAdapter->FillItemL(aContactItem, *contactItem); |
|
818 CleanupStack::PopAndDestroy(contactItem); |
|
819 } |
|
820 |
|
821 void CPIMContactListAdapter::IsDatabaseReadyL() |
|
822 { |
|
823 JELOG2(EPim); |
|
824 __ASSERT_ALWAYS(iDatabase, User::Leave(KErrNotReady)); |
|
825 } |
|
826 |
|
827 // End of file |