|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <cntview.h> |
|
17 #include "CNTSTD.H" |
|
18 #include <cntitem.h> |
|
19 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
20 #include "cnthint.h" |
|
21 #endif |
|
22 |
|
23 |
|
24 //#define CNTVIEW_API_PROFILING |
|
25 |
|
26 // To see the diferences between class versions check the in source documentation of TContactViewEvent |
|
27 const TUint KClassVersion1 = 1; |
|
28 const TUint KClassVersion2 = 2; |
|
29 |
|
30 |
|
31 CContactGroupView::CContactGroupView(const CContactDatabase& aDb,CContactViewBase& aView,TGroupType aGroupType) |
|
32 :CContactViewBase(aDb),iGroupId(KErrNotFound),iView(aView),iGroupType(aGroupType), iClassVersion(KClassVersion1) |
|
33 {} |
|
34 |
|
35 CContactGroupView::~CContactGroupView() |
|
36 /** Destructor */ |
|
37 { |
|
38 iView.Close(*this); |
|
39 iGroupContacts.Close(); |
|
40 } |
|
41 |
|
42 EXPORT_C CContactGroupView* CContactGroupView::NewL(const CContactDatabase& aDb,CContactViewBase& aView,MContactViewObserver& aObserver,const TContactItemId aGroupId,const TGroupType aGroupType) |
|
43 /** Allocates and constructs a CContactGroupView version 1 object, identifying the group |
|
44 by its ID. |
|
45 |
|
46 A group with the specified ID must exist in the database, otherwise when an |
|
47 attempt is made to update the view, a leave will occur with KErrNotFound. To |
|
48 create an unfiled view, the group id must be KNullContactId and the group type |
|
49 'EShowContactsNotInAnyGroup'. In this case the group id isn't used and no leave |
|
50 will occur. |
|
51 |
|
52 When adding contacts in the view, MContactViewObserver observer will receive |
|
53 TContactViewEvent events with iInt parameter set to KErrNone. |
|
54 When deleting contacts in the view, MContactViewObserver observer will receive |
|
55 TContactViewEvent events with iInt parameter set to index into the observed view of the deleted item |
|
56 |
|
57 |
|
58 @param aDb The database containing the contact group. |
|
59 @param aView The underlying view. |
|
60 @param aObserver An observer that receives notifications when this view is |
|
61 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady |
|
62 event when the view is ready. An attempt to use the view before this notification |
|
63 causes a panic. |
|
64 @param aGroupId The ID of the contact group. |
|
65 @param aGroupType Controls whether the view displays items belonging to the |
|
66 group, items that do not belong to the group or items that do not belong to |
|
67 any group. |
|
68 @return The newly constructed group view object. */ |
|
69 { |
|
70 #ifdef CNTVIEW_API_PROFILING |
|
71 RDebug::Print(_L("[CNTMODEL] CContactGroupView::NewL(Group Id %u)\n"), aGroupId); |
|
72 #endif |
|
73 CContactGroupView* self=new(ELeave) CContactGroupView(aDb,aView,aGroupType); |
|
74 CleanupStack::PushL(self); |
|
75 self->ConstructL(aObserver,aGroupId); |
|
76 CleanupStack::Pop(self); |
|
77 return self; |
|
78 } |
|
79 |
|
80 EXPORT_C CContactGroupView* CContactGroupView::NewL(const CContactDatabase& aDb,CContactViewBase& aView,MContactViewObserver& aObserver,const TDesC& aGroupName,const TGroupType aGroupType) |
|
81 /** Allocates and constructs a CContactGroupView version 1 object, identifying the group |
|
82 by its label. |
|
83 |
|
84 A group with the specified label must exist in the database, otherwise when |
|
85 an attempt is made to update the view, a leave will occur with KErrNotFound. |
|
86 |
|
87 When adding contacts in the view, MContactViewObserver observer will receive |
|
88 TContactViewEvent events with iInt parameter set to KErrNone. |
|
89 When deleting contacts in the view, MContactViewObserver observer will receive |
|
90 TContactViewEvent events with iInt parameter set to index into the observed view of the deleted item |
|
91 |
|
92 |
|
93 @param aDb The database containing the contact group. |
|
94 @param aView The underlying view. |
|
95 @param aObserver An observer that receives notifications when this view is |
|
96 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady |
|
97 event when the view is ready. An attempt to use the view before this notification |
|
98 causes a panic. |
|
99 @param aGroupName The group label. |
|
100 @param aGroupType Controls whether the view displays items belonging to the |
|
101 group, items that do not belong to the group or items that do not belong to |
|
102 any group. |
|
103 @return The newly constructed group view object. */ |
|
104 { |
|
105 #ifdef CNTVIEW_API_PROFILING |
|
106 RDebug::Print(_L("[CNTMODEL] CContactGroupView::NewL(Group Name \"%s\")\n"), &aGroupName); |
|
107 #endif |
|
108 CContactGroupView* self=new(ELeave) CContactGroupView(aDb,aView,aGroupType); |
|
109 CleanupStack::PushL(self); |
|
110 TContactItemId groupId = self->GetGroupIdbyNameL(aGroupName); |
|
111 self->ConstructL(aObserver,groupId); |
|
112 CleanupStack::Pop(self); |
|
113 return self; |
|
114 } |
|
115 EXPORT_C CContactGroupView* CContactGroupView::NewL(CContactViewBase& aView,const CContactDatabase& aDb, MContactViewObserver& aObserver,const TContactItemId aGroupId,const TGroupType aGroupType) |
|
116 /** Allocates and constructs a CContactGroupView version 2 object, identifying the group |
|
117 by its ID. |
|
118 |
|
119 A group with the specified ID must exist in the database, otherwise when an |
|
120 attempt is made to update the view, a leave will occur with KErrNotFound. To |
|
121 create an unfiled view, the group id must be KNullContactId and the group type |
|
122 'EShowContactsNotInAnyGroup'. In this case the group id isn't used and no leave |
|
123 will occur. |
|
124 |
|
125 When adding/deleting contacts in the view, MContactViewObserver observer will receive |
|
126 TContactViewEvent events with iInt parameter set to index into the observed view of the added/deleted item |
|
127 |
|
128 @param aDb The database containing the contact group. |
|
129 @param aView The underlying view. |
|
130 @param aObserver An observer that receives notifications when this view is |
|
131 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady |
|
132 event when the view is ready. An attempt to use the view before this notification |
|
133 causes a panic. |
|
134 @param aGroupId The ID of the contact group. |
|
135 @param aGroupType Controls whether the view displays items belonging to the |
|
136 group, items that do not belong to the group or items that do not belong to |
|
137 any group. |
|
138 @return The newly constructed group view object. */ |
|
139 { |
|
140 #ifdef CNTVIEW_API_PROFILING |
|
141 RDebug::Print(_L("[CNTMODEL] CContactGroupView::NewL(Group Id %u)\n"), aGroupId); |
|
142 #endif |
|
143 CContactGroupView* self=new(ELeave) CContactGroupView(aDb,aView,aGroupType); |
|
144 CleanupStack::PushL(self); |
|
145 self->ConstructL(aObserver,aGroupId); |
|
146 self->iClassVersion = KClassVersion2; |
|
147 CleanupStack::Pop(self); |
|
148 return self; |
|
149 } |
|
150 |
|
151 EXPORT_C CContactGroupView* CContactGroupView::NewL(CContactViewBase& aView, const CContactDatabase& aDb, MContactViewObserver& aObserver,const TDesC& aGroupName,const TGroupType aGroupType) |
|
152 /** Allocates and constructs a CContactGroupView version 2 object, identifying the group |
|
153 by its label. |
|
154 |
|
155 A group with the specified label must exist in the database, otherwise when |
|
156 an attempt is made to update the view, a leave will occur with KErrNotFound. |
|
157 |
|
158 When adding/deleting contacts in the view, MContactViewObserver observer will receive |
|
159 TContactViewEvent events with iInt parameter set to index into the observed view of the added/deleted item |
|
160 |
|
161 @param aDb The database containing the contact group. |
|
162 @param aView The underlying view. |
|
163 @param aObserver An observer that receives notifications when this view is |
|
164 ready for use and when changes take place in it. The observer receives a TContactViewEvent::EReady |
|
165 event when the view is ready. An attempt to use the view before this notification |
|
166 causes a panic. |
|
167 @param aGroupName The group label. |
|
168 @param aGroupType Controls whether the view displays items belonging to the |
|
169 group, items that do not belong to the group or items that do not belong to |
|
170 any group. |
|
171 @return The newly constructed group view object. */ |
|
172 { |
|
173 #ifdef CNTVIEW_API_PROFILING |
|
174 RDebug::Print(_L("[CNTMODEL] CContactGroupView::NewL(Group Name \"%s\")\n"), &aGroupName); |
|
175 #endif |
|
176 CContactGroupView* self=new(ELeave) CContactGroupView(aDb,aView,aGroupType); |
|
177 CleanupStack::PushL(self); |
|
178 TContactItemId groupId = self->GetGroupIdbyNameL(aGroupName); |
|
179 self->ConstructL(aObserver,groupId); |
|
180 self->iClassVersion = KClassVersion2; |
|
181 CleanupStack::Pop(self); |
|
182 return self; |
|
183 } |
|
184 |
|
185 |
|
186 |
|
187 /* |
|
188 * Second phase constructor |
|
189 * @param aObserver view observer |
|
190 */ |
|
191 void CContactGroupView::ConstructL(MContactViewObserver& aObserver,const TContactItemId aGroupId) |
|
192 { |
|
193 CContactViewBase::ConstructL(); |
|
194 OpenL(aObserver); |
|
195 iView.OpenL(*this); |
|
196 iGroupId=aGroupId; |
|
197 } |
|
198 |
|
199 // Update iGroupContacts based on group view options |
|
200 EXPORT_C void CContactGroupView::UpdateGroupViewL() |
|
201 /** Populates the group view. |
|
202 |
|
203 Removes any existing items from the group view then searches the underlying |
|
204 view. The group view is repopulated with those items, maintaining the order |
|
205 in which they occur in the underlying view. |
|
206 |
|
207 @leave KErrNotFound The group, identified by the label or ID specified during |
|
208 construction, does not exist in the database. */ |
|
209 { |
|
210 switch(iGroupType) |
|
211 { |
|
212 case EShowContactsInGroup: |
|
213 UpdateForContactsInGroupL(); |
|
214 break; |
|
215 case EShowContactsNotInGroup: |
|
216 iGroupContacts.Reset(); |
|
217 UpdateForContactsNotInThisGroupL(); |
|
218 break; |
|
219 case EShowContactsNotInAnyGroup: |
|
220 iGroupContacts.Reset(); |
|
221 UpdateForUnfiledContactsL(); |
|
222 break; |
|
223 default: |
|
224 ASSERT(EFalse); |
|
225 }; |
|
226 } |
|
227 |
|
228 /* |
|
229 * This is a reserved virtual exported function that is used for BC proofing |
|
230 * against present and future additions of new exported virtual functions. |
|
231 **/ |
|
232 TAny* CContactGroupView::CContactViewBase_Reserved_1(TFunction aFunction,TAny* aParams) |
|
233 { |
|
234 return CContactViewBase::CContactViewBase_Reserved_1(aFunction,aParams); |
|
235 } |
|
236 |
|
237 /* Identify all contacts in the view which are not members of the group */ |
|
238 void CContactGroupView::UpdateForContactsNotInThisGroupL() |
|
239 { |
|
240 CContactGroup* group = STATIC_CAST(CContactGroup*,MUTABLE_CAST(CContactDatabase&,iDb).ReadContactLC(iGroupId)); |
|
241 const CContactIdArray* memberArray = group->ItemsContained(); |
|
242 if (memberArray) |
|
243 { |
|
244 const TInt numContacts=iView.CountL(); |
|
245 TContactIdWithMapping idMapping; |
|
246 TInt insertError=0; |
|
247 for (TInt ii=0;ii<numContacts;++ii) |
|
248 { |
|
249 const TContactItemId id = iView.AtL(ii); |
|
250 if(memberArray->Find(id)==KErrNotFound) |
|
251 { |
|
252 idMapping.iId=id; |
|
253 idMapping.iMapping=ii; |
|
254 |
|
255 TRAPD(err,insertError=iGroupContacts.InsertInOrder(idMapping,TLinearOrder<TContactIdWithMapping>(CompareMappingsL))); |
|
256 User::LeaveIfError(err); |
|
257 User::LeaveIfError(insertError); |
|
258 } |
|
259 } |
|
260 } |
|
261 CleanupStack::PopAndDestroy(group); |
|
262 } |
|
263 |
|
264 /* Identify all members of the group in the view */ |
|
265 void CContactGroupView::UpdateForContactsInGroupL() |
|
266 { |
|
267 CContactGroup* group = STATIC_CAST(CContactGroup*,MUTABLE_CAST(CContactDatabase&,iDb).ReadContactLC(iGroupId)); |
|
268 const CContactIdArray* memberArray = group->ItemsContained(); |
|
269 |
|
270 if (memberArray && iClassVersion == KClassVersion2) |
|
271 { |
|
272 //Simulate members removed event. |
|
273 //We have to do this because the item removed event which arrives after group change event would be filtered out. |
|
274 NotifyRemovedMembersL(memberArray); |
|
275 } |
|
276 |
|
277 iGroupContacts.Reset(); |
|
278 if (memberArray) |
|
279 { |
|
280 UpdateForContactListL(memberArray); |
|
281 } |
|
282 CleanupStack::PopAndDestroy(group); |
|
283 } |
|
284 |
|
285 /* |
|
286 * Identify all "unfiled" contacts in the view. |
|
287 * "Unfiled" contacts are all contacts which do not belong to any group |
|
288 */ |
|
289 void CContactGroupView::UpdateForUnfiledContactsL() |
|
290 { |
|
291 CContactIdArray* unfiled= MUTABLE_CAST(CContactDatabase&,iDb).UnfiledContactsL(); |
|
292 CleanupStack::PushL(unfiled); |
|
293 UpdateForContactListL(unfiled); |
|
294 CleanupStack::PopAndDestroy(unfiled); |
|
295 } |
|
296 |
|
297 /* Iterate through aArray and if they are in the view, add them to iGroupContacts */ |
|
298 void CContactGroupView::UpdateForContactListL(const CContactIdArray* aArray) |
|
299 { |
|
300 const TInt count = aArray->Count(); |
|
301 TInt pos=KErrNotFound; |
|
302 TContactIdWithMapping idMapping; |
|
303 TInt insertError=KErrNone; |
|
304 |
|
305 for (TInt ii=0;ii<count;++ii) |
|
306 { |
|
307 pos = iView.FindL((*aArray)[ii]); |
|
308 if(pos!=KErrNotFound) |
|
309 { |
|
310 idMapping.iId=iView.AtL(pos); |
|
311 idMapping.iMapping=pos; |
|
312 TRAPD(err,insertError=iGroupContacts.InsertInOrder(idMapping,TLinearOrder<TContactIdWithMapping>(CompareMappingsL))); |
|
313 User::LeaveIfError(err); |
|
314 User::LeaveIfError(insertError); |
|
315 } |
|
316 } |
|
317 } |
|
318 |
|
319 |
|
320 /* Static comparision method used for iGroupContacts ordering */ |
|
321 TInt CContactGroupView::CompareMappingsL(const TContactIdWithMapping& aFirst,const TContactIdWithMapping& aSecond) |
|
322 { |
|
323 if(aFirst.iMapping>aSecond.iMapping) |
|
324 { |
|
325 return 1; |
|
326 } |
|
327 if(aFirst.iMapping<aSecond.iMapping) |
|
328 { |
|
329 return -1; |
|
330 } |
|
331 ASSERT(aFirst.iMapping!=aSecond.iMapping); |
|
332 return 0; |
|
333 } |
|
334 |
|
335 /* |
|
336 * Find a group ID given a group name. |
|
337 * @param aGroupName Group name |
|
338 * @return Group Item ID if found, KNullContactItemId if group doesn't exist |
|
339 */ |
|
340 TContactItemId CContactGroupView::GetGroupIdbyNameL(const TDesC& aGroupName) |
|
341 { |
|
342 ASSERT(aGroupName.Length()>0); |
|
343 |
|
344 TContactItemId groupId = KNullContactId; |
|
345 CContactIdArray* groups = iDb.GetGroupIdListL(); |
|
346 CleanupStack::PushL(groups); |
|
347 const TInt groupCount = groups->Count(); |
|
348 for (TInt ii=0;ii<groupCount;++ii) |
|
349 { |
|
350 CContactGroup* group = STATIC_CAST(CContactGroup*,MUTABLE_CAST(CContactDatabase&,iDb).ReadContactLC((*groups)[ii])); |
|
351 if(group->GetGroupLabelL().Compare(aGroupName)==0) |
|
352 { |
|
353 //found Group |
|
354 groupId = (*groups)[ii]; |
|
355 CleanupStack::PopAndDestroy(group); |
|
356 break; |
|
357 } |
|
358 CleanupStack::PopAndDestroy(group); |
|
359 } |
|
360 CleanupStack::PopAndDestroy(groups); |
|
361 |
|
362 return groupId; |
|
363 } |
|
364 |
|
365 /* Handle events from the parent view */ |
|
366 void CContactGroupView::HandleContactViewEvent(const CContactViewBase& aView,const TContactViewEvent& aEvent) |
|
367 { |
|
368 ASSERT(&aView==&iView); |
|
369 TContactViewEvent event=aEvent; |
|
370 TBool notifyObservers = ETrue; |
|
371 TInt err; |
|
372 switch (event.iEventType) |
|
373 { |
|
374 case TContactViewEvent::EUnavailable: |
|
375 case TContactViewEvent::ESortError: |
|
376 case TContactViewEvent::EServerError: |
|
377 iState=ENotReady; |
|
378 break; |
|
379 case TContactViewEvent::ESortOrderChanged: |
|
380 case TContactViewEvent::EReady: |
|
381 { |
|
382 if(&iView==&aView) |
|
383 { |
|
384 TState oldState = iState; |
|
385 iState = EReady; |
|
386 TRAP(err,UpdateGroupViewL()); |
|
387 if(err!=KErrNone) |
|
388 { |
|
389 iState = oldState; |
|
390 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err)); |
|
391 notifyObservers = EFalse; |
|
392 break; |
|
393 } |
|
394 } |
|
395 } |
|
396 break; |
|
397 case TContactViewEvent::EItemAdded: |
|
398 if(&iView==&aView) |
|
399 { |
|
400 TRAP(err, notifyObservers = HandleAddEventL(event)); |
|
401 if(err!=KErrNone) |
|
402 { |
|
403 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err)); |
|
404 notifyObservers = EFalse; |
|
405 break; |
|
406 } |
|
407 } |
|
408 break; |
|
409 case TContactViewEvent::EItemRemoved: |
|
410 if(&iView==&aView) |
|
411 { |
|
412 if (event.iContactId == iGroupId) |
|
413 { |
|
414 // The group which this class represents has been deleted |
|
415 // so we need to re-build. |
|
416 TRAP(err, UpdateGroupViewL()); |
|
417 } |
|
418 else |
|
419 { |
|
420 // Just a single contact has been deleted. |
|
421 TRAP(err, notifyObservers = HandleRemoveEventL(event)); |
|
422 } |
|
423 |
|
424 if(err!=KErrNone) |
|
425 { |
|
426 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err)); |
|
427 notifyObservers = EFalse; |
|
428 break; |
|
429 } |
|
430 } |
|
431 break; |
|
432 case TContactViewEvent::EGroupChanged: |
|
433 { |
|
434 if(aEvent.iContactId==iGroupId || iGroupId==KNullContactId) |
|
435 { |
|
436 // The group which this class represents has changed or this |
|
437 // view represents the "unfiled" group so we need to re-build. |
|
438 TRAP(err,UpdateGroupViewL()); |
|
439 event.iEventType = TContactViewEvent::ESortOrderChanged;//force children views to re-build themselves. |
|
440 //ESortOrderChanged should be changed in future to something like EUnderlyingDataChanged |
|
441 event.iContactId = KNullContactId; |
|
442 if(err!=KErrNone) |
|
443 { |
|
444 NotifyObservers(TContactViewEvent(TContactViewEvent::ESortError,err)); |
|
445 notifyObservers = EFalse; |
|
446 break; |
|
447 } |
|
448 } |
|
449 |
|
450 } |
|
451 break; |
|
452 default: |
|
453 ASSERT(EFalse); |
|
454 } |
|
455 |
|
456 if (notifyObservers) |
|
457 { |
|
458 NotifyObservers(event); |
|
459 } |
|
460 } |
|
461 |
|
462 /* Handles a EItemRemoved event from the underlying view */ |
|
463 TBool CContactGroupView::HandleRemoveEventL(TContactViewEvent& aEvent) |
|
464 { |
|
465 TBool retval = EFalse; |
|
466 TContactIdWithMapping mapping; |
|
467 TInt pos = 0; |
|
468 |
|
469 // check to see if the contact being removed belongs to us, |
|
470 mapping.iMapping = aEvent.iInt; |
|
471 mapping.iId = aEvent.iContactId; |
|
472 pos = iGroupContacts.Find(mapping,TIdentityRelation<TContactIdWithMapping>(IdsEqual)); |
|
473 if ( pos != KErrNotFound ) // contact is a member of our list |
|
474 { |
|
475 retval = ETrue; // inform clients. |
|
476 iGroupContacts.Remove(pos); // remove from our list |
|
477 aEvent.iInt = pos; |
|
478 } |
|
479 |
|
480 UpdateMappingsL(); |
|
481 return retval; |
|
482 } |
|
483 |
|
484 /* Handles a EItemAdded event from the underlying view */ |
|
485 TBool CContactGroupView::HandleAddEventL(TContactViewEvent& aEvent) |
|
486 { |
|
487 TBool retval = ETrue; |
|
488 aEvent.iInt = KErrNone; |
|
489 |
|
490 switch(iGroupType) |
|
491 { |
|
492 case EShowContactsInGroup: |
|
493 case EShowContactsNotInGroup: |
|
494 UpdateGroupViewL(); |
|
495 //Positions have changed in underlying view |
|
496 UpdateMappingsL(); |
|
497 break; |
|
498 |
|
499 |
|
500 case EShowContactsNotInAnyGroup: |
|
501 { |
|
502 retval = HandleAddEventForUnfiledContactsL(aEvent); |
|
503 } |
|
504 break; |
|
505 |
|
506 }; |
|
507 if(retval && iClassVersion == KClassVersion2) //if is the second version of the class put the right values in event |
|
508 { |
|
509 TContactIdWithMapping mapping; |
|
510 mapping.iMapping = aEvent.iInt; |
|
511 mapping.iId = aEvent.iContactId; |
|
512 TInt pos = iGroupContacts.Find(mapping,TIdentityRelation<TContactIdWithMapping>(IdsEqual)); |
|
513 |
|
514 if ( pos != KErrNotFound ) // contact is a member of our list |
|
515 { |
|
516 aEvent.iInt = pos; |
|
517 } |
|
518 else |
|
519 { |
|
520 retval = EFalse; |
|
521 } |
|
522 } |
|
523 |
|
524 return retval; |
|
525 } |
|
526 |
|
527 |
|
528 TInt CContactGroupView::CompareIndexesAllowingDuplicates(const TContactIdWithMapping& aFirst,const TContactIdWithMapping& aSecond) |
|
529 { |
|
530 TInt retval = 0; |
|
531 if (aFirst.iMapping > aSecond.iMapping) retval = 1; |
|
532 if (aFirst.iMapping < aSecond.iMapping) retval = -1; |
|
533 return retval; |
|
534 } |
|
535 |
|
536 |
|
537 TBool CContactGroupView::HandleAddEventForUnfiledContactsL(const TContactViewEvent& aEvent ) |
|
538 { |
|
539 TBool retval = EFalse; |
|
540 TContactIdWithMapping contactIdWithMapping; |
|
541 CContactItem* contact = const_cast<CContactDatabase&>(iDb).ReadContactLC(aEvent.iContactId); |
|
542 |
|
543 |
|
544 // If contact is a group then don't do anything - the add event is of no |
|
545 // consequence. |
|
546 if (contact->Type() == KUidContactGroup) |
|
547 { |
|
548 CleanupStack::PopAndDestroy(contact); |
|
549 // No need to notify observers so return EFalse. |
|
550 return EFalse; |
|
551 } |
|
552 |
|
553 |
|
554 UpdateMappingsL(); |
|
555 |
|
556 const CContactItemPlusGroup* contactCard = static_cast<const CContactCard*>(contact); |
|
557 const CContactIdArray* idArray = contactCard->GroupsJoined(); |
|
558 |
|
559 if (idArray == NULL || idArray->Count() == 0) // |
|
560 { |
|
561 contactIdWithMapping.iId = aEvent.iContactId; |
|
562 |
|
563 // iGroupContacts contains contactIdWithMapping objects which have an index |
|
564 // to the contact item held in the underlying array iView. |
|
565 // The mapping needs to be updated with this index before being added to iGroupContacts. |
|
566 contactIdWithMapping.iMapping = iView.FindL(contactIdWithMapping.iId); |
|
567 |
|
568 iGroupContacts.InsertInOrder(contactIdWithMapping, |
|
569 TLinearOrder<TContactIdWithMapping>(CompareIndexesAllowingDuplicates)); |
|
570 retval = ETrue; |
|
571 } |
|
572 |
|
573 |
|
574 CleanupStack::PopAndDestroy(contact); |
|
575 UpdateMappingsL(); |
|
576 return retval; |
|
577 } |
|
578 |
|
579 /* |
|
580 * Update view mappings. |
|
581 * This is called when an item has been added or removed from the underlying |
|
582 * view and the current mappings are therefore invalid. |
|
583 */ |
|
584 void CContactGroupView::UpdateMappingsL() |
|
585 { |
|
586 TInt updatedViewIndex=KErrNotFound; |
|
587 for (TInt i=0; i < iGroupContacts.Count(); ++i) |
|
588 { |
|
589 const TContactItemId idUpdate = iGroupContacts[i].iId; |
|
590 updatedViewIndex=iView.FindL(idUpdate); |
|
591 if(updatedViewIndex==KErrNotFound) |
|
592 { |
|
593 //local view has removed this contact, so we need to as well. |
|
594 iGroupContacts.Remove(i); |
|
595 i--; |
|
596 continue; |
|
597 } |
|
598 iGroupContacts[i].iMapping=updatedViewIndex; |
|
599 } |
|
600 } |
|
601 |
|
602 TContactItemId CContactGroupView::AtL(TInt aIndex) const |
|
603 /** Gets the contact item ID at the specified view index. |
|
604 |
|
605 @param aIndex Index into the group view. |
|
606 @leave KErrNotFound aIndex is outside the bounds of the array. |
|
607 @return The contact item ID. */ |
|
608 { |
|
609 if(aIndex>=iGroupContacts.Count()) |
|
610 { |
|
611 //Out of Bounds. |
|
612 User::Leave(KErrNotFound); |
|
613 } |
|
614 return (iGroupContacts)[aIndex].iId; |
|
615 } |
|
616 |
|
617 const CViewContact& CContactGroupView::ContactAtL(TInt aIndex) const |
|
618 /** Gets the contact item at the specified view index. |
|
619 |
|
620 @param aIndex Index into the view of the required item. |
|
621 @leave KErrNotFound aIndex is outside the bounds of the array. |
|
622 @return The contact item. */ |
|
623 { |
|
624 if(aIndex>=iGroupContacts.Count()) |
|
625 { |
|
626 //Out of Bounds. |
|
627 User::Leave(KErrNotFound); |
|
628 } |
|
629 return iView.ContactAtL((iGroupContacts)[aIndex].iMapping); |
|
630 } |
|
631 |
|
632 TInt CContactGroupView::CountL() const |
|
633 /** Gets the number of contact item IDs in the group view. |
|
634 |
|
635 @return The number of contact items in the group view. */ |
|
636 { |
|
637 return iGroupContacts.Count(); |
|
638 } |
|
639 |
|
640 TInt CContactGroupView::FindL(TContactItemId aId) const |
|
641 /** Finds the index into the group view of the specified contact item. |
|
642 |
|
643 @param aId The contact item ID to search for. |
|
644 @leave KErrNotReady The view is not ready for use. |
|
645 @return The index of the first matching item in the view or KErrNotFound if |
|
646 no matching item can be found. |
|
647 */ |
|
648 { |
|
649 if (iState != EReady) |
|
650 { |
|
651 User::Leave(KErrNotReady); |
|
652 } |
|
653 TContactIdWithMapping idWithDummyMapping; |
|
654 idWithDummyMapping.iId=aId; |
|
655 return iGroupContacts.Find(idWithDummyMapping,TIdentityRelation<TContactIdWithMapping>(IdsEqual)); |
|
656 } |
|
657 |
|
658 HBufC* CContactGroupView::AllFieldsLC(TInt aIndex,const TDesC& aSeparator) const |
|
659 /** Gets a descriptor containing the contents of all fields in an item in the |
|
660 view. |
|
661 |
|
662 The fields are separated by aSeparator. |
|
663 |
|
664 @param aIndex The index into the view of the contact item. |
|
665 @param aSeparator The string to use to separate the fields. |
|
666 @return Pointer to the contact item descriptor. */ |
|
667 { |
|
668 return iView.AllFieldsLC((iGroupContacts)[aIndex].iMapping,aSeparator); |
|
669 } |
|
670 |
|
671 TContactViewPreferences CContactGroupView::ContactViewPreferences() |
|
672 /** Gets the underlying view's view preferences. |
|
673 |
|
674 @return The view preferences. */ |
|
675 { |
|
676 return iView.ContactViewPreferences(); |
|
677 } |
|
678 |
|
679 const RContactViewSortOrder& CContactGroupView::SortOrderL() const |
|
680 /** Gets the underlying view's sort order. |
|
681 |
|
682 @return The sort order. */ |
|
683 { |
|
684 return iView.SortOrderL(); |
|
685 } |
|
686 |
|
687 void CContactGroupView::NotifyRemovedMembersL(const CContactIdArray* aArray) |
|
688 { |
|
689 |
|
690 TInt count = iGroupContacts.Count(); |
|
691 |
|
692 if(count > aArray->Count()) |
|
693 { |
|
694 TInt pos = KErrNotFound; |
|
695 TContactViewEvent event(TContactViewEvent::EItemRemoved); |
|
696 |
|
697 for(TInt loop = 0;loop < count;++loop) |
|
698 { |
|
699 pos = aArray->Find(iGroupContacts[loop].iId); |
|
700 if(pos != KErrNotFound) |
|
701 { |
|
702 iGroupContacts[loop].iMapping = iView.FindL(iGroupContacts[loop].iId); |
|
703 } |
|
704 } |
|
705 |
|
706 for(TInt loop = 0;loop < count;++loop) |
|
707 { |
|
708 pos = aArray->Find(iGroupContacts[loop].iId); |
|
709 if(pos == KErrNotFound) |
|
710 { |
|
711 event.iContactId = iGroupContacts[loop].iId; |
|
712 event.iInt = loop; |
|
713 iGroupContacts.Remove(loop); |
|
714 --count; |
|
715 --loop; |
|
716 NotifyObservers(event); |
|
717 } |
|
718 } // for |
|
719 } // if |
|
720 } |