|
1 /* |
|
2 * Copyright (c) 2005-2007 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: A operation class for setting/getting speeddial information |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "CSpeedDialAttributeOperation.h" |
|
20 #include "CContactStore.h" |
|
21 #include "TContactField.h" |
|
22 #include "CContact.h" |
|
23 #include "CContactLink.h" |
|
24 |
|
25 #include <CVPbkSpeedDialAttribute.h> |
|
26 |
|
27 #include <MVPbkStoreContactField.h> |
|
28 #include <MVPbkContactAttributeManager.h> |
|
29 #include <MVPbkContactAttribute.h> |
|
30 #include <CVPbkAsyncOperation.h> |
|
31 #include <CVPbkAsyncCallback.h> |
|
32 #include <CVPbkContactManager.h> |
|
33 #include <MVPbkContactStoreList.h> |
|
34 #include <VPbkStoreUriLiterals.h> |
|
35 #include <TVPbkContactStoreUriPtr.h> |
|
36 #include <MVPbkContactFindObserver.h> |
|
37 #include <CVPbkContactLinkArray.h> |
|
38 #include <CVPbkBatchOperation.h> |
|
39 |
|
40 // From Contacts Model |
|
41 #include <cntitem.h> |
|
42 |
|
43 // Debug includes |
|
44 #include <VPbkDebug.h> |
|
45 |
|
46 #ifdef _DEBUG |
|
47 namespace { |
|
48 enum TPanic |
|
49 { |
|
50 EPreCond_FindSpeedDialsL, |
|
51 EPreCond_FindSpeedDialL |
|
52 }; |
|
53 |
|
54 void Panic(TPanic aPanic) |
|
55 { |
|
56 _LIT(KPanicCat, "CSpeedDialAttributeOperation"); |
|
57 User::Panic(KPanicCat, aPanic); |
|
58 } |
|
59 } |
|
60 #endif // _DEBUG |
|
61 |
|
62 namespace VPbkCntModel { |
|
63 |
|
64 const TInt KMinPhoneNumberBufLength = 50; |
|
65 const TInt KMaxPhoneNumberBufLength = 200; |
|
66 |
|
67 static const TInt speedDialUids[] = |
|
68 {0, // to make this array 1-based |
|
69 KUidSpeedDialOneValue, |
|
70 KUidSpeedDialTwoValue, |
|
71 KUidSpeedDialThreeValue, |
|
72 KUidSpeedDialFourValue, |
|
73 KUidSpeedDialFiveValue, |
|
74 KUidSpeedDialSixValue, |
|
75 KUidSpeedDialSevenValue, |
|
76 KUidSpeedDialEightValue, |
|
77 KUidSpeedDialNineValue}; |
|
78 |
|
79 // --------------------------------------------------------------------------- |
|
80 // CSpeedDialAttributeOperation::CSpeedDialAttributeOperation |
|
81 // --------------------------------------------------------------------------- |
|
82 // |
|
83 CSpeedDialAttributeOperation::CSpeedDialAttributeOperation( |
|
84 TOperationMode aOperationMode, |
|
85 CContactStore& aContactStore, |
|
86 MVPbkStoreContactField& aField, |
|
87 MVPbkSetAttributeObserver& aObserver) : |
|
88 iOperationMode(aOperationMode), |
|
89 iContactStore(aContactStore), |
|
90 iField(&aField), |
|
91 iSetObserver(&aObserver) |
|
92 { |
|
93 } |
|
94 |
|
95 // --------------------------------------------------------------------------- |
|
96 // CSpeedDialAttributeOperation::CSpeedDialAttributeOperation |
|
97 // --------------------------------------------------------------------------- |
|
98 // |
|
99 CSpeedDialAttributeOperation::CSpeedDialAttributeOperation( |
|
100 TOperationMode aOperationMode, |
|
101 CContactStore& aContactStore, |
|
102 MVPbkContactFindObserver& aObserver) : |
|
103 iOperationMode(aOperationMode), |
|
104 iContactStore(aContactStore), |
|
105 iFindObserver(&aObserver) |
|
106 { |
|
107 } |
|
108 |
|
109 // --------------------------------------------------------------------------- |
|
110 // CSpeedDialAttributeOperation::ConstructL |
|
111 // --------------------------------------------------------------------------- |
|
112 // |
|
113 void CSpeedDialAttributeOperation::ConstructL( |
|
114 const CVPbkSpeedDialAttribute& aAttribute) |
|
115 { |
|
116 iAsyncOperation = new(ELeave) VPbkEngUtils::CVPbkAsyncOperation; |
|
117 iAttribute = static_cast<CVPbkSpeedDialAttribute*>(aAttribute.CloneLC()); |
|
118 CleanupStack::Pop(); |
|
119 } |
|
120 |
|
121 // --------------------------------------------------------------------------- |
|
122 // CSpeedDialAttributeOperation::NewSetLC |
|
123 // --------------------------------------------------------------------------- |
|
124 // |
|
125 CSpeedDialAttributeOperation* CSpeedDialAttributeOperation::NewSetLC( |
|
126 CContactStore& aContactStore, |
|
127 MVPbkStoreContactField& aField, |
|
128 const CVPbkSpeedDialAttribute& aAttribute, |
|
129 MVPbkSetAttributeObserver& aObserver) |
|
130 { |
|
131 CSpeedDialAttributeOperation* self = new(ELeave) CSpeedDialAttributeOperation( |
|
132 ESet, aContactStore, aField, aObserver); |
|
133 CleanupStack::PushL(self); |
|
134 self->ConstructL(aAttribute); |
|
135 return self; |
|
136 } |
|
137 |
|
138 // --------------------------------------------------------------------------- |
|
139 // CSpeedDialAttributeOperation::NewRemoveLC |
|
140 // --------------------------------------------------------------------------- |
|
141 // |
|
142 CSpeedDialAttributeOperation* CSpeedDialAttributeOperation::NewRemoveLC( |
|
143 CContactStore& aContactStore, |
|
144 MVPbkStoreContactField& aField, |
|
145 const CVPbkSpeedDialAttribute& aAttribute, |
|
146 MVPbkSetAttributeObserver& aObserver) |
|
147 { |
|
148 CSpeedDialAttributeOperation* self = new(ELeave) CSpeedDialAttributeOperation( |
|
149 ERemove, aContactStore, aField, aObserver); |
|
150 CleanupStack::PushL(self); |
|
151 self->ConstructL(aAttribute); |
|
152 return self; |
|
153 } |
|
154 |
|
155 // --------------------------------------------------------------------------- |
|
156 // CSpeedDialAttributeOperation::NewListLC |
|
157 // --------------------------------------------------------------------------- |
|
158 // |
|
159 CSpeedDialAttributeOperation* CSpeedDialAttributeOperation::NewListLC( |
|
160 CContactStore& aContactStore, |
|
161 const CVPbkSpeedDialAttribute& aAttribute, |
|
162 MVPbkContactFindObserver& aObserver) |
|
163 { |
|
164 CSpeedDialAttributeOperation* self = new(ELeave) CSpeedDialAttributeOperation( |
|
165 EList, aContactStore, aObserver); |
|
166 CleanupStack::PushL(self); |
|
167 self->ConstructL(aAttribute); |
|
168 return self; |
|
169 } |
|
170 |
|
171 // --------------------------------------------------------------------------- |
|
172 // CSpeedDialAttributeOperation::~CSpeedDialAttributeOperation |
|
173 // --------------------------------------------------------------------------- |
|
174 // |
|
175 CSpeedDialAttributeOperation::~CSpeedDialAttributeOperation() |
|
176 { |
|
177 delete iAsyncOperation; |
|
178 delete iAttribute; |
|
179 delete iLinkArray; |
|
180 delete iEmptyOperation; |
|
181 } |
|
182 |
|
183 // --------------------------------------------------------------------------- |
|
184 // From class MVPbkContactOperation |
|
185 // CSpeedDialAttributeOperation::StartL |
|
186 // --------------------------------------------------------------------------- |
|
187 // |
|
188 void CSpeedDialAttributeOperation::StartL() |
|
189 { |
|
190 if (iOperationMode == EList) |
|
191 { |
|
192 VPbkEngUtils::MAsyncCallback* callback = |
|
193 VPbkEngUtils::CreateAsyncCallbackLC( |
|
194 *this, |
|
195 &CSpeedDialAttributeOperation::DoListOperationL, |
|
196 &CSpeedDialAttributeOperation::ListOperationError, |
|
197 *iFindObserver); |
|
198 iAsyncOperation->CallbackL(callback); |
|
199 CleanupStack::Pop(callback); |
|
200 } |
|
201 else |
|
202 { |
|
203 VPbkEngUtils::MAsyncCallback* callback = |
|
204 VPbkEngUtils::CreateAsyncCallbackLC( |
|
205 *this, |
|
206 &CSpeedDialAttributeOperation::DoSetOperationL, |
|
207 &CSpeedDialAttributeOperation::SetOperationError, |
|
208 *iSetObserver); |
|
209 iAsyncOperation->CallbackL(callback); |
|
210 CleanupStack::Pop(callback); |
|
211 } |
|
212 } |
|
213 |
|
214 // --------------------------------------------------------------------------- |
|
215 // From class MVPbkContactOperation |
|
216 // CSpeedDialAttributeOperation::Cancel |
|
217 // --------------------------------------------------------------------------- |
|
218 // |
|
219 void CSpeedDialAttributeOperation::Cancel() |
|
220 { |
|
221 iAsyncOperation->Purge(); |
|
222 } |
|
223 |
|
224 // --------------------------------------------------------------------------- |
|
225 // From class MVPbkBatchOperationObserver |
|
226 // CSpeedDialAttributeOperation::StepComplete |
|
227 // --------------------------------------------------------------------------- |
|
228 // |
|
229 void CSpeedDialAttributeOperation::StepComplete( |
|
230 MVPbkContactOperationBase& /*aOperation*/, |
|
231 TInt /*aStepSize*/ ) |
|
232 { |
|
233 // Do nothing |
|
234 } |
|
235 |
|
236 // --------------------------------------------------------------------------- |
|
237 // From class MVPbkBatchOperationObserver |
|
238 // CSpeedDialAttributeOperation::StepFailed |
|
239 // --------------------------------------------------------------------------- |
|
240 // |
|
241 TBool CSpeedDialAttributeOperation::StepFailed( |
|
242 MVPbkContactOperationBase& /*aOperation*/, |
|
243 TInt /*aStepSize*/, |
|
244 TInt /*aError*/ ) |
|
245 { |
|
246 // Do not continue batch operation. |
|
247 return EFalse; |
|
248 } |
|
249 |
|
250 // --------------------------------------------------------------------------- |
|
251 // From class MVPbkBatchOperationObserver |
|
252 // CSpeedDialAttributeOperation::OperationComplete |
|
253 // --------------------------------------------------------------------------- |
|
254 // |
|
255 void CSpeedDialAttributeOperation::OperationComplete |
|
256 ( MVPbkContactOperationBase& /*aOperation*/ ) |
|
257 { |
|
258 TRAPD( error, HandleOperationCompleteL() ); |
|
259 if ( error != KErrNone ) |
|
260 { |
|
261 // If error has occured, we don't continue. |
|
262 iFindObserver->FindFailed( error ); |
|
263 } |
|
264 } |
|
265 |
|
266 // --------------------------------------------------------------------------- |
|
267 // CSpeedDialAttributeOperation::HandleOperationCompleteL() |
|
268 // --------------------------------------------------------------------------- |
|
269 // |
|
270 void CSpeedDialAttributeOperation::HandleOperationCompleteL() |
|
271 { |
|
272 if ( iAttribute->Index() == |
|
273 CVPbkSpeedDialAttribute::KSpeedDialIndexNotDefined ) |
|
274 { |
|
275 // Find all |
|
276 FindSpeedDialsL(); |
|
277 } |
|
278 else |
|
279 { |
|
280 // Find specified |
|
281 FindSpeedDialL(); |
|
282 } |
|
283 } |
|
284 |
|
285 // --------------------------------------------------------------------------- |
|
286 // CSpeedDialAttributeOperation::DoSetOperationL |
|
287 // --------------------------------------------------------------------------- |
|
288 // |
|
289 void CSpeedDialAttributeOperation::DoSetOperationL( |
|
290 MVPbkSetAttributeObserver& aObserver) |
|
291 { |
|
292 if (&iField->ContactStore() == &iContactStore) |
|
293 { |
|
294 CContact& contact = static_cast<CContact&>(iField->ParentContact()); |
|
295 TContactField& field = static_cast<TContactField&>(*iField); |
|
296 |
|
297 if (iOperationMode == ESet) |
|
298 { |
|
299 TContactItemId cid = contact.NativeContact()->Id(); |
|
300 const TInt nativeFieldIndex = field.NativeFieldIndex(); |
|
301 |
|
302 iContactStore.NativeDatabase().SetFieldAsSpeedDialL( |
|
303 *contact.NativeContact(), |
|
304 nativeFieldIndex, |
|
305 iAttribute->Index()); |
|
306 |
|
307 // SetFieldAsSpeedDialL commits the contact, so we want to load it again |
|
308 CContactItem* contactItem = iContactStore.NativeDatabase().OpenContactL(cid); |
|
309 contact.SetContact(contactItem); |
|
310 // This is called because we want the parent contact's field collection |
|
311 // iCurrentField to be refreshed to point again to this field |
|
312 contact.Fields().FieldAt(nativeFieldIndex); |
|
313 } |
|
314 else if (iOperationMode == ERemove) |
|
315 { |
|
316 if (iAttribute->Index() == CVPbkSpeedDialAttribute::KSpeedDialIndexNotDefined) |
|
317 { |
|
318 for (TInt i = 1; i <= KCntMaxSpeedDialIndex; ++i) |
|
319 { |
|
320 TBuf<KSpeedDialPhoneLength> phoneNumber; |
|
321 TContactItemId cid = |
|
322 iContactStore.NativeDatabase().GetSpeedDialFieldL(i, phoneNumber); |
|
323 |
|
324 if (cid == contact.NativeContact()->Id() && |
|
325 field.NativeField()->ContentType().ContainsFieldType( |
|
326 TFieldType::Uid(speedDialUids[i]))) |
|
327 { |
|
328 iContactStore.NativeDatabase().CommitContactL( |
|
329 *contact.NativeContact()); |
|
330 |
|
331 iContactStore.NativeDatabase().RemoveSpeedDialFieldL( |
|
332 contact.NativeContact()->Id(), |
|
333 i); |
|
334 |
|
335 const TInt fieldIndex = NativeFieldIndex(contact, field); |
|
336 // RemoveSpeedDialFieldL commits the contact, so we want to |
|
337 // load it again |
|
338 CContactItem* contactItem = |
|
339 iContactStore.NativeDatabase().OpenContactL(cid); |
|
340 contact.SetContact(contactItem); |
|
341 // This is called because we want the parent contact's field |
|
342 // collection iCurrentField to be refreshed to point again |
|
343 // to this field |
|
344 contact.Fields().FieldAt(fieldIndex); |
|
345 } |
|
346 } |
|
347 } |
|
348 else |
|
349 { |
|
350 const TInt index( iAttribute->Index() ); |
|
351 TBuf<KSpeedDialPhoneLength> phoneNumber; |
|
352 TContactItemId cid = |
|
353 iContactStore.NativeDatabase().GetSpeedDialFieldL( |
|
354 index, phoneNumber); |
|
355 |
|
356 if ( cid == contact.NativeContact()->Id() ) |
|
357 { |
|
358 iContactStore.NativeDatabase().CommitContactL(*contact.NativeContact()); |
|
359 |
|
360 iContactStore.NativeDatabase().RemoveSpeedDialFieldL( cid, index ); |
|
361 |
|
362 const TInt fieldIndex = NativeFieldIndex(contact, field); |
|
363 // RemoveSpeedDialFieldL commits the contact, so we want to load it again |
|
364 CContactItem* contactItem = iContactStore.NativeDatabase().OpenContactL(cid); |
|
365 contact.SetContact(contactItem); |
|
366 // This is called because we want the parent contact's field collection |
|
367 // iCurrentField to be refreshed to point again to this field |
|
368 contact.Fields().FieldAt(fieldIndex); |
|
369 } |
|
370 else |
|
371 { |
|
372 User::Leave( KErrArgument ); |
|
373 } |
|
374 } |
|
375 } |
|
376 } |
|
377 |
|
378 aObserver.AttributeOperationComplete(*this); |
|
379 } |
|
380 |
|
381 // --------------------------------------------------------------------------- |
|
382 // CSpeedDialAttributeOperation::SetOperationError |
|
383 // --------------------------------------------------------------------------- |
|
384 // |
|
385 void CSpeedDialAttributeOperation::SetOperationError( |
|
386 MVPbkSetAttributeObserver& aObserver, |
|
387 TInt aError) |
|
388 { |
|
389 aObserver.AttributeOperationFailed(*this, aError); |
|
390 } |
|
391 |
|
392 // --------------------------------------------------------------------------- |
|
393 // CSpeedDialAttributeOperation::DoListOperationL |
|
394 // --------------------------------------------------------------------------- |
|
395 // |
|
396 void CSpeedDialAttributeOperation::DoListOperationL( |
|
397 MVPbkContactFindObserver& /*aObserver*/) |
|
398 { |
|
399 VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING( |
|
400 "CSpeedDialAttributeOperation::DoListOperationL" ) ); |
|
401 |
|
402 if ( iEmptyOperation ) |
|
403 { |
|
404 delete iEmptyOperation; |
|
405 iEmptyOperation = NULL; |
|
406 } |
|
407 |
|
408 if ( iLinkArray ) |
|
409 { |
|
410 delete iLinkArray; |
|
411 iLinkArray = NULL; |
|
412 } |
|
413 |
|
414 iEmptyOperation = CVPbkBatchOperation::NewLC( *this ); |
|
415 CleanupStack::Pop( iEmptyOperation ); |
|
416 iEmptyOperation->StartL(); |
|
417 |
|
418 VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING( |
|
419 "CSpeedDialAttributeOperation::DoListOperationL end" ) ); |
|
420 } |
|
421 |
|
422 // --------------------------------------------------------------------------- |
|
423 // CSpeedDialAttributeOperation::ListOperationError |
|
424 // --------------------------------------------------------------------------- |
|
425 // |
|
426 void CSpeedDialAttributeOperation::ListOperationError( |
|
427 MVPbkContactFindObserver& aObserver, |
|
428 TInt aError) |
|
429 { |
|
430 aObserver.FindFailed(aError); |
|
431 } |
|
432 |
|
433 // --------------------------------------------------------------------------- |
|
434 // CSpeedDialAttributeOperation::NativeFieldIndex |
|
435 // --------------------------------------------------------------------------- |
|
436 // |
|
437 TInt CSpeedDialAttributeOperation::NativeFieldIndex( CContact& aContact, |
|
438 TContactField& aField ) const |
|
439 { |
|
440 TInt result = KErrNotFound; |
|
441 |
|
442 CContactItemFieldSet& fields = aContact.NativeContact()->CardFields(); |
|
443 const TInt count = fields.Count(); |
|
444 for (TInt i = 0; i < count; ++i) |
|
445 { |
|
446 if (&fields[i] == aField.NativeField()) |
|
447 { |
|
448 result = i; |
|
449 break; |
|
450 } |
|
451 } |
|
452 |
|
453 return result; |
|
454 } |
|
455 |
|
456 // --------------------------------------------------------------------------- |
|
457 // CSpeedDialAttributeOperation::FindSpeedDialsL |
|
458 // Find all contacst that have speed dial |
|
459 // --------------------------------------------------------------------------- |
|
460 // |
|
461 void CSpeedDialAttributeOperation::FindSpeedDialsL() |
|
462 { |
|
463 __ASSERT_DEBUG( iAttribute->Index() == |
|
464 CVPbkSpeedDialAttribute::KSpeedDialIndexNotDefined, |
|
465 Panic( EPreCond_FindSpeedDialsL ) ); |
|
466 |
|
467 // Symbian GetSpeedDialFieldL documentation defines these |
|
468 const TInt firstSpeedDialIndex = 1; |
|
469 const TInt lastSpeedDialIndex = 9; |
|
470 |
|
471 CVPbkContactLinkArray* results = CVPbkContactLinkArray::NewLC(); |
|
472 for ( TInt i = firstSpeedDialIndex; i <= lastSpeedDialIndex; ++i ) |
|
473 { |
|
474 CContactLink* link = DoFindSpeedDialLC( i ); |
|
475 if ( link ) |
|
476 { |
|
477 results->AppendL( link ); |
|
478 CleanupStack::Pop( link ); |
|
479 } |
|
480 } |
|
481 CleanupStack::Pop( results ); |
|
482 iFindObserver->FindCompleteL( results ); |
|
483 } |
|
484 |
|
485 // --------------------------------------------------------------------------- |
|
486 // CSpeedDialAttributeOperation::FindSpeedDialL |
|
487 // Find contact for specified speed dial index |
|
488 // --------------------------------------------------------------------------- |
|
489 // |
|
490 void CSpeedDialAttributeOperation::FindSpeedDialL() |
|
491 { |
|
492 __ASSERT_DEBUG( iAttribute->Index() != |
|
493 CVPbkSpeedDialAttribute::KSpeedDialIndexNotDefined, |
|
494 Panic( EPreCond_FindSpeedDialL ) ); |
|
495 |
|
496 CVPbkContactLinkArray* results = CVPbkContactLinkArray::NewLC(); |
|
497 CContactLink* link = DoFindSpeedDialLC( iAttribute->Index() ); |
|
498 if ( link ) |
|
499 { |
|
500 results->AppendL( link ); |
|
501 CleanupStack::Pop( link ); |
|
502 } |
|
503 CleanupStack::Pop( results ); |
|
504 iFindObserver->FindCompleteL( results ); |
|
505 } |
|
506 |
|
507 // --------------------------------------------------------------------------- |
|
508 // CSpeedDialAttributeOperation::DoFindSpeedDialLC |
|
509 // Returns a link if speed dial was set, otherwise NULL (not in CleanupStack) |
|
510 // --------------------------------------------------------------------------- |
|
511 // |
|
512 CContactLink* CSpeedDialAttributeOperation::DoFindSpeedDialLC( TInt aIndex ) |
|
513 { |
|
514 VPBK_DEBUG_PRINT( VPBK_DEBUG_STRING( |
|
515 "CSpeedDialAttributeOperation::FindSpeedDialL index %d)" ), aIndex ); |
|
516 |
|
517 const TInt doubleFactor = 2; |
|
518 TInt bufSize = KMinPhoneNumberBufLength; |
|
519 TContactItemId cid = KNullContactId; |
|
520 TBool speedDialFound = EFalse; |
|
521 // Contacts model responds with KErrOverflow if the buffer is too small |
|
522 // Grow the buffer until it's big enough. |
|
523 do |
|
524 { |
|
525 HBufC* tmp = HBufC::NewLC( bufSize ); |
|
526 TPtr tmpPtr( tmp->Des() ); |
|
527 // Get native contact id from Contacts Model |
|
528 cid = iContactStore.NativeDatabase().GetSpeedDialFieldL( aIndex, |
|
529 tmpPtr ); |
|
530 if ( cid == KErrOverflow ) |
|
531 { |
|
532 // Double the size of the buffer |
|
533 bufSize *= doubleFactor; |
|
534 } |
|
535 else if ( tmpPtr.Length() > 0 ) |
|
536 { |
|
537 // Symbian documentation says that if the speed dial hasn't been |
|
538 // set then tmpPtr should be KNullDesC |
|
539 speedDialFound = ETrue; |
|
540 } |
|
541 CleanupStack::PopAndDestroy( tmp ); |
|
542 } |
|
543 while ( ( cid == KErrOverflow ) && ( bufSize <= KMaxPhoneNumberBufLength ) ); |
|
544 |
|
545 CContactLink* result = NULL; |
|
546 if ( speedDialFound ) |
|
547 { |
|
548 result = CContactLink::NewLC( iContactStore, cid ); |
|
549 } |
|
550 |
|
551 return result; |
|
552 } |
|
553 } // namespace VPbkCntModel |
|
554 |
|
555 // End of File |