diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookui/Phonebook2/ServerApplication/src/CPbk2MultiAssignDataPhase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/ServerApplication/src/CPbk2MultiAssignDataPhase.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,676 @@ +/* +* Copyright (c) 2005-2007 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: Phonebook 2 server app contact data assign phase. +* +*/ + + +#include "CPbk2MultiAssignDataPhase.h" + +// Phonebook 2 +#include "MPbk2ServicePhaseObserver.h" +#include "CPbk2ServerAppAppUi.h" +#include "Pbk2ServerApp.hrh" +#include "MPbk2ContactAssigner.h" +#include "Pbk2ContactAssignerFactory.h" +#include "MPbk2SelectFieldProperty.h" +#include "TPbk2AssignNoteService.h" +#include "Pbk2AssignValidateField.h" +#include "CPbk2KeyEventDealer.h" +#include +#include +#include +#include +#include +#include + +// Virtual Phonebook +#include +#include +#include +#include +#include +#include +#include +#include + +// System includes +#include + +using namespace AiwContactAssign; + +/// Unnamed namespace for local definitions +namespace { + +const TInt KFirstElement = 0; +const TInt KGranularity = 4; + +/** + * Copies a link array to another. + * + * @param aSourceLinkArray Link array which is copied + * @param aTargetLinkArray Links are copied to this + */ +void CopyContactLinksL( const MVPbkContactLinkArray& aSourceLinkArray, + CVPbkContactLinkArray& aTargetLinkArray ) + { + const TInt count = aSourceLinkArray.Count(); + for ( TInt i(0); i < count; ++i ) + { + const MVPbkContactLink& contactLink = aSourceLinkArray.At(i); + aTargetLinkArray.AppendL( contactLink.CloneLC() ); + CleanupStack::Pop(); // link + } + } + +} /// namespace + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::CPbk2MultiAssignDataPhase +// -------------------------------------------------------------------------- +// +CPbk2MultiAssignDataPhase::CPbk2MultiAssignDataPhase + ( MPbk2ServicePhaseObserver& aObserver, + MPbk2SelectFieldProperty* aSelectedFieldProperty, + HBufC* aDataBuffer, TInt aMimeType, TUint aNoteFlags ) : + iObserver( aObserver ), + iSelectedFieldProperty( aSelectedFieldProperty ), + iDataBuffer( aDataBuffer ), + iMimeType( aMimeType ), + iNoteFlags( aNoteFlags ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::~CPbk2MultiAssignDataPhase +// -------------------------------------------------------------------------- +// +CPbk2MultiAssignDataPhase::~CPbk2MultiAssignDataPhase() + { + delete iResults; + delete iContactDataAssigner; + delete iContactLinks; + delete iRetrieveOperation; + delete iCommitOperation; + delete iStoreContact; + delete iDealer; + if ( iStoreContacts ) + { + iStoreContacts->ResetAndDestroy(); + } + delete iStoreContacts; + + if ( iDestroyedPtr ) + { + *iDestroyedPtr = ETrue; + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::ConstructL +// -------------------------------------------------------------------------- +// +inline void CPbk2MultiAssignDataPhase::ConstructL + ( MVPbkContactLinkArray* aContactLinks ) + { + iEikenv = CEikonEnv::Static(); + + iContactLinks = CVPbkContactLinkArray::NewL(); + // Take a own copy of supplied contact links + CopyContactLinksL( *aContactLinks, *iContactLinks ); + + iDealer = CPbk2KeyEventDealer::NewL( *this ); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::NewL +// -------------------------------------------------------------------------- +// +CPbk2MultiAssignDataPhase* CPbk2MultiAssignDataPhase::NewL + ( MPbk2ServicePhaseObserver& aObserver, + MVPbkContactLinkArray* aContactLinks, + MPbk2SelectFieldProperty* aSelectedFieldProperty, + HBufC* aDataBuffer, TInt aMimeType, TUint aNoteFlags ) + { + CPbk2MultiAssignDataPhase* self = + new ( ELeave ) CPbk2MultiAssignDataPhase + ( aObserver, aSelectedFieldProperty, + aDataBuffer, aMimeType, aNoteFlags ); + CleanupStack::PushL( self ); + self->ConstructL( aContactLinks ); + CleanupStack::Pop( self ); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::LaunchServicePhaseL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::LaunchServicePhaseL() + { + ContinueL(); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::CancelServicePhase +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::CancelServicePhase() + { + iOperationCancelled = ETrue; + iObserver.PhaseCanceled( *this ); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::RequestCancelL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::RequestCancelL( TInt aExitCommandId ) + { + // Withdraw our key event agent so that it does not react to + // app shutter's escape key event simulation + delete iDealer; + iDealer = NULL; + + iOperationCancelled = ETrue; + + if ( aExitCommandId == EEikBidCancel ) + { + iObserver.PhaseAborted( *this ); + } + else + { + iObserver.PhaseCanceled( *this ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AcceptDelayed +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AcceptDelayedL + ( const TDesC8& /*aContactLinkBuffer*/ ) + { + // Nothing to do + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::DenyDelayed +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::DenyDelayedL + ( const TDesC8& /*aContactLinkBuffer*/ ) + { + // Nothing to do + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::Results +// -------------------------------------------------------------------------- +// +MVPbkContactLinkArray* CPbk2MultiAssignDataPhase::Results() const + { + return iResults; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::ExtraResultData +// -------------------------------------------------------------------------- +// +TInt CPbk2MultiAssignDataPhase::ExtraResultData() const + { + return KErrNotSupported; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::TakeStoreContact +// -------------------------------------------------------------------------- +// +MVPbkStoreContact* CPbk2MultiAssignDataPhase::TakeStoreContact() + { + // Not supported + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::FieldContent +// -------------------------------------------------------------------------- +// +HBufC* CPbk2MultiAssignDataPhase::FieldContent() const + { + return NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AssignComplete +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AssignComplete + ( MPbk2ContactAssigner& /*aAssigner*/, TInt /*aIndex*/ ) + { + MVPbkStoreContact* storeContact = iStoreContact; + iStoreContact = NULL; + TRAPD( err, AppendResultAndContinueL( storeContact ) ); + if ( err != KErrNone ) + { + iObserver.PhaseError( *this, err ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AssignFailed +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AssignFailed + ( MPbk2ContactAssigner& /*aAssigner*/, TInt aErrorCode ) + { + iObserver.PhaseError( *this, aErrorCode ); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::ContactOperationCompleted +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::ContactOperationCompleted + ( TContactOpResult aResult ) + { + if ( aResult.iOpCode == EContactLock ) + { + TRAPD( err, AssignDataL() ); + + if ( err != KErrNone && err != KErrDied ) + { + iObserver.PhaseError( *this, err ); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::ContactOperationFailed +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::ContactOperationFailed + ( TContactOp /*aOpCode*/, TInt aErrorCode, TBool /*aErrorNotified*/ ) + { + // If the contact operation failed, the iStoreContact is expected to be deleted, + // otherwise it will lead to memory leak. + if ( iStoreContact ) + { + delete iStoreContact; + iStoreContact = NULL; + } + + // if iContactsProcessed > 0, the note (how many contacts had been processed) needs to be shown. + if ( (iContactLinks->Count() > 0) || (iContactsProcessed > 0) ) + { + ContinueL(); + } + else + { + iObserver.PhaseError( *this, aErrorCode ); + } + + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::VPbkSingleContactOperationComplete +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::VPbkSingleContactOperationComplete + ( MVPbkContactOperationBase& /*aOperation*/, + MVPbkStoreContact* aContact ) + { + iStoreContact = aContact; + TRAPD( err, iStoreContact->LockL( *this ) ); + if ( err != KErrNone ) + { + iObserver.PhaseError( *this, err ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::VPbkSingleContactOperationFailed +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::VPbkSingleContactOperationFailed + ( MVPbkContactOperationBase& /*aOperation*/, TInt aError ) + { + iObserver.PhaseError( *this, aError ); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::StepComplete +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::StepComplete + ( MVPbkContactOperationBase& /*aOperation*/, TInt /*aStepSize*/ ) + { + // Do nothing + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::StepFailed +// -------------------------------------------------------------------------- +// +TBool CPbk2MultiAssignDataPhase::StepFailed + ( MVPbkContactOperationBase& /*aOperation*/, TInt /*aStepSize*/, + TInt aError ) + { + iObserver.PhaseError( *this, aError ); + + // Do not continue + return EFalse; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::OperationComplete +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::OperationComplete + ( MVPbkContactOperationBase& /*aOperation*/ ) + { + // Commit done, we can finish now + Finalize(); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::Pbk2ProcessKeyEventL +// -------------------------------------------------------------------------- +// +TBool CPbk2MultiAssignDataPhase::Pbk2ProcessKeyEventL + ( const TKeyEvent& aKeyEvent, TEventCode aType ) + { + TBool ret = EFalse; + + if ( aType == EEventKey && aKeyEvent.iCode == EKeyEscape ) + { + iObserver.PhaseOkToExit( *this, EEikBidCancel ); + ret = ETrue; + } + + return ret; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AssignDataL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AssignDataL() + { + const MVPbkFieldType* fieldType = NULL; + if ( iSelectedFieldProperty ) + { + fieldType = iSelectedFieldProperty->SelectedFieldType(); + } + + if ( fieldType ) + { + MVPbkStoreContactField* contactField = NULL; + if ( SelectContactFieldL( contactField ) ) + { + CPbk2ServerAppAppUi& appUi = static_cast + ( *iEikenv->EikAppUi() ); + + delete iContactDataAssigner; + iContactDataAssigner = NULL; + iContactDataAssigner = + Pbk2ContactAssignerFactory::CreateContactDataAssignerL + ( *this, iMimeType, fieldType, + appUi.ApplicationServices().ContactManager(), + appUi.ApplicationServices().FieldProperties() ); + + iContactDataAssigner->AssignDataL + ( *iStoreContact, contactField, fieldType, iDataBuffer ); + } + else + { + ContinueL(); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::SelectContactFieldL +// -------------------------------------------------------------------------- +// +TBool CPbk2MultiAssignDataPhase::SelectContactFieldL + ( MVPbkStoreContactField*& aField ) + { + TBool ret = ETrue; + + TBool thisDestroyed = EFalse; + iDestroyedPtr = &thisDestroyed; + TPbk2DestructionIndicator indicator( &thisDestroyed, iDestroyedPtr ); + + CPbk2ServerAppAppUi& appUi = static_cast + ( *iEikenv->EikAppUi() ); + + CPbk2PresentationContact* contact = + CPbk2PresentationContact::NewL( *iStoreContact, + appUi.ApplicationServices().FieldProperties() ); + CleanupStack::PushL( contact ); + + // Check is the field type already used up in the contact + TInt fieldIndex = KErrNotSupported; + TInt result = + Pbk2AssignValidateField::ValidateFieldTypeUsageInContactL + ( *contact, *iSelectedFieldProperty->SelectedFieldType(), + appUi.ApplicationServices().ContactManager().FsSession(), + fieldIndex ); + + switch( result ) + { + case KErrAlreadyExists: + { + // Contact already has the one and only suitable contact + // field filled up, show replace detail query + TPbk2AssignNoteService noteService; + TInt queryResult = noteService.ShowReplaceDetailQueryL + ( appUi.ApplicationServices().NameFormatter(), + *iStoreContact ); + if ( !queryResult ) + { + ret = EFalse; + } + else if ( !thisDestroyed ) + { + // Set contact field to existing field so it gets replaced + aField = &iStoreContact->Fields().FieldAt( fieldIndex ); + } + break; + } + case KErrPathNotFound: + { + // Set contact field to existing field so it gets replaced + aField = &iStoreContact->Fields().FieldAt( fieldIndex ); + break; + } + case KErrNotFound: // FALLTHROUGH + case KErrNone: + { + // Contact does not have the field type used, or does have + // it used but supports more fields of that type. + // Return value stays at ETrue. + break; + } + default: + { + // If result was any other error code + if ( result < KErrNone ) + { + TPbk2AssignNoteService noteService; + noteService.ShowCanNotAddDetailNoteL + ( appUi.ApplicationServices().NameFormatter(), + *iStoreContact ); + ret = EFalse; + } + break; + } + }; + + CleanupStack::PopAndDestroy( contact ); + + if ( thisDestroyed || iOperationCancelled ) + { + // The calling code excepts us to leave with KErrDied if + // this was destroyed + User::Leave( KErrDied ); + } + + return ret; + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AppendResultL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AppendResultL + ( MVPbkStoreContact* aStoreContact ) + { + if ( aStoreContact ) + { + CleanupDeletePushL( aStoreContact ); + + // Add the contact link to the result array + MVPbkContactLink* link = aStoreContact->CreateLinkLC(); + if ( link ) + { + if ( !iResults ) + { + iResults = CVPbkContactLinkArray::NewL(); + } + + CleanupStack::Pop(); // aStoreContact->CreateLinkLC() + + iResults->AppendL( link ); + } + + if ( !iStoreContacts ) + { + iStoreContacts = new ( ELeave ) + CArrayPtrFlat( KGranularity ); + } + + // Add contact to the array of store contacts + // to be commited later + CleanupStack::Pop(); // aStoreContact + iStoreContacts->AppendL( aStoreContact ); // takes ownership + ++iContactsProcessed; + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::DisplayNotesL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::DisplayNotesL() + { + CPbk2ServerAppAppUi& appUi = static_cast + ( *iEikenv->EikAppUi() ); + CPbk2StorePropertyArray& array = + appUi.ApplicationServices().StoreProperties(); + + TPbk2AssignNoteService noteService; + noteService.ShowDetailAddedNoteL( iContactsProcessed ); + + TVPbkContactStoreUriPtr store + ( VPbkContactStoreUris::DefaultCntDbUri() ); + if ( iNoteFlags & KPbk2NoteFlagOneContactRelocated ) + { + noteService.ShowInformationNoteL + ( R_QTN_PHOB_NOTE_CONTACT_HIDDEN, store, array ); + } + else if ( iNoteFlags & KPbk2NoteFlagSeveralContactsRelocated ) + { + noteService.ShowInformationNoteL + ( R_QTN_PHOB_NOTE_CONTACTS_HIDDEN, store, array ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::AppendResultAndContinueL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::AppendResultAndContinueL + ( MVPbkStoreContact* aContact ) + { + AppendResultL( aContact ); + ContinueL(); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::RetrieveContactL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::RetrieveContactL() + { + CPbk2ServerAppAppUi& appUi = static_cast + ( *iEikenv->EikAppUi() ); + + // Retrieve one contact at a time + delete iRetrieveOperation; + iRetrieveOperation = NULL; + iRetrieveOperation = appUi.ApplicationServices().ContactManager(). + RetrieveContactL( iContactLinks->At( KFirstElement ), *this ); + iContactLinks->Delete( KFirstElement ); + } +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::CommitContactsL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::CommitContactsL() + { + CPbk2ServerAppAppUi& appUi = static_cast + ( *iEikenv->EikAppUi() ); + + // All contacts have been processed, commit changes + delete iCommitOperation; + iCommitOperation = NULL; + iCommitOperation = appUi.ApplicationServices().ContactManager(). + CommitContactsL( iStoreContacts->Array(), *this ); + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::ContinueL +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::ContinueL() + { + if ( iContactLinks->Count() > 0 ) + { + RetrieveContactL(); + } + else if ( iStoreContacts && iStoreContacts->Count() > 0 ) + { + CommitContactsL(); + } + else + { + Finalize(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2MultiAssignDataPhase::Finalize +// -------------------------------------------------------------------------- +// +void CPbk2MultiAssignDataPhase::Finalize() + { + // Safe to ignore the error, it concerns only showing notes + TRAP_IGNORE( DisplayNotesL(); ); + + iObserver.NextPhase( *this ); + } + +// End of File