messagingappbase/msgavkon/muiu_domain/messageiterator/src/MuiuMessageIterator.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgavkon/muiu_domain/messageiterator/src/MuiuMessageIterator.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,449 @@
+/*
+* 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: MuiuMessageIterator implementation
+*
+*/
+
+
+
+// INCLUDE FILES
+#include <msvids.h> // KMsvNullIndexEntryId
+#include <mtclreg.h> // CClientMtmRegistry
+#include <mtuireg.h> // CMtmUiRegistry
+#include <mtmuibas.h> // CBaseMtmUi
+#include <mtmuidef.hrh> // CBaseMtmUi
+#include "MuiuMessageIterator.h"
+#include "muiudomainpan.h" // Panic codes
+
+
+// CONSTANTS
+const TUid KUidMsvMessageListSortOrder={0x10005359};
+
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// ---------------------------------------------------------
+// CMessageIterator::NewL
+// ---------------------------------------------------------
+//
+EXPORT_C CMessageIterator* CMessageIterator::NewL( CMsvSession& aSession,
+ const TMsvEntry& aCurrentMessage )
+ { // static
+ CMessageIterator* me = new( ELeave ) CMessageIterator;
+ CleanupStack::PushL( me );
+ me->ConstructL( aSession,aCurrentMessage );
+ CleanupStack::Pop( me );
+ return me;
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::CMessageIterator
+// ---------------------------------------------------------
+//
+CMessageIterator::CMessageIterator()
+ {
+ // Nothing to do.
+ // Note iEntryObserver has been initialised to EFalse as this is a CBase derived class.
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::ConstructL
+// ---------------------------------------------------------
+//
+void CMessageIterator::ConstructL( CMsvSession& aSession, const TMsvEntry& aCurrentMessage )
+ {
+ // Assume only the root entry has no parent
+ __ASSERT_DEBUG( aCurrentMessage.Id() != KMsvRootIndexEntryId,
+ Panic( EMuiuMsgIteratorEntryHasNoParent ) );
+
+ //
+ // Get crrent sort settings used by Message Centre for displaying the message list
+ // this assumes that the message list sort order changing doesn't
+ // affect the editors next/prev behaviour
+ // i.e. the iterator uses the sort order that was being used when it was created.
+ TMsvSelectionOrdering sort( KMsvGroupByType, EMsvSortByDateReverse, EFalse );
+ CMsvEntry* entry=aSession.GetEntryL(KMsvRootIndexEntryId);
+ CleanupStack::PushL( entry );
+ if ( entry->HasStoreL() )
+ {
+ CMsvStore* store = entry->ReadStoreL();
+ CleanupStack::PushL( store );
+ if ( store->IsPresentL( KUidMsvMessageListSortOrder ) )
+ {
+ RMsvReadStream readStream;
+ readStream.OpenLC( *store, KUidMsvMessageListSortOrder );
+ sort.InternalizeL( readStream );
+ CleanupStack::PopAndDestroy(); // readStream
+ }
+ CleanupStack::PopAndDestroy( store );
+ }
+
+ //
+ // Setup iParentOfCurrent. Set sorting of parents children so
+ // next/prev order matches the view the user had of the messages from the Email app.
+ // Also become an observer of the parent to keep our copy of the children list updated.
+ entry->SetEntryL( aCurrentMessage.Parent() );
+ CleanupStack::Pop( entry ); // entry (we're about to allocate it to instance data)
+ iParentOfCurrent = entry;
+
+ __ASSERT_ALWAYS( iParentOfCurrent,Panic( EMuiuMsgIteratorParentEntryNull ) );
+
+ iParentOfCurrent->SetSortTypeL( sort ); // set sort to be same as Message Centre
+ iParentOfCurrent->AddObserverL( *this );
+ iEntryObserver = ETrue; // To ensure we de-register, as an observer, in the destructor
+
+ //
+ // Create iChildrenOfParent and intialise iCurrentIndex
+ iChildrenOfParent=new( ELeave ) CMsvEntrySelection;
+ UpdateChildrenOfParentL( aCurrentMessage.Id() );
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::HandleEntryEventL
+//
+// HandleEntryEvent from MMsvEntryObserver
+// If the parent of current entry changes then we may need to re-build our local children list.
+// ---------------------------------------------------------
+//
+void CMessageIterator::HandleEntryEventL(TMsvEntryEvent aEvent,
+ TAny* /*aArg1*/,
+ TAny* /*aArg2*/,
+ TAny* /*aArg3*/)
+ {
+ //
+ // Ensure we're ready to handle the event
+ if( !iParentOfCurrent )
+ {
+ return;
+ }
+
+ // React according to event type
+ switch( aEvent )
+ {
+ case EMsvEntryDeleted:
+ // This should not occur as the editor should have locked the entry
+ // Panic( EMuiuMsgIteratorParentEntryDeleted );
+ break;
+
+ case EMsvEntryMoved:
+ // This should not occur as the editor should have locked the entry
+ Panic( EMuiuMsgIteratorParentEntryMoved );
+ break;
+
+ case EMsvChildrenChanged:
+ // No need to do anything as a child has changed, but not the children list
+ break;
+
+ case EMsvContextInvalid:
+ case EMsvChildrenMissing:
+ case EMsvChildrenInvalid:
+ // Have to call SetEntryL before re-builiding children list
+ iParentOfCurrent->SetEntryL( iParentOfCurrent->EntryId() );
+ // drop thru to rebuild children list code
+
+ default:
+ case EMsvEntryChanged:
+ case EMsvNewChildren:
+ case EMsvDeletedChildren:
+ //
+ // Re-create child list and refresh the index of our current entry
+
+ //if a class 0 sms is received into empty inbox we have a situation
+ //where Count == 0. This causes a crash when another class 0 arrives.
+ if( iChildrenOfParent->Count() != 0 )
+ {
+ TInt originalCount = iChildrenOfParent->Count();
+ UpdateChildrenOfParentL( ( *iChildrenOfParent )[iCurrentIndex] );
+
+ if ( iMessageIteratorObserver && ( iChildrenOfParent->Count() != originalCount ))
+ {
+ iMessageIteratorObserver->HandleIteratorEventL(
+ MMessageIteratorObserver::EFolderCountChanged );
+ }
+ }
+
+ break;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::~CMessageIterator
+// ---------------------------------------------------------
+//
+EXPORT_C CMessageIterator::~CMessageIterator()
+ {
+ delete iChildrenOfParent;
+ if( iParentOfCurrent )
+ {
+ // Only de-register our observer-ness if our original registration did not leave
+ if( iEntryObserver )
+ {
+ iParentOfCurrent->RemoveObserver( *this );
+ }
+ delete iParentOfCurrent;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::CurrentMessage
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C const TMsvEntry& CMessageIterator::CurrentMessage() const
+ {
+ __ASSERT_ALWAYS(iParentOfCurrent,Panic(EMuiuMsgIteratorParentEntryNull));
+ __ASSERT_ALWAYS(iCurrentIndex<iChildrenOfParent->Count(),
+ Panic(EMuiuMsgIteratorInvalidCurrentIndex));
+
+ TInt foundIndex = KErrNotFound;
+ TMsvId entryId = ( *iChildrenOfParent )[iCurrentIndex];
+ const TInt count = iParentOfCurrent->Count();
+
+ for ( TInt loop = 0; loop < count && foundIndex == KErrNotFound; loop++ )
+ {
+ if ( ( *iParentOfCurrent )[ loop ].Id() == entryId )
+ {
+ foundIndex = loop;
+ }
+
+ }
+
+ __ASSERT_ALWAYS( foundIndex != KErrNotFound,Panic( EMuiuMsgIteratorChildEntryNotFound ) );
+ return ( *iParentOfCurrent )[foundIndex];
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::CurrentParent
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C const TMsvEntry& CMessageIterator::CurrentParent() const
+ {
+ __ASSERT_ALWAYS( iParentOfCurrent, Panic( EMuiuMsgIteratorParentEntryNull ) );
+ return iParentOfCurrent->Entry();
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::NextMessageExists
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMessageIterator::NextMessageExists() const
+ {
+ //
+ // Next message exists if current is not last in list
+ if( iChildrenOfParent->Count() <= 0 )
+ {
+ return EFalse;
+ }
+ else
+ {
+ return( iChildrenOfParent->Count()-1 != iCurrentIndex );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::PreviousMessageExists
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMessageIterator::PreviousMessageExists() const
+ {
+ //
+ // Previous message if current is not first in list
+ return( 0 != iCurrentIndex );
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::CurrentMessageIndex
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMessageIterator::CurrentMessageIndex() const
+ {
+ return iCurrentIndex;
+ }
+
+// ---------------------------------------------------------
+// CMessageIterator::MessagesInFolder
+//
+// Query
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMessageIterator::MessagesInFolder() const
+ {
+ return iChildrenOfParent->Count();
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::SetCurrentMessageL
+//
+// State changer
+// ---------------------------------------------------------
+//
+EXPORT_C void CMessageIterator::SetCurrentMessageL( const TMsvEntry& aCurrentMessage )
+ {
+ // Assume only the root entry has no parent
+ __ASSERT_DEBUG( aCurrentMessage.Id() != KMsvRootIndexEntryId,
+ Panic( EMuiuMsgIteratorEntryHasNoParent ) );
+
+ //
+ // Update list of children
+ iParentOfCurrent->SetEntryL( aCurrentMessage.Parent() );
+ UpdateChildrenOfParentL( aCurrentMessage.Id() );
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::SetNextMessage
+//
+// State changer.
+// Returns KErrNotFound on 'no next message'
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMessageIterator::SetNextMessage()
+ {
+ // Check if next message exists
+ if( !NextMessageExists() )
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ // Increment index
+ ++iCurrentIndex;
+ return KErrNone;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::SetPreviousMessage
+//
+// State changer.
+// Returns KErrNotFound on 'no previous message'
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CMessageIterator::SetPreviousMessage()
+ {
+ // Check if next message exists
+ if( !PreviousMessageExists() )
+ {
+ return KErrNotFound;
+ }
+ else
+ {
+ // Decrement index
+ --iCurrentIndex;
+ return KErrNone;
+ }
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::OpenCurrentMessageL
+//
+// Editor/viewer launcher
+// ---------------------------------------------------------
+//
+EXPORT_C CMsvOperation* CMessageIterator::OpenCurrentMessageL( TRequestStatus& aStatus,
+ TBool aEmbed )
+ {
+ __ASSERT_ALWAYS( iParentOfCurrent, Panic( EMuiuMsgIteratorParentEntryNull ) );
+
+ // Get mtm ui layer
+ CClientMtmRegistry* mtmReg = CClientMtmRegistry::NewL( iParentOfCurrent->Session() );
+ CleanupStack::PushL( mtmReg );
+ CBaseMtm* baseMtm = mtmReg->NewMtmL( CurrentMessage().iMtm );
+ CleanupStack::PushL( baseMtm );
+ CMtmUiRegistry* mtmUiReg = CMtmUiRegistry::NewL( iParentOfCurrent->Session() );
+ CleanupStack::PushL( mtmUiReg );
+ CBaseMtmUi* mtmUi = mtmUiReg->NewMtmUiL( *baseMtm );
+ CleanupStack::PushL( mtmUi );
+
+ // Open the message
+ baseMtm->SwitchCurrentEntryL( CurrentMessage().Id() );
+ if( aEmbed )
+ {
+ mtmUi->SetPreferences( mtmUi->Preferences() | EMtmUiFlagEditorPreferEmbedded );
+ }
+ CMsvOperation* op = mtmUi->OpenL( aStatus );
+
+ CleanupStack::PopAndDestroy( 4, mtmReg ); // mtmUi, mtmUiReg, baseMtm, mtmReg
+ return op;
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::SetMessageIteratorObserver
+//
+// Set iterator observer.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMessageIterator::SetMessageIteratorObserver( MMessageIteratorObserver* aObserver )
+ {
+ iMessageIteratorObserver = aObserver;
+ }
+
+
+// ---------------------------------------------------------
+// CMessageIterator::UpdateChildrenOfParentL
+//
+// Intialise/update iChildrenOfParent & iCurrentIndex
+// ---------------------------------------------------------
+//
+void CMessageIterator::UpdateChildrenOfParentL( TMsvId aCurrentMessageId )
+ {
+ // We assume that iParentOfCurrent has already had it's context set correctly
+ // Get child list
+ CMsvEntrySelection* tempSel = iParentOfCurrent->ChildrenL();
+ CleanupStack::PushL( tempSel );
+
+ // remove all except messages from the list.
+ for ( TInt loop = tempSel->Count() - 1; loop >= 0; loop-- )
+ {
+ const TMsvEntry& childEntry = iParentOfCurrent->ChildDataL( ( *tempSel )[loop] );
+
+ if ( childEntry.iType.iUid != KUidMsvMessageEntryValue )
+ {
+ tempSel->Delete( loop );
+ }
+ }
+
+ // Use the new child list
+ delete iChildrenOfParent;
+ CleanupStack::Pop( tempSel );
+ iChildrenOfParent = tempSel;
+
+ // Update current index
+ iCurrentIndex = iChildrenOfParent->Find( aCurrentMessageId );
+ if ( iCurrentIndex < 0 )
+ {
+ iCurrentIndex = 0;
+ }
+ }
+
+// End of file