--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/View/src/CPbkContactInfoControl.cpp Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,923 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Provides methods for UI control of phonebook "Contact Info View".
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbkContactInfoControl.h" // Class declarations
+
+#include <barsread.h> // TResourceReader
+#include <akntitle.h> // CAknTitlePane
+#include <aknlists.h> // CAknDoubleGraphicStyleListBox
+#include <cntdef.h>
+#include <AknsConstants.h>
+#include <AknDef.h> // KEikDynamicLayoutVariantSwitch
+#include <bautils.h>
+
+#include <PbkDebug.h>
+#include <PbkView.rsg> // View resources
+#include <PbkView.hrh>
+#include "CPbkViewState.h"
+#include "CPbkThumbnailPopup.h"
+#include "CPbkFieldListBoxModel.h"
+#include <CPbkIconArray.h>
+
+#include <CPbkExtGlobals.h>
+#include <MPbkExtensionFactory.h>
+
+// PbkEng.dll
+#include <CPbkContactEngine.h>
+#include <CPbkFieldInfo.h>
+#include <CPbkContactItem.h>
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+enum TPanicCode
+ {
+ EPanicPreCond_CurrentField = 1,
+ EPanicLogic_CurrentField,
+ EPanicPostCond_Constructor,
+ EPanicPreCond_ConstructFromResourceL,
+ EPanicPostCond_ConstructFromResourceL,
+ EPanicInvalidListBoxType,
+ EPanicPreCond_ContactItem,
+ EPanicPreCond_CurrentFieldIndex,
+ EPanicPostCond_CurrentFieldIndex,
+ EPanicPreCond_FieldPos, // 10
+ EPanicPreCond_UpdateL,
+ EPanicPostCond_UpdateL,
+ EPanicPreCond_OfferKeyEventL,
+ EPanicPreCond_SizeChanged,
+ EPanicPreCond_CountComponentControls,
+ EPanicPreCond_ComponentControl,
+ EPanicPreCond_FieldCount,
+ EPanicPreCond_ListBox
+ };
+
+void Panic(TInt aReason)
+ {
+ _LIT(KPanicText, "CPbkContactInfoControl");
+ User::Panic(KPanicText, aReason);
+ }
+
+} // namespace
+
+// MODULE DATA STRUCTURES
+
+/**
+ * listbox item drawer for CPbkContactInfoControl.
+ */
+NONSHARABLE_CLASS(CPbkContactInfoControl::CItemDrawer) :
+ public CFormattedCellListBoxItemDrawer
+ {
+ public: // interface
+ /**
+ * Constructor.
+ */
+ inline CItemDrawer(MTextListBoxModel* aTextListBoxModel,
+ const CFont* aFont,
+ CFormattedCellListBoxData* aFormattedCellData);
+
+ /**
+ * Sets iFields to aFields.
+ */
+ inline void SetFields(const CPbkFieldArray& aFields);
+
+ private: // from CListItemDrawer
+ TListItemProperties Properties(TInt aItemIndex) const;
+
+ private: // data members
+ /// Ref: array of fields.
+ const CPbkFieldArray* iFields;
+ };
+
+/**
+ * Listbox for CPbkContactInfoControl
+ */
+NONSHARABLE_CLASS(CPbkContactInfoControl::CListBox) :
+ public CAknFormDoubleGraphicStyleListBox
+ {
+ public: // constructor
+ inline CListBox();
+ inline CItemDrawer* ItemDrawer() const;
+ inline void SetIconArray(CPbkIconArray* aIconArray);
+ inline CPbkIconArray* IconArray();
+ public: // from CEikFormattedCellListBox
+ void CreateItemDrawerL();
+
+ };
+
+/**
+ * Data holding helper class for CPbkContactInfoControl::UpdateL().
+ */
+NONSHARABLE_CLASS(CPbkContactInfoControl::CUpdateData) :
+ public CBase
+ {
+ public: // Interface
+ // Compiler-generated default constructor is ok for this class
+ ~CUpdateData();
+
+ /**
+ * Saves data into this object which restores aListBox's state (model,
+ * top and current item index) in this objects destructor.
+ */
+ void StoreListBoxState(CEikTextListBox& aListBox);
+
+ /**
+ * Resets any data set with StoreListBoxState().
+ */
+ inline void ResetListBoxState();
+
+ public: // Data
+ CPbkFieldArray* iFieldArray;
+ HBufC* iTitlePaneText;
+ CPbkThumbnailPopup* iThumbnailHandler;
+ MDesCArray* iListBoxModel;
+
+ private: // Data
+ CEikTextListBox* iListBox;
+ MDesCArray* iItemTextArray;
+ TInt iRestoreTopItem;
+ TInt iRestoreCurrentItem;
+ };
+
+
+/**
+ * Helper class for UpdateL module test.
+ */
+NONSHARABLE_CLASS(CPbkContactInfoControl::CUpdateTestData) :
+ public CBase
+ {
+ public: // Interface
+ void ConstructL(CPbkContactInfoControl& aControl);
+ ~CUpdateTestData();
+ TBool Compare(CPbkContactInfoControl& aControl) const;
+
+ private: // Data
+ CPbkContactItem* iContactItem;
+ TInt iTopIndex;
+ TInt iCurrentIndex;
+ CAknTitlePane* iTitlePane;
+ HBufC* iTitlePaneText;
+ CPbkFieldArray* iFieldArray;
+ CPbkThumbnailPopup* iThumbnailHandler;
+ };
+
+// ==================== LOCAL FUNCTIONS ====================
+
+template<class Type>
+inline void Swap(Type& aObj1, Type& aObj2)
+ {
+ Type tmp = aObj1;
+ aObj1 = aObj2;
+ aObj2 = tmp;
+ }
+
+
+// ================= MEMBER FUNCTIONS =======================
+inline
+CPbkContactInfoControl::CItemDrawer::CItemDrawer
+ (MTextListBoxModel* aTextListBoxModel,
+ const CFont* aFont,
+ CFormattedCellListBoxData* aFormattedCellData) :
+ CFormattedCellListBoxItemDrawer(
+ aTextListBoxModel,
+ aFont,
+ aFormattedCellData)
+ {
+ }
+
+inline
+void CPbkContactInfoControl::CItemDrawer::SetFields
+ (const CPbkFieldArray& aFields)
+ {
+ iFields = &aFields;
+ }
+
+TListItemProperties CPbkContactInfoControl::CItemDrawer::Properties
+ (TInt aItemIndex) const
+ {
+ TListItemProperties result =
+ CFormattedCellListBoxItemDrawer::Properties(aItemIndex);
+
+ // TODO: aItemIndex<iFields->Count() and aItemIndex>=0 restrictions below
+ // because class' internal data is corrupted,
+ // probably in CPbkContactInfoControl::UpdateL
+ if (iFields && aItemIndex>=0 && aItemIndex<iFields->Count() &&
+ (*iFields)[aItemIndex].DefaultPhoneNumberField())
+ {
+ // default phonenumber field prompt is underlined
+ result.SetUnderlined(ETrue);
+ }
+ return result;
+ }
+
+inline
+CPbkContactInfoControl::CListBox::CListBox()
+ {
+ }
+
+inline
+CPbkContactInfoControl::CItemDrawer* CPbkContactInfoControl::CListBox::ItemDrawer
+ ( ) const
+ {
+ return static_cast<CPbkContactInfoControl::CItemDrawer*>(CAknDoubleGraphicStyleListBox::ItemDrawer());
+ }
+
+inline
+void CPbkContactInfoControl::CListBox::SetIconArray(CPbkIconArray* aIconArray)
+ {
+ ItemDrawer()->ColumnData()->SetIconArray(aIconArray);
+ }
+
+inline
+CPbkIconArray* CPbkContactInfoControl::CListBox::IconArray()
+ {
+ return static_cast<CPbkIconArray*>(ItemDrawer()->ColumnData()->IconArray());
+ }
+
+void CPbkContactInfoControl::CListBox::CreateItemDrawerL()
+ {
+ CFormattedCellListBoxData* formattedData = CFormattedCellListBoxData::NewL();
+ CleanupStack::PushL(formattedData);
+ iItemDrawer = new(ELeave) CPbkContactInfoControl::CItemDrawer(Model(), iEikonEnv->NormalFont(), formattedData);
+ CleanupStack::Pop();
+ }
+
+CPbkContactInfoControl::CUpdateData::~CUpdateData()
+ {
+ if (iListBox)
+ {
+ iListBox->Model()->SetItemTextArray(iItemTextArray);
+ if (iRestoreTopItem >= 0) iListBox->SetTopItemIndex(iRestoreTopItem);
+ if (iRestoreCurrentItem >= 0) iListBox->SetCurrentItemIndex(iRestoreCurrentItem);
+ }
+ delete iThumbnailHandler;
+ delete iTitlePaneText;
+ delete iListBoxModel;
+ delete iFieldArray;
+ }
+
+void CPbkContactInfoControl::CUpdateData::StoreListBoxState
+ (CEikTextListBox& aListBox)
+ {
+ iListBox = &aListBox;
+ iItemTextArray = iListBox->Model()->ItemTextArray();
+ iRestoreTopItem = iListBox->TopItemIndex();
+ iRestoreCurrentItem = iListBox->CurrentItemIndex();
+ }
+
+inline void CPbkContactInfoControl::CUpdateData::ResetListBoxState()
+ {
+ iListBox = NULL;
+ }
+
+EXPORT_C CPbkContactInfoControl* CPbkContactInfoControl::NewL
+ (TInt aResId,
+ const CCoeControl& aParent,
+ CPbkContactItem* aContact,
+ CPbkContactEngine* aEngine)
+ {
+ CPbkContactInfoControl* self = new(ELeave) CPbkContactInfoControl;
+ CleanupStack::PushL(self);
+
+ self->iContactEngine = aEngine;
+ self->SetContainerWindowL(aParent);
+
+ TResourceReader reader;
+ self->iCoeEnv->CreateResourceReaderLC(reader, aResId);
+ self->ConstructFromResourceL(reader);
+ CleanupStack::PopAndDestroy(); // reader
+
+ self->UpdateL(aContact);
+ CleanupStack::Pop(); // self
+ return self;
+ }
+
+CPbkContactInfoControl::CPbkContactInfoControl()
+ {
+ iShowThumbnail = ETrue;
+ // new(ELeave) will reset member data
+ __ASSERT_DEBUG(
+ !iListBox && iFlags==0 && !iFields && !iContactItem && !iThumbnailHandler,
+ Panic(EPanicPostCond_Constructor));
+ }
+
+void CPbkContactInfoControl::ConstructFromResourceL(TResourceReader& aReader)
+ {
+ __ASSERT_DEBUG(
+ !iListBox && !iListBoxModel && iFlags==0 && !iFields && !iContactItem && !iThumbnailHandler,
+ Panic(EPanicPreCond_ConstructFromResourceL));
+
+ TPtrC emptyText = aReader.ReadTPtrC();
+ iFlags = aReader.ReadUint32();
+ const TInt listBoxType = aReader.ReadInt16();
+ // It is no more possible to specify the listbox type from resource file
+ __ASSERT_ALWAYS(listBoxType == EAknCtDoubleGraphicListBox,
+ Panic(EPanicInvalidListBoxType));
+
+ iListBox = new(ELeave) CListBox;
+ iListBox->SetContainerWindowL(*this);
+ iListBox->ConstructFromResourceL(aReader);
+ iListBox->View()->SetListEmptyTextL(emptyText);
+
+ // Load list box icons
+ TInt iconArrayRes = aReader.ReadInt32();
+ // Use granularity of 4
+ CPbkIconArray* iconArray = new(ELeave) CPbkIconArray(4);
+ CleanupStack::PushL(iconArray);
+ iconArray->ConstructFromResourceL(iconArrayRes);
+
+ // get extension factory for setting extension icons
+ CPbkExtGlobals* extGlobal = CPbkExtGlobals::InstanceL();
+ extGlobal->PushL();
+ MPbkExtensionFactory& factory = extGlobal->FactoryL();
+ factory.AddPbkFieldIconsL(NULL, iconArray);
+ CleanupStack::PopAndDestroy(extGlobal);
+
+ CleanupStack::Pop(); // iconArray
+ iListBox->SetIconArray(iconArray);
+
+ iDefaultIconId = static_cast<TPbkIconId>(aReader.ReadInt32());
+
+ // Set up the listbox
+ iListBox->CreateScrollBarFrameL(ETrue);
+ iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
+ // Take ownership of default listbox model
+ iListBoxModel = iListBox->Model()->ItemTextArray();
+ iListBox->Model()->SetOwnershipType(ELbmDoesNotOwnItemArray);
+
+ __ASSERT_DEBUG(
+ iListBox && iListBoxModel && !iFields && !iContactItem && !iThumbnailHandler,
+ Panic(EPanicPostCond_ConstructFromResourceL));
+ }
+
+CPbkContactInfoControl::~CPbkContactInfoControl()
+ {
+ delete iMarkedItemsArray;
+ delete iThumbnailHandler;
+ delete iListBox;
+ delete iListBoxModel;
+ delete iFields;
+ }
+
+void CPbkContactInfoControl::UpdateL(CPbkContactItem* aContact)
+ {
+ // PreCond:
+ __ASSERT_DEBUG(aContact && iListBox, Panic(EPanicPreCond_UpdateL));
+
+ iVoiceTagField = NULL;
+ iVoiceTagFetchCompleted = EFalse;
+
+ CUpdateData* updateData = new(ELeave) CUpdateData;
+ CleanupStack::PushL(updateData);
+ updateData->iFieldArray = new(ELeave) CPbkFieldArray(8); // granularity of 8
+
+ CheckRingToneFieldL( aContact );
+
+ const TInt fieldCount = aContact->CardFields().Count();
+ for (TInt i = 0; i < fieldCount; ++i)
+ {
+ TPbkContactItemField& field = aContact->CardFields()[i];
+ if (!field.IsHidden() && // Don't show hidden fields
+ !field.IsEmptyOrAllSpaces() && // Don't show empty fields
+ // Don't show name fields unless specfied by flags
+ ((iFlags & KPbkContactInfoControlShowNameFields) || !field.FieldInfo().NameField()) &&
+ // Don't show image fields unless specfied by flags
+ ((iFlags & KPbkContactInfoControlShowImageFields) || !field.FieldInfo().IsImageField()))
+ {
+ updateData->iFieldArray->AppendL(field);
+ }
+ }
+
+ CEikStatusPane* statusPane = iEikonEnv->AppUiFactory()->StatusPane();
+ CAknTitlePane* titlePane = NULL;
+ if (statusPane && (iFlags & KPbkContactInfoControlUpdateStatusPane))
+ {
+ if ((iFlags & KPbkContactInfoControlUpdateTitlePane) &&
+ statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidTitle)).IsPresent())
+ {
+ titlePane = static_cast<CAknTitlePane*>(statusPane->ControlL(TUid::Uid(EEikStatusPaneUidTitle)));
+ updateData->iTitlePaneText = aContact->GetContactTitleOrNullL();
+ if (!updateData->iTitlePaneText)
+ {
+ updateData->iTitlePaneText = iCoeEnv->AllocReadResourceL(R_QTN_PHOB_UNNAMED);
+ }
+ }
+ if ( (iFlags & KPbkContactInfoControlUpdateContextPane) && iShowThumbnail )
+ {
+ updateData->iThumbnailHandler = CPbkThumbnailPopup::NewL(*iContactEngine);
+ updateData->iThumbnailHandler->Load(*aContact, iListBox );
+ }
+ }
+
+ // Contact must be set before setting listbox
+ iContactItem = aContact;
+
+ // Update list box
+ HBufC* timeFormat = iCoeEnv->AllocReadResourceLC(R_QTN_DATE_USUAL);
+
+ CPbkFieldListBoxModel::TParams params(
+ *updateData->iFieldArray,
+ *timeFormat,
+ *iListBox->IconArray());
+ params.iDefaultIconId = iDefaultIconId;
+ params.iFieldAnalyzer = this;
+
+ CPbkFieldListBoxModel* listBoxModel = CPbkFieldListBoxModel::NewL(params);
+ CleanupStack::PopAndDestroy(); // timeFormat
+ listBoxModel->SetClipper(*this);
+ updateData->iListBoxModel = listBoxModel;
+ updateData->StoreListBoxState(*iListBox);
+ iListBox->Model()->SetItemTextArray(updateData->iListBoxModel);
+ iListBox->Reset();
+ iListBox->UpdateScrollBarsL();
+
+ // All code that might leave has been executed succesfully
+ // -> Change state and redraw.
+ updateData->ResetListBoxState();
+ Swap(iFields, updateData->iFieldArray);
+ Swap(iListBoxModel, updateData->iListBoxModel);
+ iListBox->ItemDrawer()->SetFields(*iFields);
+ iContactItem = aContact;
+ if (titlePane && updateData->iTitlePaneText)
+ {
+ titlePane->SetText(updateData->iTitlePaneText);
+ updateData->iTitlePaneText = NULL;
+ }
+ Swap(iThumbnailHandler, updateData->iThumbnailHandler);
+
+ // Cleanup
+ CleanupStack::PopAndDestroy(); // updateData
+
+ __ASSERT_DEBUG(iListBox && iContactItem && iFields && iListBoxModel, Panic(EPanicPostCond_UpdateL));
+ __ASSERT_DEBUG(iContactItem->CardFields().Count() >= iFields->Count(), Panic(EPanicPostCond_UpdateL));
+ __ASSERT_DEBUG(&static_cast<CPbkFieldListBoxModel*>(iListBoxModel)->Array() == iFields, Panic(EPanicPostCond_UpdateL));
+ __ASSERT_DEBUG(iListBox->Model()->ItemTextArray() == iListBoxModel, Panic(EPanicPostCond_UpdateL));
+ __ASSERT_DEBUG(iListBox->Model()->NumberOfItems() == iFields->Count(), Panic(EPanicPostCond_UpdateL));
+ }
+
+CPbkContactItem& CPbkContactInfoControl::ContactItem()
+ {
+ __ASSERT_DEBUG(iContactItem, Panic(EPanicPreCond_ContactItem));
+ return *iContactItem;
+ }
+
+TPbkContactItemField* CPbkContactInfoControl::CurrentField() const
+ {
+ // PreCond:
+ __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_CurrentField));
+
+ const TInt index = iListBox->CurrentItemIndex();
+ // CPbkFieldArray will check index
+ if (index >= 0)
+ {
+ __ASSERT_DEBUG(index < iFields->Count(), Panic(EPanicLogic_CurrentField));
+ return &(*iFields)[index];
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+EXPORT_C TInt CPbkContactInfoControl::CurrentFieldIndex
+ ( ) const
+ {
+ // PreCond:
+ __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_CurrentFieldIndex));
+
+ const TPbkContactItemField* currentField = CurrentField();
+ // Initialize the index to surely errornous value
+ TInt index = -1;
+ if (currentField)
+ {
+ // Search the field in the stored fields array
+ index = iContactItem->FindFieldIndex(*currentField);
+ // Field must be found
+ __ASSERT_DEBUG(index >= 0, Panic(EPanicPostCond_CurrentFieldIndex));
+ }
+ return index;
+ }
+
+EXPORT_C TInt CPbkContactInfoControl::FieldPos(const TPbkContactItemField& aField)
+ {
+ // PreCond:
+ __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_FieldPos));
+
+ for (TInt i = 0; i < iFields->Count(); ++i)
+ {
+ if ((*iFields)[i].IsSame(aField))
+ {
+ // aField found
+ return i;
+ }
+ }
+
+ // aField not found
+ return -1;
+ }
+
+EXPORT_C TInt CPbkContactInfoControl::FieldCount() const
+ {
+ // PreCond:
+ __ASSERT_DEBUG(iFields, Panic(EPanicPreCond_FieldCount));
+
+ return iFields->Count();
+ }
+
+EXPORT_C CPbkViewState* CPbkContactInfoControl::GetStateL() const
+ {
+ CPbkViewState* state = GetStateLC();
+ CleanupStack::Pop(); // state
+ return state;
+ }
+
+EXPORT_C CPbkViewState* CPbkContactInfoControl::GetStateLC() const
+ {
+ CPbkViewState* state = CPbkViewState::NewLC();
+ state->SetFocusedContactId(iContactItem->Id());
+ if (iListBox->Model()->NumberOfItems() > 0)
+ {
+ state->SetFocusedFieldIndex(CurrentFieldIndex());
+ const TInt topIndex = iListBox->TopItemIndex();
+ if (topIndex >= 0)
+ {
+ const TPbkContactItemField& topField = (*iFields)[topIndex];
+ state->SetTopFieldIndex(iContactItem->FindFieldIndex(topField));
+ }
+ }
+ return state;
+ }
+
+EXPORT_C void CPbkContactInfoControl::RestoreStateL(const CPbkViewState* aState)
+ {
+ const TInt numItems = iListBox->Model()->NumberOfItems();
+ if (aState && numItems > 0)
+ {
+ TInt focusIndex = 0;
+ TInt topIndex = 0;
+ const TInt height = iListBox->View()->NumberOfItemsThatFitInRect(iListBox->View()->ViewRect());
+
+ // The index of field to-be-focused depends on whether the shown
+ // contact is the latest contact that has been shown in ContactInfo.
+ // For re-opened contacts the focus is same as before the ContactInfo
+ // was closed. For new contact the first POC field should be focused.
+ if (aState->FocusedFieldIndex() == -1)
+ {
+ // "New" contact. Set focus to first POC field
+ for (TInt i = 0; i < iFields->Count(); i++)
+ {
+ if ((*iFields)[i].FieldInfo().IsPocField())
+ {
+ focusIndex = i;
+ break;
+ }
+ }
+ // Set top index so that focused field is bottom-most visible field
+ topIndex = Max(focusIndex - height + 1, 0);
+ }
+ else
+ {
+ // "Old" contact. Set focus to previously selected field
+ // Set top item
+ if (aState->TopFieldIndex() >= 0 && aState->TopFieldIndex() < iContactItem->CardFields().Count())
+ {
+ topIndex = Max(FieldPos(iContactItem->CardFields()[aState->TopFieldIndex()]), 0);
+ }
+
+ // Set listIndex so that maximum number of items are visible
+ if (topIndex + height > numItems)
+ {
+ topIndex += numItems - (height + topIndex);
+ if (topIndex < 0) topIndex = 0;
+ }
+
+ // Set focus
+ if (aState->FocusedFieldIndex() >= 0)
+ {
+ if (aState->FocusedFieldIndex() < iContactItem->CardFields().Count())
+ {
+ focusIndex = Max(FieldPos(iContactItem->CardFields()[aState->FocusedFieldIndex()]), 0);
+ }
+ else
+ {
+ focusIndex = iContactItem->CardFields().Count() - 1;
+ }
+ }
+ }
+ iListBox->SetTopItemIndex(topIndex);
+
+ // TODO: focusIndex may be invalid e.g. after contact ringing tone
+ // removal/addition.
+ if (focusIndex<0)
+ {
+ focusIndex=0;
+ }
+ else if (focusIndex>=numItems )
+ {
+ focusIndex=numItems-1;
+ }
+ iListBox->SetCurrentItemIndex(focusIndex);
+ }
+ else
+ {
+ iListBox->Reset();
+ }
+ iListBox->UpdateScrollBarsL();
+ }
+
+EXPORT_C CEikListBox& CPbkContactInfoControl::ListBox()
+ {
+ __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_ListBox));
+ return *iListBox;
+ }
+
+void CPbkContactInfoControl::HideThumbnail()
+ {
+ iShowThumbnail = EFalse;
+ if (iThumbnailHandler)
+ {
+ iThumbnailHandler->CancelLoading();
+ }
+ }
+
+void CPbkContactInfoControl::ShowThumbnailL()
+ {
+ iShowThumbnail = ETrue;
+ if (iFlags & KPbkContactInfoControlUpdateContextPane)
+ {
+ if (iContactItem)
+ {
+ if (!iThumbnailHandler)
+ {
+ iThumbnailHandler = CPbkThumbnailPopup::NewL(*iContactEngine);
+ }
+ iThumbnailHandler->Load(*iContactItem, iListBox);
+ }
+ }
+ }
+
+TKeyResponse CPbkContactInfoControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
+ {
+ __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_OfferKeyEventL));
+
+ if ( iThumbnailHandler &&
+ (aKeyEvent.iScanCode == EStdKeyUpArrow || aKeyEvent.iScanCode == EStdKeyDownArrow ))
+ {
+ iThumbnailHandler->Refresh();
+ }
+ // Forward all key events to the list box
+ return iListBox->OfferKeyEventL(aKeyEvent,aType);
+ }
+
+TInt CPbkContactInfoControl::NumberOfItems() const
+ {
+ // This control displays only one item
+ return 1;
+ }
+
+TBool CPbkContactInfoControl::ItemsMarked() const
+ {
+ // No items can be marked in this control
+ return EFalse;
+ }
+
+const CContactIdArray& CPbkContactInfoControl::MarkedItemsL() const
+ {
+ if (!iMarkedItemsArray)
+ {
+ iMarkedItemsArray = CContactIdArray::NewL();
+ }
+
+ // Remove old contents of array
+ // (use Remove instead of Reset to keep the array buffer)
+ iMarkedItemsArray->Remove(0,iMarkedItemsArray->Count());
+ iMarkedItemsArray->AddL(FocusedContactIdL());
+
+ return *iMarkedItemsArray;
+ }
+
+TContactItemId CPbkContactInfoControl::FocusedContactIdL() const
+ {
+ return iContactItem->Id();
+ }
+
+const TPbkContactItemField* CPbkContactInfoControl::FocusedField() const
+ {
+ return CurrentField();
+ }
+
+MObjectProvider* CPbkContactInfoControl::ObjectProvider()
+ {
+ return this;
+ }
+
+TInt CPbkContactInfoControl::FocusedFieldIndex() const
+ {
+ return CurrentFieldIndex();
+ }
+
+TBool CPbkContactInfoControl::ClipFromBeginning(TDes& aBuffer, TInt aItemIndex, TInt aSubCellNumber)
+ {
+ return AknTextUtils::ClipToFit(aBuffer, AknTextUtils::EClipFromBeginning,
+ this->iListBox, aItemIndex, aSubCellNumber);
+ }
+
+TBool CPbkContactInfoControl::HasVoiceTagL(const TPbkContactItemField& aField) const
+ {
+ if (!iVoiceTagFetchCompleted)
+ {
+ iVoiceTagField = iContactItem->VoiceTagField();
+ iVoiceTagFetchCompleted = ETrue;
+ }
+ if (iVoiceTagFetchCompleted && iVoiceTagField)
+ {
+ return (!iVoiceTagField->IsEmptyOrAllSpaces() && iVoiceTagField->IsSame(aField));
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+TBool CPbkContactInfoControl::HasSpeedDialL(const TPbkContactItemField& aField) const
+ {
+ if (!iContactEngine)
+ {
+ return EFalse;
+ }
+
+ const TInt fieldIndex = iContactItem->FindFieldIndex(aField);
+
+ // If there is no such a field, KErrNotFound is returned as a
+ // field index.
+ if ( fieldIndex != KErrNotFound )
+ {
+ return (iContactEngine->IsSpeedDialAssigned(*iContactItem, fieldIndex));
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+void CPbkContactInfoControl::SizeChanged()
+ {
+ __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_SizeChanged));
+ // Listbox occupies whole area of this control
+ iListBox->SetRect(Rect());
+ }
+
+TInt CPbkContactInfoControl::CountComponentControls() const
+ {
+ __ASSERT_DEBUG(iListBox, Panic(EPanicPreCond_CountComponentControls));
+ // Always only one child control: the list box.
+ return 1;
+ }
+
+CCoeControl* CPbkContactInfoControl::ComponentControl(TInt PBK_DEBUG_ONLY(aIndex)) const
+ {
+ __ASSERT_DEBUG(iListBox && aIndex==0, Panic(EPanicPreCond_ComponentControl));
+ // Return the one and only child control
+ return iListBox;
+ }
+
+void CPbkContactInfoControl::HandleResourceChange(TInt aType)
+ {
+ CPbkContactDetailsBaseControl::HandleResourceChange(aType);
+ TRAP_IGNORE(DoHandleResourceChangeL(aType));
+ }
+
+void CPbkContactInfoControl::DoHandleResourceChangeL(TInt aType)
+ {
+ if (aType == KAknsMessageSkinChange || aType == KEikDynamicLayoutVariantSwitch)
+ {
+ CPbkIconArray* iconArray = iListBox->IconArray();
+ if (iconArray)
+ {
+ iconArray->RefreshL(R_PBK_ICON_INFO_ARRAY);
+ }
+ const TBool isNonFocusing( IsNonFocusing() );
+ if ( iContactItem )
+ {
+ if ( !isNonFocusing )
+ {
+ if (IsFocused())
+ {
+ iThumbnailHandler->Load(*iContactItem, iListBox);
+ }
+ }
+ }
+ if (aType == KEikDynamicLayoutVariantSwitch)
+ {
+ SizeChanged();
+ if ( !isNonFocusing )
+ {
+ if (IsFocused())
+ {
+ // cause also refreshing of thumbnail
+ ShowThumbnailL();
+ }
+ }
+ }
+ }
+ }
+
+
+void CPbkContactInfoControl::FocusChanged( TDrawNow aDrawNow )
+ {
+ CCoeControl::FocusChanged( aDrawNow );
+ const TBool focused( IsFocused() );
+
+ if (focused)
+ {
+ // No big deal if thumbnail is not shown
+ TRAP_IGNORE( ShowThumbnailL() );
+ }
+ else
+ {
+ HideThumbnail();
+ }
+
+ if( iListBox )
+ {
+ iListBox->SetFocus( IsFocused(), aDrawNow );
+ }
+ }
+
+void CPbkContactInfoControl::CheckRingToneFieldL( CPbkContactItem* aContact )
+ {
+ // Check is there ringtone field and if there is, check that file is still
+ // available. If not, hide the field.
+ TPbkContactItemField* ringtoneField =
+ aContact->FindField( EPbkFieldIdPersonalRingingToneIndication );
+ if ( ringtoneField )
+ {
+ if ( ringtoneField->StorageType()==KStorageTypeText )
+ {
+ if ( !BaflUtils::FileExists(
+ iContactEngine->FsSession(),
+ ringtoneField->Text()) )
+ {
+ ringtoneField->SetHidden( ETrue );
+ }
+ }
+ }
+ }
+
+// CPbkContactInfoControl::CUpdateTestData implementation
+#ifdef __TEST_UpdateL__
+void CPbkContactInfoControl::CUpdateTestData::ConstructL(CPbkContactInfoControl& aControl)
+ {
+ iContactItem = aControl.iContactItem;
+ iTopIndex = aControl.iListBox->TopItemIndex();
+ iCurrentIndex = aControl.iListBox->CurrentItemIndex();
+
+ CEikStatusPane* statusPane = static_cast<CEikonEnv*>(aControl.iCoeEnv)->AppUiFactory()->StatusPane();
+ if (statusPane && statusPane->PaneCapabilities(TUid::Uid(EEikStatusPaneUidTitle)).IsPresent())
+ {
+ iTitlePane = static_cast<CAknTitlePane*>(statusPane->ControlL(TUid::Uid(EEikStatusPaneUidTitle)));
+ iTitlePaneText = iTitlePane->Text()->AllocL();
+ }
+
+ iFieldArray = aControl.iFields;
+ iThumbnailHandler = aControl.iThumbnailHandler;
+ }
+
+CPbkContactInfoControl::CUpdateTestData::~CUpdateTestData()
+ {
+ delete iTitlePaneText;
+ }
+
+TBool CPbkContactInfoControl::CUpdateTestData::Compare(CPbkContactInfoControl& aControl) const
+ {
+ return
+ iContactItem == aControl.iContactItem &&
+ (iTopIndex < 0 || iTopIndex == aControl.iListBox->TopItemIndex()) &&
+ (iCurrentIndex < 0 || iCurrentIndex == aControl.iListBox->CurrentItemIndex()) &&
+ iTitlePaneText->Compare(*iTitlePane->Text())==0 &&
+ iFieldArray == aControl.iFields &&
+ (!iFieldArray || iFieldArray == &static_cast<CPbkFieldListBoxModel*>(aControl.iListBoxModel)->Array()) &&
+ iThumbnailHandler == aControl.iThumbnailHandler;
+ }
+#endif
+
+// End of File