phonebookui/Phonebook/App/src/CPbkAppUi.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook/App/src/CPbkAppUi.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,605 @@
+/*
+* 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: 
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbkAppUi.h"       // This class' declaration
+
+#include <pbkconfig.hrh>
+#include <barsread.h>        // TResourceReader
+#include <eikmenup.h>
+#include <aknnavide.h>       // CAknNavigationDecorator
+#include <aknnotewrappers.h>
+#include <FeatMgr.h>
+#include <hlplch.h>          // HlpLauncher
+
+#include <Phonebook.rsg>     // Phonebook resources
+#include "CPbkApplication.h" // Phonebook application class
+#include "CPbkDocument.h"    // Phonebook document class
+#include "PbkAppViewFactory.h"   // Application view factory
+#include "CViewActivationTransactionImpl.h"
+#include "CPbkAppGlobals.h"
+#include "CPbkViewNavigator.h"
+#include "CPbkStartupView.h"
+
+//SendUi
+#include <sendui.h>                 // Send UI API
+#include <SenduiMtmUids.h>          // Send UI MTM uids
+
+
+// PbkEng.dll header files
+#include <DigViewGraph.h>
+
+// PbkView.dll header files
+#include <CPbkViewState.h>
+#include <CPbkCompressUiImpl.h>  // Phonebook compression UI
+#include <CPbkFFSCheck.h>
+
+// PbkUI.dll header files
+#include <CPbkAppViewBase.h>
+#include <MPbkCommandFactory.h>
+
+// From PbkExt
+#include <MPbkExtensionFactory.h>
+#include <CPbkExtGlobals.h>
+
+// Engine classes
+#include    <CPbkContactEngine.h> // Phonebook engine class
+#include    <CPbkConstants.h>
+
+// Debugging headers
+#include <pbkdebug.h>
+#include "PbkProfiling.h"
+
+
+// CONSTANTS
+// View UID constants
+const TUid CPbkAppUi::KPbkNamesListViewUid          = { EPbkNamesListViewId         };
+const TUid CPbkAppUi::KPbkGroupsListViewUid         = { EPbkGroupsListViewId        };
+const TUid CPbkAppUi::KPbkGroupMembersListViewUid   = { EPbkGroupMembersListViewId  };
+const TUid CPbkAppUi::KPbkContactInfoViewUid        = { EPbkContactInfoViewId       };
+const TUid CPbkAppUi::KPbkPhotoViewUid              = { EPbkPhotoViewViewId         };
+const TUid CPbkAppUi::KPbkPersonalInfoViewUid       = { EPbkPersonalInfoViewId      };
+
+/// Unnamed namespace for local definitions
+namespace {
+
+// LOCAL CONSTANTS AND MACROS
+#ifdef _DEBUG
+enum TPanicCode
+    {
+    EPanicPreCond_ConstructL = 1,
+    EPanicPostCond_ConstructL,
+    };
+    
+#else
+// Amount of free heap memory required for always-on functionality
+const TInt KAlwaysOnMinimumTreshold = 200*1024; // 200 kB
+
+#endif
+
+
+// ==================== LOCAL FUNCTIONS ====================
+
+#ifdef _DEBUG
+void Panic(TPanicCode aReason)
+    {
+    _LIT(KPanicText, "CPbkAppUi");
+    User::Panic(KPanicText, aReason);
+    }
+#endif
+
+}  // namespace
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+CPbkAppUi::CPbkAppUi() :
+    iViewResourceFile(*iCoeEnv)
+    {
+    }
+
+inline void CPbkAppUi::CreateEngineL()
+    {
+    TRAPD(err, PbkDocument()->CreateEngineL(EFalse));
+    if (err == KErrCorrupt)
+        {
+        // Database cannot be opened or recoverd -> replace it with an
+        // empty one. Always notify caller about DB corruption, even if
+        // replacing fails.
+        CAknNoteWrapper* note = new(ELeave) CAknNoteWrapper;
+        note->ExecuteLD(R_PBK_NOTE_DATABASE_CORRUPTED);
+        PbkDocument()->CreateEngineL(ETrue);
+        }
+    else if (err != KErrNone)
+        {
+        User::Leave(err);
+        }
+    }
+
+/**
+ * Loads view navigation graph from resources.
+ */
+inline void CPbkAppUi::ReadViewGraphL()
+    {
+    TResourceReader reader;
+    iCoeEnv->CreateResourceReaderLC(reader, R_PBK_VIEWNODES);
+    iViewGraph = CDigViewGraph::NewL(reader);
+    CleanupStack::PopAndDestroy(); // reader
+
+    iAppUiExtension->ApplyExtensionViewGraphChangesL(*iViewGraph);
+    }
+
+void CPbkAppUi::ConstructL()
+    {
+    __ASSERT_DEBUG(
+        !iViewGraph && !iNaviPane && !iCompressUi,
+        Panic(EPanicPreCond_ConstructL));
+
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("PHONEBOOK: started"));
+
+    // Init base class
+    __PBK_PROFILE_START(PbkProfiling::EAppUiBaseConstruct);
+    BaseConstructL(EAknEnableSkin);
+    __PBK_PROFILE_END(PbkProfiling::EAppUiBaseConstruct);
+
+    // Initialize feature manager
+    FeatureManager::InitializeLibL();
+
+    // Create Phonebook engine
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Engine construct begin"));
+    CreateEngineL();
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Engine construct end"));
+    PbkDocument()->CreateGlobalsL();
+
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Extension construct start"));
+    CPbkExtGlobals* extGlobal = CPbkExtGlobals::InstanceL();
+    extGlobal->PushL();
+    iAppUiExtension = extGlobal->FactoryL().
+        CreatePbkAppUiExtensionL(*PbkDocument()->Engine());
+    CleanupStack::PopAndDestroy(extGlobal);
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Extension construct end"));
+
+    // Create UI elements
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Viewnavi construct start"));
+    __PBK_PROFILE_START(PbkProfiling::EViewNaviConstruct);
+    ReadViewGraphL();
+    iNaviPane = static_cast<CAknNavigationControlContainer*>
+        (StatusPane()->ControlL(TUid::Uid(EEikStatusPaneUidNavi)));
+    iViewNavigator = CPbkViewNavigator::NewL(*iViewGraph, *this);
+    __PBK_PROFILE_END(PbkProfiling::EViewNaviConstruct);
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Viewnavi construct end"));
+
+    // Load view dll resource file
+    iViewResourceFile.OpenL();
+    // Create FFS space checker
+    iFFSCheck = CPbkFFSCheck::NewL(iCoeEnv);
+    // Create the compression UI
+    iCompressUi = CPbkCompressUiImpl::NewL(*PbkDocument()->Engine());
+    // Enable compression always
+    iCompressUi->EnableCompression(ETrue);
+
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Views construct start"));
+    CPbkStartupView* startupView = CPbkStartupView::NewLC(*iAppUiExtension);
+    AddViewL(startupView);
+    CleanupStack::Pop(startupView);
+    SetDefaultViewL(*startupView);
+    CreateViewsL();
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("Views construct end"));
+
+    CCoeEnv::Static()->AddForegroundObserverL(*this);
+
+    __PBK_PROFILE_START(PbkProfiling::EStartupViewActivation);
+
+    __ASSERT_DEBUG(
+        iViewGraph && iNaviPane && iCompressUi,
+        Panic(EPanicPostCond_ConstructL));
+    }
+
+CPbkAppUi::~CPbkAppUi()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkAppUi::~CPbkAppUi()"));
+
+    CCoeEnv::Static()->RemoveForegroundObserver(*this);
+
+    // delete data members
+    delete iCompressUi;
+    delete iFFSCheck;
+    iViewResourceFile.Close();
+    // Application views will be deleted by the base class destructor.
+    delete iViewNavigator;
+    delete iViewGraph;
+    delete iAppGlobals;
+    Release(iAppUiExtension);
+
+    FeatureManager::UnInitializeLib();
+    }
+
+CPbkDocument* CPbkAppUi::PbkDocument() const
+    {
+    // Explicit cast: the document must always be of type CPbkDocument
+    return static_cast<CPbkDocument*>(Document());
+    }
+
+CPbkApplication* CPbkAppUi::PbkApplication() const
+    {
+    // Explicit cast: the application must always be of type CPbkApplication
+    return static_cast<CPbkApplication*>(Application());
+    }
+
+void CPbkAppUi::ActivatePhonebookViewL
+        (TUid aViewId,
+        const CPbkViewState* aViewState/*=NULL*/)
+    {
+    if (aViewState)
+        {
+        HBufC8* stateBuf = aViewState->PackLC();
+        ActivateLocalViewL(aViewId, CPbkViewState::Uid(), *stateBuf);
+        CleanupStack::PopAndDestroy();  // stateBuf
+        }
+    else
+        {
+        ActivateLocalViewL(aViewId);
+        }
+    }
+
+void CPbkAppUi::ActivatePreviousViewL
+        (const CPbkViewState* aViewState /*=NULL*/)
+    {
+    // Find current view in the graph
+    CDigViewNode* viewNode = iViewGraph->FindNodeWithViewId(iView->Id());
+    if (viewNode)
+        {
+        // get previous node
+        CDigViewNode* prevNode = viewNode->PreviousNode();
+        if (!prevNode)
+            {
+            prevNode = viewNode->DefaultPreviousNode();
+            }
+        if (prevNode)
+            {
+            if (prevNode->ExitNode())
+                {
+                ExitL();
+                }
+            else
+                {
+                ActivatePhonebookViewL(prevNode->ViewId(), aViewState);
+                }
+            }
+        }
+    }
+
+CAknNavigationControlContainer* CPbkAppUi::NaviPane()
+    {
+    return iNaviPane;
+    }
+
+void CPbkAppUi::FFSClCheckL(const MPbkCommandHandler& aCommandHandler,
+                            TInt aBytesToWrite /*=0*/)
+    {
+    iFFSCheck->FFSClCheckL(aCommandHandler, aBytesToWrite);
+    }
+
+CPbkAppUi::CViewActivationTransaction* CPbkAppUi::HandleViewActivationLC
+        (const TUid& aViewId, const TVwsViewId& aPrevViewId,
+        const TDesC* aTitlePaneText,
+        const CEikImage* aContextPanePicture,
+        TUint aFlags)
+    {
+    // Create and return an instance of view activation transaction
+    return CViewActivationTransactionImpl::NewLC
+        (*this, aViewId, aPrevViewId, aTitlePaneText,
+        aContextPanePicture, aFlags);
+    }
+
+CPbkAppGlobalsBase* CPbkAppUi::AppGlobalsL()
+    {
+    if (!iAppGlobals)
+        {
+        iAppGlobals = CPbkAppGlobals::NewL();
+        }
+    return iAppGlobals;
+    }
+
+void CPbkAppUi::ExitL()
+    {
+    // Set this flag to EFalse to signal that we're either dying or going
+    // to background.
+    iIsRunningForeground = EFalse;
+
+#ifndef _DEBUG
+
+    // Check that we have enough free heap memory to go to background.
+    // User::Available() does not check for the possibility to grow the heap,
+    // so we'll need to allocate a dummy block and release it immediately.
+    TAny* tmp = User::Alloc(KAlwaysOnMinimumTreshold);
+    delete tmp;
+    if (!iEndKeyExit && tmp &&
+        PbkDocument()->Engine()->Constants()->LocallyVariatedFeatureEnabled(
+            EPbkLVAlwaysOnPhonebook))
+        {
+        CPbkViewState* state = CPbkViewState::NewLC();
+        state->SetFlags(CPbkViewState::EInitialized | CPbkViewState::ESendToBackground);
+        // Activation of Names list view will send application to background.
+        // Application can not be sent here to background because
+        // activation is asynchronous operation and application could be set
+        // to background before the view activation.
+        ActivatePhonebookViewL(KPbkNamesListViewUid, state);
+        CleanupStack::PopAndDestroy();  // state
+        }
+    else
+        {
+        CAknViewAppUi::ProcessCommandL(EAknCmdExit);
+        }
+#else // _DEBUG
+    CAknViewAppUi::ProcessCommandL(EAknCmdExit);
+#endif // _DEBUG
+    }
+
+void CPbkAppUi::Exit()
+    {
+    CPbkAppUiBase::Exit();
+    }
+
+TBool CPbkAppUi::IsRunningForeground() const
+    {
+    return iIsRunningForeground;
+    }
+
+/**
+ * Returns true if aViewId is a phonebook view.
+ */
+TBool CPbkAppUi::IsPhonebookView(const TVwsViewId& aViewId) const
+    {
+    if (aViewId.iAppUid == Application()->AppDllUid())
+        {
+        const CDigViewNode* viewNode =
+            iViewGraph->FindNodeWithViewId(aViewId.iViewUid);
+        return viewNode && !viewNode->ExitNode();
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+inline void CPbkAppUi::CmdExitL()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkAppUi::CmdExitL()"));
+    // notify views before the exit is executed
+    CAknViewAppUi::ProcessCommandL(EPbkCmdExit);
+    CAknViewAppUi::Exit();
+    }
+
+void CPbkAppUi::SendAppToBackgroundL()
+    {
+    // Get the current task
+    RWsSession ws;
+    User::LeaveIfError(ws.Connect());
+    TApaTaskList tasklist(ws);
+
+    TApaTask task = tasklist.FindApp(Application()->AppDllUid());
+    CleanupClosePushL(ws);
+    if (task.Exists())
+        {
+        task.SendToBackground();
+        }
+    CleanupStack::PopAndDestroy(); // ws
+    }
+
+void CPbkAppUi::HandleCommandL(TInt aCommand)
+    {
+    switch (aCommand)
+        {
+        case EAknCmdHelp:
+            {
+            HlpLauncher::LaunchHelpApplicationL(iEikonEnv->WsSession(),
+                AppHelpContextL());
+            break;
+            }
+
+        case EEikCmdExit:
+            {
+            // standard exit command
+            CmdExitL();
+            break;
+            }
+
+        case EAknSoftkeyExit:
+        case EAknCmdExit:
+        case EPbkCmdExit:
+            {
+            ExitL();
+            break;
+            }
+
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+void CPbkAppUi::DynInitMenuPaneL
+        (TInt aResourceId,
+        CEikMenuPane* aMenuPane)
+    {
+    switch (aResourceId)
+        {
+        case R_PHONEBOOK_SYSTEM_MENU:
+            {
+            if (!FeatureManager::FeatureSupported(KFeatureIdHelp))
+                {
+                // remove non-supported help from menu
+                aMenuPane->SetItemDimmed(EAknCmdHelp, ETrue);
+                }
+            break;
+            }
+
+        default:
+            {
+            break;
+            }
+        }
+    }
+
+TKeyResponse CPbkAppUi::HandleKeyEventL
+        (const TKeyEvent& aKeyEvent,
+        TEventCode aType)
+    {
+    if (PbkProcessKeyEventL(aKeyEvent, aType))
+        {
+        PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkAppUi::HandleKeyEventL() processed key event"));
+        return EKeyWasConsumed;
+        }
+    return EKeyWasNotConsumed;
+    }
+
+void CPbkAppUi::HandleForegroundEventL(TBool aForeground)
+    {
+    // Call base class
+    CAknViewAppUi::HandleForegroundEventL(aForeground);
+    }
+
+void CPbkAppUi::HandleResourceChangeL(TInt aType)
+    {
+    CPbkAppUiBase::HandleResourceChangeL(aType);
+    // This is needed to change the application
+    // icon when the skin changes (especially if
+    // a contact with a thumbnail is currently
+    // selected and the app icon is not visible)
+    CEikStatusPane* pane = StatusPane();
+    if (pane)
+        {
+        pane->HandleResourceChange(aType);
+        }
+
+    // The resource change event has to be forwarded to
+    // view navigator
+    if(iViewNavigator)
+        {
+        iViewNavigator->HandleResourceChange(aType);
+        }
+    }
+
+void CPbkAppUi::HandleWsEventL(const TWsEvent& aEvent, CCoeControl* aDestination)
+    {
+    switch (aEvent.Type())
+        {
+        case KAknUidValueEndKeyCloseEvent:
+            {
+            // Make a real exit on end-key event
+            iEndKeyExit = ETrue;
+            } // fallthrough
+        default:
+            {
+            CPbkAppUiBase::HandleWsEventL(aEvent, aDestination);
+            break;
+            }
+        }
+    }
+
+TBool CPbkAppUi::PbkProcessKeyEventL
+        (const TKeyEvent& aKeyEvent, TEventCode aType)
+    {
+    // Ensure that navigator has already been constructed
+    if (iViewNavigator)
+        {
+        return iViewNavigator->HandleNavigationKeyEventL(aKeyEvent,aType);
+        }
+    return EFalse;
+    }
+
+void CPbkAppUi::CreateViewsL()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("CPbkAppUi::CreateViewsL start"));
+
+    CPbkAppViewFactory* factory = CPbkAppViewFactory::NewLC();
+
+    // Create and add application views
+    for (TInt i = 0; i < iViewGraph->Count(); ++i)
+        {
+        const CDigViewNode& viewNode = (*iViewGraph)[i];
+        if (!viewNode.ExitNode())
+            {
+            CAknView* view = factory->CreateAppViewLC(viewNode.ViewId());
+            PBK_DEBUG_PRINT(PBK_DEBUG_STRING(
+                "CPbkAppUi::CreateViewsL created view %d"), viewNode.ViewId());
+
+            AddViewL(view);
+            CleanupStack::Pop();  // view
+            }
+        }
+    CleanupStack::PopAndDestroy(); // factory
+    }
+
+void CPbkAppUi::HandleGainingForeground()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("void CPbkAppUi::HandleGainingForeground()"));
+
+    if (PbkDocument()->Engine()->Constants()->
+            LocallyVariatedFeatureEnabled(EPbkLVAlwaysOnPhonebook))
+        {
+        // If phonebook is running in background (i.e. user has exited it) the
+        // Names list view is active and it is incorrectly marked as being in
+        // foreground (this happens during the view's activation
+        // when exiting Phonebook). Therefore its HandleForegroundEventL() will
+        // not be called unless we first mark the view explicitly as being in
+        // background. Now when CPbkAppUi::HandleForegroundEventL(ETrue) is
+        // called, the NamesListView's HandleForegroundEventL() is called
+        // correctly
+        if (!iIsRunningForeground && iView &&
+            iView->Id() == KPbkNamesListViewUid)
+            {
+            TRAPD(err, HandleForegroundEventL(EFalse));
+            if (KErrNone != err)
+                {
+                CCoeEnv::Static()->HandleError(err);
+                }
+            }        
+        // this if-case is here, because if the end-key is pressed to execute 
+        // the exit, the activation of names list view causes additional call of
+        // HandleGainingForeground and HandleLosingForeground methods. 
+        // In end-key-exit-case the phonebook should not be shown in fast
+        // swap menu, and the additional gaining foreground call causes
+        // the visibility of phonebook in fast swap if it is not 
+        // blocked.        
+        if ( !iEndKeyExit )
+            {
+            iIsRunningForeground = ETrue;
+            }
+        else
+            {            
+            iEndKeyExit = EFalse;
+            }
+        HideApplicationFromFSW(!iIsRunningForeground);
+        }
+    }
+
+void CPbkAppUi::HandleLosingForeground()
+    {
+    PBK_DEBUG_PRINT(PBK_DEBUG_STRING("void CPbkAppUi::HandleLosingForeground()"));
+
+    if (PbkDocument()->Engine()->Constants()->
+            LocallyVariatedFeatureEnabled(EPbkLVAlwaysOnPhonebook))
+        {
+        HideApplicationFromFSW(!iIsRunningForeground);
+        }
+    }
+
+//  End of File