phonebookui/Phonebook/View/src/CPbkContactInfoControl.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     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