phonebookui/Phonebook/View/src/CPbkDataSaveAppUi.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 Phonebook Data Save service helper.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CPbkDataSaveAppUi.h"
       
    22 #include <cntfldst.h>
       
    23 #include <eikmenup.h>
       
    24 #include <avkon.rsg>
       
    25 
       
    26 // PbkView include files
       
    27 #include "PbkDataSaveAppUi.hrh"
       
    28 #include <PbkView.rsg>
       
    29 #include "CPbkContactEditorDlg.h"
       
    30 #include "CPbkSingleEntryFetchDlg.h"
       
    31 #include "CPbkMemoryEntryAddItemDlg.h"
       
    32 #include <CPbkFFSCheck.h>
       
    33 
       
    34 // PbkExt include files
       
    35 #include <CPbkExtGlobals.h>
       
    36 
       
    37 // PbkEng include files
       
    38 #include <CPbkContactEngine.h>
       
    39 #include <CPbkContactItem.h>
       
    40 #include <CPbkFieldInfo.h>
       
    41 
       
    42 
       
    43 /// Unnamed namespace for local definitions
       
    44 namespace {
       
    45 
       
    46 // LOCAL CONSTANTS AND MACROS
       
    47 #ifdef _DEBUG
       
    48 enum TPanicCode
       
    49     {
       
    50     EPanicPreCond_CTextFieldData_AddFieldL = 1,
       
    51     EPanicPreCond_CDateFieldData_AddFieldL,
       
    52     EPanicPreCond_DoHandleCommandL,
       
    53     EPanicPreCond_ResetWhenDestroyed,
       
    54     EPanicPreCond_SelectFieldTypeL,
       
    55     EPanicPreCond_EditContactL,
       
    56     EPanicPreCond_GetContactItemL,
       
    57     EPanicPreCond_ExecuteLD
       
    58     };
       
    59 #endif
       
    60 
       
    61 /**
       
    62  * Flags for CPbkDataSaveAppUi.
       
    63  */
       
    64 enum TFlags
       
    65     {
       
    66     EFlagsHideEditorExit = 0x00000001
       
    67     };
       
    68 
       
    69 
       
    70 // ==================== LOCAL FUNCTIONS ====================
       
    71 
       
    72 #ifdef _DEBUG
       
    73 void Panic(TPanicCode aReason)
       
    74     {
       
    75     _LIT(KPanicText, "CPbkDataSaveAppUi");
       
    76     User::Panic(KPanicText, aReason);
       
    77     }
       
    78 #endif
       
    79 
       
    80 
       
    81 }  // namespace
       
    82 
       
    83 
       
    84 // MODULE DATA STRUCTURES
       
    85 
       
    86 /**
       
    87  * Field adder strategy class for CPbkDataSaveAppUi implementation.
       
    88  * Encapsulates the data to be added to the contact.
       
    89  */
       
    90 class CPbkDataSaveAppUi::MFieldData
       
    91     {
       
    92     public:
       
    93         /**
       
    94          * Virtual destructor.
       
    95          */
       
    96         virtual ~MFieldData() { }
       
    97 
       
    98         /**
       
    99          * Returns the storage type of data to be added.
       
   100          */
       
   101         virtual TUint StorageType() const = 0;
       
   102 
       
   103         /**
       
   104          * Adds a field with data encapsulated in this class in to a contact.
       
   105          *
       
   106          * @param aContact  contact where the field and data is to be added.
       
   107          * @param aFieldType    type of the field to add. 
       
   108          * @param aCallback     calls back to this object if there are 
       
   109          *                      problems when adding the field.
       
   110          * @return  the added field containing data, NULL if field couldn't be
       
   111          *          added.
       
   112          * @precond aFieldType.FieldStorageType()==this->StorageType()
       
   113          */
       
   114         virtual TPbkContactItemField* AddFieldL
       
   115             (CPbkContactItem& aContact, 
       
   116             CPbkFieldInfo& aFieldType,
       
   117             MPbkDataSaveCallback* aCallback) = 0;
       
   118 
       
   119     };
       
   120 
       
   121 /**
       
   122  * Text field data implementation.
       
   123  */
       
   124 NONSHARABLE_CLASS(CPbkDataSaveAppUi::CTextFieldData) : 
       
   125         public CBase, 
       
   126         public CPbkDataSaveAppUi::MFieldData
       
   127     {
       
   128     public:
       
   129         static CTextFieldData* NewLC(const TDesC& aText);
       
   130         ~CTextFieldData();
       
   131 
       
   132     public:  // from MFieldData
       
   133         TUint StorageType() const;
       
   134         TPbkContactItemField* AddFieldL
       
   135             (CPbkContactItem& aContact, 
       
   136             CPbkFieldInfo& aFieldType,
       
   137             MPbkDataSaveCallback* aCallback);
       
   138 
       
   139     private:  // Implementation
       
   140         CTextFieldData();
       
   141 
       
   142     private:  // Data
       
   143         /// Own: text data
       
   144         HBufC* iText;
       
   145     };
       
   146 
       
   147 /**
       
   148  * Date field data implementation.
       
   149  */
       
   150 NONSHARABLE_CLASS(CPbkDataSaveAppUi::CDateFieldData) : 
       
   151         public CBase, 
       
   152         public CPbkDataSaveAppUi::MFieldData
       
   153     {
       
   154     public:
       
   155         static CDateFieldData* NewLC(const TTime& aText);
       
   156 
       
   157     public:  // from MFieldData
       
   158         TUint StorageType() const;
       
   159         TPbkContactItemField* AddFieldL
       
   160             (CPbkContactItem& aContact, 
       
   161             CPbkFieldInfo& aFieldType,
       
   162             MPbkDataSaveCallback* aCallback);
       
   163 
       
   164     private:  // Implementation
       
   165         CDateFieldData();
       
   166 
       
   167     private:  // Data
       
   168         /// Own: date data
       
   169         TTime iDate;
       
   170     };
       
   171 
       
   172 /**
       
   173  * Command base class for CPbkDataSaveAppUi::HandleCommandL implementation.
       
   174  */
       
   175 NONSHARABLE_CLASS(CPbkDataSaveAppUi::CCommandBase) : 
       
   176         public CBase
       
   177     {
       
   178     public:  // Interface
       
   179         /**
       
   180          * Command intialisation data.
       
   181          */
       
   182         struct TData
       
   183             {
       
   184             /// Own: the command id to execute
       
   185             TInt iCommandId;
       
   186             /// Ref: Phonebook engine
       
   187             CPbkContactEngine* iEngine;
       
   188             /// Ref: field types to apply
       
   189             CArrayPtr<CPbkFieldInfo>* iFieldTypes;
       
   190             /// Ref: field data to save
       
   191             MFieldData* iFieldData;
       
   192             /// Ref: callback interface
       
   193             MPbkDataSaveCallback* iCallback;
       
   194             /// Own: copy of CPbkDataSaveAppUi's flags
       
   195             TUint iFlags;
       
   196             };
       
   197 
       
   198         /**
       
   199          * Resets aSelfPtr to NULL when this object is destroyed.
       
   200          * @precond !aSelfPtr || *aSelfPtr==this
       
   201          */
       
   202         void ResetWhenDestroyed(CCommandBase** aSelfPtr);
       
   203 
       
   204         /**
       
   205          * Executes this command
       
   206          */
       
   207         TBool ExecuteLD();
       
   208 
       
   209         /**
       
   210          * Destructor.
       
   211          */
       
   212         ~CCommandBase();
       
   213 
       
   214     protected:  // Interface
       
   215         /**
       
   216          * Constructor.
       
   217          */
       
   218         CCommandBase();
       
   219 
       
   220         /**
       
   221          * Creates/Reads the contact item where to add data.
       
   222          */
       
   223         virtual CPbkContactItem* GetContactItemL() = 0;
       
   224 
       
   225         /**
       
   226          * Creates the field type dialog to use in SelectFieldTypeL.
       
   227          */
       
   228         virtual CPbkMemoryEntryAddItemDlg* CreateFieldTypeDialogL() = 0;
       
   229 
       
   230         /**
       
   231          * Selects field type.
       
   232          * @param aFieldTypes   types where to select from.
       
   233          * @return selected field type or NULL if canceled or nothing to select.
       
   234          */
       
   235         CPbkFieldInfo* SelectFieldTypeL(CArrayPtr<CPbkFieldInfo>& aFieldTypes);
       
   236 
       
   237         /**
       
   238          * Opens contact editor for a contact.
       
   239          *
       
   240          * @param aContact  contact to be edited.
       
   241          * @param aField    field to focus intially in the editor.
       
   242          * @return ETrue if contact was saved, EFalse otherwise.
       
   243          */
       
   244         TBool EditContactL
       
   245             (CPbkContactItem& aContact, const TPbkContactItemField& aField);
       
   246 
       
   247         /**
       
   248          * Returns the index of the field to be focused in the contact editor
       
   249          * dialog. Default implementation returns aField's index in aContact's
       
   250          * field set.
       
   251          */
       
   252         virtual TInt FocusedFieldIndex
       
   253             (CPbkContactItem& aContact,
       
   254             const TPbkContactItemField& aField) const;
       
   255 
       
   256         /**
       
   257          * Returns ETrue if this command modfies a new contact, EFalse 
       
   258          * otherwise.
       
   259          */
       
   260         virtual TBool NewContact() = 0;
       
   261 
       
   262         /**
       
   263          * Filters applicable field types according to what new fields the
       
   264          * contact can accept and compabilty between field type and storage
       
   265          * type.
       
   266          *
       
   267          * @param aContact  contact where the field is to be added.
       
   268          * @param aFieldTypes   list of field types to be filtered.
       
   269          * @param aStorageType  type of data to be added to the field.
       
   270          * @return new filtered array of field types.
       
   271          */
       
   272         CArrayPtr<CPbkFieldInfo>* GetFilterFieldTypesLC
       
   273             (const CPbkContactItem& aContact, 
       
   274             CArrayPtr<CPbkFieldInfo>& aFieldTypes,
       
   275             TUint aStorageType);
       
   276 
       
   277         /**
       
   278          * Returns true field type aFieldType should be included in selectable 
       
   279          * types. Checks if the new field can be added to aContact and that the
       
   280          * field type is compatible with aStorageType.
       
   281          */
       
   282         TBool FieldTypeIncluded
       
   283             (CPbkFieldInfo& aFieldType,
       
   284             const CPbkContactItem& aContact, 
       
   285             TUint aStorageType);
       
   286 
       
   287     protected:  // Data
       
   288         /// Own: data
       
   289         TData iData;
       
   290 
       
   291     private: // Implementation
       
   292         NONSHARABLE_CLASS(TSelfCleanup)
       
   293             {
       
   294             public:
       
   295                 inline TSelfCleanup(CCommandBase* aSelf) : iSelf(aSelf) 
       
   296                     { 
       
   297                     }
       
   298                 inline operator TCleanupItem()
       
   299                     {
       
   300                     return TCleanupItem(Cleanup,this);
       
   301                     }
       
   302                 inline void Reset() { iSelf=NULL; }
       
   303             private:
       
   304                 static void Cleanup(TAny* aObject);
       
   305                 CCommandBase* iSelf;
       
   306             };
       
   307 
       
   308     private:  // Data
       
   309         /// Ref: referred pointer is set to NULL in destructor
       
   310         CCommandBase** iSelfPtr;
       
   311         /// Own: for cleanup purposes
       
   312         TSelfCleanup* iSelfCleanup;
       
   313         /// Own: iContactItem
       
   314         CPbkContactItem* iContactItem;
       
   315         /// Own: add item dialog
       
   316         CPbkMemoryEntryAddItemDlg* iItemTypeDlg;
       
   317         /// Own: editor dialog
       
   318         CPbkContactEditorDlg* iEditDlg;
       
   319     };
       
   320 
       
   321 /**
       
   322  * Command implementation for Create New service.
       
   323  */
       
   324 NONSHARABLE_CLASS(CPbkDataSaveAppUi::CCreateNewCommand) : 
       
   325         public CPbkDataSaveAppUi::CCommandBase
       
   326     {
       
   327     public:  // Interface
       
   328         static CCreateNewCommand* NewL(const TData& aData);
       
   329 
       
   330     public:  // from CCommandBase
       
   331         CPbkContactItem* GetContactItemL();
       
   332         CPbkMemoryEntryAddItemDlg* CreateFieldTypeDialogL();
       
   333         TInt FocusedFieldIndex
       
   334             (CPbkContactItem& aContact,
       
   335             const TPbkContactItemField& aField) const;
       
   336         TBool NewContact();
       
   337 
       
   338     private:  // Implementation
       
   339         CCreateNewCommand();
       
   340     };
       
   341 
       
   342 /**
       
   343  * Command implementation for Add to Existing service.
       
   344  */
       
   345 NONSHARABLE_CLASS(CPbkDataSaveAppUi::CAddToExistingCommand) : 
       
   346         public CPbkDataSaveAppUi::CCommandBase
       
   347     {
       
   348     public:  // Interface
       
   349         static CAddToExistingCommand* NewL(const TData& aData);
       
   350         ~CAddToExistingCommand();
       
   351 
       
   352     public:  // from CCommandBase
       
   353         CPbkContactItem* GetContactItemL();
       
   354         CPbkMemoryEntryAddItemDlg* CreateFieldTypeDialogL();
       
   355         TBool NewContact();
       
   356 
       
   357     private:  // Implementation
       
   358         CAddToExistingCommand();
       
   359 
       
   360     private:  // Data
       
   361         /// Own: Active fetch dialog
       
   362         CPbkSingleEntryFetchDlg* iFetchDlg;
       
   363     };
       
   364 
       
   365 
       
   366 // ==================== MEMBER FUNCTIONS ====================
       
   367 
       
   368 ////////////////////////////////////////////////////////////
       
   369 // CPbkDataSaveAppUi
       
   370 inline CPbkDataSaveAppUi::CPbkDataSaveAppUi(CPbkContactEngine& aEngine) :
       
   371     iEngine(&aEngine),
       
   372     iBaseCommandId(EPbkCmdDataSaveBase)
       
   373     {
       
   374     // CBase::operator new() will reset other members
       
   375     }
       
   376 
       
   377 inline void CPbkDataSaveAppUi::ConstructL()
       
   378     {
       
   379     iFFSCheck = CPbkFFSCheck::NewL();
       
   380 
       
   381     // Keep a handle to the UI extension factory in this dialog to prevent 
       
   382     // multiple inits of the factory by the subdialogs that are launched by
       
   383     // this service.
       
   384     iExtGlobals = CPbkExtGlobals::InstanceL();
       
   385     }
       
   386 
       
   387 EXPORT_C CPbkDataSaveAppUi* CPbkDataSaveAppUi::NewL
       
   388         (CPbkContactEngine& aEngine)
       
   389     {
       
   390     CPbkDataSaveAppUi* self = new(ELeave) CPbkDataSaveAppUi(aEngine);
       
   391     CleanupStack::PushL(self);
       
   392     self->ConstructL();
       
   393     CleanupStack::Pop(self);
       
   394     return self;
       
   395     }
       
   396 
       
   397 CPbkDataSaveAppUi::~CPbkDataSaveAppUi()
       
   398     {
       
   399     delete iExecutingCommand;
       
   400     Release(iExtGlobals);
       
   401     delete iFFSCheck;
       
   402     }
       
   403 
       
   404 EXPORT_C void CPbkDataSaveAppUi::AddMenuItemsL
       
   405         (CEikMenuPane* aMenuPane, TInt aCommandId)
       
   406     {
       
   407     // Store base command id
       
   408     iBaseCommandId = aCommandId;
       
   409     // Store replaced menu item's position
       
   410     TInt pos;
       
   411     aMenuPane->ItemAndPos(aCommandId, pos);
       
   412     // Add data save submenu after marker item
       
   413     aMenuPane->AddMenuItemsL(R_PBK_DATA_SAVE_MENU, aCommandId);
       
   414     // Delete marker item from the menu
       
   415     aMenuPane->DeleteBetweenMenuItems(pos,pos);
       
   416     }
       
   417 
       
   418 EXPORT_C void CPbkDataSaveAppUi::DynInitMenuPaneL(TInt aResourceId, CEikMenuPane* aMenuPane)
       
   419     {
       
   420     if (aResourceId == R_PBK_DATA_SAVE_SUBMENU)
       
   421         {
       
   422         // Patch command ids of the submenu to be relative to iBaseCommandId
       
   423         CEikMenuPaneItem::SData& createNewItemData = 
       
   424             aMenuPane->ItemData(EPbkCmdDataSaveCreateNew);
       
   425         CEikMenuPaneItem::SData& addToExistingItemData =
       
   426             aMenuPane->ItemData(EPbkCmdDataSaveAddToExisting); 
       
   427         createNewItemData.iCommandId += iBaseCommandId;
       
   428         addToExistingItemData.iCommandId += iBaseCommandId;
       
   429         }
       
   430     }
       
   431 
       
   432 EXPORT_C TBool CPbkDataSaveAppUi::HandleCommandL
       
   433         (TInt aCommandId, 
       
   434         CArrayPtr<CPbkFieldInfo>& aFieldTypes,
       
   435         const TDesC& aText,
       
   436         MPbkDataSaveCallback* aCallback/*=NULL*/)
       
   437     {
       
   438     TBool result = EFalse;
       
   439     if (iFFSCheck->FFSClCheckL())
       
   440         {
       
   441         // Pack data into a MFieldData wrapper
       
   442         CTextFieldData* fieldData = CTextFieldData::NewLC(aText);
       
   443         result = DoHandleCommandL
       
   444             (aCommandId, aFieldTypes, *fieldData, aCallback);
       
   445         CleanupStack::PopAndDestroy();  // fieldData
       
   446         }
       
   447     return result;
       
   448     }
       
   449 
       
   450 EXPORT_C void CPbkDataSaveAppUi::HideEditorExitCommand()
       
   451     {
       
   452     iFlags |= EFlagsHideEditorExit;
       
   453     }
       
   454 
       
   455 EXPORT_C TBool CPbkDataSaveAppUi::HandleCommandL
       
   456         (TInt aCommandId, 
       
   457         CArrayPtr<CPbkFieldInfo>& aFieldTypes,
       
   458         const TTime& aDate,
       
   459         MPbkDataSaveCallback* aCallback/*=NULL*/)
       
   460     {
       
   461     TBool result = EFalse;
       
   462     if (iFFSCheck->FFSClCheckL())
       
   463         {
       
   464         // Pack data into a MFieldData wrapper
       
   465         CDateFieldData* fieldData = CDateFieldData::NewLC(aDate);
       
   466         result = DoHandleCommandL
       
   467             (aCommandId, aFieldTypes, *fieldData, aCallback);
       
   468         CleanupStack::PopAndDestroy();  // fieldData
       
   469         }
       
   470     return result;
       
   471     }
       
   472 
       
   473 TBool CPbkDataSaveAppUi::DoHandleCommandL
       
   474         (TInt aCommandId, 
       
   475         CArrayPtr<CPbkFieldInfo>& aFieldTypes,
       
   476         MFieldData& aFieldData,
       
   477         MPbkDataSaveCallback* aCallback)
       
   478     {
       
   479     // Create command object parameter data
       
   480     __ASSERT_DEBUG(!iExecutingCommand, Panic(EPanicPreCond_DoHandleCommandL));
       
   481 
       
   482     CCommandBase::TData cmdData;
       
   483     cmdData.iCommandId = aCommandId-iBaseCommandId;
       
   484     cmdData.iEngine = iEngine;
       
   485     cmdData.iFieldTypes = &aFieldTypes;
       
   486     cmdData.iFieldData = &aFieldData;
       
   487     cmdData.iFlags = iFlags;
       
   488 
       
   489     // Default callback object
       
   490     MPbkDataSaveCallback defaultCallback;
       
   491     if (aCallback)
       
   492         {
       
   493         cmdData.iCallback = aCallback;
       
   494         }
       
   495     else
       
   496         {
       
   497         cmdData.iCallback = &defaultCallback;
       
   498         }
       
   499 
       
   500     // Create a command object
       
   501     TBool result = EFalse;
       
   502     switch (cmdData.iCommandId)
       
   503         {
       
   504         case EPbkCmdDataSaveCreateNew:
       
   505             {
       
   506             iExecutingCommand = CCreateNewCommand::NewL(cmdData);
       
   507             break;
       
   508             }
       
   509         case EPbkCmdDataSaveAddToExisting:
       
   510             {
       
   511             iExecutingCommand = CAddToExistingCommand::NewL(cmdData);
       
   512             break;
       
   513             }
       
   514         }
       
   515 
       
   516     if (iExecutingCommand)
       
   517         {
       
   518         iExecutingCommand->ResetWhenDestroyed(&iExecutingCommand);
       
   519         result = iExecutingCommand->ExecuteLD();
       
   520         }
       
   521 
       
   522     return result;
       
   523     }
       
   524 
       
   525 
       
   526 ////////////////////////////////////////////////////////////
       
   527 // CPbkDataSaveAppUi::CTextFieldData
       
   528 
       
   529 inline CPbkDataSaveAppUi::CTextFieldData::CTextFieldData()
       
   530     {
       
   531     // operator new(TLeave) resets member data
       
   532     }
       
   533 
       
   534 CPbkDataSaveAppUi::CTextFieldData* CPbkDataSaveAppUi::CTextFieldData::NewLC
       
   535         (const TDesC& aText)
       
   536     {
       
   537     CTextFieldData* self = new(ELeave) CTextFieldData;
       
   538     CleanupStack::PushL(self);
       
   539     self->iText = aText.AllocL();
       
   540     return self;
       
   541     }
       
   542 
       
   543 CPbkDataSaveAppUi::CTextFieldData::~CTextFieldData()
       
   544     {
       
   545     delete iText;
       
   546     }
       
   547 
       
   548 TUint CPbkDataSaveAppUi::CTextFieldData::StorageType() const
       
   549     {
       
   550     return KStorageTypeText;
       
   551     }
       
   552 
       
   553 TPbkContactItemField* CPbkDataSaveAppUi::CTextFieldData::AddFieldL
       
   554         (CPbkContactItem& aContact, 
       
   555         CPbkFieldInfo& aFieldInfo,
       
   556         MPbkDataSaveCallback* aCallback)
       
   557     {
       
   558     __ASSERT_DEBUG(aFieldInfo.FieldStorageType() == StorageType(), 
       
   559         Panic(EPanicPreCond_CTextFieldData_AddFieldL));
       
   560 
       
   561     TPtrC text = *iText;
       
   562     if (text.Length() > aFieldInfo.MaxLength())
       
   563         {
       
   564         if (aCallback)
       
   565             {
       
   566             text.Set(aCallback->PbkDataSaveClipTextL(*iText, aFieldInfo));
       
   567             // Give up if text is still too long
       
   568             if (text.Length() > aFieldInfo.MaxLength())
       
   569                 {
       
   570                 User::Leave(KErrOverflow);
       
   571                 }
       
   572             }
       
   573         else
       
   574             {
       
   575             text.Set(iText->Left(aFieldInfo.MaxLength()));
       
   576             }
       
   577         }
       
   578 
       
   579     // Don't add an empty field
       
   580     if (text.Length() == 0)
       
   581         {
       
   582         return NULL;
       
   583         }
       
   584 
       
   585     // Add field and text into it leave-safely
       
   586     HBufC* textBuf = text.AllocLC();
       
   587     TPbkContactItemField* field = aContact.AddOrReturnUnusedFieldL(aFieldInfo);
       
   588     CleanupStack::Pop();  // textBuf
       
   589     field->TextStorage()->SetText(textBuf);
       
   590     return field;
       
   591     }
       
   592 
       
   593 
       
   594 ////////////////////////////////////////////////////////////
       
   595 // CPbkDataSaveAppUi::CDateFieldData
       
   596 
       
   597 inline CPbkDataSaveAppUi::CDateFieldData::CDateFieldData()
       
   598     {
       
   599     // operator new(TLeave) resets member data
       
   600     }
       
   601 
       
   602 CPbkDataSaveAppUi::CDateFieldData* CPbkDataSaveAppUi::CDateFieldData::NewLC
       
   603         (const TTime& aDate)
       
   604     {
       
   605     CDateFieldData* self = new(ELeave) CDateFieldData;
       
   606     CleanupStack::PushL(self);
       
   607     self->iDate = aDate;
       
   608     return self;
       
   609     }
       
   610 
       
   611 TUint CPbkDataSaveAppUi::CDateFieldData::StorageType() const
       
   612     {
       
   613     return KStorageTypeDateTime;
       
   614     }
       
   615 
       
   616 TPbkContactItemField* CPbkDataSaveAppUi::CDateFieldData::AddFieldL
       
   617         (CPbkContactItem& aContact, 
       
   618         CPbkFieldInfo& aFieldInfo,
       
   619         MPbkDataSaveCallback* /*aCallback*/)
       
   620     {
       
   621     __ASSERT_DEBUG(aFieldInfo.FieldStorageType() == StorageType(), 
       
   622         Panic(EPanicPreCond_CDateFieldData_AddFieldL));
       
   623     TPbkContactItemField* field = aContact.AddOrReturnUnusedFieldL(aFieldInfo);
       
   624     field->DateTimeStorage()->SetTime(iDate);
       
   625     return field;
       
   626     }
       
   627 
       
   628 
       
   629 ////////////////////////////////////////////////////////////
       
   630 // CPbkDataSaveAppUi::CCommandBase
       
   631 
       
   632 inline CPbkDataSaveAppUi::CCommandBase::CCommandBase()
       
   633     {
       
   634     // operator new(TLeave) resets member data
       
   635     }
       
   636 
       
   637 void CPbkDataSaveAppUi::CCommandBase::ResetWhenDestroyed(CCommandBase** aSelfPtr)
       
   638     {
       
   639     __ASSERT_DEBUG(!aSelfPtr || *aSelfPtr==this, Panic(EPanicPreCond_ResetWhenDestroyed));
       
   640 
       
   641     iSelfPtr = aSelfPtr;
       
   642     }
       
   643 
       
   644 TBool CPbkDataSaveAppUi::CCommandBase::ExecuteLD()
       
   645     {
       
   646     __ASSERT_DEBUG(!iContactItem, Panic(EPanicPreCond_ExecuteLD));
       
   647 
       
   648     TSelfCleanup selfCleanup(this);
       
   649     iSelfCleanup = &selfCleanup;
       
   650     CleanupStack::PushL(selfCleanup);
       
   651 
       
   652     TBool result = EFalse;
       
   653     iContactItem = GetContactItemL();
       
   654     if (iContactItem)
       
   655         {
       
   656         CArrayPtr<CPbkFieldInfo>* filteredFieldTypes = GetFilterFieldTypesLC
       
   657             (*iContactItem, *iData.iFieldTypes, iData.iFieldData->StorageType());
       
   658 
       
   659         CPbkFieldInfo* fieldType = NULL;
       
   660         if (filteredFieldTypes->Count() > 1)
       
   661             {
       
   662             fieldType = SelectFieldTypeL(*filteredFieldTypes);
       
   663             }
       
   664         else if (filteredFieldTypes->Count() == 1)
       
   665             {
       
   666             fieldType = (*filteredFieldTypes)[0];
       
   667             }
       
   668         else
       
   669             {
       
   670             if (iData.iCallback) 
       
   671                 {
       
   672                 iData.iCallback->PbkDataSaveNoFieldL(*iContactItem);
       
   673                 }
       
   674             }
       
   675 
       
   676         TPbkContactItemField* field = NULL;
       
   677         if (fieldType)
       
   678             {
       
   679             field = iData.iFieldData->AddFieldL(*iContactItem, *fieldType, iData.iCallback);
       
   680             }
       
   681 
       
   682         if (field)
       
   683             {
       
   684             result = EditContactL(*iContactItem, *field);
       
   685             }
       
   686 
       
   687         CleanupStack::PopAndDestroy();  // filteredFieldTypes
       
   688         }
       
   689 
       
   690     CleanupStack::PopAndDestroy();  // selfCleanup
       
   691     return result;
       
   692     }
       
   693 
       
   694 CPbkDataSaveAppUi::CCommandBase::~CCommandBase()
       
   695     {
       
   696     if (iSelfCleanup)
       
   697         {
       
   698         // Prevent double deletion through cleanup stack
       
   699         iSelfCleanup->Reset();
       
   700         }
       
   701     if (iSelfPtr)
       
   702         {
       
   703         *iSelfPtr = NULL;
       
   704         }
       
   705     delete iItemTypeDlg;
       
   706     delete iEditDlg;
       
   707     if (iContactItem)
       
   708         {
       
   709         // CpbkContactEngine::CloseContactL() never leaves despite its name
       
   710         iData.iEngine->CloseContactL(iContactItem->Id());
       
   711         delete iContactItem;
       
   712         }
       
   713     }
       
   714 
       
   715 CPbkFieldInfo* CPbkDataSaveAppUi::CCommandBase::SelectFieldTypeL
       
   716         (CArrayPtr<CPbkFieldInfo>& aFieldTypes)
       
   717     {
       
   718     __ASSERT_DEBUG(!iItemTypeDlg, Panic(EPanicPreCond_SelectFieldTypeL));
       
   719     iItemTypeDlg = CreateFieldTypeDialogL();
       
   720     iItemTypeDlg->ResetWhenDestroyed(&iItemTypeDlg);
       
   721     CPbkFieldInfo* result = NULL;
       
   722     result = iItemTypeDlg->ExecuteLD(aFieldTypes);
       
   723     return result;
       
   724     }
       
   725 
       
   726 TBool CPbkDataSaveAppUi::CCommandBase::EditContactL
       
   727         (CPbkContactItem& aContact, const TPbkContactItemField& aField)
       
   728     {
       
   729     __ASSERT_DEBUG(!iEditDlg, Panic(EPanicPreCond_EditContactL));
       
   730 
       
   731     const TInt fieldIndex = FocusedFieldIndex(aContact,aField);
       
   732 	iEditDlg = CPbkContactEditorDlg::NewL
       
   733         (*iData.iEngine, aContact, NewContact(), fieldIndex, ETrue);
       
   734     iEditDlg->ResetWhenDestroyed(&iEditDlg);
       
   735     if (iData.iFlags & EFlagsHideEditorExit)
       
   736         {
       
   737         iEditDlg->HideExitCommand();
       
   738         }
       
   739 	TBool result = EFalse;
       
   740     result = iEditDlg->ExecuteLD() != KNullContactId; 
       
   741     return result;
       
   742     }
       
   743 
       
   744 TInt CPbkDataSaveAppUi::CCommandBase::FocusedFieldIndex
       
   745         (CPbkContactItem& aContact,
       
   746         const TPbkContactItemField& aField) const
       
   747     {
       
   748     return aContact.FindFieldIndex(aField);
       
   749     }
       
   750 
       
   751 inline TBool CPbkDataSaveAppUi::CCommandBase::FieldTypeIncluded
       
   752         (CPbkFieldInfo& aFieldType,
       
   753         const CPbkContactItem& aContact, 
       
   754         TUint aStorageType)
       
   755     {
       
   756     return 
       
   757         (aFieldType.FieldStorageType()==aStorageType &&
       
   758         aFieldType.IsEditable() &&
       
   759         aContact.CanAcceptDataOfType(aFieldType) &&
       
   760         aFieldType.UserCanAddField() );
       
   761     }
       
   762 
       
   763 CArrayPtr<CPbkFieldInfo>* CPbkDataSaveAppUi::CCommandBase::GetFilterFieldTypesLC
       
   764         (const CPbkContactItem& aContact, 
       
   765         CArrayPtr<CPbkFieldInfo>& aFieldTypes,
       
   766         TUint aStorageType)
       
   767     {
       
   768     CArrayPtrFlat<CPbkFieldInfo>* filteredFieldTypes = 
       
   769         new(ELeave) CArrayPtrFlat<CPbkFieldInfo>(1 /*realloc granularity*/);
       
   770     CleanupStack::PushL(filteredFieldTypes);
       
   771     const TInt count = aFieldTypes.Count();
       
   772     filteredFieldTypes->SetReserveL(count);
       
   773     for (TInt i = 0; i < count; ++i)
       
   774         {
       
   775         CPbkFieldInfo* fieldType = aFieldTypes[i];
       
   776         if (FieldTypeIncluded(*fieldType,aContact,aStorageType))
       
   777             {
       
   778             filteredFieldTypes->AppendL(fieldType);
       
   779             }
       
   780         }
       
   781     return filteredFieldTypes;
       
   782     }
       
   783 
       
   784 void CPbkDataSaveAppUi::CCommandBase::TSelfCleanup::Cleanup(TAny* aObject)
       
   785     {
       
   786     delete (static_cast<TSelfCleanup*>(aObject)->iSelf);
       
   787     }
       
   788 
       
   789 
       
   790 ////////////////////////////////////////////////////////////
       
   791 // CPbkDataSaveAppUi::CCreateNewCommand
       
   792 
       
   793 inline CPbkDataSaveAppUi::CCreateNewCommand::CCreateNewCommand()
       
   794     {
       
   795     // operator new(TLeave) resets member data
       
   796     }
       
   797 
       
   798 CPbkDataSaveAppUi::CCreateNewCommand* CPbkDataSaveAppUi::CCreateNewCommand::NewL
       
   799         (const TData& aData)
       
   800     {
       
   801     CCreateNewCommand* self = new(ELeave) CCreateNewCommand;
       
   802     self->iData = aData;
       
   803     return self;
       
   804     }
       
   805 
       
   806 CPbkContactItem* CPbkDataSaveAppUi::CCreateNewCommand::GetContactItemL()
       
   807     {
       
   808     CPbkContactItem* ci = iData.iEngine->CreateEmptyContactL();
       
   809     return ci;
       
   810     }
       
   811 
       
   812 CPbkMemoryEntryAddItemDlg* CPbkDataSaveAppUi::CCreateNewCommand::CreateFieldTypeDialogL()
       
   813     {
       
   814     return new(ELeave) CPbkItemTypeSelectCreateNew;
       
   815     }
       
   816 
       
   817 TInt CPbkDataSaveAppUi::CCreateNewCommand::FocusedFieldIndex
       
   818         (CPbkContactItem& /*aContact*/,
       
   819         const TPbkContactItemField& /*aField*/) const
       
   820     {
       
   821     // Always focus the first field
       
   822     return 0;
       
   823     }
       
   824 
       
   825 TBool CPbkDataSaveAppUi::CCreateNewCommand::NewContact()
       
   826     {
       
   827     return ETrue;
       
   828     }
       
   829 
       
   830 
       
   831 ////////////////////////////////////////////////////////////
       
   832 // CPbkDataSaveAppUi::CAddToExistingCommand
       
   833 
       
   834 inline CPbkDataSaveAppUi::CAddToExistingCommand::CAddToExistingCommand()
       
   835     {
       
   836     // operator new(TLeave) resets member data
       
   837     }
       
   838 
       
   839 CPbkDataSaveAppUi::CAddToExistingCommand* CPbkDataSaveAppUi::CAddToExistingCommand::NewL
       
   840         (const TData& aData)
       
   841     {
       
   842     CAddToExistingCommand* self = new(ELeave) CAddToExistingCommand;
       
   843     self->iData = aData;
       
   844     return self;
       
   845     }
       
   846 
       
   847 CPbkDataSaveAppUi::CAddToExistingCommand::~CAddToExistingCommand()
       
   848     {
       
   849     delete iFetchDlg;
       
   850     }
       
   851 
       
   852 CPbkContactItem* CPbkDataSaveAppUi::CAddToExistingCommand::GetContactItemL()
       
   853     {
       
   854     __ASSERT_DEBUG(!iFetchDlg, Panic(EPanicPreCond_GetContactItemL));
       
   855 
       
   856     // Run Single Entry Fetch
       
   857     CPbkSingleEntryFetchDlg::TParams params;
       
   858     params.iContactView = &iData.iEngine->AllContactsView();
       
   859 	params.iCbaId = R_PBK_SOFTKEYS_SINGLE_ENTRY_FETCH;
       
   860 
       
   861     iFetchDlg = CPbkSingleEntryFetchDlg::NewL(params);
       
   862     iFetchDlg->ResetWhenDestroyed(&iFetchDlg);
       
   863 	TInt res = 0;
       
   864     res = iFetchDlg->ExecuteLD();
       
   865 
       
   866     CPbkContactItem* ci = NULL;
       
   867     if (res && params.iSelectedEntry != KNullContactId)
       
   868         {
       
   869         ci = iData.iEngine->OpenContactL(params.iSelectedEntry);
       
   870         }
       
   871     return ci;
       
   872     }
       
   873 
       
   874 CPbkMemoryEntryAddItemDlg* CPbkDataSaveAppUi::CAddToExistingCommand::CreateFieldTypeDialogL()
       
   875     {
       
   876     return new(ELeave) CPbkItemTypeSelectAddToExisting;
       
   877     }
       
   878 
       
   879 TBool CPbkDataSaveAppUi::CAddToExistingCommand::NewContact()
       
   880     {
       
   881     return EFalse;
       
   882     }
       
   883 
       
   884 
       
   885 ////////////////////////////////////////////////////////////
       
   886 // MPbkDataSaveCallback default implementation
       
   887 
       
   888 EXPORT_C void MPbkDataSaveCallback::PbkDataSaveNoFieldL
       
   889         (CPbkContactItem& /*aContact*/)
       
   890     {
       
   891     }
       
   892 
       
   893 EXPORT_C TPtrC MPbkDataSaveCallback::PbkDataSaveClipTextL
       
   894         (const TDesC& aText, CPbkFieldInfo& aFieldInfo)
       
   895     {
       
   896     return aText.Left(aFieldInfo.MaxLength());
       
   897     }
       
   898 
       
   899 // End of File