diff -r 000000000000 -r e686773b3f54 phonebookui/Phonebook/App/src/CPbkContactInfoAppView.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook/App/src/CPbkContactInfoAppView.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,1536 @@ +/* +* 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 Contact Info App View class methods. +* +*/ + + +// INCLUDE FILES +#include "CPbkContactInfoAppView.h" // This class' declaration + +#include // CEikMenuBar +#include +#include +#include +#include + +// Phonebook.app include files +#include +#include + +// Phone include files +#include + +// Send UI +#include +#include +#include +#include + +// AIW +#include + +// Clipboard +#include + +// PbkEng.dll include files +#include +#include +#include +#include +#include +#include + +// PbkUi.dll include files +#include +#include +#include +#include + +// PbkView.dll classes +#include +#include +#include +#include +#include +#include +#include +#include + +// PbkExtension classes +#include +#include +#include +#include + +// Postcard Uid +#include + +// Phonebook.app include files +#include +#include "CPbkAppUi.h" +#include "CPbkAppGlobals.h" +#include "CPbkDocument.h" +#include "MPbkContactInfoNavigationStrategy.h" +#include "PbkContactInfoNavigationStrategyFactory.h" +#include +#include "CPbkCodImageCmd.h" + +// Debugging headers +#include +#include "PbkProfiling.h" + +/// Unnamed namespace for local definitions +namespace { + +// LOCAL CONSTANTS AND MACROS + +#ifdef _DEBUG +enum TPanicCode + { + EPanicPostCond_DoActivateL = 1, + EPanicPostCond_DoDeactivate, + EPanicPreCond_HandleCommandL, + EPanicPreCond_ConstructL, + EPanicPostCond_ConstructL, + EPanicPreCond_CmdSpeedDialL, + EPanicPreCond_CmdWriteToContactL, + EPanicPreCond_CmdEditMeL, + EPanicPostCond_CmdEditMeL, + EPanicPreCond_CmdRemoveSpeedDialL, // 10 + EPanicPreCond_DynInitMenuPaneL, + EPanicIcon_StatusPaneUpdateL, + EPanicPreCond_HandleCommandKeyL, + EPanicPreCond_CmdRemoveCodL, + EPanicPreCond_CmdAddCodFieldL, + EPanicFieldInfoNotFound_CmdAddCodFieldL, + EPanicImageStorageNotFound_CmdAddCodFieldL, + EPanicPreCond_CmdEditTextCodFieldL, + EPanicFieldInfoNotFound_HandleCodTextChangeL, + EPanicTextStorageNotFound_HandleCodTextChangeL + }; +#endif // _DEBUG + + +// ==================== LOCAL FUNCTIONS ==================== + +#ifdef _DEBUG +void Panic(TPanicCode aReason) + { + _LIT(KPanicText, "CPbkContactInfoAppView"); + User::Panic(KPanicText, aReason); + } +#endif // _DEBUG + +} // namespace + + +// ================= MEMBER FUNCTIONS ======================= + +inline CPbkContactInfoAppView::CPbkContactInfoAppView() + { + } + +inline void CPbkContactInfoAppView::ConstructL() + { + // PreCond + __ASSERT_DEBUG(!iContainer && !iViewState, + Panic(EPanicPreCond_ConstructL)); + + // Init base class + __PBK_PROFILE_START(PbkProfiling::EViewBaseConstruct); + BaseConstructL(R_PBK_CONTACTINFO_APPVIEW); + __PBK_PROFILE_END(PbkProfiling::EViewBaseConstruct); + + iExtGlobal = CPbkExtGlobals::InstanceL(); + + // Create AIW interest array for call + CreateInterestItemAndAttachL(KAiwCmdCall, + R_PHONEBOOK_CALL_MENU, R_PHONEBOOK_CALLUI_AIW_INTEREST, ETrue); + // The last parameter is false, since KAiwCmdCall is already attached + // to base services above + CreateInterestItemAndAttachL(KAiwCmdCall, + R_PHONEBOOK_CALL_CONTEXT_MENU, R_PHONEBOOK_CALLUI_AIW_INTEREST, EFalse); + + // Create AIW interest array for PoC + CreateInterestItemAndAttachL(KAiwCmdPoC, + R_PHONEBOOK_POC_MENU, R_PHONEBOOK_POCUI_AIW_INTEREST, ETrue); + // The last parameter is false, since KAiwCmdPoC is already attached + // to base services above + CreateInterestItemAndAttachL(KAiwCmdPoC, + R_PHONEBOOK_POC_CONTEXT_MENU, R_PHONEBOOK_POCUI_AIW_INTEREST, EFalse); + + // FFS checker + iPbkFFSCheck = CPbkFFSCheck::NewL(); + + // PostCond + __ASSERT_DEBUG(!iContainer && !iContactItem && !iViewState, + Panic(EPanicPostCond_ConstructL)); + } + +CPbkContactInfoAppView* CPbkContactInfoAppView::NewL() + { + CPbkContactInfoAppView* self = new(ELeave) CPbkContactInfoAppView(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); // self + return self; + } + +CPbkContactInfoAppView::~CPbkContactInfoAppView() + { + if (iContainer) + { + // Remove the container from the view stack + AppUi()->RemoveFromViewStack(*this, iContainer); + // Destroy the control container + delete iContainer; + } + delete iUpdateContact; + delete iContactItem; + delete iViewState; + delete iNaviStrategy; + Release(iViewExtension); + Release(iExtGlobal); + delete iPbkCodImageCmd; + delete iPbkFFSCheck; + } + +/** + * Command handler: Opens the context sensive menu. + */ +void CPbkContactInfoAppView::CmdContextMenuL() + { + LaunchPopupMenuL(R_PBK_CONTACTINFO_CONTEXTBAR); + } + +/** + * Command handler: Edit contact. + */ +void CPbkContactInfoAppView::CmdEditMeL() + { + __ASSERT_DEBUG( + iContainer && iContainer->Control() && iContactItem, + Panic(EPanicPreCond_CmdEditMeL)); + CPbkContactInfoControl* control = iContainer->Control(); + + // Find focused field's index in contact item + const TPbkContactItemField* field = control->CurrentField(); + const TInt fieldIndex = field ? + iContactItem->FindFieldIndex(*field) : KErrNotFound; + + // Store the view state + delete iViewState; + iViewState = NULL; + iViewState = iContainer->Control()->GetStateL(); + + // Open contact for editing + CPbkContactItem* ci = Engine()->OpenContactLCX(iContactItem->Id()); + + // Run the editor dialog + CPbkContactEditorDlg* editorDlg = CPbkContactEditorDlg::NewL + (*Engine(), *ci, EFalse, fieldIndex); + editorDlg->SetExitCommandId(EPbkCmdExit); + + control->HideThumbnail(); + iSavedId = KNullContactId; + iContainer->SetFocusing( EFalse ); + iContainer->CoeControl()->SetFocusing( EFalse ); + TRAPD( err, iSavedId = editorDlg->ExecuteLD() ); + iContainer->SetFocusing( ETrue ); + iContainer->CoeControl()->SetFocusing( ETrue ); + control->ShowThumbnailL(); + User::LeaveIfError( err ); + + CleanupStack::PopAndDestroy(2); // lock, ci + + // delay update so that if desctruction of phonebook + // has caused stopping of editor execution, no update is done + // if this is deleted. + delete iUpdateContact; + iUpdateContact = NULL; + iUpdateContact = CIdle::NewL(CActive::EPriorityIdle); + + TCallBack callBack( UpdateContact,this ); + iUpdateContact->Start( callBack ); + } + +TInt CPbkContactInfoAppView::UpdateContact(TAny* aPbkContactInfoAppView) + { + return static_cast(aPbkContactInfoAppView)->DoUpdateContact(); + } + +TInt CPbkContactInfoAppView::DoUpdateContact() + { + CPbkContactInfoControl* control = NULL; + if( iContainer ) + { + control = iContainer->Control(); + } + + if ( !iExitInProgress && control ) + { + CPbkContactInfoControl* control = iContainer->Control(); + if (iSavedId != KNullContactId) + { + // Reload contact and update UI control. Do this manually here instead + // of in HandleDatabaseEventL() because editor dialog restores previous + // text into title pane which would be wrong in this case. + CPbkContactItem* ci = NULL; + TRAPD( err, ci = Engine()->ReadContactL(iSavedId) ); + if ( err == KErrNone ) + { + TRAP( err, control->UpdateL(ci)); + if ( err == KErrNone ) + { + delete iContactItem; + iContactItem = ci; + if ( iViewState ) + { + // Restore UI control state, no harm done + // if this fails, focus just changes + TRAP_IGNORE( iContainer->Control()->RestoreStateL(iViewState) ); + // Delete the view state object to save memory + delete iViewState; + iViewState = NULL; + } + control->DrawNow(); + } + else + { + delete ci; + } + } + if ( err != KErrNone ) + { + iContainer->ControlEnv()->HandleError( err ); + } + } + else + { + // It is just thumbnail, we can manage if that fails to show + TRAP_IGNORE( control->ShowThumbnailL() ); + } + + __ASSERT_DEBUG( + iContainer && iContainer->Control() && iContactItem, + Panic(EPanicPostCond_CmdEditMeL)); + } + // Stop idle callback + return KErrNone; + } + +/** + * Command handler: Default settings. + */ +void CPbkContactInfoAppView::CmdDefaultSettingsL() + { + CPbkContactInfoControl* control = iContainer->Control(); + control->HideThumbnail(); + CPbkMemoryEntryDefaultsDlg* memoryEntryDefaultsDlg = + CPbkMemoryEntryDefaultsDlg::NewL(iContactItem->Id(), *Engine()); + memoryEntryDefaultsDlg->ExecuteLD(); + control->ShowThumbnailL(); + } + +/** + * Command handler: Assign a speed dial to a phone number. + */ +void CPbkContactInfoAppView::CmdAssignSpeedDialL() + { + //PreCond: + __ASSERT_DEBUG(iContainer->Control()->FieldCount() > 0, + Panic(EPanicPreCond_CmdSpeedDialL)); + + TInt fieldId = iContainer->Control()->CurrentFieldIndex(); + + CSpdiaControl* speedDialDlg = CSpdiaControl::NewL(); + if (speedDialDlg->ExecuteLD(iContactItem->Id(), fieldId) && !iExitInProgress) + { + // this can removed when CContactDatabase::SetSpeedDialField sends notifications + CPbkContactItem* ci = Engine()->ReadContactLC(iContactItem->Id()); + // Update the UI control + TInt focus = iContainer->Control()->ListBox().CurrentItemIndex(); + iContainer->Control()->UpdateL(ci); + if (focus > 0 && focus < iContainer->Control()->FieldCount()) + { + iContainer->Control()->ListBox().SetCurrentItemIndex(focus); + } + // Update member + delete iContactItem; + CleanupStack::Pop(ci); + iContactItem = ci; + iContainer->Control()->DrawNow(); + } + } + +/** + * Command handler: Removes a speed dial from a phone number. + */ +void CPbkContactInfoAppView::CmdRemoveSpeedDialL() + { + //PreCond: + __ASSERT_DEBUG(iContainer->Control()->FieldCount() > 0, + Panic(EPanicPreCond_CmdRemoveSpeedDialL)); + + CSpdiaControl* speedDialDlg = CSpdiaControl::NewL(); + CleanupStack::PushL( speedDialDlg ); + + CArrayFix* speedDialIndexes = + iContainer->Control()->CurrentField()->SpeedDialIndexesL(); + if (speedDialIndexes) + { + CleanupStack::PushL(speedDialIndexes); + for (TInt i = 0; i < speedDialIndexes->Count(); ++i) + { + speedDialDlg->RemoveDialIndexL( + speedDialDlg->Index( (*speedDialIndexes)[i] ) ); + } + CleanupStack::PopAndDestroy(speedDialIndexes); + } + + CleanupStack::PopAndDestroy( speedDialDlg ); + + // This can removed when CContactDatabase::RemoveSpeedDialFieldL sends notifications + CPbkContactItem* ci = Engine()->ReadContactLC(iContactItem->Id()); + // Update the UI control + TInt focus = iContainer->Control()->ListBox().CurrentItemIndex(); + iContainer->Control()->UpdateL(ci); + if (focus > 0 && focus < iContainer->Control()->FieldCount()) + { + iContainer->Control()->ListBox().SetCurrentItemIndex(focus); + } + // Update member + delete iContactItem; + CleanupStack::Pop(ci); + iContactItem = ci; + iContainer->Control()->DrawNow(); + } + +/** + * Command handler: Personal Ringing tone setting + */ +void CPbkContactInfoAppView::CmdPersonalRingingToneL() + { + CPbkRingingToneFetch* toneFetch = CPbkRingingToneFetch::NewL(*Engine()); + CleanupStack::PushL(toneFetch); + TFileName ringingToneFile; + TPbkContactItemField* field = + iContactItem->FindField(EPbkFieldIdPersonalRingingToneIndication); + if (field) + { + ringingToneFile.Copy(field->Text().Left(ringingToneFile.MaxLength())); + } + if (toneFetch->FetchRingingToneL(ringingToneFile)) + { + CPbkContactItem* item = Engine()->OpenContactLCX(iContactItem->Id()); + toneFetch->SetRingingToneL(*item, ringingToneFile); + + // Check disk space before assigning. + // If not enough memory then leaves with KErrDiskFull. + iPbkFFSCheck->FFSClCheckL(); + + Engine()->CommitContactL(*item); + CleanupStack::PopAndDestroy(2); // lock, item + } + CleanupStack::PopAndDestroy(); // toneFetch + } + + +void CPbkContactInfoAppView::CmdSendContactL(TPbkSendingParams aParams) + { + TPbkContactItemField* field = iContainer->Control()->CurrentField(); + + // Create the send contact command object + MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()-> + CommandFactory().CreateSendContactCmdL(aParams,*Engine(), + CPbkAppGlobals::InstanceL()->BCardEngL(*Engine()), + iContactItem->Id(), field); + // Execute the command + cmd->ExecuteLD(); + } + +/** + * Command handler: write message to contact + */ +void CPbkContactInfoAppView::CmdWriteToContactL(TPbkSendingParams aParams) + { + __ASSERT_DEBUG( + iContainer && iContainer->Control() && iContactItem, + Panic(EPanicPreCond_CmdWriteToContactL)); + + TPbkContactItemField* currentField = iContainer->Control()->CurrentField(); + + // Create the write message command object + MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()-> + CommandFactory().CreateSendMultipleMessageCmdL( + *Engine(), + aParams, + iContainer->Control()->MarkedItemsL(), + currentField, + EFalse); + // Execute the command + cmd->ExecuteLD(); + } + + +/** + * Command handler: go to URL command. + */ +void CPbkContactInfoAppView::CmdGoToURLL() + { + // Create the go to URL command object + MPbkCommand* cmd = CPbkAppGlobalsBase::InstanceL()-> + CommandFactory().CreateGoToURLCmdL(*iContactItem, NULL); + // Execute the command + cmd->ExecuteLD(); + } + +/** + * Command handler: prepend. + */ +void CPbkContactInfoAppView::CmdPrependL() + { + // Get the Phone number + RBuf number; + number.CreateL( iContainer->Control()->CurrentField()->FieldInfo().MaxLength() ); + number.CleanupClosePushL(); + iContainer->Control()->CurrentField()->GetTextL(number); + + // Convert digits to foreign characters if necessary + AknTextUtils::DisplayTextLanguageSpecificNumberConversion(number); + + CPbkPrependDlg* dlg = CPbkPrependDlg::NewL(number); + if (dlg->ExecuteLD(R_PBK_PREPEND_QUERY)) + { + // convert digits back from foreign characters to western digits if necessary + AknTextUtils::ConvertDigitsTo(number, EDigitTypeWestern); + + // Create a temporary contact + CPbkContactItem* tempContact = Engine()->CreateEmptyContactL(); + CleanupStack::PushL(tempContact); + + // Add the prepended number to it + TPbkContactItemField* phoneNumberField = + tempContact->AddOrReturnUnusedFieldL( + *Engine()->FieldsInfo().Find( + iContainer->Control()->CurrentField()->FieldInfo().FieldId())); + + if (phoneNumberField) + { + phoneNumberField->TextStorage()->SetTextL(number); + } + + // Create an array out of the temp contact + CContactIdArray* array = CContactIdArray::NewL(); + CleanupStack::PushL(array); + array->AddL(tempContact->Id()); + + // Now place a call to the temp contact + iAiwInterestArray->HandleCommandL( + EPbkCmdCall, + *array, + phoneNumberField, // "focused field" in this case + KAiwCmdCall); + + CleanupStack::PopAndDestroy(2); // array, tempContact + } + CleanupStack::PopAndDestroy(); //number + } + +/** + * Command handler: copy number. + */ +void CPbkContactInfoAppView::CmdCopyNumberL() + { + const TInt KBeginning = 0; + // Construct a plain text from the number + RBuf number; + number.CreateL( iContainer->Control()->CurrentField()->FieldInfo().MaxLength() ); + number.CleanupClosePushL(); + iContainer->Control()->CurrentField()->GetTextL(number); + CPlainText* plainText = CPlainText::NewL(); + CleanupStack::PushL(plainText); + plainText->InsertL(KBeginning, number); + + // Copy to clipboard + CClipboard* cb = CClipboard::NewForWritingLC(Engine()->FsSession()); + plainText->CopyToStoreL(cb->Store(), cb->StreamDictionary(), + KBeginning, plainText->DocumentLength()); + cb->CommitL(); + + CleanupStack::PopAndDestroy(2); // cb, plainText + + // Show a note + HBufC* prompt = StringLoader::LoadLC(R_QTN_LOGS_NOTE_COPY_DONE); + CAknInformationNote* dlg = new(ELeave) CAknInformationNote(ETrue); + dlg->ExecuteLD(*prompt); + CleanupStack::PopAndDestroy(); // prompt + CleanupStack::PopAndDestroy(); //number + } + +void CPbkContactInfoAppView::ContactChangedL() + { + // if end key has been pressed, do not update the contact + // infromation in info control. + if (!iExitInProgress) + { + ChangeContactL(iContactItem->Id()); + } + } + +CPbkContactItem* CPbkContactInfoAppView::ContactItemL() + { + return iContactItem; + } + +TContactItemId CPbkContactInfoAppView::ContactItemId() + { + return iContactItem->Id(); + } + +TBool CPbkContactInfoAppView::HandleCommandKeyL + (const TKeyEvent& aKeyEvent, + TEventCode aType) + { + __ASSERT_DEBUG(iContainer && iContactItem && iNaviStrategy, + Panic(EPanicPreCond_HandleCommandKeyL)); + + // Pass the key to the strategy + TBool ret = iNaviStrategy->HandleCommandKeyL(aKeyEvent, aType); + if (!ret) + { + // Check was it send key press + if (aKeyEvent.iCode == EKeyPhoneSend) + { + HandleCommandL(EPbkCmdCall); + ret = ETrue; + } + else if (aKeyEvent.iCode == EKeyPoC) + { + HandleCommandL(EPbkCmdPoc); + ret = ETrue; + } + else + { + // Pass the key event to base class + ret = CPbkMemoryEntryAppView::HandleCommandKeyL(aKeyEvent, aType); + } + } + return ret; + } + +CPbkViewState* CPbkContactInfoAppView::GetViewStateLC() const + { + return iContainer ? iContainer->Control()->GetStateLC() : NULL; + } + +void CPbkContactInfoAppView::HandleCommandL + (TInt aCommandId) + { + // PreCond: (this is the precond for all Cmd* functions at the same time) + __ASSERT_DEBUG(iContainer && iContactItem && iViewExtension, + Panic(EPanicPreCond_HandleCommandL)); + + TInt serviceCmdId = KNullHandle; + if (aCommandId == EPbkCmdCall) + { + serviceCmdId = KAiwCmdCall; + } + else if (aCommandId == EPbkCmdPoc) + { + serviceCmdId = KAiwCmdPoC; + } + + // Offer the command first to AIW + if (iAiwInterestArray->HandleCommandL( + aCommandId, + iContainer->Control()->MarkedItemsL(), + iContainer->Control()->FocusedField(), + serviceCmdId)) + { + return; + } + + + // And then to the extension + if (iViewExtension->HandleCommandL(aCommandId)) + { + return; + } + + // Process view-specific commands + switch (aCommandId) + { + case EPbkCmdContextMenu: + { + CmdContextMenuL(); + break; + } + + case EPbkCmdEditMe: + { + PbkAppUi()->FFSClCheckL(PbkCommandHandler(this, + &CPbkContactInfoAppView::CmdEditMeL)); + UpdateUrlFieldInfo(); + break; + } + + case EPbkCmdDefaultSettings: + { + PbkAppUi()->FFSClCheckL(PbkCommandHandler(this, + &CPbkContactInfoAppView::CmdDefaultSettingsL)); + break; + } + + case EPbkCmdAssignSpeedDial: + { + PbkAppUi()->FFSClCheckL(PbkCommandHandler(this, + &CPbkContactInfoAppView::CmdAssignSpeedDialL)); + break; + } + + case EPbkCmdRemoveSpeedDial: + { + CmdRemoveSpeedDialL(); + break; + } + + case EPbkCmdPersonalRingingTone: + { + PbkAppUi()->FFSClCheckL(PbkCommandHandler(this, + &CPbkContactInfoAppView::CmdPersonalRingingToneL)); + break; + } + + case EPbkCmdGoToURL: + { + CmdGoToURLL(); + break; + } + + case EPbkCmdPrepend: + { + CmdPrependL(); + break; + } + + case EPbkCmdCopyNumber: + { + CmdCopyNumberL(); + break; + } + case EPbkCmdWrite: + { + TPbkSendingParams params = CreateWriteParamsLC(); + PbkAppUi()->FFSClCheckL(PbkCommandHandler(this, + &CPbkContactInfoAppView::CmdWriteToContactL, + params)); + CleanupStack::PopAndDestroy(); //mtmFilter + break; + } + case EPbkCmdSendUICommand: + { + TPbkSendingParams params = CreateSendParamsLC(); + CmdSendContactL(params); + CleanupStack::PopAndDestroy(); //mtmFilter + break; + } + case EPbkCmdCodRemoveObject: + { + // Only one Cod field exists at a time. + // By callig both functions the existing field + // will be deleted + CmdRemoveCodL( EPbkFieldIdCodTextID ); + CmdRemoveCodL( EPbkFieldIdCodImageID ); + break; + } + // Following methods need critical level check of memory + case EPbkCmdCodAddObjectText: + case EPbkCmdCodAddObjectImage: + { + CmdAddCodFieldL( aCommandId ); + break; + } + case EPbkCmdCodEditText: + { + CmdEditTextCodFieldL(); + break; + } + case EPbkCmdCodViewImage: + { + CmdViewCodImageL(); + break; + } + case EPbkCmdCodChangeImage: + { + CmdAddCodFieldL(EPbkCmdCodAddObjectImage); + break; + } + case EPbkCmdCodAddObjectSubMenu: + { + break; + } + case EPbkCmdExit: + { + // Turn up the iExitInProgress flag to avoid unwanted + // contact redraw in exit case. This happens if the editor + // dialog is running while exit should be executed. + iExitInProgress = ETrue; + // fall through to default handler. + } + default: + { + CPbkMemoryEntryAppView::HandleCommandL(aCommandId); + break; + } + } + } + +void CPbkContactInfoAppView::DynInitMenuPaneL + (TInt aResourceId, + CEikMenuPane* aMenuPane) + { + __ASSERT_DEBUG(iContainer && iViewExtension, + Panic(EPanicPreCond_DynInitMenuPaneL)); + + TUint flags = KPbkInfoView; + if (iContainer->Control()->FieldCount() == 0) + { + flags |= KPbkControlEmpty; + } + + TPbkContactItemField* currentField = + iContainer->Control()->CurrentField(); + + if (currentField && currentField->FieldInfo().IsPhoneNumberField()) + { + flags |= KPbkCurrentFieldPhoneNumber; + } + + if (currentField && currentField->FieldInfo().IsVoipField()) + { + flags |= KPbkCurrentFieldVoipAddress; + } + + // The flag KPbkCurrentFieldPoc is valid for using only + // in PoC context menu filtering in CPbkAiwInterestItemPoc::InitMenuPaneL + if ( currentField ) + { + // We can't use the IsPocField() info here, since context + // menu filtering is more strict than that + const TPbkFieldId fieldId = currentField->FieldInfo().FieldId(); + switch ( fieldId ) + { + case EPbkFieldIdVOIP: // FALLTHROUGH + case EPbkFieldIdPushToTalk: // FALLTHROUGH + case EPbkFieldIdShareView: // FALLTHROUGH + case EPbkFieldIdSIPID: + { + flags |= KPbkCurrentFieldPoc; + } + default: + { + // Do nothing + } + } + } + + // Offer the menu to AIW first + if (iAiwInterestArray->InitMenuPaneL(aResourceId, *aMenuPane, flags)) + { + // No need to continue + return; + } + + iViewExtension->DynInitMenuPaneL(aResourceId, aMenuPane); + + switch (aResourceId) + { + case R_PBK_CONTACTINFO_OPTIONS_MENU: + { + OptionsMenuFilteringL(*aMenuPane, flags); + break; + } + case R_PBK_CONTACTINFO_CONTEXT_MENU: + { + ContextMenuFilteringL(*aMenuPane, flags); + break; + } + case R_PBK_ADD_OBJECT_SUBMENU: // Add object menu item + { + AddObjectSubPaneMenuFilteringL(*aMenuPane, flags); + break; + } + default: + { + break; + } + } + + CPbkMemoryEntryAppView::DynInitMenuPaneL(aResourceId,aMenuPane); + } + +inline void CPbkContactInfoAppView::OptionsMenuFilteringL + (CEikMenuPane& aMenuPane, + TUint aFlags) + { + if ((aFlags & KPbkControlEmpty) + || Engine()->IsSpeedDialAssigned(*iContactItem, + iContainer->Control()->CurrentFieldIndex())) + { + aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue); + } + else if (FeatureManager::FeatureSupported(KFeatureIdCommonVoip)) + { + if (!iContainer->Control()->CurrentField()-> + FieldInfo().IsVoipField()) + { + aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue); + } + } + else + { + if (!iContainer->Control()->CurrentField()-> + FieldInfo().IsPhoneNumberField()) + { + aMenuPane.SetItemDimmed(EPbkCmdAssignSpeedDial, ETrue); + } + } + + if ((aFlags & KPbkControlEmpty) || + !Engine()->IsSpeedDialAssigned(*iContactItem, + iContainer->Control()->CurrentFieldIndex())) + { + // Field is a phone number and speed dial for this field + aMenuPane.SetItemDimmed(EPbkCmdRemoveSpeedDial, ETrue); + } + if ((aFlags & KPbkControlEmpty) || (!iUrlFieldAvailable)) + { + // URL field not present + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + } + if ((aFlags & KPbkControlEmpty) || !(aFlags & KPbkCurrentFieldPhoneNumber)) + { + // Field is not a phone number field + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + } + + if (aFlags & KPbkControlEmpty) + { + aMenuPane.SetItemDimmed(EPbkCmdDefaultSettings, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdSendUICommand, ETrue); + } + else + { + aMenuPane.SetItemDimmed(EPbkCmdSendUICommand, EFalse); + } + + if (FeatureManager::FeatureSupported(KFeatureIdCallImagetext)) + { + // Empty contact, no fields + if( (aFlags & KPbkControlEmpty) ) + { + aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue ); + } + else + { + TPbkContactItemField* field = iContainer->Control()->CurrentField(); + const TPbkFieldId pbkFieldId( field->FieldInfo().FieldId() ); + + if (pbkFieldId == EPbkFieldIdCodTextID && CodTextFieldEnabled()) + { + if (CodImageFieldEnabled()) + { + // Text field contains Cod image filename + aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue ); + } + else + { + // Text field is used for Cod text purposes + aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue ); + } + } + else + { + // Focus is not on the Object for call field. + aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue ); + aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue ); + } + } + } + else + { + // Image/text for call feature not supported. + // Dimm all related commands + aMenuPane.SetItemDimmed( EPbkCmdCodEditText, ETrue); + aMenuPane.SetItemDimmed( EPbkCmdCodViewImage, ETrue); + aMenuPane.SetItemDimmed( EPbkCmdCodChangeImage, ETrue); + aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectSubMenu, ETrue); + aMenuPane.SetItemDimmed( EPbkCmdCodRemoveObject, ETrue); + } + + } + +inline void CPbkContactInfoAppView::ContextMenuFilteringL + (CEikMenuPane& aMenuPane, + TUint aFlags) + { + TPbkContactItemField* field = iContainer->Control()->CurrentField(); + + // context sensitive menu filtering + if (aFlags & KPbkControlEmpty) + { + aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + } + else if (field) + { + switch(field->FieldInfo().FieldId()) + { + case EPbkFieldIdPhoneNumberStandard: // FALLTHROUGH + case EPbkFieldIdPhoneNumberHome: // FALLTHROUGH + case EPbkFieldIdPhoneNumberWork: // FALLTHROUGH + case EPbkFieldIdPhoneNumberMobile: // FALLTHROUGH + case EPbkFieldIdPhoneNumberVideo: // FALLTHROUGH + case EPbkFieldIdFaxNumber: // FALLTHROUGH + case EPbkFieldIdAssistantNumber: // FALLTHROUGH + case EPbkFieldIdCarNumber: + { + aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + break; + } + case EPbkFieldIdEmailAddress: + { + aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + break; + } + case EPbkFieldIdPersonalRingingToneIndication: + { + aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdEditMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + break; + } + case EPbkFieldIdURL: + { + aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + break; + } + default: + { + // By default only Edit item is shown + aMenuPane.SetItemDimmed(EPbkCmdWrite, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdUseNumber, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdDeleteMe, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdPersonalRingingTone, ETrue); + aMenuPane.SetItemDimmed(EPbkCmdGoToURL, ETrue); + break; + } + } + } + } + +TPbkSendingParams CPbkContactInfoAppView::CreateWriteParamsLC() + { + // Construct the MTM filter + CArrayFixFlat* mtmFilter = + new(ELeave) CArrayFixFlat(4); + CleanupStack::PushL(mtmFilter); + + if (iContainer->Control()->FieldCount() > 0) + { + switch(iContainer->Control()->CurrentField()->FieldInfo().FieldId()) + { + case EPbkFieldIdPhoneNumberStandard: // FALLTHROUGH + case EPbkFieldIdPhoneNumberHome: // FALLTHROUGH + case EPbkFieldIdPhoneNumberWork: // FALLTHROUGH + case EPbkFieldIdPhoneNumberMobile: // FALLTHROUGH + case EPbkFieldIdAssistantNumber: // FALLTHROUGH + case EPbkFieldIdCarNumber: + { + mtmFilter->AppendL(KSenduiMtmSmtpUid); //Email + break; + } + case EPbkFieldIdEmailAddress: + { + mtmFilter->AppendL(KSenduiMtmSmsUid); //Sms + break; + } + default: + break; + } + } + + TSendingCapabilities capabilities = TSendingCapabilities(); + capabilities.iFlags = TSendingCapabilities::ESupportsEditor; + return TPbkSendingParams( mtmFilter, capabilities ); + } + +TPbkSendingParams CPbkContactInfoAppView::CreateSendParamsLC() + { + // Construct the MTM filter + CArrayFixFlat* mtmFilter = + new(ELeave) CArrayFixFlat(4); + CleanupStack::PushL(mtmFilter); + + const TUid KPostcardMtmUid = { KSenduiMtmPostcardUidValue }; + + mtmFilter->AppendL(KPostcardMtmUid); // hide postcard + mtmFilter->AppendL(KSenduiMtmAudioMessageUid); // hide audio message + + TSendingCapabilities capabilities = TSendingCapabilities(); + capabilities.iFlags = TSendingCapabilities::ESupportsBioSending; + capabilities.iFlags |= TSendingCapabilities::ESupportsAttachments; + return TPbkSendingParams( mtmFilter, capabilities ); + } + +TUid CPbkContactInfoAppView::Id() const + { + return CPbkAppUi::KPbkContactInfoViewUid; + } + +void CPbkContactInfoAppView::HandleStatusPaneSizeChange() + { + // Resize the container to fill the client rectangle + if (iContainer) + { + iContainer->SetRect(ClientRect()); + } + } + +void CPbkContactInfoAppView::DoActivateL + (const TVwsViewId& aPrevViewId, + TUid aCustomMessageId, + const TDesC8& aCustomMessage) + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactInfoAppView(%x)::DoActivateL()"), this); + + // reset the exit in progress flag. + iExitInProgress = EFalse; + + // Call base class, this must be done! + CPbkMemoryEntryAppView::DoActivateL(aPrevViewId, + aCustomMessageId, aCustomMessage); + + // Update application-wide state. UI control updates the title pane. + CPbkAppUi::CViewActivationTransaction* viewActivationTransaction = + PbkAppUi()->HandleViewActivationLC + (Id(), aPrevViewId, NULL, NULL, + CPbkAppUi::EUpdateNaviPane | CPbkAppUi::EUpdateContextPane); + + if (aCustomMessageId == CPbkViewState::Uid()) + { + // Read the desired UI state from aCustomMessage + CPbkViewState* viewState = CPbkViewState::NewL(aCustomMessage); + if (iViewState) + { + // Merge parameter view state with the stored state + if (viewState->FocusedContactId() != iViewState->FocusedContactId()) + { + iViewState->SetFocusedContactId(viewState->FocusedContactId()); + iViewState->SetFocusedFieldIndex(-1); + iViewState->SetTopFieldIndex(-1); + } + if (viewState->FocusedFieldIndex() >= 0) + { + iViewState->SetFocusedFieldIndex(viewState->FocusedFieldIndex()); + } + if (viewState->TopFieldIndex() >= 0) + { + iViewState->SetTopFieldIndex(viewState->TopFieldIndex()); + } + if (viewState->ParentContactId() != iViewState->ParentContactId()) + { + iViewState->SetParentContactId(viewState->ParentContactId()); + } + // delete parameter view state + delete viewState; + } + else + { + // No stored state, use the parameter supplied one + iViewState = viewState; + } + } + else + { + // No UI state specified, restore in previous state + if (!iViewState) + { + // No previous state + User::Leave(KErrArgument); + } + } + + // Read the contact + if (!iContactItem || iContactItem->Id() != iViewState->FocusedContactId()) + { + CPbkContactItem* ci = Engine()->ReadContactLC + (iViewState->FocusedContactId()); + if (iContainer && iContainer->Control()) + { + // Change the contact item inside the UI control + iContainer->Control()->UpdateL(ci); + } + delete iContactItem; + CleanupStack::Pop(); // ci + iContactItem = ci; + + //Check does the contact have an URL field + UpdateUrlFieldInfo(); + } + + if (!iContainer) + { + // Create the container control + iContainer = CContainer::NewL(this, *this); + + iContainer->SetHelpContext(TCoeHelpContext(ApplicationUid(), + KPHOB_HLP_CONTACT_INFO_VIEW)); + + // Create extension + if (!iViewExtension) + { + iViewExtension = + iExtGlobal->FactoryL().CreatePbkViewExtensionL + (Id(), *PbkAppUi()->PbkDocument()->Engine(), *this); + } + + // Create the view-side UI control + CPbkContactInfoControl* control = CPbkContactInfoControl::NewL + (R_PBK_DEFAULT_CONTACTINFO_CONTROL, + *iContainer, + iContactItem, + Engine()); + + // Set up the container. iContainer takes ownership of control safely + iContainer->SetControl(control, ClientRect()); + iViewExtension->SetContactUiControl(control); + iContainer->ActivateL(); + + // create navigation strategy + iNaviStrategy = PbkContactInfoNavigationStrategyFactory::CreateL( + *Engine(), *this, iViewState->ParentContactId()); + + // Add this view and container to the view stack + AppUi()->AddToViewStackL(*this, iContainer); + } + + // Restore UI control state + iContainer->Control()->RestoreStateL(iViewState); + // Delete the view state object to save memory + delete iViewState; + iViewState = NULL; + + // Commit application-wide state changes + viewActivationTransaction->Commit(); + CleanupStack::PopAndDestroy(); // viewActivationTransaction + + // Draw the control + iContainer->Control()->DrawNow(); + + // PostCond + __ASSERT_DEBUG( + iContainer && iContainer->Control() && + iContactItem && !iViewState, + Panic(EPanicPostCond_DoActivateL)); + } + +void CPbkContactInfoAppView::DoDeactivate() + { + PBK_DEBUG_PRINT(PBK_DEBUG_STRING + ("CPbkContactInfoAppView(%x)::DoDeactivate()"), this); + + // Delete any previous view state + delete iViewState; + iViewState = NULL; + + // delete navigation strategy + delete iNaviStrategy; + iNaviStrategy = NULL; + + if (iContainer) + { + if (iContainer->Control()) + { + // Store the view state for next activation + TRAP_IGNORE(iViewState = iContainer->Control()->GetStateL()); + } + // Remove view and its control from the view stack + AppUi()->RemoveFromViewStack(*this, iContainer); + // Destroy the container control + delete iContainer; + iContainer = NULL; + } + + if (iViewExtension) + { + iViewExtension->SetContactUiControl(NULL); + } + + // Delete the contact item + delete iContactItem; + iContactItem = NULL; + + // Call base class, this must be done! + CPbkMemoryEntryAppView::DoDeactivate(); + + // PostCond + __ASSERT_DEBUG(!iContainer && !iContactItem, + Panic(EPanicPostCond_DoDeactivate)); + } + + +void CPbkContactInfoAppView::UpdateUrlFieldInfo() + { + iUrlFieldAvailable = EFalse; + if (iContactItem->FindField(EPbkFieldIdURL)) + { + iUrlFieldAvailable = ETrue; + } + } + +void CPbkContactInfoAppView::ChangeContactL + (TContactItemId aContactId) + { + // Load the contact + CPbkContactItem* ci = Engine()->ReadContactLC(aContactId); + // Check if the contact content has changed or the contact + // has changed. CPbkContactItem's == operator only compares + // fields, therefore the id check has to be done manually. + if ((aContactId != iContactItem->Id()) || (*ci != *iContactItem)) + { + // Update the UI control + CPbkContactInfoControl* control = iContainer->Control(); + CPbkViewState* controlState = control->GetStateLC(); + control->UpdateL(ci); + control->RestoreStateL(controlState); + CleanupStack::PopAndDestroy(controlState); + // Update members + delete iContactItem; + CleanupStack::Pop(ci); + iContactItem = ci; + UpdateUrlFieldInfo(); + control->DrawNow(); + } + else + { + // Contact data not changed, no need to update + CleanupStack::PopAndDestroy(); // ci + } + } + +CEikStatusPane* CPbkContactInfoAppView::GetStatusPane() const + { + return StatusPane(); + } + +TContactItemId CPbkContactInfoAppView::GetContactItemId() const + { + return iContactItem->Id(); + } + +void CPbkContactInfoAppView::AddObjectSubPaneMenuFilteringL( + CEikMenuPane& aMenuPane, TUint + aFlags + ) + { + if (FeatureManager::FeatureSupported(KFeatureIdCallImagetext)) + { + // If empty contanct then no more execution needed + if (! (aFlags & KPbkControlEmpty) ) + { + if (CodTextFieldEnabled()) + { + if (CodImageFieldEnabled()) + { + aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectImage, ETrue ); + } + else + { + aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectText, ETrue ); + } + } + } + } + else + { + aMenuPane.SetItemDimmed( EPbkCmdCodAddObjectImage, ETrue ); + } + } + +/** + * Command handler: Removes object for call from the contact. + */ +void CPbkContactInfoAppView::CmdRemoveCodL(TInt aFieldType) + { + //PreCond: Field type id should be either Cod image for Cod text. + __ASSERT_DEBUG( ( aFieldType == EPbkFieldIdCodTextID || + aFieldType == EPbkFieldIdCodImageID ), + Panic(EPanicPreCond_CmdRemoveCodL) ); + + TPbkContactItemField* field = iContactItem->FindField( aFieldType ); + if (field && aFieldType == EPbkFieldIdCodTextID ) + { + CPbkContactItem* ci = Engine()->OpenContactLCX(iContactItem->Id()); + ci->RemoveField(iContactItem->FindFieldIndex(*field)); + Engine()->CommitContactL(*ci); + // Update member + CleanupStack::PopAndDestroy(ci); + CleanupStack::PopAndDestroy(); // lock + // UI refresh is handled by HandleDatabaseEventL method in base class + } + else + { + PbkCodImageCmdL().RemoveImageL(iContactItem->Id()); + } + } + +inline void CPbkContactInfoAppView::CmdAddCodFieldL( TInt aCommandId ) + { + __ASSERT_DEBUG( EPbkCmdCodAddObjectImage == aCommandId || + EPbkCmdCodAddObjectText == aCommandId, + Panic(EPanicPreCond_CmdAddCodFieldL) ); + #ifdef _DEBUG + TInt fieldId(EPbkCmdCodAddObjectText==aCommandId? + EPbkFieldIdCodTextID:EPbkFieldIdCodImageID); + // Field info should be found + CPbkFieldInfo* fieldInfo = Engine()->FieldsInfo().Find(fieldId); + #endif + __ASSERT_DEBUG( fieldInfo, + Panic(EPanicFieldInfoNotFound_CmdAddCodFieldL) ); + + if (aCommandId==EPbkCmdCodAddObjectText) + { + // Check if Cod image exists. + if ( CodTextFieldEnabled() && CodImageFieldEnabled() ) + { + // Reset data. + CmdRemoveCodL(EPbkFieldIdCodTextID); + CmdRemoveCodL(EPbkFieldIdCodImageID); + } + HandleCodTextChangeL(iContactItem->Id()); + } + else + { + HandleCodImageChangeL(iContactItem->Id()); + } + } + +inline TBool CPbkContactInfoAppView::HandleCodTextChangeL(TContactItemId aId) const + { + TBool ret(EFalse); + + // Field info should be found + CPbkFieldInfo* fieldInfo = Engine()->FieldsInfo().Find(EPbkFieldIdCodTextID); + __ASSERT_DEBUG( fieldInfo, + Panic( EPanicFieldInfoNotFound_HandleCodTextChangeL ) ); + + CPbkContactItem* ci = Engine()->OpenContactLCX(aId); + // Use text field if exists + TPbkContactItemField* field = ci->FindField( EPbkFieldIdCodTextID ); + if (!field) + { + // Otherwise create new field for filename purposes + field = ci->AddOrReturnUnusedFieldL(*fieldInfo); + } + __ASSERT_DEBUG( field->TextStorage(), + Panic(EPanicTextStorageNotFound_HandleCodTextChangeL) ); + + HBufC* textToBeModified = HBufC::NewMaxLC(KPbkCodTextMaxLength); + CContactTextField& contactTextField = *field->TextStorage(); + textToBeModified->Des().Copy(contactTextField.Text().Left(KPbkCodTextMaxLength)); + TPtr ptr = textToBeModified->Des(); + HBufC* prompt = StringLoader::LoadLC(R_QTN_PHOB_PRTX_TEXT_FOR_CALL); + CAknTextQueryDialog* aknTextQueryDialog = CAknTextQueryDialog::NewL(ptr); + aknTextQueryDialog->SetMaxLength(KPbkCodTextMaxLength); + if (aknTextQueryDialog->ExecuteLD(R_PBK_EDIT_FIELD_TEXT_FOR_QUERY, *prompt)) + { + // The text is set if data query not cancelled + contactTextField.SetTextL(*textToBeModified); + + TPbkContactItemField* imageField=ci->FindField(EPbkFieldIdCodImageID); + if (imageField) + { + // Image can not exist if Cod text field is used. + ci->RemoveField(ci->FindFieldIndex(*field)); + } + Engine()->CommitContactL(*ci); + ret = ETrue; + } + CleanupStack::PopAndDestroy(4); //textToBeModified, prompt, ci, lock + + return ret; + } + +inline void CPbkContactInfoAppView::CmdEditTextCodFieldL() + { + __ASSERT_DEBUG( iContactItem->FindField(EPbkFieldIdCodTextID), + Panic(EPanicPreCond_CmdEditTextCodFieldL) ); + HandleCodTextChangeL(iContactItem->Id()); + } + +inline TBool CPbkContactInfoAppView::HandleCodImageChangeL(TContactItemId aId) + { + return PbkCodImageCmdL().FetchImageL(aId); + } + +CPbkCodImageCmd& CPbkContactInfoAppView::PbkCodImageCmdL() + { + if (!iPbkCodImageCmd) + { + iPbkCodImageCmd = CPbkCodImageCmd::NewL(*Engine()); + } + return *iPbkCodImageCmd; + } + +inline void CPbkContactInfoAppView::CmdViewCodImageL() + { + PbkCodImageCmdL().ViewImageL(iContactItem->Id()); + } + +TBool CPbkContactInfoAppView::CodTextFieldEnabled() const + { + return iContactItem->FindField(EPbkFieldIdCodTextID)?ETrue:EFalse; + } + +TBool CPbkContactInfoAppView::CodImageFieldEnabled() const + { + return iContactItem->FindField(EPbkFieldIdCodImageID)?ETrue:EFalse; + } + +// End of File