phonebookui/Phonebook/View/src/CPbkFetchDlg.cpp
changeset 0 e686773b3f54
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/View/src/CPbkFetchDlg.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,873 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*       Provides methods for Fetch dialog for Phonebook.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbkFetchDlg.h"   // This class
+#include <barsread.h>       // TResourceReader
+#include <avkon.rsg>        // AVKON resource IDs
+#include <aknnavide.h>      // CAknNavigationDecorator
+#include <aknappui.h>       // CEikAppUi
+#include <PbkView.rsg>              // Phonebook view dll resource IDs
+#include <AknUtils.h> 
+#include <CPbkContactIdSet.h>
+#include <TPbkContactViewIterator.h>
+#include <CPbkExtGlobals.h>
+
+#include <PbkView.hrh>              // Phonebook view dll resource constants
+#include "CPbkContextPaneIcon.h"
+#include "MPbkFetchDlgPage.h"
+#include "PbkFetchDlgPageFactory.h"
+#include "MPbkFetchCallbacks.h"
+#include "MPbkFetchDlgSelection.h"
+#include <CPbkContactViewListControl.h>
+#include <PbkIconInfo.h>
+#include <akntabgrp.h>					// CAknTabGroup
+#include <AknsUtils.h>
+#include <PbkDebug.h>
+
+
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+enum TPanicCode
+    {
+    EPanicNullContactView = 1,
+    EPanicPreCond_ConstructL,
+    EPanicInvalidResourceData,
+    EPanicPreCond_PreLayoutDynInitL,
+    EPanicPostCond_PreLayoutDynInitL,
+    EPanicPreCond_ResetWhenDestroyed,
+    };
+
+
+// ==================== LOCAL FUNCTIONS ====================
+
+void Panic(TInt aReason)
+    {
+    _LIT(KPanicText, "CPbkFetchDlg");
+    User::Panic(KPanicText, aReason);
+    }
+
+/**
+ * Returns ETrue if all dialog pages in aPages are ready.
+ */
+TBool AllPagesReady(const MPbkFetchDlgPages& aPages)
+    {
+    const TInt count = aPages.DlgPageCount();
+    for (TInt i=0; i < count; ++i)
+        {
+        if (!aPages.DlgPageAt(i).DlgPageReady())
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+    }
+
+}  // namespace
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// CPbkFetchDlg::TParams
+CPbkFetchDlg::TParams::TParams() :
+    iFlags(FETCH_FOCUSED),
+    iResId(R_PBK_SINGLE_ENTRY_FETCH_DLG),
+    iContactView(NULL),
+    iKeyCallback(NULL),
+    iAcceptCallback(NULL),
+    iFetchSelection(NULL),                    
+    iCbaId(0),    
+    iFocusedEntry(KNullContactId),
+    iMarkedEntries(NULL)
+    {
+    }
+
+CPbkFetchDlg::TParams::operator TCleanupItem()
+    {
+    return TCleanupItem(Cleanup,this);
+    }
+
+void CPbkFetchDlg::TParams::Cleanup(TAny* aPtr)
+    {
+    TParams* self = static_cast<TParams*>(aPtr);
+    self->iFocusedEntry = KNullContactId;
+    delete self->iMarkedEntries;
+    self->iMarkedEntries = NULL;
+    }
+
+
+// CPbkFetchDlg::TResData
+inline void CPbkFetchDlg::TResData::ReadFromResource(TResourceReader& aReader)
+    {
+    iDialogId   = aReader.ReadInt32();
+    iCbaId      = aReader.ReadInt32();
+    iEmptyCbaId = aReader.ReadInt32();
+    iNaviPaneId = aReader.ReadInt32();
+    }
+
+
+// CPbkFetchDlg
+inline CPbkFetchDlg::CPbkFetchDlg
+        (TParams& aParams, 
+        CPbkContactEngine& aEngine) :
+    iParams(aParams),
+    iEngine(aEngine),
+    iPreviousStatusPaneLayout(KErrNotFound)
+    {
+    // CBase::operator new(TLeave) resets other member data
+    }
+
+CPbkFetchDlg* CPbkFetchDlg::NewL
+        (TParams& aParams, 
+        CPbkContactEngine& aEngine)
+    {
+    // PreCond
+    __ASSERT_ALWAYS(aParams.iContactView, Panic(EPanicNullContactView));
+
+    CPbkFetchDlg* dlg = new(ELeave) CPbkFetchDlg(aParams, aEngine);
+    CleanupStack::PushL(dlg);
+    dlg->ConstructL();
+    CleanupStack::Pop(dlg);
+    return dlg;
+    }
+
+CPbkFetchDlg::~CPbkFetchDlg()
+    {
+    delete iTabSkinDelay;
+    if (iSelfPtr)
+        {
+        *iSelfPtr = NULL;
+        }
+    Release(iExtGlobals);
+    delete iPages;
+    delete iNaviDecorator;
+    delete iContextPaneIcon;
+    delete iSelectedIdSet;
+    delete iDialogAccepter;
+    }
+
+void CPbkFetchDlg::ResetWhenDestroyed(CPbkFetchDlg** aSelfPtr)
+    {
+    __ASSERT_DEBUG(!aSelfPtr || *aSelfPtr == this, 
+            Panic(EPanicPreCond_ResetWhenDestroyed));
+
+    iSelfPtr = aSelfPtr;
+    }
+
+TInt CPbkFetchDlg::ExecuteLD()
+    {
+    TBool canceled = EFalse;
+    iCanceledPtr = &canceled;
+    iContextPaneIcon = CPbkContextPaneIcon::NewL(*iEikonEnv);
+    
+    // Status pane layout switching made.
+    // Otherwise status pane layout problems could occur 
+    // e.g. when no contacts in fetch dialog.
+    // Calling app has to restore the layout if different.
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+    TInt statusPaneLayout = KErrNotFound;
+    if (statusPane)
+        {
+        statusPaneLayout = statusPane->CurrentLayoutResId();
+        statusPane->SwitchLayoutL(R_AVKON_STATUS_PANE_LAYOUT_USUAL);
+        }
+    TInt res = CEikDialog::ExecuteLD(iResData.iDialogId);
+
+    if (statusPane && (statusPaneLayout != KErrNotFound))
+        {
+        statusPane->SwitchLayoutL(statusPaneLayout);
+        }
+
+    return canceled ? 0 : res;
+    }
+
+void CPbkFetchDlg::ConstructL()
+    {
+    __ASSERT_DEBUG(iParams.iContactView, Panic(EPanicPreCond_ConstructL));
+
+    // Read resources
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC(reader, iParams.iResId);
+    iResData.ReadFromResource(reader);
+    __ASSERT_ALWAYS(iResData.iDialogId != 0, Panic(EPanicInvalidResourceData));
+    __ASSERT_ALWAYS(iResData.iCbaId != 0, Panic(EPanicInvalidResourceData));
+    __ASSERT_ALWAYS(iResData.iEmptyCbaId != 0, Panic(EPanicInvalidResourceData));
+    CleanupStack::PopAndDestroy();  // reader
+
+    iSelectedIdSet = CPbkContactIdSet::NewL();
+
+    // Keep a handle to the UI extension factory in this dialog to prevent 
+    // multiple inits of the factory by this dialog's subobjects
+    iExtGlobals = CPbkExtGlobals::InstanceL();
+    
+    TCallBack accepter( TryAcceptSelectionL, this );
+    iDialogAccepter =
+        new (ELeave) CAsyncCallBack( accepter, CActive::EPriorityStandard );
+
+    CAknDialog::ConstructL(R_PBK_EMPTY_MENU_PANE);
+
+    // dialog tabs appears status pane stack only after dialog is fully
+    // constructed, so we need to delay tab skinning. Even in PostLayoutDyninit
+    // tab group is wrong
+    iTabSkinDelay = CIdle::NewL( CActive::EPriorityLow );
+    iTabSkinDelay->Start( TCallBack( DelaySkinning, this ));
+    }
+
+SEikControlInfo CPbkFetchDlg::CreateCustomControlL(TInt aControlType)
+    {
+    SEikControlInfo ctrl;
+    ctrl.iControl = NULL;
+    ctrl.iTrailerTextId = 0;
+    ctrl.iFlags = 0;
+    ctrl.iControl = PbkFetchDlgPageFactory::CreateCustomControlL(aControlType);
+    return ctrl;
+    }
+
+void CPbkFetchDlg::PreLayoutDynInitL()
+    {
+    // PreCond
+    __ASSERT_DEBUG(iParams.iContactView, Panic(EPanicPreCond_PreLayoutDynInitL));
+
+    CEikDialog::PreLayoutDynInitL();
+
+    SetupStatusPaneL();
+
+    iPages = PbkFetchDlgPageFactory::CreatePagesL(*this);
+    if (iParams.iFetchSelection)
+	    {
+	    iPages->DlgPageWithId(ECtrlFetchNamesList)->
+	    	SetMPbkFetchDlgSelection(iParams.iFetchSelection);
+	    iPages->DlgPageWithId(ECtrlFetchGroupsList)->
+	    	SetMPbkFetchDlgSelection(iParams.iFetchSelection);
+	    }
+    iCurrentPage = iPages->DlgPageWithId(ECtrlFetchNamesList);
+    iCurrentPage->ActivateFetchDlgPageL();
+
+    if ( AknLayoutUtils::MSKEnabled() )
+        {
+        // Set this as MSK observer to be able to receive MSK events.       
+        CEikButtonGroupContainer& bgc = ButtonGroupContainer();            
+        CEikCba* cba;
+        cba = ( static_cast<CEikCba*>( bgc.ButtonGroup() ) ); // downcast from MEikButtonGroup
+        cba->SetMSKCommandObserver(this);    
+        }
+        
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        // Add observer for contact item double tap events
+        const TInt count = iPages->DlgPageCount();
+        for ( TInt i = 0; i < count; ++i )
+            {
+            iPages->DlgPageAt(i).Control().AddObserverL(*this);
+            }
+        }
+    
+    __ASSERT_DEBUG(iPages && iCurrentPage, Panic(EPanicPostCond_PreLayoutDynInitL));
+    }
+    
+void CPbkFetchDlg::ProcessCommandL(TInt aCommandId)
+    {
+    // This method gets called if CPbkFetckDlg has been set as
+    // MSK observer. 
+    
+    // close the menu, otherwise problems with FEP
+    HideMenu();
+    
+    if (!iCurrentPage->IsFetchDlgPageEmpty() &&
+        iCurrentPage->ProcessSoftkeyMarkCommandL(aCommandId))
+        {        
+        if ( aCommandId == EAknSoftkeyMark )
+            {
+            iCurrentPage->Control().MarkItemL(iCurrentPage->FocusedContactIdL(), ETrue);
+            }
+        else if ( aCommandId == EAknSoftkeyUnmark )
+            {
+            iCurrentPage->Control().MarkItemL(iCurrentPage->FocusedContactIdL(), EFalse);
+            }
+        // update the label of MSK
+        UpdateMSKL( iCurrentPage->Control().CurrentItemIndex() );
+        }
+    }
+
+TBool CPbkFetchDlg::OkToExitL(TInt aButtonId)
+    {    
+    // normally OkToExitL -method is called when we are really
+    // exiting this dialog, but since the MSK came to the 
+    // picture, all the MSK related softkeys are handled here.
+    // so, we're not going to exit the dialog, just ignore all
+    // softkey events related to MSK, those are handled in ProcessCommandL.
+    if ( aButtonId == EAknSoftkeyMark ||
+         aButtonId == EAknSoftkeyUnmark ||
+         aButtonId == EAknSoftkeyEmpty )
+        {                    
+        return EFalse;        
+        }       
+    
+    // Reset return values
+    TBool result = ETrue;
+    iParams.iFocusedEntry = KNullContactId;
+    iParams.iMarkedEntries = NULL;
+    
+	
+
+    if (iParams.iFlags & FETCH_FOCUSED)
+        {
+        const TContactItemId focusId = 
+            iPages->DlgPageWithId(ECtrlFetchNamesList)->FocusedContactIdL();
+        if (focusId != KNullContactId)
+            {
+            iParams.iFocusedEntry = focusId;
+            }
+        else
+            {
+            if (!(iParams.iFlags & FETCH_MARKED))
+                {
+                // Don't close the dialog if there is no focus, probably
+                // the focus is missing because find text has filtered
+                // the list box empty.
+                result = EFalse;
+                }
+            }
+        }
+
+    if (iParams.iFlags & FETCH_MARKED)
+        {
+        // Copy marked entries set to iParams.iMarkedEntries in the same order
+        // they appear in iParams.iContactView        
+        TPbkContactViewIterator iter(*iParams.iContactView);
+        TContactItemId contactId;
+
+        delete iParams.iMarkedEntries;
+        iParams.iMarkedEntries = NULL;
+        iParams.iMarkedEntries = CContactIdArray::NewLC();
+        
+        while ((contactId = iter.NextL()) != KNullContactId)
+            {
+            if (iSelectedIdSet->Find(contactId))
+                {
+                iParams.iMarkedEntries->AddL(contactId);
+                }
+            }
+        
+        // Can't destroy the iMarkedEntries, these entries need to return to client as
+        // the fetch datum.
+        CleanupStack::Pop(iParams.iMarkedEntries);
+        }
+
+    // Run accept callback if specified and this dialog is being accepted
+    if (result && iParams.iAcceptCallback)
+        {
+        MPbkFetchDlgAccept::TPbkFetchAccepted res = 
+            iParams.iAcceptCallback->PbkFetchAcceptedL(iParams.iFocusedEntry, iParams.iMarkedEntries);
+        switch (res)
+            {
+            case MPbkFetchDlgAccept::KFetchYes:
+                {
+                result = ETrue;
+                break;
+                }
+            case MPbkFetchDlgAccept::KFetchCanceled:
+                {
+                iParams.iFocusedEntry = KNullContactId;
+                delete iParams.iMarkedEntries;
+                iParams.iMarkedEntries = NULL;
+                result = ETrue;
+                if (iCanceledPtr) 
+                    {
+                    *iCanceledPtr = ETrue;
+                    }
+                break;
+                }
+            case MPbkFetchDlgAccept::KFetchNo:
+                {
+                result = EFalse;
+                break;
+                }
+            }
+        }
+
+    switch (aButtonId)
+        {
+        case EAknSoftkeyBack:       // FALLTHROUGH
+        case EAknSoftkeyCancel:     // FALLTHROUGH
+        case EAknSoftkeyClose:      // FALLTHROUGH
+        case EAknSoftkeyNo:         // FALLTHROUGH
+        case EAknSoftkeyExit:
+            {
+            if (iCanceledPtr) 
+                {
+                *iCanceledPtr = ETrue;
+                }
+            break;
+            }
+
+        case EAknSoftkeyOk:
+            {
+            // Markable list -dialog shouldn't be closed if there are no marked
+            // items in current page. This happens if a selection accepter
+            // didn't accept the selection of focused item when EAknSoftkeyOk
+            // was pressed. If we close the dialog the User might think that
+            // selection succeeded. Now we stay in the dialog and give the
+            // selection accepter a change to show some error message about
+            // failed selection
+            if ( result && (iParams.iFlags & FETCH_MARKED) && 
+                iCurrentPage && !iCurrentPage->ItemsMarked())
+                {
+                result = EFalse;
+                }
+            break;
+            } 
+        }
+
+    return result;
+    }
+
+void CPbkFetchDlg::PageChangedL(TInt aPageId)
+    {
+    MPbkFetchDlgPage* newPage = iPages->DlgPageWithId(aPageId);
+    if (newPage)
+        {
+        newPage->ActivateFetchDlgPageL();
+        if (iCurrentPage)
+            {
+            iCurrentPage->DeactivateFetchDlgPage();
+            }
+        iCurrentPage = newPage;
+        	    
+	    if ( iParams.iFlags & FETCH_FOCUSED )
+	        {
+	        // this is for single fetch	                  	    
+	        UpdateCbasL();	        
+	        }
+	    else
+	        {	        
+            // for multiple fetch and MSK
+            // first update the CBA set
+            UpdateCbasL();
+	        TInt index = iCurrentPage->Control().CurrentItemIndex();
+	        if ( index != KErrNotFound && AknLayoutUtils::MSKEnabled())
+                {	            
+	            // if MSK enable, update it.
+	            UpdateMSKL(index);
+	            }
+            
+            }
+        }
+    }
+    
+void CPbkFetchDlg::UpdateMSKL( TInt aIndex )
+    {    
+	// do not update MSK for single fetch dialog
+    if ( !(iParams.iFlags & FETCH_FOCUSED) )                
+        {
+        
+        TBool hasSelected (iCurrentPage->Control().ItemMarked(aIndex));
+        
+        if ( hasSelected )
+            {
+            CEikButtonGroupContainer& cba = ButtonGroupContainer();
+            cba.SetCommandL(3,R_AVKON_SOFTKEY_UNMARK);
+            cba.DrawDeferred();
+            }        
+        else
+            {
+            CEikButtonGroupContainer& cba = ButtonGroupContainer();            
+            cba.SetCommandL(3,R_AVKON_SOFTKEY_MARK);
+            cba.DrawDeferred();        
+            }
+        }   
+    }
+
+void CPbkFetchDlg::HandleContactViewListControlEventL(
+        CPbkContactViewListControl& /*aControl*/,
+        const TPbkContactViewListControlEvent& aEvent)
+    {
+    switch ( aEvent.iEventType )
+        {
+        case TPbkContactViewListControlEvent::EContactDoubleTapped:
+            {
+            if ( iParams.iFlags & FETCH_FOCUSED )
+                {
+                // Single item/entry fetch, try to accept the dialog
+                iDialogAccepter->Cancel();
+                iDialogAccepter->CallBack();
+                break;
+                }
+            // else fallthrough
+            }
+        case TPbkContactViewListControlEvent::EContactTapped:   // fallthrough
+        case TPbkContactViewListControlEvent::EContactSelected: // fallthrough
+        case TPbkContactViewListControlEvent::EContactUnselected:
+            {
+            UpdateMSKL( iCurrentPage->Control().CurrentItemIndex() );
+            break;
+            }
+        default:;
+        }
+    
+    if ( aEvent.iEventType ==
+            TPbkContactViewListControlEvent::EContactDoubleTapped ||
+         aEvent.iEventType ==
+            TPbkContactViewListControlEvent::EContactTapped )
+        {
+        if ( iCurrentPage->Control().ItemMarked(
+                iCurrentPage->Control().CurrentItemIndex() ) )
+            {
+            iCurrentPage->ProcessSoftkeyMarkCommandL( EAknSoftkeyMark );
+            }
+        else
+            {
+            iCurrentPage->ProcessSoftkeyMarkCommandL( EAknSoftkeyUnmark );
+            }
+        }
+    }        
+
+TInt CPbkFetchDlg::TryAcceptSelectionL( TAny* aSelf )
+    {
+    static_cast<CPbkFetchDlg*>( aSelf )->TryExitL( EEikBidOk );
+    return KErrNone;
+    }
+
+TKeyResponse CPbkFetchDlg::OfferKeyEventL
+        (const TKeyEvent& aKeyEvent,
+        TEventCode aType)
+    {
+    // if the MSK is enabled, multiple dialog needs to know
+    // which contact is going to be focused and set the 
+    // label of MSK referring is the certain contact marked
+    // or not, or has limited multiple fetch count already
+    // achieved.
+    if ( AknLayoutUtils::MSKEnabled() )
+        {
+        if ( !iCurrentPage->IsFetchDlgPageEmpty() )
+            {
+            if ( ( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow ) &&
+                 aType == EEventKey )
+                {        
+                TInt index = iCurrentPage->Control().CurrentItemIndex();                            
+                
+                if ( aKeyEvent.iCode == EKeyUpArrow )
+                    {
+                    index--;
+                    if (index < 0)
+                        {
+                        // set the index to the last in the list
+                        index = iCurrentPage->Control().ItemCount() - 1;                    
+                        }     
+                    }
+                if ( aKeyEvent.iCode == EKeyDownArrow )
+                    {
+                    index++;
+                    if (index >= iCurrentPage->Control().ItemCount() )
+                        {
+                        // set the index to first in the list
+                        index = 0;
+                        }     
+                    }                                       
+                UpdateCbasL();       
+                UpdateMSKL( index );
+                }
+            }
+        }
+
+    if (iParams.iKeyCallback)
+        {
+        MPbkFetchKeyCallback::TResult result = 
+            iParams.iKeyCallback->PbkFetchKeyCallbackL(aKeyEvent, aType);
+        
+        switch (result)
+            {
+            case MPbkFetchKeyCallback::EKeyWasNotConsumed:
+                {
+                break;
+                }
+            case MPbkFetchKeyCallback::EKeyWasConsumed:
+                {
+                return EKeyWasConsumed;
+                }
+            case MPbkFetchKeyCallback::EAccept:
+                {
+                TryExitL(EEikBidOk);
+                return EKeyWasConsumed;
+                }
+            case MPbkFetchKeyCallback::ECancel:
+                {
+                TryExitL(EEikBidCancel);
+                return EKeyWasConsumed;
+                }
+			default:
+				{
+				break;
+				}
+            }
+        }
+    return CEikDialog::OfferKeyEventL(aKeyEvent, aType);
+    }
+
+CCoeControl* CPbkFetchDlg::FetchDlgControl(TInt aCtrlId) const
+    {
+    return ControlOrNull(aCtrlId);
+    }
+
+CContactViewBase& CPbkFetchDlg::FetchDlgNamesView() const
+    {
+    return *iParams.iContactView;
+    }
+
+CPbkContactIdSet& CPbkFetchDlg::FetchDlgSelection()
+    {
+    return *iSelectedIdSet;
+    }
+
+void CPbkFetchDlg::FetchDlgHandleError(TInt aError)
+    {
+    iEikonEnv->HandleError(aError);
+    }
+
+TRect CPbkFetchDlg::FetchDlgClientRect() const
+    {
+    TRect appRect = iAvkonAppUi->ApplicationRect();
+    TAknLayoutRect mainPane;
+    mainPane.LayoutRect(appRect, AKN_LAYOUT_WINDOW_main_pane(appRect,0,1,1));
+    return mainPane.Rect();    
+    }
+
+CPbkContactEngine& CPbkFetchDlg::PbkEngine()
+    {
+    return iEngine;
+    }
+
+void CPbkFetchDlg::FetchDlgPageChangedL(MPbkFetchDlgPage& /*aPage*/)
+    {
+    if ( iParams.iFlags & FETCH_FOCUSED )
+        {
+        UpdateCbasL();	        
+        }
+    else
+        {
+        UpdateCbasL();
+        if ( AknLayoutUtils::MSKEnabled() )
+            {
+            // update also the MSK
+            TInt index = iCurrentPage->Control().CurrentItemIndex();
+	        if ( index != KErrNotFound )
+	            {                
+                UpdateMSKL(index);
+                }
+            }        
+        }
+    }
+
+void CPbkFetchDlg::SetCbaCommandSetL(TInt aResourceId)
+    {
+    if (aResourceId != iCbaCommandSet)
+        {
+        CEikButtonGroupContainer& cba = ButtonGroupContainer();
+        cba.SetCommandSetL(aResourceId);
+        iCbaCommandSet = aResourceId;
+        cba.DrawDeferred();
+        }
+    }
+
+void CPbkFetchDlg::SetupStatusPaneL()
+    {
+    delete iNaviDecorator;
+    iNaviDecorator = NULL;
+    
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+    if (statusPane)
+        {
+        // Setup navi pane if defined in resources
+        if (iResData.iNaviPaneId && 
+            statusPane->PaneCapabilities
+            (TUid::Uid(EEikStatusPaneUidNavi)).IsPresent())
+            {
+            CAknNavigationControlContainer* naviPane = 
+                static_cast<CAknNavigationControlContainer*> 
+                (statusPane->ControlL(TUid::Uid(EEikStatusPaneUidNavi)));
+            TResourceReader reader;
+            iCoeEnv->CreateResourceReaderLC(reader, iResData.iNaviPaneId);
+            iNaviDecorator =
+                naviPane->ConstructNavigationDecoratorFromResourceL(reader);
+            naviPane->PushL(*iNaviDecorator);
+            CleanupStack::PopAndDestroy();  // reader
+            }
+        }
+    }
+
+void CPbkFetchDlg::HandleResourceChange(TInt aType)
+    {    
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+    if (aType == KEikDynamicLayoutVariantSwitch)
+        {
+        // Layout dialog itself
+        SetRect( iAvkonAppUi->ClientRect() );
+        // Layout dialog page controls
+        const TInt count(iPages->DlgPageCount());
+        for (TInt i = 0; i < count; ++i)
+            {
+            iPages->DlgPageAt(i).LayoutContents();
+            }
+        // If the fetch dialog has been launched in landscape mode, 
+        // and then later changed to the portrait mode, the icon has to 
+        // be set again, otherwise there will be shown the icon of
+        // the "parent" -application.
+        delete iContextPaneIcon;            
+        iContextPaneIcon = NULL;        
+        TRAP_IGNORE(iContextPaneIcon = CPbkContextPaneIcon::NewL(*iEikonEnv));
+
+        if (statusPane)
+            {
+            TRAP_IGNORE(statusPane->SwitchLayoutL(
+                R_AVKON_STATUS_PANE_LAYOUT_USUAL));
+            }
+        }
+    else if (aType == KAknsMessageSkinChange)
+        {
+        // Just visual effect, no need to handle error
+        TRAP_IGNORE( SkinTabsL() );
+        }
+        
+    if (statusPane)
+		{
+		statusPane->HandleResourceChange(aType);
+		}    
+		
+	CAknDialog::HandleResourceChange(aType);
+    }
+    
+// --------------------------------------------------------------------------
+// CPbkFetchDlg::LineChangedL
+// --------------------------------------------------------------------------
+//
+void CPbkFetchDlg::LineChangedL(TInt /*aControlId*/)
+    {
+    // never gets called
+    }
+
+// --------------------------------------------------------------------------
+// CPbkFetchDlg::UpdateCbasL
+// --------------------------------------------------------------------------
+//
+void CPbkFetchDlg::UpdateCbasL()
+    {
+    if ( AllPagesReady(*iPages) && 
+    		iCurrentPage && !iCurrentPage->IsFetchDlgPageEmpty() )
+    	{       		        	
+    	// Use user defined cba resources if exist
+	    if (iParams.iCbaId)
+	        {
+	        SetCbaCommandSetL(iParams.iCbaId);
+	        }    	        
+	    else if ( iResData.iCbaId )
+	        {
+	        SetCbaCommandSetL( iResData.iCbaId );
+	        }
+	    
+	    // Resources for single fetch
+	    else if ( iParams.iFlags & FETCH_FOCUSED )
+	    	{
+	    	SetCbaCommandSetL( R_PBK_SOFTKEYS_OK_BACK_OK );
+	    	} 
+	    // Resources for multiple fetch
+	    else
+	        {
+	        SetCbaCommandSetL(R_PBK_SOFTKEYS_OK_BACK_MARK);	  
+	        }
+    	}
+    else
+    	{    	
+    	SetCbaCommandSetL(iResData.iEmptyCbaId);
+    	}
+    }    
+
+// --------------------------------------------------------------------------
+// CPbkFetchDlg::SkinTabsL
+// --------------------------------------------------------------------------
+//
+void CPbkFetchDlg::SkinTabsL()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL start"));
+    CEikStatusPane* statusPane = iAvkonAppUi->StatusPane();
+
+    if (statusPane && statusPane->PaneCapabilities
+		(TUid::Uid(EEikStatusPaneUidNavi)).IsPresent())
+        {
+        CAknNavigationControlContainer* naviPane =
+			static_cast<CAknNavigationControlContainer*>
+			(statusPane->ControlL(TUid::Uid(EEikStatusPaneUidNavi)));
+        CAknNavigationDecorator* naviDeco = naviPane->Top();
+
+        if ( naviDeco )
+            {
+            PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL naviDeco"));
+            if ( naviDeco->ControlType() == CAknNavigationDecorator::ETabGroup )
+                {
+                PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL ETabGroup"));
+                CPbkIconInfoContainer* iconInfoContainer = 
+                    CPbkIconInfoContainer::NewL( R_PBK_FETCH_TAB_ICON_INFO_ARRAY );
+                CleanupStack::PushL(iconInfoContainer);
+
+                MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+                CAknTabGroup* tabGroup = 
+                    static_cast<CAknTabGroup*>(naviDeco->DecoratedControl());
+                                
+                const TInt count = tabGroup->TabCount();
+                PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL TabCount = %d"), count);
+                for (TInt i = 0; i < count; ++i)
+                    {
+                    TInt tabId = tabGroup->TabIdFromIndex(i);
+                    // tabId is used as icon id
+                    const TPbkIconInfo* iconInfo = 
+                        iconInfoContainer->Find(TPbkIconId(tabId));
+                    if (iconInfo)
+                        {
+                        CFbsBitmap* bitmap = NULL;
+                        CFbsBitmap* mask = NULL;
+                        PbkIconUtils::CreateIconLC(
+                            skin, bitmap, mask, *iconInfo);
+
+                        PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL ReplaceTabL %d"), tabId);
+                        tabGroup->ReplaceTabL(tabId, bitmap, mask);
+
+                        CleanupStack::Pop(2); // mask, bitmap
+                        }
+                    }
+                CleanupStack::PopAndDestroy( iconInfoContainer );
+                }
+            }
+        }
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("SkinTabsL end"));
+    }
+
+// --------------------------------------------------------------------------
+// CPbkFetchDlg::SkinTabsL
+// --------------------------------------------------------------------------
+//
+TInt CPbkFetchDlg::DelaySkinning( TAny* aFetchDlg )
+    {
+    // Tab skinning is just visual effect, no need to handle error
+    TRAP_IGNORE( ( (CPbkFetchDlg*)aFetchDlg)->SkinTabsL() );
+    return EFalse; // one time only
+    }
+
+//  End of File