EXPORT_C void CMsvEntryArray::SortL(TMsvSelectionOrdering aOrdering) // // sorts this array // { // If we're going to reverse the array first sort by id so sorting twice will give the same result switch(aOrdering.Sorting()) { case EMsvSortByDateReverse: case EMsvSortByIdReverse: case EMsvSortBySizeReverse: case EMsvSortByDescriptionReverse: case EMsvSortByDetailsReverse: { TKeyArrayFixPtr key = MessageSortKey(EMsvSortById); User::LeaveIfError(Sort(key)); break; } default: // Not required - break break; } if (Count() && (aOrdering.Sorting()!=EMsvSortByNone || aOrdering.GroupingOn())) GroupL(EGroupByStandardFolders, aOrdering, (aOrdering.Sorting()!=EMsvSortByNone)); }
void CMsvEntryArray::GroupL(TGroupCriterion aGroupCriterion,TMsvSelectionOrdering aOrdering,TBool aDoSort) // // This function works recursively, grouping and sorting the entry selection. The // 'sort' happens at the same time as the 1st 'group', then separate grouped arrays // are grouped indidvidually and then merged together at the end. The order in which // the grouping occurs is determined by the CMsvEntryArray::TGroupCriterion enum // { TMsvSorting sortType=aOrdering.Sorting(); TKeyArrayFixPtr key=MessageSortKey(sortType); if (aGroupCriterion==EStopGrouping) { // if you haven't sorted yet if (aDoSort) { // Subject based sorting requires a special algorithm. Only message entries are treated as other entries normally // do not have a prefix like e.g. "re: " or "fwd: " if(At(0)->iType == KUidMsvMessageEntry && (sortType == EMsvSortByDescription || sortType == EMsvSortByDescriptionReverse)) { SubjectBasedSortL(sortType == EMsvSortByDescriptionReverse,aOrdering.SubjectSkipString()); } else { CMsvEntryArray* temp=CMsvEntryArray::NewLC(iOrigMtmList); TInt count=Count(); if (count) temp->InsertL(0,&(*(this))[0],count); Reset(); const TMsvEntry** entry = &temp->At(0); while (count--) InsertIsqAllowDuplicatesL(*entry++, key); // Sorted ReverseOrder(sortType); CleanupStack::PopAndDestroy(); // temp } if (At(0)->iType == KUidMsvMessageEntry && (sortType == EMsvSortByDetails || sortType == EMsvSortByDetailsReverse)) { DetailBasedSortL(); // Sort blocks of messages with matching details into newest first } } else { // The aDoSort flag is not set, but we still need to do a subject // based sort if this array contains only message entries, and we are // sorting by description. Alternatively, we need to do a date based sort // if this array contains only message entries and we are sorting by detail. // In order to ensure the array contains only message entries, we // check that we have previously grouped the entries by type which would // have put all the message entries together in their own array. if (Count() > 0 && At(0)->iType == KUidMsvMessageEntry && OkToGroup(EGroupByType, aOrdering)) { if (sortType == EMsvSortByDescription || sortType == EMsvSortByDescriptionReverse) { SubjectBasedSortL(sortType == EMsvSortByDescriptionReverse,aOrdering.SubjectSkipString()); } else if (sortType == EMsvSortByDetails || sortType == EMsvSortByDetailsReverse) { DetailBasedSortL(); // Sort blocks of messages with matching details into newest first } } } return; } if (OkToGroup(aGroupCriterion, aOrdering)) { // // Copy contents into temp and then put new grouped contents into 'this' TInt count=Count(); if (count==0) return; // nothing to do here const TInt numberOfArrays=NumberOfArraysToSplitIntoL(aGroupCriterion); if (numberOfArrays<1) // cannot group on this so move on to next grouping { GroupL(TGroupCriterion(aGroupCriterion+1), aOrdering, aDoSort); return; } CMsvEntryArray* temp; if (iActualMtmList) temp = CMsvEntryArray::NewLC(*iActualMtmList); else temp = CMsvEntryArray::NewLC(iOrigMtmList); temp->InsertL(0,&(*(this))[0],count); Reset(); // // create the separate arrays for each group CArrayFixFlat<CMsvEntryArray*>* arrays=new(ELeave) CArrayFixFlat<CMsvEntryArray*>(numberOfArrays); CleanupStack::PushL(arrays); for (TInt ii=0; ii<numberOfArrays; ii++) { if (iActualMtmList) arrays->AppendL(CMsvEntryArray::NewLC(*iActualMtmList)); else arrays->AppendL(CMsvEntryArray::NewLC(iOrigMtmList)); } // // split the selection into the correct group, // sorting aswell if needed and not doing standard folders const TMsvEntry** entry = &temp->At(0); if (!aDoSort || aGroupCriterion==EGroupByStandardFolders) { while (count--) { arrays->At(ArrayId(*entry,aGroupCriterion))->AppendL(*entry); entry++; } } else if (aGroupCriterion==EGroupByType) { TKeyArrayFixPtr folderKey = TKeyArrayFixPtr(_FOFF(TMsvEntry,iDetails),ECmpCollated); while (count--) { if ((*entry)->iType==KUidMsvFolderEntry) arrays->At(ArrayId(*entry, aGroupCriterion))->InsertIsqAllowDuplicatesL(*entry, folderKey); else arrays->At(ArrayId(*entry, aGroupCriterion))->InsertIsqAllowDuplicatesL(*entry, key); entry++; } for (TInt jj=0; jj<numberOfArrays; jj++) { if (arrays->At(jj)->Count() && arrays->At(jj)->At(0)->iType!=KUidMsvFolderEntry) arrays->At(jj)->ReverseOrder(sortType); } aDoSort=EFalse; } else { while (count--) { arrays->At(ArrayId(*entry, aGroupCriterion))->InsertIsqAllowDuplicatesL(*entry, key); // Sorted entry++; } for (TInt jj=0; jj<numberOfArrays; jj++) arrays->At(jj)->ReverseOrder(sortType); aDoSort=EFalse; } // // group further - but check that standard entries and grouped folders are not grouped anymore if (aGroupCriterion==EGroupByStandardFolders) { __ASSERT_DEBUG(numberOfArrays==2, PanicServer(EMsvToManyGroups)); arrays->At(0)->GroupL(TGroupCriterion(aGroupCriterion+1), aOrdering, aDoSort); } else if (aGroupCriterion==EGroupByType) { for (TInt jj=0; jj<numberOfArrays; jj++) if (arrays->At(jj)->Count() && arrays->At(jj)->At(0)->iType!=KUidMsvFolderEntry) arrays->At(jj)->GroupL(TGroupCriterion(aGroupCriterion+1), aOrdering, aDoSort); } else { for (TInt jj=0; jj<numberOfArrays; jj++) arrays->At(jj)->GroupL(TGroupCriterion(aGroupCriterion+1), aOrdering, aDoSort); } // // merge the separate arrays into 'this' for (TInt kk=0; kk<numberOfArrays; kk++) { count=arrays->At(kk)->Count(); if (count) InsertL(0,&(*(arrays->At(kk)))[0],count); } CleanupStack::PopAndDestroy(numberOfArrays+2); // arrays contents + temp + arrays } else // move on to the next grouping GroupL(TGroupCriterion(aGroupCriterion+1), aOrdering, aDoSort); }