/*
* Copyright (c) 2007 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:
* Item array for the message items to be displayed by mce.
* Main view items are kept in memory (CArrayFixFlat<TMceListItem>) when created but
* Message view list items are fetched from the msgs when needed in MdcaPoint function
*
*/
// INCLUDE FILES
#include <AknUtils.h> // AknTextUtils
#include <mtudcbas.h>
#include <msvids.h>
#include <NpdApi.h> // CNotepadApi
#include "MtmRegistryObserver.h" // MMtmUiDataRegistryObserver
#include <StringLoader.h> // StringLoader
#include <mce.rsg>
#include <SenduiMtmUids.h> // mtm uids
#include <eikenv.h>
#include <gulicon.h>
#include "MceOneRowMessageListArray.h"
#include "MceLogText.h"
#include <MTMStore.h>
#include <commonphoneparser.h>
#include <aknappui.h>
#include <akncontext.h>
#include <aknconsts.h>
#include <e32math.h>
#include <bldvariant.hrh>
#include <featmgr.h>
#include <NumberGrouping.h>
#include <mmsconst.h>
#include <mmsgenutils.h>
#include <mmsclient.h>
#include <mtclreg.h>
#include <muiu.mbg>
// security data caging
#include <data_caging_path_literals.hrh>
#include <miutset.h>
#include <msvapi.h>
#include "MceCommands.hrh"
#include "MceOneRowMessageListArrayLoader.h"
#include <smuthdr.h>
// CONSTANTS
// LOCAL CONSTANTS AND MACROS
const TInt KMceTimeHours = 23;
const TInt KMceTimeMinutes = 59;
const TInt KMceTimeSeconds = 59;
const TInt KMceTimeMicroSeconds = 999999;
const TInt KMceTimeOneDay = 1;
const TInt KMceTimeOneWeek = 7;
const TUid KUidMsvMessageListSortOrder = {0x10005359};
_LIT( KSortSubjectSkipString, "*:*" );
const TChar KWhiteSpaceCharacter(' ');
const TInt KSortSubjectStringLength = 100;
const TInt KMceLoopCounter = 200;
//cmail update
#define KUidMsgTypeCmailMtmVal 0x2001F406
// ================= MEMBER FUNCTIONS =======================
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::NewL
// ----------------------------------------------------
CMceOneRowListItemArrayLoader* CMceOneRowListItemArrayLoader::NewL(
CMsvSessionPtr aSession )
{
return CMceOneRowListItemArrayLoader::NewL(
0x1002, //KMsvGlobalInBoxIndexEntryId,
aSession );
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::NewL
// ----------------------------------------------------
CMceOneRowListItemArrayLoader* CMceOneRowListItemArrayLoader::NewL(
TMsvId aFolderId,
CMsvSessionPtr aSession )
{
CMceOneRowListItemArrayLoader* self = new (ELeave) CMceOneRowListItemArrayLoader( aSession );
CleanupStack::PushL( self );
self->ConstructL( aFolderId );
CleanupStack::Pop( self );
return self;
}
// ----------------------------------------------------
// C++ default constructor can NOT contain any code that
// might leave.
// ----------------------------------------------------
CMceOneRowListItemArrayLoader::CMceOneRowListItemArrayLoader(
CMsvSessionPtr aSession )
: CActive( CActive::EPriorityIdle ),
iListType( EHCListTypeTime ),
iSession( aSession ),
iEmailFramework(EFalse)
{
}
// ----------------------------------------------------
// destructor
// ----------------------------------------------------
CMceOneRowListItemArrayLoader::~CMceOneRowListItemArrayLoader()
{
iHCListItemArray.Close();
if ( &iSession )
{
iSession->RemoveObserver( *this );
}
Cancel();
delete iFolderEntry;
delete iEntriesToBeAdded;
delete iEntriesReceivedDuringListCreation;
if ( iEmailFramework )
{
delete iCmailSelectionList ;
}
iMarkedArray.Close();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ConstructL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::ConstructL(
TMsvId aFolderId )
{
iSession->AddObserverL( *this );
FeatureManager::InitializeLibL();
if ( FeatureManager::FeatureSupported( KFeatureIdFfEmailFramework ) )
{
iEmailFramework = ETrue;
}
FeatureManager::UnInitializeLib();
iFolderEntry = CMsvEntry::NewL(
*iSession,
aFolderId,
TMsvSelectionOrdering(
KMsvGroupByStandardFolders, EMsvSortByDateReverse ));
CActiveScheduler::Add( this );
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::StartL
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::StartL()
{
Cancel();
InitialiseSearch();
delete iEntriesToBeAdded;
iEntriesToBeAdded = NULL;
iEntriesToBeAdded = iFolderEntry->ChildrenL();
iEntryToBeAdded = 0;
LoadMessagesL();
QueueLoad();
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::FinishL
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::FinishL()
{
if(IsActive())
{
// First consume the outstanding completion.
Cancel();
}
// Loop until all entries and subtitles has been added to iHCListItemArray
while ( iEntriesToBeAdded && iEntriesToBeAdded->Count() )
{
LoadMessagesL();
}
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::DoCancel
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::DoCancel()
{
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::RunL
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::RunL()
{
TRAP_IGNORE( LoadMessagesL( ) );
QueueLoad();
if(!IsActive())
{
}
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::QueueLoad
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::QueueLoad()
{
if ( IsActive() )
{
return;
}
if ( iEntriesToBeAdded->Count() || iEntriesReceivedDuringListCreation )
{
TRequestStatus *s = &iStatus;
User::RequestComplete(s, KErrNone);
SetActive();
}
}
// ---------------------------------------------------------
// CMceOneRowListItemArrayLoader::LoadMessagesL
// ---------------------------------------------------------
//
void CMceOneRowListItemArrayLoader::LoadMessagesL()
{
if ( iEntriesToBeAdded->Count() )
{
if ( iEmailFramework )
{
TRAP_IGNORE( CreateCmailEntryIndexL() ) ;
}
AppendMessagesL();
}
else if ( iEntriesReceivedDuringListCreation )
{
Cancel();
// do something
const TInt count = iEntriesReceivedDuringListCreation->Count();
for (TInt i=0; i<count; i++)
{
EntryCreatedL( (*iEntriesReceivedDuringListCreation)[i] );
}
delete iEntriesReceivedDuringListCreation;
iEntriesReceivedDuringListCreation = NULL;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArray::ItemIndex
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::ItemIndex(TMsvId aItemId) const
{
TInt foundItem = KErrNotFound;
const TInt count = iHCListItemArray.Count();
for( TInt loop = 0; loop < count && foundItem == KErrNotFound ; loop++)
{
if ( iHCListItemArray[loop].iEntryId == aItemId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
foundItem = loop;
}
}
return foundItem;
}
// ----------------------------------------------------
// CMceOneRowListItemArray::HCItemType
// ----------------------------------------------------
//THListItemType CMceOneRowListItemArray::HCItemType( TInt aIndex )
TInt CMceOneRowListItemArrayLoader::HCItemType(TInt aIndex )
{
return iHCListItemArray[aIndex].iItemType;
}
// ----------------------------------------------------
// CMceOneRowListItemArray::ItemId
// ----------------------------------------------------
TMsvId CMceOneRowListItemArrayLoader::ItemId( TInt aIndex ) const
{
TMsvId id = KErrNotFound;
if ( aIndex >= 0 && iHCListItemArray.Count() > aIndex )
{
if ( iHCListItemArray[aIndex].iItemType == EHListItemEntry )
{
id = iHCListItemArray[aIndex].iEntryId;
}
}
return id;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SetEntryL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SetEntryL( TMsvId aFolderId )
{
iHCListItemArray.Reset();
iFolderEntry->SetEntryL( aFolderId );
TMsvSelectionOrdering ordering = iFolderEntry->SortType();
TMsvSorting sorting = iFolderEntry->SortType().Sorting();
ordering.SetSorting( sorting );
iFolderEntry->SetSortTypeL( ordering );
StartL();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::Count
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::Count()
{
TInt count = 0;
count = iHCListItemArray.Count();
return count;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetEntry
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::GetEntry( TMsvId aEntryId, TMsvEntry& aEntry )
{
TMsvId serviceId;
TInt error = iSession->GetEntry( aEntryId, serviceId, aEntry );
return error;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetEntry
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::GetEntry( TInt aIndex, TMsvEntry& aEntry )
{
if ( aIndex < 0 || aIndex > iHCListItemArray.Count() )
{
return KErrNotFound;
}
TMsvId serviceId;
TMsvId entryId;
entryId = iHCListItemArray[aIndex].iEntryId;
TInt error = iSession->GetEntry( entryId, serviceId, aEntry );
if ( error == KErrNone )
{
if ( iHCListItemArray[aIndex].iItemType == EHListItemSubtitle )
{
error = iListType;
}
}
return error;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetTimeBasedSubtitle
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::GetTimeBasedSubtitle( TInt aIndex )
{
if ( aIndex < 0 || aIndex > iHCListItemArray.Count() )
{
return KErrNotFound;
}
TInt value = KErrNotSupported;
if ( iListType == EHCListTypeTime )
{
if ( iHCListItemArray[aIndex].iItemType == EHListItemSubtitle )
{
value = iHCListItemArray[aIndex].iSubtitleType;
}
else
{
TInt subtitleIndex = ParentItemIndex( aIndex );
if ( subtitleIndex >= 0 )
{
value = iHCListItemArray[subtitleIndex].iSubtitleType;
}
}
}
return value;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetCurrentEntry
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::GetCurrentEntry( TMsvEntry& aEntry )
{
aEntry = iFolderEntry->Entry();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::CurrentEntryId
// ----------------------------------------------------
TMsvId CMceOneRowListItemArrayLoader::CurrentEntryId()
{
return iFolderEntry->EntryId();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SetListItemArrayObserver
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SetListItemArrayObserver( MMceOneRowListItemArrayObserver* aObserver )
{
iListItemArrayObserver = aObserver;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::InitialiseSearch
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::InitialiseSearch()
{
iHCListItemArray.Reset();
iCounter = 0;
iStep = 0;
for (TInt i=EMondayAdded; i<=EOlderAdded; i++)
{
iSubtitleAdded[i] = EFalse;
}
UpdateCurrentTime();
iAddSubtitle = EFalse;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::HandleSessionEventL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::HandleSessionEventL(
TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* /*aArg3*/)
{
MCELOGGER_ENTERFN("CMceOneRowListItemArrayLoader::HandleSessionEventL");
// if active...
if ( !IsActive() )
{
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::HandleSessionEventL not active");
return;
}
TMsvId changedFolderId = (*(TMsvId*) (aArg2));
if ( changedFolderId != iFolderEntry->EntryId() )
{
// not in our folder...
return;
}
switch (aEvent)
{
case EMsvEntriesChanged:
case EMsvEntriesCreated:
{
if ( !iEntriesReceivedDuringListCreation )
{
iEntriesReceivedDuringListCreation = new( ELeave ) CMsvEntrySelection();
}
CMsvEntrySelection* selection = (CMsvEntrySelection*) aArg1;
const TInt count = selection->Count();
for (TInt i=0; i<count; i++)
{
iEntriesReceivedDuringListCreation->AppendL( (*selection)[i] );
}
}
break;
case EMsvEntriesDeleted:
{
// ?
}
case EMsvEntriesMoved:
{
}
break;
default:
break;
};
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::HandleSessionEventL");
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::AppendMessagesL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::AppendMessagesL()
{
switch ( iListType )
{
case EHCListTypeTime:
CreateTimeBasedArrayL();
break;
case EHCListTypeSender:
CreateSenderBasedArrayL();
break;
case EHCListTypeSubject:
CreateSubjectBasedArrayL();
break;
case EHCListTypeType:
CreateTypeBasedArrayL();
break;
default:
CreateTimeBasedArrayL();
break;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::CreateTimeBasedArrayL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::CreateTimeBasedArrayL()
{
CArrayFixFlat<TInt>* itemsAdded = new (ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL( itemsAdded );
TInt entryCount = 0; // divides list building into smaller pieces
TBool itemAdded = EFalse;
// Loop until all entries and subtitles has been added to iHCListItemArray
while ( iEntriesToBeAdded->Count() )
{
TBool nonCmailEntry = ETrue;
if ( iEmailFramework )
{
nonCmailEntry = CheckCmailEntryIndexL ((*iEntriesToBeAdded)[0]);
}
if ( nonCmailEntry )
{
iEntryToBeAdded = (*iEntriesToBeAdded)[0];
iEntriesToBeAdded->Delete( 0 );
// First add folders
if ( iStep == 0 )
{
TMsvEntry entry = iFolderEntry->ChildDataL( iEntryToBeAdded );
// Find folders
while ( entry.iType == KUidMsvFolderEntry )
{
THCListListItem item;
item.iTreeItemId = 0;
item.iEntryId = entry.Id();
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
entryCount++;
iCounter++;
if ( iEntriesToBeAdded->Count() )
{
iEntryToBeAdded = (*iEntriesToBeAdded)[0];
iEntriesToBeAdded->Delete( 0 );
entry = iFolderEntry->ChildDataL( iEntryToBeAdded );
}
else
{
iEntryToBeAdded = 0;
// All entries has been checked for folder type
break;
}
}
}
// Add subtitle
if ( iAddSubtitle )
{
THCListListItem item;
item.iTreeItemId = 0;
item.iEntryId = iEntryToBeAdded;
item.iItemType = EHListItemSubtitle;
item.iSubtitleType = iSubtitleType;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
iAddSubtitle = EFalse;
entryCount++;
}
// iCounter still in valid range
if ( iEntryToBeAdded > 0 )
{
TMsvEntry entry = iFolderEntry->ChildDataL( iEntryToBeAdded );
TTime entryTime = entry.iDate;
GetTime( entryTime );
TInt subtitleType = TimeBasedSubtitleType( entryTime, EFalse );
if ( !iSubtitleAdded[subtitleType] )
{
iAddSubtitle = ETrue;
iSubtitleType = subtitleType;
iSubtitleAdded[subtitleType] = ETrue;
}
// Add entry item if no subtitle added
if( !iAddSubtitle )
{
THCListListItem item;
item.iTreeItemId = 0;
item.iEntryId = entry.Id();
item.iItemType = EHListItemEntry;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
item.iSubtitleType = iSubtitleType;
itemAdded = ETrue;
entryCount++;
}
else
{
// Subtitle added: breaks out and after that
// active scheduler returns to add subtitle and entries
iEntriesToBeAdded->InsertL( 0, iEntryToBeAdded );
iStep = 1;
break;
}
// This breaks building the array after every KMceLoopCounter entries.
// Necessary for not slowing down execution when there are many messages
// as this is a part of an active scheduler callback.
if ( entryCount >= KMceLoopCounter )
{
iCounter++;
break;
}
}
}
else
{
iEntriesToBeAdded->Delete( 0 );
}
iCounter++;
}
iStep = 1;
// Update Tree list
if ( iListItemArrayObserver && itemAdded )
{
iListItemArrayObserver->MceListItemArrayChangedL( *itemsAdded );
}
CleanupStack::PopAndDestroy( itemsAdded );
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::CreateSenderBasedArrayL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::CreateSenderBasedArrayL()
{
CArrayFixFlat<TInt>* itemsAdded = new (ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL( itemsAdded );
TBool itemAdded = EFalse;
TInt i = 0;
while ( iEntriesToBeAdded->Count() && i < KMceLoopCounter )
{
THCListListItem item;
item.iTreeItemId = 0;
TBool nonCmailEntry = ETrue ;
if (iEmailFramework )
{
nonCmailEntry = CheckCmailEntryIndexL ((*iEntriesToBeAdded)[0]);
}
if ( nonCmailEntry )
{
TMsvId entryToBeAdded = (*iEntriesToBeAdded)[0];
iEntriesToBeAdded->Delete( 0 );
if ( iEntryToBeAdded <= 0 )
{
TMsvEntry entry = iFolderEntry->ChildDataL( entryToBeAdded );
item.iEntryId = entryToBeAdded;
if ( entry.iType != KUidMsvFolderEntry )
{
item.iItemType = EHListItemSubtitle;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
i++;
}
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
iEntryToBeAdded = entryToBeAdded;
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
}
else
{
TMsvEntry previousEntry = iFolderEntry->ChildDataL( iEntryToBeAdded );
TMsvEntry currentEntry = iFolderEntry->ChildDataL( entryToBeAdded );
item.iEntryId = currentEntry.Id();
if ( currentEntry.iType != KUidMsvFolderEntry &&
currentEntry.iDetails.Compare(previousEntry.iDetails) != 0 )
{
item.iItemType = EHListItemSubtitle;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
i++;
}
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
iEntryToBeAdded = entryToBeAdded;
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
}
}
else
{
iEntriesToBeAdded->Delete( 0 );
}
iCounter++;
i++;
}
if ( iListItemArrayObserver && itemAdded )
{
iListItemArrayObserver->MceListItemArrayChangedL( *itemsAdded );
}
CleanupStack::PopAndDestroy( itemsAdded );
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::CreateSubjectBasedArrayL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::CreateSubjectBasedArrayL()
{
CArrayFixFlat<TInt>* itemsAdded = new (ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL( itemsAdded );
TBool itemAdded = EFalse;
TInt i = 0;
while ( iEntriesToBeAdded->Count() && i < KMceLoopCounter )
{
THCListListItem item;
item.iTreeItemId = 0;
TBool nonCmailEntry = ETrue;
if (iEmailFramework )
{
nonCmailEntry = CheckCmailEntryIndexL ((*iEntriesToBeAdded)[0]);
}
if ( nonCmailEntry )
{
TMsvId entryToBeAdded = (*iEntriesToBeAdded)[0];
iEntriesToBeAdded->Delete( 0 );
if ( iEntryToBeAdded <= 0 )
{
TMsvEntry entry = iFolderEntry->ChildDataL( entryToBeAdded );
item.iEntryId = entryToBeAdded;
if ( entry.iType != KUidMsvFolderEntry )
{
item.iItemType = EHListItemSubtitle;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
i++;
}
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
iEntryToBeAdded = entryToBeAdded;
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
}
else
{
TMsvEntry previousEntry = iFolderEntry->ChildDataL( iEntryToBeAdded );
TMsvEntry currentEntry = iFolderEntry->ChildDataL( entryToBeAdded );
item.iEntryId = currentEntry.Id();
// Remove prefix from current entry description
TBufC<100> tmpString( currentEntry.iDescription.Left( KSortSubjectStringLength ) );
const TInt length1 = tmpString.Length();
TInt start = SkipPrefix( tmpString.Des() );
TPtrC currentMid = currentEntry.iDescription.Mid( start, length1 - start );
// Remove prefix from previous entry description
TBufC<100> tmpString2( previousEntry.iDescription.Left( KSortSubjectStringLength ) );
const TInt length2 = tmpString2.Length();
start = SkipPrefix( tmpString2.Des() );
TPtrC prevMid = previousEntry.iDescription.Mid( start, length2 - start );
// Compare descriptions
if ( currentEntry.iType != KUidMsvFolderEntry &&
currentMid.CompareF( prevMid ) != 0 )
{
item.iItemType = EHListItemSubtitle;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
i++;
}
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
iEntryToBeAdded = entryToBeAdded;
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
}
}
else
{
iEntriesToBeAdded->Delete( 0 );
}
iCounter++;
i++;
}
if ( iListItemArrayObserver && itemAdded )
{
iListItemArrayObserver->MceListItemArrayChangedL( *itemsAdded );
}
CleanupStack::PopAndDestroy( itemsAdded );
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::CreateTypeBasedArrayL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::CreateTypeBasedArrayL()
{
CArrayFixFlat<TInt>* itemsAdded = new (ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL( itemsAdded );
TBool itemAdded = EFalse;
TInt i = 0;
while ( iEntriesToBeAdded->Count() && i < KMceLoopCounter )
{
THCListListItem item;
item.iTreeItemId = 0;
TBool nonCmailEntry = ETrue;
if (iEmailFramework )
{
nonCmailEntry = CheckCmailEntryIndexL ((*iEntriesToBeAdded)[0]);
}
if ( nonCmailEntry )
{
TMsvId entryToBeAdded = (*iEntriesToBeAdded)[0];
iEntriesToBeAdded->Delete( 0 );
item.iEntryId = entryToBeAdded;
item.iItemType = EHListItemEntry;
itemAdded = ETrue;
iHCListItemArray.AppendL( item );
itemsAdded->AppendL( iHCListItemArray.Count()-1 );
}
else
{
iEntriesToBeAdded->Delete( 0 );
}
iCounter++;
i++;
}
if ( iListItemArrayObserver && itemAdded )
{
iListItemArrayObserver->MceListItemArrayChangedL( *itemsAdded );
}
CleanupStack::PopAndDestroy( itemsAdded );
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SortType
// ----------------------------------------------------
THCListListType CMceOneRowListItemArrayLoader::SortTypeHCList()
{
return iListType;
}
// ----------------------------------------------------
// CMceMessageListItemArray::SortType
// returns folder's sort type
//
// ----------------------------------------------------
TMsvSelectionOrdering CMceOneRowListItemArrayLoader::SortType( )
{
return iFolderEntry->SortType();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SetOrderingL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SetOrderingL( TInt aSortType, TBool aOrdering )
{
TMsvSorting sorting = EMsvSortByDateReverse;
TInt grouping = KMsvGroupByStandardFolders;
switch ( aSortType )
{
case EMceCmdSortByType:
grouping = KMsvGroupByStandardFolders|KMsvGroupByMtm;
sorting = aOrdering ? EMsvSortByIdReverse: EMsvSortById;
iListType = EHCListTypeType;
break;
case EMceCmdSortByRecipient:
case EMceCmdSortBySender:
sorting = aOrdering ? EMsvSortByDetailsReverse: EMsvSortByDetails;
iListType = EHCListTypeSender;
break;
case EMceCmdSortBySubject:
sorting = aOrdering ? EMsvSortByDescriptionReverse: EMsvSortByDescription;
iListType = EHCListTypeSubject;
break;
case EMceCmdSortByDate:
default:
sorting = aOrdering ? EMsvSortByDate: EMsvSortByDateReverse;
iListType = EHCListTypeTime;
break;
}
const TMsvSelectionOrdering newOrdering( grouping, sorting, EFalse );
iFolderEntry->SetSortTypeL( newOrdering );
// Ignore possible error. If this leaves worst thing is that ordering is not saved to root for message iterator.
TRAP_IGNORE( SaveOrderingL( newOrdering ) );
iPreviousSelectionOrdering = newOrdering;
StartL();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SaveOrderingL
// Write the sorting order into the message store, MUIU accesses and
// uses this for CMessageIterator
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SaveOrderingL( const TMsvSelectionOrdering& aNewOrdering ) const
{
// TMsvSelectionOrdering class does not have != operator
if ( !(iPreviousSelectionOrdering == aNewOrdering ) )
{
CMsvEntry* entry=iSession->GetEntryL( KMsvRootIndexEntryId ); // Access the entry
CleanupStack::PushL( entry );
CMsvStore* store = entry->EditStoreL();
CleanupStack::PushL( store );
RMsvWriteStream writeStream;
writeStream.AssignLC( *store, KUidMsvMessageListSortOrder );
aNewOrdering.ExternalizeL( writeStream );
writeStream.CommitL();
store->CommitL();
CleanupStack::PopAndDestroy( 3 );
}
}
// ----------------------------------------------------
// CMceMessageListItemArray::DeleteDiscard
// return ETrue, if delete command should be discarded
//
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::DeleteDiscard( TMsvId aItemId ) const
{
TMsvEntry entry;
TMsvId serviceId;
if ( iSession->GetEntry(aItemId,serviceId,entry) != KErrNone )
{
return ETrue;
}
//mail or syncml folder cannot be deleted
if ( ( entry.iType == KUidMsvFolderEntry ) &&
( entry.iMtm == KSenduiMtmImap4Uid ||
entry.iMtm == KSenduiMtmSyncMLEmailUid ) )
{
return ETrue;
}
if ( iFolderEntry->Entry().Id() == KMsvGlobalOutBoxIndexEntryId )
{
if ( entry.SendingState() == KMsvSendStateSending )
{
return ETrue;
}
// Message in waiting state cannot be deleted except e-mail.
// For e-mail, waiting, resend and scheduled states are presented
// to user as queued state (by CSmtpMtmUiData). Delete is allowed
// from the queued state.
if ( ( entry.SendingState() == KMsvSendStateWaiting ) &&
( entry.iMtm != KSenduiMtmSmtpUid ) )
{
return ETrue;
}
if ( entry.iMtm == KSenduiMtmSmsUid ||
entry.iMtm == KSenduiMtmMmsUid )
{
if ( entry.Connected() || ( entry.SendingState() == KMsvSendStateUnknown )
|| ( entry.SendingState() == KMsvSendStateNotApplicable ) )
{
return ETrue;
}
}
}
return EFalse;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::IsItemFolder
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::IsItemFolder( TMsvId aItemId ) const
{
TBool isFolder = EFalse;
TMsvId serviceId;
TMsvEntry entry;
if ( iSession->GetEntry( aItemId, serviceId, entry ) == KErrNone &&
entry.iType == KUidMsvFolderEntry )
{
isFolder = ETrue;
}
return isFolder;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::TreeItemId
// ----------------------------------------------------
TAknTreeItemID CMceOneRowListItemArrayLoader::TreeItemId( TInt aIndex )
{
return iHCListItemArray[aIndex].iTreeItemId;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::MsvItemId
// ----------------------------------------------------
TMsvId CMceOneRowListItemArrayLoader::MsvItemId( TAknTreeItemID aTreeItemId )
{
TMsvId foundItem = KErrNotFound;
const TInt count = iHCListItemArray.Count();
for( TInt loop = 0; loop < count && foundItem == KErrNotFound ; loop++)
{
if ( iHCListItemArray[loop].iTreeItemId == aTreeItemId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
foundItem = iHCListItemArray[loop].iEntryId;
}
}
return foundItem;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ParentItemId
// ----------------------------------------------------
TAknTreeItemID CMceOneRowListItemArrayLoader::ParentItemId( TInt aIndex )
{
if ( aIndex < 0 || aIndex > iHCListItemArray.Count() )
{
return KAknTreeIIDNone;
}
TInt i = aIndex;
TAknTreeItemID parentId = KAknTreeIIDRoot;
if ( iHCListItemArray[i].iItemType == EHListItemEntry )
{
// if item is subtitle row, then return root, but since it is message, search its subtitle row
while ( i >= 0 && iHCListItemArray[i].iItemType == EHListItemEntry )
{
i--;
}
if ( i >= 0 )
{
parentId = iHCListItemArray[i].iTreeItemId;
}
}
return parentId;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ParentItemIndex
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::ParentItemIndex( TInt aIndex )
{
if ( aIndex < 0 || aIndex > iHCListItemArray.Count() )
{
return KErrNotFound;
}
TInt i = aIndex;
if ( iHCListItemArray[i].iItemType == EHListItemEntry )
{
// if item is subtitle row, then return root, but since it is message, search its subtitle row
while ( i >= 0 && iHCListItemArray[i].iItemType == EHListItemEntry )
{
i--;
}
}
return i;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SetTreeItemId
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SetTreeItemId( TInt aIndex, TAknTreeItemID aTreeItemId )
{
iHCListItemArray[aIndex].iTreeItemId = aTreeItemId;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ResetAllTreeItemId
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::ResetAllTreeItemId()
{
TInt i = iHCListItemArray.Count()-1;
while ( i >= 0 )
{
iHCListItemArray[i].iTreeItemId = 0;
i--;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::Compare
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::Compare( TAknTreeItemID aFirst, TAknTreeItemID aSecond )
{
TInt firstIndex = KErrNotFound;
TInt secondIndex = KErrNotFound;
TInt i = iHCListItemArray.Count()-1;
while ( i >= 0 && ( firstIndex < 0 || secondIndex < 0 ) )
{
if ( iHCListItemArray[i].iTreeItemId == aFirst )
{
firstIndex = i;
}
if ( iHCListItemArray[i].iTreeItemId == aSecond )
{
secondIndex = i;
}
i--;
}
if ( firstIndex > KErrNotFound && secondIndex > KErrNotFound )
{
return firstIndex - secondIndex;
}
else
{
return 0;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ItemIndexTreeId
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::ItemIndexTreeId( TAknTreeItemID aTreeItemId )
{
TInt i = iHCListItemArray.Count()-1;
while ( i >= 0 && iHCListItemArray[i].iTreeItemId != aTreeItemId )
{
i--;
}
return i;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SetItemMarked
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SetItemMarked( TAknTreeItemID aFocused, TBool aState )
{
TInt index = ItemIndexTreeId( aFocused );
TInt subItemCount = GetSubfolderItemCount( aFocused );
if ( subItemCount != KErrNotFound && iHCListItemArray[index].iItemType == EHListItemSubtitle )
{
while ( index <= subItemCount )
{
iHCListItemArray[index].iMarked = aState;
index++;
}
}
else if ( aFocused == 1 )
{
TInt i = iHCListItemArray.Count()-1;
while ( i >= 0)
{
iHCListItemArray[i].iMarked = aState;
i--;
}
}
else
{
// Set item marked
iHCListItemArray[index].iMarked = aState;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetItemMarkStatusL
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::GetItemMarkStatusL( TMsvId aEntryId )
{
TInt markedCount = iMarkedArray.Count();
TInt index = iMarkedArray.Find( aEntryId );
if ( index > KErrNotFound )
{
iMarkedArray.Remove( index );
return ETrue;
}
return EFalse;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetSubfolderItemCount
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::GetSubfolderItemCount( TAknTreeItemID aParent )
{
TInt itemCount = 0;
TInt index = ItemIndexTreeId( aParent );
if ( index != KErrNotFound && iHCListItemArray[index].iItemType == EHListItemSubtitle )
{
TInt arrCount = iHCListItemArray.Count()-1;
while ( index < arrCount && iHCListItemArray[index + 1].iItemType != EHListItemSubtitle )
{
index++;
itemCount++;
}
}
else
{
return KErrNotFound;
}
return itemCount;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::ResetTreeItemId
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::ResetTreeItemId( TAknTreeItemID aTreeItemId )
{
TInt index = ItemIndexTreeId( aTreeItemId );
if ( index >= 0 )
{
iHCListItemArray[index].iTreeItemId = 0;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FolderEntry
// ----------------------------------------------------
const TMsvEntry& CMceOneRowListItemArrayLoader::FolderEntry() const
{
return iFolderEntry->Entry();
}
// ----------------------------------------------------
// CMceMessageListItemArray::GetParentFolder
// ----------------------------------------------------
TMsvId CMceOneRowListItemArrayLoader::GetParentFolderId() const
{
return iFolderEntry->Entry().Parent();
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FindFirstUnreadMessageL
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::FindFirstUnreadMessageL( TMsvId& aEntryId ) const
{
aEntryId = KErrNotFound;
TInt numberOfUnreadMessages = 0;
const TInt itemCount = iFolderEntry->Count();
for ( TInt loop = 0; loop < itemCount; loop++ )
{
if ( (*iFolderEntry)[loop].iType == KUidMsvMessageEntry &&
(*iFolderEntry)[loop].Unread() )
{
if ( aEntryId == KErrNotFound )
{
aEntryId = (*iFolderEntry)[loop].Id();
}
numberOfUnreadMessages++;
if ( numberOfUnreadMessages > 1 )
{
// we are only interested of first unread message and info that if
// there are more than one unread messages.
// So we can stop if there are more than one.
break;
}
}
}
return (numberOfUnreadMessages == 1);
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FindUnreadMessageUnderSubtitleL
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::FindUnreadMessageUnderSubtitleL( TAknTreeItemID aSubtitleID )
{
TInt itemCount = GetSubfolderItemCount( aSubtitleID );
TInt startIndex = ItemIndexTreeId( aSubtitleID ) + 1;
for ( TInt loop = startIndex ; loop < itemCount + startIndex ; loop++ )
{
TMsvId entryId = iHCListItemArray[loop].iEntryId;
TMsvEntry entry;
TInt error = GetEntry(entryId, entry );
if ( !error && entry.Unread() )
{
return ETrue;
}
}
return EFalse;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FolderCount
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::FolderCount()
{
TInt numberOfFolders = 0;
const TInt itemCount = iFolderEntry->Count();
for ( TInt loop = 0; loop < itemCount; loop++ )
{
if ( (*iFolderEntry)[loop].iType == KUidMsvFolderEntry )
{
numberOfFolders++;
}
else if ( (*iFolderEntry)[loop].iType == KUidMsvMessageEntry )
{
// folders are grouped first, so we can stop when first message is reached.
break; //loop = itemCount;
}
}
return numberOfFolders;
}
// ----------------------------------------------------
// CMceMessageListItemArray::MessageCount
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::MessageCount()
{
TInt numberOfMessages = 0;
const TInt itemCount = iFolderEntry->Count();
for ( TInt loop = 0; loop < itemCount; loop++ )
{
if ( (*iFolderEntry)[loop].iType == KUidMsvMessageEntry )
{
numberOfMessages++;
}
}
return numberOfMessages;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::IsConnected
// return ETrue, if account is connected
//
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::IsConnected() const
{
TMsvEntry entry;
entry = iFolderEntry->Entry();
TMsvEntry serviceEntry;
TMsvId serviceId;
if ( iSession->GetEntry(entry.iServiceId,serviceId,serviceEntry) == KErrNone )
{
return serviceEntry.Connected();
}
else
{
return EFalse;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FindEntryIndex
// Finds entry index in message list
//
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::FindEntryIndex( const TDesC& aMatchString ) const
{
TInt foundIndex = KErrNotFound;
TMsvSelectionOrdering ordering( KMsvNoGrouping, EMsvSortByDateReverse, EFalse );
ordering = iFolderEntry->SortType();
const TInt count = iFolderEntry->Count();
const TInt length = aMatchString.Length();
if ( ( ordering.Sorting() == EMsvSortByDetails ) ||
( ordering.Sorting() == EMsvSortByDetailsReverse ) )
{
for( TInt loop = 0; loop < count && foundIndex == KErrNotFound ; loop++ )
{
if ( aMatchString.CompareF( ( *iFolderEntry )[loop].iDetails.Left( length ) ) == 0 )
{
foundIndex = loop;
}
}
}
else if ( ( ordering.Sorting() == EMsvSortByDescription ) ||
( ordering.Sorting() == EMsvSortByDescriptionReverse ) )
{
for( TInt loop = 0; loop < count && foundIndex == KErrNotFound ; loop++ )
{
TBufC<100> tmpString( ( *iFolderEntry )[loop].iDescription.Left(KSortSubjectStringLength) );
TInt start = SkipPrefix( tmpString.Des() );
if ( start < tmpString.Length() && tmpString.Length() >= length )
{
TPtrC mid = (*iFolderEntry)[loop].iDescription.Mid( start, length );
if ( aMatchString.CompareF( mid ) == 0 )
{
foundIndex = loop;
}
}
}
}
else
{
//EMsvSortByReverse, nothing cannot be searched
}
return foundIndex;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SkipPrefix
// Removes the "Re:" or "Fw:" prefixes from the given
// text string
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::SkipPrefix( TPtrC aTextString ) const
{
TPtrC searchString( aTextString );
TPtrC searchStringOrig( aTextString );
TInt matchInd = searchString.Match( KSortSubjectSkipString );
TInt matchStart = 0;
TInt lenRight = searchString.Length() - matchInd - 1;
// Find the last prefix character
while ( matchInd != KErrNotFound && lenRight > 0 )
{
TPtrC searchString2 = searchString.Right( lenRight );
matchStart += matchInd + 1;
matchInd = searchString2.Match( KSortSubjectSkipString );
lenRight = searchString2.Length() - matchInd - 1;
searchString.Set( searchString2 );
}
// Skip the white space after the prefix character
matchInd = searchStringOrig.LocateReverse( KWhiteSpaceCharacter );
if ( matchInd != KErrNotFound && matchStart == matchInd )
{
++matchStart;
}
return matchStart;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::EntryCreatedL
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::EntryCreatedL( TMsvId aEntryId )
{
MCELOGGER_ENTERFN("CMceOneRowListItemArrayLoader::EntryCreatedL");
if ( IsActive() )
{
MCELOGGER_WRITE("Already active, ignore");
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::EntryCreatedL");
return 0;
}
// how to make sure iFolderEntry is already updated?
MCELOGGER_WRITE_FORMAT("aEntryId = 0x%x", aEntryId );
CMsvEntry* folderEntry = CMsvEntry::NewL(
*iSession,
iFolderEntry->EntryId(),
iFolderEntry->SortType() );
CleanupStack::PushL( folderEntry );
TInt entryIndex = KErrNotFound;
TInt i = 0;
const TInt count = folderEntry->Count();
#ifdef _DEBUG
while ( i < folderEntry->Count() )
{
MCELOGGER_WRITE_FORMAT2("(*folderEntry)[%d].Id() = 0x%x", i, (*folderEntry)[i].Id() );
i++;
}
i = 0;
#endif
while ( i < folderEntry->Count() && entryIndex == KErrNotFound )
{
if ( (*folderEntry)[i].Id() == aEntryId )
{
MCELOGGER_WRITE_FORMAT("found entry at index %d", i );
entryIndex = i;
}
i++;
}
CleanupStack::Pop( folderEntry );
delete iFolderEntry;
iFolderEntry = folderEntry;
TInt createdCount = 0;
if ( entryIndex > KErrNotFound )
{
createdCount = InsertEntryL( entryIndex, aEntryId );
}
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::EntryCreatedL");
return createdCount;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::InsertEntryL
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::InsertEntryL( TInt aEntryIndex, TMsvId aEntryId )
{
MCELOGGER_ENTERFN("CMceOneRowListItemArrayLoader::InsertEntryL");
MCELOGGER_WRITE_FORMAT("aEntryId: 0x%x", aEntryId );
MCELOGGER_WRITE_FORMAT("aEntryIndex: %d", aEntryIndex );
iDuplicate = EFalse;
TInt previous = FindPreviousFromArrayL( aEntryId );
if ( iDuplicate )
{
// Entry already exist in array return without creating a new instance
return 0;
}
TInt next = FindNextFromArrayL( aEntryId );
if ( iDuplicate )
{
// Entry already exist in array return without creating a new instance
return 0;
}
MCELOGGER_WRITE_FORMAT2("previous index: %d, next index %d", previous, next );
TBool previousAnchor = EFalse;
if ( iFolderEntry->operator[](aEntryIndex).iType == KUidMsvFolderEntry )
{
TInt count = InsertFolderEntryL( aEntryIndex, aEntryId );
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::InsertEntryL - folder insert");
return count;
}
TInt needSubtitle = ETrue;
TMsvId insertId = KErrNotFound;
// Index to end of the array by default
TInt insertIndex = iHCListItemArray.Count();
// Sorting by type don't have subtitles
if ( iListType == EHCListTypeType )
{
needSubtitle = EFalse;
if ( next > 0 )
{
insertIndex = next-1;
}
}
// Find closest entry with same subtitle
if ( needSubtitle )
{
// Search subtitle for preceding entry
if ( previous > KErrNotFound )
{
if ( SameSubtitle( aEntryIndex, previous ) )
{
MCELOGGER_WRITE_FORMAT("Prev index %d has SAME subtitle", previous );
needSubtitle = EFalse;
insertId = iFolderEntry->operator[](previous).Id();
previousAnchor = ETrue;
MCELOGGER_WRITE_FORMAT("Id 0x%x has SAME subtitle", insertId );
}
}
// Search subtitle for following entry
if ( needSubtitle && next > KErrNotFound )
{
insertId = iFolderEntry->operator[](next).Id();
if ( SameSubtitle( aEntryIndex, next ) )
{
MCELOGGER_WRITE_FORMAT("Next index %d has SAME subtitle", next );
needSubtitle = EFalse;
previousAnchor = EFalse;
MCELOGGER_WRITE_FORMAT("Id 0x%x has SAME subtitle", insertId );
}
}
}
#ifdef _DEBUG
TInt tempcount = iHCListItemArray.Count();
MCELOGGER_WRITE_FORMAT("array before add, count %d", tempcount );
for( TInt loop = 0; loop < tempcount; loop++)
{
if ( iHCListItemArray[loop].iItemType == EHListItemEntry )
{
MCELOGGER_WRITE_FORMAT2("%d entry 0x%x", loop, iHCListItemArray[loop].iEntryId );
}
else
{
MCELOGGER_WRITE_FORMAT2("%d subtitle 0x%x", loop, iHCListItemArray[loop].iEntryId );
}
}
#endif
// First index and no following entry
if ( aEntryIndex == 0 && insertId <= 0 )
{
insertIndex = 0; // to the beginning...
}
// If neighbour entry
if ( insertId > 0 )
{
MCELOGGER_WRITE_FORMAT("try to find entry 0x%x", insertId );
const TInt count = iHCListItemArray.Count();
// First find entry which already exists in iHCListItemArray
for( TInt loop = 0; loop < count; loop++)
{
if ( iHCListItemArray[loop].iEntryId == insertId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
MCELOGGER_WRITE_FORMAT("FOUND message index %d", loop );
insertIndex = loop;
if ( previousAnchor )
{
insertIndex++;
}
break;
}
}
// next find corresponding subtitle row
while ( needSubtitle && insertIndex >= 0
&& iHCListItemArray[insertIndex].iItemType != EHListItemSubtitle )
{
insertIndex--;
}
MCELOGGER_WRITE_FORMAT("subtitle index %d", insertIndex );
}
// Insert entry item
THCListListItem item;
item.iTreeItemId = 0;
item.iEntryId = aEntryId;
item.iItemType = EHListItemEntry;
iHCListItemArray.InsertL( item, insertIndex );
TInt createdCount = 1;
MCELOGGER_WRITE_FORMAT("Inserted item to %d", insertIndex );
// Add subtitle if needed
if ( needSubtitle )
{
item.iItemType = EHListItemSubtitle;
if ( iListType == EHCListTypeTime )
{
TTime entryTime = iFolderEntry->operator[](aEntryIndex).iDate;
GetTime( entryTime );
item.iSubtitleType = TimeBasedSubtitleType( entryTime, ETrue );
}
else
{
item.iSubtitleType = 0;
}
iHCListItemArray.InsertL( item, insertIndex );
MCELOGGER_WRITE_FORMAT("Inserted subtitle to %d", insertIndex );
createdCount++;
}
// Handle entries that has been received during the list creation
if ( iEntriesReceivedDuringListCreation && iListItemArrayObserver )
{
CArrayFixFlat<TInt>* itemsAdded = new (ELeave) CArrayFixFlat<TInt>(4);
CleanupStack::PushL( itemsAdded );
itemsAdded->AppendL( insertIndex );
if ( needSubtitle )
{
itemsAdded->AppendL( insertIndex+1 );
}
iListItemArrayObserver->MceListItemArrayChangedL( *itemsAdded );
CleanupStack::PopAndDestroy( itemsAdded );
}
#ifdef _DEBUG
tempcount = iHCListItemArray.Count();
MCELOGGER_WRITE_FORMAT("array AFTER add, count %d", tempcount );
for( TInt loop = 0; loop < tempcount; loop++)
{
if ( iHCListItemArray[loop].iItemType == EHListItemEntry )
{
MCELOGGER_WRITE_FORMAT2("%d entry 0x%x", loop, iHCListItemArray[loop].iEntryId );
}
else
{
MCELOGGER_WRITE_FORMAT2("%d subtitle 0x%x", loop, iHCListItemArray[loop].iEntryId );
}
}
#endif
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::InsertEntryL");
return createdCount;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SameSubtitle
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::SameSubtitle( TInt aIndex1, TInt aIndex2 )
{
TBool sameSubtitle = EFalse;
// Time based subtitles
if ( iListType == EHCListTypeTime )
{
TTime entryDate1 = iFolderEntry->operator[](aIndex1).iDate;
GetTime( entryDate1 );
TTime entryDate2 = iFolderEntry->operator[](aIndex2).iDate;
GetTime( entryDate2 );
TInt subtitle1 = TimeBasedSubtitleType( entryDate1, ETrue );
TInt subtitle2 = TimeBasedSubtitleType( entryDate2, EFalse );
if ( subtitle1 == subtitle2 )
{
sameSubtitle = ETrue;
}
}
// Sender based subtitles
else if ( iListType == EHCListTypeSender )
{
TMsvEntry previousEntry = iFolderEntry->operator[](aIndex1);
TMsvEntry currentEntry = iFolderEntry->operator[](aIndex2);
if ( currentEntry.iDetails.Compare(previousEntry.iDetails) == 0 )
{
sameSubtitle = ETrue;
}
}
// Subject based subtitles
else if ( iListType == EHCListTypeSubject )
{
TMsvEntry previousEntry = iFolderEntry->operator[](aIndex1);
TMsvEntry currentEntry = iFolderEntry->operator[](aIndex2);
// Remove prefix from current entry description
TBufC<100> tmpString( currentEntry.iDescription.Left( KSortSubjectStringLength ) );
const TInt length1 = tmpString.Length();
TInt start = SkipPrefix( tmpString.Des() );
TPtrC currentMid = currentEntry.iDescription.Mid( start, length1 - start );
//Remove prefix from previous entry description
TBufC<100> tmpString2( previousEntry.iDescription.Left( KSortSubjectStringLength ) );
const TInt length2 = tmpString2.Length();
start = SkipPrefix( tmpString2.Des() );
TPtrC prevMid = previousEntry.iDescription.Mid( start, length2 - start );
// Compare descriptions
if ( currentMid.CompareF( prevMid ) == 0 )
{
sameSubtitle = ETrue;
}
}
// Type based sorting don't have subtitles. Return ETrue so new subtitle are not created
else if ( iListType == EHCListTypeType )
{
sameSubtitle = ETrue;
}
return sameSubtitle;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::InsertFolderEntryL
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::InsertFolderEntryL( TInt aEntryIndex, TMsvId aEntryId )
{
MCELOGGER_ENTERFN("CMceOneRowListItemArrayLoader::InsertFolderEntryL");
THCListListItem item;
item.iTreeItemId = 0;
item.iEntryId = aEntryId;
item.iItemType = EHListItemEntry;
iHCListItemArray.InsertL( item, aEntryIndex );
MCELOGGER_WRITE_FORMAT("Inserted item to %d", aEntryIndex );
MCELOGGER_LEAVEFN("CMceOneRowListItemArrayLoader::InsertFolderEntryL");
return 1;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::EntryDeletedL
// ----------------------------------------------------
TBool CMceOneRowListItemArrayLoader::EntryDeletedL(
TMsvId aEntryId,
TAknTreeItemID& aTreeItemId,
TAknTreeItemID& aParentTreeItemId )
{
aParentTreeItemId = KAknTreeIIDNone;
aTreeItemId = KAknTreeIIDNone;
TBool deleteParent = EFalse;
TInt itemIndex = ItemIndex( aEntryId );
if ( itemIndex >= 0 )
{
aTreeItemId = TreeItemId( itemIndex );
TAknTreeItemID parentTreeItemId = ParentItemId( itemIndex );
iHCListItemArray.Remove( itemIndex );
if ( parentTreeItemId > KAknTreeIIDRoot )
{
TInt parentIndex = ItemIndexTreeId( parentTreeItemId );
if ( parentIndex >= 0 )
{
TInt i = parentIndex+1;
TInt count = iHCListItemArray.Count();
while ( i < count && iHCListItemArray[i].iItemType == EHListItemEntry )
{
i++;
}
if ( i-parentIndex == 1 )
{
// we must delete parent also
iHCListItemArray.Remove( parentIndex );
deleteParent = ETrue;
}
}
aParentTreeItemId = parentTreeItemId;
}
}
return deleteParent;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetTime
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::GetTime( TTime& aEntryTime ) const
{
TTime homeTime;
homeTime.HomeTime();
TTime timeNow;
timeNow.UniversalTime();
TTimeIntervalMinutes timeZone;
if ( homeTime.MinutesFrom(timeNow, timeZone) == KErrNone )
{
aEntryTime = aEntryTime + timeZone;
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::GetCurrentTime
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::GetCurrentTime( TTime& aCurrentTime ) const
{
TTime timeNow;
timeNow.HomeTime();
TDateTime dateTime = timeNow.DateTime();
dateTime.SetHour( KMceTimeHours );
dateTime.SetMinute( KMceTimeMinutes );
dateTime.SetSecond( KMceTimeSeconds );
dateTime.SetMicroSecond( KMceTimeMicroSeconds );
aCurrentTime = dateTime;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FindPreviousFromArrayL
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::FindPreviousFromArrayL( TMsvId aId )
{
// Get snapshot from message store
CMsvEntrySelection* children = iFolderEntry->ChildrenL();
CleanupStack::PushL( children );
// Find index in message store
TInt index = children->Find( aId );
TMsvId prevId = KErrNotFound;
if ( index == KErrNotFound )
{
CleanupStack::PopAndDestroy( children );
return KErrNotFound;
}
TInt foundItem = KErrNotFound;
// Go through previous entry indexes in array until end or match found
while ( index >= 0 && foundItem == KErrNotFound )
{
prevId = (*children)[index];
const TInt count = iHCListItemArray.Count();
for( TInt loop = 0; loop < count && foundItem == KErrNotFound ; loop++)
{
// Previous entry exists in list
if ( iHCListItemArray[loop].iEntryId == prevId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
foundItem = loop;
}
// Entry with same Id exists already
if ( iHCListItemArray[loop].iEntryId == aId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
iDuplicate = ETrue;
}
}
if ( foundItem == KErrNotFound )
{
index--;
}
}
// Previous item found, return id
if ( foundItem > KErrNotFound )
{
foundItem = children->Find( prevId );
}
CleanupStack::PopAndDestroy( children );
return foundItem;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::FindNextFromArrayL
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::FindNextFromArrayL( TMsvId aId )
{
CMsvEntrySelection* children = iFolderEntry->ChildrenL();
CleanupStack::PushL( children );
TInt index = children->Find( aId );
TMsvId nextId = KErrNotFound;
if ( index == KErrNotFound )
{
CleanupStack::PopAndDestroy( children );
return KErrNotFound;
}
const TInt childrenCount = children->Count();
TInt foundItem = KErrNotFound;
while ( index < childrenCount && foundItem == KErrNotFound )
{
nextId = (*children)[index];
const TInt count = iHCListItemArray.Count();
for( TInt loop = 0; loop < count && foundItem == KErrNotFound ; loop++)
{
if ( iHCListItemArray[loop].iEntryId == nextId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
foundItem = loop;
}
if ( iHCListItemArray[loop].iEntryId == aId &&
iHCListItemArray[loop].iItemType == EHListItemEntry )
{
iDuplicate = ETrue;
}
}
if ( foundItem == KErrNotFound )
{
index++;
}
}
if ( foundItem > KErrNotFound )
{
foundItem = children->Find( nextId );
}
CleanupStack::PopAndDestroy( children );
return foundItem;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::TimeBasedSubtitleType
// ----------------------------------------------------
TInt CMceOneRowListItemArrayLoader::TimeBasedSubtitleType( TTime& aTime, TBool aUpdateCurrentTime )
{
if ( aUpdateCurrentTime )
{
UpdateCurrentTime();
}
TInt timeBasedSubtitleType = 0;
if ( aTime >= iToday )
{
timeBasedSubtitleType = ETodayAdded;
}
else if ( aTime >= iYesterday )
{
timeBasedSubtitleType = EYesterdayAdded;
}
else if ( aTime < iTwoWeeksAgo )
{
timeBasedSubtitleType = EOlderAdded;
}
else if ( aTime < iOneWeekAgo )
{
timeBasedSubtitleType = ELastWeekAdded;
}
else
{
timeBasedSubtitleType = aTime.DayNoInWeek();
}
return timeBasedSubtitleType;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::UpdateCurrentTime
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::UpdateCurrentTime()
{
TTime timeNow;
GetCurrentTime( timeNow );
TLocale locale;
TDay startOfWeek = locale.StartOfWeek();
TTimeIntervalDays oneDay( KMceTimeOneDay );
TInt firstDayInWeek = timeNow.DayNoInWeek() - startOfWeek + 1;
if ( firstDayInWeek < 0 )
{
firstDayInWeek+=ESunday+1;
}
TTimeIntervalDays oneWeek( firstDayInWeek );
iOneWeekAgo = timeNow-oneWeek;
TTimeIntervalDays twoWeeks( KMceTimeOneWeek );
iTwoWeeksAgo = iOneWeekAgo-twoWeeks;
iToday = timeNow-oneDay;
iYesterday = iToday-oneDay;
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::SaveMarkingL
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::SaveMarkingL( RArray<TAknTreeItemID>& aMarked )
{
TInt count( aMarked.Count() );
iMarkedArray.Reset();
for (TInt loop = 0; loop < count; loop++ )
{
TMsvId id = MsvItemId( aMarked[ loop ] );
if ( id != KErrNotFound )
{
iMarkedArray.AppendL( id );
}
}
}
// ----------------------------------------------------
// CMceOneRowListItemArrayLoader::TodayTime
// ----------------------------------------------------
TTime CMceOneRowListItemArrayLoader::TodayTime ()
{
return iToday ;
}
// ----------------------------------------------------
// CMceMessageListItemArray::CreateEntryIndex()
// ----------------------------------------------------
void CMceOneRowListItemArrayLoader::CreateCmailEntryIndexL()
{
iCmailSelectionList = new( ELeave ) CMsvEntrySelection() ;
//Find email messages
CMsvEntrySelection *smtpselection = iFolderEntry->ChildrenWithMtmL( KUidMsgTypeSMTP );
CleanupStack::PushL( smtpselection );
CMsvEntrySelection *pop3selection = NULL;
CMsvEntrySelection *imapselection = NULL ;
CMsvEntrySelection *cmailselection = NULL ;
if(!iEmailFramework)
{
pop3selection = iFolderEntry->ChildrenWithMtmL( KUidMsgTypePOP3 );
CleanupStack::PushL( pop3selection );
imapselection = iFolderEntry->ChildrenWithMtmL( KUidMsgTypeIMAP4 );
CleanupStack::PushL( imapselection );
}
else
{
cmailselection = iFolderEntry->ChildrenWithMtmL( TUid::Uid(KUidMsgTypeCmailMtmVal) );
CleanupStack::PushL( cmailselection );
}
iCmailSelectionList->Reset();
if ( smtpselection!=0 && smtpselection->Count()>0 )
{
for( TInt i=0 ; i < smtpselection->Count() ; i++ )
{
iCmailSelectionList->AppendL( smtpselection->At(i) );
}
}
if(!iEmailFramework)
{
if ( pop3selection!=0 && pop3selection->Count()>0 )
{
for( TInt i=0 ; i < pop3selection->Count() ; i++ )
{
iCmailSelectionList->AppendL( pop3selection->At(i) );
}
}
if ( imapselection!=0 && imapselection->Count()>0 )
{
for( TInt i=0 ; i < imapselection->Count() ; i++ )
{
iCmailSelectionList->AppendL( imapselection->At(i) );
}
}
}
else
{
if ( cmailselection!=0 && cmailselection->Count()>0 )
{
for( TInt i=0 ; i < cmailselection->Count() ; i++ )
{
iCmailSelectionList->AppendL( cmailselection->At(i) );
}
}
}
if(iEmailFramework)
{
CleanupStack::PopAndDestroy( cmailselection );
}
else
{
CleanupStack::PopAndDestroy(imapselection);
CleanupStack::PopAndDestroy( pop3selection );
}
CleanupStack::PopAndDestroy( smtpselection );
}
TBool CMceOneRowListItemArrayLoader::CheckCmailEntryIndexL (TMsvId aId)
{
if ( iCmailSelectionList->Find( aId ) == KErrNotFound )
{
return ETrue;
}
else
{
return EFalse;
}
}
// End of File