|
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: Contact item implementation. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // CLASS HEADER |
|
20 #include "cpimcontactitem.h" |
|
21 |
|
22 // INTERNAL INCLUDES |
|
23 #include "cpimitemdata.h" |
|
24 #include "pimcontact.h" |
|
25 #include "mpimcontactadaptermanager.h" |
|
26 #include "mpimcontactlistadapter.h" |
|
27 #include "mpimadaptermanager.h" |
|
28 #include "mpimlistadapter.h" |
|
29 #include "cpimcontactvalidator.h" |
|
30 #include "cpimmanager.h" |
|
31 #include "pimpanics.h" |
|
32 #include "logger.h" |
|
33 |
|
34 // --------------------------------------------------------------------------- |
|
35 // C++ constructor |
|
36 // --------------------------------------------------------------------------- |
|
37 // |
|
38 CPIMContactItem::CPIMContactItem(const CPIMContactValidator& aContactValidator) : |
|
39 CPIMItem(aContactValidator) |
|
40 { |
|
41 JELOG2(EPim); |
|
42 } |
|
43 |
|
44 // --------------------------------------------------------------------------- |
|
45 // CPIMContactItem::NewL |
|
46 // Default two-phase constructor |
|
47 // --------------------------------------------------------------------------- |
|
48 // |
|
49 CPIMContactItem* CPIMContactItem::NewL( |
|
50 const CPIMContactValidator& aContactValidator) |
|
51 { |
|
52 JELOG2(EPim); |
|
53 CPIMContactItem* self = CPIMContactItem::NewLC(aContactValidator); |
|
54 CleanupStack::Pop(self); |
|
55 |
|
56 return self; |
|
57 } |
|
58 |
|
59 // --------------------------------------------------------------------------- |
|
60 // CPIMContactItem::NewLC |
|
61 // Default two-phase constructor. Leaves the item to the cleanup stack |
|
62 // --------------------------------------------------------------------------- |
|
63 // |
|
64 CPIMContactItem* CPIMContactItem::NewLC( |
|
65 const CPIMContactValidator& aContactValidator) |
|
66 { |
|
67 JELOG2(EPim); |
|
68 CPIMContactItem* self = new(ELeave) CPIMContactItem(aContactValidator); |
|
69 |
|
70 CleanupStack::PushL(self); |
|
71 self->ConstructL(); |
|
72 |
|
73 return self; |
|
74 } |
|
75 |
|
76 pimbaseitem* pimbaseitem::getContactItemInstance(pimbasemanager* aPimManager) |
|
77 { |
|
78 JELOG2(EPim); |
|
79 CPIMManager* pimManager = reinterpret_cast<CPIMManager*>(aPimManager); |
|
80 CPIMContactItem* contactItem = NULL; |
|
81 TInt error = 0; |
|
82 TRAP(error, |
|
83 { |
|
84 const CPIMContactValidator& contactValidator = |
|
85 pimManager->ContactValidator(); |
|
86 contactItem = CPIMContactItem::NewL(contactValidator); |
|
87 } |
|
88 ); |
|
89 if (error != KErrNone) |
|
90 throw KErrGeneral; |
|
91 return contactItem; |
|
92 } |
|
93 |
|
94 // --------------------------------------------------------------------------- |
|
95 // Destructor |
|
96 // --------------------------------------------------------------------------- |
|
97 // |
|
98 CPIMContactItem::~CPIMContactItem() |
|
99 { |
|
100 JELOG2(EPim); |
|
101 } |
|
102 |
|
103 // --------------------------------------------------------------------------- |
|
104 // CPIMContactItem::SetContactAdapterAssociation |
|
105 // (other items were commented in a header) |
|
106 // --------------------------------------------------------------------------- |
|
107 // |
|
108 void CPIMContactItem::SetContactAdapterAssociation( |
|
109 MPIMContactAdapterManager* aContactAdapterManager, |
|
110 MPIMContactListAdapter* aContactListAdapter) |
|
111 { |
|
112 JELOG2(EPim); |
|
113 __ASSERT_DEBUG(aContactAdapterManager, User::Panic(KPIMPanicCategory, |
|
114 EPIMPanicNullArgument)); |
|
115 |
|
116 iContactAdapterManager = aContactAdapterManager; |
|
117 iContactListAdapter = aContactListAdapter; |
|
118 |
|
119 SetBaseAdapterAssociation(iContactAdapterManager->GetAdapterManager(), |
|
120 iContactListAdapter ? iContactListAdapter->GetPimListAdapter(): NULL); |
|
121 } |
|
122 |
|
123 // --------------------------------------------------------------------------- |
|
124 // CPIMContactItem::RemoveAdapterAssociation |
|
125 // (other items were commented in a header) |
|
126 // --------------------------------------------------------------------------- |
|
127 // |
|
128 void CPIMContactItem::RemoveAdapterAssociation() |
|
129 { |
|
130 JELOG2(EPim); |
|
131 iContactAdapterManager = NULL; |
|
132 iContactListAdapter = NULL; |
|
133 |
|
134 CPIMItem::RemoveAdapterAssociation(); |
|
135 } |
|
136 |
|
137 // --------------------------------------------------------------------------- |
|
138 // CPIMContactItem::ItemType |
|
139 // (other items were commented in a header) |
|
140 // --------------------------------------------------------------------------- |
|
141 // |
|
142 TPIMListType CPIMContactItem::ItemType() const |
|
143 { |
|
144 JELOG2(EPim); |
|
145 return EPIMContactList; |
|
146 } |
|
147 |
|
148 // --------------------------------------------------------------------------- |
|
149 // CPIMContactItem::commit |
|
150 // (other items were commented in a header) |
|
151 // --------------------------------------------------------------------------- |
|
152 // |
|
153 void CPIMContactItem::commit() |
|
154 { |
|
155 JELOG2(EPim); |
|
156 TInt error = KErrNone; |
|
157 TRAP(error, |
|
158 { |
|
159 if (iContactAdapterManager) |
|
160 { |
|
161 // The item is associated with a list |
|
162 if (iContactListAdapter) |
|
163 { |
|
164 // The list is open |
|
165 if (iItemID->Compare(KPIMNullItemID) == 0) |
|
166 { |
|
167 // The item does not have database entry |
|
168 iContactListAdapter->CreateContactItemL(*this); |
|
169 } |
|
170 else |
|
171 { |
|
172 // Make sure that the item is fully loaded from the native |
|
173 // database before committing the changes to it. Note that |
|
174 // already modified fields must not be overwritten by the |
|
175 // responsible list adapter |
|
176 CPIMItem::LoadFullItemL(); |
|
177 iContactListAdapter->WriteContactItemL(*this); |
|
178 } |
|
179 |
|
180 SetModified(EFalse); |
|
181 UpdateUidFieldL(EPIMContactUid, iItemID->Des()); // codescanner::leave |
|
182 } |
|
183 else |
|
184 { |
|
185 // The associated list is closed |
|
186 User::Leave(KErrDisconnected); // codescanner::leave |
|
187 } |
|
188 } |
|
189 else |
|
190 { |
|
191 // The item is not associated with a list |
|
192 User::Leave(KErrDisMounted); // codescanner::leave |
|
193 } |
|
194 } |
|
195 ); |
|
196 if (error != KErrNone) |
|
197 throw error; |
|
198 } |
|
199 |
|
200 // --------------------------------------------------------------------------- |
|
201 // CPIMContactItem::ListClosed |
|
202 // (other items were commented in a header) |
|
203 // --------------------------------------------------------------------------- |
|
204 // |
|
205 void CPIMContactItem::ListClosed() |
|
206 { |
|
207 JELOG2(EPim); |
|
208 iContactListAdapter = NULL; |
|
209 CPIMItem::ListClosed(); |
|
210 } |
|
211 |
|
212 // --------------------------------------------------------------------------- |
|
213 // CPIMContactItem::SetPreferredIndexStringL |
|
214 // (other items were commented in a header) |
|
215 // --------------------------------------------------------------------------- |
|
216 // |
|
217 void CPIMContactItem::SetPreferredIndexStringL(const TPIMField& aField, |
|
218 const TInt& aIndex, TPIMAttribute aAttribute) |
|
219 { |
|
220 JELOG2(EPim); |
|
221 const TInt numValues = iItemData->CountValues(aField); |
|
222 |
|
223 // Clear "preferred index" attribute from all values of the field |
|
224 for (TInt i = 0; i < numValues; i++) |
|
225 { |
|
226 TPIMAttribute attributes = iItemData->AttributesL(aField, i); |
|
227 // Clear attributes |
|
228 attributes &= ~aAttribute; |
|
229 iItemData->SetAttributesL(aField, i, attributes); |
|
230 } |
|
231 |
|
232 // Set "preferred index" attribute to the given value of the field |
|
233 TPIMAttribute preferredIndexAttributes = iItemData->AttributesL( |
|
234 aField, aIndex); |
|
235 // Add preferred index attribute to this attribute set |
|
236 preferredIndexAttributes |= aAttribute; |
|
237 iItemData->SetAttributesL(aField, aIndex, preferredIndexAttributes); |
|
238 } |
|
239 |
|
240 // --------------------------------------------------------------------------- |
|
241 // CPIMContactItem::AddStringL |
|
242 // (other items were commented in a header) |
|
243 // --------------------------------------------------------------------------- |
|
244 // |
|
245 void CPIMContactItem::AddStringL(TPIMField aField, |
|
246 TPIMAttribute aAttributes, HBufC* aValue) |
|
247 { |
|
248 JELOG2(EPim); |
|
249 CPIMItem::AddStringL(aField, aAttributes, aValue); |
|
250 |
|
251 // If we got this far without leaving, the last value in the field is the |
|
252 // new one. Let's see if it has the preferred index set, and clear the |
|
253 // preferred index from any other values. |
|
254 |
|
255 const TInt lastValueIndex = iItemData->CountValues(aField) - 1; |
|
256 TPIMAttribute lastValueAttributes = iItemData->AttributesL(aField, |
|
257 lastValueIndex); |
|
258 |
|
259 // Set preferred attribute |
|
260 if (lastValueAttributes & EPIMContactAttrPreferred) |
|
261 { |
|
262 SetPreferredIndexStringL(aField, lastValueIndex, |
|
263 EPIMContactAttrPreferred); |
|
264 } |
|
265 // Set preferred SMS attribute |
|
266 if (lastValueAttributes & EPIMContactAttrSms) |
|
267 { |
|
268 SetPreferredIndexStringL(aField, lastValueIndex, |
|
269 EPIMContactAttrSms); |
|
270 } |
|
271 } |
|
272 |
|
273 // --------------------------------------------------------------------------- |
|
274 // CPIMContactItem::SetStringL |
|
275 // (other items were commented in a header) |
|
276 // --------------------------------------------------------------------------- |
|
277 // |
|
278 void CPIMContactItem::SetStringL(TPIMField aField, TInt aIndex, |
|
279 TPIMAttribute aAttributes, HBufC* aValue) |
|
280 { |
|
281 JELOG2(EPim); |
|
282 CPIMItem::SetStringL(aField, aIndex, aAttributes, aValue); |
|
283 |
|
284 // If we got this far without leaving, the freshly set value in the field |
|
285 // might have preferred index set. If so, we clear the preferred index |
|
286 // from any other values. |
|
287 |
|
288 TPIMAttribute realValueAttributes = iItemData->AttributesL(aField, |
|
289 aIndex); |
|
290 |
|
291 // Set preferred attribute |
|
292 if (realValueAttributes & EPIMContactAttrPreferred) |
|
293 { |
|
294 SetPreferredIndexStringL(aField, aIndex, |
|
295 EPIMContactAttrPreferred); |
|
296 } |
|
297 // Set preferred SMS attribute |
|
298 if (realValueAttributes & EPIMContactAttrSms) |
|
299 { |
|
300 SetPreferredIndexStringL(aField, aIndex, EPIMContactAttrSms); |
|
301 } |
|
302 } |
|
303 |
|
304 // --------------------------------------------------------------------------- |
|
305 // CPIMContactItem::SetContactItemIdL |
|
306 // (other items were commented in a header) |
|
307 // --------------------------------------------------------------------------- |
|
308 // |
|
309 void CPIMContactItem::SetContactItemIdL( |
|
310 const TPIMItemID& aContactItemId) |
|
311 { |
|
312 JELOG2(EPim); |
|
313 // Set item id for the base class |
|
314 CPIMItem::SetIdL(aContactItemId); |
|
315 |
|
316 // Update UID field if it is supported by this contact item |
|
317 if (iAdapterManager && iAdapterManager->IsSupportedField( |
|
318 EPIMContactUid)) |
|
319 { |
|
320 UpdateUidFieldL(EPIMContactUid, aContactItemId); |
|
321 } |
|
322 } |
|
323 |
|
324 // --------------------------------------------------------------------------- |
|
325 // CPIMContactItem::SetContactItemIdL |
|
326 // (other items were commented in a header) |
|
327 // --------------------------------------------------------------------------- |
|
328 // |
|
329 void CPIMContactItem::SetContactItemIdL(const TUint aContactItemId) |
|
330 { |
|
331 JELOG2(EPim); |
|
332 TBuf8<KPIMItemIdDesSize> entryId; |
|
333 entryId.Num(static_cast<TUint>(aContactItemId)); |
|
334 |
|
335 // Set item id for the base class |
|
336 CPIMItem::SetIdL(entryId); |
|
337 |
|
338 // Update UID field if it is supported by this contact item |
|
339 if (iAdapterManager && iAdapterManager->IsSupportedField( |
|
340 EPIMContactUid)) |
|
341 { |
|
342 UpdateUidFieldL(EPIMContactUid, entryId); |
|
343 } |
|
344 } |
|
345 |
|
346 // --------------------------------------------------------------------------- |
|
347 // CPIMContactItem::ContactItemId |
|
348 // (other items were commented in a header) |
|
349 // --------------------------------------------------------------------------- |
|
350 // |
|
351 TUint CPIMContactItem::ContactItemIdL() const |
|
352 { |
|
353 JELOG2(EPim); |
|
354 // Return zero if there is no contact item id |
|
355 if (CPIMItem::GetId() == KPIMNullItemID) |
|
356 { |
|
357 return 0; |
|
358 } |
|
359 // Convert PIM item id to contact database |
|
360 // item id, so it is easier to use |
|
361 TUint id(0); |
|
362 TLex8 lex(iItemID->Des()); |
|
363 TInt status = lex.Val(id); |
|
364 User::LeaveIfError(status); |
|
365 |
|
366 return id; |
|
367 } |
|
368 |
|
369 // --------------------------------------------------------------------------- |
|
370 // CPIMContactItem::SetLastModifiedL |
|
371 // (other items were commented in a header) |
|
372 // --------------------------------------------------------------------------- |
|
373 // |
|
374 void CPIMContactItem::SetLastModifiedL(TPIMDate aLastModified) |
|
375 { |
|
376 JELOG2(EPim); |
|
377 CPIMItem::SetLastModifiedL(aLastModified); |
|
378 // Update revision field if it is supported |
|
379 if (iAdapterManager && iAdapterManager->IsSupportedField( |
|
380 EPIMContactRevision)) |
|
381 { |
|
382 UpdateRevisionFieldL(EPIMContactRevision, LastModified()); |
|
383 } |
|
384 } |
|
385 |
|
386 // --------------------------------------------------------------------------- |
|
387 // CPIMContactItem::PrepareForLoadL |
|
388 // (other items were commented in a header) |
|
389 // --------------------------------------------------------------------------- |
|
390 // |
|
391 void CPIMContactItem::PrepareForLoadL() |
|
392 { |
|
393 JELOG2(EPim); |
|
394 // Prepare base class for loading from the database |
|
395 CPIMItem::PrepareForLoadL(); |
|
396 } |
|
397 |
|
398 // --------------------------------------------------------------------------- |
|
399 // CPIMContactItem::IsReadOnly |
|
400 // (other items were commented in a header) |
|
401 // --------------------------------------------------------------------------- |
|
402 // |
|
403 TBool CPIMContactItem::IsReadOnly(const TPIMField& aField) |
|
404 { |
|
405 JELOG2(EPim); |
|
406 TBool retVal = EFalse; |
|
407 |
|
408 // UID and REVISION fields are read-only if the item |
|
409 // has been persisted |
|
410 if (aField == EPIMContactUid || aField == EPIMContactRevision) |
|
411 { |
|
412 retVal = (iItemID->Compare(KPIMNullItemID) != 0); |
|
413 } |
|
414 |
|
415 return retVal; |
|
416 } |
|
417 |
|
418 // --------------------------------------------------------------------------- |
|
419 // CPIMContactItem::DoLoadFullItemL |
|
420 // (other items were commented in a header) |
|
421 // --------------------------------------------------------------------------- |
|
422 // |
|
423 void CPIMContactItem::DoLoadFullItemL() |
|
424 { |
|
425 JELOG2(EPim); |
|
426 __ASSERT_DEBUG(iInitializedFields || iContactListAdapter, |
|
427 User::Panic(KPIMPanicCategory, EPIMPanicInvalidState)); |
|
428 |
|
429 // Read full contact item from the adapter. It means that all possible |
|
430 // fields are added to this item and the item becomes full. |
|
431 TRAPD(err, iContactListAdapter->ReadContactItemL(*this)); |
|
432 // KErrNotFound indicates that item has been removed and we need to return |
|
433 // only those fields which are currently in the item |
|
434 __ASSERT_ALWAYS((err == KErrNone) || (err == KErrNotFound), |
|
435 User::Leave(err)); |
|
436 // Reset initialized field to mark that the item is fully loaded |
|
437 delete iInitializedFields; |
|
438 iInitializedFields = NULL; |
|
439 } |
|
440 |
|
441 // --------------------------------------------------------------------------- |
|
442 // CPIMContactItem::DoLoadFieldL |
|
443 // (other items were commented in a header) |
|
444 // --------------------------------------------------------------------------- |
|
445 // |
|
446 void CPIMContactItem::DoLoadFieldL(const TPIMField aField) |
|
447 { |
|
448 JELOG2(EPim); |
|
449 __ASSERT_DEBUG(iInitializedFields || iContactListAdapter, |
|
450 User::Panic(KPIMPanicCategory, EPIMPanicInvalidState)); |
|
451 |
|
452 // Note that revision and uid can not be loaded separately. Those fields |
|
453 // will be added to the item when it is generated and associated with a list |
|
454 if (aField != EPIMContactRevision && aField != EPIMContactUid) |
|
455 { |
|
456 iContactListAdapter->ReadContactFieldL(*this, |
|
457 static_cast<TPIMContactField>(aField)); |
|
458 } |
|
459 |
|
460 // The field is now read form the adapter, so we add it to the list |
|
461 // because there is no need to load this field anymore |
|
462 iInitializedFields->AppendL(aField); |
|
463 } |
|
464 |
|
465 // --------------------------------------------------------------------------- |
|
466 // CPIMContactItem::GetItemData |
|
467 // (other items were commented in a header) |
|
468 // --------------------------------------------------------------------------- |
|
469 // |
|
470 MPIMItemData& CPIMContactItem::ItemData() |
|
471 { |
|
472 JELOG2(EPim); |
|
473 return *iItemData; |
|
474 } |
|
475 |
|
476 // --------------------------------------------------------------------------- |
|
477 // CPIMContactItem::GetItemData |
|
478 // (other items were commented in a header) |
|
479 // --------------------------------------------------------------------------- |
|
480 // |
|
481 const MPIMItemData& CPIMContactItem::ItemData() const |
|
482 { |
|
483 JELOG2(EPim); |
|
484 return *iItemData; |
|
485 } |
|
486 |
|
487 // --------------------------------------------------------------------------- |
|
488 // CPIMContactItem::GetPreferredIndex |
|
489 // (other items were commented in a header) |
|
490 // --------------------------------------------------------------------------- |
|
491 // |
|
492 |
|
493 int CPIMContactItem::getPreferredIndex(TPIMField aField) const |
|
494 { |
|
495 JELOG2(EPim); |
|
496 TInt error = KErrNone; |
|
497 int retVal = 0; |
|
498 TRAP(error, |
|
499 { |
|
500 LeaveIfInvalidOrUnsupportedFieldL(aField); |
|
501 retVal = DoGetPreferredIndexL(aField); |
|
502 }); |
|
503 if (error != KErrNone) |
|
504 throw error; |
|
505 return retVal; |
|
506 } |
|
507 |
|
508 // --------------------------------------------------------------------------- |
|
509 // CPIMContactItem::DoGetPreferredIndexL |
|
510 // (other items were commented in a header) |
|
511 // --------------------------------------------------------------------------- |
|
512 // |
|
513 TInt CPIMContactItem::DoGetPreferredIndexL(const TPIMField& aField) const |
|
514 { |
|
515 JELOG2(EPim); |
|
516 const TPIMFieldDataType fieldType = fieldDataType(aField); |
|
517 |
|
518 // Check that the field is valid |
|
519 if (EPIMFieldInvalid == fieldType) |
|
520 { |
|
521 User::Leave(KErrArgument); |
|
522 } |
|
523 |
|
524 // The field is valid. If it is not a string field, it cannot have |
|
525 // preferred index (in the Nokia implementation). |
|
526 switch (fieldType) |
|
527 { |
|
528 case EPIMFieldString: |
|
529 { |
|
530 // Search through values of the field |
|
531 TInt count = iItemData->CountValues(aField); |
|
532 |
|
533 for (TInt i = 0; i < count; i++) |
|
534 { |
|
535 TPIMAttribute attributes = iItemData->AttributesL( |
|
536 aField, i); |
|
537 if ((attributes & EPIMContactAttrPreferred) != 0) |
|
538 { |
|
539 return i; |
|
540 } |
|
541 } |
|
542 return KPIMNoPreferredIndex; |
|
543 } |
|
544 default: |
|
545 { |
|
546 // Not supported. |
|
547 // We must not leave, but just ignore the query and return |
|
548 // "not set". |
|
549 return KPIMNoPreferredIndex; |
|
550 } |
|
551 } |
|
552 } |
|
553 |
|
554 // End of File |