--- /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