|
1 /* |
|
2 * Copyright (c) 2002 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: |
|
15 * Provides methods for UI control of phonebook "Contact Info View". |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include "CPbkContactInfoControl.h" // Class declarations |
|
22 |
|
23 #include <barsread.h> // TResourceReader |
|
24 #include <akntitle.h> // CAknTitlePane |
|
25 #include <aknlists.h> // CAknDoubleGraphicStyleListBox |
|
26 #include <cntdef.h> |
|
27 #include <AknsConstants.h> |
|
28 #include <AknDef.h> // KEikDynamicLayoutVariantSwitch |
|
29 #include <bautils.h> |
|
30 |
|
31 #include <PbkDebug.h> |
|
32 #include <PbkView.rsg> // View resources |
|
33 #include <PbkView.hrh> |
|
34 #include "CPbkViewState.h" |
|
35 #include "CPbkThumbnailPopup.h" |
|
36 #include "CPbkFieldListBoxModel.h" |
|
37 #include <CPbkIconArray.h> |
|
38 |
|
39 #include <CPbkExtGlobals.h> |
|
40 #include <MPbkExtensionFactory.h> |
|
41 |
|
42 // PbkEng.dll |
|
43 #include <CPbkContactEngine.h> |
|
44 #include <CPbkFieldInfo.h> |
|
45 #include <CPbkContactItem.h> |
|
46 |
|
47 |
|
48 /// Unnamed namespace for local definitions |
|
49 namespace { |
|
50 |
|
51 // LOCAL CONSTANTS AND MACROS |
|
52 enum TPanicCode |
|
53 { |
|
54 EPanicPreCond_CurrentField = 1, |
|
55 EPanicLogic_CurrentField, |
|
56 EPanicPostCond_Constructor, |
|
57 EPanicPreCond_ConstructFromResourceL, |
|
58 EPanicPostCond_ConstructFromResourceL, |
|
59 EPanicInvalidListBoxType, |
|
60 EPanicPreCond_ContactItem, |
|
61 EPanicPreCond_CurrentFieldIndex, |
|
62 EPanicPostCond_CurrentFieldIndex, |
|
63 EPanicPreCond_FieldPos, // 10 |
|
64 EPanicPreCond_UpdateL, |
|
65 EPanicPostCond_UpdateL, |
|
66 EPanicPreCond_OfferKeyEventL, |
|
67 EPanicPreCond_SizeChanged, |
|
68 EPanicPreCond_CountComponentControls, |
|
69 EPanicPreCond_ComponentControl, |
|
70 EPanicPreCond_FieldCount, |
|
71 EPanicPreCond_ListBox |
|
72 }; |
|
73 |
|
74 void Panic(TInt aReason) |
|
75 { |
|
76 _LIT(KPanicText, "CPbkContactInfoControl"); |
|
77 User::Panic(KPanicText, aReason); |
|
78 } |
|
79 |
|
80 } // namespace |
|
81 |
|
82 // MODULE DATA STRUCTURES |
|
83 |
|
84 /** |
|
85 * listbox item drawer for CPbkContactInfoControl. |
|
86 */ |
|
87 NONSHARABLE_CLASS(CPbkContactInfoControl::CItemDrawer) : |
|
88 public CFormattedCellListBoxItemDrawer |
|
89 { |
|
90 public: // interface |
|
91 /** |
|
92 * Constructor. |
|
93 */ |
|
94 inline CItemDrawer(MTextListBoxModel* aTextListBoxModel, |
|
95 const CFont* aFont, |
|
96 CFormattedCellListBoxData* aFormattedCellData); |
|
97 |
|
98 /** |
|
99 * Sets iFields to aFields. |
|
100 */ |
|
101 inline void SetFields(const CPbkFieldArray& aFields); |
|
102 |
|
103 private: // from CListItemDrawer |
|
104 TListItemProperties Properties(TInt aItemIndex) const; |
|
105 |
|
106 private: // data members |
|
107 /// Ref: array of fields. |
|
108 const CPbkFieldArray* iFields; |
|
109 }; |
|
110 |
|
111 /** |
|
112 * Listbox for CPbkContactInfoControl |
|
113 */ |
|
114 NONSHARABLE_CLASS(CPbkContactInfoControl::CListBox) : |
|
115 public CAknFormDoubleGraphicStyleListBox |
|
116 { |
|
117 public: // constructor |
|
118 inline CListBox(); |
|
119 inline CItemDrawer* ItemDrawer() const; |
|
120 inline void SetIconArray(CPbkIconArray* aIconArray); |
|
121 inline CPbkIconArray* IconArray(); |
|
122 public: // from CEikFormattedCellListBox |
|
123 void CreateItemDrawerL(); |
|
124 |
|
125 }; |
|
126 |
|
127 /** |
|
128 * Data holding helper class for CPbkContactInfoControl::UpdateL(). |
|
129 */ |
|
130 NONSHARABLE_CLASS(CPbkContactInfoControl::CUpdateData) : |
|
131 public CBase |
|
132 { |
|
133 public: // Interface |
|
134 // Compiler-generated default constructor is ok for this class |
|
135 ~CUpdateData(); |
|
136 |
|
137 /** |
|
138 * Saves data into this object which restores aListBox's state (model, |
|
139 * top and current item index) in this objects destructor. |
|
140 */ |
|
141 void StoreListBoxState(CEikTextListBox& aListBox); |
|
142 |
|
143 /** |
|
144 * Resets any data set with StoreListBoxState(). |
|
145 */ |
|
146 inline void ResetListBoxState(); |
|
147 |
|
148 public: // Data |
|
149 CPbkFieldArray* iFieldArray; |
|
150 HBufC* iTitlePaneText; |
|
151 CPbkThumbnailPopup* iThumbnailHandler; |
|
152 MDesCArray* iListBoxModel; |
|
153 |
|
154 private: // Data |
|
155 CEikTextListBox* iListBox; |
|
156 MDesCArray* iItemTextArray; |
|
157 TInt iRestoreTopItem; |
|
158 TInt iRestoreCurrentItem; |
|
159 }; |
|
160 |
|
161 |
|
162 /** |
|
163 * Helper class for UpdateL module test. |
|
164 */ |
|
165 NONSHARABLE_CLASS(CPbkContactInfoControl::CUpdateTestData) : |
|
166 public CBase |
|
167 { |
|
168 public: // Interface |
|
169 void ConstructL(CPbkContactInfoControl& aControl); |
|
170 ~CUpdateTestData(); |
|
171 TBool Compare(CPbkContactInfoControl& aControl) const; |
|
172 |
|
173 private: // Data |
|
174 CPbkContactItem* iContactItem; |
|
175 TInt iTopIndex; |
|
176 TInt iCurrentIndex; |
|
177 CAknTitlePane* iTitlePane; |
|
178 HBufC* iTitlePaneText; |
|
179 CPbkFieldArray* iFieldArray; |
|
180 CPbkThumbnailPopup* iThumbnailHandler; |
|
181 }; |
|
182 |
|
183 // ==================== LOCAL FUNCTIONS ==================== |
|
184 |
|
185 template<class Type> |
|
186 inline void Swap(Type& aObj1, Type& aObj2) |
|
187 { |
|
188 Type tmp = aObj1; |
|
189 aObj1 = aObj2; |
|
190 aObj2 = tmp; |
|
191 } |
|
192 |
|
193 |
|
194 // ================= MEMBER FUNCTIONS ======================= |
|
195 inline |
|
196 CPbkContactInfoControl::CItemDrawer::CItemDrawer |
|
197 (MTextListBoxModel* aTextListBoxModel, |
|
198 const CFont* aFont, |
|
199 CFormattedCellListBoxData* aFormattedCellData) : |
|
200 CFormattedCellListBoxItemDrawer( |
|
201 aTextListBoxModel, |
|
202 aFont, |
|
203 aFormattedCellData) |
|
204 { |
|
205 } |
|
206 |
|
207 inline |
|
208 void CPbkContactInfoControl::CItemDrawer::SetFields |
|
209 (const CPbkFieldArray& aFields) |
|
210 { |
|
211 iFields = &aFields; |
|
212 } |
|
213 |
|
214 TListItemProperties CPbkContactInfoControl::CItemDrawer::Properties |
|
215 (TInt aItemIndex) const |
|
216 { |
|
217 TListItemProperties result = |
|
218 CFormattedCellListBoxItemDrawer::Properties(aItemIndex); |
|
219 |
|
220 // TODO: aItemIndex<iFields->Count() and aItemIndex>=0 restrictions below |
|
221 // because class' internal data is corrupted, |
|
222 // probably in CPbkContactInfoControl::UpdateL |
|
223 if (iFields && aItemIndex>=0 && aItemIndex<iFields->Count() && |
|
224 (*iFields)[aItemIndex].DefaultPhoneNumberField()) |
|
225 { |
|
226 // default phonenumber field prompt is underlined |
|
227 result.SetUnderlined(ETrue); |
|
228 } |
|
229 return result; |
|
230 } |
|
231 |
|
232 inline |
|
233 CPbkContactInfoControl::CListBox::CListBox() |
|
234 { |
|
235 } |
|
236 |
|
237 inline |
|
238 CPbkContactInfoControl::CItemDrawer* CPbkContactInfoControl::CListBox::ItemDrawer |
|
239 ( ) const |
|
240 { |
|
241 return static_cast<CPbkContactInfoControl::CItemDrawer*>(CAknDoubleGraphicStyleListBox::ItemDrawer()); |
|
242 } |
|
243 |
|
244 inline |
|
245 void CPbkContactInfoControl::CListBox::SetIconArray(CPbkIconArray* aIconArray) |
|
246 { |
|
247 ItemDrawer()->ColumnData()->SetIconArray(aIconArray); |
|
248 } |
|
249 |
|
250 inline |
|
251 CPbkIconArray* CPbkContactInfoControl::CListBox::IconArray() |
|
252 { |
|
253 return static_cast<CPbkIconArray*>(ItemDrawer()->ColumnData()->IconArray()); |
|
254 } |
|
255 |
|
256 void CPbkContactInfoControl::CListBox::CreateItemDrawerL() |
|
257 { |
|
258 CFormattedCellListBoxData* formattedData = CFormattedCellListBoxData::NewL(); |
|
259 CleanupStack::PushL(formattedData); |
|
260 iItemDrawer = new(ELeave) CPbkContactInfoControl::CItemDrawer(Model(), iEikonEnv->NormalFont(), formattedData); |
|
261 CleanupStack::Pop(); |
|
262 } |
|
263 |
|
264 CPbkContactInfoControl::CUpdateData::~CUpdateData() |
|
265 { |
|
266 if (iListBox) |
|
267 { |
|
268 iListBox->Model()->SetItemTextArray(iItemTextArray); |
|
269 if (iRestoreTopItem >= 0) iListBox->SetTopItemIndex(iRestoreTopItem); |
|
270 if (iRestoreCurrentItem >= 0) iListBox->SetCurrentItemIndex(iRestoreCurrentItem); |
|
271 } |
|
272 delete iThumbnailHandler; |
|
273 delete iTitlePaneText; |
|
274 delete iListBoxModel; |
|
275 delete iFieldArray; |
|
276 } |
|
277 |
|
278 void CPbkContactInfoControl::CUpdateData::StoreListBoxState |
|
279 (CEikTextListBox& aListBox) |
|
280 { |
|
281 iListBox = &aListBox; |
|
282 iItemTextArray = iListBox->Model()->ItemTextArray(); |
|
283 iRestoreTopItem = iListBox->TopItemIndex(); |
|
284 iRestoreCurrentItem = iListBox->CurrentItemIndex(); |
|
285 } |
|
286 |
|
287 inline void CPbkContactInfoControl::CUpdateData::ResetListBoxState() |
|
288 { |
|
289 iListBox = NULL; |
|
290 } |
|
291 |
|
292 EXPORT_C CPbkContactInfoControl* CPbkContactInfoControl::NewL |
|
293 (TInt aResId, |
|
294 const CCoeControl& aParent, |
|
295 CPbkContactItem* aContact, |
|
296 CPbkContactEngine* aEngine) |
|
297 { |
|
298 CPbkContactInfoControl* self = new(ELeave) CPbkContactInfoControl; |
|
299 CleanupStack::PushL(self); |
|
300 |
|
301 self->iContactEngine = aEngine; |
|
302 self->SetContainerWindowL(aParent); |
|
303 |
|
304 TResourceReader reader; |
|
305 self->iCoeEnv->CreateResourceReaderLC(reader, aResId); |
|
306 self->ConstructFromResourceL(reader); |
|
307 CleanupStack::PopAndDestroy(); // reader |
|
308 |
|
309 self->UpdateL(aContact); |
|
310 CleanupStack::Pop(); // self |
|
311 return self; |
|
312 } |
|
313 |
|
314 CPbkContactInfoControl::CPbkContactInfoControl() |
|
315 { |
|
316 iShowThumbnail = ETrue; |
|
317 // new(ELeave) will reset member data |
|
318 __ASSERT_DEBUG( |
|
319 !iListBox && iFlags==0 && !iFields && !iContactItem && !iThumbnailHandler, |
|
320 Panic(EPanicPostCond_Constructor)); |
|
321 } |
|
322 |
|
323 void CPbkContactInfoControl::ConstructFromResourceL(TResourceReader& aReader) |
|
324 { |
|
325 __ASSERT_DEBUG( |
|
326 !iListBox && !iListBoxModel && iFlags==0 && !iFields && !iContactItem && !iThumbnailHandler, |
|
327 Panic(EPanicPreCond_ConstructFromResourceL)); |
|
328 |
|
329 TPtrC emptyText = aReader.ReadTPtrC(); |
|
330 iFlags = aReader.ReadUint32(); |
|
331 const TInt listBoxType = aReader.ReadInt16(); |
|
332 // It is no more possible to specify the listbox type from resource file |
|
333 __ASSERT_ALWAYS(listBoxType == EAknCtDoubleGraphicListBox, |
|
334 Panic(EPanicInvalidListBoxType)); |
|
335 |
|
336 iListBox = new(ELeave) CListBox; |
|
337 iListBox->SetContainerWindowL(*this); |
|
338 iListBox->ConstructFromResourceL(aReader); |
|
339 iListBox->View()->SetListEmptyTextL(emptyText); |
|
340 |
|
341 // Load list box icons |
|
342 TInt iconArrayRes = aReader.ReadInt32(); |
|
343 // Use granularity of 4 |
|
344 CPbkIconArray* iconArray = new(ELeave) CPbkIconArray(4); |
|
345 CleanupStack::PushL(iconArray); |
|
346 iconArray->ConstructFromResourceL(iconArrayRes); |
|
347 |
|
348 // get extension factory for setting extension icons |
|
349 CPbkExtGlobals* extGlobal = CPbkExtGlobals::InstanceL(); |
|
350 extGlobal->PushL(); |
|
351 MPbkExtensionFactory& factory = extGlobal->FactoryL(); |
|
352 factory.AddPbkFieldIconsL(NULL, iconArray); |
|
353 CleanupStack::PopAndDestroy(extGlobal); |
|
354 |
|
355 CleanupStack::Pop(); // iconArray |
|
356 iListBox->SetIconArray(iconArray); |
|
357 |
|
358 iDefaultIconId = static_cast<TPbkIconId>(aReader.ReadInt32()); |
|
359 |
|
360 // Set up the listbox |
|
361 iListBox->CreateScrollBarFrameL(ETrue); |
|
362 iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto); |
|
363 // Take ownership of default listbox model |
|
364 iListBoxModel = iListBox->Model()->ItemTextArray(); |
|
365 iListBox->Model()->SetOwnershipType(ELbmDoesNotOwnItemArray); |
|
366 |
|
367 __ASSERT_DEBUG( |
|
368 iListBox && iListBoxModel && !iFields && !iContactItem && !iThumbnailHandler, |
|
369 Panic(EPanicPostCond_ConstructFromResourceL)); |
|
370 } |
|
371 |
|
372 CPbkContactInfoControl::~CPbkContactInfoControl() |
|
373 { |
|
374 delete iMarkedItemsArray; |
|
375 delete iThumbnailHandler; |
|
376 delete iListBox; |
|
377 delete iListBoxModel; |
|
378 delete iFields; |
|
379 } |
|
380 |
|
381 void CPbkContactInfoControl::UpdateL(CPbkContactItem* aContact) |
|
382 { |
|
383 // PreCond: |
|
384 __ASSERT_DEBUG(aContact && iListBox, Panic(EPanicPreCond_UpdateL)); |
|
385 |
|
386 iVoiceTagField = NULL; |
|
387 iVoiceTagFetchCompleted = EFalse; |
|
388 |
|
389 CUpdateData* updateData = new(ELeave) CUpdateData; |
|
390 CleanupStack::PushL(updateData); |
|
391 updateData->iFieldArray = new(ELeave) CPbkFieldArray(8); // granularity of 8 |
|
392 |
|
393 CheckRingToneFieldL( aContact ); |
|
394 |
|
395 const TInt fieldCount = aContact->CardFields().Count(); |
|
396 for (TInt i = 0; i < fieldCount; ++i) |
|
397 { |
|
398 TPbkContactItemField& field = aContact->CardFields()[i]; |
|
399 if (!field.IsHidden() && // Don't show hidden fields |
|
400 !field.IsEmptyOrAllSpaces() && // Don't show empty fields |
|
401 // Don't show name fields unless specfied by flags |
|
402 ((iFlags & KPbkContactInfoControlShowNameFields) || !field.FieldInfo().NameField()) && |
|
403 // Don't show image fields unless specfied by flags |
|
404 ((iFlags & KPbkContactInfoControlShowImageFields) || !field.FieldInfo().IsImageField())) |
|
405 { |
|
406 updateData->iFieldArray->AppendL(field); |
|
407 } |
|
408 } |
|
409 |
|
410 CEikStatusPane* statusPane = iEikonEnv->AppUiFactory()->StatusPane(); |
|
411 CAknTitlePane* titlePane = NULL; |
|
412 if (statusPane && (iFlags & KPbkContactInfoControlUpdateStatusPane)) |
|
413 { |
|
414 if ((iFlags & KPbkContactInfoControlUpdateTitlePane) && |
|
415 statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidTitle)).IsPresent()) |
|
416 { |
|
417 titlePane = static_cast<CAknTitlePane*>(statusPane->ControlL(TUid::Uid(EEikStatusPaneUidTitle))); |
|
418 updateData->iTitlePaneText = aContact->GetContactTitleOrNullL(); |
|
419 if (!updateData->iTitlePaneText) |
|
420 { |
|
421 updateData->iTitlePaneText = iCoeEnv->AllocReadResourceL(R_QTN_PHOB_UNNAMED); |
|
422 } |
|
423 } |
|
424 if ( (iFlags & KPbkContactInfoControlUpdateContextPane) && iShowThumbnail ) |
|
425 { |
|
426 updateData->iThumbnailHandler = CPbkThumbnailPopup::NewL(*iContactEngine); |
|
427 updateData->iThumbnailHandler->Load(*aContact, iListBox ); |
|
428 } |
|
429 } |
|
430 |
|
431 // Contact must be set before setting listbox |
|
432 iContactItem = aContact; |
|
433 |
|
434 // Update list box |
|
435 HBufC* timeFormat = iCoeEnv->AllocReadResourceLC(R_QTN_DATE_USUAL); |
|
436 |
|
437 CPbkFieldListBoxModel::TParams params( |
|
438 *updateData->iFieldArray, |
|
439 *timeFormat, |
|
440 *iListBox->IconArray()); |
|
441 params.iDefaultIconId = iDefaultIconId; |
|
442 params.iFieldAnalyzer = this; |
|
443 |
|
444 CPbkFieldListBoxModel* listBoxModel = CPbkFieldListBoxModel::NewL(params); |
|
445 CleanupStack::PopAndDestroy(); // timeFormat |
|
446 listBoxModel->SetClipper(*this); |
|
447 updateData->iListBoxModel = listBoxModel; |
|
448 updateData->StoreListBoxState(*iListBox); |
|
449 iListBox->Model()->SetItemTextArray(updateData->iListBoxModel); |
|
450 iListBox->Reset(); |
|
451 iListBox->UpdateScrollBarsL(); |
|
452 |
|
453 // All code that might leave has been executed succesfully |
|
454 // -> Change state and redraw. |
|
455 updateData->ResetListBoxState(); |
|
456 Swap(iFields, updateData->iFieldArray); |
|
457 Swap(iListBoxModel, updateData->iListBoxModel); |
|
458 iListBox->ItemDrawer()->SetFields(*iFields); |
|
459 iContactItem = aContact; |
|
460 if (titlePane && updateData->iTitlePaneText) |
|
461 { |
|
462 titlePane->SetText(updateData->iTitlePaneText); |
|
463 updateData->iTitlePaneText = NULL; |
|
464 } |
|
465 Swap(iThumbnailHandler, updateData->iThumbnailHandler); |
|
466 |
|
467 // Cleanup |
|
468 CleanupStack::PopAndDestroy(); // updateData |
|
469 |
|
470 __ASSERT_DEBUG(iListBox && iContactItem && iFields && iListBoxModel, Panic(EPanicPostCond_UpdateL)); |
|
471 __ASSERT_DEBUG(iContactItem->CardFields().Count() >= iFields->Count(), Panic(EPanicPostCond_UpdateL)); |
|
472 __ASSERT_DEBUG(&static_cast<CPbkFieldListBoxModel*>(iListBoxModel)->Array() == iFields, Panic(EPanicPostCond_UpdateL)); |
|
473 __ASSERT_DEBUG(iListBox->Model()->ItemTextArray() == iListBoxModel, Panic(EPanicPostCond_UpdateL)); |
|
474 __ASSERT_DEBUG(iListBox->Model()->NumberOfItems() == iFields->Count(), Panic(EPanicPostCond_UpdateL)); |
|
475 } |
|
476 |
|
477 CPbkContactItem& CPbkContactInfoControl::ContactItem() |
|
478 { |
|
479 __ASSERT_DEBUG(iContactItem, Panic(EPanicPreCond_ContactItem)); |
|
480 return *iContactItem; |
|
481 } |
|
482 |
|
483 TPbkContactItemField* CPbkContactInfoControl::CurrentField() const |
|
484 { |
|
485 // PreCond: |
|
486 __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_CurrentField)); |
|
487 |
|
488 const TInt index = iListBox->CurrentItemIndex(); |
|
489 // CPbkFieldArray will check index |
|
490 if (index >= 0) |
|
491 { |
|
492 __ASSERT_DEBUG(index < iFields->Count(), Panic(EPanicLogic_CurrentField)); |
|
493 return &(*iFields)[index]; |
|
494 } |
|
495 else |
|
496 { |
|
497 return NULL; |
|
498 } |
|
499 } |
|
500 |
|
501 EXPORT_C TInt CPbkContactInfoControl::CurrentFieldIndex |
|
502 ( ) const |
|
503 { |
|
504 // PreCond: |
|
505 __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_CurrentFieldIndex)); |
|
506 |
|
507 const TPbkContactItemField* currentField = CurrentField(); |
|
508 // Initialize the index to surely errornous value |
|
509 TInt index = -1; |
|
510 if (currentField) |
|
511 { |
|
512 // Search the field in the stored fields array |
|
513 index = iContactItem->FindFieldIndex(*currentField); |
|
514 // Field must be found |
|
515 __ASSERT_DEBUG(index >= 0, Panic(EPanicPostCond_CurrentFieldIndex)); |
|
516 } |
|
517 return index; |
|
518 } |
|
519 |
|
520 EXPORT_C TInt CPbkContactInfoControl::FieldPos(const TPbkContactItemField& aField) |
|
521 { |
|
522 // PreCond: |
|
523 __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_FieldPos)); |
|
524 |
|
525 for (TInt i = 0; i < iFields->Count(); ++i) |
|
526 { |
|
527 if ((*iFields)[i].IsSame(aField)) |
|
528 { |
|
529 // aField found |
|
530 return i; |
|
531 } |
|
532 } |
|
533 |
|
534 // aField not found |
|
535 return -1; |
|
536 } |
|
537 |
|
538 EXPORT_C TInt CPbkContactInfoControl::FieldCount() const |
|
539 { |
|
540 // PreCond: |
|
541 __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_FieldCount)); |
|
542 |
|
543 return iFields->Count(); |
|
544 } |
|
545 |
|
546 EXPORT_C CPbkViewState* CPbkContactInfoControl::GetStateL() const |
|
547 { |
|
548 CPbkViewState* state = GetStateLC(); |
|
549 CleanupStack::Pop(); // state |
|
550 return state; |
|
551 } |
|
552 |
|
553 EXPORT_C CPbkViewState* CPbkContactInfoControl::GetStateLC() const |
|
554 { |
|
555 CPbkViewState* state = CPbkViewState::NewLC(); |
|
556 state->SetFocusedContactId(iContactItem->Id()); |
|
557 if (iListBox->Model()->NumberOfItems() > 0) |
|
558 { |
|
559 state->SetFocusedFieldIndex(CurrentFieldIndex()); |
|
560 const TInt topIndex = iListBox->TopItemIndex(); |
|
561 if (topIndex >= 0) |
|
562 { |
|
563 const TPbkContactItemField& topField = (*iFields)[topIndex]; |
|
564 state->SetTopFieldIndex(iContactItem->FindFieldIndex(topField)); |
|
565 } |
|
566 } |
|
567 return state; |
|
568 } |
|
569 |
|
570 EXPORT_C void CPbkContactInfoControl::RestoreStateL(const CPbkViewState* aState) |
|
571 { |
|
572 const TInt numItems = iListBox->Model()->NumberOfItems(); |
|
573 if (aState && numItems > 0) |
|
574 { |
|
575 TInt focusIndex = 0; |
|
576 TInt topIndex = 0; |
|
577 const TInt height = iListBox->View()->NumberOfItemsThatFitInRect(iListBox->View()->ViewRect()); |
|
578 |
|
579 // The index of field to-be-focused depends on whether the shown |
|
580 // contact is the latest contact that has been shown in ContactInfo. |
|
581 // For re-opened contacts the focus is same as before the ContactInfo |
|
582 // was closed. For new contact the first POC field should be focused. |
|
583 if (aState->FocusedFieldIndex() == -1) |
|
584 { |
|
585 // "New" contact. Set focus to first POC field |
|
586 for (TInt i = 0; i < iFields->Count(); i++) |
|
587 { |
|
588 if ((*iFields)[i].FieldInfo().IsPocField()) |
|
589 { |
|
590 focusIndex = i; |
|
591 break; |
|
592 } |
|
593 } |
|
594 // Set top index so that focused field is bottom-most visible field |
|
595 topIndex = Max(focusIndex - height + 1, 0); |
|
596 } |
|
597 else |
|
598 { |
|
599 // "Old" contact. Set focus to previously selected field |
|
600 // Set top item |
|
601 if (aState->TopFieldIndex() >= 0 && aState->TopFieldIndex() < iContactItem->CardFields().Count()) |
|
602 { |
|
603 topIndex = Max(FieldPos(iContactItem->CardFields()[aState->TopFieldIndex()]), 0); |
|
604 } |
|
605 |
|
606 // Set listIndex so that maximum number of items are visible |
|
607 if (topIndex + height > numItems) |
|
608 { |
|
609 topIndex += numItems - (height + topIndex); |
|
610 if (topIndex < 0) topIndex = 0; |
|
611 } |
|
612 |
|
613 // Set focus |
|
614 if (aState->FocusedFieldIndex() >= 0) |
|
615 { |
|
616 if (aState->FocusedFieldIndex() < iContactItem->CardFields().Count()) |
|
617 { |
|
618 focusIndex = Max(FieldPos(iContactItem->CardFields()[aState->FocusedFieldIndex()]), 0); |
|
619 } |
|
620 else |
|
621 { |
|
622 focusIndex = iContactItem->CardFields().Count() - 1; |
|
623 } |
|
624 } |
|
625 } |
|
626 iListBox->SetTopItemIndex(topIndex); |
|
627 |
|
628 // TODO: focusIndex may be invalid e.g. after contact ringing tone |
|
629 // removal/addition. |
|
630 if (focusIndex<0) |
|
631 { |
|
632 focusIndex=0; |
|
633 } |
|
634 else if (focusIndex>=numItems ) |
|
635 { |
|
636 focusIndex=numItems-1; |
|
637 } |
|
638 iListBox->SetCurrentItemIndex(focusIndex); |
|
639 } |
|
640 else |
|
641 { |
|
642 iListBox->Reset(); |
|
643 } |
|
644 iListBox->UpdateScrollBarsL(); |
|
645 } |
|
646 |
|
647 EXPORT_C CEikListBox& CPbkContactInfoControl::ListBox() |
|
648 { |
|
649 __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_ListBox)); |
|
650 return *iListBox; |
|
651 } |
|
652 |
|
653 void CPbkContactInfoControl::HideThumbnail() |
|
654 { |
|
655 iShowThumbnail = EFalse; |
|
656 if (iThumbnailHandler) |
|
657 { |
|
658 iThumbnailHandler->CancelLoading(); |
|
659 } |
|
660 } |
|
661 |
|
662 void CPbkContactInfoControl::ShowThumbnailL() |
|
663 { |
|
664 iShowThumbnail = ETrue; |
|
665 if (iFlags & KPbkContactInfoControlUpdateContextPane) |
|
666 { |
|
667 if (iContactItem) |
|
668 { |
|
669 if (!iThumbnailHandler) |
|
670 { |
|
671 iThumbnailHandler = CPbkThumbnailPopup::NewL(*iContactEngine); |
|
672 } |
|
673 iThumbnailHandler->Load(*iContactItem, iListBox); |
|
674 } |
|
675 } |
|
676 } |
|
677 |
|
678 TKeyResponse CPbkContactInfoControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) |
|
679 { |
|
680 __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_OfferKeyEventL)); |
|
681 |
|
682 if ( iThumbnailHandler && |
|
683 (aKeyEvent.iScanCode == EStdKeyUpArrow || aKeyEvent.iScanCode == EStdKeyDownArrow )) |
|
684 { |
|
685 iThumbnailHandler->Refresh(); |
|
686 } |
|
687 // Forward all key events to the list box |
|
688 return iListBox->OfferKeyEventL(aKeyEvent,aType); |
|
689 } |
|
690 |
|
691 TInt CPbkContactInfoControl::NumberOfItems() const |
|
692 { |
|
693 // This control displays only one item |
|
694 return 1; |
|
695 } |
|
696 |
|
697 TBool CPbkContactInfoControl::ItemsMarked() const |
|
698 { |
|
699 // No items can be marked in this control |
|
700 return EFalse; |
|
701 } |
|
702 |
|
703 const CContactIdArray& CPbkContactInfoControl::MarkedItemsL() const |
|
704 { |
|
705 if (!iMarkedItemsArray) |
|
706 { |
|
707 iMarkedItemsArray = CContactIdArray::NewL(); |
|
708 } |
|
709 |
|
710 // Remove old contents of array |
|
711 // (use Remove instead of Reset to keep the array buffer) |
|
712 iMarkedItemsArray->Remove(0,iMarkedItemsArray->Count()); |
|
713 iMarkedItemsArray->AddL(FocusedContactIdL()); |
|
714 |
|
715 return *iMarkedItemsArray; |
|
716 } |
|
717 |
|
718 TContactItemId CPbkContactInfoControl::FocusedContactIdL() const |
|
719 { |
|
720 return iContactItem->Id(); |
|
721 } |
|
722 |
|
723 const TPbkContactItemField* CPbkContactInfoControl::FocusedField() const |
|
724 { |
|
725 return CurrentField(); |
|
726 } |
|
727 |
|
728 MObjectProvider* CPbkContactInfoControl::ObjectProvider() |
|
729 { |
|
730 return this; |
|
731 } |
|
732 |
|
733 TInt CPbkContactInfoControl::FocusedFieldIndex() const |
|
734 { |
|
735 return CurrentFieldIndex(); |
|
736 } |
|
737 |
|
738 TBool CPbkContactInfoControl::ClipFromBeginning(TDes& aBuffer, TInt aItemIndex, TInt aSubCellNumber) |
|
739 { |
|
740 return AknTextUtils::ClipToFit(aBuffer, AknTextUtils::EClipFromBeginning, |
|
741 this->iListBox, aItemIndex, aSubCellNumber); |
|
742 } |
|
743 |
|
744 TBool CPbkContactInfoControl::HasVoiceTagL(const TPbkContactItemField& aField) const |
|
745 { |
|
746 if (!iVoiceTagFetchCompleted) |
|
747 { |
|
748 iVoiceTagField = iContactItem->VoiceTagField(); |
|
749 iVoiceTagFetchCompleted = ETrue; |
|
750 } |
|
751 if (iVoiceTagFetchCompleted && iVoiceTagField) |
|
752 { |
|
753 return (!iVoiceTagField->IsEmptyOrAllSpaces() && iVoiceTagField->IsSame(aField)); |
|
754 } |
|
755 else |
|
756 { |
|
757 return EFalse; |
|
758 } |
|
759 } |
|
760 |
|
761 TBool CPbkContactInfoControl::HasSpeedDialL(const TPbkContactItemField& aField) const |
|
762 { |
|
763 if (!iContactEngine) |
|
764 { |
|
765 return EFalse; |
|
766 } |
|
767 |
|
768 const TInt fieldIndex = iContactItem->FindFieldIndex(aField); |
|
769 |
|
770 // If there is no such a field, KErrNotFound is returned as a |
|
771 // field index. |
|
772 if ( fieldIndex != KErrNotFound ) |
|
773 { |
|
774 return (iContactEngine->IsSpeedDialAssigned(*iContactItem, fieldIndex)); |
|
775 } |
|
776 else |
|
777 { |
|
778 return EFalse; |
|
779 } |
|
780 } |
|
781 |
|
782 void CPbkContactInfoControl::SizeChanged() |
|
783 { |
|
784 __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_SizeChanged)); |
|
785 // Listbox occupies whole area of this control |
|
786 iListBox->SetRect(Rect()); |
|
787 } |
|
788 |
|
789 TInt CPbkContactInfoControl::CountComponentControls() const |
|
790 { |
|
791 __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_CountComponentControls)); |
|
792 // Always only one child control: the list box. |
|
793 return 1; |
|
794 } |
|
795 |
|
796 CCoeControl* CPbkContactInfoControl::ComponentControl(TInt PBK_DEBUG_ONLY(aIndex)) const |
|
797 { |
|
798 __ASSERT_DEBUG(iListBox && aIndex==0, Panic(EPanicPreCond_ComponentControl)); |
|
799 // Return the one and only child control |
|
800 return iListBox; |
|
801 } |
|
802 |
|
803 void CPbkContactInfoControl::HandleResourceChange(TInt aType) |
|
804 { |
|
805 CPbkContactDetailsBaseControl::HandleResourceChange(aType); |
|
806 TRAP_IGNORE(DoHandleResourceChangeL(aType)); |
|
807 } |
|
808 |
|
809 void CPbkContactInfoControl::DoHandleResourceChangeL(TInt aType) |
|
810 { |
|
811 if (aType == KAknsMessageSkinChange || aType == KEikDynamicLayoutVariantSwitch) |
|
812 { |
|
813 CPbkIconArray* iconArray = iListBox->IconArray(); |
|
814 if (iconArray) |
|
815 { |
|
816 iconArray->RefreshL(R_PBK_ICON_INFO_ARRAY); |
|
817 } |
|
818 const TBool isNonFocusing( IsNonFocusing() ); |
|
819 if ( iContactItem ) |
|
820 { |
|
821 if ( !isNonFocusing ) |
|
822 { |
|
823 if (IsFocused()) |
|
824 { |
|
825 iThumbnailHandler->Load(*iContactItem, iListBox); |
|
826 } |
|
827 } |
|
828 } |
|
829 if (aType == KEikDynamicLayoutVariantSwitch) |
|
830 { |
|
831 SizeChanged(); |
|
832 if ( !isNonFocusing ) |
|
833 { |
|
834 if (IsFocused()) |
|
835 { |
|
836 // cause also refreshing of thumbnail |
|
837 ShowThumbnailL(); |
|
838 } |
|
839 } |
|
840 } |
|
841 } |
|
842 } |
|
843 |
|
844 |
|
845 void CPbkContactInfoControl::FocusChanged( TDrawNow aDrawNow ) |
|
846 { |
|
847 CCoeControl::FocusChanged( aDrawNow ); |
|
848 const TBool focused( IsFocused() ); |
|
849 |
|
850 if (focused) |
|
851 { |
|
852 // No big deal if thumbnail is not shown |
|
853 TRAP_IGNORE( ShowThumbnailL() ); |
|
854 } |
|
855 else |
|
856 { |
|
857 HideThumbnail(); |
|
858 } |
|
859 |
|
860 if( iListBox ) |
|
861 { |
|
862 iListBox->SetFocus( IsFocused(), aDrawNow ); |
|
863 } |
|
864 } |
|
865 |
|
866 void CPbkContactInfoControl::CheckRingToneFieldL( CPbkContactItem* aContact ) |
|
867 { |
|
868 // Check is there ringtone field and if there is, check that file is still |
|
869 // available. If not, hide the field. |
|
870 TPbkContactItemField* ringtoneField = |
|
871 aContact->FindField( EPbkFieldIdPersonalRingingToneIndication ); |
|
872 if ( ringtoneField ) |
|
873 { |
|
874 if ( ringtoneField->StorageType()==KStorageTypeText ) |
|
875 { |
|
876 if ( !BaflUtils::FileExists( |
|
877 iContactEngine->FsSession(), |
|
878 ringtoneField->Text()) ) |
|
879 { |
|
880 ringtoneField->SetHidden( ETrue ); |
|
881 } |
|
882 } |
|
883 } |
|
884 } |
|
885 |
|
886 // CPbkContactInfoControl::CUpdateTestData implementation |
|
887 #ifdef __TEST_UpdateL__ |
|
888 void CPbkContactInfoControl::CUpdateTestData::ConstructL(CPbkContactInfoControl& aControl) |
|
889 { |
|
890 iContactItem = aControl.iContactItem; |
|
891 iTopIndex = aControl.iListBox->TopItemIndex(); |
|
892 iCurrentIndex = aControl.iListBox->CurrentItemIndex(); |
|
893 |
|
894 CEikStatusPane* statusPane = static_cast<CEikonEnv*>(aControl.iCoeEnv)->AppUiFactory()->StatusPane(); |
|
895 if (statusPane && statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidTitle)).IsPresent()) |
|
896 { |
|
897 iTitlePane = static_cast<CAknTitlePane*>(statusPane->ControlL(TUid::Uid(EEikStatusPaneUidTitle))); |
|
898 iTitlePaneText = iTitlePane->Text()->AllocL(); |
|
899 } |
|
900 |
|
901 iFieldArray = aControl.iFields; |
|
902 iThumbnailHandler = aControl.iThumbnailHandler; |
|
903 } |
|
904 |
|
905 CPbkContactInfoControl::CUpdateTestData::~CUpdateTestData() |
|
906 { |
|
907 delete iTitlePaneText; |
|
908 } |
|
909 |
|
910 TBool CPbkContactInfoControl::CUpdateTestData::Compare(CPbkContactInfoControl& aControl) const |
|
911 { |
|
912 return |
|
913 iContactItem == aControl.iContactItem && |
|
914 (iTopIndex < 0 || iTopIndex == aControl.iListBox->TopItemIndex()) && |
|
915 (iCurrentIndex < 0 || iCurrentIndex == aControl.iListBox->CurrentItemIndex()) && |
|
916 iTitlePaneText->Compare(*iTitlePane->Text())==0 && |
|
917 iFieldArray == aControl.iFields && |
|
918 (!iFieldArray || iFieldArray == &static_cast<CPbkFieldListBoxModel*>(aControl.iListBoxModel)->Array()) && |
|
919 iThumbnailHandler == aControl.iThumbnailHandler; |
|
920 } |
|
921 #endif |
|
922 |
|
923 // End of File |